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