Warning, file /utilities/konsole/src/colorscheme/ColorSchemeManager.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 This source file is part of Konsole, a terminal emulator. 0003 0004 SPDX-FileCopyrightText: 2007-2008 Robert Knight <robertknight@gmail.com> 0005 SPDX-FileCopyrightText: 2018 Harald Sitter <sitter@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 // Own 0011 #include "ColorSchemeManager.h" 0012 0013 #include "colorschemedebug.h" 0014 0015 // Qt 0016 #include <QDir> 0017 #include <QFile> 0018 #include <QFileInfo> 0019 0020 // KDE 0021 #include <KConfig> 0022 0023 using namespace Konsole; 0024 0025 ColorSchemeManager::ColorSchemeManager() 0026 { 0027 } 0028 0029 Q_GLOBAL_STATIC(ColorSchemeManager, theColorSchemeManager) 0030 0031 ColorSchemeManager *ColorSchemeManager::instance() 0032 { 0033 return theColorSchemeManager; 0034 } 0035 0036 QList<std::shared_ptr<const ColorScheme>> ColorSchemeManager::allColorSchemes() 0037 { 0038 int failed = 0; 0039 0040 QList<std::shared_ptr<const ColorScheme>> ret; 0041 for (const QString &name : listColorSchemes()) { 0042 std::shared_ptr<const ColorScheme> scheme = findColorScheme(colorSchemeNameFromPath(name)); 0043 if (!scheme) { 0044 failed++; 0045 continue; 0046 } 0047 ret.append(scheme); 0048 } 0049 0050 if (failed > 0) { 0051 qCDebug(ColorSchemeDebug) << "failed to load " << failed << " color schemes."; 0052 } 0053 0054 return ret; 0055 } 0056 0057 std::shared_ptr<const ColorScheme> ColorSchemeManager::loadColorScheme(const QString &filePath) 0058 { 0059 if (!pathIsColorScheme(filePath) || !QFile::exists(filePath)) { 0060 return nullptr; 0061 } 0062 0063 const QString name = colorSchemeNameFromPath(filePath); 0064 0065 KConfig config(filePath, KConfig::NoGlobals); 0066 std::shared_ptr<ColorScheme> scheme = std::make_shared<ColorScheme>(); 0067 scheme->setName(name); 0068 scheme->read(config); 0069 0070 if (scheme->name().isEmpty()) { 0071 qCDebug(ColorSchemeDebug) << "Color scheme in" << filePath << "does not have a valid name and was not loaded."; 0072 return nullptr; 0073 } 0074 0075 if (!_colorSchemes.contains(name)) { 0076 _colorSchemes.insert(scheme->name(), scheme); 0077 } else { 0078 // qDebug() << "color scheme with name" << scheme->name() << "has already been" << 0079 // "found, replacing."; 0080 0081 _colorSchemes[name] = scheme; 0082 } 0083 0084 return scheme; 0085 } 0086 0087 bool ColorSchemeManager::unloadColorScheme(const QString &filePath) 0088 { 0089 if (!pathIsColorScheme(filePath)) { 0090 return false; 0091 } 0092 _colorSchemes.remove(colorSchemeNameFromPath(filePath)); 0093 return true; 0094 } 0095 0096 QString ColorSchemeManager::colorSchemeNameFromPath(const QString &path) 0097 { 0098 if (!pathIsColorScheme(path)) { 0099 return QString(); 0100 } 0101 return QFileInfo(path).completeBaseName(); 0102 } 0103 0104 QStringList ColorSchemeManager::listColorSchemes() 0105 { 0106 QStringList colorschemes; 0107 const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("konsole"), QStandardPaths::LocateDirectory); 0108 colorschemes.reserve(dirs.size()); 0109 0110 for (const QString &dir : dirs) { 0111 const QStringList fileNames = QDir(dir).entryList(QStringList() << QStringLiteral("*.colorscheme")); 0112 for (const QString &file : fileNames) { 0113 colorschemes.append(dir + QLatin1Char('/') + file); 0114 } 0115 } 0116 return colorschemes; 0117 } 0118 0119 const std::shared_ptr<const ColorScheme> &ColorSchemeManager::defaultColorScheme() const 0120 { 0121 static const std::shared_ptr<const ColorScheme> defaultScheme = std::make_shared<const ColorScheme>(); 0122 return defaultScheme; 0123 } 0124 0125 void ColorSchemeManager::addColorScheme(const std::shared_ptr<ColorScheme> &scheme) 0126 { 0127 _colorSchemes[scheme->name()] = scheme; 0128 0129 // save changes to disk 0130 0131 const QString dir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/konsole/"); 0132 QDir().mkpath(dir); 0133 const QString path = dir + scheme->name() + QStringLiteral(".colorscheme"); 0134 KConfig config(path, KConfig::NoGlobals); 0135 0136 scheme->write(config); 0137 } 0138 0139 bool ColorSchemeManager::deleteColorScheme(const QString &name) 0140 { 0141 Q_ASSERT(_colorSchemes.contains(name)); 0142 0143 // look up the path and delete 0144 QString path = findColorSchemePath(name); 0145 if (QFile::remove(path)) { 0146 _colorSchemes.remove(name); 0147 return true; 0148 } 0149 qCDebug(ColorSchemeDebug) << "Failed to remove color scheme -" << path; 0150 return false; 0151 } 0152 0153 std::shared_ptr<const ColorScheme> ColorSchemeManager::findColorScheme(const QString &name) 0154 { 0155 if (name.isEmpty()) { 0156 return defaultColorScheme(); 0157 } 0158 0159 // A fix to prevent infinite loops if users puts / in ColorScheme name 0160 // Konsole will create a sub-folder in that case (bko 315086) 0161 // More code will have to go in to prevent the users from doing that. 0162 if (name.contains(QLatin1String("/"))) { 0163 qCDebug(ColorSchemeDebug) << name << " has an invalid character / in the name ... skipping"; 0164 return defaultColorScheme(); 0165 } 0166 0167 if (_colorSchemes.contains(name)) { 0168 std::shared_ptr<const ColorScheme> colorScheme = _colorSchemes.value(name).lock(); 0169 if (colorScheme) { 0170 return colorScheme; 0171 } else { 0172 // Remove outdated weak pointer 0173 _colorSchemes.remove(name); 0174 } 0175 } 0176 // look for this color scheme 0177 QString path = findColorSchemePath(name); 0178 if (path.isEmpty()) { 0179 qCDebug(ColorSchemeDebug) << "Could not find color scheme - " << name; 0180 return nullptr; 0181 } 0182 return loadColorScheme(path); 0183 } 0184 0185 QString ColorSchemeManager::findColorSchemePath(const QString &name) const 0186 { 0187 QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("konsole/") + name + QStringLiteral(".colorscheme")); 0188 0189 if (!path.isEmpty()) { 0190 return path; 0191 } 0192 0193 return QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("konsole/") + name + QStringLiteral(".schema")); 0194 } 0195 0196 bool ColorSchemeManager::pathIsColorScheme(const QString &path) 0197 { 0198 return path.endsWith(QLatin1String(".colorscheme")); 0199 } 0200 0201 bool ColorSchemeManager::isColorSchemeDeletable(const QString &name) 0202 { 0203 QFileInfo fileInfo(findColorSchemePath(name)); 0204 QFileInfo dirInfo(fileInfo.path()); 0205 0206 return dirInfo.isWritable(); 0207 } 0208 0209 bool ColorSchemeManager::canResetColorScheme(const QString &name) 0210 { 0211 const QStringList paths = 0212 QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("konsole/") + name + QStringLiteral(".colorscheme")); 0213 0214 // if the colorscheme exists in both a writable location under the 0215 // user's home dir and a system-wide location, then it's possible 0216 // to delete the colorscheme under the user's home dir so that the 0217 // colorscheme from the system-wide location can be used instead, 0218 // i.e. resetting the colorscheme 0219 return (paths.count() > 1); 0220 }