File indexing completed on 2024-04-14 03:55:29

0001 /*
0002     SPDX-FileCopyrightText: 2007, 2008 Matthew Woehlke <mw_triad@users.sourceforge.net>
0003     SPDX-FileCopyrightText: 2003 Christoph Cullmann <cullmann@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "kateconfig.h"
0009 
0010 #include "katedocument.h"
0011 #include "kateglobal.h"
0012 #include "katepartdebug.h"
0013 #include "katerenderer.h"
0014 #include "katesyntaxmanager.h"
0015 #include "kateview.h"
0016 
0017 #include <KConfigGroup>
0018 
0019 #include <KEncodingProber>
0020 #include <QGuiApplication>
0021 #include <QSettings>
0022 #include <QStringDecoder>
0023 #include <QStringEncoder>
0024 #include <QStringListModel>
0025 
0026 #include <Sonnet/GuessLanguage>
0027 #include <Sonnet/Speller>
0028 
0029 // BEGIN KateConfig
0030 KateConfig::KateConfig(const KateConfig *parent)
0031     : m_parent(parent)
0032     , m_configKeys(m_parent ? nullptr : new QStringList())
0033     , m_configKeyToEntry(m_parent ? nullptr : new QHash<QString, const ConfigEntry *>())
0034 {
0035 }
0036 
0037 KateConfig::~KateConfig() = default;
0038 
0039 void KateConfig::addConfigEntry(ConfigEntry &&entry)
0040 {
0041     // shall only be called for toplevel config
0042     Q_ASSERT(isGlobal());
0043 
0044     // There shall be no gaps in the entries; i.e. in KateViewConfig constructor
0045     // addConfigEntry() is called on each value from the ConfigEntryTypes enum in
0046     // the same order as the enumrators.
0047     // we might later want to use a vector
0048     // qDebug() << m_configEntries.size() << entry.enumKey;
0049     Q_ASSERT(m_configEntries.size() == static_cast<size_t>(entry.enumKey));
0050 
0051     // add new element
0052     m_configEntries.emplace(entry.enumKey, entry);
0053 }
0054 
0055 void KateConfig::finalizeConfigEntries()
0056 {
0057     // shall only be called for toplevel config
0058     Q_ASSERT(isGlobal());
0059 
0060     // compute list of all config keys + register map from key => config entry
0061     //
0062     // we skip entries without a command name, these config entries are not exposed ATM
0063     for (const auto &entry : m_configEntries) {
0064         if (!entry.second.commandName.isEmpty()) {
0065             Q_ASSERT_X(!m_configKeys->contains(entry.second.commandName),
0066                        "finalizeConfigEntries",
0067                        (QLatin1String("KEY NOT UNIQUE: ") + entry.second.commandName).toLocal8Bit().constData());
0068             m_configKeys->append(entry.second.commandName);
0069             m_configKeyToEntry->insert(entry.second.commandName, &entry.second);
0070         }
0071     }
0072 }
0073 
0074 void KateConfig::readConfigEntries(const KConfigGroup &config)
0075 {
0076     configStart();
0077 
0078     // read all config entries, even the ones ATM not set in this config object but known in the toplevel one
0079     for (const auto &entry : fullConfigEntries()) {
0080         setValue(entry.second.enumKey, config.readEntry(entry.second.configKey, entry.second.defaultValue));
0081     }
0082 
0083     configEnd();
0084 }
0085 
0086 void KateConfig::writeConfigEntries(KConfigGroup &config) const
0087 {
0088     // write all config entries, even the ones ATM not set in this config object but known in the toplevel one
0089     for (const auto &entry : fullConfigEntries()) {
0090         config.writeEntry(entry.second.configKey, value(entry.second.enumKey));
0091     }
0092 }
0093 
0094 void KateConfig::configStart()
0095 {
0096     configSessionNumber++;
0097 
0098     if (configSessionNumber > 1) {
0099         return;
0100     }
0101 }
0102 
0103 void KateConfig::configEnd()
0104 {
0105     if (configSessionNumber == 0) {
0106         return;
0107     }
0108 
0109     configSessionNumber--;
0110 
0111     if (configSessionNumber > 0) {
0112         return;
0113     }
0114 
0115     updateConfig();
0116 }
0117 
0118 QVariant KateConfig::value(const int key) const
0119 {
0120     // first: local lookup
0121     const auto it = m_configEntries.find(key);
0122     if (it != m_configEntries.end()) {
0123         return it->second.value;
0124     }
0125 
0126     // else: fallback to parent config, if any
0127     if (m_parent) {
0128         return m_parent->value(key);
0129     }
0130 
0131     // if we arrive here, the key was invalid! => programming error
0132     // for release builds, we just return invalid variant
0133     Q_ASSERT(false);
0134     return QVariant();
0135 }
0136 
0137 bool KateConfig::setValue(const int key, const QVariant &value)
0138 {
0139     // check: is this key known at all?
0140     const auto &knownEntries = fullConfigEntries();
0141     const auto knownIt = knownEntries.find(key);
0142     if (knownIt == knownEntries.end()) {
0143         // if we arrive here, the key was invalid! => programming error
0144         // for release builds, we just fail to set the value
0145         Q_ASSERT(false);
0146         return false;
0147     }
0148 
0149     // validator set? use it, if not accepting, abort setting
0150     if (knownIt->second.validator && !knownIt->second.validator(value)) {
0151         return false;
0152     }
0153 
0154     // check if value already there for this config
0155     auto valueIt = m_configEntries.find(key);
0156     if (valueIt != m_configEntries.end()) {
0157         // skip any work if value is equal
0158         if (valueIt->second.value == value) {
0159             return true;
0160         }
0161 
0162         // else: alter value and be done
0163         configStart();
0164         valueIt->second.value = value;
0165         configEnd();
0166         return true;
0167     }
0168 
0169     // if not in this hash, we must copy the known entry and adjust the value
0170     configStart();
0171     auto res = m_configEntries.emplace(key, knownIt->second);
0172     res.first->second.value = value;
0173     configEnd();
0174     return true;
0175 }
0176 
0177 QVariant KateConfig::value(const QString &key) const
0178 {
0179     // check if we know this key, if not, return invalid variant
0180     const auto &knownEntries = fullConfigKeyToEntry();
0181     const auto it = knownEntries.find(key);
0182     if (it == knownEntries.end()) {
0183         return QVariant();
0184     }
0185 
0186     // key known, dispatch to normal value() function with enum
0187     return value(it.value()->enumKey);
0188 }
0189 
0190 bool KateConfig::setValue(const QString &key, const QVariant &value)
0191 {
0192     // check if we know this key, if not, ignore the set
0193     const auto &knownEntries = fullConfigKeyToEntry();
0194     const auto it = knownEntries.find(key);
0195     if (it == knownEntries.end()) {
0196         return false;
0197     }
0198 
0199     // key known, dispatch to normal setValue() function with enum
0200     return setValue(it.value()->enumKey, value);
0201 }
0202 
0203 // END
0204 
0205 // BEGIN HelperFunctions
0206 KateGlobalConfig *KateGlobalConfig::s_global = nullptr;
0207 KateDocumentConfig *KateDocumentConfig::s_global = nullptr;
0208 KateViewConfig *KateViewConfig::s_global = nullptr;
0209 KateRendererConfig *KateRendererConfig::s_global = nullptr;
0210 
0211 /**
0212  * validate if an encoding is ok
0213  * @param name encoding name
0214  * @return encoding ok?
0215  */
0216 static bool isEncodingOk(const QString &name)
0217 {
0218     return QStringDecoder(name.toUtf8().constData()).isValid() && QStringEncoder(name.toUtf8().constData()).isValid();
0219 }
0220 
0221 static bool inBounds(const int min, const QVariant &value, const int max)
0222 {
0223     const int val = value.toInt();
0224     return (val >= min) && (val <= max);
0225 }
0226 
0227 static bool isPositive(const QVariant &value)
0228 {
0229     bool ok;
0230     value.toUInt(&ok);
0231     return ok;
0232 }
0233 // END
0234 
0235 // BEGIN KateGlobalConfig
0236 KateGlobalConfig::KateGlobalConfig()
0237 {
0238     // register this as our global instance
0239     Q_ASSERT(isGlobal());
0240     s_global = this;
0241 
0242     // avoid updateConfig effects like config write in constructor, see bug 377067
0243     Q_ASSERT(configSessionNumber == 0);
0244     ++configSessionNumber;
0245 
0246     // init all known config entries
0247     addConfigEntry(ConfigEntry(EncodingProberType, "Encoding Prober Type", QString(), KEncodingProber::Universal));
0248     addConfigEntry(ConfigEntry(FallbackEncoding,
0249                                "Fallback Encoding",
0250                                QString(),
0251                                QString::fromUtf8(QStringConverter::nameForEncoding(QStringConverter::Latin1)),
0252                                [](const QVariant &value) {
0253                                    return isEncodingOk(value.toString());
0254                                }));
0255 
0256     // finalize the entries, e.g. hashs them
0257     finalizeConfigEntries();
0258 
0259     // init with defaults from config or really hardcoded ones
0260     KConfigGroup cg(KTextEditor::EditorPrivate::config(), QStringLiteral("KTextEditor Editor"));
0261     readConfig(cg);
0262 
0263     // avoid updateConfig effects like config write in constructor, see bug 377067
0264     Q_ASSERT(configSessionNumber == 1);
0265     --configSessionNumber;
0266 }
0267 
0268 void KateGlobalConfig::readConfig(const KConfigGroup &config)
0269 {
0270     // start config update group
0271     configStart();
0272 
0273     // read generic entries
0274     readConfigEntries(config);
0275 
0276     // end config update group, might trigger updateConfig()
0277     configEnd();
0278 }
0279 
0280 void KateGlobalConfig::writeConfig(KConfigGroup &config)
0281 {
0282     // write generic entries
0283     writeConfigEntries(config);
0284 }
0285 
0286 void KateGlobalConfig::updateConfig()
0287 {
0288     // write config
0289     KConfigGroup cg(KTextEditor::EditorPrivate::config(), QStringLiteral("KTextEditor Editor"));
0290     writeConfig(cg);
0291     KTextEditor::EditorPrivate::config()->sync();
0292 
0293     // trigger emission of KTextEditor::Editor::configChanged
0294     KTextEditor::EditorPrivate::self()->triggerConfigChanged();
0295 }
0296 // END
0297 
0298 // BEGIN KateDocumentConfig
0299 KateDocumentConfig::KateDocumentConfig()
0300 {
0301     // register this as our global instance
0302     Q_ASSERT(isGlobal());
0303     s_global = this;
0304 
0305     // avoid updateConfig effects like config write in constructor, see bug 377067
0306     Q_ASSERT(configSessionNumber == 0);
0307     ++configSessionNumber;
0308 
0309     // init all known config entries
0310     addConfigEntry(ConfigEntry(TabWidth, "Tab Width", QStringLiteral("tab-width"), 4, [](const QVariant &value) {
0311         return value.toInt() >= 1;
0312     }));
0313     addConfigEntry(ConfigEntry(IndentationWidth, "Indentation Width", QStringLiteral("indent-width"), 4, [](const QVariant &value) {
0314         return value.toInt() >= 1;
0315     }));
0316     addConfigEntry(ConfigEntry(OnTheFlySpellCheck, "On-The-Fly Spellcheck", QStringLiteral("on-the-fly-spellcheck"), false));
0317     addConfigEntry(ConfigEntry(IndentOnTextPaste, "Indent On Text Paste", QStringLiteral("indent-pasted-text"), true));
0318     addConfigEntry(ConfigEntry(ReplaceTabsWithSpaces, "ReplaceTabsDyn", QStringLiteral("replace-tabs"), true));
0319     addConfigEntry(ConfigEntry(BackupOnSaveLocal, "Backup Local", QStringLiteral("backup-on-save-local"), false));
0320     addConfigEntry(ConfigEntry(BackupOnSaveRemote, "Backup Remote", QStringLiteral("backup-on-save-remote"), false));
0321     addConfigEntry(ConfigEntry(BackupOnSavePrefix, "Backup Prefix", QStringLiteral("backup-on-save-prefix"), QString()));
0322     addConfigEntry(ConfigEntry(BackupOnSaveSuffix, "Backup Suffix", QStringLiteral("backup-on-save-suffix"), QStringLiteral("~")));
0323     addConfigEntry(ConfigEntry(IndentationMode, "Indentation Mode", QString(), QStringLiteral("normal")));
0324     addConfigEntry(ConfigEntry(TabHandlingMode, "Tab Handling", QString(), KateDocumentConfig::tabSmart));
0325     addConfigEntry(ConfigEntry(StaticWordWrap, "Word Wrap", QString(), false));
0326     addConfigEntry(ConfigEntry(StaticWordWrapColumn, "Word Wrap Column", QString(), 80, [](const QVariant &value) {
0327         return value.toInt() >= 1;
0328     }));
0329     addConfigEntry(ConfigEntry(PageUpDownMovesCursor, "PageUp/PageDown Moves Cursor", QString(), false));
0330     addConfigEntry(ConfigEntry(SmartHome, "Smart Home", QString(), true));
0331     addConfigEntry(ConfigEntry(ShowTabs, "Show Tabs", QString(), true));
0332     addConfigEntry(ConfigEntry(IndentOnTab, "Indent On Tab", QString(), true));
0333     addConfigEntry(ConfigEntry(KeepExtraSpaces, "Keep Extra Spaces", QString(), false));
0334     addConfigEntry(ConfigEntry(BackspaceIndents, "Indent On Backspace", QString(), true));
0335     addConfigEntry(ConfigEntry(ShowSpacesMode, "Show Spaces", QString(), KateDocumentConfig::None));
0336     addConfigEntry(ConfigEntry(TrailingMarkerSize, "Trailing Marker Size", QString(), 1));
0337     addConfigEntry(ConfigEntry(RemoveSpacesMode, "Remove Spaces", QString(), 1 /* on modified lines per default */, [](const QVariant &value) {
0338         return inBounds(0, value, 2);
0339     }));
0340     addConfigEntry(ConfigEntry(NewlineAtEOF, "Newline at End of File", QString(), true));
0341     addConfigEntry(ConfigEntry(OverwriteMode, "Overwrite Mode", QString(), false));
0342     addConfigEntry(
0343         ConfigEntry(Encoding, "Encoding", QString(), QString::fromUtf8(QStringConverter::nameForEncoding(QStringConverter::Utf8)), [](const QVariant &value) {
0344             return isEncodingOk(value.toString());
0345         }));
0346     addConfigEntry(ConfigEntry(EndOfLine, "End of Line", QString(), 0));
0347     addConfigEntry(ConfigEntry(AllowEndOfLineDetection, "Allow End of Line Detection", QString(), true));
0348     addConfigEntry(ConfigEntry(ByteOrderMark, "BOM", QString(), false));
0349     addConfigEntry(ConfigEntry(SwapFile, "Swap File Mode", QString(), KateDocumentConfig::EnableSwapFile));
0350     addConfigEntry(ConfigEntry(SwapFileDirectory, "Swap Directory", QString(), QString()));
0351     addConfigEntry(ConfigEntry(SwapFileSyncInterval, "Swap Sync Interval", QString(), 15));
0352     addConfigEntry(ConfigEntry(LineLengthLimit, "Line Length Limit", QString(), 10000));
0353     addConfigEntry(ConfigEntry(CamelCursor, "Camel Cursor", QString(), true));
0354     addConfigEntry(ConfigEntry(AutoDetectIndent, "Auto Detect Indent", QString(), true));
0355 
0356     // Auto save and co.
0357     addConfigEntry(ConfigEntry(AutoSave, "Auto Save", QString(), false));
0358     addConfigEntry(ConfigEntry(AutoSaveOnFocusOut, "Auto Save On Focus Out", QString(), false));
0359     addConfigEntry(ConfigEntry(AutoSaveInteral, "Auto Save Interval", QString(), 0));
0360 
0361     // Shall we do auto reloading for stuff e.g. in Git?
0362     addConfigEntry(ConfigEntry(AutoReloadIfStateIsInVersionControl, "Auto Reload If State Is In Version Control", QString(), true));
0363 
0364     // finalize the entries, e.g. hashs them
0365     finalizeConfigEntries();
0366 
0367     // init with defaults from config or really hardcoded ones
0368     KConfigGroup cg(KTextEditor::EditorPrivate::config(), QStringLiteral("KTextEditor Document"));
0369     readConfig(cg);
0370 
0371     // avoid updateConfig effects like config write in constructor, see bug 377067
0372     Q_ASSERT(configSessionNumber == 1);
0373     --configSessionNumber;
0374 }
0375 
0376 KateDocumentConfig::KateDocumentConfig(KTextEditor::DocumentPrivate *doc)
0377     : KateConfig(s_global)
0378     , m_doc(doc)
0379 {
0380     // per document config doesn't read stuff per default
0381 }
0382 
0383 void KateDocumentConfig::readConfig(const KConfigGroup &config)
0384 {
0385     // start config update group
0386     configStart();
0387 
0388     // read generic entries
0389     readConfigEntries(config);
0390 
0391     // fixup sonnet config, see KateSpellCheckConfigTab::apply(), too
0392     // WARNING: this is slightly hackish, but it's currently the only way to
0393     //          do it, see also the KTextEdit class
0394     if (isGlobal()) {
0395         const QSettings settings(QStringLiteral("KDE"), QStringLiteral("Sonnet"));
0396         const bool onTheFlyChecking = settings.value(QStringLiteral("checkerEnabledByDefault"), false).toBool();
0397         setOnTheFlySpellCheck(onTheFlyChecking);
0398 
0399         // ensure we load the default dictionary speller + trigrams early
0400         // this avoids hangs for auto-spellchecking on first edits
0401         // do this if we have on the fly spellchecking on only
0402         if (onTheFlyChecking) {
0403             Sonnet::Speller speller;
0404             speller.setLanguage(Sonnet::Speller().defaultLanguage());
0405             Sonnet::GuessLanguage languageGuesser;
0406             languageGuesser.identify(QStringLiteral("dummy to trigger identify"));
0407         }
0408     }
0409 
0410     // backwards compatibility mappings
0411     // convert stuff, old entries deleted in writeConfig
0412     if (const int backupFlags = config.readEntry("Backup Flags", 0)) {
0413         setBackupOnSaveLocal(backupFlags & 0x1);
0414         setBackupOnSaveRemote(backupFlags & 0x2);
0415     }
0416 
0417     // end config update group, might trigger updateConfig()
0418     configEnd();
0419 }
0420 
0421 void KateDocumentConfig::writeConfig(KConfigGroup &config)
0422 {
0423     // write generic entries
0424     writeConfigEntries(config);
0425 
0426     // backwards compatibility mappings
0427     // here we remove old entries we converted on readConfig
0428     config.deleteEntry("Backup Flags");
0429 }
0430 
0431 void KateDocumentConfig::updateConfig()
0432 {
0433     if (m_doc) {
0434         m_doc->updateConfig();
0435         return;
0436     }
0437 
0438     if (isGlobal()) {
0439         const auto docs = KTextEditor::EditorPrivate::self()->documents();
0440         for (auto doc : docs) {
0441             static_cast<KTextEditor::DocumentPrivate *>(doc)->updateConfig();
0442         }
0443 
0444         // write config
0445         KConfigGroup cg(KTextEditor::EditorPrivate::config(), QStringLiteral("KTextEditor Document"));
0446         writeConfig(cg);
0447         KTextEditor::EditorPrivate::config()->sync();
0448 
0449         // trigger emission of KTextEditor::Editor::configChanged
0450         KTextEditor::EditorPrivate::self()->triggerConfigChanged();
0451     }
0452 }
0453 
0454 QString KateDocumentConfig::eolString() const
0455 {
0456     switch (eol()) {
0457     case KateDocumentConfig::eolDos:
0458         return QStringLiteral("\r\n");
0459 
0460     case KateDocumentConfig::eolMac:
0461         return QStringLiteral("\r");
0462 
0463     default:
0464         return QStringLiteral("\n");
0465     }
0466 }
0467 // END
0468 
0469 // BEGIN KateViewConfig
0470 KateViewConfig::KateViewConfig()
0471 {
0472     // register this as our global instance
0473     Q_ASSERT(isGlobal());
0474     s_global = this;
0475 
0476     // avoid updateConfig effects like config write in constructor, see bug 377067
0477     Q_ASSERT(configSessionNumber == 0);
0478     ++configSessionNumber;
0479 
0480     // Init all known config entries
0481     // NOTE: Ensure to keep the same order as listed in enum ConfigEntryTypes or it will later assert!
0482     // addConfigEntry(ConfigEntry(<EnumKey>, <ConfigKey>, <CommandName>, <DefaultValue>,  [<ValidatorFunction>]))
0483     addConfigEntry(ConfigEntry(AllowMarkMenu, "Allow Mark Menu", QStringLiteral("allow-mark-menu"), true));
0484     addConfigEntry(ConfigEntry(AutoBrackets, "Auto Brackets", QStringLiteral("auto-brackets"), true));
0485     addConfigEntry(ConfigEntry(AutoCenterLines, "Auto Center Lines", QStringLiteral("auto-center-lines"), 0));
0486     addConfigEntry(ConfigEntry(AutomaticCompletionInvocation, "Auto Completion", QString(), true));
0487     addConfigEntry(ConfigEntry(AutomaticCompletionPreselectFirst, "Auto Completion Preselect First Entry", QString(), true));
0488     addConfigEntry(ConfigEntry(BackspaceRemoveComposedCharacters, "Backspace Remove Composed Characters", QString(), false));
0489     addConfigEntry(ConfigEntry(BookmarkSorting, "Bookmark Menu Sorting", QString(), 0));
0490     addConfigEntry(ConfigEntry(CharsToEncloseSelection, "Chars To Enclose Selection", QStringLiteral("enclose-selection"), QStringLiteral("<>(){}[]'\"")));
0491     addConfigEntry(ConfigEntry(ClipboardHistoryEntries, "Max Clipboard History Entries", QString(), 20, [](const QVariant &value) {
0492         return inBounds(1, value, 999);
0493     }));
0494     addConfigEntry(
0495         ConfigEntry(DefaultMarkType, "Default Mark Type", QStringLiteral("default-mark-type"), KTextEditor::Document::markType01, [](const QVariant &value) {
0496             return isPositive(value);
0497         }));
0498     addConfigEntry(ConfigEntry(DynWordWrapAlignIndent, "Dynamic Word Wrap Align Indent", QString(), 80, [](const QVariant &value) {
0499         return inBounds(0, value, 100);
0500     }));
0501     addConfigEntry(ConfigEntry(DynWordWrapIndicators, "Dynamic Word Wrap Indicators", QString(), 1, [](const QVariant &value) {
0502         return inBounds(0, value, 2);
0503     }));
0504     addConfigEntry(ConfigEntry(DynWrapAnywhere, "Dynamic Wrap not at word boundaries", QStringLiteral("dynamic-word-wrap-anywhere"), false));
0505     addConfigEntry(ConfigEntry(DynWrapAtStaticMarker, "Dynamic Word Wrap At Static Marker", QString(), false));
0506     addConfigEntry(ConfigEntry(DynamicWordWrap, "Dynamic Word Wrap", QStringLiteral("dynamic-word-wrap"), true));
0507     addConfigEntry(ConfigEntry(EnterToInsertCompletion, "Enter To Insert Completion", QStringLiteral("enter-to-insert-completion"), true));
0508     addConfigEntry(ConfigEntry(FoldFirstLine, "Fold First Line", QString(), false));
0509     addConfigEntry(ConfigEntry(InputMode, "Input Mode", QString(), 0, [](const QVariant &value) {
0510         return isPositive(value);
0511     }));
0512     addConfigEntry(ConfigEntry(KeywordCompletion, "Keyword Completion", QStringLiteral("keyword-completion"), true));
0513     addConfigEntry(ConfigEntry(MaxHistorySize, "Maximum Search History Size", QString(), 100, [](const QVariant &value) {
0514         return inBounds(0, value, 999);
0515     }));
0516     addConfigEntry(ConfigEntry(MousePasteAtCursorPosition, "Mouse Paste At Cursor Position", QString(), false));
0517     addConfigEntry(ConfigEntry(PersistentSelection, "Persistent Selection", QStringLiteral("persistent-selectionq"), false));
0518     addConfigEntry(ConfigEntry(ScrollBarMiniMapWidth, "Scroll Bar Mini Map Width", QString(), 60, [](const QVariant &value) {
0519         return inBounds(0, value, 999);
0520     }));
0521     addConfigEntry(ConfigEntry(ScrollPastEnd, "Scroll Past End", QString(), false));
0522     addConfigEntry(ConfigEntry(SearchFlags, "Search/Replace Flags", QString(), IncFromCursor | PowerMatchCase | PowerModePlainText));
0523     addConfigEntry(ConfigEntry(TabCompletion, "Enable Tab completion", QString(), false));
0524     addConfigEntry(ConfigEntry(ShowBracketMatchPreview, "Bracket Match Preview", QStringLiteral("bracket-match-preview"), false));
0525     addConfigEntry(ConfigEntry(ShowFoldingBar, "Folding Bar", QStringLiteral("folding-bar"), true));
0526     addConfigEntry(ConfigEntry(ShowFoldingPreview, "Folding Preview", QStringLiteral("folding-preview"), true));
0527     addConfigEntry(ConfigEntry(ShowIconBar, "Icon Bar", QStringLiteral("icon-bar"), false));
0528     addConfigEntry(ConfigEntry(ShowLineCount, "Show Line Count", QString(), false));
0529     addConfigEntry(ConfigEntry(ShowLineModification, "Line Modification", QStringLiteral("modification-markers"), true));
0530     addConfigEntry(ConfigEntry(ShowLineNumbers, "Line Numbers", QStringLiteral("line-numbers"), true));
0531     addConfigEntry(ConfigEntry(ShowScrollBarMarks, "Scroll Bar Marks", QString(), false));
0532     addConfigEntry(ConfigEntry(ShowScrollBarMiniMap, "Scroll Bar MiniMap", QStringLiteral("scrollbar-minimap"), true));
0533     addConfigEntry(ConfigEntry(ShowScrollBarMiniMapAll, "Scroll Bar Mini Map All", QString(), true));
0534     addConfigEntry(ConfigEntry(ShowScrollBarPreview, "Scroll Bar Preview", QStringLiteral("scrollbar-preview"), true));
0535     addConfigEntry(ConfigEntry(ShowScrollbars, "Show Scrollbars", QString(), AlwaysOn, [](const QVariant &value) {
0536         return inBounds(0, value, 2);
0537     }));
0538     addConfigEntry(ConfigEntry(ShowWordCount, "Show Word Count", QString(), false));
0539     addConfigEntry(ConfigEntry(TextDragAndDrop, "Text Drag And Drop", QString(), true));
0540     addConfigEntry(ConfigEntry(SmartCopyCut, "Smart Copy Cut", QString(), true));
0541     addConfigEntry(ConfigEntry(UserSetsOfCharsToEncloseSelection, "User Sets Of Chars To Enclose Selection", QString(), QStringList()));
0542     addConfigEntry(ConfigEntry(ViInputModeStealKeys, "Vi Input Mode Steal Keys", QString(), false));
0543     addConfigEntry(ConfigEntry(ViRelativeLineNumbers, "Vi Relative Line Numbers", QString(), false));
0544     addConfigEntry(ConfigEntry(WordCompletion, "Word Completion", QString(), true));
0545     addConfigEntry(ConfigEntry(WordCompletionMinimalWordLength,
0546                                "Word Completion Minimal Word Length",
0547                                QStringLiteral("word-completion-minimal-word-length"),
0548                                3,
0549                                [](const QVariant &value) {
0550                                    return inBounds(0, value, 99);
0551                                }));
0552     addConfigEntry(ConfigEntry(WordCompletionRemoveTail, "Word Completion Remove Tail", QString(), true));
0553     addConfigEntry(ConfigEntry(ShowFocusFrame, "Show Focus Frame Around Editor", QString(), true));
0554     addConfigEntry(ConfigEntry(ShowDocWithCompletion, "Show Documentation With Completion", QString(), true));
0555     addConfigEntry(ConfigEntry(MultiCursorModifier, "Multiple Cursor Modifier", QString(), (int)Qt::AltModifier));
0556     addConfigEntry(ConfigEntry(ShowFoldingOnHoverOnly, "Show Folding Icons On Hover Only", QString(), true));
0557 
0558     // Statusbar stuff
0559     addConfigEntry(ConfigEntry(ShowStatusbarLineColumn, "Show Statusbar Line Column", QString(), true));
0560     addConfigEntry(ConfigEntry(ShowStatusbarDictionary, "Show Statusbar Dictionary", QString(), true));
0561     addConfigEntry(ConfigEntry(ShowStatusbarInputMode, "Show Statusbar Input Mode", QString(), true));
0562     addConfigEntry(ConfigEntry(ShowStatusbarHighlightingMode, "Show Statusbar Highlighting Mode", QString(), true));
0563     addConfigEntry(ConfigEntry(ShowStatusbarTabSettings, "Show Statusbar Tab Settings", QString(), true));
0564     addConfigEntry(ConfigEntry(ShowStatusbarFileEncoding, "Show File Encoding", QString(), true));
0565     addConfigEntry(ConfigEntry(StatusbarLineColumnCompact, "Statusbar Line Column Compact Mode", QString(), true));
0566     addConfigEntry(ConfigEntry(ShowStatusbarEOL, "Shoe Line Ending Type in Statusbar", QString(), false));
0567     addConfigEntry(ConfigEntry(EnableAccessibility, "Enable Accessibility", QString(), true));
0568 
0569     // Never forget to finalize or the <CommandName> becomes not available
0570     finalizeConfigEntries();
0571 
0572     // init with defaults from config or really hardcoded ones
0573     KConfigGroup config(KTextEditor::EditorPrivate::config(), QStringLiteral("KTextEditor View"));
0574     readConfig(config);
0575 
0576     // avoid updateConfig effects like config write in constructor, see bug 377067
0577     Q_ASSERT(configSessionNumber == 1);
0578     --configSessionNumber;
0579 }
0580 
0581 KateViewConfig::KateViewConfig(KTextEditor::ViewPrivate *view)
0582     : KateConfig(s_global)
0583     , m_view(view)
0584 {
0585 }
0586 
0587 KateViewConfig::~KateViewConfig() = default;
0588 
0589 void KateViewConfig::readConfig(const KConfigGroup &config)
0590 {
0591     configStart();
0592 
0593     // read generic entries
0594     readConfigEntries(config);
0595 
0596     configEnd();
0597 }
0598 
0599 void KateViewConfig::writeConfig(KConfigGroup &config)
0600 {
0601     // write generic entries
0602     writeConfigEntries(config);
0603 }
0604 
0605 void KateViewConfig::updateConfig()
0606 {
0607     if (m_view) {
0608         m_view->updateConfig();
0609         return;
0610     }
0611 
0612     if (isGlobal()) {
0613         for (KTextEditor::ViewPrivate *view : KTextEditor::EditorPrivate::self()->views()) {
0614             view->updateConfig();
0615         }
0616 
0617         // write config
0618         KConfigGroup cg(KTextEditor::EditorPrivate::config(), QStringLiteral("KTextEditor View"));
0619         writeConfig(cg);
0620         KTextEditor::EditorPrivate::config()->sync();
0621 
0622         // trigger emission of KTextEditor::Editor::configChanged
0623         KTextEditor::EditorPrivate::self()->triggerConfigChanged();
0624     }
0625 }
0626 // END
0627 
0628 // BEGIN KateRendererConfig
0629 KateRendererConfig::KateRendererConfig()
0630     : m_lineMarkerColor(KTextEditor::Document::reservedMarkersCount())
0631     , m_schemaSet(false)
0632     , m_fontSet(false)
0633     , m_wordWrapMarkerSet(false)
0634     , m_showIndentationLinesSet(false)
0635     , m_showWholeBracketExpressionSet(false)
0636     , m_backgroundColorSet(false)
0637     , m_selectionColorSet(false)
0638     , m_highlightedLineColorSet(false)
0639     , m_highlightedBracketColorSet(false)
0640     , m_wordWrapMarkerColorSet(false)
0641     , m_tabMarkerColorSet(false)
0642     , m_indentationLineColorSet(false)
0643     , m_iconBarColorSet(false)
0644     , m_foldingColorSet(false)
0645     , m_lineNumberColorSet(false)
0646     , m_currentLineNumberColorSet(false)
0647     , m_separatorColorSet(false)
0648     , m_spellingMistakeLineColorSet(false)
0649     , m_templateColorsSet(false)
0650     , m_modifiedLineColorSet(false)
0651     , m_savedLineColorSet(false)
0652     , m_searchHighlightColorSet(false)
0653     , m_replaceHighlightColorSet(false)
0654     , m_lineMarkerColorSet(m_lineMarkerColor.size())
0655 
0656 {
0657     // init bitarray
0658     m_lineMarkerColorSet.fill(true);
0659 
0660     // register this as our global instance
0661     Q_ASSERT(isGlobal());
0662     s_global = this;
0663 
0664     // avoid updateConfig effects like config write in constructor, see bug 377067
0665     Q_ASSERT(configSessionNumber == 0);
0666     ++configSessionNumber;
0667 
0668     // Init all known config entries
0669     addConfigEntry(ConfigEntry(AutoColorThemeSelection, "Auto Color Theme Selection", QString(), true));
0670 
0671     // Never forget to finalize or the <CommandName> becomes not available
0672     finalizeConfigEntries();
0673 
0674     // init with defaults from config or really hardcoded ones
0675     KConfigGroup config(KTextEditor::EditorPrivate::config(), QStringLiteral("KTextEditor Renderer"));
0676     readConfig(config);
0677 
0678     // avoid updateConfig effects like config write in constructor, see bug 377067
0679     Q_ASSERT(configSessionNumber == 1);
0680     --configSessionNumber;
0681 }
0682 
0683 KateRendererConfig::KateRendererConfig(KateRenderer *renderer)
0684     : KateConfig(s_global)
0685     , m_lineMarkerColor(KTextEditor::Document::reservedMarkersCount())
0686     , m_schemaSet(false)
0687     , m_fontSet(false)
0688     , m_wordWrapMarkerSet(false)
0689     , m_showIndentationLinesSet(false)
0690     , m_showWholeBracketExpressionSet(false)
0691     , m_backgroundColorSet(false)
0692     , m_selectionColorSet(false)
0693     , m_highlightedLineColorSet(false)
0694     , m_highlightedBracketColorSet(false)
0695     , m_wordWrapMarkerColorSet(false)
0696     , m_tabMarkerColorSet(false)
0697     , m_indentationLineColorSet(false)
0698     , m_iconBarColorSet(false)
0699     , m_foldingColorSet(false)
0700     , m_lineNumberColorSet(false)
0701     , m_currentLineNumberColorSet(false)
0702     , m_separatorColorSet(false)
0703     , m_spellingMistakeLineColorSet(false)
0704     , m_templateColorsSet(false)
0705     , m_modifiedLineColorSet(false)
0706     , m_savedLineColorSet(false)
0707     , m_searchHighlightColorSet(false)
0708     , m_replaceHighlightColorSet(false)
0709     , m_lineMarkerColorSet(m_lineMarkerColor.size())
0710     , m_renderer(renderer)
0711 {
0712     // init bitarray
0713     m_lineMarkerColorSet.fill(false);
0714 }
0715 
0716 KateRendererConfig::~KateRendererConfig() = default;
0717 
0718 namespace
0719 {
0720 const char KEY_FONT[] = "Text Font";
0721 const char KEY_COLOR_THEME[] = "Color Theme";
0722 const char KEY_WORD_WRAP_MARKER[] = "Word Wrap Marker";
0723 const char KEY_SHOW_INDENTATION_LINES[] = "Show Indentation Lines";
0724 const char KEY_SHOW_WHOLE_BRACKET_EXPRESSION[] = "Show Whole Bracket Expression";
0725 const char KEY_ANIMATE_BRACKET_MATCHING[] = "Animate Bracket Matching";
0726 const char KEY_LINE_HEIGHT_MULTIPLIER[] = "Line Height Multiplier";
0727 }
0728 
0729 void KateRendererConfig::readConfig(const KConfigGroup &config)
0730 {
0731     configStart();
0732 
0733     // read generic entries
0734     readConfigEntries(config);
0735 
0736     // read font
0737     setFont(config.readEntry(KEY_FONT, QFontDatabase::systemFont(QFontDatabase::FixedFont)));
0738 
0739     // setSchema will default to right theme
0740     setSchema(config.readEntry(KEY_COLOR_THEME, QString()));
0741 
0742     setWordWrapMarker(config.readEntry(KEY_WORD_WRAP_MARKER, false));
0743 
0744     setShowIndentationLines(config.readEntry(KEY_SHOW_INDENTATION_LINES, false));
0745 
0746     setShowWholeBracketExpression(config.readEntry(KEY_SHOW_WHOLE_BRACKET_EXPRESSION, false));
0747 
0748     setAnimateBracketMatching(config.readEntry(KEY_ANIMATE_BRACKET_MATCHING, false));
0749 
0750     setLineHeightMultiplier(config.readEntry<qreal>(KEY_LINE_HEIGHT_MULTIPLIER, 1.0));
0751 
0752     configEnd();
0753 }
0754 
0755 void KateRendererConfig::writeConfig(KConfigGroup &config)
0756 {
0757     // write generic entries
0758     writeConfigEntries(config);
0759 
0760     config.writeEntry(KEY_FONT, baseFont());
0761 
0762     config.writeEntry(KEY_COLOR_THEME, schema());
0763 
0764     config.writeEntry(KEY_WORD_WRAP_MARKER, wordWrapMarker());
0765 
0766     config.writeEntry(KEY_SHOW_INDENTATION_LINES, showIndentationLines());
0767 
0768     config.writeEntry(KEY_SHOW_WHOLE_BRACKET_EXPRESSION, showWholeBracketExpression());
0769 
0770     config.writeEntry(KEY_ANIMATE_BRACKET_MATCHING, animateBracketMatching());
0771 
0772     config.writeEntry<qreal>(KEY_LINE_HEIGHT_MULTIPLIER, lineHeightMultiplier());
0773 }
0774 
0775 void KateRendererConfig::updateConfig()
0776 {
0777     if (m_renderer) {
0778         m_renderer->updateConfig();
0779         return;
0780     }
0781 
0782     if (isGlobal()) {
0783         for (auto view : KTextEditor::EditorPrivate::self()->views()) {
0784             view->renderer()->updateConfig();
0785         }
0786 
0787         // write config
0788         KConfigGroup cg(KTextEditor::EditorPrivate::config(), QStringLiteral("KTextEditor Renderer"));
0789         writeConfig(cg);
0790         KTextEditor::EditorPrivate::config()->sync();
0791 
0792         // trigger emission of KTextEditor::Editor::configChanged
0793         KTextEditor::EditorPrivate::self()->triggerConfigChanged();
0794     }
0795 }
0796 
0797 const QString &KateRendererConfig::schema() const
0798 {
0799     if (m_schemaSet || isGlobal()) {
0800         return m_schema;
0801     }
0802 
0803     return s_global->schema();
0804 }
0805 
0806 void KateRendererConfig::setSchema(QString schema)
0807 {
0808     // check if we have some matching theme, else fallback to best theme for current palette
0809     // same behavior as for the "Automatic Color Theme Selection"
0810     if (!KateHlManager::self()->repository().theme(schema).isValid()) {
0811         schema = KateHlManager::self()->repository().themeForPalette(qGuiApp->palette()).name();
0812     }
0813 
0814     if (m_schemaSet && m_schema == schema) {
0815         return;
0816     }
0817 
0818     configStart();
0819     m_schemaSet = true;
0820     m_schema = schema;
0821     setSchemaInternal(m_schema);
0822     configEnd();
0823 }
0824 
0825 void KateRendererConfig::reloadSchema()
0826 {
0827     if (isGlobal()) {
0828         setSchemaInternal(m_schema);
0829         for (KTextEditor::ViewPrivate *view : KTextEditor::EditorPrivate::self()->views()) {
0830             view->rendererConfig()->reloadSchema();
0831         }
0832     }
0833 
0834     else if (m_renderer && m_schemaSet) {
0835         setSchemaInternal(m_schema);
0836     }
0837 
0838     // trigger renderer/view update
0839     if (m_renderer) {
0840         m_renderer->updateConfig();
0841     }
0842 }
0843 
0844 void KateRendererConfig::setSchemaInternal(const QString &schema)
0845 {
0846     // we always set the theme if we arrive here!
0847     m_schemaSet = true;
0848 
0849     // for the global config, we honor the auto selection based on the palette
0850     // 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!
0851     if ((isGlobal() && value(AutoColorThemeSelection).toBool()) || !KateHlManager::self()->repository().theme(schema).isValid()) {
0852         // always choose some theme matching the current application palette
0853         // we will arrive here after palette changed signals, too!
0854         m_schema = KateHlManager::self()->repository().themeForPalette(qGuiApp->palette()).name();
0855     } else {
0856         // take user given theme 1:1
0857         m_schema = schema;
0858     }
0859 
0860     const auto theme = KateHlManager::self()->repository().theme(m_schema);
0861 
0862     m_backgroundColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::BackgroundColor));
0863     m_backgroundColorSet = true;
0864 
0865     m_selectionColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::TextSelection));
0866     m_selectionColorSet = true;
0867 
0868     m_highlightedLineColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::CurrentLine));
0869     m_highlightedLineColorSet = true;
0870 
0871     m_highlightedBracketColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::BracketMatching));
0872     m_highlightedBracketColorSet = true;
0873 
0874     m_wordWrapMarkerColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::WordWrapMarker));
0875     m_wordWrapMarkerColorSet = true;
0876 
0877     m_tabMarkerColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::TabMarker));
0878     m_tabMarkerColorSet = true;
0879 
0880     m_indentationLineColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::IndentationLine));
0881     m_indentationLineColorSet = true;
0882 
0883     m_iconBarColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::IconBorder));
0884     m_iconBarColorSet = true;
0885 
0886     m_foldingColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::CodeFolding));
0887     m_foldingColorSet = true;
0888 
0889     m_lineNumberColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::LineNumbers));
0890     m_lineNumberColorSet = true;
0891 
0892     m_currentLineNumberColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::CurrentLineNumber));
0893     m_currentLineNumberColorSet = true;
0894 
0895     m_separatorColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::Separator));
0896     m_separatorColorSet = true;
0897 
0898     m_spellingMistakeLineColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::SpellChecking));
0899     m_spellingMistakeLineColorSet = true;
0900 
0901     m_modifiedLineColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::ModifiedLines));
0902     m_modifiedLineColorSet = true;
0903 
0904     m_savedLineColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::SavedLines));
0905     m_savedLineColorSet = true;
0906 
0907     m_searchHighlightColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::SearchHighlight));
0908     m_searchHighlightColorSet = true;
0909 
0910     m_replaceHighlightColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::ReplaceHighlight));
0911     m_replaceHighlightColorSet = true;
0912 
0913     for (int i = 0; i <= KSyntaxHighlighting::Theme::MarkError - KSyntaxHighlighting::Theme::MarkBookmark; i++) {
0914         QColor col =
0915             QColor::fromRgba(theme.editorColor(static_cast<KSyntaxHighlighting::Theme::EditorColorRole>(i + KSyntaxHighlighting::Theme::MarkBookmark)));
0916         m_lineMarkerColorSet[i] = true;
0917         m_lineMarkerColor[i] = col;
0918     }
0919 
0920     m_templateBackgroundColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::TemplateBackground));
0921 
0922     m_templateFocusedEditablePlaceholderColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::TemplateFocusedPlaceholder));
0923 
0924     m_templateEditablePlaceholderColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::TemplatePlaceholder));
0925 
0926     m_templateNotEditablePlaceholderColor = QColor::fromRgba(theme.editorColor(KSyntaxHighlighting::Theme::TemplateReadOnlyPlaceholder));
0927 
0928     m_templateColorsSet = true;
0929 }
0930 
0931 const QFont &KateRendererConfig::baseFont() const
0932 {
0933     if (m_fontSet || isGlobal()) {
0934         return m_font;
0935     }
0936 
0937     return s_global->baseFont();
0938 }
0939 
0940 void KateRendererConfig::setFont(const QFont &font)
0941 {
0942     if (m_fontSet && m_font == font) {
0943         return;
0944     }
0945 
0946     configStart();
0947     m_font = font;
0948     m_fontSet = true;
0949     configEnd();
0950 }
0951 
0952 bool KateRendererConfig::wordWrapMarker() const
0953 {
0954     if (m_wordWrapMarkerSet || isGlobal()) {
0955         return m_wordWrapMarker;
0956     }
0957 
0958     return s_global->wordWrapMarker();
0959 }
0960 
0961 void KateRendererConfig::setWordWrapMarker(bool on)
0962 {
0963     if (m_wordWrapMarkerSet && m_wordWrapMarker == on) {
0964         return;
0965     }
0966 
0967     configStart();
0968 
0969     m_wordWrapMarkerSet = true;
0970     m_wordWrapMarker = on;
0971 
0972     configEnd();
0973 }
0974 
0975 const QColor &KateRendererConfig::backgroundColor() const
0976 {
0977     if (m_backgroundColorSet || isGlobal()) {
0978         return m_backgroundColor;
0979     }
0980 
0981     return s_global->backgroundColor();
0982 }
0983 
0984 void KateRendererConfig::setBackgroundColor(const QColor &col)
0985 {
0986     if (m_backgroundColorSet && m_backgroundColor == col) {
0987         return;
0988     }
0989 
0990     configStart();
0991 
0992     m_backgroundColorSet = true;
0993     m_backgroundColor = col;
0994 
0995     configEnd();
0996 }
0997 
0998 const QColor &KateRendererConfig::selectionColor() const
0999 {
1000     if (m_selectionColorSet || isGlobal()) {
1001         return m_selectionColor;
1002     }
1003 
1004     return s_global->selectionColor();
1005 }
1006 
1007 void KateRendererConfig::setSelectionColor(const QColor &col)
1008 {
1009     if (m_selectionColorSet && m_selectionColor == col) {
1010         return;
1011     }
1012 
1013     configStart();
1014 
1015     m_selectionColorSet = true;
1016     m_selectionColor = col;
1017 
1018     configEnd();
1019 }
1020 
1021 const QColor &KateRendererConfig::highlightedLineColor() const
1022 {
1023     if (m_highlightedLineColorSet || isGlobal()) {
1024         return m_highlightedLineColor;
1025     }
1026 
1027     return s_global->highlightedLineColor();
1028 }
1029 
1030 void KateRendererConfig::setHighlightedLineColor(const QColor &col)
1031 {
1032     if (m_highlightedLineColorSet && m_highlightedLineColor == col) {
1033         return;
1034     }
1035 
1036     configStart();
1037 
1038     m_highlightedLineColorSet = true;
1039     m_highlightedLineColor = col;
1040 
1041     configEnd();
1042 }
1043 
1044 const QColor &KateRendererConfig::lineMarkerColor(KTextEditor::Document::MarkTypes type) const
1045 {
1046     int index = 0;
1047     if (type > 0) {
1048         while ((type >> index++) ^ 1) { }
1049     }
1050     index -= 1;
1051 
1052     if (index < 0 || index >= KTextEditor::Document::reservedMarkersCount()) {
1053         static QColor dummy;
1054         return dummy;
1055     }
1056 
1057     if (m_lineMarkerColorSet[index] || isGlobal()) {
1058         return m_lineMarkerColor[index];
1059     }
1060 
1061     return s_global->lineMarkerColor(type);
1062 }
1063 
1064 const QColor &KateRendererConfig::highlightedBracketColor() const
1065 {
1066     if (m_highlightedBracketColorSet || isGlobal()) {
1067         return m_highlightedBracketColor;
1068     }
1069 
1070     return s_global->highlightedBracketColor();
1071 }
1072 
1073 void KateRendererConfig::setHighlightedBracketColor(const QColor &col)
1074 {
1075     if (m_highlightedBracketColorSet && m_highlightedBracketColor == col) {
1076         return;
1077     }
1078 
1079     configStart();
1080 
1081     m_highlightedBracketColorSet = true;
1082     m_highlightedBracketColor = col;
1083 
1084     configEnd();
1085 }
1086 
1087 const QColor &KateRendererConfig::wordWrapMarkerColor() const
1088 {
1089     if (m_wordWrapMarkerColorSet || isGlobal()) {
1090         return m_wordWrapMarkerColor;
1091     }
1092 
1093     return s_global->wordWrapMarkerColor();
1094 }
1095 
1096 void KateRendererConfig::setWordWrapMarkerColor(const QColor &col)
1097 {
1098     if (m_wordWrapMarkerColorSet && m_wordWrapMarkerColor == col) {
1099         return;
1100     }
1101 
1102     configStart();
1103 
1104     m_wordWrapMarkerColorSet = true;
1105     m_wordWrapMarkerColor = col;
1106 
1107     configEnd();
1108 }
1109 
1110 const QColor &KateRendererConfig::tabMarkerColor() const
1111 {
1112     if (m_tabMarkerColorSet || isGlobal()) {
1113         return m_tabMarkerColor;
1114     }
1115 
1116     return s_global->tabMarkerColor();
1117 }
1118 
1119 void KateRendererConfig::setTabMarkerColor(const QColor &col)
1120 {
1121     if (m_tabMarkerColorSet && m_tabMarkerColor == col) {
1122         return;
1123     }
1124 
1125     configStart();
1126 
1127     m_tabMarkerColorSet = true;
1128     m_tabMarkerColor = col;
1129 
1130     configEnd();
1131 }
1132 
1133 const QColor &KateRendererConfig::indentationLineColor() const
1134 {
1135     if (m_indentationLineColorSet || isGlobal()) {
1136         return m_indentationLineColor;
1137     }
1138 
1139     return s_global->indentationLineColor();
1140 }
1141 
1142 void KateRendererConfig::setIndentationLineColor(const QColor &col)
1143 {
1144     if (m_indentationLineColorSet && m_indentationLineColor == col) {
1145         return;
1146     }
1147 
1148     configStart();
1149 
1150     m_indentationLineColorSet = true;
1151     m_indentationLineColor = col;
1152 
1153     configEnd();
1154 }
1155 
1156 const QColor &KateRendererConfig::iconBarColor() const
1157 {
1158     if (m_iconBarColorSet || isGlobal()) {
1159         return m_iconBarColor;
1160     }
1161 
1162     return s_global->iconBarColor();
1163 }
1164 
1165 void KateRendererConfig::setIconBarColor(const QColor &col)
1166 {
1167     if (m_iconBarColorSet && m_iconBarColor == col) {
1168         return;
1169     }
1170 
1171     configStart();
1172 
1173     m_iconBarColorSet = true;
1174     m_iconBarColor = col;
1175 
1176     configEnd();
1177 }
1178 
1179 const QColor &KateRendererConfig::foldingColor() const
1180 {
1181     if (m_foldingColorSet || isGlobal()) {
1182         return m_foldingColor;
1183     }
1184 
1185     return s_global->foldingColor();
1186 }
1187 
1188 void KateRendererConfig::setFoldingColor(const QColor &col)
1189 {
1190     if (m_foldingColorSet && m_foldingColor == col) {
1191         return;
1192     }
1193 
1194     configStart();
1195 
1196     m_foldingColorSet = true;
1197     m_foldingColor = col;
1198 
1199     configEnd();
1200 }
1201 
1202 const QColor &KateRendererConfig::templateBackgroundColor() const
1203 {
1204     if (m_templateColorsSet || isGlobal()) {
1205         return m_templateBackgroundColor;
1206     }
1207 
1208     return s_global->templateBackgroundColor();
1209 }
1210 
1211 const QColor &KateRendererConfig::templateEditablePlaceholderColor() const
1212 {
1213     if (m_templateColorsSet || isGlobal()) {
1214         return m_templateEditablePlaceholderColor;
1215     }
1216 
1217     return s_global->templateEditablePlaceholderColor();
1218 }
1219 
1220 const QColor &KateRendererConfig::templateFocusedEditablePlaceholderColor() const
1221 {
1222     if (m_templateColorsSet || isGlobal()) {
1223         return m_templateFocusedEditablePlaceholderColor;
1224     }
1225 
1226     return s_global->templateFocusedEditablePlaceholderColor();
1227 }
1228 
1229 const QColor &KateRendererConfig::templateNotEditablePlaceholderColor() const
1230 {
1231     if (m_templateColorsSet || isGlobal()) {
1232         return m_templateNotEditablePlaceholderColor;
1233     }
1234 
1235     return s_global->templateNotEditablePlaceholderColor();
1236 }
1237 
1238 const QColor &KateRendererConfig::lineNumberColor() const
1239 {
1240     if (m_lineNumberColorSet || isGlobal()) {
1241         return m_lineNumberColor;
1242     }
1243 
1244     return s_global->lineNumberColor();
1245 }
1246 
1247 void KateRendererConfig::setLineNumberColor(const QColor &col)
1248 {
1249     if (m_lineNumberColorSet && m_lineNumberColor == col) {
1250         return;
1251     }
1252 
1253     configStart();
1254 
1255     m_lineNumberColorSet = true;
1256     m_lineNumberColor = col;
1257 
1258     configEnd();
1259 }
1260 
1261 const QColor &KateRendererConfig::currentLineNumberColor() const
1262 {
1263     if (m_currentLineNumberColorSet || isGlobal()) {
1264         return m_currentLineNumberColor;
1265     }
1266 
1267     return s_global->currentLineNumberColor();
1268 }
1269 
1270 void KateRendererConfig::setCurrentLineNumberColor(const QColor &col)
1271 {
1272     if (m_currentLineNumberColorSet && m_currentLineNumberColor == col) {
1273         return;
1274     }
1275 
1276     configStart();
1277 
1278     m_currentLineNumberColorSet = true;
1279     m_currentLineNumberColor = col;
1280 
1281     configEnd();
1282 }
1283 
1284 const QColor &KateRendererConfig::separatorColor() const
1285 {
1286     if (m_separatorColorSet || isGlobal()) {
1287         return m_separatorColor;
1288     }
1289 
1290     return s_global->separatorColor();
1291 }
1292 
1293 void KateRendererConfig::setSeparatorColor(const QColor &col)
1294 {
1295     if (m_separatorColorSet && m_separatorColor == col) {
1296         return;
1297     }
1298 
1299     configStart();
1300 
1301     m_separatorColorSet = true;
1302     m_separatorColor = col;
1303 
1304     configEnd();
1305 }
1306 
1307 const QColor &KateRendererConfig::spellingMistakeLineColor() const
1308 {
1309     if (m_spellingMistakeLineColorSet || isGlobal()) {
1310         return m_spellingMistakeLineColor;
1311     }
1312 
1313     return s_global->spellingMistakeLineColor();
1314 }
1315 
1316 void KateRendererConfig::setSpellingMistakeLineColor(const QColor &col)
1317 {
1318     if (m_spellingMistakeLineColorSet && m_spellingMistakeLineColor == col) {
1319         return;
1320     }
1321 
1322     configStart();
1323 
1324     m_spellingMistakeLineColorSet = true;
1325     m_spellingMistakeLineColor = col;
1326 
1327     configEnd();
1328 }
1329 
1330 const QColor &KateRendererConfig::modifiedLineColor() const
1331 {
1332     if (m_modifiedLineColorSet || isGlobal()) {
1333         return m_modifiedLineColor;
1334     }
1335 
1336     return s_global->modifiedLineColor();
1337 }
1338 
1339 void KateRendererConfig::setModifiedLineColor(const QColor &col)
1340 {
1341     if (m_modifiedLineColorSet && m_modifiedLineColor == col) {
1342         return;
1343     }
1344 
1345     configStart();
1346 
1347     m_modifiedLineColorSet = true;
1348     m_modifiedLineColor = col;
1349 
1350     configEnd();
1351 }
1352 
1353 const QColor &KateRendererConfig::savedLineColor() const
1354 {
1355     if (m_savedLineColorSet || isGlobal()) {
1356         return m_savedLineColor;
1357     }
1358 
1359     return s_global->savedLineColor();
1360 }
1361 
1362 void KateRendererConfig::setSavedLineColor(const QColor &col)
1363 {
1364     if (m_savedLineColorSet && m_savedLineColor == col) {
1365         return;
1366     }
1367 
1368     configStart();
1369 
1370     m_savedLineColorSet = true;
1371     m_savedLineColor = col;
1372 
1373     configEnd();
1374 }
1375 
1376 const QColor &KateRendererConfig::searchHighlightColor() const
1377 {
1378     if (m_searchHighlightColorSet || isGlobal()) {
1379         return m_searchHighlightColor;
1380     }
1381 
1382     return s_global->searchHighlightColor();
1383 }
1384 
1385 void KateRendererConfig::setSearchHighlightColor(const QColor &col)
1386 {
1387     if (m_searchHighlightColorSet && m_searchHighlightColor == col) {
1388         return;
1389     }
1390 
1391     configStart();
1392 
1393     m_searchHighlightColorSet = true;
1394     m_searchHighlightColor = col;
1395 
1396     configEnd();
1397 }
1398 
1399 const QColor &KateRendererConfig::replaceHighlightColor() const
1400 {
1401     if (m_replaceHighlightColorSet || isGlobal()) {
1402         return m_replaceHighlightColor;
1403     }
1404 
1405     return s_global->replaceHighlightColor();
1406 }
1407 
1408 void KateRendererConfig::setReplaceHighlightColor(const QColor &col)
1409 {
1410     if (m_replaceHighlightColorSet && m_replaceHighlightColor == col) {
1411         return;
1412     }
1413 
1414     configStart();
1415 
1416     m_replaceHighlightColorSet = true;
1417     m_replaceHighlightColor = col;
1418 
1419     configEnd();
1420 }
1421 
1422 void KateRendererConfig::setLineHeightMultiplier(qreal value)
1423 {
1424     configStart();
1425     m_lineHeightMultiplier = value;
1426     configEnd();
1427 }
1428 
1429 bool KateRendererConfig::showIndentationLines() const
1430 {
1431     if (m_showIndentationLinesSet || isGlobal()) {
1432         return m_showIndentationLines;
1433     }
1434 
1435     return s_global->showIndentationLines();
1436 }
1437 
1438 void KateRendererConfig::setShowIndentationLines(bool on)
1439 {
1440     if (m_showIndentationLinesSet && m_showIndentationLines == on) {
1441         return;
1442     }
1443 
1444     configStart();
1445 
1446     m_showIndentationLinesSet = true;
1447     m_showIndentationLines = on;
1448 
1449     configEnd();
1450 }
1451 
1452 bool KateRendererConfig::showWholeBracketExpression() const
1453 {
1454     if (m_showWholeBracketExpressionSet || isGlobal()) {
1455         return m_showWholeBracketExpression;
1456     }
1457 
1458     return s_global->showWholeBracketExpression();
1459 }
1460 
1461 void KateRendererConfig::setShowWholeBracketExpression(bool on)
1462 {
1463     if (m_showWholeBracketExpressionSet && m_showWholeBracketExpression == on) {
1464         return;
1465     }
1466 
1467     configStart();
1468 
1469     m_showWholeBracketExpressionSet = true;
1470     m_showWholeBracketExpression = on;
1471 
1472     configEnd();
1473 }
1474 
1475 bool KateRendererConfig::animateBracketMatching()
1476 {
1477     return s_global->m_animateBracketMatching;
1478 }
1479 
1480 void KateRendererConfig::setAnimateBracketMatching(bool on)
1481 {
1482     if (!isGlobal()) {
1483         s_global->setAnimateBracketMatching(on);
1484     } else if (on != m_animateBracketMatching) {
1485         configStart();
1486         m_animateBracketMatching = on;
1487         configEnd();
1488     }
1489 }
1490 
1491 // END