KTextEditor

katedialogs.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2002, 2003 Anders Lund <anders.lund@lund.tdcadsl.dk>
4 SPDX-FileCopyrightText: 2003 Christoph Cullmann <cullmann@kde.org>
5 SPDX-FileCopyrightText: 2001 Joseph Wenninger <jowenn@kde.org>
6 SPDX-FileCopyrightText: 2006 Dominik Haumann <dhdev@gmx.de>
7 SPDX-FileCopyrightText: 2007 Mirko Stocker <me@misto.ch>
8 SPDX-FileCopyrightText: 2009 Michel Ludwig <michel.ludwig@kdemail.net>
9 SPDX-FileCopyrightText: 2009 Erlend Hamberg <ehamberg@gmail.com>
10
11 Based on work of:
12 SPDX-FileCopyrightText: 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de>
13
14 SPDX-License-Identifier: LGPL-2.0-only
15*/
16
17// BEGIN Includes
18#include "katedialogs.h"
19
20#include <ktexteditor/message.h>
21#include <ktexteditor_version.h>
22
23#include "kateautoindent.h"
24#include "katebuffer.h"
25#include "kateconfig.h"
26#include "katedocument.h"
27#include "kateglobal.h"
28#include "katemodeconfigpage.h"
29#include "kateview.h"
30#include "spellcheck/spellcheck.h"
31
32// auto generated ui files
33#include "ui_bordersappearanceconfigwidget.h"
34#include "ui_completionconfigtab.h"
35#include "ui_editconfigwidget.h"
36#include "ui_indentationconfigwidget.h"
37#include "ui_navigationconfigwidget.h"
38#include "ui_opensaveconfigadvwidget.h"
39#include "ui_opensaveconfigwidget.h"
40#include "ui_spellcheckconfigwidget.h"
41#include "ui_statusbarconfigwidget.h"
42#include "ui_textareaappearanceconfigwidget.h"
43
44#include <KIO/Job>
45#include <KIO/JobUiDelegateFactory>
46#include <KIO/OpenUrlJob>
47
48#include "kateabstractinputmodefactory.h"
49#include "katepartdebug.h"
50#include <KActionCollection>
51#include <KCharsets>
52#include <KColorCombo>
53#include <KEncodingProber>
54#include <KFontRequester>
55#include <KMessageBox>
56#include <KProcess>
57#include <KSeparator>
58
59#include <QCheckBox>
60#include <QClipboard>
61#include <QComboBox>
62#include <QDomDocument>
63#include <QFile>
64#include <QFileDialog>
65#include <QFontDatabase>
66#include <QGroupBox>
67#include <QKeyEvent>
68#include <QLabel>
69#include <QLayout>
70#include <QPainter>
71#include <QRadioButton>
72#include <QSettings>
73#include <QSlider>
74#include <QSpinBox>
75#include <QStringList>
76#include <QTabBar>
77#include <QTemporaryFile>
78#include <QTextStream>
79#include <QToolButton>
80#include <QWhatsThis>
81
82// END
83
84// BEGIN KateIndentConfigTab
85KateIndentConfigTab::KateIndentConfigTab(QWidget *parent)
86 : KateConfigPage(parent)
87{
88 // This will let us have more separation between this page and
89 // the QTabWidget edge (ereslibre)
90 QVBoxLayout *layout = new QVBoxLayout(this);
91 QWidget *newWidget = new QWidget(this);
92
93 ui = new Ui::IndentationConfigWidget();
94 ui->setupUi(newWidget);
95
96 ui->cmbMode->addItems(KateAutoIndent::listModes());
97
98 // FIXME Give ui->label a more descriptive name, it's these "More..." info about tab key action
99 ui->label->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard);
100 connect(ui->label, &QLabel::linkActivated, this, &KateIndentConfigTab::showWhatsThis);
101
102 // "What's This?" help can be found in the ui file
103
104 reload();
105
106 observeChanges(ui->chkAutoDetectIndent);
107 observeChanges(ui->chkBackspaceUnindents);
108 observeChanges(ui->chkIndentPaste);
109 observeChanges(ui->chkKeepExtraSpaces);
110 observeChanges(ui->cmbMode);
111 observeChanges(ui->rbIndentMixed);
112 observeChanges(ui->rbIndentWithSpaces);
113 observeChanges(ui->rbIndentWithTabs);
114 connect(ui->rbIndentWithTabs, &QAbstractButton::toggled, ui->sbIndentWidth, &QWidget::setDisabled);
115 connect(ui->rbIndentWithTabs, &QAbstractButton::toggled, this, &KateIndentConfigTab::slotChanged); // FIXME See slot below
116 observeChanges(ui->rbTabAdvances);
117 observeChanges(ui->rbTabIndents);
118 observeChanges(ui->rbTabSmart);
119 observeChanges(ui->sbIndentWidth);
120 observeChanges(ui->sbTabWidth);
121
122 layout->addWidget(newWidget);
123}
124
125KateIndentConfigTab::~KateIndentConfigTab()
126{
127 delete ui;
128}
129
130void KateIndentConfigTab::slotChanged()
131{
132 // FIXME Make it working without this quirk
133 // When the value is not copied it will silently set back to "Tabs & Spaces"
134 if (ui->rbIndentWithTabs->isChecked()) {
135 ui->sbIndentWidth->setValue(ui->sbTabWidth->value());
136 }
137}
138
139// NOTE Should we have more use of such info stuff, consider to make it part
140// of KateConfigPage and add a similar function like observeChanges(..)
141void KateIndentConfigTab::showWhatsThis(const QString &text)
142{
144}
145
146void KateIndentConfigTab::apply()
147{
148 // nothing changed, no need to apply stuff
149 if (!hasChanged()) {
150 return;
151 }
152 m_changed = false;
153
154 KateDocumentConfig::global()->configStart();
155
156 KateDocumentConfig::global()->setBackspaceIndents(ui->chkBackspaceUnindents->isChecked());
157 KateDocumentConfig::global()->setIndentPastedText(ui->chkIndentPaste->isChecked());
158 KateDocumentConfig::global()->setIndentationMode(KateAutoIndent::modeName(ui->cmbMode->currentIndex()));
159 KateDocumentConfig::global()->setIndentationWidth(ui->sbIndentWidth->value());
160 KateDocumentConfig::global()->setKeepExtraSpaces(ui->chkKeepExtraSpaces->isChecked());
161 KateDocumentConfig::global()->setReplaceTabsDyn(ui->rbIndentWithSpaces->isChecked());
162 KateDocumentConfig::global()->setTabWidth(ui->sbTabWidth->value());
163 KateDocumentConfig::global()->setAutoDetectIndent(ui->chkAutoDetectIndent->isChecked());
164
165 if (ui->rbTabAdvances->isChecked()) {
166 KateDocumentConfig::global()->setTabHandling(KateDocumentConfig::tabInsertsTab);
167 } else if (ui->rbTabIndents->isChecked()) {
168 KateDocumentConfig::global()->setTabHandling(KateDocumentConfig::tabIndents);
169 } else {
170 KateDocumentConfig::global()->setTabHandling(KateDocumentConfig::tabSmart);
171 }
172
173 KateDocumentConfig::global()->configEnd();
174}
175
176void KateIndentConfigTab::reload()
177{
178 ui->chkBackspaceUnindents->setChecked(KateDocumentConfig::global()->backspaceIndents());
179 ui->chkIndentPaste->setChecked(KateDocumentConfig::global()->indentPastedText());
180 ui->chkKeepExtraSpaces->setChecked(KateDocumentConfig::global()->keepExtraSpaces());
181
182 ui->chkAutoDetectIndent->setChecked(KateDocumentConfig::global()->autoDetectIndent());
183 ui->sbIndentWidth->setSuffix(ki18np(" character", " characters"));
184 ui->sbIndentWidth->setValue(KateDocumentConfig::global()->indentationWidth());
185 ui->sbTabWidth->setSuffix(ki18np(" character", " characters"));
186 ui->sbTabWidth->setValue(KateDocumentConfig::global()->tabWidth());
187
188 ui->rbTabAdvances->setChecked(KateDocumentConfig::global()->tabHandling() == KateDocumentConfig::tabInsertsTab);
189 ui->rbTabIndents->setChecked(KateDocumentConfig::global()->tabHandling() == KateDocumentConfig::tabIndents);
190 ui->rbTabSmart->setChecked(KateDocumentConfig::global()->tabHandling() == KateDocumentConfig::tabSmart);
191
192 ui->cmbMode->setCurrentIndex(KateAutoIndent::modeNumber(KateDocumentConfig::global()->indentationMode()));
193
194 if (KateDocumentConfig::global()->replaceTabsDyn()) {
195 ui->rbIndentWithSpaces->setChecked(true);
196 } else {
197 if (KateDocumentConfig::global()->indentationWidth() == KateDocumentConfig::global()->tabWidth()) {
198 ui->rbIndentWithTabs->setChecked(true);
199 } else {
200 ui->rbIndentMixed->setChecked(true);
201 }
202 }
203
204 ui->sbIndentWidth->setEnabled(!ui->rbIndentWithTabs->isChecked());
205}
206
207QString KateIndentConfigTab::name() const
208{
209 return i18n("Indentation");
210}
211
212// END KateIndentConfigTab
213
214// BEGIN KateCompletionConfigTab
215KateCompletionConfigTab::KateCompletionConfigTab(QWidget *parent)
216 : KateConfigPage(parent)
217{
218 // This will let us have more separation between this page and
219 // the QTabWidget edge (ereslibre)
220 QVBoxLayout *layout = new QVBoxLayout(this);
221 QWidget *newWidget = new QWidget(this);
222
223 ui = new Ui::CompletionConfigTab();
224 ui->setupUi(newWidget);
225
226 // "What's This?" help can be found in the ui file
227
228 reload();
229
230 observeChanges(ui->chkAutoCompletionEnabled);
231 observeChanges(ui->chkAutoSelectFirstEntry);
232 observeChanges(ui->chkTabCompletion);
233 observeChanges(ui->chkEnterCompletion);
234 observeChanges(ui->gbKeywordCompletion);
235 observeChanges(ui->gbShowDoc);
236 observeChanges(ui->gbWordCompletion);
237 observeChanges(ui->minimalWordLength);
238 observeChanges(ui->removeTail);
239
240 layout->addWidget(newWidget);
241}
242
243KateCompletionConfigTab::~KateCompletionConfigTab()
244{
245 delete ui;
246}
247
248void KateCompletionConfigTab::showWhatsThis(const QString &text) // NOTE Not used atm, remove? See also KateIndentConfigTab::showWhatsThis
249{
251}
252
253void KateCompletionConfigTab::apply()
254{
255 // nothing changed, no need to apply stuff
256 if (!hasChanged()) {
257 return;
258 }
259 m_changed = false;
260
261 KateViewConfig::global()->configStart();
262
263 KateViewConfig::global()->setValue(KateViewConfig::AutomaticCompletionInvocation, ui->chkAutoCompletionEnabled->isChecked());
264 KateViewConfig::global()->setValue(KateViewConfig::AutomaticCompletionPreselectFirst, ui->chkAutoSelectFirstEntry->isChecked());
265 KateViewConfig::global()->setValue(KateViewConfig::TabCompletion, ui->chkTabCompletion->isChecked());
266 KateViewConfig::global()->setValue(KateViewConfig::EnterToInsertCompletion, ui->chkEnterCompletion->isChecked());
267 KateViewConfig::global()->setValue(KateViewConfig::KeywordCompletion, ui->gbKeywordCompletion->isChecked());
268 KateViewConfig::global()->setValue(KateViewConfig::WordCompletion, ui->gbWordCompletion->isChecked());
269 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionMinimalWordLength, ui->minimalWordLength->value());
270 KateViewConfig::global()->setValue(KateViewConfig::WordCompletionRemoveTail, ui->removeTail->isChecked());
271 KateViewConfig::global()->setValue(KateViewConfig::ShowDocWithCompletion, ui->gbShowDoc->isChecked());
272
273 KateViewConfig::global()->configEnd();
274}
275
276void KateCompletionConfigTab::reload()
277{
278 ui->chkAutoCompletionEnabled->setChecked(KateViewConfig::global()->automaticCompletionInvocation());
279 ui->chkAutoSelectFirstEntry->setChecked(KateViewConfig::global()->automaticCompletionPreselectFirst());
280 ui->chkTabCompletion->setChecked(KateViewConfig::global()->tabCompletion());
281 ui->chkEnterCompletion->setChecked(KateViewConfig::global()->value(KateViewConfig::EnterToInsertCompletion).toBool());
282
283 ui->gbKeywordCompletion->setChecked(KateViewConfig::global()->keywordCompletion());
284 ui->gbWordCompletion->setChecked(KateViewConfig::global()->wordCompletion());
285 ui->gbShowDoc->setChecked(KateViewConfig::global()->showDocWithCompletion());
286
287 ui->minimalWordLength->setValue(KateViewConfig::global()->wordCompletionMinimalWordLength());
288 ui->removeTail->setChecked(KateViewConfig::global()->wordCompletionRemoveTail());
289}
290
291QString KateCompletionConfigTab::name() const
292{
293 return i18n("Auto Completion");
294}
295
296// END KateCompletionConfigTab
297
298// BEGIN KateSpellCheckConfigTab
299KateSpellCheckConfigTab::KateSpellCheckConfigTab(QWidget *parent)
300 : KateConfigPage(parent)
301{
302 // This will let us have more separation between this page and
303 // the QTabWidget edge (ereslibre)
304 QVBoxLayout *layout = new QVBoxLayout(this);
305 QWidget *newWidget = new QWidget(this);
306
307 ui = new Ui::SpellCheckConfigWidget();
308 ui->setupUi(newWidget);
309
310 // "What's This?" help can be found in the ui file
311
312 reload();
313
314 m_sonnetConfigWidget = new Sonnet::ConfigWidget(this);
315 connect(m_sonnetConfigWidget, &Sonnet::ConfigWidget::configChanged, this, &KateSpellCheckConfigTab::slotChanged);
316 layout->addWidget(m_sonnetConfigWidget);
317
318 layout->addWidget(newWidget);
319}
320
321KateSpellCheckConfigTab::~KateSpellCheckConfigTab()
322{
323 delete ui;
324}
325
326void KateSpellCheckConfigTab::showWhatsThis(const QString &text) // NOTE Not used atm, remove? See also KateIndentConfigTab::showWhatsThis
327{
329}
330
331void KateSpellCheckConfigTab::apply()
332{
333 if (!hasChanged()) {
334 // nothing changed, no need to apply stuff
335 return;
336 }
337 m_changed = false;
338
339 // WARNING: this is slightly hackish, but it's currently the only way to
340 // do it, see also the KTextEdit class
341 KateDocumentConfig::global()->configStart();
342 m_sonnetConfigWidget->save();
343 QSettings settings(QStringLiteral("KDE"), QStringLiteral("Sonnet"));
344 KateDocumentConfig::global()->setOnTheFlySpellCheck(settings.value(QStringLiteral("checkerEnabledByDefault"), false).toBool());
345 KateDocumentConfig::global()->configEnd();
346
347 const auto docs = KTextEditor::EditorPrivate::self()->documents();
348 for (KTextEditor::Document *doc : docs) {
349 static_cast<KTextEditor::DocumentPrivate *>(doc)->refreshOnTheFlyCheck();
350 }
351}
352
353void KateSpellCheckConfigTab::reload()
354{
355 // does nothing
356}
357
358QString KateSpellCheckConfigTab::name() const
359{
360 return i18n("Spellcheck");
361}
362
363// END KateSpellCheckConfigTab
364
365// BEGIN KateNavigationConfigTab
366KateNavigationConfigTab::KateNavigationConfigTab(QWidget *parent)
367 : KateConfigPage(parent)
368{
369 // This will let us having more separation between this page and
370 // the QTabWidget edge (ereslibre)
371 QVBoxLayout *layout = new QVBoxLayout(this);
372 QWidget *newWidget = new QWidget(this);
373
374 ui = new Ui::NavigationConfigWidget();
375 ui->setupUi(newWidget);
376
377 initMulticursorModifierComboBox();
378
379 // "What's This?" help can be found in the ui file
380
381 reload();
382
383 observeChanges(ui->cbTextSelectionMode);
384 observeChanges(ui->chkBackspaceRemoveComposed);
385 observeChanges(ui->chkPagingMovesCursor);
386 observeChanges(ui->chkScrollPastEnd);
387 observeChanges(ui->chkSmartHome);
388 observeChanges(ui->sbAutoCenterCursor);
389 observeChanges(ui->chkCamelCursor);
390 observeChanges(ui->cmbMultiCursorModifier);
391
392 layout->addWidget(newWidget);
393}
394
395KateNavigationConfigTab::~KateNavigationConfigTab()
396{
397 delete ui;
398}
399
400void KateNavigationConfigTab::initMulticursorModifierComboBox()
401{
402 // On macOS, the ControlModifier value corresponds to the Command keys on the
403 // keyboard, and the MetaModifier value corresponds to the Control keys.
404 auto *c = ui->cmbMultiCursorModifier;
405
406#ifndef Q_OS_DARWIN
407 c->insertItem(0, i18n("Alt"), (int)Qt::ALT);
408 c->insertItem(1, i18n("Ctrl"), (int)Qt::CTRL);
409 c->insertItem(2, i18n("Meta"), (int)Qt::META);
410 c->insertItem(3, i18n("Ctrl + Alt"), (int)(Qt::CTRL | Qt::ALT));
411 c->insertItem(4, i18n("Meta + Alt"), (int)(Qt::META | Qt::ALT));
412 c->insertItem(5, i18n("Ctrl + Meta"), (int)(Qt::CTRL | Qt::META));
413#else
414 c->insertItem(0, i18n("Alt"), (int)Qt::ALT);
415 c->insertItem(1, i18n("Cmd"), (int)Qt::CTRL);
416 c->insertItem(2, i18n("Ctrl"), (int)Qt::META);
417 c->insertItem(3, i18n("Cmd + Alt"), (int)(Qt::CTRL | Qt::ALT));
418 c->insertItem(4, i18n("Ctrl + Alt"), (int)(Qt::META | Qt::ALT));
419 c->insertItem(5, i18n("Cmd + Ctrl"), (int)(Qt::CTRL | Qt::META));
420#endif
421}
422
423void KateNavigationConfigTab::apply()
424{
425 // nothing changed, no need to apply stuff
426 if (!hasChanged()) {
427 return;
428 }
429 m_changed = false;
430
431 KateViewConfig::global()->configStart();
432 KateDocumentConfig::global()->configStart();
433
434 KateDocumentConfig::global()->setPageUpDownMovesCursor(ui->chkPagingMovesCursor->isChecked());
435 KateDocumentConfig::global()->setSmartHome(ui->chkSmartHome->isChecked());
436 KateDocumentConfig::global()->setCamelCursor(ui->chkCamelCursor->isChecked());
437
438 KateViewConfig::global()->setValue(KateViewConfig::AutoCenterLines, ui->sbAutoCenterCursor->value());
439 KateViewConfig::global()->setValue(KateViewConfig::BackspaceRemoveComposedCharacters, ui->chkBackspaceRemoveComposed->isChecked());
440 KateViewConfig::global()->setValue(KateViewConfig::PersistentSelection, ui->cbTextSelectionMode->currentIndex() == 1);
441 KateViewConfig::global()->setValue(KateViewConfig::ScrollPastEnd, ui->chkScrollPastEnd->isChecked());
442
443 const int modifers = ui->cmbMultiCursorModifier->currentData().toInt();
444 KateViewConfig::global()->setMultiCursorModifiers(Qt::KeyboardModifiers(modifers));
445
446 KateDocumentConfig::global()->configEnd();
447 KateViewConfig::global()->configEnd();
448}
449
450void KateNavigationConfigTab::reload()
451{
452 ui->cbTextSelectionMode->setCurrentIndex(KateViewConfig::global()->persistentSelection() ? 1 : 0);
453
454 ui->chkBackspaceRemoveComposed->setChecked(KateViewConfig::global()->backspaceRemoveComposed());
455 ui->chkPagingMovesCursor->setChecked(KateDocumentConfig::global()->pageUpDownMovesCursor());
456 ui->chkScrollPastEnd->setChecked(KateViewConfig::global()->scrollPastEnd());
457 ui->chkSmartHome->setChecked(KateDocumentConfig::global()->smartHome());
458 ui->chkCamelCursor->setChecked(KateDocumentConfig::global()->camelCursor());
459
460 ui->sbAutoCenterCursor->setValue(KateViewConfig::global()->autoCenterLines());
461
462 const int mods = KateViewConfig::global()->multiCursorModifiers();
463 const auto count = ui->cmbMultiCursorModifier->count();
464 for (int i = 0; i < count; ++i) {
465 int idxMods = ui->cmbMultiCursorModifier->itemData(i).toInt();
466 if (idxMods == mods) {
467 ui->cmbMultiCursorModifier->setCurrentIndex(i);
468 break;
469 }
470 }
471}
472
473QString KateNavigationConfigTab::name() const
474{
475 return i18n("Text Navigation");
476}
477
478// END KateNavigationConfigTab
479
480// BEGIN KateEditGeneralConfigTab
481KateEditGeneralConfigTab::KateEditGeneralConfigTab(QWidget *parent)
482 : KateConfigPage(parent)
483{
484 QVBoxLayout *layout = new QVBoxLayout(this);
485 QWidget *newWidget = new QWidget(this);
486 ui = new Ui::EditConfigWidget();
487 ui->setupUi(newWidget);
488
489 for (const auto &fact : KTextEditor::EditorPrivate::self()->inputModeFactories()) {
490 ui->cmbInputMode->addItem(fact->name(), static_cast<int>(fact->inputMode()));
491 }
492
493 // "What's This?" Help is in the ui-files
494
495 reload();
496
497 observeChanges(ui->chkAutoBrackets);
498 observeChanges(ui->chkMousePasteAtCursorPosition);
499 observeChanges(ui->chkShowStaticWordWrapMarker);
500 observeChanges(ui->chkTextDragAndDrop);
501 observeChanges(ui->chkSmartCopyCut);
502 observeChanges(ui->sbClipboardHistoryEntries);
503 observeChanges(ui->chkStaticWordWrap);
504 observeChanges(ui->cmbEncloseSelection);
506 connect(ui->cmbEncloseSelection->lineEdit(), &QLineEdit::editingFinished, [this] {
507 const int index = ui->cmbEncloseSelection->currentIndex();
508 const QString text = ui->cmbEncloseSelection->currentText();
509 // Text removed? Remove item, but don't remove default data!
510 if (index >= UserData && text.isEmpty()) {
511 ui->cmbEncloseSelection->removeItem(index);
512 slotChanged();
513
514 // Not already there? Add new item! For whatever reason it isn't done automatically
515 } else if (ui->cmbEncloseSelection->findText(text) < 0) {
516 ui->cmbEncloseSelection->addItem(text);
517 slotChanged();
518 }
519 ui->cmbEncloseSelection->setCurrentIndex(ui->cmbEncloseSelection->findText(text));
520 });
521 observeChanges(ui->cmbInputMode);
522 observeChanges(ui->sbWordWrap);
523 observeChanges(ui->chkAccessibility);
524
525 layout->addWidget(newWidget);
526}
527
528KateEditGeneralConfigTab::~KateEditGeneralConfigTab()
529{
530 delete ui;
531}
532
533void KateEditGeneralConfigTab::apply()
534{
535 // nothing changed, no need to apply stuff
536 if (!hasChanged()) {
537 return;
538 }
539 m_changed = false;
540
541 KateViewConfig::global()->configStart();
542 KateDocumentConfig::global()->configStart();
543
544 KateDocumentConfig::global()->setWordWrap(ui->chkStaticWordWrap->isChecked());
545 KateDocumentConfig::global()->setWordWrapAt(ui->sbWordWrap->value());
546
547 KateRendererConfig::global()->setWordWrapMarker(ui->chkShowStaticWordWrapMarker->isChecked());
548
549 KateViewConfig::global()->setValue(KateViewConfig::AutoBrackets, ui->chkAutoBrackets->isChecked());
550 KateViewConfig::global()->setValue(KateViewConfig::CharsToEncloseSelection, ui->cmbEncloseSelection->currentText());
551 QStringList userLetters;
552 for (int i = UserData; i < ui->cmbEncloseSelection->count(); ++i) {
553 userLetters.append(ui->cmbEncloseSelection->itemText(i));
554 }
555 KateViewConfig::global()->setValue(KateViewConfig::UserSetsOfCharsToEncloseSelection, userLetters);
556 KateViewConfig::global()->setValue(KateViewConfig::InputMode, ui->cmbInputMode->currentData().toInt());
557 KateViewConfig::global()->setValue(KateViewConfig::MousePasteAtCursorPosition, ui->chkMousePasteAtCursorPosition->isChecked());
558 KateViewConfig::global()->setValue(KateViewConfig::TextDragAndDrop, ui->chkTextDragAndDrop->isChecked());
559 KateViewConfig::global()->setValue(KateViewConfig::SmartCopyCut, ui->chkSmartCopyCut->isChecked());
560 KateViewConfig::global()->setValue(KateViewConfig::ClipboardHistoryEntries, ui->sbClipboardHistoryEntries->value());
561 KateViewConfig::global()->setValue(KateViewConfig::EnableAccessibility, ui->chkAccessibility->isChecked());
562
563 KateDocumentConfig::global()->configEnd();
564 KateViewConfig::global()->configEnd();
565}
566
567void KateEditGeneralConfigTab::reload()
568{
569 ui->chkAutoBrackets->setChecked(KateViewConfig::global()->autoBrackets());
570 ui->chkMousePasteAtCursorPosition->setChecked(KateViewConfig::global()->mousePasteAtCursorPosition());
571 ui->chkShowStaticWordWrapMarker->setChecked(KateRendererConfig::global()->wordWrapMarker());
572 ui->chkTextDragAndDrop->setChecked(KateViewConfig::global()->textDragAndDrop());
573 ui->chkSmartCopyCut->setChecked(KateViewConfig::global()->smartCopyCut());
574 ui->chkStaticWordWrap->setChecked(KateDocumentConfig::global()->wordWrap());
575 ui->sbClipboardHistoryEntries->setValue(KateViewConfig::global()->clipboardHistoryEntries());
576
577 ui->sbWordWrap->setSuffix(ki18ncp("Wrap words at (value is at 20 or larger)", " character", " characters"));
578 ui->sbWordWrap->setValue(KateDocumentConfig::global()->wordWrapAt());
579
580 ui->cmbEncloseSelection->clear();
581 ui->cmbEncloseSelection->lineEdit()->setClearButtonEnabled(true);
582 ui->cmbEncloseSelection->lineEdit()->setPlaceholderText(i18n("Feature is not active"));
583 ui->cmbEncloseSelection->addItem(QString(), None);
584 ui->cmbEncloseSelection->setItemData(0, i18n("Disable Feature"), Qt::ToolTipRole);
585 ui->cmbEncloseSelection->addItem(QStringLiteral("`*_~"), MarkDown);
586 ui->cmbEncloseSelection->setItemData(1, i18n("May be handy with Markdown"), Qt::ToolTipRole);
587 ui->cmbEncloseSelection->addItem(QStringLiteral("<>(){}[]'\""), MirrorChar);
588 ui->cmbEncloseSelection->setItemData(2, i18n("Mirror characters, similar but not exactly like auto brackets"), Qt::ToolTipRole);
589 ui->cmbEncloseSelection->addItem(QStringLiteral("´`_.:|#@~*!?$%/=,;-+^°§&"), NonLetters);
590 ui->cmbEncloseSelection->setItemData(3, i18n("Non letter character"), Qt::ToolTipRole);
591 const QStringList userLetters = KateViewConfig::global()->value(KateViewConfig::UserSetsOfCharsToEncloseSelection).toStringList();
592 for (int i = 0; i < userLetters.size(); ++i) {
593 ui->cmbEncloseSelection->addItem(userLetters.at(i), UserData + i);
594 }
595 ui->cmbEncloseSelection->setCurrentIndex(ui->cmbEncloseSelection->findText(KateViewConfig::global()->charsToEncloseSelection()));
596
597 const int id = static_cast<int>(KateViewConfig::global()->inputMode());
598 ui->cmbInputMode->setCurrentIndex(ui->cmbInputMode->findData(id));
599 ui->chkAccessibility->setChecked(KateViewConfig::global()->value(KateViewConfig::EnableAccessibility).toBool());
600}
601
602QString KateEditGeneralConfigTab::name() const
603{
604 return i18n("General");
605}
606
607// END KateEditGeneralConfigTab
608
609// BEGIN KateEditConfigTab
610KateEditConfigTab::KateEditConfigTab(QWidget *parent)
611 : KateConfigPage(parent)
612 , editConfigTab(new KateEditGeneralConfigTab(this))
613 , navigationConfigTab(new KateNavigationConfigTab(this))
614 , indentConfigTab(new KateIndentConfigTab(this))
615 , completionConfigTab(new KateCompletionConfigTab(this))
616 , spellCheckConfigTab(new KateSpellCheckConfigTab(this))
617{
618 QVBoxLayout *layout = new QVBoxLayout(this);
619 layout->setContentsMargins(0, 0, 0, 0);
620 QTabWidget *tabWidget = new QTabWidget(this);
621 tabWidget->setDocumentMode(true);
622
623 // add all tabs
624 tabWidget->insertTab(0, editConfigTab, editConfigTab->name());
625 tabWidget->insertTab(1, navigationConfigTab, navigationConfigTab->name());
626 tabWidget->insertTab(2, indentConfigTab, indentConfigTab->name());
627 tabWidget->insertTab(3, completionConfigTab, completionConfigTab->name());
628 tabWidget->insertTab(4, spellCheckConfigTab, spellCheckConfigTab->name());
629
630 observeChanges(editConfigTab);
631 observeChanges(navigationConfigTab);
632 observeChanges(indentConfigTab);
633 observeChanges(completionConfigTab);
634 observeChanges(spellCheckConfigTab);
635
636 int i = tabWidget->count();
637 for (const auto &factory : KTextEditor::EditorPrivate::self()->inputModeFactories()) {
638 KateConfigPage *tab = factory->createConfigPage(this);
639 if (tab) {
640 m_inputModeConfigTabs.push_back(tab);
641 tabWidget->insertTab(i, tab, tab->name());
642 observeChanges(tab);
643 i++;
644 }
645 }
646
647 layout->addWidget(tabWidget);
648}
649
650KateEditConfigTab::~KateEditConfigTab()
651{
652 qDeleteAll(m_inputModeConfigTabs);
653}
654
655void KateEditConfigTab::apply()
656{
657 // try to update the rest of tabs
658 editConfigTab->apply();
659 navigationConfigTab->apply();
660 indentConfigTab->apply();
661 completionConfigTab->apply();
662 spellCheckConfigTab->apply();
663 for (KateConfigPage *tab : m_inputModeConfigTabs) {
664 tab->apply();
665 }
666}
667
668void KateEditConfigTab::reload()
669{
670 editConfigTab->reload();
671 navigationConfigTab->reload();
672 indentConfigTab->reload();
673 completionConfigTab->reload();
674 spellCheckConfigTab->reload();
675 for (KateConfigPage *tab : m_inputModeConfigTabs) {
676 tab->reload();
677 }
678}
679
680void KateEditConfigTab::reset()
681{
682 editConfigTab->reset();
683 navigationConfigTab->reset();
684 indentConfigTab->reset();
685 completionConfigTab->reset();
686 spellCheckConfigTab->reset();
687 for (KateConfigPage *tab : m_inputModeConfigTabs) {
688 tab->reset();
689 }
690}
691
692void KateEditConfigTab::defaults()
693{
694 editConfigTab->defaults();
695 navigationConfigTab->defaults();
696 indentConfigTab->defaults();
697 completionConfigTab->defaults();
698 spellCheckConfigTab->defaults();
699 for (KateConfigPage *tab : m_inputModeConfigTabs) {
700 tab->defaults();
701 }
702}
703
704QString KateEditConfigTab::name() const
705{
706 return i18n("Editing");
707}
708
709QString KateEditConfigTab::fullName() const
710{
711 return i18n("Editing Options");
712}
713
714QIcon KateEditConfigTab::icon() const
715{
716 return QIcon::fromTheme(QStringLiteral("accessories-text-editor"));
717}
718
719// END KateEditConfigTab
720
721// BEGIN KateViewDefaultsConfig
722KateViewDefaultsConfig::KateViewDefaultsConfig(QWidget *parent)
723 : KateConfigPage(parent)
724 , textareaUi(new Ui::TextareaAppearanceConfigWidget())
725 , bordersUi(new Ui::BordersAppearanceConfigWidget())
726 , statusBarUi(new Ui::StatusbarConfigWidget())
727{
728 QLayout *layout = new QVBoxLayout(this);
729 QTabWidget *tabWidget = new QTabWidget(this);
730 tabWidget->setDocumentMode(true);
731 layout->addWidget(tabWidget);
732 layout->setContentsMargins(0, 0, 0, 0);
733
734 QWidget *textareaTab = new QWidget(tabWidget);
735 textareaUi->setupUi(textareaTab);
736 tabWidget->addTab(textareaTab, i18n("General"));
737
738 QWidget *bordersTab = new QWidget(tabWidget);
739 bordersUi->setupUi(bordersTab);
740 tabWidget->addTab(bordersTab, i18n("Borders"));
741
742 QWidget *statusbarTab = new QWidget(tabWidget);
743 statusBarUi->setupUi(statusbarTab);
744 tabWidget->addTab(statusbarTab, i18n("Statusbar"));
745
746 textareaUi->cmbDynamicWordWrapIndicator->addItem(i18n("Off"));
747 textareaUi->cmbDynamicWordWrapIndicator->addItem(i18n("Follow Line Numbers"));
748 textareaUi->cmbDynamicWordWrapIndicator->addItem(i18n("Always On"));
749
750 // "What's This?" help is in the ui-file
751
752 reload();
753
754 observeChanges(textareaUi->kfontrequester);
755
756 observeChanges(textareaUi->chkAnimateBracketMatching);
757 observeChanges(textareaUi->chkDynWrapAnywhere);
758 observeChanges(textareaUi->chkDynWrapAtStaticMarker);
759 observeChanges(textareaUi->chkFoldFirstLine);
760 observeChanges(textareaUi->chkShowBracketMatchPreview);
761 observeChanges(textareaUi->chkShowIndentationLines);
762 observeChanges(textareaUi->chkShowLineCount);
763 observeChanges(textareaUi->chkShowTabs);
764 observeChanges(textareaUi->chkShowWholeBracketExpression);
765 observeChanges(textareaUi->chkShowWordCount);
766 observeChanges(textareaUi->cmbDynamicWordWrapIndicator);
767 observeChanges(textareaUi->cbxWordWrap);
768 observeChanges(textareaUi->chkFocusFrame);
769 observeChanges(textareaUi->spbLineHeightMultiplier);
770 auto a = [ui = textareaUi, cbx = textareaUi->cbxWordWrap]() {
771 ui->chkDynWrapAtStaticMarker->setEnabled(cbx->isChecked());
772 ui->chkDynWrapAnywhere->setEnabled(cbx->isChecked());
773 ui->cmbDynamicWordWrapIndicator->setEnabled(cbx->isChecked());
774 ui->sbDynamicWordWrapDepth->setEnabled(cbx->isChecked());
775 };
776 connect(textareaUi->cbxWordWrap, &QCheckBox::stateChanged, this, a);
777 a();
778 auto b = [cbx = textareaUi->cbxIndentWrappedLines, sb = textareaUi->sbDynamicWordWrapDepth]() {
779 sb->setEnabled(cbx->isChecked());
780 };
781 b();
782 connect(textareaUi->cbxIndentWrappedLines, &QCheckBox::stateChanged, this, b);
783 observeChanges(textareaUi->cbxIndentWrappedLines);
784 observeChanges(textareaUi->sbDynamicWordWrapDepth);
785 observeChanges(textareaUi->sliSetMarkerSize);
786 observeChanges(textareaUi->spacesComboBox);
787
788 observeChanges(bordersUi->chkIconBorder);
789 observeChanges(bordersUi->chkLineNumbers);
790 observeChanges(bordersUi->chkScrollbarMarks);
791 observeChanges(bordersUi->chkScrollbarMiniMap);
792 observeChanges(bordersUi->chkScrollbarMiniMapAll);
793 bordersUi->chkScrollbarMiniMapAll->hide(); // this is temporary until the feature is done
794 observeChanges(bordersUi->chkScrollbarPreview);
795 observeChanges(bordersUi->chkShowFoldingMarkers);
796 observeChanges(bordersUi->chkShowFoldingPreview);
797 observeChanges(bordersUi->chkShowLineModification);
798 observeChanges(bordersUi->cmbShowScrollbars);
799 observeChanges(bordersUi->rbSortBookmarksByCreation);
800 observeChanges(bordersUi->rbSortBookmarksByPosition);
801 observeChanges(bordersUi->spBoxMiniMapWidth);
802 observeChanges(bordersUi->cmbFoldingArrowVisiblity);
803
804 // statusBarUi
805 observeChanges(statusBarUi->cbShowActiveDictionary);
806 observeChanges(statusBarUi->cbShowHighlightingMode);
807 observeChanges(statusBarUi->cbShowInputMode);
808 observeChanges(statusBarUi->cbShowLineColumn);
809 observeChanges(statusBarUi->cbShowTabSetting);
810 observeChanges(statusBarUi->cbShowEncoding);
811 observeChanges(statusBarUi->cbShowEOL);
812}
813
814KateViewDefaultsConfig::~KateViewDefaultsConfig()
815{
816 delete bordersUi;
817 delete textareaUi;
818 delete statusBarUi;
819}
820
821void KateViewDefaultsConfig::apply()
822{
823 // nothing changed, no need to apply stuff
824 if (!hasChanged()) {
825 return;
826 }
827 m_changed = false;
828
829 KateViewConfig::global()->configStart();
830 KateRendererConfig::global()->configStart();
831
832 KateDocumentConfig::global()->setMarkerSize(textareaUi->sliSetMarkerSize->value());
833 KateDocumentConfig::global()->setShowSpaces(KateDocumentConfig::WhitespaceRendering(textareaUi->spacesComboBox->currentIndex()));
834 KateDocumentConfig::global()->setShowTabs(textareaUi->chkShowTabs->isChecked());
835
836 KateRendererConfig::global()->setFont(textareaUi->kfontrequester->font());
837 KateRendererConfig::global()->setAnimateBracketMatching(textareaUi->chkAnimateBracketMatching->isChecked());
838 KateRendererConfig::global()->setShowIndentationLines(textareaUi->chkShowIndentationLines->isChecked());
839 KateRendererConfig::global()->setShowWholeBracketExpression(textareaUi->chkShowWholeBracketExpression->isChecked());
840 KateRendererConfig::global()->setLineHeightMultiplier(textareaUi->spbLineHeightMultiplier->value());
841
842 KateViewConfig::global()->setDynWordWrap(textareaUi->cbxWordWrap->isChecked());
843 KateViewConfig::global()->setShowWordCount(textareaUi->chkShowWordCount->isChecked());
844 KateViewConfig::global()->setValue(KateViewConfig::BookmarkSorting, bordersUi->rbSortBookmarksByPosition->isChecked() ? 0 : 1);
845 if (!textareaUi->cbxIndentWrappedLines->isChecked()) {
846 KateViewConfig::global()->setValue(KateViewConfig::DynWordWrapAlignIndent, 0);
847 } else {
848 KateViewConfig::global()->setValue(KateViewConfig::DynWordWrapAlignIndent, textareaUi->sbDynamicWordWrapDepth->value());
849 }
850 KateViewConfig::global()->setValue(KateViewConfig::DynWordWrapIndicators, textareaUi->cmbDynamicWordWrapIndicator->currentIndex());
851 KateViewConfig::global()->setValue(KateViewConfig::DynWrapAnywhere, textareaUi->chkDynWrapAnywhere->isChecked());
852 KateViewConfig::global()->setValue(KateViewConfig::DynWrapAtStaticMarker, textareaUi->chkDynWrapAtStaticMarker->isChecked());
853 KateViewConfig::global()->setValue(KateViewConfig::FoldFirstLine, textareaUi->chkFoldFirstLine->isChecked());
854 KateViewConfig::global()->setValue(KateViewConfig::ScrollBarMiniMapWidth, bordersUi->spBoxMiniMapWidth->value());
855 KateViewConfig::global()->setValue(KateViewConfig::ShowBracketMatchPreview, textareaUi->chkShowBracketMatchPreview->isChecked());
856 KateViewConfig::global()->setValue(KateViewConfig::ShowFocusFrame, textareaUi->chkFocusFrame->isChecked());
857 KateViewConfig::global()->setValue(KateViewConfig::ShowFoldingBar, bordersUi->chkShowFoldingMarkers->isChecked());
858 KateViewConfig::global()->setValue(KateViewConfig::ShowFoldingPreview, bordersUi->chkShowFoldingPreview->isChecked());
859 KateViewConfig::global()->setValue(KateViewConfig::ShowIconBar, bordersUi->chkIconBorder->isChecked());
860 KateViewConfig::global()->setValue(KateViewConfig::ShowLineCount, textareaUi->chkShowLineCount->isChecked());
861 KateViewConfig::global()->setValue(KateViewConfig::ShowLineModification, bordersUi->chkShowLineModification->isChecked());
862 KateViewConfig::global()->setValue(KateViewConfig::ShowLineNumbers, bordersUi->chkLineNumbers->isChecked());
863 KateViewConfig::global()->setValue(KateViewConfig::ShowScrollBarMarks, bordersUi->chkScrollbarMarks->isChecked());
864 KateViewConfig::global()->setValue(KateViewConfig::ShowScrollBarMiniMap, bordersUi->chkScrollbarMiniMap->isChecked());
865 KateViewConfig::global()->setValue(KateViewConfig::ShowScrollBarMiniMapAll, bordersUi->chkScrollbarMiniMapAll->isChecked());
866 KateViewConfig::global()->setValue(KateViewConfig::ShowScrollBarPreview, bordersUi->chkScrollbarPreview->isChecked());
867 KateViewConfig::global()->setValue(KateViewConfig::ShowScrollbars, bordersUi->cmbShowScrollbars->currentIndex());
868 bool showOnHoverOnly = bordersUi->cmbFoldingArrowVisiblity->currentIndex() == 0;
869 KateViewConfig::global()->setValue(KateViewConfig::ShowFoldingOnHoverOnly, showOnHoverOnly);
870
871 // Statusbar stuff
872 KateViewConfig::global()->setValue(KateViewConfig::ShowStatusbarDictionary, statusBarUi->cbShowActiveDictionary->isChecked());
873 KateViewConfig::global()->setValue(KateViewConfig::ShowStatusbarHighlightingMode, statusBarUi->cbShowHighlightingMode->isChecked());
874 KateViewConfig::global()->setValue(KateViewConfig::ShowStatusbarInputMode, statusBarUi->cbShowInputMode->isChecked());
875 KateViewConfig::global()->setValue(KateViewConfig::ShowStatusbarLineColumn, statusBarUi->cbShowLineColumn->isChecked());
876 KateViewConfig::global()->setValue(KateViewConfig::ShowStatusbarTabSettings, statusBarUi->cbShowTabSetting->isChecked());
877 KateViewConfig::global()->setValue(KateViewConfig::ShowStatusbarFileEncoding, statusBarUi->cbShowEncoding->isChecked());
878 KateViewConfig::global()->setValue(KateViewConfig::ShowStatusbarEOL, statusBarUi->cbShowEOL->isChecked());
879
880 KateRendererConfig::global()->configEnd();
881 KateViewConfig::global()->configEnd();
882}
883
884void KateViewDefaultsConfig::reload()
885{
886 bordersUi->chkIconBorder->setChecked(KateViewConfig::global()->iconBar());
887 bordersUi->chkLineNumbers->setChecked(KateViewConfig::global()->lineNumbers());
888 bordersUi->chkScrollbarMarks->setChecked(KateViewConfig::global()->scrollBarMarks());
889 bordersUi->chkScrollbarMiniMap->setChecked(KateViewConfig::global()->scrollBarMiniMap());
890 bordersUi->chkScrollbarMiniMapAll->setChecked(KateViewConfig::global()->scrollBarMiniMapAll());
891 bordersUi->chkScrollbarPreview->setChecked(KateViewConfig::global()->scrollBarPreview());
892 bordersUi->chkShowFoldingMarkers->setChecked(KateViewConfig::global()->foldingBar());
893 bordersUi->chkShowFoldingPreview->setChecked(KateViewConfig::global()->foldingPreview());
894 bordersUi->chkShowLineModification->setChecked(KateViewConfig::global()->lineModification());
895 bordersUi->cmbShowScrollbars->setCurrentIndex(KateViewConfig::global()->showScrollbars());
896 bordersUi->rbSortBookmarksByCreation->setChecked(KateViewConfig::global()->bookmarkSort() == 1);
897 bordersUi->rbSortBookmarksByPosition->setChecked(KateViewConfig::global()->bookmarkSort() == 0);
898 bordersUi->spBoxMiniMapWidth->setValue(KateViewConfig::global()->scrollBarMiniMapWidth());
899 bordersUi->cmbFoldingArrowVisiblity->setCurrentIndex(KateViewConfig::global()->showFoldingOnHoverOnly() ? 0 : 1);
900
901 textareaUi->kfontrequester->setFont(KateRendererConfig::global()->baseFont());
902
903 textareaUi->chkAnimateBracketMatching->setChecked(KateRendererConfig::global()->animateBracketMatching());
904 textareaUi->chkDynWrapAnywhere->setChecked(KateViewConfig::global()->dynWrapAnywhere());
905 textareaUi->chkDynWrapAtStaticMarker->setChecked(KateViewConfig::global()->dynWrapAtStaticMarker());
906 textareaUi->chkFoldFirstLine->setChecked(KateViewConfig::global()->foldFirstLine());
907 textareaUi->chkShowBracketMatchPreview->setChecked(KateViewConfig::global()->value(KateViewConfig::ShowBracketMatchPreview).toBool());
908 textareaUi->chkShowIndentationLines->setChecked(KateRendererConfig::global()->showIndentationLines());
909 textareaUi->chkShowLineCount->setChecked(KateViewConfig::global()->showLineCount());
910 textareaUi->chkShowTabs->setChecked(KateDocumentConfig::global()->showTabs());
911 textareaUi->chkShowWholeBracketExpression->setChecked(KateRendererConfig::global()->showWholeBracketExpression());
912 textareaUi->chkShowWordCount->setChecked(KateViewConfig::global()->showWordCount());
913 textareaUi->cmbDynamicWordWrapIndicator->setCurrentIndex(KateViewConfig::global()->dynWordWrapIndicators());
914 textareaUi->cbxWordWrap->setChecked(KateViewConfig::global()->dynWordWrap());
915 textareaUi->cbxIndentWrappedLines->setChecked(KateViewConfig::global()->dynWordWrapAlignIndent() != 0);
916 textareaUi->sbDynamicWordWrapDepth->setValue(KateViewConfig::global()->dynWordWrapAlignIndent());
917 textareaUi->sliSetMarkerSize->setValue(KateDocumentConfig::global()->markerSize());
918 textareaUi->spacesComboBox->setCurrentIndex(KateDocumentConfig::global()->showSpaces());
919 textareaUi->chkFocusFrame->setChecked(KateViewConfig::global()->showFocusFrame());
920 textareaUi->spbLineHeightMultiplier->setValue(KateRendererConfig::global()->lineHeightMultiplier());
921
922 statusBarUi->cbShowLineColumn->setChecked(KateViewConfig::global()->value(KateViewConfig::ShowStatusbarLineColumn).toBool());
923 statusBarUi->cbShowActiveDictionary->setChecked(KateViewConfig::global()->value(KateViewConfig::ShowStatusbarDictionary).toBool());
924 statusBarUi->cbShowTabSetting->setChecked(KateViewConfig::global()->value(KateViewConfig::ShowStatusbarTabSettings).toBool());
925 statusBarUi->cbShowHighlightingMode->setChecked(KateViewConfig::global()->value(KateViewConfig::ShowStatusbarHighlightingMode).toBool());
926 statusBarUi->cbShowInputMode->setChecked(KateViewConfig::global()->value(KateViewConfig::ShowStatusbarInputMode).toBool());
927 statusBarUi->cbShowEncoding->setChecked(KateViewConfig::global()->value(KateViewConfig::ShowStatusbarFileEncoding).toBool());
928 statusBarUi->cbShowEOL->setChecked(KateViewConfig::global()->value(KateViewConfig::ShowStatusbarEOL).toBool());
929}
930
931void KateViewDefaultsConfig::reset()
932{
933}
934
935void KateViewDefaultsConfig::defaults()
936{
937}
938
939QString KateViewDefaultsConfig::name() const
940{
941 return i18n("Appearance");
942}
943
944QString KateViewDefaultsConfig::fullName() const
945{
946 return i18n("Appearance");
947}
948
949QIcon KateViewDefaultsConfig::icon() const
950{
951 return QIcon::fromTheme(QStringLiteral("preferences-desktop-theme"));
952}
953
954// END KateViewDefaultsConfig
955
956// BEGIN KateSaveConfigTab
957KateSaveConfigTab::KateSaveConfigTab(QWidget *parent)
958 : KateConfigPage(parent)
959 , modeConfigPage(new ModeConfigPage(this))
960{
961 // FIXME: Is really needed to move all this code below to another class,
962 // since it is another tab itself on the config dialog. This means we should
963 // initialize, add and work with as we do with modeConfigPage (ereslibre)
964 QVBoxLayout *layout = new QVBoxLayout(this);
965 layout->setContentsMargins(0, 0, 0, 0);
966 QTabWidget *tabWidget = new QTabWidget(this);
967 tabWidget->setDocumentMode(true);
968
969 QWidget *tmpWidget = new QWidget(tabWidget);
970 QVBoxLayout *internalLayout = new QVBoxLayout(tmpWidget);
971 QWidget *newWidget = new QWidget(tabWidget);
972 ui = new Ui::OpenSaveConfigWidget();
973 ui->setupUi(newWidget);
974
975 QWidget *tmpWidget2 = new QWidget(tabWidget);
976 QVBoxLayout *internalLayout2 = new QVBoxLayout(tmpWidget2);
977 QWidget *newWidget2 = new QWidget(tabWidget);
978 uiadv = new Ui::OpenSaveConfigAdvWidget();
979 uiadv->setupUi(newWidget2);
980 uiadv->lblExplanatory->setText(
981 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 "
982 "cause data loss in case of a system crash.",
984 uiadv->lblExplanatory->setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
985
986 // "What's This?" help can be found in the ui file
987
988 reload();
989
990 observeChanges(ui->cbRemoveTrailingSpaces);
991 observeChanges(ui->chkDetectEOL);
992 observeChanges(ui->chkEnableBOM);
993 observeChanges(ui->chkNewLineAtEof);
994 observeChanges(ui->cmbEOL);
995 observeChanges(ui->cmbEncoding);
996 observeChanges(ui->cmbEncodingDetection);
997 observeChanges(ui->cmbEncodingFallback);
998 observeChanges(ui->lineLengthLimit);
999 observeChanges(ui->gbAutoSave);
1000 observeChanges(ui->cbAutoSaveOnFocus);
1001 observeChanges(ui->spbAutoSaveInterval);
1002
1003 observeChanges(uiadv->chkAutoReloadVersionControl);
1004
1005 observeChanges(uiadv->chkBackupLocalFiles);
1006 observeChanges(uiadv->chkBackupRemoteFiles);
1007 observeChanges(uiadv->cmbSwapFileMode);
1008 connect(uiadv->cmbSwapFileMode, &QComboBox::currentIndexChanged, this, &KateSaveConfigTab::swapFileModeChanged);
1009
1010 observeChanges(uiadv->edtBackupPrefix);
1011 observeChanges(uiadv->edtBackupSuffix);
1012 observeChanges(uiadv->kurlSwapDirectory);
1013 observeChanges(uiadv->spbSwapFileSync);
1014
1015 internalLayout->addWidget(newWidget);
1016 internalLayout2->addWidget(newWidget2);
1017
1018 // add all tabs
1019 tabWidget->insertTab(0, tmpWidget, i18n("General"));
1020 tabWidget->insertTab(1, tmpWidget2, i18n("Advanced"));
1021 tabWidget->insertTab(2, modeConfigPage, modeConfigPage->name());
1022
1023 observeChanges(modeConfigPage);
1024
1025 layout->addWidget(tabWidget);
1026
1027 // support variable expansion in backup prefix/suffix
1028 KTextEditor::Editor::instance()->addVariableExpansion({uiadv->edtBackupPrefix, uiadv->edtBackupSuffix},
1029 {QStringLiteral("Date:Locale"),
1030 QStringLiteral("Date:ISO"),
1031 QStringLiteral("Date:"),
1032 QStringLiteral("Time:Locale"),
1033 QStringLiteral("Time:ISO"),
1034 QStringLiteral("Time:"),
1035 QStringLiteral("ENV:"),
1036 QStringLiteral("JS:"),
1037 QStringLiteral("UUID")});
1038}
1039
1040KateSaveConfigTab::~KateSaveConfigTab()
1041{
1042 delete uiadv;
1043 delete ui;
1044}
1045
1046void KateSaveConfigTab::swapFileModeChanged(int idx)
1047{
1048 const KateDocumentConfig::SwapFileMode mode = static_cast<KateDocumentConfig::SwapFileMode>(idx);
1049 switch (mode) {
1050 case KateDocumentConfig::DisableSwapFile:
1051 uiadv->lblSwapDirectory->setEnabled(false);
1052 uiadv->kurlSwapDirectory->setEnabled(false);
1053 uiadv->lblSwapFileSync->setEnabled(false);
1054 uiadv->spbSwapFileSync->setEnabled(false);
1055 break;
1056 case KateDocumentConfig::EnableSwapFile:
1057 uiadv->lblSwapDirectory->setEnabled(false);
1058 uiadv->kurlSwapDirectory->setEnabled(false);
1059 uiadv->lblSwapFileSync->setEnabled(true);
1060 uiadv->spbSwapFileSync->setEnabled(true);
1061 break;
1062 case KateDocumentConfig::SwapFilePresetDirectory:
1063 uiadv->lblSwapDirectory->setEnabled(true);
1064 uiadv->kurlSwapDirectory->setEnabled(true);
1065 uiadv->lblSwapFileSync->setEnabled(true);
1066 uiadv->spbSwapFileSync->setEnabled(true);
1067 break;
1068 }
1069}
1070
1071void KateSaveConfigTab::apply()
1072{
1073 modeConfigPage->apply();
1074
1075 // nothing changed, no need to apply stuff
1076 if (!hasChanged()) {
1077 return;
1078 }
1079 m_changed = false;
1080
1081 KateGlobalConfig::global()->configStart();
1082 KateDocumentConfig::global()->configStart();
1083
1084 if (uiadv->edtBackupSuffix->text().isEmpty() && uiadv->edtBackupPrefix->text().isEmpty()) {
1085 KMessageBox::information(this, i18n("You did not provide a backup suffix or prefix. Using default suffix: '~'"), i18n("No Backup Suffix or Prefix"));
1086 uiadv->edtBackupSuffix->setText(QStringLiteral("~"));
1087 }
1088
1089 KateDocumentConfig::global()->setBackupOnSaveLocal(uiadv->chkBackupLocalFiles->isChecked());
1090 KateDocumentConfig::global()->setBackupOnSaveRemote(uiadv->chkBackupRemoteFiles->isChecked());
1091 KateDocumentConfig::global()->setBackupPrefix(uiadv->edtBackupPrefix->text());
1092 KateDocumentConfig::global()->setBackupSuffix(uiadv->edtBackupSuffix->text());
1093
1094 KateDocumentConfig::global()->setSwapFileMode(uiadv->cmbSwapFileMode->currentIndex());
1095 KateDocumentConfig::global()->setSwapDirectory(uiadv->kurlSwapDirectory->url().toLocalFile());
1096 KateDocumentConfig::global()->setSwapSyncInterval(uiadv->spbSwapFileSync->value());
1097
1098 KateDocumentConfig::global()->setRemoveSpaces(ui->cbRemoveTrailingSpaces->currentIndex());
1099
1100 KateDocumentConfig::global()->setNewLineAtEof(ui->chkNewLineAtEof->isChecked());
1101
1102 // set both standard and fallback encoding
1103 KateDocumentConfig::global()->setEncoding(KCharsets::charsets()->encodingForName(ui->cmbEncoding->currentText()));
1104
1105 KateGlobalConfig::global()->setValue(KateGlobalConfig::EncodingProberType, (KEncodingProber::ProberType)ui->cmbEncodingDetection->currentIndex());
1106 KateGlobalConfig::global()->setFallbackEncoding(KCharsets::charsets()->encodingForName(ui->cmbEncodingFallback->currentText()));
1107
1108 KateDocumentConfig::global()->setEol(ui->cmbEOL->currentIndex());
1109 KateDocumentConfig::global()->setAllowEolDetection(ui->chkDetectEOL->isChecked());
1110 KateDocumentConfig::global()->setBom(ui->chkEnableBOM->isChecked());
1111
1112 KateDocumentConfig::global()->setLineLengthLimit(ui->lineLengthLimit->value());
1113
1114 KateDocumentConfig::global()->setValue(KateDocumentConfig::AutoSave, ui->gbAutoSave->isChecked());
1115 KateDocumentConfig::global()->setValue(KateDocumentConfig::AutoSaveOnFocusOut, ui->cbAutoSaveOnFocus->isChecked());
1116 KateDocumentConfig::global()->setValue(KateDocumentConfig::AutoSaveInteral, ui->spbAutoSaveInterval->value());
1117
1118 KateDocumentConfig::global()->setValue(KateDocumentConfig::AutoReloadIfStateIsInVersionControl, uiadv->chkAutoReloadVersionControl->isChecked());
1119
1120 KateDocumentConfig::global()->configEnd();
1121 KateGlobalConfig::global()->configEnd();
1122}
1123
1124void KateSaveConfigTab::reload()
1125{
1126 modeConfigPage->reload();
1127
1128 // encodings
1129 ui->cmbEncoding->clear();
1130 ui->cmbEncodingFallback->clear();
1131 QStringList encodings(KCharsets::charsets()->descriptiveEncodingNames());
1132 for (int i = 0; i < encodings.count(); i++) {
1133 const auto encodingName = KCharsets::charsets()->encodingForName(encodings[i]);
1134
1135 ui->cmbEncoding->addItem(encodings[i]);
1136 ui->cmbEncodingFallback->addItem(encodings[i]);
1137
1138 if (encodingName == KateDocumentConfig::global()->encoding()) {
1139 ui->cmbEncoding->setCurrentIndex(i);
1140 }
1141
1142 if (encodingName == KateGlobalConfig::global()->fallbackEncoding()) {
1143 // adjust index for fallback config, has no default!
1144 ui->cmbEncodingFallback->setCurrentIndex(i);
1145 }
1146 }
1147
1148 // encoding detection
1149 ui->cmbEncodingDetection->clear();
1150 bool found = false;
1151 const auto proberType = (KEncodingProber::ProberType)KateGlobalConfig::global()->value(KateGlobalConfig::EncodingProberType).toInt();
1152 for (int i = 0; !KEncodingProber::nameForProberType((KEncodingProber::ProberType)i).isEmpty(); ++i) {
1153 ui->cmbEncodingDetection->addItem(KEncodingProber::nameForProberType((KEncodingProber::ProberType)i));
1154 if (i == proberType) {
1155 ui->cmbEncodingDetection->setCurrentIndex(ui->cmbEncodingDetection->count() - 1);
1156 found = true;
1157 }
1158 }
1159 if (!found) {
1160 ui->cmbEncodingDetection->setCurrentIndex(KEncodingProber::Universal);
1161 }
1162
1163 // eol
1164 ui->cmbEOL->setCurrentIndex(KateDocumentConfig::global()->eol());
1165 ui->chkDetectEOL->setChecked(KateDocumentConfig::global()->allowEolDetection());
1166 ui->chkEnableBOM->setChecked(KateDocumentConfig::global()->bom());
1167 ui->lineLengthLimit->setValue(KateDocumentConfig::global()->lineLengthLimit());
1168
1169 ui->cbRemoveTrailingSpaces->setCurrentIndex(KateDocumentConfig::global()->removeSpaces());
1170 ui->chkNewLineAtEof->setChecked(KateDocumentConfig::global()->newLineAtEof());
1171
1172 // other stuff
1173 uiadv->chkBackupLocalFiles->setChecked(KateDocumentConfig::global()->backupOnSaveLocal());
1174 uiadv->chkBackupRemoteFiles->setChecked(KateDocumentConfig::global()->backupOnSaveRemote());
1175 uiadv->edtBackupPrefix->setText(KateDocumentConfig::global()->backupPrefix());
1176 uiadv->edtBackupSuffix->setText(KateDocumentConfig::global()->backupSuffix());
1177
1178 uiadv->cmbSwapFileMode->setCurrentIndex(KateDocumentConfig::global()->swapFileMode());
1179 uiadv->kurlSwapDirectory->setUrl(QUrl::fromLocalFile(KateDocumentConfig::global()->swapDirectory()));
1180 uiadv->spbSwapFileSync->setValue(KateDocumentConfig::global()->swapSyncInterval());
1181 swapFileModeChanged(KateDocumentConfig::global()->swapFileMode());
1182
1183 ui->gbAutoSave->setChecked(KateDocumentConfig::global()->autoSave());
1184 ui->cbAutoSaveOnFocus->setChecked(KateDocumentConfig::global()->autoSaveOnFocusOut());
1185 ui->spbAutoSaveInterval->setValue(KateDocumentConfig::global()->autoSaveInterval());
1186
1187 uiadv->chkAutoReloadVersionControl->setChecked(KateDocumentConfig::global()->value(KateDocumentConfig::AutoReloadIfStateIsInVersionControl).toBool());
1188}
1189
1190void KateSaveConfigTab::reset()
1191{
1192 modeConfigPage->reset();
1193}
1194
1195void KateSaveConfigTab::defaults()
1196{
1197 modeConfigPage->defaults();
1198
1199 ui->cbRemoveTrailingSpaces->setCurrentIndex(0);
1200
1201 uiadv->chkBackupLocalFiles->setChecked(true);
1202 uiadv->chkBackupRemoteFiles->setChecked(false);
1203 uiadv->edtBackupPrefix->setText(QString());
1204 uiadv->edtBackupSuffix->setText(QStringLiteral("~"));
1205
1206 uiadv->cmbSwapFileMode->setCurrentIndex(1);
1207 uiadv->kurlSwapDirectory->setDisabled(true);
1208 uiadv->lblSwapDirectory->setDisabled(true);
1209 uiadv->spbSwapFileSync->setValue(15);
1210}
1211
1212QString KateSaveConfigTab::name() const
1213{
1214 return i18n("Open/Save");
1215}
1216
1217QString KateSaveConfigTab::fullName() const
1218{
1219 return i18n("File Opening & Saving");
1220}
1221
1222QIcon KateSaveConfigTab::icon() const
1223{
1224 return QIcon::fromTheme(QStringLiteral("document-save"));
1225}
1226
1227// END KateSaveConfigTab
1228
1229// BEGIN KateGotoBar
1230KateGotoBar::KateGotoBar(KTextEditor::View *view, QWidget *parent)
1231 : KateViewBarWidget(true, parent)
1232 , m_view(view)
1233{
1234 Q_ASSERT(m_view != nullptr); // this bar widget is pointless w/o a view
1235
1236 QHBoxLayout *topLayout = new QHBoxLayout(centralWidget());
1237 topLayout->setContentsMargins(0, 0, 0, 0);
1238
1239 QToolButton *btn = new QToolButton(this);
1240 btn->setAutoRaise(true);
1241 btn->setMinimumSize(QSize(1, btn->minimumSizeHint().height()));
1242 btn->setText(i18n("&Line:"));
1243 btn->setToolTip(i18n("Go to line number from clipboard"));
1244 connect(btn, &QToolButton::clicked, this, &KateGotoBar::gotoClipboard);
1245 topLayout->addWidget(btn);
1246
1247 m_gotoRange = new QSpinBox(this);
1248 topLayout->addWidget(m_gotoRange, 1);
1249 topLayout->setStretchFactor(m_gotoRange, 0);
1250
1251 btn = new QToolButton(this);
1252 btn->setAutoRaise(true);
1253 btn->setMinimumSize(QSize(1, btn->minimumSizeHint().height()));
1254 btn->setText(i18n("Go to"));
1255 btn->setIcon(QIcon::fromTheme(QStringLiteral("go-jump")));
1257 connect(btn, &QToolButton::clicked, this, &KateGotoBar::gotoLine);
1258 topLayout->addWidget(btn);
1259
1260 btn = m_modifiedUp = new QToolButton(this);
1261 btn->setAutoRaise(true);
1262 btn->setMinimumSize(QSize(1, btn->minimumSizeHint().height()));
1263 btn->setDefaultAction(m_view->action(QStringLiteral("modified_line_up")));
1264 btn->setIcon(QIcon::fromTheme(QStringLiteral("go-up-search")));
1265 btn->setText(QString());
1266 btn->installEventFilter(this);
1267 topLayout->addWidget(btn);
1268
1269 btn = m_modifiedDown = new QToolButton(this);
1270 btn->setAutoRaise(true);
1271 btn->setMinimumSize(QSize(1, btn->minimumSizeHint().height()));
1272 btn->setDefaultAction(m_view->action(QStringLiteral("modified_line_down")));
1273 btn->setIcon(QIcon::fromTheme(QStringLiteral("go-down-search")));
1274 btn->setText(QString());
1275 btn->installEventFilter(this);
1276 topLayout->addWidget(btn);
1277
1278 topLayout->addStretch();
1279
1280 setFocusProxy(m_gotoRange);
1281}
1282
1283void KateGotoBar::showEvent(QShowEvent *event)
1284{
1285 Q_UNUSED(event)
1286 // Catch rare cases where the bar is visible while document is edited
1287 connect(m_view->document(), &KTextEditor::Document::textChanged, this, &KateGotoBar::updateData);
1288}
1289
1290void KateGotoBar::closed()
1291{
1292 disconnect(m_view->document(), &KTextEditor::Document::textChanged, this, &KateGotoBar::updateData);
1293}
1294
1295bool KateGotoBar::eventFilter(QObject *object, QEvent *event)
1296{
1297 if (object == m_modifiedUp || object == m_modifiedDown) {
1298 if (event->type() != QEvent::Wheel) {
1299 return false;
1300 }
1301
1302 int delta = static_cast<QWheelEvent *>(event)->angleDelta().y();
1303 // Reset m_wheelDelta when scroll direction change
1304 if (m_wheelDelta != 0 && (m_wheelDelta < 0) != (delta < 0)) {
1305 m_wheelDelta = 0;
1306 }
1307
1308 m_wheelDelta += delta;
1309
1310 if (m_wheelDelta >= 120) {
1311 m_wheelDelta = 0;
1312 m_modifiedUp->click();
1313 } else if (m_wheelDelta <= -120) {
1314 m_wheelDelta = 0;
1315 m_modifiedDown->click();
1316 }
1317 }
1318
1319 return false;
1320}
1321
1322void KateGotoBar::gotoClipboard()
1323{
1324 static const QRegularExpression rx(QStringLiteral("-?\\d+"));
1325 bool ok = false;
1326 const int lineNo = rx.match(QApplication::clipboard()->text(QClipboard::Selection)).captured().toInt(&ok);
1327 if (!ok) {
1328 return;
1329 }
1330 if (lineNo >= m_gotoRange->minimum() && lineNo <= m_gotoRange->maximum()) {
1331 m_gotoRange->setValue(lineNo);
1332 gotoLine();
1333 } else {
1334 QPointer<KTextEditor::Message> message = new KTextEditor::Message(i18n("No valid line number found in clipboard"));
1335 message->setWordWrap(true);
1336 message->setAutoHide(2000);
1337 message->setPosition(KTextEditor::Message::BottomInView);
1338 message->setView(m_view), m_view->document()->postMessage(message);
1339 }
1340}
1341
1342void KateGotoBar::updateData()
1343{
1344 int lines = m_view->document()->lines();
1345 m_gotoRange->setMinimum(-lines);
1346 m_gotoRange->setMaximum(lines);
1347 if (!isVisible()) {
1348 m_gotoRange->setValue(m_view->cursorPosition().line() + 1);
1349 m_gotoRange->adjustSize(); // ### does not respect the range :-(
1350 }
1351
1352 m_gotoRange->selectAll();
1353}
1354
1355void KateGotoBar::keyPressEvent(QKeyEvent *event)
1356{
1357 int key = event->key();
1358 if (key == Qt::Key_Return || key == Qt::Key_Enter) {
1359 gotoLine();
1360 return;
1361 }
1363}
1364
1365void KateGotoBar::gotoLine()
1366{
1367 KTextEditor::ViewPrivate *kv = qobject_cast<KTextEditor::ViewPrivate *>(m_view);
1368 if (kv && kv->selection() && !kv->config()->persistentSelection()) {
1369 kv->clearSelection();
1370 }
1371
1372 int gotoValue = m_gotoRange->value();
1373 if (gotoValue < 0) {
1374 gotoValue += m_view->document()->lines();
1375 } else if (gotoValue > 0) {
1376 gotoValue -= 1;
1377 }
1378
1379 m_view->setCursorPosition(KTextEditor::Cursor(gotoValue, 0));
1380 m_view->setFocus();
1381 Q_EMIT hideMe();
1382}
1383// END KateGotoBar
1384
1385// BEGIN KateDictionaryBar
1386KateDictionaryBar::KateDictionaryBar(KTextEditor::ViewPrivate *view, QWidget *parent)
1387 : KateViewBarWidget(true, parent)
1388 , m_view(view)
1389{
1390 Q_ASSERT(m_view != nullptr); // this bar widget is pointless w/o a view
1391
1392 QHBoxLayout *topLayout = new QHBoxLayout(centralWidget());
1393 topLayout->setContentsMargins(0, 0, 0, 0);
1394 // topLayout->setSpacing(spacingHint());
1395 m_dictionaryComboBox = new Sonnet::DictionaryComboBox(centralWidget());
1396 connect(m_dictionaryComboBox, &Sonnet::DictionaryComboBox::dictionaryChanged, this, &KateDictionaryBar::dictionaryChanged);
1397 connect(view->doc(), &KTextEditor::DocumentPrivate::defaultDictionaryChanged, this, &KateDictionaryBar::updateData);
1398 QLabel *label = new QLabel(i18n("Dictionary:"), centralWidget());
1399 label->setBuddy(m_dictionaryComboBox);
1400
1401 topLayout->addWidget(label);
1402 topLayout->addWidget(m_dictionaryComboBox, 1);
1403 topLayout->setStretchFactor(m_dictionaryComboBox, 0);
1404 topLayout->addStretch();
1405}
1406
1407KateDictionaryBar::~KateDictionaryBar()
1408{
1409}
1410
1411void KateDictionaryBar::updateData()
1412{
1413 KTextEditor::DocumentPrivate *document = m_view->doc();
1414 QString dictionary = document->defaultDictionary();
1415 if (dictionary.isEmpty()) {
1416 dictionary = Sonnet::Speller().defaultLanguage();
1417 }
1418 m_dictionaryComboBox->setCurrentByDictionary(dictionary);
1419}
1420
1421void KateDictionaryBar::dictionaryChanged(const QString &dictionary)
1422{
1423 const KTextEditor::Range selection = m_view->selectionRange();
1424 if (selection.isValid() && !selection.isEmpty()) {
1425 const bool blockmode = m_view->blockSelection();
1426 m_view->doc()->setDictionary(dictionary, selection, blockmode);
1427 } else {
1428 m_view->doc()->setDefaultDictionary(dictionary);
1429 }
1430}
1431
1432// END KateGotoBar
1433
1434// BEGIN KateModOnHdPrompt
1435KateModOnHdPrompt::KateModOnHdPrompt(KTextEditor::DocumentPrivate *doc, KTextEditor::Document::ModifiedOnDiskReason modtype, const QString &reason)
1436 : QObject(doc)
1437 , m_doc(doc)
1438 , m_message(new KTextEditor::Message(reason, KTextEditor::Message::Information))
1439 , m_fullDiffPath(QStandardPaths::findExecutable(QStringLiteral("diff")))
1440 , m_proc(nullptr)
1441 , m_diffFile(nullptr)
1442 , m_diffAction(nullptr)
1443{
1444 m_message->setPosition(KTextEditor::Message::AboveView);
1445 m_message->setWordWrap(true);
1446
1447 // If the file isn't deleted, present a diff button
1448 const bool onDiskDeleted = modtype == KTextEditor::Document::OnDiskDeleted;
1449 if (!onDiskDeleted) {
1450 QAction *aAutoReload = new QAction(i18n("Enable Auto Reload"), this);
1451 aAutoReload->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh")));
1452 aAutoReload->setToolTip(
1453 i18n("Reloads and will automatically reload without warning about disk changes from now until you close either the tab or window."));
1454 m_message->addAction(aAutoReload, false);
1455 connect(aAutoReload, &QAction::triggered, this, &KateModOnHdPrompt::autoReloadTriggered);
1456
1457 if (!m_fullDiffPath.isEmpty()) {
1458 m_diffAction = new QAction(i18n("View &Difference"), this);
1459 m_diffAction->setIcon(QIcon::fromTheme(QStringLiteral("document-multiple")));
1460 m_diffAction->setToolTip(i18n("Shows a diff of the changes."));
1461 m_message->addAction(m_diffAction, false);
1462 connect(m_diffAction, &QAction::triggered, this, &KateModOnHdPrompt::slotDiff);
1463 }
1464
1465 QAction *aReload = new QAction(i18n("&Reload"), this);
1466 aReload->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh")));
1467 aReload->setToolTip(i18n("Reloads the file from disk. Unsaved changes will be lost."));
1468 m_message->addAction(aReload);
1469 connect(aReload, &QAction::triggered, this, &KateModOnHdPrompt::reloadTriggered);
1470 } else {
1471 QAction *closeFile = new QAction(i18nc("@action:button closes the opened file", "&Close File"), this);
1472 closeFile->setIcon(QIcon::fromTheme(QStringLiteral("document-close")));
1473 closeFile->setToolTip(i18n("Closes the file, discarding its content."));
1474 m_message->addAction(closeFile, false);
1475 connect(closeFile, &QAction::triggered, this, &KateModOnHdPrompt::closeTriggered);
1476
1477 QAction *aSaveAs = new QAction(i18n("&Save As..."), this);
1478 aSaveAs->setIcon(QIcon::fromTheme(QStringLiteral("document-save-as")));
1479 aSaveAs->setToolTip(i18n("Lets you select a location and save the file again."));
1480 m_message->addAction(aSaveAs, false);
1481 connect(aSaveAs, &QAction::triggered, this, &KateModOnHdPrompt::saveAsTriggered);
1482 }
1483
1484 QAction *aIgnore = new QAction(i18n("&Ignore"), this);
1485 aIgnore->setToolTip(i18n("Ignores the changes on disk without any action."));
1486 aIgnore->setIcon(QIcon::fromTheme(QStringLiteral("dialog-cancel")));
1487 m_message->addAction(aIgnore);
1488 connect(aIgnore, &QAction::triggered, this, &KateModOnHdPrompt::ignoreTriggered);
1489
1490 m_doc->postMessage(m_message);
1491}
1492
1493KateModOnHdPrompt::~KateModOnHdPrompt()
1494{
1495 delete m_proc;
1496 m_proc = nullptr;
1497 if (m_diffFile) {
1498 m_diffFile->setAutoRemove(true);
1499 delete m_diffFile;
1500 m_diffFile = nullptr;
1501 }
1502 delete m_message;
1503}
1504
1505void KateModOnHdPrompt::slotDiff()
1506{
1507 if (m_diffFile) {
1508 return;
1509 }
1510
1511 m_diffFile = new QTemporaryFile(QDir::temp().filePath(QLatin1String("XXXXXX.diff")));
1512 m_diffFile->open();
1513
1514 // Start a KProcess that creates a diff
1515 m_proc = new KProcess(this);
1517 *m_proc << m_fullDiffPath << QStringLiteral("-u") << QStringLiteral("-") << m_doc->url().toLocalFile();
1518 connect(m_proc, &KProcess::readyRead, this, &KateModOnHdPrompt::slotDataAvailable);
1519 connect(m_proc, &KProcess::finished, this, &KateModOnHdPrompt::slotPDone);
1520
1521 // disable the diff button, to hinder the user to run it twice.
1522 m_diffAction->setEnabled(false);
1523
1524 m_proc->start();
1525
1526 QTextStream ts(m_proc);
1527 int lastln = m_doc->lines() - 1;
1528 for (int l = 0; l < lastln; ++l) {
1529 ts << m_doc->line(l) << '\n';
1530 }
1531 ts << m_doc->line(lastln);
1532 ts.flush();
1533 m_proc->closeWriteChannel();
1534}
1535
1536void KateModOnHdPrompt::slotDataAvailable()
1537{
1538 m_diffFile->write(m_proc->readAll());
1539}
1540
1541void KateModOnHdPrompt::slotPDone()
1542{
1543 m_diffAction->setEnabled(true);
1544
1545 const QProcess::ExitStatus es = m_proc->exitStatus();
1546 delete m_proc;
1547 m_proc = nullptr;
1548
1549 if (es != QProcess::NormalExit) {
1550 KMessageBox::error(m_doc->activeView(),
1551 i18n("The diff command failed. Please make sure that "
1552 "diff(1) is installed and in your PATH."),
1553 i18n("Error Creating Diff"));
1554 delete m_diffFile;
1555 m_diffFile = nullptr;
1556 return;
1557 }
1558
1559 if (m_diffFile->size() == 0) {
1560 KMessageBox::information(m_doc->activeView(), i18n("The files are identical."), i18n("Diff Output"));
1561 delete m_diffFile;
1562 m_diffFile = nullptr;
1563 return;
1564 }
1565
1566 m_diffFile->setAutoRemove(false);
1567 QUrl url = QUrl::fromLocalFile(m_diffFile->fileName());
1568 delete m_diffFile;
1569 m_diffFile = nullptr;
1570
1571 KIO::OpenUrlJob *job = new KIO::OpenUrlJob(url, QStringLiteral("text/x-patch"));
1573 job->setDeleteTemporaryFile(true); // delete the file, once the client exits
1574 job->start();
1575}
1576
1577// END KateModOnHdPrompt
1578
1579#include "moc_katedialogs.cpp"
QString encodingForName(const QString &descriptiveName) const
static KCharsets * charsets()
static QString nameForProberType(ProberType proberType)
void setDeleteTemporaryFile(bool b)
void start() override
void setUiDelegate(KJobUiDelegate *delegate)
void start()
void setOutputChannelMode(OutputChannelMode mode)
virtual void apply()=0
This slot is called whenever the button Apply or OK was clicked.
virtual void reset()=0
This slot is called whenever the button Reset was clicked.
virtual QString name() const =0
Get a readable name for the config page.
virtual void defaults()=0
Sets default options This slot is called whenever the button Defaults was clicked.
The Cursor represents a position in a Document.
Definition cursor.h:75
constexpr int line() const noexcept
Retrieve the line on which this cursor is situated.
Definition cursor.h:174
A KParts derived class representing a text document.
Definition document.h:284
void textChanged(KTextEditor::Document *document)
The document emits this signal whenever its text changes.
virtual int lines() const =0
Get the count of lines of the document.
virtual bool postMessage(Message *message)=0
Post message to the Document and its Views.
ModifiedOnDiskReason
Reasons why a document is modified on disk.
Definition document.h:1423
@ OnDiskDeleted
The file was deleted on disk.
Definition document.h:1427
static KTextEditor::EditorPrivate * self()
Kate Part Internal stuff ;)
QList< KTextEditor::Document * > documents() override
Returns a list of all documents of this editor.
Definition kateglobal.h:112
static Editor * instance()
Accessor to get the Editor instance.
void addVariableExpansion(const QList< QWidget * > &widgets, const QStringList &variables=QStringList()) const
Adds a QAction to the widget in widgets that whenever focus is gained.
This class holds a Message to display in Views.
Definition message.h:94
@ AboveView
show message above view.
Definition message.h:119
@ BottomInView
show message as view overlay in the bottom right corner.
Definition message.h:125
An object representing a section of text, from one Cursor to another.
constexpr bool isEmpty() const noexcept
Returns true if this range contains no characters, ie.
constexpr bool isValid() const noexcept
Validity check.
A text widget with KXMLGUIClient that represents a Document.
Definition view.h:244
virtual bool setCursorPosition(Cursor position)=0
Set the view's new cursor to position.
virtual Document * document() const =0
Get the view's document, that means the view is a view of the returned document.
virtual Cursor cursorPosition() const =0
Get the view's current cursor position.
static uint modeNumber(const QString &name)
Maps name -> index.
const QString & modeName() const
mode name
static QStringList listModes()
List all possible modes by name, i.e.
void configEnd()
End a config change transaction, update the concerned KateDocumentConfig/KateDocumentConfig/KateDocum...
void configStart()
Start some config changes.
bool setValue(const int key, const QVariant &value)
Set a config value.
QVariant value(const int key) const
Get a config value.
void dictionaryChanged(const QString &dictionary)
void setCurrentByDictionary(const QString &dictionary)
KLocalizedString KI18N_EXPORT ki18np(const char *singular, const char *plural)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
KLocalizedString KI18N_EXPORT ki18ncp(const char *context, const char *singular, const char *plural)
QString i18n(const char *text, const TYPE &arg...)
KIOCORE_EXPORT KJobUiDelegate * createDefaultJobUiDelegate()
void information(QWidget *parent, const QString &text, const QString &title=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
const QList< QKeySequence > & reload()
QString label(StandardShortcut id)
The KTextEditor namespace contains all the public API that is required to use the KTextEditor compone...
void clicked(bool checked)
void setIcon(const QIcon &icon)
void setText(const QString &text)
void toggled(bool checked)
void setEnabled(bool)
void setIcon(const QIcon &icon)
void setToolTip(const QString &tip)
void triggered(bool checked)
void addStretch(int stretch)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
bool setStretchFactor(QWidget *widget, int stretch)
void stateChanged(int state)
void currentIndexChanged(int index)
QPoint pos()
QDir temp()
virtual qint64 size() const const override
QFont systemFont(QFontDatabase::SystemFont type)
QClipboard * clipboard()
QIcon fromTheme(const QString &name)
QByteArray readAll()
void readyRead()
qint64 write(const char *data, qint64 maxSize)
void linkActivated(const QString &link)
void addWidget(QWidget *w)
void setContentsMargins(int left, int top, int right, int bottom)
void editingFinished()
void append(const T &value)
const T & at(int i) const const
int size() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
void installEventFilter(QObject *filterObj)
void finished(int exitCode)
void closeWriteChannel()
QProcess::ExitStatus exitStatus() const const
int height() const const
void setMaximum(int max)
void setValue(int val)
bool isEmpty() const const
ToolTipRole
Key_Return
typedef KeyboardModifiers
LinksAccessibleByMouse
ToolButtonTextBesideIcon
int addTab(QWidget *page, const QString &label)
void setDocumentMode(bool set)
int insertTab(int index, QWidget *page, const QString &label)
virtual QString fileName() const const override
void setAutoRemove(bool b)
void setAutoRaise(bool enable)
virtual QSize minimumSizeHint() const const override
void setDefaultAction(QAction *action)
void setToolButtonStyle(Qt::ToolButtonStyle style)
QUrl fromLocalFile(const QString &localFile)
QStringList toStringList() const const
void showText(const QPoint &pos, const QString &text, QWidget *w)
int y() const const
void adjustSize()
virtual bool event(QEvent *event) override
virtual void keyPressEvent(QKeyEvent *event)
void setMinimumSize(const QSize &)
void setDisabled(bool disable)
void setFocus()
void setToolTip(const QString &)
bool isVisible() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Feb 24 2024 20:00:58 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.