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"