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

KDE's Doxygen guidelines are available online.