kcm.cpp 10.3 KB
Newer Older
1
/*
Vlad Zahorodnii's avatar
Vlad Zahorodnii committed
2
3
4
5
6
    SPDX-FileCopyrightText: 2019 Valerio Pilo <vpilo@coldshock.net>
    SPDX-FileCopyrightText: 2019 Cyril Rossi <cyril.rossi@enioka.com>

    SPDX-License-Identifier: LGPL-2.0-only
*/
7

8
9
#include "kcm.h"
#include "decorationmodel.h"
10
#include "declarative-plugin/buttonsmodel.h"
11
#include <config-kwin.h>
12

13
#include <KAboutData>
14
#include <KConfigGroup>
15
#include <KLocalizedString>
16
#include <KPluginFactory>
17
18
#include <KNSCore/Engine>

19
20
#include <QDBusConnection>
#include <QDBusMessage>
21
#include <QDebug>
22
#include <QQuickItem>
23
#include <QQuickWindow>
24
#include <QSortFilterProxyModel>
25

26
27
#include <KNewStuff3/KNS3/DownloadDialog>

28
#include "kwindecorationdata.h"
29
#include "kwindecorationsettings.h"
30

31
K_PLUGIN_FACTORY_WITH_JSON(KCMKWinDecorationFactory, "kwindecoration.json", registerPlugin<KCMKWinDecoration>();registerPlugin<KWinDecorationData>();)
32

33
34
Q_DECLARE_METATYPE(KDecoration2::BorderSize)

35

36
namespace
37
{
38
const KDecoration2::BorderSize s_defaultRecommendedBorderSize = KDecoration2::BorderSize::Normal;
39
}
40

41
KCMKWinDecoration::KCMKWinDecoration(QObject *parent, const QVariantList &arguments)
42
    : KQuickAddons::ManagedConfigModule(parent, arguments)
43
44
45
46
47
    , m_themesModel(new KDecoration2::Configuration::DecorationsModel(this))
    , m_proxyThemesModel(new QSortFilterProxyModel(this))
    , m_leftButtonsModel(new KDecoration2::Preview::ButtonsModel(DecorationButtonsList(), this))
    , m_rightButtonsModel(new KDecoration2::Preview::ButtonsModel(DecorationButtonsList(), this))
    , m_availableButtonsModel(new KDecoration2::Preview::ButtonsModel(this))
48
    , m_data(new KWinDecorationData(this))
49
{
50
    auto about = new KAboutData(QStringLiteral("kcm_kwindecoration"),
51
                                i18n("Window Decorations"),
52
53
54
55
56
57
58
                                QStringLiteral("1.0"),
                                QString(),
                                KAboutLicense::GPL);
    about->addAuthor(i18n("Valerio Pilo"),
                     i18n("Author"),
                     QStringLiteral("vpilo@coldshock.net"));
    setAboutData(about);
59
    setButtons(Apply | Default | Help);
Laurent Montel's avatar
Laurent Montel committed
60
61
    qmlRegisterAnonymousType<QAbstractListModel>("org.kde.kwin.KWinDecoration", 1);
    qmlRegisterAnonymousType<QSortFilterProxyModel>("org.kde.kwin.KWinDecoration", 1);
62
    qmlRegisterAnonymousType<KWinDecorationSettings>("org.kde.kwin.KWinDecoration", 1);
63
64
65
66
67
    m_proxyThemesModel->setSourceModel(m_themesModel);
    m_proxyThemesModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
    m_proxyThemesModel->setSortCaseSensitivity(Qt::CaseInsensitive);
    m_proxyThemesModel->sort(0);

68
69
    connect(m_data->settings(), &KWinDecorationSettings::themeChanged, this, &KCMKWinDecoration::themeChanged);
    connect(m_data->settings(), &KWinDecorationSettings::borderSizeChanged, this, &KCMKWinDecoration::borderSizeChanged);
70

71
72
73
74
    connect(m_data->settings(), &KWinDecorationSettings::borderSizeAutoChanged, this, &KCMKWinDecoration::borderIndexChanged);
    connect(this, &KCMKWinDecoration::borderSizeChanged, this, &KCMKWinDecoration::borderIndexChanged);
    connect(this, &KCMKWinDecoration::themeChanged, this, &KCMKWinDecoration::borderIndexChanged);

75
76
77
78
79
80
    connect(this, &KCMKWinDecoration::themeChanged, this, [=](){
        if (m_data->settings()->borderSizeAuto()) {
            setBorderSize(recommendedBorderSize());
        }
    });

81
82
83
84
85
86
87
88
89
90
91
    connect(m_leftButtonsModel, &QAbstractItemModel::rowsInserted, this, &KCMKWinDecoration::onLeftButtonsChanged);
    connect(m_leftButtonsModel, &QAbstractItemModel::rowsMoved, this, &KCMKWinDecoration::onLeftButtonsChanged);
    connect(m_leftButtonsModel, &QAbstractItemModel::rowsRemoved, this, &KCMKWinDecoration::onLeftButtonsChanged);
    connect(m_leftButtonsModel, &QAbstractItemModel::modelReset, this, &KCMKWinDecoration::onLeftButtonsChanged);

    connect(m_rightButtonsModel, &QAbstractItemModel::rowsInserted, this, &KCMKWinDecoration::onRightButtonsChanged);
    connect(m_rightButtonsModel, &QAbstractItemModel::rowsMoved, this, &KCMKWinDecoration::onRightButtonsChanged);
    connect(m_rightButtonsModel, &QAbstractItemModel::rowsRemoved, this, &KCMKWinDecoration::onRightButtonsChanged);
    connect(m_rightButtonsModel, &QAbstractItemModel::modelReset, this, &KCMKWinDecoration::onRightButtonsChanged);

    connect(this, &KCMKWinDecoration::borderSizeChanged, this, &KCMKWinDecoration::settingsChanged);
92
93
94
95

    // Update the themes when the color scheme or a theme's settings change
    QDBusConnection::sessionBus()
        .connect(QString(), QStringLiteral("/KWin"), QStringLiteral("org.kde.KWin"), QStringLiteral("reloadConfig"),
96
            this, SLOT(reloadKWinSettings()));
97
98

    QMetaObject::invokeMethod(m_themesModel, "init", Qt::QueuedConnection);
99
100
}

