File indexing completed on 2024-05-05 16:17:39
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2002, 2003 Anders Lund <anders.lund@lund.tdcadsl.dk> 0004 SPDX-FileCopyrightText: 2003 Christoph Cullmann <cullmann@kde.org> 0005 SPDX-FileCopyrightText: 2001 Joseph Wenninger <jowenn@kde.org> 0006 SPDX-FileCopyrightText: 2006 Dominik Haumann <dhdev@gmx.de> 0007 SPDX-FileCopyrightText: 2007 Mirko Stocker <me@misto.ch> 0008 SPDX-FileCopyrightText: 2009 Michel Ludwig <michel.ludwig@kdemail.net> 0009 SPDX-FileCopyrightText: 2009 Erlend Hamberg <ehamberg@gmail.com> 0010 0011 Based on work of: 0012 SPDX-FileCopyrightText: 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de> 0013 0014 SPDX-License-Identifier: LGPL-2.0-only 0015 */ 0016 0017 // BEGIN Includes 0018 #include "katedialogs.h" 0019 0020 #include <ktexteditor/message.h> 0021 #include <ktexteditor_version.h> 0022 0023 #include "kateautoindent.h" 0024 #include "katebuffer.h" 0025 #include "kateconfig.h" 0026 #include "katedocument.h" 0027 #include "kateglobal.h" 0028 #include "katemodeconfigpage.h" 0029 #include "kateview.h" 0030 #include "spellcheck/spellcheck.h" 0031 0032 // auto generated ui files 0033 #include "ui_bordersappearanceconfigwidget.h" 0034 #include "ui_completionconfigtab.h" 0035 #include "ui_editconfigwidget.h" 0036 #include "ui_indentationconfigwidget.h" 0037 #include "ui_navigationconfigwidget.h" 0038 #include "ui_opensaveconfigadvwidget.h" 0039 #include "ui_opensaveconfigwidget.h" 0040 #include "ui_spellcheckconfigwidget.h" 0041 #include "ui_statusbarconfigwidget.h" 0042 #include "ui_textareaappearanceconfigwidget.h" 0043 0044 #include <KIO/Job> 0045 #include <KIO/JobUiDelegateFactory> 0046 #include <KIO/OpenUrlJob> 0047 0048 #include "kateabstractinputmodefactory.h" 0049 #include "katepartdebug.h" 0050 #include <KActionCollection> 0051 #include <KCharsets> 0052 #include <KColorCombo> 0053 #include <KFontRequester> 0054 #include <KMessageBox> 0055 #include <KProcess> 0056 #include <KSeparator> 0057 0058 #include <QCheckBox> 0059 #include <QClipboard> 0060 #include <QComboBox> 0061 #include <QDomDocument> 0062 #include <QFile> 0063 #include <QFileDialog> 0064 #include <QGroupBox> 0065 #include <QKeyEvent> 0066 #include <QLabel> 0067 #include <QLayout> 0068 #include <QMap> 0069 #include <QPainter> 0070 #include <QRadioButton> 0071 #include <QSettings> 0072 #include <QSlider> 0073 #include <QSpinBox> 0074 #include <QStringList> 0075 #include <QTabBar> 0076 #include <QTemporaryFile> 0077 #include <QTextCodec> 0078 #include <QTextStream> 0079 #include <QToolButton> 0080 #include <QWhatsThis> 0081 0082 // END 0083 0084 // BEGIN KateIndentConfigTab 0085 KateIndentConfigTab::KateIndentConfigTab(QWidget *parent) 0086 : KateConfigPage(parent) 0087 { 0088 // This will let us have more separation between this page and 0089 // the QTabWidget edge (ereslibre) 0090 QVBoxLayout *layout = new QVBoxLayout(this); 0091 QWidget *newWidget = new QWidget(this); 0092 0093 ui = new Ui::IndentationConfigWidget(); 0094 ui->setupUi(newWidget); 0095 0096 ui->cmbMode->addItems(KateAutoIndent::listModes()); 0097 0098 // FIXME Give ui->label a more descriptive name, it's these "More..." info about tab key action 0099 ui->label->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard); 0100 connect(ui->label, &QLabel::linkActivated, this, &KateIndentConfigTab::showWhatsThis); 0101 0102 // "What's This?" help can be found in the ui file 0103 0104 reload(); 0105 0106 observeChanges(ui->chkAutoDetectIndent); 0107 observeChanges(ui->chkBackspaceUnindents); 0108 observeChanges(ui->chkIndentPaste); 0109 observeChanges(ui->chkKeepExtraSpaces); 0110 observeChanges(ui->cmbMode); 0111 observeChanges(ui->rbIndentMixed); 0112 observeChanges(ui->rbIndentWithSpaces); 0113 observeChanges(ui->rbIndentWithTabs); 0114 connect(ui->rbIndentWithTabs, &QAbstractButton::toggled, ui->sbIndentWidth, &QWidget::setDisabled); 0115 connect(ui->rbIndentWithTabs, &QAbstractButton::toggled, this, &KateIndentConfigTab::slotChanged); // FIXME See slot below 0116 observeChanges(ui->rbTabAdvances); 0117 observeChanges(ui->rbTabIndents); 0118 observeChanges(ui->rbTabSmart); 0119 observeChanges(ui->sbIndentWidth); 0120 observeChanges(ui->sbTabWidth); 0121 0122 layout->addWidget(newWidget); 0123 } 0124 0125 KateIndentConfigTab::~KateIndentConfigTab() 0126 { 0127 delete ui; 0128 } 0129 0130 void KateIndentConfigTab::slotChanged() 0131 { 0132 // FIXME Make it working without this quirk 0133 // When the value is not copied it will silently set back to "Tabs & Spaces" 0134 if (ui->rbIndentWithTabs->isChecked()) { 0135 ui->sbIndentWidth->setValue(ui->sbTabWidth->value()); 0136 } 0137 } 0138 0139 // NOTE Should we have more use of such info stuff, consider to make it part 0140 // of KateConfigPage and add a similar function like observeChanges(..) 0141 void KateIndentConfigTab::showWhatsThis(const QString &text) 0142 { 0143 QWhatsThis::showText(QCursor::pos(), text); 0144 } 0145 0146 void KateIndentConfigTab::apply() 0147 { 0148 // nothing changed, no need to apply stuff 0149 if (!hasChanged()) { 0150 return; 0151 } 0152 m_changed = false; 0153 0154 KateDocumentConfig::global()->configStart(); 0155 0156 KateDocumentConfig::global()->setBackspaceIndents(ui->chkBackspaceUnindents->isChecked()); 0157 KateDocumentConfig::global()->setIndentPastedText(ui->chkIndentPaste->isChecked()); 0158 KateDocumentConfig::global()->setIndentationMode(KateAutoIndent::modeName(ui->cmbMode->currentIndex())); 0159 KateDocumentConfig::global()->setIndentationWidth(ui->sbIndentWidth->value()); 0160 KateDocumentConfig::global()->setKeepExtraSpaces(ui->chkKeepExtraSpaces->isChecked()); 0161 KateDocumentConfig::global()->setReplaceTabsDyn(ui->rbIndentWithSpaces->isChecked()); 0162 KateDocumentConfig::global()->setTabWidth(ui->sbTabWidth->value()); 0163 KateDocumentConfig::global()->setAutoDetectIndent(ui->chkAutoDetectIndent->isChecked()); 0164 0165 if (ui->rbTabAdvances->isChecked()) { 0166 KateDocumentConfig::global()->setTabHandling(KateDocumentConfig::tabInsertsTab); 0167 } else if (ui->rbTabIndents->isChecked()) { 0168 KateDocumentConfig::global()->setTabHandling(KateDocumentConfig::tabIndents); 0169 } else { 0170 KateDocumentConfig::global()->setTabHandling(KateDocumentConfig::tabSmart); 0171 } 0172 0173 KateDocumentConfig::global()->configEnd(); 0174 } 0175 0176 void KateIndentConfigTab::reload() 0177 { 0178 ui->chkBackspaceUnindents->setChecked(KateDocumentConfig::global()->backspaceIndents()); 0179 ui->chkIndentPaste->setChecked(KateDocumentConfig::global()->indentPastedText()); 0180 ui->chkKeepExtraSpaces->setChecked(KateDocumentConfig::global()->keepExtraSpaces()); 0181 0182 ui->chkAutoDetectIndent->setChecked(KateDocumentConfig::global()->autoDetectIndent()); 0183 ui->sbIndentWidth->setSuffix(ki18np(" character", " characters")); 0184 ui->sbIndentWidth->setValue(KateDocumentConfig::global()->indentationWidth()); 0185 ui->sbTabWidth->setSuffix(ki18np(" character", " characters")); 0186 ui->sbTabWidth->setValue(KateDocumentConfig::global()->tabWidth()); 0187 0188 ui->rbTabAdvances->setChecked(KateDocumentConfig::global()->tabHandling() == KateDocumentConfig::tabInsertsTab); 0189 ui->rbTabIndents->setChecked(KateDocumentConfig::global()->tabHandling() == KateDocumentConfig::tabIndents); 0190 ui->rbTabSmart->setChecked(KateDocumentConfig::global()->tabHandling() == KateDocumentConfig::tabSmart); 0191 0192 ui->cmbMode->setCurrentIndex(KateAutoIndent::modeNumber(KateDocumentConfig::global()->indentationMode())); 0193 0194 if (KateDocumentConfig::global()->replaceTabsDyn()) { 0195 ui->rbIndentWithSpaces->setChecked(true); 0196 } else { 0197 if (KateDocumentConfig::global()->indentationWidth() == KateDocumentConfig::global()->tabWidth()) { 0198 ui->rbIndentWithTabs->setChecked(true); 0199 } else { 0200 ui->rbIndentMixed->setChecked(true); 0201 } 0202 } 0203 0204 ui->sbIndentWidth->setEnabled(!ui->rbIndentWithTabs->isChecked()); 0205 } 0206 0207 QString KateIndentConfigTab::name() const 0208 { 0209 return i18n("Indentation"); 0210 } 0211 0212 // END KateIndentConfigTab 0213 0214 // BEGIN KateCompletionConfigTab 0215 KateCompletionConfigTab::KateCompletionConfigTab(QWidget *parent) 0216 : KateConfigPage(parent) 0217 { 0218 // This will let us have more separation between this page and 0219 // the QTabWidget edge (ereslibre) 0220 QVBoxLayout *layout = new QVBoxLayout(this); 0221 QWidget *newWidget = new QWidget(this); 0222 0223 ui = new Ui::CompletionConfigTab(); 0224 ui->setupUi(newWidget); 0225 0226 // "What's This?" help can be found in the ui file 0227 0228 reload(); 0229 0230 observeChanges(ui->chkAutoCompletionEnabled); 0231 observeChanges(ui->chkAutoSelectFirstEntry); 0232 observeChanges(ui->chkTabCompletion); 0233 observeChanges(ui->gbKeywordCompletion); 0234 observeChanges(ui->gbShowDoc); 0235 observeChanges(ui->gbWordCompletion); 0236 observeChanges(ui->minimalWordLength); 0237 observeChanges(ui->removeTail); 0238 0239 layout->addWidget(newWidget); 0240 } 0241 0242 KateCompletionConfigTab::~KateCompletionConfigTab() 0243 { 0244 delete ui; 0245 } 0246 0247 void KateCompletionConfigTab::showWhatsThis(const QString &text) // NOTE Not used atm, remove? See also KateIndentConfigTab::showWhatsThis 0248 { 0249 QWhatsThis::showText(QCursor::pos(), text); 0250 } 0251 0252 void KateCompletionConfigTab::apply() 0253 { 0254 // nothing changed, no need to apply stuff 0255 if (!hasChanged()) { 0256 return; 0257 } 0258 m_changed = false; 0259 0260 KateViewConfig::global()->configStart(); 0261 0262 KateViewConfig::global()->setValue(KateViewConfig::AutomaticCompletionInvocation, ui->chkAutoCompletionEnabled->isChecked()); 0263 KateViewConfig::global()->setValue(KateViewConfig::AutomaticCompletionPreselectFirst, ui->chkAutoSelectFirstEntry->isChecked()); 0264 KateViewConfig::global()->setValue(KateViewConfig::TabCompletion, ui->chkTabCompletion->isChecked()); 0265 KateViewConfig::global()->setValue(KateViewConfig::KeywordCompletion, ui->gbKeywordCompletion->isChecked()); 0266 KateViewConfig::global()->setValue(KateViewConfig::WordCompletion, ui->gbWordCompletion->isChecked()); 0267 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionMinimalWordLength, ui->minimalWordLength->value()); 0268 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, ui->removeTail->isChecked()); 0269 KateViewConfig::global()->setValue(KateViewConfig::ShowDocWithCompletion, ui->gbShowDoc->isChecked()); 0270 0271 KateViewConfig::global()->configEnd(); 0272 } 0273 0274 void KateCompletionConfigTab::reload() 0275 { 0276 ui->chkAutoCompletionEnabled->setChecked(KateViewConfig::global()->automaticCompletionInvocation()); 0277 ui->chkAutoSelectFirstEntry->setChecked(KateViewConfig::global()->automaticCompletionPreselectFirst()); 0278 ui->chkTabCompletion->setChecked(KateViewConfig::global()->tabCompletion()); 0279 0280 ui->gbKeywordCompletion->setChecked(KateViewConfig::global()->keywordCompletion()); 0281 ui->gbWordCompletion->setChecked(KateViewConfig::global()->wordCompletion()); 0282 ui->gbShowDoc->setChecked(KateViewConfig::global()->showDocWithCompletion()); 0283 0284 ui->minimalWordLength->setValue(KateViewConfig::global()->wordCompletionMinimalWordLength()); 0285 ui->removeTail->setChecked(KateViewConfig::global()->wordCompletionRemoveTail()); 0286 } 0287 0288 QString KateCompletionConfigTab::name() const 0289 { 0290 return i18n("Auto Completion"); 0291 } 0292 0293 // END KateCompletionConfigTab 0294 0295 // BEGIN KateSpellCheckConfigTab 0296 KateSpellCheckConfigTab::KateSpellCheckConfigTab(QWidget *parent) 0297 : KateConfigPage(parent) 0298 { 0299 // This will let us have more separation between this page and 0300 // the QTabWidget edge (ereslibre) 0301 QVBoxLayout *layout = new QVBoxLayout(this); 0302 QWidget *newWidget = new QWidget(this); 0303 0304 ui = new Ui::SpellCheckConfigWidget(); 0305 ui->setupUi(newWidget); 0306 0307 // "What's This?" help can be found in the ui file 0308 0309 reload(); 0310 0311 m_sonnetConfigWidget = new Sonnet::ConfigWidget(this); 0312 connect(m_sonnetConfigWidget, &Sonnet::ConfigWidget::configChanged, this, &KateSpellCheckConfigTab::slotChanged); 0313 layout->addWidget(m_sonnetConfigWidget); 0314 0315 layout->addWidget(newWidget); 0316 } 0317 0318 KateSpellCheckConfigTab::~KateSpellCheckConfigTab() 0319 { 0320 delete ui; 0321 } 0322 0323 void KateSpellCheckConfigTab::showWhatsThis(const QString &text) // NOTE Not used atm, remove? See also KateIndentConfigTab::showWhatsThis 0324 { 0325 QWhatsThis::showText(QCursor::pos(), text); 0326 } 0327 0328 void KateSpellCheckConfigTab::apply() 0329 { 0330 if (!hasChanged()) { 0331 // nothing changed, no need to apply stuff 0332 return; 0333 } 0334 m_changed = false; 0335 0336 // WARNING: this is slightly hackish, but it's currently the only way to 0337 // do it, see also the KTextEdit class 0338 KateDocumentConfig::global()->configStart(); 0339 m_sonnetConfigWidget->save(); 0340 QSettings settings(QStringLiteral("KDE"), QStringLiteral("Sonnet")); 0341 KateDocumentConfig::global()->setOnTheFlySpellCheck(settings.value(QStringLiteral("checkerEnabledByDefault"), false).toBool()); 0342 KateDocumentConfig::global()->configEnd(); 0343 0344 const auto docs = KTextEditor::EditorPrivate::self()->kateDocuments(); 0345 for (KTextEditor::DocumentPrivate *doc : docs) { 0346 doc->refreshOnTheFlyCheck(); 0347 } 0348 } 0349 0350 void KateSpellCheckConfigTab::reload() 0351 { 0352 // does nothing 0353 } 0354 0355 QString KateSpellCheckConfigTab::name() const 0356 { 0357 return i18n("Spellcheck"); 0358 } 0359 0360 // END KateSpellCheckConfigTab 0361 0362 // BEGIN KateNavigationConfigTab 0363 KateNavigationConfigTab::KateNavigationConfigTab(QWidget *parent) 0364 : KateConfigPage(parent) 0365 { 0366 // This will let us having more separation between this page and 0367 // the QTabWidget edge (ereslibre) 0368 QVBoxLayout *layout = new QVBoxLayout(this); 0369 QWidget *newWidget = new QWidget(this); 0370 0371 ui = new Ui::NavigationConfigWidget(); 0372 ui->setupUi(newWidget); 0373 0374 initMulticursorModifierComboBox(); 0375 0376 // "What's This?" help can be found in the ui file 0377 0378 reload(); 0379 0380 observeChanges(ui->cbTextSelectionMode); 0381 observeChanges(ui->chkBackspaceRemoveComposed); 0382 observeChanges(ui->chkPagingMovesCursor); 0383 observeChanges(ui->chkScrollPastEnd); 0384 observeChanges(ui->chkSmartHome); 0385 observeChanges(ui->sbAutoCenterCursor); 0386 observeChanges(ui->chkCamelCursor); 0387 observeChanges(ui->cmbMultiCursorModifier); 0388 0389 layout->addWidget(newWidget); 0390 } 0391 0392 KateNavigationConfigTab::~KateNavigationConfigTab() 0393 { 0394 delete ui; 0395 } 0396 0397 void KateNavigationConfigTab::initMulticursorModifierComboBox() 0398 { 0399 // On macOS, the ControlModifier value corresponds to the Command keys on the 0400 // keyboard, and the MetaModifier value corresponds to the Control keys. 0401 auto *c = ui->cmbMultiCursorModifier; 0402 0403 #ifndef Q_OS_DARWIN 0404 c->insertItem(0, i18n("Alt"), (int)Qt::ALT); 0405 c->insertItem(1, i18n("Ctrl"), (int)Qt::CTRL); 0406 c->insertItem(2, i18n("Meta"), (int)Qt::META); 0407 c->insertItem(3, i18n("Ctrl + Alt"), (int)(Qt::CTRL | Qt::ALT)); 0408 c->insertItem(4, i18n("Meta + Alt"), (int)(Qt::META | Qt::ALT)); 0409 c->insertItem(5, i18n("Ctrl + Meta"), (int)(Qt::CTRL | Qt::META)); 0410 #else 0411 c->insertItem(0, i18n("Alt"), (int)Qt::ALT); 0412 c->insertItem(1, i18n("Cmd"), (int)Qt::CTRL); 0413 c->insertItem(2, i18n("Ctrl"), (int)Qt::META); 0414 c->insertItem(3, i18n("Cmd + Alt"), (int)(Qt::CTRL | Qt::ALT)); 0415 c->insertItem(4, i18n("Ctrl + Alt"), (int)(Qt::META | Qt::ALT)); 0416 c->insertItem(5, i18n("Cmd + Ctrl"), (int)(Qt::CTRL | Qt::META)); 0417 #endif 0418 } 0419 0420 void KateNavigationConfigTab::apply() 0421 { 0422 // nothing changed, no need to apply stuff 0423 if (!hasChanged()) { 0424 return; 0425 } 0426 m_changed = false; 0427 0428 KateViewConfig::global()->configStart(); 0429 KateDocumentConfig::global()->configStart(); 0430 0431 KateDocumentConfig::global()->setPageUpDownMovesCursor(ui->chkPagingMovesCursor->isChecked()); 0432 KateDocumentConfig::global()->setSmartHome(ui->chkSmartHome->isChecked()); 0433 KateDocumentConfig::global()->setCamelCursor(ui->chkCamelCursor->isChecked()); 0434 0435 KateViewConfig::global()->setValue(KateViewConfig::AutoCenterLines, ui->sbAutoCenterCursor->value()); 0436 KateViewConfig::global()->setValue(KateViewConfig::BackspaceRemoveComposedCharacters, ui->chkBackspaceRemoveComposed->isChecked()); 0437 KateViewConfig::global()->setValue(KateViewConfig::PersistentSelection, ui->cbTextSelectionMode->currentIndex() == 1); 0438 KateViewConfig::global()->setValue(KateViewConfig::ScrollPastEnd, ui->chkScrollPastEnd->isChecked()); 0439 0440 const int modifers = ui->cmbMultiCursorModifier->currentData().toInt(); 0441 KateViewConfig::global()->setMultiCursorModifiers(Qt::KeyboardModifiers(modifers)); 0442 0443 KateDocumentConfig::global()->configEnd(); 0444 KateViewConfig::global()->configEnd(); 0445 } 0446 0447 void KateNavigationConfigTab::reload() 0448 { 0449 ui->cbTextSelectionMode->setCurrentIndex(KateViewConfig::global()->persistentSelection() ? 1 : 0); 0450 0451 ui->chkBackspaceRemoveComposed->setChecked(KateViewConfig::global()->backspaceRemoveComposed()); 0452 ui->chkPagingMovesCursor->setChecked(KateDocumentConfig::global()->pageUpDownMovesCursor()); 0453 ui->chkScrollPastEnd->setChecked(KateViewConfig::global()->scrollPastEnd()); 0454 ui->chkSmartHome->setChecked(KateDocumentConfig::global()->smartHome()); 0455 ui->chkCamelCursor->setChecked(KateDocumentConfig::global()->camelCursor()); 0456 0457 ui->sbAutoCenterCursor->setValue(KateViewConfig::global()->autoCenterLines()); 0458 0459 const int mods = KateViewConfig::global()->multiCursorModifiers(); 0460 const auto count = ui->cmbMultiCursorModifier->count(); 0461 for (int i = 0; i < count; ++i) { 0462 int idxMods = ui->cmbMultiCursorModifier->itemData(i).toInt(); 0463 if (idxMods == mods) { 0464 ui->cmbMultiCursorModifier->setCurrentIndex(i); 0465 break; 0466 } 0467 } 0468 } 0469 0470 QString KateNavigationConfigTab::name() const 0471 { 0472 return i18n("Text Navigation"); 0473 } 0474 0475 // END KateNavigationConfigTab 0476 0477 // BEGIN KateEditGeneralConfigTab 0478 KateEditGeneralConfigTab::KateEditGeneralConfigTab(QWidget *parent) 0479 : KateConfigPage(parent) 0480 { 0481 QVBoxLayout *layout = new QVBoxLayout(this); 0482 QWidget *newWidget = new QWidget(this); 0483 ui = new Ui::EditConfigWidget(); 0484 ui->setupUi(newWidget); 0485 0486 for (const auto &fact : KTextEditor::EditorPrivate::self()->inputModeFactories()) { 0487 ui->cmbInputMode->addItem(fact->name(), static_cast<int>(fact->inputMode())); 0488 } 0489 0490 // "What's This?" Help is in the ui-files 0491 0492 reload(); 0493 0494 observeChanges(ui->chkAutoBrackets); 0495 observeChanges(ui->chkMousePasteAtCursorPosition); 0496 observeChanges(ui->chkShowStaticWordWrapMarker); 0497 observeChanges(ui->chkTextDragAndDrop); 0498 observeChanges(ui->chkSmartCopyCut); 0499 observeChanges(ui->sbClipboardHistoryEntries); 0500 observeChanges(ui->chkStaticWordWrap); 0501 observeChanges(ui->cmbEncloseSelection); 0502 ui->lblBracketHelp->setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont)); 0503 connect(ui->cmbEncloseSelection->lineEdit(), &QLineEdit::editingFinished, [=] { 0504 const int index = ui->cmbEncloseSelection->currentIndex(); 0505 const QString text = ui->cmbEncloseSelection->currentText(); 0506 // Text removed? Remove item, but don't remove default data! 0507 if (index >= UserData && text.isEmpty()) { 0508 ui->cmbEncloseSelection->removeItem(index); 0509 slotChanged(); 0510 0511 // Not already there? Add new item! For whatever reason it isn't done automatically 0512 } else if (ui->cmbEncloseSelection->findText(text) < 0) { 0513 ui->cmbEncloseSelection->addItem(text); 0514 slotChanged(); 0515 } 0516 ui->cmbEncloseSelection->setCurrentIndex(ui->cmbEncloseSelection->findText(text)); 0517 }); 0518 observeChanges(ui->cmbInputMode); 0519 observeChanges(ui->sbWordWrap); 0520 0521 layout->addWidget(newWidget); 0522 } 0523 0524 KateEditGeneralConfigTab::~KateEditGeneralConfigTab() 0525 { 0526 delete ui; 0527 } 0528 0529 void KateEditGeneralConfigTab::apply() 0530 { 0531 // nothing changed, no need to apply stuff 0532 if (!hasChanged()) { 0533 return; 0534 } 0535 m_changed = false; 0536 0537 KateViewConfig::global()->configStart(); 0538 KateDocumentConfig::global()->configStart(); 0539 0540 KateDocumentConfig::global()->setWordWrap(ui->chkStaticWordWrap->isChecked()); 0541 KateDocumentConfig::global()->setWordWrapAt(ui->sbWordWrap->value()); 0542 0543 KateRendererConfig::global()->setWordWrapMarker(ui->chkShowStaticWordWrapMarker->isChecked()); 0544 0545 KateViewConfig::global()->setValue(KateViewConfig::AutoBrackets, ui->chkAutoBrackets->isChecked()); 0546 KateViewConfig::global()->setValue(KateViewConfig::CharsToEncloseSelection, ui->cmbEncloseSelection->currentText()); 0547 QStringList userLetters; 0548 for (int i = UserData; i < ui->cmbEncloseSelection->count(); ++i) { 0549 userLetters.append(ui->cmbEncloseSelection->itemText(i)); 0550 } 0551 KateViewConfig::global()->setValue(KateViewConfig::UserSetsOfCharsToEncloseSelection, userLetters); 0552 KateViewConfig::global()->setValue(KateViewConfig::InputMode, ui->cmbInputMode->currentData().toInt()); 0553 KateViewConfig::global()->setValue(KateViewConfig::MousePasteAtCursorPosition, ui->chkMousePasteAtCursorPosition->isChecked()); 0554 KateViewConfig::global()->setValue(KateViewConfig::TextDragAndDrop, ui->chkTextDragAndDrop->isChecked()); 0555 KateViewConfig::global()->setValue(KateViewConfig::SmartCopyCut, ui->chkSmartCopyCut->isChecked()); 0556 KateViewConfig::global()->setValue(KateViewConfig::ClipboardHistoryEntries, ui->sbClipboardHistoryEntries->value()); 0557 0558 KateDocumentConfig::global()->configEnd(); 0559 KateViewConfig::global()->configEnd(); 0560 } 0561 0562 void KateEditGeneralConfigTab::reload() 0563 { 0564 ui->chkAutoBrackets->setChecked(KateViewConfig::global()->autoBrackets()); 0565 ui->chkMousePasteAtCursorPosition->setChecked(KateViewConfig::global()->mousePasteAtCursorPosition()); 0566 ui->chkShowStaticWordWrapMarker->setChecked(KateRendererConfig::global()->wordWrapMarker()); 0567 ui->chkTextDragAndDrop->setChecked(KateViewConfig::global()->textDragAndDrop()); 0568 ui->chkSmartCopyCut->setChecked(KateViewConfig::global()->smartCopyCut()); 0569 ui->chkStaticWordWrap->setChecked(KateDocumentConfig::global()->wordWrap()); 0570 ui->sbClipboardHistoryEntries->setValue(KateViewConfig::global()->clipboardHistoryEntries()); 0571 0572 ui->sbWordWrap->setSuffix(ki18ncp("Wrap words at (value is at 20 or larger)", " character", " characters")); 0573 ui->sbWordWrap->setValue(KateDocumentConfig::global()->wordWrapAt()); 0574 0575 ui->cmbEncloseSelection->clear(); 0576 ui->cmbEncloseSelection->lineEdit()->setClearButtonEnabled(true); 0577 ui->cmbEncloseSelection->lineEdit()->setPlaceholderText(i18n("Feature is not active")); 0578 ui->cmbEncloseSelection->addItem(QString(), None); 0579 ui->cmbEncloseSelection->setItemData(0, i18n("Disable Feature"), Qt::ToolTipRole); 0580 ui->cmbEncloseSelection->addItem(QStringLiteral("`*_~"), MarkDown); 0581 ui->cmbEncloseSelection->setItemData(1, i18n("May be handy with Markdown"), Qt::ToolTipRole); 0582 ui->cmbEncloseSelection->addItem(QStringLiteral("<>(){}[]'\""), MirrorChar); 0583 ui->cmbEncloseSelection->setItemData(2, i18n("Mirror characters, similar but not exactly like auto brackets"), Qt::ToolTipRole); 0584 ui->cmbEncloseSelection->addItem(QStringLiteral("´`_.:|#@~*!?$%/=,;-+^°§&"), NonLetters); 0585 ui->cmbEncloseSelection->setItemData(3, i18n("Non letter character"), Qt::ToolTipRole); 0586 const QStringList userLetters = KateViewConfig::global()->value(KateViewConfig::UserSetsOfCharsToEncloseSelection).toStringList(); 0587 for (int i = 0; i < userLetters.size(); ++i) { 0588 ui->cmbEncloseSelection->addItem(userLetters.at(i), UserData + i); 0589 } 0590 ui->cmbEncloseSelection->setCurrentIndex(ui->cmbEncloseSelection->findText(KateViewConfig::global()->charsToEncloseSelection())); 0591 0592 const int id = static_cast<int>(KateViewConfig::global()->inputMode()); 0593 ui->cmbInputMode->setCurrentIndex(ui->cmbInputMode->findData(id)); 0594 } 0595 0596 QString KateEditGeneralConfigTab::name() const 0597 { 0598 return i18n("General"); 0599 } 0600 0601 // END KateEditGeneralConfigTab 0602 0603 // BEGIN KateEditConfigTab 0604 KateEditConfigTab::KateEditConfigTab(QWidget *parent) 0605 : KateConfigPage(parent) 0606 , editConfigTab(new KateEditGeneralConfigTab(this)) 0607 , navigationConfigTab(new KateNavigationConfigTab(this)) 0608 , indentConfigTab(new KateIndentConfigTab(this)) 0609 , completionConfigTab(new KateCompletionConfigTab(this)) 0610 , spellCheckConfigTab(new KateSpellCheckConfigTab(this)) 0611 { 0612 QVBoxLayout *layout = new QVBoxLayout(this); 0613 layout->setContentsMargins(0, 0, 0, 0); 0614 QTabWidget *tabWidget = new QTabWidget(this); 0615 0616 // add all tabs 0617 tabWidget->insertTab(0, editConfigTab, editConfigTab->name()); 0618 tabWidget->insertTab(1, navigationConfigTab, navigationConfigTab->name()); 0619 tabWidget->insertTab(2, indentConfigTab, indentConfigTab->name()); 0620 tabWidget->insertTab(3, completionConfigTab, completionConfigTab->name()); 0621 tabWidget->insertTab(4, spellCheckConfigTab, spellCheckConfigTab->name()); 0622 0623 observeChanges(editConfigTab); 0624 observeChanges(navigationConfigTab); 0625 observeChanges(indentConfigTab); 0626 observeChanges(completionConfigTab); 0627 observeChanges(spellCheckConfigTab); 0628 0629 int i = tabWidget->count(); 0630 for (const auto &factory : KTextEditor::EditorPrivate::self()->inputModeFactories()) { 0631 KateConfigPage *tab = factory->createConfigPage(this); 0632 if (tab) { 0633 m_inputModeConfigTabs << tab; 0634 tabWidget->insertTab(i, tab, tab->name()); 0635 observeChanges(tab); 0636 i++; 0637 } 0638 } 0639 0640 layout->addWidget(tabWidget); 0641 } 0642 0643 KateEditConfigTab::~KateEditConfigTab() 0644 { 0645 qDeleteAll(m_inputModeConfigTabs); 0646 } 0647 0648 void KateEditConfigTab::apply() 0649 { 0650 // try to update the rest of tabs 0651 editConfigTab->apply(); 0652 navigationConfigTab->apply(); 0653 indentConfigTab->apply(); 0654 completionConfigTab->apply(); 0655 spellCheckConfigTab->apply(); 0656 for (KateConfigPage *tab : std::as_const(m_inputModeConfigTabs)) { 0657 tab->apply(); 0658 } 0659 } 0660 0661 void KateEditConfigTab::reload() 0662 { 0663 editConfigTab->reload(); 0664 navigationConfigTab->reload(); 0665 indentConfigTab->reload(); 0666 completionConfigTab->reload(); 0667 spellCheckConfigTab->reload(); 0668 for (KateConfigPage *tab : std::as_const(m_inputModeConfigTabs)) { 0669 tab->reload(); 0670 } 0671 } 0672 0673 void KateEditConfigTab::reset() 0674 { 0675 editConfigTab->reset(); 0676 navigationConfigTab->reset(); 0677 indentConfigTab->reset(); 0678 completionConfigTab->reset(); 0679 spellCheckConfigTab->reset(); 0680 for (KateConfigPage *tab : std::as_const(m_inputModeConfigTabs)) { 0681 tab->reset(); 0682 } 0683 } 0684 0685 void KateEditConfigTab::defaults() 0686 { 0687 editConfigTab->defaults(); 0688 navigationConfigTab->defaults(); 0689 indentConfigTab->defaults(); 0690 completionConfigTab->defaults(); 0691 spellCheckConfigTab->defaults(); 0692 for (KateConfigPage *tab : std::as_const(m_inputModeConfigTabs)) { 0693 tab->defaults(); 0694 } 0695 } 0696 0697 QString KateEditConfigTab::name() const 0698 { 0699 return i18n("Editing"); 0700 } 0701 0702 QString KateEditConfigTab::fullName() const 0703 { 0704 return i18n("Editing Options"); 0705 } 0706 0707 QIcon KateEditConfigTab::icon() const 0708 { 0709 return QIcon::fromTheme(QStringLiteral("accessories-text-editor")); 0710 } 0711 0712 // END KateEditConfigTab 0713 0714 // BEGIN KateViewDefaultsConfig 0715 KateViewDefaultsConfig::KateViewDefaultsConfig(QWidget *parent) 0716 : KateConfigPage(parent) 0717 , textareaUi(new Ui::TextareaAppearanceConfigWidget()) 0718 , bordersUi(new Ui::BordersAppearanceConfigWidget()) 0719 , statusBarUi(new Ui::StatusbarConfigWidget()) 0720 { 0721 QLayout *layout = new QVBoxLayout(this); 0722 QTabWidget *tabWidget = new QTabWidget(this); 0723 layout->addWidget(tabWidget); 0724 layout->setContentsMargins(0, 0, 0, 0); 0725 0726 QWidget *textareaTab = new QWidget(tabWidget); 0727 textareaUi->setupUi(textareaTab); 0728 tabWidget->addTab(textareaTab, i18n("General")); 0729 0730 QWidget *bordersTab = new QWidget(tabWidget); 0731 bordersUi->setupUi(bordersTab); 0732 tabWidget->addTab(bordersTab, i18n("Borders")); 0733 0734 QWidget *statusbarTab = new QWidget(tabWidget); 0735 statusBarUi->setupUi(statusbarTab); 0736 tabWidget->addTab(statusbarTab, i18n("Statusbar")); 0737 0738 textareaUi->cmbDynamicWordWrapIndicator->addItem(i18n("Off")); 0739 textareaUi->cmbDynamicWordWrapIndicator->addItem(i18n("Follow Line Numbers")); 0740 textareaUi->cmbDynamicWordWrapIndicator->addItem(i18n("Always On")); 0741 0742 // "What's This?" help is in the ui-file 0743 0744 reload(); 0745 0746 observeChanges(textareaUi->kfontrequester); 0747 0748 observeChanges(textareaUi->chkAnimateBracketMatching); 0749 observeChanges(textareaUi->chkDynWrapAnywhere); 0750 observeChanges(textareaUi->chkDynWrapAtStaticMarker); 0751 observeChanges(textareaUi->chkFoldFirstLine); 0752 observeChanges(textareaUi->chkShowBracketMatchPreview); 0753 observeChanges(textareaUi->chkShowIndentationLines); 0754 observeChanges(textareaUi->chkShowLineCount); 0755 observeChanges(textareaUi->chkShowTabs); 0756 observeChanges(textareaUi->chkShowWholeBracketExpression); 0757 observeChanges(textareaUi->chkShowWordCount); 0758 observeChanges(textareaUi->cmbDynamicWordWrapIndicator); 0759 observeChanges(textareaUi->cbxWordWrap); 0760 observeChanges(textareaUi->chkFocusFrame); 0761 observeChanges(textareaUi->spbLineHeightMultiplier); 0762 auto a = [ui = textareaUi, cbx = textareaUi->cbxWordWrap]() { 0763 ui->chkDynWrapAtStaticMarker->setEnabled(cbx->isChecked()); 0764 ui->chkDynWrapAnywhere->setEnabled(cbx->isChecked()); 0765 ui->cmbDynamicWordWrapIndicator->setEnabled(cbx->isChecked()); 0766 ui->sbDynamicWordWrapDepth->setEnabled(cbx->isChecked()); 0767 }; 0768 connect(textareaUi->cbxWordWrap, &QCheckBox::stateChanged, this, a); 0769 a(); 0770 auto b = [cbx = textareaUi->cbxIndentWrappedLines, sb = textareaUi->sbDynamicWordWrapDepth]() { 0771 sb->setEnabled(cbx->isChecked()); 0772 }; 0773 b(); 0774 connect(textareaUi->cbxIndentWrappedLines, &QCheckBox::stateChanged, this, b); 0775 observeChanges(textareaUi->cbxIndentWrappedLines); 0776 observeChanges(textareaUi->sbDynamicWordWrapDepth); 0777 observeChanges(textareaUi->sliSetMarkerSize); 0778 observeChanges(textareaUi->spacesComboBox); 0779 0780 observeChanges(bordersUi->chkIconBorder); 0781 observeChanges(bordersUi->chkLineNumbers); 0782 observeChanges(bordersUi->chkScrollbarMarks); 0783 observeChanges(bordersUi->chkScrollbarMiniMap); 0784 observeChanges(bordersUi->chkScrollbarMiniMapAll); 0785 bordersUi->chkScrollbarMiniMapAll->hide(); // this is temporary until the feature is done 0786 observeChanges(bordersUi->chkScrollbarPreview); 0787 observeChanges(bordersUi->chkShowFoldingMarkers); 0788 observeChanges(bordersUi->chkShowFoldingPreview); 0789 observeChanges(bordersUi->chkShowLineModification); 0790 observeChanges(bordersUi->cmbShowScrollbars); 0791 observeChanges(bordersUi->rbSortBookmarksByCreation); 0792 observeChanges(bordersUi->rbSortBookmarksByPosition); 0793 observeChanges(bordersUi->spBoxMiniMapWidth); 0794 observeChanges(bordersUi->cmbFoldingArrowVisiblity); 0795 0796 // statusBarUi 0797 observeChanges(statusBarUi->cbShowActiveDictionary); 0798 observeChanges(statusBarUi->cbShowHighlightingMode); 0799 observeChanges(statusBarUi->cbShowInputMode); 0800 observeChanges(statusBarUi->cbShowLineColumn); 0801 observeChanges(statusBarUi->cbShowTabSetting); 0802 observeChanges(statusBarUi->cbShowEncoding); 0803 observeChanges(statusBarUi->cbShowEOL); 0804 } 0805 0806 KateViewDefaultsConfig::~KateViewDefaultsConfig() 0807 { 0808 delete bordersUi; 0809 delete textareaUi; 0810 delete statusBarUi; 0811 } 0812 0813 void KateViewDefaultsConfig::apply() 0814 { 0815 // nothing changed, no need to apply stuff 0816 if (!hasChanged()) { 0817 return; 0818 } 0819 m_changed = false; 0820 0821 KateViewConfig::global()->configStart(); 0822 KateRendererConfig::global()->configStart(); 0823 0824 KateDocumentConfig::global()->setMarkerSize(textareaUi->sliSetMarkerSize->value()); 0825 KateDocumentConfig::global()->setShowSpaces(KateDocumentConfig::WhitespaceRendering(textareaUi->spacesComboBox->currentIndex())); 0826 KateDocumentConfig::global()->setShowTabs(textareaUi->chkShowTabs->isChecked()); 0827 0828 KateRendererConfig::global()->setFont(textareaUi->kfontrequester->font()); 0829 KateRendererConfig::global()->setAnimateBracketMatching(textareaUi->chkAnimateBracketMatching->isChecked()); 0830 KateRendererConfig::global()->setShowIndentationLines(textareaUi->chkShowIndentationLines->isChecked()); 0831 KateRendererConfig::global()->setShowWholeBracketExpression(textareaUi->chkShowWholeBracketExpression->isChecked()); 0832 KateRendererConfig::global()->setLineHeightMultiplier(textareaUi->spbLineHeightMultiplier->value()); 0833 0834 KateViewConfig::global()->setDynWordWrap(textareaUi->cbxWordWrap->isChecked()); 0835 KateViewConfig::global()->setShowWordCount(textareaUi->chkShowWordCount->isChecked()); 0836 KateViewConfig::global()->setValue(KateViewConfig::BookmarkSorting, bordersUi->rbSortBookmarksByPosition->isChecked() ? 0 : 1); 0837 if (!textareaUi->cbxIndentWrappedLines->isChecked()) { 0838 KateViewConfig::global()->setValue(KateViewConfig::DynWordWrapAlignIndent, 0); 0839 } else { 0840 KateViewConfig::global()->setValue(KateViewConfig::DynWordWrapAlignIndent, textareaUi->sbDynamicWordWrapDepth->value()); 0841 } 0842 KateViewConfig::global()->setValue(KateViewConfig::DynWordWrapIndicators, textareaUi->cmbDynamicWordWrapIndicator->currentIndex()); 0843 KateViewConfig::global()->setValue(KateViewConfig::DynWrapAnywhere, textareaUi->chkDynWrapAnywhere->isChecked()); 0844 KateViewConfig::global()->setValue(KateViewConfig::DynWrapAtStaticMarker, textareaUi->chkDynWrapAtStaticMarker->isChecked()); 0845 KateViewConfig::global()->setValue(KateViewConfig::FoldFirstLine, textareaUi->chkFoldFirstLine->isChecked()); 0846 KateViewConfig::global()->setValue(KateViewConfig::ScrollBarMiniMapWidth, bordersUi->spBoxMiniMapWidth->value()); 0847 KateViewConfig::global()->setValue(KateViewConfig::ShowBracketMatchPreview, textareaUi->chkShowBracketMatchPreview->isChecked()); 0848 KateViewConfig::global()->setValue(KateViewConfig::ShowFocusFrame, textareaUi->chkFocusFrame->isChecked()); 0849 KateViewConfig::global()->setValue(KateViewConfig::ShowFoldingBar, bordersUi->chkShowFoldingMarkers->isChecked()); 0850 KateViewConfig::global()->setValue(KateViewConfig::ShowFoldingPreview, bordersUi->chkShowFoldingPreview->isChecked()); 0851 KateViewConfig::global()->setValue(KateViewConfig::ShowIconBar, bordersUi->chkIconBorder->isChecked()); 0852 KateViewConfig::global()->setValue(KateViewConfig::ShowLineCount, textareaUi->chkShowLineCount->isChecked()); 0853 KateViewConfig::global()->setValue(KateViewConfig::ShowLineModification, bordersUi->chkShowLineModification->isChecked()); 0854 KateViewConfig::global()->setValue(KateViewConfig::ShowLineNumbers, bordersUi->chkLineNumbers->isChecked()); 0855 KateViewConfig::global()->setValue(KateViewConfig::ShowScrollBarMarks, bordersUi->chkScrollbarMarks->isChecked()); 0856 KateViewConfig::global()->setValue(KateViewConfig::ShowScrollBarMiniMap, bordersUi->chkScrollbarMiniMap->isChecked()); 0857 KateViewConfig::global()->setValue(KateViewConfig::ShowScrollBarMiniMapAll, bordersUi->chkScrollbarMiniMapAll->isChecked()); 0858 KateViewConfig::global()->setValue(KateViewConfig::ShowScrollBarPreview, bordersUi->chkScrollbarPreview->isChecked()); 0859 KateViewConfig::global()->setValue(KateViewConfig::ShowScrollbars, bordersUi->cmbShowScrollbars->currentIndex()); 0860 bool showOnHoverOnly = bordersUi->cmbFoldingArrowVisiblity->currentIndex() == 0; 0861 KateViewConfig::global()->setValue(KateViewConfig::ShowFoldingOnHoverOnly, showOnHoverOnly); 0862 0863 // Statusbar stuff 0864 KateViewConfig::global()->setValue(KateViewConfig::ShowStatusbarDictionary, statusBarUi->cbShowActiveDictionary->isChecked()); 0865 KateViewConfig::global()->setValue(KateViewConfig::ShowStatusbarHighlightingMode, statusBarUi->cbShowHighlightingMode->isChecked()); 0866 KateViewConfig::global()->setValue(KateViewConfig::ShowStatusbarInputMode, statusBarUi->cbShowInputMode->isChecked()); 0867 KateViewConfig::global()->setValue(KateViewConfig::ShowStatusbarLineColumn, statusBarUi->cbShowLineColumn->isChecked()); 0868 KateViewConfig::global()->setValue(KateViewConfig::ShowStatusbarTabSettings, statusBarUi->cbShowTabSetting->isChecked()); 0869 KateViewConfig::global()->setValue(KateViewConfig::ShowStatusbarFileEncoding, statusBarUi->cbShowEncoding->isChecked()); 0870 KateViewConfig::global()->setValue(KateViewConfig::ShowStatusbarEOL, statusBarUi->cbShowEOL->isChecked()); 0871 0872 KateRendererConfig::global()->configEnd(); 0873 KateViewConfig::global()->configEnd(); 0874 } 0875 0876 void KateViewDefaultsConfig::reload() 0877 { 0878 bordersUi->chkIconBorder->setChecked(KateViewConfig::global()->iconBar()); 0879 bordersUi->chkLineNumbers->setChecked(KateViewConfig::global()->lineNumbers()); 0880 bordersUi->chkScrollbarMarks->setChecked(KateViewConfig::global()->scrollBarMarks()); 0881 bordersUi->chkScrollbarMiniMap->setChecked(KateViewConfig::global()->scrollBarMiniMap()); 0882 bordersUi->chkScrollbarMiniMapAll->setChecked(KateViewConfig::global()->scrollBarMiniMapAll()); 0883 bordersUi->chkScrollbarPreview->setChecked(KateViewConfig::global()->scrollBarPreview()); 0884 bordersUi->chkShowFoldingMarkers->setChecked(KateViewConfig::global()->foldingBar()); 0885 bordersUi->chkShowFoldingPreview->setChecked(KateViewConfig::global()->foldingPreview()); 0886 bordersUi->chkShowLineModification->setChecked(KateViewConfig::global()->lineModification()); 0887 bordersUi->cmbShowScrollbars->setCurrentIndex(KateViewConfig::global()->showScrollbars()); 0888 bordersUi->rbSortBookmarksByCreation->setChecked(KateViewConfig::global()->bookmarkSort() == 1); 0889 bordersUi->rbSortBookmarksByPosition->setChecked(KateViewConfig::global()->bookmarkSort() == 0); 0890 bordersUi->spBoxMiniMapWidth->setValue(KateViewConfig::global()->scrollBarMiniMapWidth()); 0891 bordersUi->cmbFoldingArrowVisiblity->setCurrentIndex(KateViewConfig::global()->showFoldingOnHoverOnly() ? 0 : 1); 0892 0893 textareaUi->kfontrequester->setFont(KateRendererConfig::global()->baseFont()); 0894 0895 textareaUi->chkAnimateBracketMatching->setChecked(KateRendererConfig::global()->animateBracketMatching()); 0896 textareaUi->chkDynWrapAnywhere->setChecked(KateViewConfig::global()->dynWrapAnywhere()); 0897 textareaUi->chkDynWrapAtStaticMarker->setChecked(KateViewConfig::global()->dynWrapAtStaticMarker()); 0898 textareaUi->chkFoldFirstLine->setChecked(KateViewConfig::global()->foldFirstLine()); 0899 textareaUi->chkShowBracketMatchPreview->setChecked(KateViewConfig::global()->value(KateViewConfig::ShowBracketMatchPreview).toBool()); 0900 textareaUi->chkShowIndentationLines->setChecked(KateRendererConfig::global()->showIndentationLines()); 0901 textareaUi->chkShowLineCount->setChecked(KateViewConfig::global()->showLineCount()); 0902 textareaUi->chkShowTabs->setChecked(KateDocumentConfig::global()->showTabs()); 0903 textareaUi->chkShowWholeBracketExpression->setChecked(KateRendererConfig::global()->showWholeBracketExpression()); 0904 textareaUi->chkShowWordCount->setChecked(KateViewConfig::global()->showWordCount()); 0905 textareaUi->cmbDynamicWordWrapIndicator->setCurrentIndex(KateViewConfig::global()->dynWordWrapIndicators()); 0906 textareaUi->cbxWordWrap->setChecked(KateViewConfig::global()->dynWordWrap()); 0907 textareaUi->cbxIndentWrappedLines->setChecked(KateViewConfig::global()->dynWordWrapAlignIndent() != 0); 0908 textareaUi->sbDynamicWordWrapDepth->setValue(KateViewConfig::global()->dynWordWrapAlignIndent()); 0909 textareaUi->sliSetMarkerSize->setValue(KateDocumentConfig::global()->markerSize()); 0910 textareaUi->spacesComboBox->setCurrentIndex(KateDocumentConfig::global()->showSpaces()); 0911 textareaUi->chkFocusFrame->setChecked(KateViewConfig::global()->showFocusFrame()); 0912 textareaUi->spbLineHeightMultiplier->setValue(KateRendererConfig::global()->lineHeightMultiplier()); 0913 0914 statusBarUi->cbShowLineColumn->setChecked(KateViewConfig::global()->value(KateViewConfig::ShowStatusbarLineColumn).toBool()); 0915 statusBarUi->cbShowActiveDictionary->setChecked(KateViewConfig::global()->value(KateViewConfig::ShowStatusbarDictionary).toBool()); 0916 statusBarUi->cbShowTabSetting->setChecked(KateViewConfig::global()->value(KateViewConfig::ShowStatusbarTabSettings).toBool()); 0917 statusBarUi->cbShowHighlightingMode->setChecked(KateViewConfig::global()->value(KateViewConfig::ShowStatusbarHighlightingMode).toBool()); 0918 statusBarUi->cbShowInputMode->setChecked(KateViewConfig::global()->value(KateViewConfig::ShowStatusbarInputMode).toBool()); 0919 statusBarUi->cbShowEncoding->setChecked(KateViewConfig::global()->value(KateViewConfig::ShowStatusbarFileEncoding).toBool()); 0920 statusBarUi->cbShowEOL->setChecked(KateViewConfig::global()->value(KateViewConfig::ShowStatusbarEOL).toBool()); 0921 } 0922 0923 void KateViewDefaultsConfig::reset() 0924 { 0925 } 0926 0927 void KateViewDefaultsConfig::defaults() 0928 { 0929 } 0930 0931 QString KateViewDefaultsConfig::name() const 0932 { 0933 return i18n("Appearance"); 0934 } 0935 0936 QString KateViewDefaultsConfig::fullName() const 0937 { 0938 return i18n("Appearance"); 0939 } 0940 0941 QIcon KateViewDefaultsConfig::icon() const 0942 { 0943 return QIcon::fromTheme(QStringLiteral("preferences-desktop-theme")); 0944 } 0945 0946 // END KateViewDefaultsConfig 0947 0948 // BEGIN KateSaveConfigTab 0949 KateSaveConfigTab::KateSaveConfigTab(QWidget *parent) 0950 : KateConfigPage(parent) 0951 , modeConfigPage(new ModeConfigPage(this)) 0952 { 0953 // FIXME: Is really needed to move all this code below to another class, 0954 // since it is another tab itself on the config dialog. This means we should 0955 // initialize, add and work with as we do with modeConfigPage (ereslibre) 0956 QVBoxLayout *layout = new QVBoxLayout(this); 0957 layout->setContentsMargins(0, 0, 0, 0); 0958 QTabWidget *tabWidget = new QTabWidget(this); 0959 0960 QWidget *tmpWidget = new QWidget(tabWidget); 0961 QVBoxLayout *internalLayout = new QVBoxLayout(tmpWidget); 0962 QWidget *newWidget = new QWidget(tabWidget); 0963 ui = new Ui::OpenSaveConfigWidget(); 0964 ui->setupUi(newWidget); 0965 0966 QWidget *tmpWidget2 = new QWidget(tabWidget); 0967 QVBoxLayout *internalLayout2 = new QVBoxLayout(tmpWidget2); 0968 QWidget *newWidget2 = new QWidget(tabWidget); 0969 uiadv = new Ui::OpenSaveConfigAdvWidget(); 0970 uiadv->setupUi(newWidget2); 0971 uiadv->lblExplanatory->setText(i18n("%1 backs up unsaved files to \"swap files.\" Swap files allow %1 to recover your work in the case of a system crash. Disabling swap files may cause data loss in case of a system crash.", QCoreApplication::applicationName())); 0972 uiadv->lblExplanatory->setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont)); 0973 0974 // "What's This?" help can be found in the ui file 0975 0976 reload(); 0977 0978 observeChanges(ui->cbRemoveTrailingSpaces); 0979 observeChanges(ui->chkDetectEOL); 0980 observeChanges(ui->chkEnableBOM); 0981 observeChanges(ui->chkNewLineAtEof); 0982 observeChanges(ui->cmbEOL); 0983 observeChanges(ui->cmbEncoding); 0984 observeChanges(ui->cmbEncodingDetection); 0985 observeChanges(ui->cmbEncodingFallback); 0986 observeChanges(ui->lineLengthLimit); 0987 observeChanges(ui->gbAutoSave); 0988 observeChanges(ui->cbAutoSaveOnFocus); 0989 observeChanges(ui->spbAutoSaveInterval); 0990 0991 observeChanges(uiadv->chkAutoReloadVersionControl); 0992 0993 observeChanges(uiadv->chkBackupLocalFiles); 0994 observeChanges(uiadv->chkBackupRemoteFiles); 0995 observeChanges(uiadv->cmbSwapFileMode); 0996 connect(uiadv->cmbSwapFileMode, qOverload<int>(&QComboBox::currentIndexChanged), this, &KateSaveConfigTab::swapFileModeChanged); 0997 0998 observeChanges(uiadv->edtBackupPrefix); 0999 observeChanges(uiadv->edtBackupSuffix); 1000 observeChanges(uiadv->kurlSwapDirectory); 1001 observeChanges(uiadv->spbSwapFileSync); 1002 1003 internalLayout->addWidget(newWidget); 1004 internalLayout2->addWidget(newWidget2); 1005 1006 // add all tabs 1007 tabWidget->insertTab(0, tmpWidget, i18n("General")); 1008 tabWidget->insertTab(1, tmpWidget2, i18n("Advanced")); 1009 tabWidget->insertTab(2, modeConfigPage, modeConfigPage->name()); 1010 1011 observeChanges(modeConfigPage); 1012 1013 layout->addWidget(tabWidget); 1014 1015 // support variable expansion in backup prefix/suffix 1016 KTextEditor::Editor::instance()->addVariableExpansion({uiadv->edtBackupPrefix, uiadv->edtBackupSuffix}, 1017 {QStringLiteral("Date:Locale"), 1018 QStringLiteral("Date:ISO"), 1019 QStringLiteral("Date:"), 1020 QStringLiteral("Time:Locale"), 1021 QStringLiteral("Time:ISO"), 1022 QStringLiteral("Time:"), 1023 QStringLiteral("ENV:"), 1024 QStringLiteral("JS:"), 1025 QStringLiteral("UUID")}); 1026 } 1027 1028 KateSaveConfigTab::~KateSaveConfigTab() 1029 { 1030 delete uiadv; 1031 delete ui; 1032 } 1033 1034 void KateSaveConfigTab::swapFileModeChanged(int idx) 1035 { 1036 const KateDocumentConfig::SwapFileMode mode = static_cast<KateDocumentConfig::SwapFileMode>(idx); 1037 switch (mode) { 1038 case KateDocumentConfig::DisableSwapFile: 1039 uiadv->lblSwapDirectory->setEnabled(false); 1040 uiadv->kurlSwapDirectory->setEnabled(false); 1041 uiadv->lblSwapFileSync->setEnabled(false); 1042 uiadv->spbSwapFileSync->setEnabled(false); 1043 break; 1044 case KateDocumentConfig::EnableSwapFile: 1045 uiadv->lblSwapDirectory->setEnabled(false); 1046 uiadv->kurlSwapDirectory->setEnabled(false); 1047 uiadv->lblSwapFileSync->setEnabled(true); 1048 uiadv->spbSwapFileSync->setEnabled(true); 1049 break; 1050 case KateDocumentConfig::SwapFilePresetDirectory: 1051 uiadv->lblSwapDirectory->setEnabled(true); 1052 uiadv->kurlSwapDirectory->setEnabled(true); 1053 uiadv->lblSwapFileSync->setEnabled(true); 1054 uiadv->spbSwapFileSync->setEnabled(true); 1055 break; 1056 } 1057 } 1058 1059 void KateSaveConfigTab::apply() 1060 { 1061 modeConfigPage->apply(); 1062 1063 // nothing changed, no need to apply stuff 1064 if (!hasChanged()) { 1065 return; 1066 } 1067 m_changed = false; 1068 1069 KateGlobalConfig::global()->configStart(); 1070 KateDocumentConfig::global()->configStart(); 1071 1072 if (uiadv->edtBackupSuffix->text().isEmpty() && uiadv->edtBackupPrefix->text().isEmpty()) { 1073 KMessageBox::information(this, i18n("You did not provide a backup suffix or prefix. Using default suffix: '~'"), i18n("No Backup Suffix or Prefix")); 1074 uiadv->edtBackupSuffix->setText(QStringLiteral("~")); 1075 } 1076 1077 KateDocumentConfig::global()->setBackupOnSaveLocal(uiadv->chkBackupLocalFiles->isChecked()); 1078 KateDocumentConfig::global()->setBackupOnSaveRemote(uiadv->chkBackupRemoteFiles->isChecked()); 1079 KateDocumentConfig::global()->setBackupPrefix(uiadv->edtBackupPrefix->text()); 1080 KateDocumentConfig::global()->setBackupSuffix(uiadv->edtBackupSuffix->text()); 1081 1082 KateDocumentConfig::global()->setSwapFileMode(uiadv->cmbSwapFileMode->currentIndex()); 1083 KateDocumentConfig::global()->setSwapDirectory(uiadv->kurlSwapDirectory->url().toLocalFile()); 1084 KateDocumentConfig::global()->setSwapSyncInterval(uiadv->spbSwapFileSync->value()); 1085 1086 KateDocumentConfig::global()->setRemoveSpaces(ui->cbRemoveTrailingSpaces->currentIndex()); 1087 1088 KateDocumentConfig::global()->setNewLineAtEof(ui->chkNewLineAtEof->isChecked()); 1089 1090 // set both standard and fallback encoding 1091 KateDocumentConfig::global()->setEncoding(KCharsets::charsets()->encodingForName(ui->cmbEncoding->currentText())); 1092 1093 KateGlobalConfig::global()->setProberType((KEncodingProber::ProberType)ui->cmbEncodingDetection->currentIndex()); 1094 KateGlobalConfig::global()->setFallbackEncoding(KCharsets::charsets()->encodingForName(ui->cmbEncodingFallback->currentText())); 1095 1096 KateDocumentConfig::global()->setEol(ui->cmbEOL->currentIndex()); 1097 KateDocumentConfig::global()->setAllowEolDetection(ui->chkDetectEOL->isChecked()); 1098 KateDocumentConfig::global()->setBom(ui->chkEnableBOM->isChecked()); 1099 1100 KateDocumentConfig::global()->setLineLengthLimit(ui->lineLengthLimit->value()); 1101 1102 KateDocumentConfig::global()->setValue(KateDocumentConfig::AutoSave, ui->gbAutoSave->isChecked()); 1103 KateDocumentConfig::global()->setValue(KateDocumentConfig::AutoSaveOnFocusOut, ui->cbAutoSaveOnFocus->isChecked()); 1104 KateDocumentConfig::global()->setValue(KateDocumentConfig::AutoSaveInteral, ui->spbAutoSaveInterval->value()); 1105 1106 KateDocumentConfig::global()->setValue(KateDocumentConfig::AutoReloadIfStateIsInVersionControl, uiadv->chkAutoReloadVersionControl->isChecked()); 1107 1108 KateDocumentConfig::global()->configEnd(); 1109 KateGlobalConfig::global()->configEnd(); 1110 } 1111 1112 void KateSaveConfigTab::reload() 1113 { 1114 modeConfigPage->reload(); 1115 1116 // encodings 1117 ui->cmbEncoding->clear(); 1118 ui->cmbEncodingFallback->clear(); 1119 QStringList encodings(KCharsets::charsets()->descriptiveEncodingNames()); 1120 int insert = 0; 1121 for (int i = 0; i < encodings.count(); i++) { 1122 QTextCodec *codecForEnc = QTextCodec::codecForName(KCharsets::charsets()->encodingForName(encodings[i]).toUtf8()); 1123 1124 if (codecForEnc) { 1125 ui->cmbEncoding->addItem(encodings[i]); 1126 ui->cmbEncodingFallback->addItem(encodings[i]); 1127 1128 if (codecForEnc == KateDocumentConfig::global()->codec()) { 1129 ui->cmbEncoding->setCurrentIndex(insert); 1130 } 1131 1132 if (codecForEnc == KateGlobalConfig::global()->fallbackCodec()) { 1133 // adjust index for fallback config, has no default! 1134 ui->cmbEncodingFallback->setCurrentIndex(insert); 1135 } 1136 1137 insert++; 1138 } 1139 } 1140 1141 // encoding detection 1142 ui->cmbEncodingDetection->clear(); 1143 bool found = false; 1144 for (int i = 0; !KEncodingProber::nameForProberType((KEncodingProber::ProberType)i).isEmpty(); ++i) { 1145 ui->cmbEncodingDetection->addItem(KEncodingProber::nameForProberType((KEncodingProber::ProberType)i)); 1146 if (i == KateGlobalConfig::global()->proberType()) { 1147 ui->cmbEncodingDetection->setCurrentIndex(ui->cmbEncodingDetection->count() - 1); 1148 found = true; 1149 } 1150 } 1151 if (!found) { 1152 ui->cmbEncodingDetection->setCurrentIndex(KEncodingProber::Universal); 1153 } 1154 1155 // eol 1156 ui->cmbEOL->setCurrentIndex(KateDocumentConfig::global()->eol()); 1157 ui->chkDetectEOL->setChecked(KateDocumentConfig::global()->allowEolDetection()); 1158 ui->chkEnableBOM->setChecked(KateDocumentConfig::global()->bom()); 1159 ui->lineLengthLimit->setValue(KateDocumentConfig::global()->lineLengthLimit()); 1160 1161 ui->cbRemoveTrailingSpaces->setCurrentIndex(KateDocumentConfig::global()->removeSpaces()); 1162 ui->chkNewLineAtEof->setChecked(KateDocumentConfig::global()->newLineAtEof()); 1163 1164 // other stuff 1165 uiadv->chkBackupLocalFiles->setChecked(KateDocumentConfig::global()->backupOnSaveLocal()); 1166 uiadv->chkBackupRemoteFiles->setChecked(KateDocumentConfig::global()->backupOnSaveRemote()); 1167 uiadv->edtBackupPrefix->setText(KateDocumentConfig::global()->backupPrefix()); 1168 uiadv->edtBackupSuffix->setText(KateDocumentConfig::global()->backupSuffix()); 1169 1170 uiadv->cmbSwapFileMode->setCurrentIndex(KateDocumentConfig::global()->swapFileMode()); 1171 uiadv->kurlSwapDirectory->setUrl(QUrl::fromLocalFile(KateDocumentConfig::global()->swapDirectory())); 1172 uiadv->spbSwapFileSync->setValue(KateDocumentConfig::global()->swapSyncInterval()); 1173 swapFileModeChanged(KateDocumentConfig::global()->swapFileMode()); 1174 1175 ui->gbAutoSave->setChecked(KateDocumentConfig::global()->autoSave()); 1176 ui->cbAutoSaveOnFocus->setChecked(KateDocumentConfig::global()->autoSaveOnFocusOut()); 1177 ui->spbAutoSaveInterval->setValue(KateDocumentConfig::global()->autoSaveInterval()); 1178 1179 uiadv->chkAutoReloadVersionControl->setChecked(KateDocumentConfig::global()->value(KateDocumentConfig::AutoReloadIfStateIsInVersionControl).toBool()); 1180 } 1181 1182 void KateSaveConfigTab::reset() 1183 { 1184 modeConfigPage->reset(); 1185 } 1186 1187 void KateSaveConfigTab::defaults() 1188 { 1189 modeConfigPage->defaults(); 1190 1191 ui->cbRemoveTrailingSpaces->setCurrentIndex(0); 1192 1193 uiadv->chkBackupLocalFiles->setChecked(true); 1194 uiadv->chkBackupRemoteFiles->setChecked(false); 1195 uiadv->edtBackupPrefix->setText(QString()); 1196 uiadv->edtBackupSuffix->setText(QStringLiteral("~")); 1197 1198 uiadv->cmbSwapFileMode->setCurrentIndex(1); 1199 uiadv->kurlSwapDirectory->setDisabled(true); 1200 uiadv->lblSwapDirectory->setDisabled(true); 1201 uiadv->spbSwapFileSync->setValue(15); 1202 } 1203 1204 QString KateSaveConfigTab::name() const 1205 { 1206 return i18n("Open/Save"); 1207 } 1208 1209 QString KateSaveConfigTab::fullName() const 1210 { 1211 return i18n("File Opening & Saving"); 1212 } 1213 1214 QIcon KateSaveConfigTab::icon() const 1215 { 1216 return QIcon::fromTheme(QStringLiteral("document-save")); 1217 } 1218 1219 // END KateSaveConfigTab 1220 1221 // BEGIN KateGotoBar 1222 KateGotoBar::KateGotoBar(KTextEditor::View *view, QWidget *parent) 1223 : KateViewBarWidget(true, parent) 1224 , m_view(view) 1225 { 1226 Q_ASSERT(m_view != nullptr); // this bar widget is pointless w/o a view 1227 1228 QHBoxLayout *topLayout = new QHBoxLayout(centralWidget()); 1229 topLayout->setContentsMargins(0, 0, 0, 0); 1230 1231 QToolButton *btn = new QToolButton(this); 1232 btn->setAutoRaise(true); 1233 btn->setMinimumSize(QSize(1, btn->minimumSizeHint().height())); 1234 btn->setText(i18n("&Line:")); 1235 btn->setToolTip(i18n("Go to line number from clipboard")); 1236 connect(btn, &QToolButton::clicked, this, &KateGotoBar::gotoClipboard); 1237 topLayout->addWidget(btn); 1238 1239 m_gotoRange = new QSpinBox(this); 1240 topLayout->addWidget(m_gotoRange, 1); 1241 topLayout->setStretchFactor(m_gotoRange, 0); 1242 1243 btn = new QToolButton(this); 1244 btn->setAutoRaise(true); 1245 btn->setMinimumSize(QSize(1, btn->minimumSizeHint().height())); 1246 btn->setText(i18n("Go to")); 1247 btn->setIcon(QIcon::fromTheme(QStringLiteral("go-jump"))); 1248 btn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 1249 connect(btn, &QToolButton::clicked, this, &KateGotoBar::gotoLine); 1250 topLayout->addWidget(btn); 1251 1252 btn = m_modifiedUp = new QToolButton(this); 1253 btn->setAutoRaise(true); 1254 btn->setMinimumSize(QSize(1, btn->minimumSizeHint().height())); 1255 btn->setDefaultAction(m_view->action("modified_line_up")); 1256 btn->setIcon(QIcon::fromTheme(QStringLiteral("go-up-search"))); 1257 btn->setText(QString()); 1258 btn->installEventFilter(this); 1259 topLayout->addWidget(btn); 1260 1261 btn = m_modifiedDown = new QToolButton(this); 1262 btn->setAutoRaise(true); 1263 btn->setMinimumSize(QSize(1, btn->minimumSizeHint().height())); 1264 btn->setDefaultAction(m_view->action("modified_line_down")); 1265 btn->setIcon(QIcon::fromTheme(QStringLiteral("go-down-search"))); 1266 btn->setText(QString()); 1267 btn->installEventFilter(this); 1268 topLayout->addWidget(btn); 1269 1270 topLayout->addStretch(); 1271 1272 setFocusProxy(m_gotoRange); 1273 } 1274 1275 void KateGotoBar::showEvent(QShowEvent *event) 1276 { 1277 Q_UNUSED(event) 1278 // Catch rare cases where the bar is visible while document is edited 1279 connect(m_view->document(), &KTextEditor::Document::textChanged, this, &KateGotoBar::updateData); 1280 } 1281 1282 void KateGotoBar::closed() 1283 { 1284 disconnect(m_view->document(), &KTextEditor::Document::textChanged, this, &KateGotoBar::updateData); 1285 } 1286 1287 bool KateGotoBar::eventFilter(QObject *object, QEvent *event) 1288 { 1289 if (object == m_modifiedUp || object == m_modifiedDown) { 1290 if (event->type() != QEvent::Wheel) { 1291 return false; 1292 } 1293 1294 int delta = static_cast<QWheelEvent *>(event)->angleDelta().y(); 1295 // Reset m_wheelDelta when scroll direction change 1296 if (m_wheelDelta != 0 && (m_wheelDelta < 0) != (delta < 0)) { 1297 m_wheelDelta = 0; 1298 } 1299 1300 m_wheelDelta += delta; 1301 1302 if (m_wheelDelta >= 120) { 1303 m_wheelDelta = 0; 1304 m_modifiedUp->click(); 1305 } else if (m_wheelDelta <= -120) { 1306 m_wheelDelta = 0; 1307 m_modifiedDown->click(); 1308 } 1309 } 1310 1311 return false; 1312 } 1313 1314 void KateGotoBar::gotoClipboard() 1315 { 1316 static const QRegularExpression rx(QStringLiteral("-?\\d+")); 1317 bool ok = false; 1318 const int lineNo = rx.match(QApplication::clipboard()->text(QClipboard::Selection)).captured().toInt(&ok); 1319 if (!ok) { 1320 return; 1321 } 1322 if (lineNo >= m_gotoRange->minimum() && lineNo <= m_gotoRange->maximum()) { 1323 m_gotoRange->setValue(lineNo); 1324 gotoLine(); 1325 } else { 1326 QPointer<KTextEditor::Message> message = new KTextEditor::Message(i18n("No valid line number found in clipboard")); 1327 message->setWordWrap(true); 1328 message->setAutoHide(2000); 1329 message->setPosition(KTextEditor::Message::BottomInView); 1330 message->setView(m_view), m_view->document()->postMessage(message); 1331 } 1332 } 1333 1334 void KateGotoBar::updateData() 1335 { 1336 int lines = m_view->document()->lines(); 1337 m_gotoRange->setMinimum(-lines); 1338 m_gotoRange->setMaximum(lines); 1339 if (!isVisible()) { 1340 m_gotoRange->setValue(m_view->cursorPosition().line() + 1); 1341 m_gotoRange->adjustSize(); // ### does not respect the range :-( 1342 } 1343 1344 m_gotoRange->selectAll(); 1345 } 1346 1347 void KateGotoBar::keyPressEvent(QKeyEvent *event) 1348 { 1349 int key = event->key(); 1350 if (key == Qt::Key_Return || key == Qt::Key_Enter) { 1351 gotoLine(); 1352 return; 1353 } 1354 KateViewBarWidget::keyPressEvent(event); 1355 } 1356 1357 void KateGotoBar::gotoLine() 1358 { 1359 KTextEditor::ViewPrivate *kv = qobject_cast<KTextEditor::ViewPrivate *>(m_view); 1360 if (kv && kv->selection() && !kv->config()->persistentSelection()) { 1361 kv->clearSelection(); 1362 } 1363 1364 int gotoValue = m_gotoRange->value(); 1365 if (gotoValue < 0) { 1366 gotoValue += m_view->document()->lines(); 1367 } else if (gotoValue > 0) { 1368 gotoValue -= 1; 1369 } 1370 1371 m_view->setCursorPosition(KTextEditor::Cursor(gotoValue, 0)); 1372 m_view->setFocus(); 1373 Q_EMIT hideMe(); 1374 } 1375 // END KateGotoBar 1376 1377 // BEGIN KateDictionaryBar 1378 KateDictionaryBar::KateDictionaryBar(KTextEditor::ViewPrivate *view, QWidget *parent) 1379 : KateViewBarWidget(true, parent) 1380 , m_view(view) 1381 { 1382 Q_ASSERT(m_view != nullptr); // this bar widget is pointless w/o a view 1383 1384 QHBoxLayout *topLayout = new QHBoxLayout(centralWidget()); 1385 topLayout->setContentsMargins(0, 0, 0, 0); 1386 // topLayout->setSpacing(spacingHint()); 1387 m_dictionaryComboBox = new Sonnet::DictionaryComboBox(centralWidget()); 1388 connect(m_dictionaryComboBox, &Sonnet::DictionaryComboBox::dictionaryChanged, this, &KateDictionaryBar::dictionaryChanged); 1389 connect(view->doc(), &KTextEditor::DocumentPrivate::defaultDictionaryChanged, this, &KateDictionaryBar::updateData); 1390 QLabel *label = new QLabel(i18n("Dictionary:"), centralWidget()); 1391 label->setBuddy(m_dictionaryComboBox); 1392 1393 topLayout->addWidget(label); 1394 topLayout->addWidget(m_dictionaryComboBox, 1); 1395 topLayout->setStretchFactor(m_dictionaryComboBox, 0); 1396 topLayout->addStretch(); 1397 } 1398 1399 KateDictionaryBar::~KateDictionaryBar() 1400 { 1401 } 1402 1403 void KateDictionaryBar::updateData() 1404 { 1405 KTextEditor::DocumentPrivate *document = m_view->doc(); 1406 QString dictionary = document->defaultDictionary(); 1407 if (dictionary.isEmpty()) { 1408 dictionary = Sonnet::Speller().defaultLanguage(); 1409 } 1410 m_dictionaryComboBox->setCurrentByDictionary(dictionary); 1411 } 1412 1413 void KateDictionaryBar::dictionaryChanged(const QString &dictionary) 1414 { 1415 const KTextEditor::Range selection = m_view->selectionRange(); 1416 if (selection.isValid() && !selection.isEmpty()) { 1417 const bool blockmode = m_view->blockSelection(); 1418 m_view->doc()->setDictionary(dictionary, selection, blockmode); 1419 } else { 1420 m_view->doc()->setDefaultDictionary(dictionary); 1421 } 1422 } 1423 1424 // END KateGotoBar 1425 1426 // BEGIN KateModOnHdPrompt 1427 KateModOnHdPrompt::KateModOnHdPrompt(KTextEditor::DocumentPrivate *doc, KTextEditor::ModificationInterface::ModifiedOnDiskReason modtype, const QString &reason) 1428 : QObject(doc) 1429 , m_doc(doc) 1430 , m_modtype(modtype) 1431 , m_fullDiffPath(QStandardPaths::findExecutable(QStringLiteral("diff"))) 1432 , m_proc(nullptr) 1433 , m_diffFile(nullptr) 1434 , m_diffAction(nullptr) 1435 { 1436 m_message = new KTextEditor::Message(reason, KTextEditor::Message::Information); 1437 m_message->setPosition(KTextEditor::Message::AboveView); 1438 m_message->setWordWrap(true); 1439 1440 // If the file isn't deleted, present a diff button 1441 const bool onDiskDeleted = modtype == KTextEditor::ModificationInterface::OnDiskDeleted; 1442 if (!onDiskDeleted) { 1443 QAction *aAutoReload = new QAction(i18n("Enable Auto Reload"), this); 1444 aAutoReload->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); 1445 aAutoReload->setToolTip(i18n("Will never again warn about on disk changes but always reload.")); 1446 m_message->addAction(aAutoReload, false); 1447 connect(aAutoReload, &QAction::triggered, this, &KateModOnHdPrompt::autoReloadTriggered); 1448 1449 if (!m_fullDiffPath.isEmpty()) { 1450 m_diffAction = new QAction(i18n("View &Difference"), this); 1451 m_diffAction->setIcon(QIcon::fromTheme(QStringLiteral("document-multiple"))); 1452 m_diffAction->setToolTip(i18n("Shows a diff of the changes")); 1453 m_message->addAction(m_diffAction, false); 1454 connect(m_diffAction, &QAction::triggered, this, &KateModOnHdPrompt::slotDiff); 1455 } 1456 1457 QAction *aReload = new QAction(i18n("&Reload"), this); 1458 aReload->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); 1459 aReload->setToolTip(i18n("Reload the file from disk. Unsaved changes will be lost.")); 1460 m_message->addAction(aReload); 1461 connect(aReload, &QAction::triggered, this, &KateModOnHdPrompt::reloadTriggered); 1462 } else { 1463 QAction *closeFile = new QAction(i18nc("@action:button closes the opened file", "&Close File"), this); 1464 closeFile->setIcon(QIcon::fromTheme(QStringLiteral("document-close"))); 1465 closeFile->setToolTip(i18n("Close the file, discarding its content.")); 1466 m_message->addAction(closeFile, false); 1467 connect(closeFile, &QAction::triggered, this, &KateModOnHdPrompt::closeTriggered); 1468 1469 QAction *aSaveAs = new QAction(i18n("&Save As..."), this); 1470 aSaveAs->setIcon(QIcon::fromTheme(QStringLiteral("document-save-as"))); 1471 aSaveAs->setToolTip(i18n("Lets you select a location and save the file again.")); 1472 m_message->addAction(aSaveAs, false); 1473 connect(aSaveAs, &QAction::triggered, this, &KateModOnHdPrompt::saveAsTriggered); 1474 } 1475 1476 QAction *aIgnore = new QAction(i18n("&Ignore"), this); 1477 aIgnore->setToolTip(i18n("Ignores the changes on disk without any action.")); 1478 aIgnore->setIcon(QIcon::fromTheme(QStringLiteral("dialog-cancel"))); 1479 m_message->addAction(aIgnore); 1480 connect(aIgnore, &QAction::triggered, this, &KateModOnHdPrompt::ignoreTriggered); 1481 1482 m_doc->postMessage(m_message); 1483 } 1484 1485 KateModOnHdPrompt::~KateModOnHdPrompt() 1486 { 1487 delete m_proc; 1488 m_proc = nullptr; 1489 if (m_diffFile) { 1490 m_diffFile->setAutoRemove(true); 1491 delete m_diffFile; 1492 m_diffFile = nullptr; 1493 } 1494 delete m_message; 1495 } 1496 1497 void KateModOnHdPrompt::slotDiff() 1498 { 1499 if (m_diffFile) { 1500 return; 1501 } 1502 1503 m_diffFile = new QTemporaryFile(QDir::temp().filePath(QLatin1String("XXXXXX.diff"))); 1504 m_diffFile->open(); 1505 1506 // Start a KProcess that creates a diff 1507 m_proc = new KProcess(this); 1508 m_proc->setOutputChannelMode(KProcess::MergedChannels); 1509 *m_proc << m_fullDiffPath << QStringLiteral("-u") << QStringLiteral("-") << m_doc->url().toLocalFile(); 1510 connect(m_proc, &KProcess::readyRead, this, &KateModOnHdPrompt::slotDataAvailable); 1511 connect(m_proc, &KProcess::finished, this, &KateModOnHdPrompt::slotPDone); 1512 1513 // disable the diff button, to hinder the user to run it twice. 1514 m_diffAction->setEnabled(false); 1515 1516 m_proc->start(); 1517 1518 QTextStream ts(m_proc); 1519 int lastln = m_doc->lines() - 1; 1520 for (int l = 0; l < lastln; ++l) { 1521 ts << m_doc->line(l) << '\n'; 1522 } 1523 ts << m_doc->line(lastln); 1524 ts.flush(); 1525 m_proc->closeWriteChannel(); 1526 } 1527 1528 void KateModOnHdPrompt::slotDataAvailable() 1529 { 1530 m_diffFile->write(m_proc->readAll()); 1531 } 1532 1533 void KateModOnHdPrompt::slotPDone() 1534 { 1535 m_diffAction->setEnabled(true); 1536 1537 const QProcess::ExitStatus es = m_proc->exitStatus(); 1538 delete m_proc; 1539 m_proc = nullptr; 1540 1541 if (es != QProcess::NormalExit) { 1542 KMessageBox::error(m_doc->activeView(), 1543 i18n("The diff command failed. Please make sure that " 1544 "diff(1) is installed and in your PATH."), 1545 i18n("Error Creating Diff")); 1546 delete m_diffFile; 1547 m_diffFile = nullptr; 1548 return; 1549 } 1550 1551 if (m_diffFile->size() == 0) { 1552 KMessageBox::information(m_doc->activeView(), i18n("The files are identical."), i18n("Diff Output")); 1553 delete m_diffFile; 1554 m_diffFile = nullptr; 1555 return; 1556 } 1557 1558 m_diffFile->setAutoRemove(false); 1559 QUrl url = QUrl::fromLocalFile(m_diffFile->fileName()); 1560 delete m_diffFile; 1561 m_diffFile = nullptr; 1562 1563 KIO::OpenUrlJob *job = new KIO::OpenUrlJob(url, QStringLiteral("text/x-patch")); 1564 job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, m_doc->activeView())); 1565 job->setDeleteTemporaryFile(true); // delete the file, once the client exits 1566 job->start(); 1567 } 1568 1569 // END KateModOnHdPrompt 1570 1571 #include "moc_katedialogs.cpp"