File indexing completed on 2024-11-10 04:56:48

0001 /*
0002     SPDX-FileCopyrightText: 2019 Valerio Pilo <vpilo@coldshock.net>
0003     SPDX-FileCopyrightText: 2019 Cyril Rossi <cyril.rossi@enioka.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-only
0006 */
0007 #include "kcm.h"
0008 
0009 #include <config-kwin.h>
0010 
0011 #include "declarative-plugin/buttonsmodel.h"
0012 #include "decorationmodel.h"
0013 
0014 #include <KConfigGroup>
0015 #include <KLocalizedString>
0016 #include <KPluginFactory>
0017 
0018 #include <QDBusConnection>
0019 #include <QDBusMessage>
0020 #include <QDebug>
0021 #include <QQuickItem>
0022 #include <QQuickWindow>
0023 #include <QSortFilterProxyModel>
0024 
0025 #include "kwindecorationdata.h"
0026 #include "kwindecorationsettings.h"
0027 #include "utils.h"
0028 
0029 K_PLUGIN_FACTORY_WITH_JSON(KCMKWinDecorationFactory, "kcm_kwindecoration.json", registerPlugin<KCMKWinDecoration>(); registerPlugin<KWinDecorationData>();)
0030 
0031 Q_DECLARE_METATYPE(KDecoration2::BorderSize)
0032 
0033 namespace
0034 {
0035 const KDecoration2::BorderSize s_defaultRecommendedBorderSize = KDecoration2::BorderSize::Normal;
0036 }
0037 
0038 KCMKWinDecoration::KCMKWinDecoration(QObject *parent, const KPluginMetaData &metaData)
0039     : KQuickManagedConfigModule(parent, metaData)
0040     , m_themesModel(new KDecoration2::Configuration::DecorationsModel(this))
0041     , m_proxyThemesModel(new QSortFilterProxyModel(this))
0042     , m_leftButtonsModel(new KDecoration2::Preview::ButtonsModel(DecorationButtonsList(), this))
0043     , m_rightButtonsModel(new KDecoration2::Preview::ButtonsModel(DecorationButtonsList(), this))
0044     , m_availableButtonsModel(new KDecoration2::Preview::ButtonsModel(this))
0045     , m_data(new KWinDecorationData(this))
0046 {
0047     setButtons(Apply | Default | Help);
0048     qmlRegisterAnonymousType<QAbstractListModel>("org.kde.kwin.KWinDecoration", 1);
0049     qmlRegisterAnonymousType<QSortFilterProxyModel>("org.kde.kwin.KWinDecoration", 1);
0050     qmlRegisterAnonymousType<KWinDecorationSettings>("org.kde.kwin.KWinDecoration", 1);
0051     m_proxyThemesModel->setSourceModel(m_themesModel);
0052     m_proxyThemesModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
0053     m_proxyThemesModel->setSortCaseSensitivity(Qt::CaseInsensitive);
0054     m_proxyThemesModel->sort(0);
0055 
0056     connect(m_proxyThemesModel, &QSortFilterProxyModel::rowsInserted, this, &KCMKWinDecoration::themeChanged);
0057     connect(m_proxyThemesModel, &QSortFilterProxyModel::rowsRemoved, this, &KCMKWinDecoration::themeChanged);
0058     connect(m_proxyThemesModel, &QSortFilterProxyModel::modelReset, this, &KCMKWinDecoration::themeChanged);
0059 
0060     connect(m_data->settings(), &KWinDecorationSettings::themeChanged, this, &KCMKWinDecoration::themeChanged);
0061     connect(m_data->settings(), &KWinDecorationSettings::borderSizeChanged, this, &KCMKWinDecoration::borderSizeChanged);
0062 
0063     connect(m_data->settings(), &KWinDecorationSettings::borderSizeAutoChanged, this, &KCMKWinDecoration::borderIndexChanged);
0064     connect(this, &KCMKWinDecoration::borderSizeChanged, this, &KCMKWinDecoration::borderIndexChanged);
0065     connect(this, &KCMKWinDecoration::themeChanged, this, &KCMKWinDecoration::borderIndexChanged);
0066 
0067     connect(this, &KCMKWinDecoration::themeChanged, this, [this]() {
0068         if (m_data->settings()->borderSizeAuto()) {
0069             setBorderSize(recommendedBorderSize());
0070         }
0071     });
0072 
0073     connect(m_leftButtonsModel, &QAbstractItemModel::rowsInserted, this, &KCMKWinDecoration::onLeftButtonsChanged);
0074     connect(m_leftButtonsModel, &QAbstractItemModel::rowsMoved, this, &KCMKWinDecoration::onLeftButtonsChanged);
0075     connect(m_leftButtonsModel, &QAbstractItemModel::rowsRemoved, this, &KCMKWinDecoration::onLeftButtonsChanged);
0076     connect(m_leftButtonsModel, &QAbstractItemModel::modelReset, this, &KCMKWinDecoration::onLeftButtonsChanged);
0077 
0078     connect(m_rightButtonsModel, &QAbstractItemModel::rowsInserted, this, &KCMKWinDecoration::onRightButtonsChanged);
0079     connect(m_rightButtonsModel, &QAbstractItemModel::rowsMoved, this, &KCMKWinDecoration::onRightButtonsChanged);
0080     connect(m_rightButtonsModel, &QAbstractItemModel::rowsRemoved, this, &KCMKWinDecoration::onRightButtonsChanged);
0081     connect(m_rightButtonsModel, &QAbstractItemModel::modelReset, this, &KCMKWinDecoration::onRightButtonsChanged);
0082 
0083     connect(this, &KCMKWinDecoration::borderSizeChanged, this, &KCMKWinDecoration::settingsChanged);
0084 
0085     // Update the themes when the color scheme or a theme's settings change
0086     QDBusConnection::sessionBus()
0087         .connect(QString(), QStringLiteral("/KWin"), QStringLiteral("org.kde.KWin"), QStringLiteral("reloadConfig"),
0088                  this, SLOT(reloadKWinSettings()));
0089 
0090     QMetaObject::invokeMethod(m_themesModel, &KDecoration2::Configuration::DecorationsModel::init, Qt::QueuedConnection);
0091 }
0092 
0093 KWinDecorationSettings *KCMKWinDecoration::settings() const
0094 {
0095     return m_data->settings();
0096 }
0097 
0098 void KCMKWinDecoration::reloadKWinSettings()
0099 {
0100     QMetaObject::invokeMethod(m_themesModel, &KDecoration2::Configuration::DecorationsModel::init, Qt::QueuedConnection);
0101 }
0102 
0103 void KCMKWinDecoration::load()
0104 {
0105     KQuickManagedConfigModule::load();
0106 
0107     m_leftButtonsModel->replace(Utils::buttonsFromString(settings()->buttonsOnLeft()));
0108     m_rightButtonsModel->replace(Utils::buttonsFromString(settings()->buttonsOnRight()));
0109 
0110     setBorderSize(borderSizeIndexFromString(settings()->borderSize()));
0111 
0112     Q_EMIT themeChanged();
0113 }
0114 
0115 void KCMKWinDecoration::save()
0116 {
0117     if (!settings()->borderSizeAuto()) {
0118         settings()->setBorderSize(borderSizeIndexToString(m_borderSizeIndex));
0119     } else {
0120         settings()->setBorderSize(settings()->defaultBorderSizeValue());
0121     }
0122 
0123     KQuickManagedConfigModule::save();
0124 
0125     // Send a signal to all kwin instances
0126     QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KWin"),
0127                                                       QStringLiteral("org.kde.KWin"),
0128                                                       QStringLiteral("reloadConfig"));
0129     QDBusConnection::sessionBus().send(message);
0130 }
0131 
0132 void KCMKWinDecoration::defaults()
0133 {
0134     KQuickManagedConfigModule::defaults();
0135 
0136     setBorderSize(recommendedBorderSize());
0137 
0138     m_leftButtonsModel->replace(Utils::buttonsFromString(settings()->buttonsOnLeft()));
0139     m_rightButtonsModel->replace(Utils::buttonsFromString(settings()->buttonsOnRight()));
0140 }
0141 
0142 void KCMKWinDecoration::onLeftButtonsChanged()
0143 {
0144     settings()->setButtonsOnLeft(Utils::buttonsToString(m_leftButtonsModel->buttons()));
0145 }
0146 
0147 void KCMKWinDecoration::onRightButtonsChanged()
0148 {
0149     settings()->setButtonsOnRight(Utils::buttonsToString(m_rightButtonsModel->buttons()));
0150 }
0151 
0152 QSortFilterProxyModel *KCMKWinDecoration::themesModel() const
0153 {
0154     return m_proxyThemesModel;
0155 }
0156 
0157 QAbstractListModel *KCMKWinDecoration::leftButtonsModel()
0158 {
0159     return m_leftButtonsModel;
0160 }
0161 
0162 QAbstractListModel *KCMKWinDecoration::rightButtonsModel()
0163 {
0164     return m_rightButtonsModel;
0165 }
0166 
0167 QAbstractListModel *KCMKWinDecoration::availableButtonsModel() const
0168 {
0169     return m_availableButtonsModel;
0170 }
0171 
0172 QStringList KCMKWinDecoration::borderSizesModel() const
0173 {
0174     // Use index 0 for borderSizeAuto == true
0175     // The rest of indexes get offset by 1
0176     QStringList model = Utils::getBorderSizeNames().values();
0177     model.insert(0, i18nc("%1 is the name of a border size", "Theme's default (%1)", model.at(recommendedBorderSize())));
0178     return model;
0179 }
0180 
0181 int KCMKWinDecoration::borderIndex() const
0182 {
0183     return settings()->borderSizeAuto() ? 0 : m_borderSizeIndex + 1;
0184 }
0185 
0186 void KCMKWinDecoration::setBorderIndex(int index)
0187 {
0188     const bool borderAuto = (index == 0);
0189     settings()->setBorderSizeAuto(borderAuto);
0190     setBorderSize(borderAuto ? recommendedBorderSize() : index - 1);
0191 }
0192 
0193 int KCMKWinDecoration::borderSize() const
0194 {
0195     return m_borderSizeIndex;
0196 }
0197 
0198 int KCMKWinDecoration::recommendedBorderSize() const
0199 {
0200     typedef KDecoration2::Configuration::DecorationsModel::DecorationRole DecoRole;
0201     const QModelIndex proxyIndex = m_proxyThemesModel->index(theme(), 0);
0202     if (proxyIndex.isValid()) {
0203         const QModelIndex index = m_proxyThemesModel->mapToSource(proxyIndex);
0204         if (index.isValid()) {
0205             QVariant ret = m_themesModel->data(index, DecoRole::RecommendedBorderSizeRole);
0206             return Utils::getBorderSizeNames().keys().indexOf(Utils::stringToBorderSize(ret.toString()));
0207         }
0208     }
0209     return Utils::getBorderSizeNames().keys().indexOf(s_defaultRecommendedBorderSize);
0210 }
0211 
0212 int KCMKWinDecoration::theme() const
0213 {
0214     return m_proxyThemesModel->mapFromSource(m_themesModel->findDecoration(settings()->pluginName(), settings()->theme())).row();
0215 }
0216 
0217 void KCMKWinDecoration::setBorderSize(int index)
0218 {
0219     if (m_borderSizeIndex != index) {
0220         m_borderSizeIndex = index;
0221         Q_EMIT borderSizeChanged();
0222     }
0223 }
0224 
0225 void KCMKWinDecoration::setBorderSize(KDecoration2::BorderSize size)
0226 {
0227     settings()->setBorderSize(Utils::borderSizeToString(size));
0228 }
0229 
0230 void KCMKWinDecoration::setTheme(int index)
0231 {
0232     QModelIndex dataIndex = m_proxyThemesModel->index(index, 0);
0233     if (dataIndex.isValid()) {
0234         settings()->setTheme(m_proxyThemesModel->data(dataIndex, KDecoration2::Configuration::DecorationsModel::ThemeNameRole).toString());
0235         settings()->setPluginName(m_proxyThemesModel->data(dataIndex, KDecoration2::Configuration::DecorationsModel::PluginNameRole).toString());
0236         Q_EMIT themeChanged();
0237     }
0238 }
0239 
0240 bool KCMKWinDecoration::isSaveNeeded() const
0241 {
0242     return !settings()->borderSizeAuto() && borderSizeIndexFromString(settings()->borderSize()) != m_borderSizeIndex;
0243 }
0244 
0245 int KCMKWinDecoration::borderSizeIndexFromString(const QString &size) const
0246 {
0247     return Utils::getBorderSizeNames().keys().indexOf(Utils::stringToBorderSize(size));
0248 }
0249 
0250 QString KCMKWinDecoration::borderSizeIndexToString(int index) const
0251 {
0252     return Utils::borderSizeToString(Utils::getBorderSizeNames().keys().at(index));
0253 }
0254 
0255 #include "kcm.moc"
0256 #include "moc_kcm.cpp"