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