File indexing completed on 2024-05-12 17:06:43
0001 /* 0002 * ThemeListModel 0003 * SPDX-FileCopyrightText: 2002 Karol Szwed <gallium@kde.org> 0004 * SPDX-FileCopyrightText: 2002 Daniel Molkentin <molkentin@kde.org> 0005 * SPDX-FileCopyrightText: 2007 Urs Wolfer <uwolfer @ kde.org> 0006 * SPDX-FileCopyrightText: 2009 Davide Bettio <davide.bettio@kdemail.net> 0007 * SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org> 0008 0009 * Portions SPDX-FileCopyrightText: 2007 Paolo Capriotti <p.capriotti@gmail.com> 0010 * Portions SPDX-FileCopyrightText: 2007 Ivan Cukic <ivan.cukic+kde@gmail.com> 0011 * Portions SPDX-FileCopyrightText: 2008 Petri Damsten <damu@iki.fi> 0012 * Portions SPDX-FileCopyrightText: 2000 TrollTech AS. 0013 * 0014 * SPDX-License-Identifier: GPL-2.0-only 0015 */ 0016 0017 #include "themelistmodel.h" 0018 0019 #include <QDir> 0020 #include <QFile> 0021 #include <QPainter> 0022 #include <QStandardPaths> 0023 0024 #include <KConfigGroup> 0025 #include <KDesktopFile> 0026 #include <KPluginMetaData> 0027 #include <KAboutData> 0028 0029 #include <KColorScheme> 0030 #include <QDebug> 0031 0032 ThemeListModel::ThemeListModel(QObject *parent) 0033 : QAbstractListModel(parent) 0034 { 0035 m_roleNames.insert(Qt::DisplayRole, "display"); 0036 m_roleNames.insert(PackageNameRole, "packageNameRole"); 0037 m_roleNames.insert(PackageDescriptionRole, "packageDescriptionRole"); 0038 m_roleNames.insert(PackageAuthorRole, "packageAuthorRole"); 0039 m_roleNames.insert(PackageVersionRole, "packageVersionRole"); 0040 m_roleNames.insert(PluginNameRole, "pluginNameRole"); 0041 m_roleNames.insert(ColorTypeRole, "colorTypeRole"); 0042 0043 reload(); 0044 } 0045 0046 ThemeListModel::~ThemeListModel() 0047 { 0048 clearThemeList(); 0049 } 0050 0051 QHash<int, QByteArray> ThemeListModel::roleNames() const 0052 { 0053 return m_roleNames; 0054 } 0055 0056 void ThemeListModel::clearThemeList() 0057 { 0058 m_themes.clear(); 0059 } 0060 0061 void ThemeListModel::reload() 0062 { 0063 clearThemeList(); 0064 0065 // get all desktop themes 0066 QStringList themes; 0067 const QStringList &packs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "plasma/desktoptheme", QStandardPaths::LocateDirectory); 0068 for (const QString &ppath : packs) { 0069 const QDir cd(ppath); 0070 const QStringList &entries = cd.entryList(QDir::Dirs | QDir::Hidden); 0071 for (const QString &pack : entries) { 0072 const QString prefix = QStringLiteral("%1%2%3%4metadata.").arg(ppath, QDir::separator(), pack, QDir::separator()); 0073 0074 QString _metadata = QStringLiteral("%1json").arg(prefix); 0075 if (QFile::exists(_metadata)) { 0076 themes << _metadata; 0077 continue; 0078 } 0079 0080 _metadata = QStringLiteral("%1desktop").arg(prefix); 0081 if (QFile::exists(_metadata)) { 0082 themes << _metadata; 0083 } 0084 } 0085 } 0086 0087 for (const QString &theme : qAsConst(themes)) { 0088 int themeSepIndex = theme.lastIndexOf('/', -1); 0089 QString themeRoot = theme.left(themeSepIndex); 0090 int themeNameSepIndex = themeRoot.lastIndexOf('/', -1); 0091 QString packageName = themeRoot.right(themeRoot.length() - themeNameSepIndex - 1); 0092 0093 QString name; 0094 QString comment; 0095 QString author; 0096 QString version; 0097 QString pluginName; 0098 0099 if (theme.endsWith(QLatin1String(".json"))) { 0100 KPluginMetaData data = KPluginMetaData::fromJsonFile(theme); 0101 name = data.name(); 0102 comment = data.description(); 0103 pluginName = data.pluginId(); 0104 0105 QList<KAboutPerson> authors = data.authors(); 0106 author = authors.isEmpty() ? QString() : authors.first().name(); 0107 0108 } else { 0109 KDesktopFile df(theme); 0110 0111 if (df.noDisplay()) { 0112 continue; 0113 } 0114 0115 name = df.readName(); 0116 if (name.isEmpty()) { 0117 name = packageName; 0118 } 0119 comment = df.readComment(); 0120 pluginName = df.desktopGroup().readEntry("X-KDE-PluginInfo-Name", QString()); 0121 author = df.desktopGroup().readEntry("X-KDE-PluginInfo-Author", QString()); 0122 version = df.desktopGroup().readEntry("X-KDE-PluginInfo-Version", QString()); 0123 } 0124 0125 ThemeInfo info; 0126 info.pluginName = pluginName; 0127 0128 bool hasPluginName = std::any_of(m_themes.begin(), m_themes.end(), [&](const ThemeInfo &item) { 0129 Q_UNUSED (item) 0130 return info.pluginName == packageName; 0131 }); 0132 0133 if (!hasPluginName) { 0134 // Plasma Theme creates a KColorScheme out of the "color" file and falls back to system colors if there is none 0135 const QString colorsPath = themeRoot + QLatin1String("/colors"); 0136 const bool followsSystemColors = !QFileInfo::exists(colorsPath); 0137 ColorType type = FollowsColorTheme; 0138 Q_UNUSED(type); 0139 info.type = FollowsColorTheme; 0140 if (!followsSystemColors) { 0141 const KSharedConfig::Ptr config = KSharedConfig::openConfig(colorsPath); 0142 const QPalette palette = KColorScheme::createApplicationPalette(config); 0143 const int windowBackgroundGray = qGray(palette.window().color().rgb()); 0144 if (windowBackgroundGray < 192) { 0145 type = DarkTheme; 0146 info.type = DarkTheme; 0147 } else { 0148 type = LightTheme; 0149 info.type = LightTheme; 0150 } 0151 } 0152 } 0153 0154 info.package = packageName; 0155 info.description = comment; 0156 info.author = author; 0157 info.version = version; 0158 info.themeRoot = themeRoot; 0159 m_themes[name] = info; 0160 } 0161 0162 beginResetModel(); 0163 endResetModel(); 0164 } 0165 0166 int ThemeListModel::rowCount(const QModelIndex &) const 0167 { 0168 return m_themes.size(); 0169 } 0170 0171 QVariant ThemeListModel::data(const QModelIndex &index, int role) const 0172 { 0173 if (!index.isValid()) { 0174 return QVariant(); 0175 } 0176 0177 if (index.row() >= m_themes.size()) { 0178 return QVariant(); 0179 } 0180 0181 QMap<QString, ThemeInfo>::const_iterator it = m_themes.constBegin(); 0182 for (int i = 0; i < index.row(); ++i) { 0183 ++it; 0184 } 0185 0186 switch (role) { 0187 case Qt::DisplayRole: 0188 return it.key(); 0189 case PackageNameRole: 0190 return (*it).package; 0191 case PackageDescriptionRole: 0192 return (*it).description; 0193 case PackageAuthorRole: 0194 return (*it).author; 0195 case PackageVersionRole: 0196 return (*it).version; 0197 case PluginNameRole: 0198 return (*it).pluginName; 0199 case ColorTypeRole: 0200 return (*it).type; 0201 default: 0202 return QVariant(); 0203 } 0204 } 0205 0206 QVariantMap ThemeListModel::get(int row) const 0207 { 0208 QVariantMap item; 0209 0210 QModelIndex idx = index(row, 0); 0211 0212 item["display"] = data(idx, Qt::DisplayRole); 0213 item["pluginNameRole"] = data(idx, PluginNameRole); 0214 item["colorTypeRole"] = data(idx, ColorTypeRole); 0215 item["packageNameRole"] = data(idx, PackageNameRole); 0216 item["packageDescriptionRole"] = data(idx, PackageDescriptionRole); 0217 item["packageAuthorRole"] = data(idx, PackageAuthorRole); 0218 item["packageVersionRole"] = data(idx, PackageVersionRole); 0219 0220 return item; 0221 } 0222 0223 QModelIndex ThemeListModel::indexOf(const QString &name) const 0224 { 0225 QMapIterator<QString, ThemeInfo> it(m_themes); 0226 int i = -1; 0227 while (it.hasNext()) { 0228 ++i; 0229 if (it.next().value().package == name) { 0230 return index(i, 0); 0231 } 0232 } 0233 0234 return {}; 0235 } 0236 0237 #include "moc_themelistmodel.cpp"