1/*
2 SPDX-FileCopyrightText: 2007, 2008 Matthew Woehlke <mw_triad@users.sourceforge.net>
3 SPDX-FileCopyrightText: 2003 Christoph Cullmann <cullmann@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "kateconfig.h"
9
10#include "katedocument.h"
11#include "kateglobal.h"
12#include "katepartdebug.h"
13#include "katerenderer.h"
14#include "katesyntaxmanager.h"
15#include "kateview.h"
16
17#include <KConfigGroup>
18
19#include <KEncodingProber>
20#include <QGuiApplication>
21#include <QSettings>
22#include <QStringDecoder>
23#include <QStringEncoder>
24#include <QStringListModel>
25
26#include <Sonnet/GuessLanguage>
27#include <Sonnet/Speller>
28
29// BEGIN KateConfig
30KateConfig::KateConfig(const KateConfig *parent)
31 : m_parent(parent)
32 , m_configKeys(m_parent ? nullptr : new QStringList())
33 , m_configKeyToEntry(m_parent ? nullptr : new QHash<QString, const ConfigEntry *>())
34{
35}
36
37KateConfig::~KateConfig() = default;
38
39void KateConfig::addConfigEntry(ConfigEntry &&entry)
40{
41 // shall only be called for toplevel config
42 Q_ASSERT(isGlobal());
43
44 // There shall be no gaps in the entries; i.e. in KateViewConfig constructor
45 // addConfigEntry() is called on each value from the ConfigEntryTypes enum in
46 // the same order as the enumrators.
47 // we might later want to use a vector
48 // qDebug() << m_configEntries.size() << entry.enumKey;
49 Q_ASSERT(m_configEntries.size() == static_cast<size_t>(entry.enumKey));
50
51 // add new element
52 m_configEntries.emplace(args: entry.enumKey, args&: entry);
53}
54
55void KateConfig::finalizeConfigEntries()
56{
57 // shall only be called for toplevel config
58 Q_ASSERT(isGlobal());
59
60 // compute list of all config keys + register map from key => config entry
61 //
62 // we skip entries without a command name, these config entries are not exposed ATM
63 for (const auto &entry : m_configEntries) {
64 if (!entry.second.commandName.isEmpty()) {
65 Q_ASSERT_X(!m_configKeys->contains(entry.second.commandName),
66 "finalizeConfigEntries",
67 (QLatin1String("KEY NOT UNIQUE: ") + entry.second.commandName).toLocal8Bit().constData());
68 m_configKeys->append(t: entry.second.commandName);
69 m_configKeyToEntry->insert(key: entry.second.commandName, value: &entry.second);
70 }
71 }
72}
73
74void KateConfig::readConfigEntries(const KConfigGroup &config)
75{
76 configStart();
77
78 // read all config entries, even the ones ATM not set in this config object but known in the toplevel one
79 for (const auto &entry : fullConfigEntries()) {
80 setValue(key: entry.second.enumKey, value: config.readEntry(key: entry.second.configKey, aDefault: entry.second.defaultValue));
81 }
82
83 configEnd();
84}
85
86void KateConfig::writeConfigEntries(KConfigGroup &config) const
87{
88 // write all config entries, even the ones ATM not set in this config object but known in the toplevel one
89 for (const auto &entry : fullConfigEntries()) {
90 config.writeEntry(key: entry.second.configKey, value: value(key: entry.second.enumKey));
91 }
92}
93
94void KateConfig::configStart()
95{
96 configSessionNumber++;
97
98 if (configSessionNumber > 1) {
99 return;
100 }
101}
102
103void KateConfig::configEnd()
104{
105 if (configSessionNumber == 0) {
106 return;
107 }
108
109 configSessionNumber--;
110
111 if (configSessionNumber > 0) {
112 return;
113 }
114
115 updateConfig();
116}
117
118QVariant KateConfig::value(const int key) const
119{
120 // first: local lookup
121 const auto it = m_configEntries.find(x: key);
122 if (it != m_configEntries.end()) {
123 return it->second.value;
124 }
125
126 // else: fallback to parent config, if any
127 if (m_parent) {
128 return m_parent->value(key);
129 }
130
131 // if we arrive here, the key was invalid! => programming error
132 // for release builds, we just return invalid variant
133 Q_ASSERT(false);
134 return QVariant();
135}
136
137bool KateConfig::setValue(const int key, const QVariant &value)
138{
139 // check: is this key known at all?
140 const auto &knownEntries = fullConfigEntries();
141 const auto knownIt = knownEntries.find(x: key);
142 if (knownIt == knownEntries.end()) {
143 // if we arrive here, the key was invalid! => programming error
144 // for release builds, we just fail to set the value
145 Q_ASSERT(false);
146 return false;
147 }
148
149 // validator set? use it, if not accepting, abort setting
150 if (knownIt->second.validator && !knownIt->second.validator(value)) {
151 return false;
152 }
153
154 // check if value already there for this config
155 auto valueIt = m_configEntries.find(x: key);
156 if (valueIt != m_configEntries.end()) {
157 // skip any work if value is equal
158 if (valueIt->second.value == value) {
159 return true;
160 }
161
162 // else: alter value and be done
163 configStart();
164 valueIt->second.value = value;
165 configEnd();
166 return true;
167 }
168
169 // if not in this hash, we must copy the known entry and adjust the value
170 configStart();
171 auto res = m_configEntries.emplace(args: key, args: knownIt->second);
172 res.first->second.value = value;
173 configEnd();
174 return true;
175}
176
177QVariant KateConfig::value(const QString &key) const
178{
179 // check if we know this key, if not, return invalid variant
180 const auto &knownEntries = fullConfigKeyToEntry();
181 const auto it = knownEntries.find(key);
182 if (it == knownEntries.end()) {
183 return QVariant();
184 }
185
186 // key known, dispatch to normal value() function with enum
187 return value(key: it.value()->enumKey);
188}
189
190bool KateConfig::setValue(const QString &key, const QVariant &value)
191{
192 // check if we know this key, if not, ignore the set
193 const auto &knownEntries = fullConfigKeyToEntry();
194 const auto it = knownEntries.find(key);
195 if (it == knownEntries.end()) {
196 return false;
197 }
198
199 // key known, dispatch to normal setValue() function with enum
200 return setValue(key: it.value()->enumKey, value);
201}
202
203// END
204
205// BEGIN HelperFunctions
206KateGlobalConfig *KateGlobalConfig::s_global = nullptr;
207KateDocumentConfig *KateDocumentConfig::s_global = nullptr;
208KateViewConfig *KateViewConfig::s_global = nullptr;
209KateRendererConfig *KateRendererConfig::s_global = nullptr;
210
211/**
212 * validate if an encoding is ok
213 * @param name encoding name
214 * @return encoding ok?
215 */
216static bool isEncodingOk(const QString &name)
217{
218 return QStringDecoder(name.toUtf8().constData()).isValid() && QStringEncoder(name.toUtf8().constData()).isValid();
219}
220
221static bool inBounds(const int min, const QVariant &value, const int max)
222{
223 const int val = value.toInt();
224 return (val >= min) && (val <= max);
225}
226
227static bool isPositive(const QVariant &value)
228{
229 bool ok;
230 value.toUInt(ok: &ok);
231 return ok;
232}
233// END
234
235// BEGIN KateGlobalConfig
236KateGlobalConfig::KateGlobalConfig()
237{
238 // register this as our global instance
239 Q_ASSERT(isGlobal());
240 s_global = this;
241
242 // avoid updateConfig effects like config write in constructor, see bug 377067
243 Q_ASSERT(configSessionNumber == 0);
244 ++configSessionNumber;
245
246 // init all known config entries
247 addConfigEntry(entry: ConfigEntry(EncodingProberType, "Encoding Prober Type", QString(), KEncodingProber::Universal));
248 addConfigEntry(entry: ConfigEntry(FallbackEncoding,
249 "Fallback Encoding",
250 QString(),
251 QString::fromUtf8(utf8: QStringConverter::nameForEncoding(e: QStringConverter::Latin1)),
252 [](const QVariant &value) {
253 return isEncodingOk(name: value.toString());
254 }));
255
256 // finalize the entries, e.g. hashs them
257 finalizeConfigEntries();
258
259 // init with defaults from config or really hardcoded ones
260 KConfigGroup cg(KTextEditor::EditorPrivate::config(), QStringLiteral("KTextEditor Editor"));
261 readConfig(config: cg);
262
263 // avoid updateConfig effects like config write in constructor, see bug 377067
264 Q_ASSERT(configSessionNumber == 1);
265 --configSessionNumber;
266}
267
268void KateGlobalConfig::readConfig(const KConfigGroup &config)
269{
270 // start config update group
271 configStart();
272
273 // read generic entries
274 readConfigEntries(config);
275
276 // end config update group, might trigger updateConfig()
277 configEnd();
278}
279
280void KateGlobalConfig::writeConfig(KConfigGroup &config)
281{
282 // write generic entries
283 writeConfigEntries(config);
284}
285
286void KateGlobalConfig::updateConfig()
287{
288 // write config
289 KConfigGroup cg(KTextEditor::EditorPrivate::config(), QStringLiteral("KTextEditor Editor"));
290 writeConfig(config&: cg);
291 KTextEditor::EditorPrivate::config()->sync();
292
293 // trigger emission of KTextEditor::Editor::configChanged
294 KTextEditor::EditorPrivate::self()->triggerConfigChanged();
295}
296// END
297
298// BEGIN KateDocumentConfig
299KateDocumentConfig::KateDocumentConfig()
300{
301 // register this as our global instance
302 Q_ASSERT(isGlobal());
303 s_global = this;
304
305 // avoid updateConfig effects like config write in constructor, see bug 377067
306 Q_ASSERT(configSessionNumber == 0);
307 ++configSessionNumber;
308
309 // init all known config entries
310 addConfigEntry(entry: ConfigEntry(TabWidth, "Tab Width", QStringLiteral("tab-width"), 4, [](const QVariant &value) {
311 return value.toInt() >= 1;
312 }));
313 addConfigEntry(entry: ConfigEntry(IndentationWidth, "Indentation Width", QStringLiteral("indent-width"), 4, [](const QVariant &value) {
314 return value.toInt() >= 1;
315 }));
316 addConfigEntry(entry: ConfigEntry(OnTheFlySpellCheck, "On-The-Fly Spellcheck", QStringLiteral("on-the-fly-spellcheck"), false));
317 addConfigEntry(entry: ConfigEntry(IndentOnTextPaste, "Indent On Text Paste", QStringLiteral("indent-pasted-text"), true));
318 addConfigEntry(entry: ConfigEntry(ReplaceTabsWithSpaces, "ReplaceTabsDyn", QStringLiteral("replace-tabs"), true));
319 addConfigEntry(entry: ConfigEntry(BackupOnSaveLocal, "Backup Local", QStringLiteral("backup-on-save-local"), false));
320 addConfigEntry(entry: ConfigEntry(BackupOnSaveRemote, "Backup Remote", QStringLiteral("backup-on-save-remote"), false));
321 addConfigEntry(entry: ConfigEntry(BackupOnSavePrefix, "Backup Prefix", QStringLiteral("backup-on-save-prefix"), QString()));
322 addConfigEntry(entry: ConfigEntry(BackupOnSaveSuffix, "Backup Suffix", QStringLiteral("backup-on-save-suffix"), QStringLiteral("~")));
323 addConfigEntry(entry: ConfigEntry(IndentationMode, "Indentation Mode", QString(), QStringLiteral("normal")));
324 addConfigEntry(entry: ConfigEntry(TabHandlingMode, "Tab Handling", QString(), KateDocumentConfig::tabSmart));
325 addConfigEntry(entry: ConfigEntry(StaticWordWrap, "Word Wrap", QString(), false));
326 addConfigEntry(entry: ConfigEntry(StaticWordWrapColumn, "Word Wrap Column", QString(), 80, [](const QVariant &value) {
327 return value.toInt() >= 1;
328 }));
329 addConfigEntry(entry: ConfigEntry(PageUpDownMovesCursor, "PageUp/PageDown Moves Cursor", QString(), false));
330 addConfigEntry(entry: ConfigEntry(SmartHome, "Smart Home", QString(), true));
331 addConfigEntry(entry: ConfigEntry(ShowTabs, "Show Tabs", QString(), true));
332 addConfigEntry(entry: ConfigEntry(IndentOnTab, "Indent On Tab", QString(), true));
333 addConfigEntry(entry: ConfigEntry(KeepExtraSpaces, "Keep Extra Spaces", QStringLiteral("keep-extra-spaces"), false));
334 addConfigEntry(entry: ConfigEntry(BackspaceIndents, "Indent On Backspace", QString(), true));
335 addConfigEntry(entry: ConfigEntry(ShowSpacesMode, "Show Spaces", QString(), KateDocumentConfig::None));
336 addConfigEntry(entry: ConfigEntry(TrailingMarkerSize, "Trailing Marker Size", QString(), 1));
337 addConfigEntry(
338 entry: ConfigEntry(RemoveSpacesMode, "Remove Spaces", QStringLiteral("remove-spaces"), 1 /* on modified lines per default */, [](const QVariant &value) {
339 return inBounds(min: 0, value, max: 2);
340 }));
341 addConfigEntry(entry: ConfigEntry(NewlineAtEOF, "Newline at End of File", QString(), true));
342 addConfigEntry(entry: ConfigEntry(OverwriteMode, "Overwrite Mode", QString(), false));
343 addConfigEntry(
344 entry: ConfigEntry(Encoding, "Encoding", QString(), QString::fromUtf8(utf8: QStringConverter::nameForEncoding(e: QStringConverter::Utf8)), [](const QVariant &value) {
345 return isEncodingOk(name: value.toString());
346 }));
347 addConfigEntry(entry: ConfigEntry(EndOfLine, "End of Line", QString(), 0));
348 addConfigEntry(entry: ConfigEntry(AllowEndOfLineDetection, "Allow End of Line Detection", QString(), true));
349 addConfigEntry(entry: ConfigEntry(ByteOrderMark, "BOM", QString(), false));
350 addConfigEntry(entry: ConfigEntry(SwapFile, "Swap File Mode", QString(), KateDocumentConfig::EnableSwapFile));
351 addConfigEntry(entry: ConfigEntry(SwapFileDirectory, "Swap Directory", QString(), QString()));
352 addConfigEntry(entry: ConfigEntry(SwapFileSyncInterval, "Swap Sync Interval", QString(), 15));
353 addConfigEntry(entry: ConfigEntry(LineLengthLimit, "Line Length Limit", QString(), 10000));
354 addConfigEntry(entry: ConfigEntry(CamelCursor, "Camel Cursor", QString(), true));
355 addConfigEntry(entry: ConfigEntry(AutoDetectIndent, "Auto Detect Indent", QString(), true));
356
357 // Auto save and co.
358 addConfigEntry(entry: ConfigEntry(AutoSave, "Auto Save", QString(), false));
359 addConfigEntry(entry: ConfigEntry(AutoSaveOnFocusOut, "Auto Save On Focus Out", QString(), false));
360 addConfigEntry(entry: ConfigEntry(AutoSaveInteral, "Auto Save Interval", QString(), 0));
361
362 // Shall we do auto reloading for stuff e.g. in Git?
363 addConfigEntry(entry: ConfigEntry(AutoReloadIfStateIsInVersionControl, "Auto Reload If State Is In Version Control", QString(), true));
364 addConfigEntry(
365 entry: ConfigEntry(AutoReloadOnExternalChanges, "Auto Reload If Any External Changes Occurs", QStringLiteral("auto-reload-on-external-changes"), false));
366 // .editorconfig
367 addConfigEntry(entry: ConfigEntry(UseEditorConfig, "Use Editor Config", QString(), true));
368
369 // finalize the entries, e.g. hashs them
370 finalizeConfigEntries();
371
372 // init with defaults from config or really hardcoded ones
373 KConfigGroup cg(KTextEditor::EditorPrivate::config(), QStringLiteral("KTextEditor Document"));
374 readConfig(config: cg);
375
376 // avoid updateConfig effects like config write in constructor, see bug 377067
377 Q_ASSERT(configSessionNumber == 1);
378 --configSessionNumber;
379}
380
381KateDocumentConfig::KateDocumentConfig(KTextEditor::DocumentPrivate *doc)
382 : KateConfig(s_global)
383 , m_doc(doc)
384{
385 // per document config doesn't read stuff per default
386}
387
388void KateDocumentConfig::readConfig(const KConfigGroup &config)
389{
390 // start config update group
391 configStart();
392
393 // read generic entries
394 readConfigEntries(config);
395
396 // fixup sonnet config, see KateSpellCheckConfigTab::apply(), too
397 // WARNING: this is slightly hackish, but it's currently the only way to
398 // do it, see also the KTextEdit class
399 if (isGlobal()) {
400 const QSettings settings(QStringLiteral("KDE"), QStringLiteral("Sonnet"));
401 const bool onTheFlyChecking = settings.value(QStringLiteral("checkerEnabledByDefault"), defaultValue: false).toBool();
402 setOnTheFlySpellCheck(onTheFlyChecking);
403
404 // ensure we load the default dictionary speller + trigrams early
405 // this avoids hangs for auto-spellchecking on first edits
406 // do this if we have on the fly spellchecking on only
407 if (onTheFlyChecking) {
408 Sonnet::Speller speller;
409 speller.setLanguage(Sonnet::Speller().defaultLanguage());
410 speller.isMisspelled(QStringLiteral("dummy to trigger dictionary load"));
411 Sonnet::GuessLanguage languageGuesser;
412 languageGuesser.identify(QStringLiteral("dummy to trigger identify"));
413 }
414 }
415
416 // backwards compatibility mappings
417 // convert stuff, old entries deleted in writeConfig
418 if (const int backupFlags = config.readEntry(key: "Backup Flags", defaultValue: 0)) {
419 setBackupOnSaveLocal(backupFlags & 0x1);
420 setBackupOnSaveRemote(backupFlags & 0x2);
421 }
422
423 // end config update group, might trigger updateConfig()
424 configEnd();
425}
426
427void KateDocumentConfig::writeConfig(KConfigGroup &config)
428{
429 // write generic entries
430 writeConfigEntries(config);
431
432 // backwards compatibility mappings
433 // here we remove old entries we converted on readConfig
434 config.deleteEntry(key: "Backup Flags");
435}
436
437void KateDocumentConfig::updateConfig()
438{
439 if (m_doc) {
440 m_doc->updateConfig();
441 return;
442 }
443
444 if (isGlobal()) {
445 const auto docs = KTextEditor::EditorPrivate::self()->documents();
446 for (auto doc : docs) {
447 static_cast<KTextEditor::DocumentPrivate *>(doc)->updateConfig();
448 }
449
450 // write config
451 KConfigGroup cg(KTextEditor::EditorPrivate::config(), QStringLiteral("KTextEditor Document"));
452 writeConfig(config&: cg);
453 KTextEditor::EditorPrivate::config()->sync();
454
455 // trigger emission of KTextEditor::Editor::configChanged
456 KTextEditor::EditorPrivate::self()->triggerConfigChanged();
457 }
458}
459
460QString KateDocumentConfig::eolString() const
461{
462 switch (eol()) {
463 case KateDocumentConfig::eolDos:
464 return QStringLiteral("\r\n");
465
466 case KateDocumentConfig::eolMac:
467 return QStringLiteral("\r");
468
469 default:
470 return QStringLiteral("\n");
471 }
472}
473// END
474
475// BEGIN KateViewConfig
476KateViewConfig::KateViewConfig()
477{
478 // register this as our global instance
479 Q_ASSERT(isGlobal());
480 s_global = this;
481
482 // avoid updateConfig effects like config write in constructor, see bug 377067
483 Q_ASSERT(configSessionNumber == 0);
484 ++configSessionNumber;
485
486 // Init all known config entries
487 // NOTE: Ensure to keep the same order as listed in enum ConfigEntryTypes or it will later assert!
488 // addConfigEntry(ConfigEntry(<EnumKey>, <ConfigKey>, <CommandName>, <DefaultValue>, [<ValidatorFunction>]))
489 addConfigEntry(entry: ConfigEntry(AllowMarkMenu, "Allow Mark Menu", QStringLiteral("allow-mark-menu"), true));
490 addConfigEntry(entry: ConfigEntry(AutoBrackets, "Auto Brackets", QStringLiteral("auto-brackets"), true));
491 addConfigEntry(entry: ConfigEntry(AutoCenterLines, "Auto Center Lines", QStringLiteral("auto-center-lines"), 0));
492 addConfigEntry(entry: ConfigEntry(AutomaticCompletionInvocation, "Auto Completion", QString(), true));
493 addConfigEntry(entry: ConfigEntry(AutomaticCompletionPreselectFirst, "Auto Completion Preselect First Entry", QString(), true));
494 addConfigEntry(entry: ConfigEntry(BackspaceRemoveComposedCharacters, "Backspace Remove Composed Characters", QString(), false));
495 addConfigEntry(entry: ConfigEntry(BookmarkSorting, "Bookmark Menu Sorting", QString(), 0));
496 addConfigEntry(entry: ConfigEntry(CharsToEncloseSelection, "Chars To Enclose Selection", QStringLiteral("enclose-selection"), QStringLiteral("<>(){}[]'\"")));
497 addConfigEntry(entry: ConfigEntry(ClipboardHistoryEntries, "Max Clipboard History Entries", QString(), 20, [](const QVariant &value) {
498 return inBounds(min: 1, value, max: 999);
499 }));
500 addConfigEntry(
501 entry: ConfigEntry(DefaultMarkType, "Default Mark Type", QStringLiteral("default-mark-type"), KTextEditor::Document::markType01, [](const QVariant &value) {
502 return isPositive(value);
503 }));
504 addConfigEntry(entry: ConfigEntry(DynWordWrapAlignIndent, "Dynamic Word Wrap Align Indent", QString(), 80, [](const QVariant &value) {
505 return inBounds(min: 0, value, max: 100);
506 }));
507 addConfigEntry(entry: ConfigEntry(DynWordWrapIndicators, "Dynamic Word Wrap Indicators", QString(), 1, [](const QVariant &value) {
508 return inBounds(min: 0, value, max: 2);
509 }));
510 addConfigEntry(entry: ConfigEntry(DynWrapAnywhere, "Dynamic Wrap not at word boundaries", QStringLiteral("dynamic-word-wrap-anywhere"), false));
511 addConfigEntry(entry: ConfigEntry(DynWrapAtStaticMarker, "Dynamic Word Wrap At Static Marker", QString(), false));
512 addConfigEntry(entry: ConfigEntry(DynamicWordWrap, "Dynamic Word Wrap", QStringLiteral("dynamic-word-wrap"), true));
513 addConfigEntry(entry: ConfigEntry(EnterToInsertCompletion, "Enter To Insert Completion", QStringLiteral("enter-to-insert-completion"), true));
514 addConfigEntry(entry: ConfigEntry(FoldFirstLine, "Fold First Line", QString(), false));
515 addConfigEntry(entry: ConfigEntry(InputMode, "Input Mode", QString(), 0, [](const QVariant &value) {
516 return isPositive(value);
517 }));
518 addConfigEntry(entry: ConfigEntry(KeywordCompletion, "Keyword Completion", QStringLiteral("keyword-completion"), true));
519 addConfigEntry(entry: ConfigEntry(MaxHistorySize, "Maximum Search History Size", QString(), 100, [](const QVariant &value) {
520 return inBounds(min: 0, value, max: 999);
521 }));
522 addConfigEntry(entry: ConfigEntry(MousePasteAtCursorPosition, "Mouse Paste At Cursor Position", QString(), false));
523 addConfigEntry(entry: ConfigEntry(PersistentSelection, "Persistent Selection", QStringLiteral("persistent-selectionq"), false));
524 addConfigEntry(entry: ConfigEntry(ScrollBarMiniMapWidth, "Scroll Bar Mini Map Width", QString(), 60, [](const QVariant &value) {
525 return inBounds(min: 0, value, max: 999);
526 }));
527 addConfigEntry(entry: ConfigEntry(ScrollPastEnd, "Scroll Past End", QString(), false));
528 addConfigEntry(entry: ConfigEntry(SearchFlags, "Search/Replace Flags", QString(), IncFromCursor | PowerMatchCase | PowerModePlainText));
529 addConfigEntry(entry: ConfigEntry(TabCompletion, "Enable Tab completion", QString(), false));
530 addConfigEntry(entry: ConfigEntry(ShowBracketMatchPreview, "Bracket Match Preview", QStringLiteral("bracket-match-preview"), false));
531 addConfigEntry(entry: ConfigEntry(ShowFoldingBar, "Folding Bar", QStringLiteral("folding-bar"), true));
532 addConfigEntry(entry: ConfigEntry(ShowFoldingPreview, "Folding Preview", QStringLiteral("folding-preview"), true));
533 addConfigEntry(entry: ConfigEntry(ShowIconBar, "Icon Bar", QStringLiteral("icon-bar"), false));
534 addConfigEntry(entry: ConfigEntry(ShowLineCount, "Show Line Count", QString(), false));
535 addConfigEntry(entry: ConfigEntry(ShowLineModification, "Line Modification", QStringLiteral("modification-markers"), true));
536 addConfigEntry(entry: ConfigEntry(ShowLineNumbers, "Line Numbers", QStringLiteral("line-numbers"), true));
537 addConfigEntry(entry: ConfigEntry(ShowScrollBarMarks, "Scroll Bar Marks", QString(), false));
538 addConfigEntry(entry: ConfigEntry(ShowScrollBarMiniMap, "Scroll Bar MiniMap", QStringLiteral("scrollbar-minimap"), true));
539 addConfigEntry(entry: ConfigEntry(ShowScrollBarMiniMapAll, "Scroll Bar Mini Map All", QString(), true));
540 addConfigEntry(entry: ConfigEntry(ShowScrollBarPreview, "Scroll Bar Preview", QStringLiteral("scrollbar-preview"), true));
541 addConfigEntry(entry: ConfigEntry(ShowScrollbars, "Show Scrollbars", QString(), AlwaysOn, [](const QVariant &value) {
542 return inBounds(min: 0, value, max: 2);
543 }));
544 addConfigEntry(entry: ConfigEntry(ShowWordCount, "Show Word Count", QString(), false));
545 addConfigEntry(entry: ConfigEntry(TextDragAndDrop, "Text Drag And Drop", QString(), true));
546 addConfigEntry(entry: ConfigEntry(SmartCopyCut, "Smart Copy Cut", QString(), true));
547 addConfigEntry(entry: ConfigEntry(UserSetsOfCharsToEncloseSelection, "User Sets Of Chars To Enclose Selection", QString(), QStringList()));
548 addConfigEntry(entry: ConfigEntry(ViInputModeStealKeys, "Vi Input Mode Steal Keys", QString(), false));
549 addConfigEntry(entry: ConfigEntry(ViRelativeLineNumbers, "Vi Relative Line Numbers", QString(), false));
550 addConfigEntry(entry: ConfigEntry(WordCompletion, "Word Completion", QString(), true));
551 addConfigEntry(entry: ConfigEntry(WordCompletionMinimalWordLength,
552 "Word Completion Minimal Word Length",
553 QStringLiteral("word-completion-minimal-word-length"),
554 3,
555 [](const QVariant &value) {
556 return inBounds(min: 0, value, max: 99);
557 }));
558 addConfigEntry(entry: ConfigEntry(WordCompletionRemoveTail, "Word Completion Remove Tail", QString(), true));
559 addConfigEntry(entry: ConfigEntry(ShowDocWithCompletion, "Show Documentation With Completion", QString(), true));
560 addConfigEntry(entry: ConfigEntry(MultiCursorModifier, "Multiple Cursor Modifier", QString(), (int)Qt::AltModifier));
561 addConfigEntry(entry: ConfigEntry(ShowFoldingOnHoverOnly, "Show Folding Icons On Hover Only", QString(), true));
562
563 // Statusbar stuff
564 addConfigEntry(entry: ConfigEntry(ShowStatusbarLineColumn, "Show Statusbar Line Column", QString(), true));
565 addConfigEntry(entry: ConfigEntry(ShowStatusbarDictionary, "Show Statusbar Dictionary", QString(), true));
566 addConfigEntry(entry: ConfigEntry(ShowStatusbarInputMode, "Show Statusbar Input Mode", QString(), true));
567 addConfigEntry(entry: ConfigEntry(ShowStatusbarHighlightingMode, "Show Statusbar Highlighting Mode", QString(), true));
568 addConfigEntry(entry: ConfigEntry(ShowStatusbarTabSettings, "Show Statusbar Tab Settings", QString(), true));
569 addConfigEntry(entry: ConfigEntry(ShowStatusbarFileEncoding, "Show File Encoding", QString(), true));
570 addConfigEntry(entry: ConfigEntry(StatusbarLineColumnCompact, "Statusbar Line Column Compact Mode", QString(), true));
571 addConfigEntry(entry: ConfigEntry(ShowStatusbarEOL, "Shoe Line Ending Type in Statusbar", QString(), false));
572 addConfigEntry(entry: ConfigEntry(EnableAccessibility, "Enable Accessibility", QString(), true));
573 addConfigEntry(entry: ConfigEntry(CycleThroughBookmarks, "Cycle Through Bookmarks", QString(), true));
574
575 // Never forget to finalize or the <CommandName> becomes not available
576 finalizeConfigEntries();
577
578 // init with defaults from config or really hardcoded ones
579 KConfigGroup config(KTextEditor::EditorPrivate::config(), QStringLiteral("KTextEditor View"));
580 readConfig(config);
581
582 // avoid updateConfig effects like config write in constructor, see bug 377067
583 Q_ASSERT(configSessionNumber == 1);
584 --configSessionNumber;
585}
586
587KateViewConfig::KateViewConfig(KTextEditor::ViewPrivate *view)
588 : KateConfig(s_global)
589 , m_view(view)
590{
591}
592
593KateViewConfig::~KateViewConfig() = default;
594
595void KateViewConfig::readConfig(const KConfigGroup &config)
596{
597 configStart();
598
599 // read generic entries
600 readConfigEntries(config);
601
602 configEnd();
603}
604
605void KateViewConfig::writeConfig(KConfigGroup &config)
606{
607 // write generic entries
608 writeConfigEntries(config);
609}
610
611void KateViewConfig::updateConfig()
612{
613 if (m_view) {
614 m_view->updateConfig();
615 return;
616 }
617
618 if (isGlobal()) {
619 for (KTextEditor::ViewPrivate *view : KTextEditor::EditorPrivate::self()->views()) {
620 view->updateConfig();
621 }
622
623 // write config
624 KConfigGroup cg(KTextEditor::EditorPrivate::config(), QStringLiteral("KTextEditor View"));
625 writeConfig(config&: cg);
626 KTextEditor::EditorPrivate::config()->sync();
627
628 // trigger emission of KTextEditor::Editor::configChanged
629 KTextEditor::EditorPrivate::self()->triggerConfigChanged();
630 }
631}
632// END
633
634// BEGIN KateRendererConfig
635KateRendererConfig::KateRendererConfig()
636 : m_lineMarkerColor(KTextEditor::Document::reservedMarkersCount())
637 , m_schemaSet(false)
638 , m_fontSet(false)
639 , m_wordWrapMarkerSet(false)
640 , m_showIndentationLinesSet(false)
641 , m_showWholeBracketExpressionSet(false)
642 , m_backgroundColorSet(false)
643 , m_selectionColorSet(false)
644 , m_highlightedLineColorSet(false)
645 , m_highlightedBracketColorSet(false)
646 , m_wordWrapMarkerColorSet(false)
647 , m_tabMarkerColorSet(false)
648 , m_indentationLineColorSet(false)
649 , m_iconBarColorSet(false)
650 , m_foldingColorSet(false)
651 , m_lineNumberColorSet(false)
652 , m_currentLineNumberColorSet(false)
653 , m_separatorColorSet(false)
654 , m_spellingMistakeLineColorSet(false)
655 , m_templateColorsSet(false)
656 , m_modifiedLineColorSet(false)
657 , m_savedLineColorSet(false)
658 , m_searchHighlightColorSet(false)
659 , m_replaceHighlightColorSet(false)
660 , m_lineMarkerColorSet(m_lineMarkerColor.size())
661
662{
663 // init bitarray
664 m_lineMarkerColorSet.fill(aval: true);
665
666 // register this as our global instance
667 Q_ASSERT(isGlobal());
668 s_global = this;
669
670 // avoid updateConfig effects like config write in constructor, see bug 377067
671 Q_ASSERT(configSessionNumber == 0);
672 ++configSessionNumber;
673
674 // Init all known config entries
675 addConfigEntry(entry: ConfigEntry(AutoColorThemeSelection, "Auto Color Theme Selection", QString(), true));
676
677 // Never forget to finalize or the <CommandName> becomes not available
678 finalizeConfigEntries();
679
680 // init with defaults from config or really hardcoded ones
681 KConfigGroup config(KTextEditor::EditorPrivate::config(), QStringLiteral("KTextEditor Renderer"));
682 readConfig(config);
683
684 // avoid updateConfig effects like config write in constructor, see bug 377067
685 Q_ASSERT(configSessionNumber == 1);
686 --configSessionNumber;
687}
688
689KateRendererConfig::KateRendererConfig(KateRenderer *renderer)
690 : KateConfig(s_global)
691 , m_lineMarkerColor(KTextEditor::Document::reservedMarkersCount())
692 , m_schemaSet(false)
693 , m_fontSet(false)
694 , m_wordWrapMarkerSet(false)
695 , m_showIndentationLinesSet(false)
696 , m_showWholeBracketExpressionSet(false)
697 , m_backgroundColorSet(false)
698 , m_selectionColorSet(false)
699 , m_highlightedLineColorSet(false)
700 , m_highlightedBracketColorSet(false)
701 , m_wordWrapMarkerColorSet(false)
702 , m_tabMarkerColorSet(false)
703 , m_indentationLineColorSet(false)
704 , m_iconBarColorSet(false)
705 , m_foldingColorSet(false)
706 , m_lineNumberColorSet(false)
707 , m_currentLineNumberColorSet(false)
708 , m_separatorColorSet(false)
709 , m_spellingMistakeLineColorSet(false)
710 , m_templateColorsSet(false)
711 , m_modifiedLineColorSet(false)
712 , m_savedLineColorSet(false)
713 , m_searchHighlightColorSet(false)
714 , m_replaceHighlightColorSet(false)
715 , m_lineMarkerColorSet(m_lineMarkerColor.size())
716 , m_renderer(renderer)
717{
718 // init bitarray
719 m_lineMarkerColorSet.fill(aval: false);
720}
721
722KateRendererConfig::~KateRendererConfig() = default;
723
724namespace
725{
726const char KEY_FONT[] = "Text Font";
727const char KEY_FONT_FEATURES[] = "Text Font Features";
728const char KEY_COLOR_THEME[] = "Color Theme";
729const char KEY_WORD_WRAP_MARKER[] = "Word Wrap Marker";
730const char KEY_SHOW_INDENTATION_LINES[] = "Show Indentation Lines";
731const char KEY_SHOW_WHOLE_BRACKET_EXPRESSION[] = "Show Whole Bracket Expression";
732const char KEY_ANIMATE_BRACKET_MATCHING[] = "Animate Bracket Matching";
733const char KEY_LINE_HEIGHT_MULTIPLIER[] = "Line Height Multiplier";
734}
735
736void KateRendererConfig::readConfig(const KConfigGroup &config)
737{
738 configStart();
739
740 // read generic entries
741 readConfigEntries(config);
742
743 // read font, including font features
744 auto font = config.readEntry(key: KEY_FONT, defaultValue: QFontDatabase::systemFont(type: QFontDatabase::FixedFont));
745 const QStringList rawFeaturesList = config.readEntry(key: KEY_FONT_FEATURES, aDefault: QStringList());
746 for (const QString &feature : rawFeaturesList) {
747 const auto parts = feature.split(QStringLiteral("="), behavior: Qt::SkipEmptyParts);
748 if (parts.length() == 2) {
749 const auto tag = QFont::Tag::fromString(view: parts[0]);
750 bool ok = false;
751 const int number = parts[1].toInt(ok: &ok);
752 if (tag.has_value() && ok) {
753 font.setFeature(tag: tag.value(), value: number);
754 }
755 }
756 }
757 setFont(font);
758
759 // setSchema will default to right theme
760 setSchema(config.readEntry(key: KEY_COLOR_THEME, aDefault: QString()));
761
762 setWordWrapMarker(config.readEntry(key: KEY_WORD_WRAP_MARKER, defaultValue: false));
763
764 setShowIndentationLines(config.readEntry(key: KEY_SHOW_INDENTATION_LINES, defaultValue: false));
765
766 setShowWholeBracketExpression(config.readEntry(key: KEY_SHOW_WHOLE_BRACKET_EXPRESSION, defaultValue: false));
767
768 setAnimateBracketMatching(config.readEntry(key: KEY_ANIMATE_BRACKET_MATCHING, defaultValue: false));
769
770 setLineHeightMultiplier(config.readEntry<qreal>(key: KEY_LINE_HEIGHT_MULTIPLIER, defaultValue: 1.0));
771
772 configEnd();
773}
774
775void KateRendererConfig::writeConfig(KConfigGroup &config)
776{
777 // write generic entries
778 writeConfigEntries(config);
779
780 // write font, including font features
781 const auto font = baseFont();
782 config.writeEntry(key: KEY_FONT, value: font);
783 const auto tags = font.featureTags();
784 QStringList features;
785 for (const auto &tag : tags) {
786 const QString name = QString::fromUtf8(ba: tag.toString());
787 const quint32 value = font.featureValue(tag);
788 features.push_back(QStringLiteral("%1=%2").arg(args: name, args: QString::number(value)));
789 }
790 config.writeEntry(key: KEY_FONT_FEATURES, value: features);
791
792 config.writeEntry(key: KEY_COLOR_THEME, value: schema());
793
794 config.writeEntry(key: KEY_WORD_WRAP_MARKER, value: wordWrapMarker());
795
796 config.writeEntry(key: KEY_SHOW_INDENTATION_LINES, value: showIndentationLines());
797
798 config.writeEntry(key: KEY_SHOW_WHOLE_BRACKET_EXPRESSION, value: showWholeBracketExpression());
799
800 config.writeEntry(key: KEY_ANIMATE_BRACKET_MATCHING, value: animateBracketMatching());
801
802 config.writeEntry<qreal>(key: KEY_LINE_HEIGHT_MULTIPLIER, value: lineHeightMultiplier());
803}
804
805void KateRendererConfig::updateConfig()
806{
807 if (m_renderer) {
808 m_renderer->updateConfig();
809 return;
810 }
811
812 if (isGlobal()) {
813 for (auto view : KTextEditor::EditorPrivate::self()->views()) {
814 view->renderer()->updateConfig();
815 }
816
817 // write config
818 KConfigGroup cg(KTextEditor::EditorPrivate::config(), QStringLiteral("KTextEditor Renderer"));
819 writeConfig(config&: cg);
820 KTextEditor::EditorPrivate::config()->sync();
821
822 // trigger emission of KTextEditor::Editor::configChanged
823 KTextEditor::EditorPrivate::self()->triggerConfigChanged();
824 }
825}
826
827const QString &KateRendererConfig::schema() const
828{
829 if (m_schemaSet || isGlobal()) {
830 return m_schema;
831 }
832
833 return s_global->schema();
834}
835
836void KateRendererConfig::setSchema(QString schema)
837{
838 // check if we have some matching theme, else fallback to best theme for current palette
839 // same behavior as for the "Automatic Color Theme Selection"
840 if (!KateHlManager::self()->repository().theme(themeName: schema).isValid()) {
841 schema = KateHlManager::self()->repository().themeForPalette(qGuiApp->palette()).name();
842 }
843
844 if (m_schemaSet && m_schema == schema) {
845 return;
846 }
847
848 configStart();
849 m_schemaSet = true;
850 m_schema = schema;
851 setSchemaInternal(m_schema);
852 configEnd();
853}
854
855void KateRendererConfig::reloadSchema()
856{
857 if (isGlobal()) {
858 setSchemaInternal(m_schema);
859 for (KTextEditor::ViewPrivate *view : KTextEditor::EditorPrivate::self()->views()) {
860 view->rendererConfig()->reloadSchema();
861 }
862 }
863
864 else if (m_renderer && m_schemaSet) {
865 setSchemaInternal(m_schema);
866 }
867
868 // trigger renderer/view update
869 if (m_renderer) {
870 m_renderer->updateConfig();
871 }
872}
873
874void KateRendererConfig::setSchemaInternal(const QString &schema)
875{
876 // we always set the theme if we arrive here!
877 m_schemaSet = true;
878
879 // for the global config, we honor the auto selection based on the palette
880 // do the same if the set theme really doesn't exist, we need a valid theme or the rendering will be broken in bad ways!
881 if ((isGlobal() && value(key: AutoColorThemeSelection).toBool()) || !KateHlManager::self()->repository().theme(themeName: schema).isValid()) {
882 // always choose some theme matching the current application palette
883 // we will arrive here after palette changed signals, too!
884 m_schema = KateHlManager::self()->repository().themeForPalette(qGuiApp->palette()).name();
885 } else {
886 // take user given theme 1:1
887 m_schema = schema;
888 }
889
890 const auto theme = KateHlManager::self()->repository().theme(themeName: m_schema);
891
892 m_backgroundColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::BackgroundColor));
893 m_backgroundColorSet = true;
894
895 m_selectionColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::TextSelection));
896 m_selectionColorSet = true;
897
898 m_highlightedLineColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::CurrentLine));
899 m_highlightedLineColorSet = true;
900
901 m_highlightedBracketColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::BracketMatching));
902 m_highlightedBracketColorSet = true;
903
904 m_wordWrapMarkerColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::WordWrapMarker));
905 m_wordWrapMarkerColorSet = true;
906
907 m_tabMarkerColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::TabMarker));
908 m_tabMarkerColorSet = true;
909
910 m_indentationLineColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::IndentationLine));
911 m_indentationLineColorSet = true;
912
913 m_iconBarColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::IconBorder));
914 m_iconBarColorSet = true;
915
916 m_foldingColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::CodeFolding));
917 m_foldingColorSet = true;
918
919 m_lineNumberColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::LineNumbers));
920 m_lineNumberColorSet = true;
921
922 m_currentLineNumberColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::CurrentLineNumber));
923 m_currentLineNumberColorSet = true;
924
925 m_separatorColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::Separator));
926 m_separatorColorSet = true;
927
928 m_spellingMistakeLineColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::SpellChecking));
929 m_spellingMistakeLineColorSet = true;
930
931 m_modifiedLineColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::ModifiedLines));
932 m_modifiedLineColorSet = true;
933
934 m_savedLineColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::SavedLines));
935 m_savedLineColorSet = true;
936
937 m_searchHighlightColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::SearchHighlight));
938 m_searchHighlightColorSet = true;
939
940 m_replaceHighlightColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::ReplaceHighlight));
941 m_replaceHighlightColorSet = true;
942
943 for (int i = 0; i <= KSyntaxHighlighting::Theme::MarkError - KSyntaxHighlighting::Theme::MarkBookmark; i++) {
944 QColor col =
945 QColor::fromRgba(rgba: theme.editorColor(role: static_cast<KSyntaxHighlighting::Theme::EditorColorRole>(i + KSyntaxHighlighting::Theme::MarkBookmark)));
946 m_lineMarkerColorSet[i] = true;
947 m_lineMarkerColor[i] = col;
948 }
949
950 m_templateBackgroundColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::TemplateBackground));
951
952 m_templateFocusedEditablePlaceholderColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::TemplateFocusedPlaceholder));
953
954 m_templateEditablePlaceholderColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::TemplatePlaceholder));
955
956 m_templateNotEditablePlaceholderColor = QColor::fromRgba(rgba: theme.editorColor(role: KSyntaxHighlighting::Theme::TemplateReadOnlyPlaceholder));
957
958 m_templateColorsSet = true;
959}
960
961const QFont &KateRendererConfig::baseFont() const
962{
963 if (m_fontSet || isGlobal()) {
964 return m_font;
965 }
966
967 return s_global->baseFont();
968}
969
970void KateRendererConfig::setFont(const QFont &font)
971{
972 if (m_fontSet && m_font == font) {
973 return;
974 }
975
976 configStart();
977 m_font = font;
978 m_fontSet = true;
979 configEnd();
980}
981
982bool KateRendererConfig::wordWrapMarker() const
983{
984 if (m_wordWrapMarkerSet || isGlobal()) {
985 return m_wordWrapMarker;
986 }
987
988 return s_global->wordWrapMarker();
989}
990
991void KateRendererConfig::setWordWrapMarker(bool on)
992{
993 if (m_wordWrapMarkerSet && m_wordWrapMarker == on) {
994 return;
995 }
996
997 configStart();
998
999 m_wordWrapMarkerSet = true;
1000 m_wordWrapMarker = on;
1001
1002 configEnd();
1003}
1004
1005const QColor &KateRendererConfig::backgroundColor() const
1006{
1007 if (m_backgroundColorSet || isGlobal()) {
1008 return m_backgroundColor;
1009 }
1010
1011 return s_global->backgroundColor();
1012}
1013
1014void KateRendererConfig::setBackgroundColor(const QColor &col)
1015{
1016 if (m_backgroundColorSet && m_backgroundColor == col) {
1017 return;
1018 }
1019
1020 configStart();
1021
1022 m_backgroundColorSet = true;
1023 m_backgroundColor = col;
1024
1025 configEnd();
1026}
1027
1028const QColor &KateRendererConfig::selectionColor() const
1029{
1030 if (m_selectionColorSet || isGlobal()) {
1031 return m_selectionColor;
1032 }
1033
1034 return s_global->selectionColor();
1035}
1036
1037void KateRendererConfig::setSelectionColor(const QColor &col)
1038{
1039 if (m_selectionColorSet && m_selectionColor == col) {
1040 return;
1041 }
1042
1043 configStart();
1044
1045 m_selectionColorSet = true;
1046 m_selectionColor = col;
1047
1048 configEnd();
1049}
1050
1051const QColor &KateRendererConfig::highlightedLineColor() const
1052{
1053 if (m_highlightedLineColorSet || isGlobal()) {
1054 return m_highlightedLineColor;
1055 }
1056
1057 return s_global->highlightedLineColor();
1058}
1059
1060void KateRendererConfig::setHighlightedLineColor(const QColor &col)
1061{
1062 if (m_highlightedLineColorSet && m_highlightedLineColor == col) {
1063 return;
1064 }
1065
1066 configStart();
1067
1068 m_highlightedLineColorSet = true;
1069 m_highlightedLineColor = col;
1070
1071 configEnd();
1072}
1073
1074const QColor &KateRendererConfig::lineMarkerColor(KTextEditor::Document::MarkTypes type) const
1075{
1076 int index = 0;
1077 if (type > 0) {
1078 while ((type >> index++) ^ 1) { }
1079 }
1080 index -= 1;
1081
1082 if (index < 0 || index >= KTextEditor::Document::reservedMarkersCount()) {
1083 static QColor dummy;
1084 return dummy;
1085 }
1086
1087 if (m_lineMarkerColorSet[index] || isGlobal()) {
1088 return m_lineMarkerColor[index];
1089 }
1090
1091 return s_global->lineMarkerColor(type);
1092}
1093
1094const QColor &KateRendererConfig::highlightedBracketColor() const
1095{
1096 if (m_highlightedBracketColorSet || isGlobal()) {
1097 return m_highlightedBracketColor;
1098 }
1099
1100 return s_global->highlightedBracketColor();
1101}
1102
1103void KateRendererConfig::setHighlightedBracketColor(const QColor &col)
1104{
1105 if (m_highlightedBracketColorSet && m_highlightedBracketColor == col) {
1106 return;
1107 }
1108
1109 configStart();
1110
1111 m_highlightedBracketColorSet = true;
1112 m_highlightedBracketColor = col;
1113
1114 configEnd();
1115}
1116
1117const QColor &KateRendererConfig::wordWrapMarkerColor() const
1118{
1119 if (m_wordWrapMarkerColorSet || isGlobal()) {
1120 return m_wordWrapMarkerColor;
1121 }
1122
1123 return s_global->wordWrapMarkerColor();
1124}
1125
1126void KateRendererConfig::setWordWrapMarkerColor(const QColor &col)
1127{
1128 if (m_wordWrapMarkerColorSet && m_wordWrapMarkerColor == col) {
1129 return;
1130 }
1131
1132 configStart();
1133
1134 m_wordWrapMarkerColorSet = true;
1135 m_wordWrapMarkerColor = col;
1136
1137 configEnd();
1138}
1139
1140const QColor &KateRendererConfig::tabMarkerColor() const
1141{
1142 if (m_tabMarkerColorSet || isGlobal()) {
1143 return m_tabMarkerColor;
1144 }
1145
1146 return s_global->tabMarkerColor();
1147}
1148
1149void KateRendererConfig::setTabMarkerColor(const QColor &col)
1150{
1151 if (m_tabMarkerColorSet && m_tabMarkerColor == col) {
1152 return;
1153 }
1154
1155 configStart();
1156
1157 m_tabMarkerColorSet = true;
1158 m_tabMarkerColor = col;
1159
1160 configEnd();
1161}
1162
1163const QColor &KateRendererConfig::indentationLineColor() const
1164{
1165 if (m_indentationLineColorSet || isGlobal()) {
1166 return m_indentationLineColor;
1167 }
1168
1169 return s_global->indentationLineColor();
1170}
1171
1172void KateRendererConfig::setIndentationLineColor(const QColor &col)
1173{
1174 if (m_indentationLineColorSet && m_indentationLineColor == col) {
1175 return;
1176 }
1177
1178 configStart();
1179
1180 m_indentationLineColorSet = true;
1181 m_indentationLineColor = col;
1182
1183 configEnd();
1184}
1185
1186const QColor &KateRendererConfig::iconBarColor() const
1187{
1188 if (m_iconBarColorSet || isGlobal()) {
1189 return m_iconBarColor;
1190 }
1191
1192 return s_global->iconBarColor();
1193}
1194
1195void KateRendererConfig::setIconBarColor(const QColor &col)
1196{
1197 if (m_iconBarColorSet && m_iconBarColor == col) {
1198 return;
1199 }
1200
1201 configStart();
1202
1203 m_iconBarColorSet = true;
1204 m_iconBarColor = col;
1205
1206 configEnd();
1207}
1208
1209const QColor &KateRendererConfig::foldingColor() const
1210{
1211 if (m_foldingColorSet || isGlobal()) {
1212 return m_foldingColor;
1213 }
1214
1215 return s_global->foldingColor();
1216}
1217
1218void KateRendererConfig::setFoldingColor(const QColor &col)
1219{
1220 if (m_foldingColorSet && m_foldingColor == col) {
1221 return;
1222 }
1223
1224 configStart();
1225
1226 m_foldingColorSet = true;
1227 m_foldingColor = col;
1228
1229 configEnd();
1230}
1231
1232const QColor &KateRendererConfig::templateBackgroundColor() const
1233{
1234 if (m_templateColorsSet || isGlobal()) {
1235 return m_templateBackgroundColor;
1236 }
1237
1238 return s_global->templateBackgroundColor();
1239}
1240
1241const QColor &KateRendererConfig::templateEditablePlaceholderColor() const
1242{
1243 if (m_templateColorsSet || isGlobal()) {
1244 return m_templateEditablePlaceholderColor;
1245 }
1246
1247 return s_global->templateEditablePlaceholderColor();
1248}
1249
1250const QColor &KateRendererConfig::templateFocusedEditablePlaceholderColor() const
1251{
1252 if (m_templateColorsSet || isGlobal()) {
1253 return m_templateFocusedEditablePlaceholderColor;
1254 }
1255
1256 return s_global->templateFocusedEditablePlaceholderColor();
1257}
1258
1259const QColor &KateRendererConfig::templateNotEditablePlaceholderColor() const
1260{
1261 if (m_templateColorsSet || isGlobal()) {
1262 return m_templateNotEditablePlaceholderColor;
1263 }
1264
1265 return s_global->templateNotEditablePlaceholderColor();
1266}
1267
1268const QColor &KateRendererConfig::lineNumberColor() const
1269{
1270 if (m_lineNumberColorSet || isGlobal()) {
1271 return m_lineNumberColor;
1272 }
1273
1274 return s_global->lineNumberColor();
1275}
1276
1277void KateRendererConfig::setLineNumberColor(const QColor &col)
1278{
1279 if (m_lineNumberColorSet && m_lineNumberColor == col) {
1280 return;
1281 }
1282
1283 configStart();
1284
1285 m_lineNumberColorSet = true;
1286 m_lineNumberColor = col;
1287
1288 configEnd();
1289}
1290
1291const QColor &KateRendererConfig::currentLineNumberColor() const
1292{
1293 if (m_currentLineNumberColorSet || isGlobal()) {
1294 return m_currentLineNumberColor;
1295 }
1296
1297 return s_global->currentLineNumberColor();
1298}
1299
1300void KateRendererConfig::setCurrentLineNumberColor(const QColor &col)
1301{
1302 if (m_currentLineNumberColorSet && m_currentLineNumberColor == col) {
1303 return;
1304 }
1305
1306 configStart();
1307
1308 m_currentLineNumberColorSet = true;
1309 m_currentLineNumberColor = col;
1310
1311 configEnd();
1312}
1313
1314const QColor &KateRendererConfig::separatorColor() const
1315{
1316 if (m_separatorColorSet || isGlobal()) {
1317 return m_separatorColor;
1318 }
1319
1320 return s_global->separatorColor();
1321}
1322
1323void KateRendererConfig::setSeparatorColor(const QColor &col)
1324{
1325 if (m_separatorColorSet && m_separatorColor == col) {
1326 return;
1327 }
1328
1329 configStart();
1330
1331 m_separatorColorSet = true;
1332 m_separatorColor = col;
1333
1334 configEnd();
1335}
1336
1337const QColor &KateRendererConfig::spellingMistakeLineColor() const
1338{
1339 if (m_spellingMistakeLineColorSet || isGlobal()) {
1340 return m_spellingMistakeLineColor;
1341 }
1342
1343 return s_global->spellingMistakeLineColor();
1344}
1345
1346void KateRendererConfig::setSpellingMistakeLineColor(const QColor &col)
1347{
1348 if (m_spellingMistakeLineColorSet && m_spellingMistakeLineColor == col) {
1349 return;
1350 }
1351
1352 configStart();
1353
1354 m_spellingMistakeLineColorSet = true;
1355 m_spellingMistakeLineColor = col;
1356
1357 configEnd();
1358}
1359
1360const QColor &KateRendererConfig::modifiedLineColor() const
1361{
1362 if (m_modifiedLineColorSet || isGlobal()) {
1363 return m_modifiedLineColor;
1364 }
1365
1366 return s_global->modifiedLineColor();
1367}
1368
1369void KateRendererConfig::setModifiedLineColor(const QColor &col)
1370{
1371 if (m_modifiedLineColorSet && m_modifiedLineColor == col) {
1372 return;
1373 }
1374
1375 configStart();
1376
1377 m_modifiedLineColorSet = true;
1378 m_modifiedLineColor = col;
1379
1380 configEnd();
1381}
1382
1383const QColor &KateRendererConfig::savedLineColor() const
1384{
1385 if (m_savedLineColorSet || isGlobal()) {
1386 return m_savedLineColor;
1387 }
1388
1389 return s_global->savedLineColor();
1390}
1391
1392void KateRendererConfig::setSavedLineColor(const QColor &col)
1393{
1394 if (m_savedLineColorSet && m_savedLineColor == col) {
1395 return;
1396 }
1397
1398 configStart();
1399
1400 m_savedLineColorSet = true;
1401 m_savedLineColor = col;
1402
1403 configEnd();
1404}
1405
1406const QColor &KateRendererConfig::searchHighlightColor() const
1407{
1408 if (m_searchHighlightColorSet || isGlobal()) {
1409 return m_searchHighlightColor;
1410 }
1411
1412 return s_global->searchHighlightColor();
1413}
1414
1415void KateRendererConfig::setSearchHighlightColor(const QColor &col)
1416{
1417 if (m_searchHighlightColorSet && m_searchHighlightColor == col) {
1418 return;
1419 }
1420
1421 configStart();
1422
1423 m_searchHighlightColorSet = true;
1424 m_searchHighlightColor = col;
1425
1426 configEnd();
1427}
1428
1429const QColor &KateRendererConfig::replaceHighlightColor() const
1430{
1431 if (m_replaceHighlightColorSet || isGlobal()) {
1432 return m_replaceHighlightColor;
1433 }
1434
1435 return s_global->replaceHighlightColor();
1436}
1437
1438void KateRendererConfig::setReplaceHighlightColor(const QColor &col)
1439{
1440 if (m_replaceHighlightColorSet && m_replaceHighlightColor == col) {
1441 return;
1442 }
1443
1444 configStart();
1445
1446 m_replaceHighlightColorSet = true;
1447 m_replaceHighlightColor = col;
1448
1449 configEnd();
1450}
1451
1452void KateRendererConfig::setLineHeightMultiplier(qreal value)
1453{
1454 configStart();
1455 m_lineHeightMultiplier = value;
1456 configEnd();
1457}
1458
1459bool KateRendererConfig::showIndentationLines() const
1460{
1461 if (m_showIndentationLinesSet || isGlobal()) {
1462 return m_showIndentationLines;
1463 }
1464
1465 return s_global->showIndentationLines();
1466}
1467
1468void KateRendererConfig::setShowIndentationLines(bool on)
1469{
1470 if (m_showIndentationLinesSet && m_showIndentationLines == on) {
1471 return;
1472 }
1473
1474 configStart();
1475
1476 m_showIndentationLinesSet = true;
1477 m_showIndentationLines = on;
1478
1479 configEnd();
1480}
1481
1482bool KateRendererConfig::showWholeBracketExpression() const
1483{
1484 if (m_showWholeBracketExpressionSet || isGlobal()) {
1485 return m_showWholeBracketExpression;
1486 }
1487
1488 return s_global->showWholeBracketExpression();
1489}
1490
1491void KateRendererConfig::setShowWholeBracketExpression(bool on)
1492{
1493 if (m_showWholeBracketExpressionSet && m_showWholeBracketExpression == on) {
1494 return;
1495 }
1496
1497 configStart();
1498
1499 m_showWholeBracketExpressionSet = true;
1500 m_showWholeBracketExpression = on;
1501
1502 configEnd();
1503}
1504
1505bool KateRendererConfig::animateBracketMatching()
1506{
1507 return s_global->m_animateBracketMatching;
1508}
1509
1510void KateRendererConfig::setAnimateBracketMatching(bool on)
1511{
1512 if (!isGlobal()) {
1513 s_global->setAnimateBracketMatching(on);
1514 } else if (on != m_animateBracketMatching) {
1515 configStart();
1516 m_animateBracketMatching = on;
1517 configEnd();
1518 }
1519}
1520
1521// END
1522

source code of ktexteditor/src/utils/kateconfig.cpp