File indexing completed on 2024-04-28 15:30:54

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