decorationmodel.cpp 6.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 * Copyright 2014  Martin Gräßlin <mgraesslin@kde.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License or (at your option) version 3 or any later version
 * accepted by the membership of KDE e.V. (or its successor approved
 * by the membership of KDE e.V.), which shall act as a proxy
 * defined in Section 14 of version 3 of the license.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
Martin Flöser's avatar
Martin Flöser committed
20
#include "decorationmodel.h"
21
22
23
// KDecoration2
#include <KDecoration2/DecorationSettings>
#include <KDecoration2/Decoration>
Martin Flöser's avatar
Martin Flöser committed
24
// KDE
25
26
#include <KPluginLoader>
#include <KPluginFactory>
27
#include <KPluginTrader>
28
29
// Qt
#include <QDebug>
30

31
namespace KDecoration2
Martin Flöser's avatar
Martin Flöser committed
32
33
{

34
namespace Configuration
35
{
36
static const QString s_pluginName = QStringLiteral("org.kde.kdecoration2");
Martin Flöser's avatar
Martin Flöser committed
37

38
39
DecorationsModel::DecorationsModel(QObject *parent)
    : QAbstractListModel(parent)
40
41
{
}
Martin Flöser's avatar
Martin Flöser committed
42

43
DecorationsModel::~DecorationsModel() = default;
Martin Flöser's avatar
Martin Flöser committed
44

45
int DecorationsModel::rowCount(const QModelIndex &parent) const
46
{
47
48
    if (parent.isValid()) {
        return 0;
Martin Flöser's avatar
Martin Flöser committed
49
    }
50
    return m_plugins.size();
51
}
Martin Flöser's avatar
Martin Flöser committed
52

53
QVariant DecorationsModel::data(const QModelIndex &index, int role) const
54
{
55
56
    if (!index.isValid() || index.column() != 0 || index.row() < 0 || index.row() >= int(m_plugins.size())) {
        return QVariant();
57
    }
58
59
60
61
    const Data &d = m_plugins.at(index.row());
    switch (role) {
    case Qt::DisplayRole:
        return d.visibleName;
62
    case PluginNameRole:
63
        return d.pluginName;
64
    case ThemeNameRole:
65
        return d.themeName;
66
    case ConfigurationRole:
67
        return d.configuration;
68
69
    case RecommendedBorderSizeRole:
        return Utils::borderSizeToString(d.recommendedBorderSize);
70
    }
71
    return QVariant();
72
}
Martin Flöser's avatar
Martin Flöser committed
73

74
QHash< int, QByteArray > DecorationsModel::roleNames() const
75
{
76
77
    QHash<int, QByteArray> roles({
        {Qt::DisplayRole, QByteArrayLiteral("display")},
78
79
        {PluginNameRole, QByteArrayLiteral("plugin")},
        {ThemeNameRole, QByteArrayLiteral("theme")},
80
81
        {ConfigurationRole, QByteArrayLiteral("configureable")},
        {RecommendedBorderSizeRole, QByteArrayLiteral("recommendedbordersize")}
82
83
    });
    return roles;
84
85
}

86
static bool isThemeEngine(const QVariantMap &decoSettingsMap)
87
{
88
89
90
91
92
    auto it = decoSettingsMap.find(QStringLiteral("themes"));
    if (it == decoSettingsMap.end()) {
        return false;
    }
    return it.value().toBool();
93
}
Martin Flöser's avatar
Martin Flöser committed
94

95
96
97
98
99
100
101
102
103
static bool isConfigureable(const QVariantMap &decoSettingsMap)
{
    auto it = decoSettingsMap.find(QStringLiteral("kcmodule"));
    if (it == decoSettingsMap.end()) {
        return false;
    }
    return it.value().toBool();
}

104
105
106
107
108
109
110
111
112
static KDecoration2::BorderSize recommendedBorderSize(const QVariantMap &decoSettingsMap)
{
    auto it = decoSettingsMap.find(QStringLiteral("recommendedBorderSize"));
    if (it == decoSettingsMap.end()) {
        return KDecoration2::BorderSize::Normal;
    }
    return Utils::stringToBorderSize(it.value().toString());
}

113
static QString themeListKeyword(const QVariantMap &decoSettingsMap)
114
{
115
116
117
    auto it = decoSettingsMap.find(QStringLiteral("themeListKeyword"));
    if (it == decoSettingsMap.end()) {
        return QString();
118
    }
119
    return it.value().toString();
120
}
Martin Flöser's avatar
Martin Flöser committed
121

122
123
124
125
126
127
128
129
130
static QString findKNewStuff(const QVariantMap &decoSettingsMap)
{
    auto it = decoSettingsMap.find(QStringLiteral("KNewStuff"));
    if (it == decoSettingsMap.end()) {
        return QString();
    }
    return it.value().toString();
}

131
void DecorationsModel::init()
132
{
133
    beginResetModel();
134
    m_plugins.clear();
135
136
137
138
139
140
    const auto plugins = KPluginTrader::self()->query(s_pluginName, s_pluginName);
    for (const auto &info : plugins) {
        KPluginLoader loader(info.libraryPath());
        KPluginFactory *factory = loader.factory();
        if (!factory) {
            continue;
141
        }
142
        auto metadata = loader.metaData().value(QStringLiteral("MetaData")).toObject().value(s_pluginName);
143
        Data data;
144
145
        if (!metadata.isUndefined()) {
            const auto decoSettingsMap = metadata.toObject().toVariantMap();
146
            const QString &kns = findKNewStuff(decoSettingsMap);
147
148
            if (!kns.isEmpty() && !m_knsProviders.contains(kns)) {
                m_knsProviders.append(kns);
149
            }
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
            if (isThemeEngine(decoSettingsMap)) {
                const QString keyword = themeListKeyword(decoSettingsMap);
                if (keyword.isNull()) {
                    // We cannot list the themes
                    continue;
                }
                QScopedPointer<QObject> themeFinder(factory->create<QObject>(keyword));
                if (themeFinder.isNull()) {
                    continue;
                }
                QVariant themes = themeFinder->property("themes");
                if (!themes.isValid()) {
                    continue;
                }
                const auto themesMap = themes.toMap();
                for (auto it = themesMap.begin(); it != themesMap.end(); ++it) {
                    Data d;
                    d.pluginName = info.pluginName();
                    d.themeName = it.value().toString();
                    d.visibleName = it.key();
170
171
172
                    QMetaObject::invokeMethod(themeFinder.data(), "hasConfiguration",
                                              Q_RETURN_ARG(bool, d.configuration),
                                              Q_ARG(QString, d.themeName));
173
174
175
176
177
178
                    m_plugins.emplace_back(std::move(d));
                }

                // it's a theme engine, we don't want to show this entry
                continue;
            }
179
180
            data.configuration = isConfigureable(decoSettingsMap);
            data.recommendedBorderSize = recommendedBorderSize(decoSettingsMap);
181
        }
182
183
        data.pluginName = info.pluginName();
        data.visibleName = info.name().isEmpty() ? info.pluginName() : info.name();
184
        data.themeName = data.visibleName;
Martin Flöser's avatar
Martin Flöser committed
185

186
        m_plugins.emplace_back(std::move(data));
187
    }
188
    endResetModel();
189
190
}

191
QModelIndex DecorationsModel::findDecoration(const QString &pluginName, const QString &themeName) const
192
{
193
194
195
196
197
198
199
    auto it = std::find_if(m_plugins.cbegin(), m_plugins.cend(),
        [pluginName, themeName](const Data &d) {
            return d.pluginName == pluginName && d.themeName == themeName;
        }
    );
    if (it == m_plugins.cend()) {
        return QModelIndex();
Martin Flöser's avatar
Martin Flöser committed
200
    }
201
202
    const auto distance = std::distance(m_plugins.cbegin(), it);
    return createIndex(distance, 0);
203
}
Martin Flöser's avatar
Martin Flöser committed
204

205
}
206
}