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