File indexing completed on 2024-11-10 04:56:48
0001 /* 0002 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 #include "decorationmodel.h" 0007 #include "utils.h" 0008 // KDecoration2 0009 #include <KDecoration2/Decoration> 0010 #include <KDecoration2/DecorationSettings> 0011 #include <KDecoration2/DecorationThemeProvider> 0012 // KDE 0013 #include <KPluginFactory> 0014 #include <KPluginMetaData> 0015 // Qt 0016 #include <QDebug> 0017 0018 namespace KDecoration2 0019 { 0020 0021 namespace Configuration 0022 { 0023 static const QString s_pluginName = QStringLiteral("org.kde.kdecoration2"); 0024 0025 DecorationsModel::DecorationsModel(QObject *parent) 0026 : QAbstractListModel(parent) 0027 { 0028 } 0029 0030 DecorationsModel::~DecorationsModel() = default; 0031 0032 int DecorationsModel::rowCount(const QModelIndex &parent) const 0033 { 0034 if (parent.isValid()) { 0035 return 0; 0036 } 0037 return m_plugins.size(); 0038 } 0039 0040 QVariant DecorationsModel::data(const QModelIndex &index, int role) const 0041 { 0042 if (!index.isValid() || index.column() != 0 || index.row() < 0 || index.row() >= int(m_plugins.size())) { 0043 return QVariant(); 0044 } 0045 const KDecoration2::DecorationThemeMetaData &d = m_plugins.at(index.row()); 0046 switch (role) { 0047 case Qt::DisplayRole: 0048 return d.visibleName(); 0049 case PluginNameRole: 0050 return d.pluginId(); 0051 case ThemeNameRole: 0052 return d.themeName(); 0053 case ConfigurationRole: 0054 return !d.configurationName().isEmpty(); 0055 case KcmoduleNameRole: 0056 return d.configurationName(); 0057 case RecommendedBorderSizeRole: 0058 return Utils::borderSizeToString(d.borderSize()); 0059 } 0060 return QVariant(); 0061 } 0062 0063 QHash<int, QByteArray> DecorationsModel::roleNames() const 0064 { 0065 QHash<int, QByteArray> roles({{Qt::DisplayRole, QByteArrayLiteral("display")}, 0066 {PluginNameRole, QByteArrayLiteral("plugin")}, 0067 {ThemeNameRole, QByteArrayLiteral("theme")}, 0068 {ConfigurationRole, QByteArrayLiteral("configureable")}, 0069 {KcmoduleNameRole, QByteArrayLiteral("kcmoduleName")}, 0070 {RecommendedBorderSizeRole, QByteArrayLiteral("recommendedbordersize")}}); 0071 return roles; 0072 } 0073 0074 static bool isThemeEngine(const QVariantMap &decoSettingsMap) 0075 { 0076 auto it = decoSettingsMap.find(QStringLiteral("themes")); 0077 if (it == decoSettingsMap.end()) { 0078 return false; 0079 } 0080 return it.value().toBool(); 0081 } 0082 0083 static KDecoration2::BorderSize recommendedBorderSize(const QVariantMap &decoSettingsMap) 0084 { 0085 auto it = decoSettingsMap.find(QStringLiteral("recommendedBorderSize")); 0086 if (it == decoSettingsMap.end()) { 0087 return KDecoration2::BorderSize::Normal; 0088 } 0089 return Utils::stringToBorderSize(it.value().toString()); 0090 } 0091 0092 static QString themeListKeyword(const QVariantMap &decoSettingsMap) 0093 { 0094 auto it = decoSettingsMap.find(QStringLiteral("themeListKeyword")); 0095 if (it == decoSettingsMap.end()) { 0096 return QString(); 0097 } 0098 return it.value().toString(); 0099 } 0100 0101 static QString findKNewStuff(const QVariantMap &decoSettingsMap) 0102 { 0103 auto it = decoSettingsMap.find(QStringLiteral("KNewStuff")); 0104 if (it == decoSettingsMap.end()) { 0105 return QString(); 0106 } 0107 return it.value().toString(); 0108 } 0109 0110 void DecorationsModel::init() 0111 { 0112 beginResetModel(); 0113 m_plugins.clear(); 0114 const auto plugins = KPluginMetaData::findPlugins(s_pluginName); 0115 for (const auto &info : plugins) { 0116 std::unique_ptr<KDecoration2::DecorationThemeProvider> themeFinder( 0117 KPluginFactory::instantiatePlugin<KDecoration2::DecorationThemeProvider>(info).plugin); 0118 KDecoration2::DecorationThemeMetaData data; 0119 const auto decoSettingsMap = info.rawData().value("org.kde.kdecoration2").toObject().toVariantMap(); 0120 if (themeFinder) { 0121 const QString &kns = findKNewStuff(decoSettingsMap); 0122 if (!kns.isEmpty() && !m_knsProviders.contains(kns)) { 0123 m_knsProviders.append(kns); 0124 } 0125 if (isThemeEngine(decoSettingsMap)) { 0126 const QString keyword = themeListKeyword(decoSettingsMap); 0127 if (keyword.isNull()) { 0128 // We cannot list the themes 0129 continue; 0130 } 0131 const auto themesList = themeFinder->themes(); 0132 for (const KDecoration2::DecorationThemeMetaData &data : themesList) { 0133 m_plugins.emplace_back(data); 0134 } 0135 0136 // it's a theme engine, we don't want to show this entry 0137 continue; 0138 } 0139 } 0140 0141 if (decoSettingsMap.contains(QStringLiteral("kcmodule"))) { 0142 qWarning() << "The use of 'kcmodule' is deprecated in favor of 'kcmoduleName', please update" << info.name(); 0143 } 0144 0145 data.setConfigurationName(info.value("X-KDE-ConfigModule")); 0146 data.setBorderSize(recommendedBorderSize(decoSettingsMap)); 0147 data.setVisibleName(info.name().isEmpty() ? info.pluginId() : info.name()); 0148 data.setPluginId(info.pluginId()); 0149 data.setThemeName(data.visibleName()); 0150 0151 m_plugins.emplace_back(std::move(data)); 0152 } 0153 endResetModel(); 0154 } 0155 0156 QModelIndex DecorationsModel::findDecoration(const QString &pluginName, const QString &themeName) const 0157 { 0158 auto it = std::find_if(m_plugins.cbegin(), m_plugins.cend(), [pluginName, themeName](const KDecoration2::DecorationThemeMetaData &d) { 0159 return d.pluginId() == pluginName && d.themeName() == themeName; 0160 }); 0161 if (it == m_plugins.cend()) { 0162 return QModelIndex(); 0163 } 0164 const auto distance = std::distance(m_plugins.cbegin(), it); 0165 return createIndex(distance, 0); 0166 } 0167 0168 } 0169 } 0170 0171 #include "moc_decorationmodel.cpp"