101
102
KWinDecorationSettings *KCMKWinDecoration::settings() const
{
103
    return m_data->settings();
104
105
}

106
107
108
109
void KCMKWinDecoration::reloadKWinSettings()
{
    QMetaObject::invokeMethod(m_themesModel, "init", Qt::QueuedConnection);
}
110

111
void KCMKWinDecoration::getNewStuff(QQuickItem *context)
112
{
113
114
115
116
117
    if (!m_newStuffDialog) {
        m_newStuffDialog = new KNS3::DownloadDialog(QStringLiteral("window-decorations.knsrc"));
        m_newStuffDialog->setWindowTitle(i18n("Download New Window Decorations"));
        m_newStuffDialog->setWindowModality(Qt::WindowModal);
        connect(m_newStuffDialog, &KNS3::DownloadDialog::accepted, this, &KCMKWinDecoration::load);
118
    }
Thomas Lübking's avatar
Thomas Lübking committed
119

120
121
122
123
    if (context && context->window()) {
        m_newStuffDialog->winId(); // so it creates the windowHandle()
        m_newStuffDialog->windowHandle()->setTransientParent(context->window());
    }
Thomas Lübking's avatar
Thomas Lübking committed
124

125
126
    connect(m_newStuffDialog, &QDialog::finished, this, &KCMKWinDecoration::reloadKWinSettings);

127
    m_newStuffDialog->show();
128
129
}

130
131
void KCMKWinDecoration::load()
{
132
    ManagedConfigModule::load();
133

134
135
    m_leftButtonsModel->replace(Utils::buttonsFromString(settings()->buttonsOnLeft()));
    m_rightButtonsModel->replace(Utils::buttonsFromString(settings()->buttonsOnRight()));
136

137
    setBorderSize(borderSizeIndexFromString(settings()->borderSize()));
138

139
    emit themeChanged();
140
141
142
}

void KCMKWinDecoration::save()
143
{
144
145
    if (!settings()->borderSizeAuto()) {
        settings()->setBorderSize(borderSizeIndexToString(m_borderSizeIndex));
146
    } else {
147
        settings()->setBorderSize(settings()->defaultBorderSizeValue());
148
149
    }

150
    ManagedConfigModule::save();
151
152
153
154
155
156

    // Send a signal to all kwin instances
    QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KWin"),
                                                      QStringLiteral("org.kde.KWin"),
                                                      QStringLiteral("reloadConfig"));
    QDBusConnection::sessionBus().send(message);
157
158
}

159
void KCMKWinDecoration::defaults()
160
{
161
    ManagedConfigModule::defaults();
162

163
    setBorderSize(recommendedBorderSize());
164

165
166
    m_leftButtonsModel->replace(Utils::buttonsFromString(settings()->buttonsOnLeft()));
    m_rightButtonsModel->replace(Utils::buttonsFromString(settings()->buttonsOnRight()));
167
168
}

169
void KCMKWinDecoration::onLeftButtonsChanged()
170
{
171
    settings()->setButtonsOnLeft(Utils::buttonsToString(m_leftButtonsModel->buttons()));
172
173
174
175
}

