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 |
86 | KateIndentConfigTab::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(texts: 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(sender: ui->label, signal: &QLabel::linkActivated, context: this, slot: &KateIndentConfigTab::showWhatsThis); |
102 | |
103 | // "What's This?" help can be found in the ui file |
104 | |
105 | reload(); |
106 | |
107 | observeChanges(button: ui->chkAutoDetectIndent); |
108 | observeChanges(button: ui->chkBackspaceUnindents); |
109 | observeChanges(button: ui->chkIndentPaste); |
110 | observeChanges(button: ui->chkKeepExtraSpaces); |
111 | observeChanges(comboBox: ui->cmbMode); |
112 | observeChanges(button: ui->rbIndentMixed); |
113 | observeChanges(button: ui->rbIndentWithSpaces); |
114 | observeChanges(button: ui->rbIndentWithTabs); |
115 | connect(sender: ui->rbIndentWithTabs, signal: &QAbstractButton::toggled, context: ui->sbIndentWidth, slot: &QWidget::setDisabled); |
116 | connect(sender: ui->rbIndentWithTabs, signal: &QAbstractButton::toggled, context: this, slot: &KateIndentConfigTab::slotChanged); // FIXME See slot below |
117 | observeChanges(button: ui->rbTabAdvances); |
118 | observeChanges(button: ui->rbTabIndents); |
119 | observeChanges(button: ui->rbTabSmart); |
120 | observeChanges(spinBox: ui->sbIndentWidth); |
121 | observeChanges(spinBox: ui->sbTabWidth); |
122 | |
123 | layout->addWidget(newWidget); |
124 | } |
125 | |
126 | KateIndentConfigTab::~KateIndentConfigTab() |
127 | { |
128 | delete ui; |
129 | } |
130 | |
131 | void 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(..) |
142 | void KateIndentConfigTab::showWhatsThis(const QString &text) |
143 | { |
144 | QWhatsThis::showText(pos: QCursor::pos(), text); |
145 | } |
146 | |
147 | void 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(mode: 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 | |
177 | void 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(spinBox: ui->sbIndentWidth, ki18np("%v character" , "%v characters" )); |
185 | ui->sbIndentWidth->setValue(KateDocumentConfig::global()->indentationWidth()); |
186 | KLocalization::setupSpinBoxFormatString(spinBox: 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(name: 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 | |
208 | QString KateIndentConfigTab::name() const |
209 | { |
210 | return i18n("Indentation" ); |
211 | } |
212 | |
213 | // END KateIndentConfigTab |
214 | |
215 | // BEGIN KateCompletionConfigTab |
216 | KateCompletionConfigTab::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(button: ui->chkAutoCompletionEnabled); |
232 | observeChanges(button: ui->chkAutoSelectFirstEntry); |
233 | observeChanges(button: ui->chkTabCompletion); |
234 | observeChanges(button: ui->chkEnterCompletion); |
235 | observeChanges(groupBox: ui->gbKeywordCompletion); |
236 | observeChanges(groupBox: ui->gbShowDoc); |
237 | observeChanges(groupBox: ui->gbWordCompletion); |
238 | observeChanges(spinBox: ui->minimalWordLength); |
239 | observeChanges(button: ui->removeTail); |
240 | |
241 | layout->addWidget(newWidget); |
242 | } |
243 | |
244 | KateCompletionConfigTab::~KateCompletionConfigTab() |
245 | { |
246 | delete ui; |
247 | } |
248 | |
249 | void KateCompletionConfigTab::showWhatsThis(const QString &text) // NOTE Not used atm, remove? See also KateIndentConfigTab::showWhatsThis |
250 | { |
251 | QWhatsThis::showText(pos: QCursor::pos(), text); |
252 | } |
253 | |
254 | void 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(key: KateViewConfig::AutomaticCompletionInvocation, value: ui->chkAutoCompletionEnabled->isChecked()); |
265 | KateViewConfig::global()->setValue(key: KateViewConfig::AutomaticCompletionPreselectFirst, value: ui->chkAutoSelectFirstEntry->isChecked()); |
266 | KateViewConfig::global()->setValue(key: KateViewConfig::TabCompletion, value: ui->chkTabCompletion->isChecked()); |
267 | KateViewConfig::global()->setValue(key: KateViewConfig::EnterToInsertCompletion, value: ui->chkEnterCompletion->isChecked()); |
268 | KateViewConfig::global()->setValue(key: KateViewConfig::KeywordCompletion, value: ui->gbKeywordCompletion->isChecked()); |
269 | KateViewConfig::global()->setValue(key: KateViewConfig::WordCompletion, value: ui->gbWordCompletion->isChecked()); |
270 | KateViewConfig::global()->setValue(key: KateViewConfig::WordCompletionMinimalWordLength, value: ui->minimalWordLength->value()); |
271 | KateViewConfig::global()->setValue(key: KateViewConfig::WordCompletionRemoveTail, value: ui->removeTail->isChecked()); |
272 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowDocWithCompletion, value: ui->gbShowDoc->isChecked()); |
273 | |
274 | KateViewConfig::global()->configEnd(); |
275 | } |
276 | |
277 | void 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(key: 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 | |
292 | QString KateCompletionConfigTab::name() const |
293 | { |
294 | return i18n("Auto Completion" ); |
295 | } |
296 | |
297 | // END KateCompletionConfigTab |
298 | |
299 | // BEGIN KateSpellCheckConfigTab |
300 | KateSpellCheckConfigTab::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(sender: m_sonnetConfigWidget, signal: &Sonnet::ConfigWidget::configChanged, context: this, slot: &KateSpellCheckConfigTab::slotChanged); |
317 | layout->addWidget(m_sonnetConfigWidget); |
318 | |
319 | layout->addWidget(newWidget); |
320 | } |
321 | |
322 | KateSpellCheckConfigTab::~KateSpellCheckConfigTab() |
323 | { |
324 | delete ui; |
325 | } |
326 | |
327 | void KateSpellCheckConfigTab::showWhatsThis(const QString &text) // NOTE Not used atm, remove? See also KateIndentConfigTab::showWhatsThis |
328 | { |
329 | QWhatsThis::showText(pos: QCursor::pos(), text); |
330 | } |
331 | |
332 | void 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" ), defaultValue: 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 | |
354 | void KateSpellCheckConfigTab::reload() |
355 | { |
356 | // does nothing |
357 | } |
358 | |
359 | QString KateSpellCheckConfigTab::name() const |
360 | { |
361 | return i18n("Spellcheck" ); |
362 | } |
363 | |
364 | // END KateSpellCheckConfigTab |
365 | |
366 | // BEGIN KateNavigationConfigTab |
367 | KateNavigationConfigTab::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(comboBox: ui->cbTextSelectionMode); |
385 | observeChanges(button: ui->chkBackspaceRemoveComposed); |
386 | observeChanges(button: ui->chkPagingMovesCursor); |
387 | observeChanges(button: ui->chkScrollPastEnd); |
388 | observeChanges(button: ui->chkSmartHome); |
389 | observeChanges(spinBox: ui->sbAutoCenterCursor); |
390 | observeChanges(button: ui->chkCamelCursor); |
391 | observeChanges(comboBox: ui->cmbMultiCursorModifier); |
392 | observeChanges(button: ui->cbCycleBookmarks); |
393 | |
394 | layout->addWidget(newWidget); |
395 | } |
396 | |
397 | KateNavigationConfigTab::~KateNavigationConfigTab() |
398 | { |
399 | delete ui; |
400 | } |
401 | |
402 | void 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(aindex: 0, i18n("Alt" ), auserData: (int)Qt::ALT); |
410 | c->insertItem(aindex: 1, i18n("Ctrl" ), auserData: (int)Qt::CTRL); |
411 | c->insertItem(aindex: 2, i18n("Meta" ), auserData: (int)Qt::META); |
412 | c->insertItem(aindex: 3, i18n("Ctrl + Alt" ), auserData: (int)(Qt::CTRL | Qt::ALT)); |
413 | c->insertItem(aindex: 4, i18n("Meta + Alt" ), auserData: (int)(Qt::META | Qt::ALT)); |
414 | c->insertItem(aindex: 5, i18n("Ctrl + Meta" ), auserData: (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 | |
425 | void 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(key: KateViewConfig::AutoCenterLines, value: ui->sbAutoCenterCursor->value()); |
441 | KateViewConfig::global()->setValue(key: KateViewConfig::BackspaceRemoveComposedCharacters, value: ui->chkBackspaceRemoveComposed->isChecked()); |
442 | KateViewConfig::global()->setValue(key: KateViewConfig::PersistentSelection, value: ui->cbTextSelectionMode->currentIndex() == 1); |
443 | KateViewConfig::global()->setValue(key: KateViewConfig::ScrollPastEnd, value: ui->chkScrollPastEnd->isChecked()); |
444 | KateViewConfig::global()->setValue(key: KateViewConfig::CycleThroughBookmarks, value: 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 | |
453 | void 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(key: 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(index: i).toInt(); |
470 | if (idxMods == mods) { |
471 | ui->cmbMultiCursorModifier->setCurrentIndex(i); |
472 | break; |
473 | } |
474 | } |
475 | } |
476 | |
477 | QString KateNavigationConfigTab::name() const |
478 | { |
479 | return i18n("Text Navigation" ); |
480 | } |
481 | |
482 | // END KateNavigationConfigTab |
483 | |
484 | // BEGIN KateEditGeneralConfigTab |
485 | KateEditGeneralConfigTab::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(atext: fact->name(), auserData: static_cast<int>(fact->inputMode())); |
495 | } |
496 | |
497 | // "What's This?" Help is in the ui-files |
498 | |
499 | reload(); |
500 | |
501 | observeChanges(button: ui->chkAutoBrackets); |
502 | observeChanges(button: ui->chkMousePasteAtCursorPosition); |
503 | observeChanges(button: ui->chkShowStaticWordWrapMarker); |
504 | observeChanges(button: ui->chkTextDragAndDrop); |
505 | observeChanges(button: ui->chkSmartCopyCut); |
506 | observeChanges(spinBox: ui->sbClipboardHistoryEntries); |
507 | observeChanges(button: ui->chkStaticWordWrap); |
508 | observeChanges(comboBox: ui->cmbEncloseSelection); |
509 | ui->lblBracketHelp->setFont(QFontDatabase::systemFont(type: QFontDatabase::SmallestReadableFont)); |
510 | connect(sender: ui->cmbEncloseSelection->lineEdit(), signal: &QLineEdit::editingFinished, slot: [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(atext: text); |
521 | slotChanged(); |
522 | } |
523 | ui->cmbEncloseSelection->setCurrentIndex(ui->cmbEncloseSelection->findText(text)); |
524 | }); |
525 | observeChanges(comboBox: ui->cmbInputMode); |
526 | observeChanges(spinBox: ui->sbWordWrap); |
527 | observeChanges(button: ui->chkAccessibility); |
528 | |
529 | layout->addWidget(newWidget); |
530 | } |
531 | |
532 | KateEditGeneralConfigTab::~KateEditGeneralConfigTab() |
533 | { |
534 | delete ui; |
535 | } |
536 | |
537 | void 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(key: KateViewConfig::AutoBrackets, value: ui->chkAutoBrackets->isChecked()); |
554 | KateViewConfig::global()->setValue(key: KateViewConfig::CharsToEncloseSelection, value: ui->cmbEncloseSelection->currentText()); |
555 | QStringList userLetters; |
556 | for (int i = UserData; i < ui->cmbEncloseSelection->count(); ++i) { |
557 | userLetters.append(t: ui->cmbEncloseSelection->itemText(index: i)); |
558 | } |
559 | KateViewConfig::global()->setValue(key: KateViewConfig::UserSetsOfCharsToEncloseSelection, value: userLetters); |
560 | KateViewConfig::global()->setValue(key: KateViewConfig::InputMode, value: ui->cmbInputMode->currentData().toInt()); |
561 | KateViewConfig::global()->setValue(key: KateViewConfig::MousePasteAtCursorPosition, value: ui->chkMousePasteAtCursorPosition->isChecked()); |
562 | KateViewConfig::global()->setValue(key: KateViewConfig::TextDragAndDrop, value: ui->chkTextDragAndDrop->isChecked()); |
563 | KateViewConfig::global()->setValue(key: KateViewConfig::SmartCopyCut, value: ui->chkSmartCopyCut->isChecked()); |
564 | KateViewConfig::global()->setValue(key: KateViewConfig::ClipboardHistoryEntries, value: ui->sbClipboardHistoryEntries->value()); |
565 | KateViewConfig::global()->setValue(key: KateViewConfig::EnableAccessibility, value: ui->chkAccessibility->isChecked()); |
566 | |
567 | KateDocumentConfig::global()->configEnd(); |
568 | KateViewConfig::global()->configEnd(); |
569 | } |
570 | |
571 | void 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(spinBox: 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(atext: QString(), auserData: None); |
588 | ui->cmbEncloseSelection->setItemData(index: 0, i18n("Disable Feature" ), role: Qt::ToolTipRole); |
589 | ui->cmbEncloseSelection->addItem(QStringLiteral("`*_~" ), auserData: MarkDown); |
590 | ui->cmbEncloseSelection->setItemData(index: 1, i18n("May be handy with Markdown" ), role: Qt::ToolTipRole); |
591 | ui->cmbEncloseSelection->addItem(QStringLiteral("<>(){}[]'\"" ), auserData: MirrorChar); |
592 | ui->cmbEncloseSelection->setItemData(index: 2, i18n("Mirror characters, similar but not exactly like auto brackets" ), role: Qt::ToolTipRole); |
593 | ui->cmbEncloseSelection->addItem(QStringLiteral("´`_.:|#@~*!?$%/=,;-+^°§&" ), auserData: NonLetters); |
594 | ui->cmbEncloseSelection->setItemData(index: 3, i18n("Non letter character" ), role: Qt::ToolTipRole); |
595 | const QStringList userLetters = KateViewConfig::global()->value(key: KateViewConfig::UserSetsOfCharsToEncloseSelection).toStringList(); |
596 | for (int i = 0; i < userLetters.size(); ++i) { |
597 | ui->cmbEncloseSelection->addItem(atext: userLetters.at(i), auserData: UserData + i); |
598 | } |
599 | ui->cmbEncloseSelection->setCurrentIndex(ui->cmbEncloseSelection->findText(text: KateViewConfig::global()->charsToEncloseSelection())); |
600 | |
601 | const int id = static_cast<int>(KateViewConfig::global()->inputMode()); |
602 | ui->cmbInputMode->setCurrentIndex(ui->cmbInputMode->findData(data: id)); |
603 | ui->chkAccessibility->setChecked(KateViewConfig::global()->value(key: KateViewConfig::EnableAccessibility).toBool()); |
604 | } |
605 | |
606 | QString KateEditGeneralConfigTab::name() const |
607 | { |
608 | return i18n("General" ); |
609 | } |
610 | |
611 | // END KateEditGeneralConfigTab |
612 | |
613 | // BEGIN KateEditConfigTab |
614 | KateEditConfigTab::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(left: 0, top: 0, right: 0, bottom: 0); |
624 | QTabWidget *tabWidget = new QTabWidget(this); |
625 | tabWidget->setDocumentMode(true); |
626 | |
627 | // add all tabs |
628 | tabWidget->insertTab(index: 0, widget: editConfigTab, editConfigTab->name()); |
629 | tabWidget->insertTab(index: 1, widget: navigationConfigTab, navigationConfigTab->name()); |
630 | tabWidget->insertTab(index: 2, widget: indentConfigTab, indentConfigTab->name()); |
631 | tabWidget->insertTab(index: 3, widget: completionConfigTab, completionConfigTab->name()); |
632 | tabWidget->insertTab(index: 4, widget: spellCheckConfigTab, spellCheckConfigTab->name()); |
633 | |
634 | observeChanges(page: editConfigTab); |
635 | observeChanges(page: navigationConfigTab); |
636 | observeChanges(page: indentConfigTab); |
637 | observeChanges(page: completionConfigTab); |
638 | observeChanges(page: 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(x: tab); |
645 | tabWidget->insertTab(index: i, widget: tab, tab->name()); |
646 | observeChanges(page: tab); |
647 | i++; |
648 | } |
649 | } |
650 | |
651 | layout->addWidget(tabWidget); |
652 | } |
653 | |
654 | KateEditConfigTab::~KateEditConfigTab() |
655 | { |
656 | qDeleteAll(c: m_inputModeConfigTabs); |
657 | } |
658 | |
659 | void 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 | |
672 | void 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 | |
684 | void 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 | |
696 | void 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 | |
708 | QString KateEditConfigTab::name() const |
709 | { |
710 | return i18n("Editing" ); |
711 | } |
712 | |
713 | QString KateEditConfigTab::fullName() const |
714 | { |
715 | return i18n("Editing Options" ); |
716 | } |
717 | |
718 | QIcon KateEditConfigTab::icon() const |
719 | { |
720 | return QIcon::fromTheme(QStringLiteral("accessories-text-editor" )); |
721 | } |
722 | |
723 | // END KateEditConfigTab |
724 | |
725 | // BEGIN KateViewDefaultsConfig |
726 | KateViewDefaultsConfig::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(w: tabWidget); |
736 | layout->setContentsMargins(left: 0, top: 0, right: 0, bottom: 0); |
737 | |
738 | QWidget *textareaTab = new QWidget(tabWidget); |
739 | textareaUi->setupUi(textareaTab); |
740 | tabWidget->addTab(widget: textareaTab, i18n("General" )); |
741 | |
742 | QWidget *bordersTab = new QWidget(tabWidget); |
743 | bordersUi->setupUi(bordersTab); |
744 | tabWidget->addTab(widget: bordersTab, i18n("Borders" )); |
745 | |
746 | QWidget *statusbarTab = new QWidget(tabWidget); |
747 | statusBarUi->setupUi(statusbarTab); |
748 | tabWidget->addTab(widget: 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(chooser: textareaUi->kfontrequester); |
759 | |
760 | observeChanges(button: textareaUi->chkAnimateBracketMatching); |
761 | observeChanges(button: textareaUi->chkDynWrapAnywhere); |
762 | observeChanges(button: textareaUi->chkDynWrapAtStaticMarker); |
763 | observeChanges(button: textareaUi->chkFoldFirstLine); |
764 | observeChanges(button: textareaUi->chkShowBracketMatchPreview); |
765 | observeChanges(button: textareaUi->chkShowIndentationLines); |
766 | observeChanges(button: textareaUi->chkShowLineCount); |
767 | observeChanges(button: textareaUi->chkShowTabs); |
768 | observeChanges(button: textareaUi->chkShowWholeBracketExpression); |
769 | observeChanges(button: textareaUi->chkShowWordCount); |
770 | observeChanges(comboBox: textareaUi->cmbDynamicWordWrapIndicator); |
771 | observeChanges(button: textareaUi->cbxWordWrap); |
772 | observeChanges(spinBox: 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 | connect(sender: textareaUi->cbxWordWrap, signal: &QCheckBox::checkStateChanged, context: this, slot&: a); |
780 | a(); |
781 | auto b = [cbx = textareaUi->cbxIndentWrappedLines, sb = textareaUi->sbDynamicWordWrapDepth]() { |
782 | sb->setEnabled(cbx->isChecked()); |
783 | }; |
784 | b(); |
785 | connect(sender: textareaUi->cbxIndentWrappedLines, signal: &QCheckBox::checkStateChanged, context: this, slot&: b); |
786 | observeChanges(button: textareaUi->cbxIndentWrappedLines); |
787 | observeChanges(spinBox: textareaUi->sbDynamicWordWrapDepth); |
788 | observeChanges(slider: textareaUi->sliSetMarkerSize); |
789 | observeChanges(comboBox: textareaUi->spacesComboBox); |
790 | |
791 | observeChanges(button: bordersUi->chkIconBorder); |
792 | observeChanges(button: bordersUi->chkLineNumbers); |
793 | observeChanges(button: bordersUi->chkScrollbarMarks); |
794 | observeChanges(button: bordersUi->chkScrollbarMiniMap); |
795 | observeChanges(button: bordersUi->chkScrollbarMiniMapAll); |
796 | bordersUi->chkScrollbarMiniMapAll->hide(); // this is temporary until the feature is done |
797 | observeChanges(button: bordersUi->chkScrollbarPreview); |
798 | observeChanges(button: bordersUi->chkShowFoldingMarkers); |
799 | observeChanges(button: bordersUi->chkShowFoldingPreview); |
800 | observeChanges(button: bordersUi->chkShowLineModification); |
801 | observeChanges(comboBox: bordersUi->cmbShowScrollbars); |
802 | observeChanges(button: bordersUi->rbSortBookmarksByCreation); |
803 | observeChanges(button: bordersUi->rbSortBookmarksByPosition); |
804 | observeChanges(spinBox: bordersUi->spBoxMiniMapWidth); |
805 | observeChanges(comboBox: bordersUi->cmbFoldingArrowVisiblity); |
806 | |
807 | // statusBarUi |
808 | observeChanges(button: statusBarUi->cbShowActiveDictionary); |
809 | observeChanges(button: statusBarUi->cbShowHighlightingMode); |
810 | observeChanges(button: statusBarUi->cbShowInputMode); |
811 | observeChanges(button: statusBarUi->cbShowLineColumn); |
812 | observeChanges(button: statusBarUi->cbShowTabSetting); |
813 | observeChanges(button: statusBarUi->cbShowEncoding); |
814 | observeChanges(button: statusBarUi->cbShowEOL); |
815 | } |
816 | |
817 | KateViewDefaultsConfig::~KateViewDefaultsConfig() |
818 | { |
819 | delete bordersUi; |
820 | delete textareaUi; |
821 | delete statusBarUi; |
822 | } |
823 | |
824 | void KateViewDefaultsConfig::apply() |
825 | { |
826 | // nothing changed, no need to apply stuff |
827 | if (!hasChanged()) { |
828 | return; |
829 | } |
830 | m_changed = false; |
831 | |
832 | KateViewConfig::global()->configStart(); |
833 | KateRendererConfig::global()->configStart(); |
834 | |
835 | KateDocumentConfig::global()->setMarkerSize(textareaUi->sliSetMarkerSize->value()); |
836 | KateDocumentConfig::global()->setShowSpaces(KateDocumentConfig::WhitespaceRendering(textareaUi->spacesComboBox->currentIndex())); |
837 | KateDocumentConfig::global()->setShowTabs(textareaUi->chkShowTabs->isChecked()); |
838 | |
839 | KateRendererConfig::global()->setFont(textareaUi->kfontrequester->font()); |
840 | KateRendererConfig::global()->setAnimateBracketMatching(textareaUi->chkAnimateBracketMatching->isChecked()); |
841 | KateRendererConfig::global()->setShowIndentationLines(textareaUi->chkShowIndentationLines->isChecked()); |
842 | KateRendererConfig::global()->setShowWholeBracketExpression(textareaUi->chkShowWholeBracketExpression->isChecked()); |
843 | KateRendererConfig::global()->setLineHeightMultiplier(textareaUi->spbLineHeightMultiplier->value()); |
844 | |
845 | KateViewConfig::global()->setDynWordWrap(textareaUi->cbxWordWrap->isChecked()); |
846 | KateViewConfig::global()->setShowWordCount(textareaUi->chkShowWordCount->isChecked()); |
847 | KateViewConfig::global()->setValue(key: KateViewConfig::BookmarkSorting, value: bordersUi->rbSortBookmarksByPosition->isChecked() ? 0 : 1); |
848 | if (!textareaUi->cbxIndentWrappedLines->isChecked()) { |
849 | KateViewConfig::global()->setValue(key: KateViewConfig::DynWordWrapAlignIndent, value: 0); |
850 | } else { |
851 | KateViewConfig::global()->setValue(key: KateViewConfig::DynWordWrapAlignIndent, value: textareaUi->sbDynamicWordWrapDepth->value()); |
852 | } |
853 | KateViewConfig::global()->setValue(key: KateViewConfig::DynWordWrapIndicators, value: textareaUi->cmbDynamicWordWrapIndicator->currentIndex()); |
854 | KateViewConfig::global()->setValue(key: KateViewConfig::DynWrapAnywhere, value: textareaUi->chkDynWrapAnywhere->isChecked()); |
855 | KateViewConfig::global()->setValue(key: KateViewConfig::DynWrapAtStaticMarker, value: textareaUi->chkDynWrapAtStaticMarker->isChecked()); |
856 | KateViewConfig::global()->setValue(key: KateViewConfig::FoldFirstLine, value: textareaUi->chkFoldFirstLine->isChecked()); |
857 | KateViewConfig::global()->setValue(key: KateViewConfig::ScrollBarMiniMapWidth, value: bordersUi->spBoxMiniMapWidth->value()); |
858 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowBracketMatchPreview, value: textareaUi->chkShowBracketMatchPreview->isChecked()); |
859 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowFoldingBar, value: bordersUi->chkShowFoldingMarkers->isChecked()); |
860 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowFoldingPreview, value: bordersUi->chkShowFoldingPreview->isChecked()); |
861 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowIconBar, value: bordersUi->chkIconBorder->isChecked()); |
862 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowLineCount, value: textareaUi->chkShowLineCount->isChecked()); |
863 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowLineModification, value: bordersUi->chkShowLineModification->isChecked()); |
864 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowLineNumbers, value: bordersUi->chkLineNumbers->isChecked()); |
865 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowScrollBarMarks, value: bordersUi->chkScrollbarMarks->isChecked()); |
866 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowScrollBarMiniMap, value: bordersUi->chkScrollbarMiniMap->isChecked()); |
867 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowScrollBarMiniMapAll, value: bordersUi->chkScrollbarMiniMapAll->isChecked()); |
868 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowScrollBarPreview, value: bordersUi->chkScrollbarPreview->isChecked()); |
869 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowScrollbars, value: bordersUi->cmbShowScrollbars->currentIndex()); |
870 | bool showOnHoverOnly = bordersUi->cmbFoldingArrowVisiblity->currentIndex() == 0; |
871 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowFoldingOnHoverOnly, value: showOnHoverOnly); |
872 | |
873 | // Statusbar stuff |
874 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowStatusbarDictionary, value: statusBarUi->cbShowActiveDictionary->isChecked()); |
875 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowStatusbarHighlightingMode, value: statusBarUi->cbShowHighlightingMode->isChecked()); |
876 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowStatusbarInputMode, value: statusBarUi->cbShowInputMode->isChecked()); |
877 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowStatusbarLineColumn, value: statusBarUi->cbShowLineColumn->isChecked()); |
878 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowStatusbarTabSettings, value: statusBarUi->cbShowTabSetting->isChecked()); |
879 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowStatusbarFileEncoding, value: statusBarUi->cbShowEncoding->isChecked()); |
880 | KateViewConfig::global()->setValue(key: KateViewConfig::ShowStatusbarEOL, value: statusBarUi->cbShowEOL->isChecked()); |
881 | |
882 | KateRendererConfig::global()->configEnd(); |
883 | KateViewConfig::global()->configEnd(); |
884 | } |
885 | |
886 | void KateViewDefaultsConfig::reload() |
887 | { |
888 | bordersUi->chkIconBorder->setChecked(KateViewConfig::global()->iconBar()); |
889 | bordersUi->chkLineNumbers->setChecked(KateViewConfig::global()->lineNumbers()); |
890 | bordersUi->chkScrollbarMarks->setChecked(KateViewConfig::global()->scrollBarMarks()); |
891 | bordersUi->chkScrollbarMiniMap->setChecked(KateViewConfig::global()->scrollBarMiniMap()); |
892 | bordersUi->chkScrollbarMiniMapAll->setChecked(KateViewConfig::global()->scrollBarMiniMapAll()); |
893 | bordersUi->chkScrollbarPreview->setChecked(KateViewConfig::global()->scrollBarPreview()); |
894 | bordersUi->chkShowFoldingMarkers->setChecked(KateViewConfig::global()->foldingBar()); |
895 | bordersUi->chkShowFoldingPreview->setChecked(KateViewConfig::global()->foldingPreview()); |
896 | bordersUi->chkShowLineModification->setChecked(KateViewConfig::global()->lineModification()); |
897 | bordersUi->cmbShowScrollbars->setCurrentIndex(KateViewConfig::global()->showScrollbars()); |
898 | bordersUi->rbSortBookmarksByCreation->setChecked(KateViewConfig::global()->bookmarkSort() == 1); |
899 | bordersUi->rbSortBookmarksByPosition->setChecked(KateViewConfig::global()->bookmarkSort() == 0); |
900 | bordersUi->spBoxMiniMapWidth->setValue(KateViewConfig::global()->scrollBarMiniMapWidth()); |
901 | bordersUi->cmbFoldingArrowVisiblity->setCurrentIndex(KateViewConfig::global()->showFoldingOnHoverOnly() ? 0 : 1); |
902 | |
903 | textareaUi->kfontrequester->setFont(font: KateRendererConfig::global()->baseFont()); |
904 | |
905 | textareaUi->chkAnimateBracketMatching->setChecked(KateRendererConfig::global()->animateBracketMatching()); |
906 | textareaUi->chkDynWrapAnywhere->setChecked(KateViewConfig::global()->dynWrapAnywhere()); |
907 | textareaUi->chkDynWrapAtStaticMarker->setChecked(KateViewConfig::global()->dynWrapAtStaticMarker()); |
908 | textareaUi->chkFoldFirstLine->setChecked(KateViewConfig::global()->foldFirstLine()); |
909 | textareaUi->chkShowBracketMatchPreview->setChecked(KateViewConfig::global()->value(key: KateViewConfig::ShowBracketMatchPreview).toBool()); |
910 | textareaUi->chkShowIndentationLines->setChecked(KateRendererConfig::global()->showIndentationLines()); |
911 | textareaUi->chkShowLineCount->setChecked(KateViewConfig::global()->showLineCount()); |
912 | textareaUi->chkShowTabs->setChecked(KateDocumentConfig::global()->showTabs()); |
913 | textareaUi->chkShowWholeBracketExpression->setChecked(KateRendererConfig::global()->showWholeBracketExpression()); |
914 | textareaUi->chkShowWordCount->setChecked(KateViewConfig::global()->showWordCount()); |
915 | textareaUi->cmbDynamicWordWrapIndicator->setCurrentIndex(KateViewConfig::global()->dynWordWrapIndicators()); |
916 | textareaUi->cbxWordWrap->setChecked(KateViewConfig::global()->dynWordWrap()); |
917 | textareaUi->cbxIndentWrappedLines->setChecked(KateViewConfig::global()->dynWordWrapAlignIndent() != 0); |
918 | textareaUi->sbDynamicWordWrapDepth->setValue(KateViewConfig::global()->dynWordWrapAlignIndent()); |
919 | textareaUi->sliSetMarkerSize->setValue(KateDocumentConfig::global()->markerSize()); |
920 | textareaUi->spacesComboBox->setCurrentIndex(KateDocumentConfig::global()->showSpaces()); |
921 | textareaUi->spbLineHeightMultiplier->setValue(KateRendererConfig::global()->lineHeightMultiplier()); |
922 | |
923 | statusBarUi->cbShowLineColumn->setChecked(KateViewConfig::global()->value(key: KateViewConfig::ShowStatusbarLineColumn).toBool()); |
924 | statusBarUi->cbShowActiveDictionary->setChecked(KateViewConfig::global()->value(key: KateViewConfig::ShowStatusbarDictionary).toBool()); |
925 | statusBarUi->cbShowTabSetting->setChecked(KateViewConfig::global()->value(key: KateViewConfig::ShowStatusbarTabSettings).toBool()); |
926 | statusBarUi->cbShowHighlightingMode->setChecked(KateViewConfig::global()->value(key: KateViewConfig::ShowStatusbarHighlightingMode).toBool()); |
927 | statusBarUi->cbShowInputMode->setChecked(KateViewConfig::global()->value(key: KateViewConfig::ShowStatusbarInputMode).toBool()); |
928 | statusBarUi->cbShowEncoding->setChecked(KateViewConfig::global()->value(key: KateViewConfig::ShowStatusbarFileEncoding).toBool()); |
929 | statusBarUi->cbShowEOL->setChecked(KateViewConfig::global()->value(key: KateViewConfig::ShowStatusbarEOL).toBool()); |
930 | } |
931 | |
932 | void KateViewDefaultsConfig::reset() |
933 | { |
934 | } |
935 | |
936 | void KateViewDefaultsConfig::defaults() |
937 | { |
938 | } |
939 | |
940 | QString KateViewDefaultsConfig::name() const |
941 | { |
942 | return i18n("Appearance" ); |
943 | } |
944 | |
945 | QString KateViewDefaultsConfig::fullName() const |
946 | { |
947 | return i18n("Appearance" ); |
948 | } |
949 | |
950 | QIcon KateViewDefaultsConfig::icon() const |
951 | { |
952 | return QIcon::fromTheme(QStringLiteral("preferences-desktop-theme" )); |
953 | } |
954 | |
955 | // END KateViewDefaultsConfig |
956 | |
957 | // BEGIN KateSaveConfigTab |
958 | KateSaveConfigTab::KateSaveConfigTab(QWidget *parent) |
959 | : KateConfigPage(parent) |
960 | , modeConfigPage(new ModeConfigPage(this)) |
961 | { |
962 | // FIXME: Is really needed to move all this code below to another class, |
963 | // since it is another tab itself on the config dialog. This means we should |
964 | // initialize, add and work with as we do with modeConfigPage (ereslibre) |
965 | QVBoxLayout *layout = new QVBoxLayout(this); |
966 | layout->setContentsMargins(left: 0, top: 0, right: 0, bottom: 0); |
967 | QTabWidget *tabWidget = new QTabWidget(this); |
968 | tabWidget->setDocumentMode(true); |
969 | |
970 | QWidget *tmpWidget = new QWidget(tabWidget); |
971 | QVBoxLayout *internalLayout = new QVBoxLayout(tmpWidget); |
972 | QWidget *newWidget = new QWidget(tabWidget); |
973 | ui = new Ui::OpenSaveConfigWidget(); |
974 | ui->setupUi(newWidget); |
975 | |
976 | QWidget *tmpWidget2 = new QWidget(tabWidget); |
977 | QVBoxLayout *internalLayout2 = new QVBoxLayout(tmpWidget2); |
978 | QWidget *newWidget2 = new QWidget(tabWidget); |
979 | uiadv = new Ui::OpenSaveConfigAdvWidget(); |
980 | uiadv->setupUi(newWidget2); |
981 | uiadv->lblExplanatory->setText( |
982 | 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 " |
983 | "cause data loss in case of a system crash." , |
984 | QCoreApplication::applicationName())); |
985 | |
986 | // "What's This?" help can be found in the ui file |
987 | |
988 | reload(); |
989 | |
990 | observeChanges(comboBox: ui->cbRemoveTrailingSpaces); |
991 | observeChanges(button: ui->chkDetectEOL); |
992 | observeChanges(button: ui->chkEnableBOM); |
993 | observeChanges(button: ui->chkNewLineAtEof); |
994 | observeChanges(comboBox: ui->cmbEOL); |
995 | observeChanges(comboBox: ui->cmbEncoding); |
996 | observeChanges(comboBox: ui->cmbEncodingDetection); |
997 | observeChanges(comboBox: ui->cmbEncodingFallback); |
998 | observeChanges(spinBox: ui->lineLengthLimit); |
999 | observeChanges(groupBox: ui->gbAutoSave); |
1000 | observeChanges(button: ui->cbAutoSaveOnFocus); |
1001 | observeChanges(spinBox: ui->spbAutoSaveInterval); |
1002 | |
1003 | observeChanges(button: uiadv->chkAutoReloadVersionControl); |
1004 | observeChanges(button: uiadv->chkAutoReloadOnExternalChanges); |
1005 | |
1006 | observeChanges(button: uiadv->chkBackupLocalFiles); |
1007 | observeChanges(button: uiadv->chkBackupRemoteFiles); |
1008 | observeChanges(comboBox: uiadv->cmbSwapFileMode); |
1009 | connect(sender: uiadv->cmbSwapFileMode, signal: &QComboBox::currentIndexChanged, context: this, slot: &KateSaveConfigTab::swapFileModeChanged); |
1010 | |
1011 | observeChanges(lineEdit: uiadv->edtBackupPrefix); |
1012 | observeChanges(lineEdit: uiadv->edtBackupSuffix); |
1013 | observeChanges(requester: uiadv->kurlSwapDirectory); |
1014 | observeChanges(spinBox: uiadv->spbSwapFileSync); |
1015 | observeChanges(button: uiadv->chkEditorConfig); |
1016 | |
1017 | internalLayout->addWidget(newWidget); |
1018 | internalLayout2->addWidget(newWidget2); |
1019 | |
1020 | // add all tabs |
1021 | tabWidget->insertTab(index: 0, widget: tmpWidget, i18n("General" )); |
1022 | tabWidget->insertTab(index: 1, widget: tmpWidget2, i18n("Advanced" )); |
1023 | tabWidget->insertTab(index: 2, widget: modeConfigPage, modeConfigPage->name()); |
1024 | |
1025 | observeChanges(page: modeConfigPage); |
1026 | |
1027 | layout->addWidget(tabWidget); |
1028 | |
1029 | // support variable expansion in backup prefix/suffix |
1030 | KTextEditor::Editor::instance()->addVariableExpansion(widgets: {uiadv->edtBackupPrefix, uiadv->edtBackupSuffix}, |
1031 | variables: {QStringLiteral("Date:Locale" ), |
1032 | QStringLiteral("Date:ISO" ), |
1033 | QStringLiteral("Date:" ), |
1034 | QStringLiteral("Time:Locale" ), |
1035 | QStringLiteral("Time:ISO" ), |
1036 | QStringLiteral("Time:" ), |
1037 | QStringLiteral("ENV:" ), |
1038 | QStringLiteral("JS:" ), |
1039 | QStringLiteral("UUID" )}); |
1040 | } |
1041 | |
1042 | KateSaveConfigTab::~KateSaveConfigTab() |
1043 | { |
1044 | delete uiadv; |
1045 | delete ui; |
1046 | } |
1047 | |
1048 | void KateSaveConfigTab::swapFileModeChanged(int idx) |
1049 | { |
1050 | const KateDocumentConfig::SwapFileMode mode = static_cast<KateDocumentConfig::SwapFileMode>(idx); |
1051 | switch (mode) { |
1052 | case KateDocumentConfig::DisableSwapFile: |
1053 | uiadv->lblSwapDirectory->setEnabled(false); |
1054 | uiadv->kurlSwapDirectory->setEnabled(false); |
1055 | uiadv->lblSwapFileSync->setEnabled(false); |
1056 | uiadv->spbSwapFileSync->setEnabled(false); |
1057 | break; |
1058 | case KateDocumentConfig::EnableSwapFile: |
1059 | uiadv->lblSwapDirectory->setEnabled(false); |
1060 | uiadv->kurlSwapDirectory->setEnabled(false); |
1061 | uiadv->lblSwapFileSync->setEnabled(true); |
1062 | uiadv->spbSwapFileSync->setEnabled(true); |
1063 | break; |
1064 | case KateDocumentConfig::SwapFilePresetDirectory: |
1065 | uiadv->lblSwapDirectory->setEnabled(true); |
1066 | uiadv->kurlSwapDirectory->setEnabled(true); |
1067 | uiadv->lblSwapFileSync->setEnabled(true); |
1068 | uiadv->spbSwapFileSync->setEnabled(true); |
1069 | break; |
1070 | } |
1071 | } |
1072 | |
1073 | void KateSaveConfigTab::apply() |
1074 | { |
1075 | modeConfigPage->apply(); |
1076 | |
1077 | // nothing changed, no need to apply stuff |
1078 | if (!hasChanged()) { |
1079 | return; |
1080 | } |
1081 | m_changed = false; |
1082 | |
1083 | KateGlobalConfig::global()->configStart(); |
1084 | KateDocumentConfig::global()->configStart(); |
1085 | |
1086 | if (uiadv->edtBackupSuffix->text().isEmpty() && uiadv->edtBackupPrefix->text().isEmpty()) { |
1087 | KMessageBox::information(parent: this, i18n("You did not provide a backup suffix or prefix. Using default suffix: '~'" ), i18n("No Backup Suffix or Prefix" )); |
1088 | uiadv->edtBackupSuffix->setText(QStringLiteral("~" )); |
1089 | } |
1090 | |
1091 | KateDocumentConfig::global()->setBackupOnSaveLocal(uiadv->chkBackupLocalFiles->isChecked()); |
1092 | KateDocumentConfig::global()->setBackupOnSaveRemote(uiadv->chkBackupRemoteFiles->isChecked()); |
1093 | KateDocumentConfig::global()->setBackupPrefix(uiadv->edtBackupPrefix->text()); |
1094 | KateDocumentConfig::global()->setBackupSuffix(uiadv->edtBackupSuffix->text()); |
1095 | |
1096 | KateDocumentConfig::global()->setSwapFileMode(uiadv->cmbSwapFileMode->currentIndex()); |
1097 | KateDocumentConfig::global()->setSwapDirectory(uiadv->kurlSwapDirectory->url().toLocalFile()); |
1098 | KateDocumentConfig::global()->setSwapSyncInterval(uiadv->spbSwapFileSync->value()); |
1099 | |
1100 | KateDocumentConfig::global()->setRemoveSpaces(ui->cbRemoveTrailingSpaces->currentIndex()); |
1101 | |
1102 | KateDocumentConfig::global()->setNewLineAtEof(ui->chkNewLineAtEof->isChecked()); |
1103 | |
1104 | // set both standard and fallback encoding |
1105 | KateDocumentConfig::global()->setEncoding(KCharsets::charsets()->encodingForName(descriptiveName: ui->cmbEncoding->currentText())); |
1106 | |
1107 | KateGlobalConfig::global()->setValue(key: KateGlobalConfig::EncodingProberType, value: (KEncodingProber::ProberType)ui->cmbEncodingDetection->currentIndex()); |
1108 | KateGlobalConfig::global()->setFallbackEncoding(KCharsets::charsets()->encodingForName(descriptiveName: ui->cmbEncodingFallback->currentText())); |
1109 | |
1110 | KateDocumentConfig::global()->setEol(ui->cmbEOL->currentIndex()); |
1111 | KateDocumentConfig::global()->setAllowEolDetection(ui->chkDetectEOL->isChecked()); |
1112 | KateDocumentConfig::global()->setBom(ui->chkEnableBOM->isChecked()); |
1113 | |
1114 | KateDocumentConfig::global()->setLineLengthLimit(ui->lineLengthLimit->value()); |
1115 | |
1116 | KateDocumentConfig::global()->setValue(key: KateDocumentConfig::AutoSave, value: ui->gbAutoSave->isChecked()); |
1117 | KateDocumentConfig::global()->setValue(key: KateDocumentConfig::AutoSaveOnFocusOut, value: ui->cbAutoSaveOnFocus->isChecked()); |
1118 | KateDocumentConfig::global()->setValue(key: KateDocumentConfig::AutoSaveInteral, value: ui->spbAutoSaveInterval->value()); |
1119 | |
1120 | KateDocumentConfig::global()->setValue(key: KateDocumentConfig::AutoReloadIfStateIsInVersionControl, value: uiadv->chkAutoReloadVersionControl->isChecked()); |
1121 | KateDocumentConfig::global()->setValue(key: KateDocumentConfig::AutoReloadOnExternalChanges, value: uiadv->chkAutoReloadOnExternalChanges->isChecked()); |
1122 | KateDocumentConfig::global()->setValue(key: KateDocumentConfig::UseEditorConfig, value: uiadv->chkEditorConfig->isChecked()); |
1123 | |
1124 | KateDocumentConfig::global()->configEnd(); |
1125 | KateGlobalConfig::global()->configEnd(); |
1126 | } |
1127 | |
1128 | void KateSaveConfigTab::reload() |
1129 | { |
1130 | modeConfigPage->reload(); |
1131 | |
1132 | // encodings |
1133 | ui->cmbEncoding->clear(); |
1134 | ui->cmbEncodingFallback->clear(); |
1135 | QStringList encodings(KCharsets::charsets()->descriptiveEncodingNames()); |
1136 | for (int i = 0; i < encodings.count(); i++) { |
1137 | const auto encodingName = KCharsets::charsets()->encodingForName(descriptiveName: encodings[i]); |
1138 | |
1139 | ui->cmbEncoding->addItem(atext: encodings[i]); |
1140 | ui->cmbEncodingFallback->addItem(atext: encodings[i]); |
1141 | |
1142 | if (encodingName == KateDocumentConfig::global()->encoding()) { |
1143 | ui->cmbEncoding->setCurrentIndex(i); |
1144 | } |
1145 | |
1146 | if (encodingName == KateGlobalConfig::global()->fallbackEncoding()) { |
1147 | // adjust index for fallback config, has no default! |
1148 | ui->cmbEncodingFallback->setCurrentIndex(i); |
1149 | } |
1150 | } |
1151 | |
1152 | // encoding detection |
1153 | ui->cmbEncodingDetection->clear(); |
1154 | bool found = false; |
1155 | const auto proberType = (KEncodingProber::ProberType)KateGlobalConfig::global()->value(key: KateGlobalConfig::EncodingProberType).toInt(); |
1156 | for (int i = 0; !KEncodingProber::nameForProberType(proberType: (KEncodingProber::ProberType)i).isEmpty(); ++i) { |
1157 | ui->cmbEncodingDetection->addItem(atext: KEncodingProber::nameForProberType(proberType: (KEncodingProber::ProberType)i)); |
1158 | if (i == proberType) { |
1159 | ui->cmbEncodingDetection->setCurrentIndex(ui->cmbEncodingDetection->count() - 1); |
1160 | found = true; |
1161 | } |
1162 | } |
1163 | if (!found) { |
1164 | ui->cmbEncodingDetection->setCurrentIndex(KEncodingProber::Universal); |
1165 | } |
1166 | |
1167 | // eol |
1168 | ui->cmbEOL->setCurrentIndex(KateDocumentConfig::global()->eol()); |
1169 | ui->chkDetectEOL->setChecked(KateDocumentConfig::global()->allowEolDetection()); |
1170 | ui->chkEnableBOM->setChecked(KateDocumentConfig::global()->bom()); |
1171 | ui->lineLengthLimit->setValue(KateDocumentConfig::global()->lineLengthLimit()); |
1172 | |
1173 | ui->cbRemoveTrailingSpaces->setCurrentIndex(KateDocumentConfig::global()->removeSpaces()); |
1174 | ui->chkNewLineAtEof->setChecked(KateDocumentConfig::global()->newLineAtEof()); |
1175 | |
1176 | // other stuff |
1177 | uiadv->chkBackupLocalFiles->setChecked(KateDocumentConfig::global()->backupOnSaveLocal()); |
1178 | uiadv->chkBackupRemoteFiles->setChecked(KateDocumentConfig::global()->backupOnSaveRemote()); |
1179 | uiadv->edtBackupPrefix->setText(KateDocumentConfig::global()->backupPrefix()); |
1180 | uiadv->edtBackupSuffix->setText(KateDocumentConfig::global()->backupSuffix()); |
1181 | |
1182 | uiadv->cmbSwapFileMode->setCurrentIndex(KateDocumentConfig::global()->swapFileMode()); |
1183 | uiadv->kurlSwapDirectory->setUrl(QUrl::fromLocalFile(localfile: KateDocumentConfig::global()->swapDirectory())); |
1184 | uiadv->spbSwapFileSync->setValue(KateDocumentConfig::global()->swapSyncInterval()); |
1185 | swapFileModeChanged(idx: KateDocumentConfig::global()->swapFileMode()); |
1186 | |
1187 | ui->gbAutoSave->setChecked(KateDocumentConfig::global()->autoSave()); |
1188 | ui->cbAutoSaveOnFocus->setChecked(KateDocumentConfig::global()->autoSaveOnFocusOut()); |
1189 | ui->spbAutoSaveInterval->setValue(KateDocumentConfig::global()->autoSaveInterval()); |
1190 | |
1191 | uiadv->chkAutoReloadVersionControl->setChecked(KateDocumentConfig::global()->value(key: KateDocumentConfig::AutoReloadIfStateIsInVersionControl).toBool()); |
1192 | uiadv->chkAutoReloadOnExternalChanges->setChecked(KateDocumentConfig::global()->value(key: KateDocumentConfig::AutoReloadOnExternalChanges).toBool()); |
1193 | uiadv->chkEditorConfig->setChecked(KateDocumentConfig::global()->value(key: KateDocumentConfig::UseEditorConfig).toBool()); |
1194 | } |
1195 | |
1196 | void KateSaveConfigTab::reset() |
1197 | { |
1198 | modeConfigPage->reset(); |
1199 | } |
1200 | |
1201 | void KateSaveConfigTab::defaults() |
1202 | { |
1203 | modeConfigPage->defaults(); |
1204 | |
1205 | ui->cbRemoveTrailingSpaces->setCurrentIndex(0); |
1206 | |
1207 | uiadv->chkBackupLocalFiles->setChecked(true); |
1208 | uiadv->chkBackupRemoteFiles->setChecked(false); |
1209 | uiadv->edtBackupPrefix->setText(QString()); |
1210 | uiadv->edtBackupSuffix->setText(QStringLiteral("~" )); |
1211 | |
1212 | uiadv->cmbSwapFileMode->setCurrentIndex(1); |
1213 | uiadv->kurlSwapDirectory->setDisabled(true); |
1214 | uiadv->lblSwapDirectory->setDisabled(true); |
1215 | uiadv->spbSwapFileSync->setValue(15); |
1216 | } |
1217 | |
1218 | QString KateSaveConfigTab::name() const |
1219 | { |
1220 | return i18n("Open/Save" ); |
1221 | } |
1222 | |
1223 | QString KateSaveConfigTab::fullName() const |
1224 | { |
1225 | return i18n("File Opening & Saving" ); |
1226 | } |
1227 | |
1228 | QIcon KateSaveConfigTab::icon() const |
1229 | { |
1230 | return QIcon::fromTheme(QStringLiteral("document-save" )); |
1231 | } |
1232 | |
1233 | // END KateSaveConfigTab |
1234 | |
1235 | // BEGIN KateGotoBar |
1236 | KateGotoBar::KateGotoBar(KTextEditor::View *view, QWidget *parent) |
1237 | : KateViewBarWidget(true, parent) |
1238 | , m_view(view) |
1239 | { |
1240 | Q_ASSERT(m_view != nullptr); // this bar widget is pointless w/o a view |
1241 | |
1242 | QHBoxLayout *topLayout = new QHBoxLayout(centralWidget()); |
1243 | topLayout->setContentsMargins(left: 0, top: 0, right: 0, bottom: 0); |
1244 | |
1245 | QToolButton *btn = new QToolButton(this); |
1246 | btn->setAutoRaise(true); |
1247 | btn->setMinimumSize(QSize(1, btn->minimumSizeHint().height())); |
1248 | btn->setText(i18n("&Line:" )); |
1249 | btn->setToolTip(i18n("Go to line number from clipboard" )); |
1250 | connect(sender: btn, signal: &QToolButton::clicked, context: this, slot: &KateGotoBar::gotoClipboard); |
1251 | topLayout->addWidget(btn); |
1252 | |
1253 | m_gotoRange = new QSpinBox(this); |
1254 | topLayout->addWidget(m_gotoRange, stretch: 1); |
1255 | topLayout->setStretchFactor(w: m_gotoRange, stretch: 0); |
1256 | |
1257 | btn = new QToolButton(this); |
1258 | btn->setAutoRaise(true); |
1259 | btn->setMinimumSize(QSize(1, btn->minimumSizeHint().height())); |
1260 | btn->setText(i18n("Go to" )); |
1261 | btn->setIcon(QIcon::fromTheme(QStringLiteral("go-jump" ))); |
1262 | btn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); |
1263 | connect(sender: btn, signal: &QToolButton::clicked, context: this, slot: &KateGotoBar::gotoLine); |
1264 | topLayout->addWidget(btn); |
1265 | |
1266 | btn = m_modifiedUp = new QToolButton(this); |
1267 | btn->setAutoRaise(true); |
1268 | btn->setMinimumSize(QSize(1, btn->minimumSizeHint().height())); |
1269 | btn->setDefaultAction(m_view->action(QStringLiteral("modified_line_up" ))); |
1270 | btn->setIcon(QIcon::fromTheme(QStringLiteral("go-up-search" ))); |
1271 | btn->setText(QString()); |
1272 | btn->installEventFilter(filterObj: this); |
1273 | topLayout->addWidget(btn); |
1274 | |
1275 | btn = m_modifiedDown = new QToolButton(this); |
1276 | btn->setAutoRaise(true); |
1277 | btn->setMinimumSize(QSize(1, btn->minimumSizeHint().height())); |
1278 | btn->setDefaultAction(m_view->action(QStringLiteral("modified_line_down" ))); |
1279 | btn->setIcon(QIcon::fromTheme(QStringLiteral("go-down-search" ))); |
1280 | btn->setText(QString()); |
1281 | btn->installEventFilter(filterObj: this); |
1282 | topLayout->addWidget(btn); |
1283 | |
1284 | topLayout->addStretch(); |
1285 | |
1286 | setFocusProxy(m_gotoRange); |
1287 | } |
1288 | |
1289 | void KateGotoBar::showEvent(QShowEvent *event) |
1290 | { |
1291 | Q_UNUSED(event) |
1292 | // Catch rare cases where the bar is visible while document is edited |
1293 | connect(sender: m_view->document(), signal: &KTextEditor::Document::textChanged, context: this, slot: &KateGotoBar::updateData); |
1294 | } |
1295 | |
1296 | void KateGotoBar::closed() |
1297 | { |
1298 | disconnect(sender: m_view->document(), signal: &KTextEditor::Document::textChanged, receiver: this, slot: &KateGotoBar::updateData); |
1299 | } |
1300 | |
1301 | bool KateGotoBar::eventFilter(QObject *object, QEvent *event) |
1302 | { |
1303 | if (object == m_modifiedUp || object == m_modifiedDown) { |
1304 | if (event->type() != QEvent::Wheel) { |
1305 | return false; |
1306 | } |
1307 | |
1308 | int delta = static_cast<QWheelEvent *>(event)->angleDelta().y(); |
1309 | // Reset m_wheelDelta when scroll direction change |
1310 | if (m_wheelDelta != 0 && (m_wheelDelta < 0) != (delta < 0)) { |
1311 | m_wheelDelta = 0; |
1312 | } |
1313 | |
1314 | m_wheelDelta += delta; |
1315 | |
1316 | if (m_wheelDelta >= 120) { |
1317 | m_wheelDelta = 0; |
1318 | m_modifiedUp->click(); |
1319 | } else if (m_wheelDelta <= -120) { |
1320 | m_wheelDelta = 0; |
1321 | m_modifiedDown->click(); |
1322 | } |
1323 | } |
1324 | |
1325 | return false; |
1326 | } |
1327 | |
1328 | void KateGotoBar::gotoClipboard() |
1329 | { |
1330 | static const QRegularExpression rx(QStringLiteral("-?\\d+" )); |
1331 | bool ok = false; |
1332 | const int lineNo = rx.match(subject: QApplication::clipboard()->text(mode: QClipboard::Selection)).captured().toInt(ok: &ok); |
1333 | if (!ok) { |
1334 | return; |
1335 | } |
1336 | if (lineNo >= m_gotoRange->minimum() && lineNo <= m_gotoRange->maximum()) { |
1337 | m_gotoRange->setValue(lineNo); |
1338 | gotoLine(); |
1339 | } else { |
1340 | QPointer<KTextEditor::Message> message = new KTextEditor::Message(i18n("No valid line number found in clipboard" )); |
1341 | message->setWordWrap(true); |
1342 | message->setAutoHide(2000); |
1343 | message->setPosition(KTextEditor::Message::BottomInView); |
1344 | message->setView(m_view), m_view->document()->postMessage(message); |
1345 | } |
1346 | } |
1347 | |
1348 | void KateGotoBar::updateData() |
1349 | { |
1350 | int lines = m_view->document()->lines(); |
1351 | m_gotoRange->setMinimum(-lines); |
1352 | m_gotoRange->setMaximum(lines); |
1353 | if (!isVisible()) { |
1354 | m_gotoRange->setValue(m_view->cursorPosition().line() + 1); |
1355 | m_gotoRange->adjustSize(); // ### does not respect the range :-( |
1356 | } |
1357 | |
1358 | m_gotoRange->selectAll(); |
1359 | } |
1360 | |
1361 | void KateGotoBar::keyPressEvent(QKeyEvent *event) |
1362 | { |
1363 | int key = event->key(); |
1364 | if (key == Qt::Key_Return || key == Qt::Key_Enter) { |
1365 | gotoLine(); |
1366 | return; |
1367 | } |
1368 | KateViewBarWidget::keyPressEvent(event); |
1369 | } |
1370 | |
1371 | void KateGotoBar::gotoLine() |
1372 | { |
1373 | KTextEditor::ViewPrivate *kv = qobject_cast<KTextEditor::ViewPrivate *>(object: m_view); |
1374 | if (kv && kv->selection() && !kv->config()->persistentSelection()) { |
1375 | kv->clearSelection(); |
1376 | } |
1377 | |
1378 | int gotoValue = m_gotoRange->value(); |
1379 | if (gotoValue < 0) { |
1380 | gotoValue += m_view->document()->lines(); |
1381 | } else if (gotoValue > 0) { |
1382 | gotoValue -= 1; |
1383 | } |
1384 | |
1385 | m_view->setCursorPosition(KTextEditor::Cursor(gotoValue, 0)); |
1386 | m_view->setFocus(); |
1387 | Q_EMIT hideMe(); |
1388 | } |
1389 | // END KateGotoBar |
1390 | |
1391 | // BEGIN KateDictionaryBar |
1392 | KateDictionaryBar::KateDictionaryBar(KTextEditor::ViewPrivate *view, QWidget *parent) |
1393 | : KateViewBarWidget(true, parent) |
1394 | , m_view(view) |
1395 | { |
1396 | Q_ASSERT(m_view != nullptr); // this bar widget is pointless w/o a view |
1397 | |
1398 | QHBoxLayout *topLayout = new QHBoxLayout(centralWidget()); |
1399 | topLayout->setContentsMargins(left: 0, top: 0, right: 0, bottom: 0); |
1400 | // topLayout->setSpacing(spacingHint()); |
1401 | m_dictionaryComboBox = new Sonnet::DictionaryComboBox(centralWidget()); |
1402 | connect(sender: m_dictionaryComboBox, signal: &Sonnet::DictionaryComboBox::dictionaryChanged, context: this, slot: &KateDictionaryBar::dictionaryChanged); |
1403 | connect(sender: view->doc(), signal: &KTextEditor::DocumentPrivate::defaultDictionaryChanged, context: this, slot: &KateDictionaryBar::updateData); |
1404 | QLabel *label = new QLabel(i18n("Dictionary:" ), centralWidget()); |
1405 | label->setBuddy(m_dictionaryComboBox); |
1406 | |
1407 | topLayout->addWidget(label); |
1408 | topLayout->addWidget(m_dictionaryComboBox, stretch: 1); |
1409 | topLayout->setStretchFactor(w: m_dictionaryComboBox, stretch: 0); |
1410 | topLayout->addStretch(); |
1411 | } |
1412 | |
1413 | KateDictionaryBar::~KateDictionaryBar() |
1414 | { |
1415 | } |
1416 | |
1417 | void KateDictionaryBar::updateData() |
1418 | { |
1419 | KTextEditor::DocumentPrivate *document = m_view->doc(); |
1420 | QString dictionary = document->defaultDictionary(); |
1421 | if (dictionary.isEmpty()) { |
1422 | dictionary = Sonnet::Speller().defaultLanguage(); |
1423 | } |
1424 | m_dictionaryComboBox->setCurrentByDictionary(dictionary); |
1425 | } |
1426 | |
1427 | void KateDictionaryBar::dictionaryChanged(const QString &dictionary) |
1428 | { |
1429 | const KTextEditor::Range selection = m_view->selectionRange(); |
1430 | if (selection.isValid() && !selection.isEmpty()) { |
1431 | const bool blockmode = m_view->blockSelection(); |
1432 | m_view->doc()->setDictionary(dict: dictionary, range: selection, blockmode); |
1433 | } else { |
1434 | m_view->doc()->setDefaultDictionary(dictionary); |
1435 | } |
1436 | } |
1437 | |
1438 | // END KateGotoBar |
1439 | |
1440 | // BEGIN KateModOnHdPrompt |
1441 | KateModOnHdPrompt::KateModOnHdPrompt(KTextEditor::DocumentPrivate *doc, KTextEditor::Document::ModifiedOnDiskReason modtype, const QString &reason) |
1442 | : QObject(doc) |
1443 | , m_doc(doc) |
1444 | , m_message(new KTextEditor::Message(reason, KTextEditor::Message::Information)) |
1445 | , m_fullDiffPath(QStandardPaths::findExecutable(QStringLiteral("diff" ))) |
1446 | , m_proc(nullptr) |
1447 | , m_diffFile(nullptr) |
1448 | , m_diffAction(nullptr) |
1449 | { |
1450 | m_message->setPosition(KTextEditor::Message::AboveView); |
1451 | m_message->setWordWrap(true); |
1452 | |
1453 | // If the file isn't deleted, present a diff button |
1454 | const bool onDiskDeleted = modtype == KTextEditor::Document::OnDiskDeleted; |
1455 | if (!onDiskDeleted) { |
1456 | QAction *aAutoReload = new QAction(i18n("Enable Auto Reload" ), this); |
1457 | aAutoReload->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh" ))); |
1458 | aAutoReload->setToolTip( |
1459 | i18n("Reloads and will automatically reload without warning about disk changes from now until you close either the tab or window." )); |
1460 | m_message->addAction(action: aAutoReload, closeOnTrigger: false); |
1461 | connect(sender: aAutoReload, signal: &QAction::triggered, context: this, slot: &KateModOnHdPrompt::autoReloadTriggered); |
1462 | |
1463 | if (!m_fullDiffPath.isEmpty()) { |
1464 | m_diffAction = new QAction(i18n("View &Difference" ), this); |
1465 | m_diffAction->setIcon(QIcon::fromTheme(QStringLiteral("document-multiple" ))); |
1466 | m_diffAction->setToolTip(i18n("Shows a diff of the changes." )); |
1467 | m_message->addAction(action: m_diffAction, closeOnTrigger: false); |
1468 | connect(sender: m_diffAction, signal: &QAction::triggered, context: this, slot: &KateModOnHdPrompt::slotDiff); |
1469 | } |
1470 | |
1471 | QAction *aReload = new QAction(i18n("&Reload" ), this); |
1472 | aReload->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh" ))); |
1473 | aReload->setToolTip(i18n("Reloads the file from disk. Unsaved changes will be lost." )); |
1474 | m_message->addAction(action: aReload); |
1475 | connect(sender: aReload, signal: &QAction::triggered, context: this, slot: &KateModOnHdPrompt::reloadTriggered); |
1476 | } else { |
1477 | QAction *closeFile = new QAction(i18nc("@action:button closes the opened file" , "&Close File" ), this); |
1478 | closeFile->setIcon(QIcon::fromTheme(QStringLiteral("document-close" ))); |
1479 | closeFile->setToolTip(i18n("Closes the file, discarding its content." )); |
1480 | m_message->addAction(action: closeFile, closeOnTrigger: false); |
1481 | connect(sender: closeFile, signal: &QAction::triggered, context: this, slot: &KateModOnHdPrompt::closeTriggered); |
1482 | |
1483 | auto *aSaveAs = new QAction(i18nc("@action" , "&Save As…" ), this); |
1484 | aSaveAs->setIcon(QIcon::fromTheme(QStringLiteral("document-save-as" ))); |
1485 | aSaveAs->setToolTip(i18n("Lets you select a location and save the file again." )); |
1486 | m_message->addAction(action: aSaveAs, closeOnTrigger: false); |
1487 | connect(sender: aSaveAs, signal: &QAction::triggered, context: this, slot: &KateModOnHdPrompt::saveAsTriggered); |
1488 | } |
1489 | |
1490 | QAction *aIgnore = new QAction(i18n("&Ignore" ), this); |
1491 | aIgnore->setToolTip(i18n("Ignores the changes on disk without any action." )); |
1492 | aIgnore->setIcon(QIcon::fromTheme(QStringLiteral("dialog-cancel" ))); |
1493 | m_message->addAction(action: aIgnore); |
1494 | connect(sender: aIgnore, signal: &QAction::triggered, context: this, slot: &KateModOnHdPrompt::ignoreTriggered); |
1495 | |
1496 | m_doc->postMessage(message: m_message); |
1497 | } |
1498 | |
1499 | KateModOnHdPrompt::~KateModOnHdPrompt() |
1500 | { |
1501 | delete m_proc; |
1502 | m_proc = nullptr; |
1503 | if (m_diffFile) { |
1504 | m_diffFile->setAutoRemove(true); |
1505 | delete m_diffFile; |
1506 | m_diffFile = nullptr; |
1507 | } |
1508 | delete m_message; |
1509 | } |
1510 | |
1511 | void KateModOnHdPrompt::slotDiff() |
1512 | { |
1513 | if (m_diffFile) { |
1514 | return; |
1515 | } |
1516 | |
1517 | m_diffFile = new QTemporaryFile(QDir::temp().filePath(fileName: QLatin1String("XXXXXX.diff" ))); |
1518 | m_diffFile->open(); |
1519 | |
1520 | // Start a KProcess that creates a diff |
1521 | m_proc = new KProcess(this); |
1522 | m_proc->setOutputChannelMode(KProcess::MergedChannels); |
1523 | *m_proc << m_fullDiffPath << QStringLiteral("-u" ) << QStringLiteral("-" ) << m_doc->url().toLocalFile(); |
1524 | connect(sender: m_proc, signal: &KProcess::readyRead, context: this, slot: &KateModOnHdPrompt::slotDataAvailable); |
1525 | connect(sender: m_proc, signal: &KProcess::finished, context: this, slot: &KateModOnHdPrompt::slotPDone); |
1526 | |
1527 | // disable the diff button, to hinder the user to run it twice. |
1528 | m_diffAction->setEnabled(false); |
1529 | |
1530 | m_proc->start(); |
1531 | |
1532 | QTextStream ts(m_proc); |
1533 | int lastln = m_doc->lines() - 1; |
1534 | for (int l = 0; l < lastln; ++l) { |
1535 | ts << m_doc->line(line: l) << '\n'; |
1536 | } |
1537 | ts << m_doc->line(line: lastln); |
1538 | ts.flush(); |
1539 | m_proc->closeWriteChannel(); |
1540 | } |
1541 | |
1542 | void KateModOnHdPrompt::slotDataAvailable() |
1543 | { |
1544 | m_diffFile->write(data: m_proc->readAll()); |
1545 | } |
1546 | |
1547 | void KateModOnHdPrompt::slotPDone() |
1548 | { |
1549 | m_diffAction->setEnabled(true); |
1550 | |
1551 | const QProcess::ExitStatus es = m_proc->exitStatus(); |
1552 | delete m_proc; |
1553 | m_proc = nullptr; |
1554 | |
1555 | if (es != QProcess::NormalExit) { |
1556 | KMessageBox::error(parent: m_doc->activeView(), |
1557 | i18n("The diff command failed. Please make sure that " |
1558 | "diff(1) is installed and in your PATH." ), |
1559 | i18n("Error Creating Diff" )); |
1560 | delete m_diffFile; |
1561 | m_diffFile = nullptr; |
1562 | return; |
1563 | } |
1564 | |
1565 | if (m_diffFile->size() == 0) { |
1566 | KMessageBox::information(parent: m_doc->activeView(), i18n("The files are identical." ), i18n("Diff Output" )); |
1567 | delete m_diffFile; |
1568 | m_diffFile = nullptr; |
1569 | return; |
1570 | } |
1571 | |
1572 | m_diffFile->setAutoRemove(false); |
1573 | QUrl url = QUrl::fromLocalFile(localfile: m_diffFile->fileName()); |
1574 | delete m_diffFile; |
1575 | m_diffFile = nullptr; |
1576 | |
1577 | KIO::OpenUrlJob *job = new KIO::OpenUrlJob(url, QStringLiteral("text/x-patch" )); |
1578 | job->setUiDelegate(KIO::createDefaultJobUiDelegate(flags: KJobUiDelegate::AutoHandlingEnabled, window: m_doc->activeView())); |
1579 | job->setDeleteTemporaryFile(true); // delete the file, once the client exits |
1580 | job->start(); |
1581 | } |
1582 | |
1583 | // END KateModOnHdPrompt |
1584 | |
1585 | #include "moc_katedialogs.cpp" |
1586 | |