void KCMKWinDecoration::onRightButtonsChanged()
{
176
    settings()->setButtonsOnRight(Utils::buttonsToString(m_rightButtonsModel->buttons()));
177
178
}

179
QSortFilterProxyModel *KCMKWinDecoration::themesModel() const
180
{
181
    return m_proxyThemesModel;
182
183
}

184
QAbstractListModel *KCMKWinDecoration::leftButtonsModel()
185
{
186
    return m_leftButtonsModel;
187
188
}

189
QAbstractListModel *KCMKWinDecoration::rightButtonsModel()
190
{
191
    return m_rightButtonsModel;
192
193
}

194
QAbstractListModel *KCMKWinDecoration::availableButtonsModel() const
195
{
196
197
    return m_availableButtonsModel;
}
198

199
200
QStringList KCMKWinDecoration::borderSizesModel() const
{
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
    // Use index 0 for borderSizeAuto == true
    // The rest of indexes get offset by 1
    QStringList model = Utils::getBorderSizeNames().values();
    model.insert(0, i18nc("%1 is the name of a border size",
                          "Theme's default (%1)", model.at(recommendedBorderSize())));
    return model;
}

int KCMKWinDecoration::borderIndex() const
{
    return settings()->borderSizeAuto() ? 0 : m_borderSizeIndex + 1;
}

void KCMKWinDecoration::setBorderIndex(int index)
{
    const bool borderAuto = (index == 0);
    settings()->setBorderSizeAuto(borderAuto);
    setBorderSize(borderAuto ? recommendedBorderSize() : index - 1);
219
220
}

221
int KCMKWinDecoration::borderSize() const
222
{
223
    return m_borderSizeIndex;
224
225
}

226
227
228
int KCMKWinDecoration::recommendedBorderSize() const
{
    typedef KDecoration2::Configuration::DecorationsModel::DecorationRole DecoRole;
229
    const QModelIndex proxyIndex = m_proxyThemesModel->index(theme(), 0);
230
231
232
233
234
235
236
237
238
239
    if (proxyIndex.isValid()) {
        const QModelIndex index = m_proxyThemesModel->mapToSource(proxyIndex);
        if (index.isValid()) {
            QVariant ret = m_themesModel->data(index, DecoRole::RecommendedBorderSizeRole);
            return Utils::getBorderSizeNames().keys().indexOf(Utils::stringToBorderSize(ret.toString()));
        }
    }
    return Utils::getBorderSizeNames().keys().indexOf(s_defaultRecommendedBorderSize);
}

240
int KCMKWinDecoration::theme() const
241
{
242
    return m_proxyThemesModel->mapFromSource(m_themesModel->findDecoration(settings()->pluginName(), settings()->theme())).row();
243
244
}

245
void KCMKWinDecoration::setBorderSize(int index)
246
{
247
248
249
250
    if (m_borderSizeIndex != index) {
        m_borderSizeIndex = index;
        emit borderSizeChanged();
    }
251
252
}

253
void KCMKWinDecoration::setBorderSize(KDecoration2::BorderSize size)
Thomas Lübking's avatar
Thomas Lübking committed
254
{
255
    settings()->setBorderSize(Utils::borderSizeToString(size));
Thomas Lübking's avatar
Thomas Lübking committed
256
257
}

258
void KCMKWinDecoration::setTheme(int index)
Thomas Lübking's avatar
Thomas Lübking committed
259
{
260
261
    QModelIndex dataIndex = m_proxyThemesModel->index(index, 0);
    if (dataIndex.isValid()) {
262
263
        settings()->setTheme(m_proxyThemesModel->data(dataIndex, KDecoration2::Configuration::DecorationsModel::ThemeNameRole).toString());
        settings()->setPluginName(m_proxyThemesModel->data(dataIndex, KDecoration2::Configuration::DecorationsModel::PluginNameRole).toString());
264
        emit themeChanged();
265
    }
Thomas Lübking's avatar
Thomas Lübking committed
266
267
}

268
bool KCMKWinDecoration::isSaveNeeded() const
269
{
270
    return !settings()->borderSizeAuto() && borderSizeIndexFromString(settings()->borderSize()) != m_borderSizeIndex;
271
272
}

273
int KCMKWinDecoration::borderSizeIndexFromString(const QString &size) const
274
{
275
    return Utils::getBorderSizeNames().keys().indexOf(Utils::stringToBorderSize(size));
276
277
}

278
QString KCMKWinDecoration::borderSizeIndexToString(int index) const
279
{
280
    return Utils::borderSizeToString(Utils::getBorderSizeNames().keys().at(index));
281
282
}

283
#include "kcm.moc"