diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -466,6 +466,7 @@ popup_input_filter.cpp rootinfo_filter.cpp rules.cpp + rulebooksettings.cpp scene.cpp screenedge.cpp screenlockerwatcher.cpp @@ -556,6 +557,8 @@ kconfig_add_kcfg_files(kwin_SRCS settings.kcfgc) kconfig_add_kcfg_files(kwin_SRCS colorcorrection/colorcorrect_settings.kcfgc) +kconfig_add_kcfg_files(kwin_SRCS rulesettings.kcfgc) +kconfig_add_kcfg_files(kwin_SRCS rulebooksettingsbase.kcfgc) qt5_add_dbus_adaptor(kwin_SRCS org.kde.KWin.xml dbusinterface.h KWin::DBusInterface) qt5_add_dbus_adaptor(kwin_SRCS org.kde.kwin.Compositing.xml dbusinterface.h KWin::CompositorDBusInterface) diff --git a/kcmkwin/kwinrules/CMakeLists.txt b/kcmkwin/kwinrules/CMakeLists.txt --- a/kcmkwin/kwinrules/CMakeLists.txt +++ b/kcmkwin/kwinrules/CMakeLists.txt @@ -6,10 +6,13 @@ include_directories(../../) set(kwinrules_MOC_HDRS yesnobox.h ../../cursor.h ../../plugins/platforms/x11/standalone/x11cursor.h) qt5_wrap_cpp(kwinrules_MOC_SRCS ${kwinrules_MOC_HDRS}) -set(kwinrules_SRCS ruleswidget.cpp ruleslist.cpp kwinsrc.cpp detectwidget.cpp main.cpp ${kwinrules_MOC_SRCS}) +set(kwinrules_SRCS ../../rulebooksettings.cpp ruleswidget.cpp ruleslist.cpp kwinsrc.cpp detectwidget.cpp main.cpp ${kwinrules_MOC_SRCS}) ki18n_wrap_ui(kwinrules_SRCS ruleslist.ui detectwidget.ui editshortcut.ui ruleswidgetbase.ui) +kconfig_add_kcfg_files(kwinrules_SRCS ../../rulesettings.kcfgc) +kconfig_add_kcfg_files(kwinrules_SRCS ../../rulebooksettingsbase.kcfgc) + add_executable(kwin_rules_dialog ${kwinrules_SRCS}) set(kwin_kcm_rules_XCB_LIBS diff --git a/kcmkwin/kwinrules/kcm.h b/kcmkwin/kwinrules/kcm.h --- a/kcmkwin/kwinrules/kcm.h +++ b/kcmkwin/kwinrules/kcm.h @@ -44,7 +44,6 @@ void moduleChanged(bool state); private: KCMRulesList* widget; - KConfig config; }; } // namespace diff --git a/kcmkwin/kwinrules/kcm.cpp b/kcmkwin/kwinrules/kcm.cpp --- a/kcmkwin/kwinrules/kcm.cpp +++ b/kcmkwin/kwinrules/kcm.cpp @@ -39,7 +39,6 @@ KCMRules::KCMRules(QWidget *parent, const QVariantList &) : KCModule(parent) - , config("kwinrulesrc", KConfig::NoGlobals) { QVBoxLayout *layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); @@ -56,17 +55,14 @@ void KCMRules::load() { - config.reparseConfiguration(); widget->load(); emit KCModule::changed(false); } void KCMRules::save() { widget->save(); emit KCModule::changed(false); - // Send signal to kwin - config.sync(); // Send signal to all kwin instances QDBusMessage message = QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig"); diff --git a/kcmkwin/kwinrules/kwinsrc.cpp b/kcmkwin/kwinrules/kwinsrc.cpp --- a/kcmkwin/kwinrules/kwinsrc.cpp +++ b/kcmkwin/kwinrules/kwinsrc.cpp @@ -19,7 +19,6 @@ // Include some code from kwin core in order to avoid // double implementation. -#include "ruleslist.h" #include "../../cursor.cpp" #include "../../plugins/platforms/x11/standalone/x11cursor.cpp" #include "../../rules.cpp" diff --git a/kcmkwin/kwinrules/main.cpp b/kcmkwin/kwinrules/main.cpp --- a/kcmkwin/kwinrules/main.cpp +++ b/kcmkwin/kwinrules/main.cpp @@ -23,6 +23,7 @@ #include #include "ruleswidget.h" +#include "rulebooksettings.h" #include "../../rules.h" #include @@ -37,40 +38,7 @@ namespace KWin { -static void loadRules(QList< Rules* >& rules) -{ - KConfig _cfg("kwinrulesrc", KConfig::NoGlobals); - KConfigGroup cfg(&_cfg, "General"); - int count = cfg.readEntry("count", 0); - for (int i = 1; - i <= count; - ++i) { - cfg = KConfigGroup(&_cfg, QString::number(i)); - Rules* rule = new Rules(cfg); - rules.append(rule); - } -} - -static void saveRules(const QList< Rules* >& rules) -{ - KConfig cfg("kwinrulesrc", KConfig::NoGlobals); - QStringList groups = cfg.groupList(); - for (QStringList::ConstIterator it = groups.constBegin(); - it != groups.constEnd(); - ++it) - cfg.deleteGroup(*it); - cfg.group("General").writeEntry("count", rules.count()); - int i = 1; - for (QList< Rules* >::ConstIterator it = rules.constBegin(); - it != rules.constEnd(); - ++it) { - KConfigGroup cg(&cfg, QString::number(i)); - (*it)->write(cg); - ++i; - } -} - -static Rules* findRule(const QList< Rules* >& rules, const QVariantMap &data, bool whole_app) +static Rules *findRule(const QVector &rules, const QVariantMap &data, bool whole_app) { QByteArray wmclass_class = data.value("resourceClass").toByteArray().toLower(); QByteArray wmclass_name = data.value("resourceName").toByteArray().toLower(); @@ -80,11 +48,8 @@ QByteArray machine = data.value("clientMachine").toByteArray(); Rules* best_match = nullptr; int match_quality = 0; - for (QList< Rules* >::ConstIterator it = rules.constBegin(); - it != rules.constEnd(); - ++it) { + for (const auto rule : rules) { // try to find an exact match, i.e. not a generic rule - Rules* rule = *it; int quality = 0; bool generic = true; if (rule->wmclassmatch != Rules::ExactMatch) @@ -202,9 +167,9 @@ static void edit(const QVariantMap &data, bool whole_app) { - QList< Rules* > rules; - loadRules(rules); - Rules* orig_rule = findRule(rules, data, whole_app); + RuleBookSettings settings(KConfig::NoGlobals); + QVector rules = settings.rules(); + Rules *orig_rule = findRule(rules, data, whole_app); RulesDialog dlg; if (whole_app) dlg.setWindowTitle(i18nc("Window caption for the application wide rules dialog", "Edit Application-Specific Settings")); @@ -223,7 +188,8 @@ rules.prepend(edited_rule); delete orig_rule; } - saveRules(rules); + settings.setRules(rules); + settings.save(); // Send signal to all kwin instances QDBusMessage message = QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig"); diff --git a/kcmkwin/kwinrules/ruleslist.h b/kcmkwin/kwinrules/ruleslist.h --- a/kcmkwin/kwinrules/ruleslist.h +++ b/kcmkwin/kwinrules/ruleslist.h @@ -20,12 +20,12 @@ #ifndef __RULESLIST_H__ #define __RULESLIST_H__ -#include "../../rules.h" - #include "ui_ruleslist.h" +#include "rulebooksettings.h" namespace KWin { +class Rules; class KCMRulesList : public QWidget, Ui_KCMRulesList @@ -49,7 +49,8 @@ void importClicked(); void activeChanged(); private: - QVector< Rules* > rules; + QVector m_rules; + RuleBookSettings m_settings; }; } // namespace diff --git a/kcmkwin/kwinrules/ruleslist.cpp b/kcmkwin/kwinrules/ruleslist.cpp --- a/kcmkwin/kwinrules/ruleslist.cpp +++ b/kcmkwin/kwinrules/ruleslist.cpp @@ -22,6 +22,8 @@ #include #include +#include "../../rules.h" +#include "rulesettings.h" #include "ruleswidget.h" namespace KWin @@ -57,11 +59,8 @@ KCMRulesList::~KCMRulesList() { - for (QVector< Rules* >::Iterator it = rules.begin(); - it != rules.end(); - ++it) - delete *it; - rules.clear(); + qDeleteAll(m_rules); + m_rules.clear(); } void KCMRulesList::activeChanged() @@ -87,7 +86,7 @@ int pos = rules_listbox->currentRow() + 1; rules_listbox->insertItem(pos , rule->description); rules_listbox->setCurrentRow(pos, QItemSelectionModel::ClearAndSelect); - rules.insert(rules.begin() + pos, rule); + m_rules.insert(m_rules.begin() + pos, rule); emit changed(true); } @@ -97,11 +96,11 @@ if (pos == -1) return; RulesDialog dlg(this); - Rules* rule = dlg.edit(rules[ pos ], {}, false); - if (rule == rules[ pos ]) + Rules *rule = dlg.edit(m_rules[pos], {}, false); + if (rule == m_rules[pos]) return; - delete rules[ pos ]; - rules[ pos ] = rule; + delete m_rules[pos]; + m_rules[pos] = rule; rules_listbox->item(pos)->setText(rule->description); emit changed(true); } @@ -111,7 +110,7 @@ int pos = rules_listbox->currentRow(); Q_ASSERT(pos != -1); delete rules_listbox->takeItem(pos); - rules.erase(rules.begin() + pos); + m_rules.erase(m_rules.begin() + pos); emit changed(true); } @@ -123,9 +122,9 @@ QListWidgetItem * item = rules_listbox->takeItem(pos); rules_listbox->insertItem(pos - 1 , item); rules_listbox->setCurrentItem(item, QItemSelectionModel::ClearAndSelect); - Rules* rule = rules[ pos ]; - rules[ pos ] = rules[ pos - 1 ]; - rules[ pos - 1 ] = rule; + Rules *rule = m_rules[pos]; + m_rules[pos] = m_rules[pos - 1]; + m_rules[pos - 1] = rule; } emit changed(true); } @@ -138,9 +137,9 @@ QListWidgetItem * item = rules_listbox->takeItem(pos); rules_listbox->insertItem(pos + 1 , item); rules_listbox->setCurrentItem(item, QItemSelectionModel::ClearAndSelect); - Rules* rule = rules[ pos ]; - rules[ pos ] = rules[ pos + 1 ]; - rules[ pos + 1 ] = rule; + Rules *rule = m_rules[pos]; + m_rules[pos] = m_rules[pos + 1]; + m_rules[pos + 1] = rule; } emit changed(true); } @@ -153,41 +152,41 @@ i18n("KWin Rules (*.kwinrule)")); if (path.isEmpty()) return; - KConfig config(path, KConfig::SimpleConfig); - KConfigGroup group(&config, rules[pos]->description); - group.deleteGroup(); - rules[pos]->write(group); + const auto cfg = KSharedConfig::openConfig(path, KConfig::SimpleConfig); + RuleSettings settings(cfg, m_rules[pos]->description); + settings.setDefaults(); + m_rules[pos]->write(&settings); + settings.save(); } void KCMRulesList::importClicked() { QString path = QFileDialog::getOpenFileName(this, i18n("Import Rules"), QDir::home().absolutePath(), i18n("KWin Rules (*.kwinrule)")); if (path.isEmpty()) return; - KConfig config(path, KConfig::SimpleConfig); - QStringList groups = config.groupList(); + const auto config = KSharedConfig::openConfig(path, KConfig::SimpleConfig); + QStringList groups = config->groupList(); if (groups.isEmpty()) return; int pos = qMax(0, rules_listbox->currentRow()); - foreach (const QString &group, groups) { - KConfigGroup grp(&config, group); - const bool remove = grp.readEntry("DeleteRule", false); - Rules* new_rule = new Rules(grp); + for (const QString &group : groups) { + RuleSettings settings(config, group); + const bool remove = settings.deleteRule(); + Rules *new_rule = new Rules(&settings); // try to replace existing rule first - for (int i = 0; i < rules.count(); ++i) { - if (rules[i]->description == new_rule->description) { - delete rules[i]; + for (int i = 0; i < m_rules.count(); ++i) { + if (m_rules[i]->description == new_rule->description) { + delete m_rules[i]; if (remove) { - rules.remove(i); + m_rules.remove(i); delete rules_listbox->takeItem(i); delete new_rule; pos = qMax(0, rules_listbox->currentRow()); // might have changed! - } - else - rules[i] = new_rule; + } else + m_rules[i] = new_rule; new_rule = nullptr; break; } @@ -201,7 +200,7 @@ // plain insertion if (new_rule) { - rules.insert(pos, new_rule); + m_rules.insert(pos, new_rule); rules_listbox->insertItem(pos++, new_rule->description); } } @@ -211,47 +210,23 @@ void KCMRulesList::load() { rules_listbox->clear(); - for (QVector< Rules* >::Iterator it = rules.begin(); - it != rules.end(); - ++it) - delete *it; - rules.clear(); - KConfig _cfg("kwinrulesrc"); - KConfigGroup cfg(&_cfg, "General"); - int count = cfg.readEntry("count", 0); - rules.reserve(count); - for (int i = 1; - i <= count; - ++i) { - cfg = KConfigGroup(&_cfg, QString::number(i)); - Rules* rule = new Rules(cfg); - rules.append(rule); + m_settings.load(); + m_rules = m_settings.rules(); + for (const auto rule : qAsConst(m_rules)) { rules_listbox->addItem(rule->description); } - if (rules.count() > 0) + + if (m_rules.count() > 0) rules_listbox->setCurrentItem(rules_listbox->item(0)); else rules_listbox->setCurrentItem(nullptr); activeChanged(); } void KCMRulesList::save() { - KConfig cfg(QLatin1String("kwinrulesrc")); - QStringList groups = cfg.groupList(); - for (QStringList::ConstIterator it = groups.constBegin(); - it != groups.constEnd(); - ++it) - cfg.deleteGroup(*it); - cfg.group("General").writeEntry("count", rules.count()); - int i = 1; - for (QVector< Rules* >::ConstIterator it = rules.constBegin(); - it != rules.constEnd(); - ++it) { - KConfigGroup cg(&cfg, QString::number(i)); - (*it)->write(cg); - ++i; - } + m_settings.setRules(m_rules); + m_settings.save(); } void KCMRulesList::defaults() diff --git a/rulebooksettings.h b/rulebooksettings.h new file mode 100644 --- /dev/null +++ b/rulebooksettings.h @@ -0,0 +1,50 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2020 Henri Chain + +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) any later version. + +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 . +*********************************************************************/ + +#ifndef RULEBOOKSETTINGS_H +#define RULEBOOKSETTINGS_H + +#include "rulebooksettingsbase.h" +#include + +namespace KWin +{ +class Rules; +class RuleSettings; + +class RuleBookSettings : public RuleBookSettingsBase +{ +public: + RuleBookSettings(KSharedConfig::Ptr config, QObject *parent = nullptr); + RuleBookSettings(const QString &configname, KConfig::OpenFlags, QObject *parent = nullptr); + RuleBookSettings(KConfig::OpenFlags, QObject *parent = nullptr); + RuleBookSettings(QObject *parent = nullptr); + void setRules(const QVector &); + QVector rules(); + bool usrSave() override; + void usrRead() override; + +private: + QVector m_list; +}; + +} + +#endif // RULEBOOKSETTINGS_H diff --git a/rulebooksettings.cpp b/rulebooksettings.cpp new file mode 100644 --- /dev/null +++ b/rulebooksettings.cpp @@ -0,0 +1,108 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2020 Henri Chain + +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) any later version. + +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 . +*********************************************************************/ + +#include "rulebooksettings.h" +#include "rulesettings.h" + +namespace KWin +{ +RuleBookSettings::RuleBookSettings(KSharedConfig::Ptr config, QObject *parent) + : RuleBookSettingsBase(config, parent) +{ + for (int i = 1; i <= count(); i++) { + m_list.append(new RuleSettings(config, QString::number(i), this)); + } +} + +RuleBookSettings::RuleBookSettings(const QString &configname, KConfig::OpenFlags flags, QObject *parent) + : RuleBookSettings(KSharedConfig::openConfig(configname, flags), parent) +{ +} + +RuleBookSettings::RuleBookSettings(KConfig::OpenFlags flags, QObject *parent) + : RuleBookSettings(QStringLiteral("kwinrulesrc"), flags, parent) +{ +} + +RuleBookSettings::RuleBookSettings(QObject *parent) + : RuleBookSettings(KConfig::FullConfig, parent) +{ +} + +void RuleBookSettings::setRules(const QVector &rules) +{ + int i = 1; + const int list_length = m_list.length(); + for (const auto &rule : rules) { + RuleSettings *settings; + if (i <= list_length) { + settings = m_list[i - 1]; + settings->setDefaults(); + } else { + // If there are more rules than in cache + settings = new RuleSettings(this->sharedConfig(), QString::number(i), this); + m_list.append(settings); + } + rule->write(settings); + i++; + } + + setCount(rules.length()); +} + +QVector RuleBookSettings::rules() +{ + QVector result; + result.reserve(mCount); + // mCount is always <= m_list.length() + for (int i = 0; i < mCount; i++) { + result.append(new Rules(m_list[i])); + } + return result; +} + +bool RuleBookSettings::usrSave() +{ + bool result = true; + for (const auto &settings : qAsConst(m_list)) { + result &= settings->save(); + } + int nRuleGroups = sharedConfig()->groupList().length() - 1; + // Remove any extra groups currently in config + for (int i = mCount + 1; i <= nRuleGroups; i++) { + sharedConfig()->deleteGroup(QString::number(i)); + } + return result; +} + +void RuleBookSettings::usrRead() +{ + const int list_length = m_list.length(); + for (int i = 1; i <= mCount; i++) { + if (i <= list_length) { + m_list[i - 1]->load(); + } else { + // If there are more groups than in cache + m_list.append(new RuleSettings(sharedConfig(), QString::number(i), this)); + } + } +} + +} diff --git a/rulebooksettingsbase.kcfg b/rulebooksettingsbase.kcfg new file mode 100644 --- /dev/null +++ b/rulebooksettingsbase.kcfg @@ -0,0 +1,13 @@ + + + + + + + + 0 + + + diff --git a/rulebooksettingsbase.kcfgc b/rulebooksettingsbase.kcfgc new file mode 100644 --- /dev/null +++ b/rulebooksettingsbase.kcfgc @@ -0,0 +1,5 @@ +File=rulebooksettingsbase.kcfg +NameSpace=KWin +ClassName=RuleBookSettingsBase +Mutators=true +ParentInConstructor=true diff --git a/rules.h b/rules.h --- a/rules.h +++ b/rules.h @@ -25,7 +25,6 @@ #include #include #include -#include #include "placement.h" #include "options.h" @@ -40,6 +39,7 @@ class AbstractClient; class Rules; +class RuleSettings; #ifndef KCMRULES // only for kwin core @@ -101,7 +101,7 @@ { public: Rules(); - explicit Rules(const KConfigGroup&); + explicit Rules(const RuleSettings*); Rules(const QString&, bool temporary); enum Type { Position = 1<<0, Size = 1<<1, Desktop = 1<<2, @@ -130,7 +130,15 @@ RegExpMatch, LastStringMatch = RegExpMatch }; - void write(KConfigGroup&) const; + enum SetRule { + UnusedSetRule = Unused, + SetRuleDummy = 256 // so that it's at least short int + }; + enum ForceRule { + UnusedForceRule = Unused, + ForceRuleDummy = 256 // so that it's at least short int + }; + void write(RuleSettings*) const; bool isEmpty() const; #ifndef KCMRULES bool discardUsed(bool withdrawn); @@ -183,19 +191,9 @@ bool matchRole(const QByteArray& match_role) const; bool matchTitle(const QString& match_title) const; bool matchClientMachine(const QByteArray& match_machine, bool local) const; - enum SetRule { - UnusedSetRule = Unused, - SetRuleDummy = 256 // so that it's at least short int - }; - enum ForceRule { - UnusedForceRule = Unused, - ForceRuleDummy = 256 // so that it's at least short int - }; - void readFromCfg(const KConfigGroup& cfg); - static SetRule readSetRule(const KConfigGroup&, const QString& key); - static ForceRule readForceRule(const KConfigGroup&, const QString& key); - static NET::WindowType readType(const KConfigGroup&, const QString& key); - static QString readDecoColor(const KConfigGroup &cfg); + void readFromSettings(const RuleSettings *settings); + static ForceRule convertForceRule(int v); + static QString getDecoColor(const QString &themeName); #ifndef KCMRULES static bool checkSetRule(SetRule rule, bool init); static bool checkForceRule(ForceRule rule); diff --git a/rules.cpp b/rules.cpp --- a/rules.cpp +++ b/rules.cpp @@ -36,6 +36,9 @@ #include "workspace.h" #endif +#include "rulesettings.h" +#include "rulebooksettings.h" + namespace KWin { @@ -95,204 +98,173 @@ file.write(s.data(), s.length()); } file.flush(); - KConfig cfg(file.fileName(), KConfig::SimpleConfig); - readFromCfg(cfg.group(QString())); + auto cfg = KSharedConfig::openConfig(file.fileName(), KConfig::SimpleConfig); + RuleSettings settings(cfg, QString()); + readFromSettings(&settings); if (description.isEmpty()) description = QStringLiteral("temporary"); } -#define READ_MATCH_STRING( var, func ) \ - var = cfg.readEntry( #var ) func; \ - var##match = (StringMatch) qMax( FirstStringMatch, \ - qMin( LastStringMatch, static_cast< StringMatch >( cfg.readEntry( #var "match",0 )))); - -#define READ_SET_RULE( var, func, def ) \ - var = func ( cfg.readEntry( #var, def)); \ - var##rule = readSetRule( cfg, QStringLiteral( #var "rule" ) ); - -#define READ_SET_RULE_DEF( var , func, def ) \ - var = func ( cfg.readEntry( #var, def )); \ - var##rule = readSetRule( cfg, QStringLiteral( #var "rule" ) ); - -#define READ_FORCE_RULE( var, func, def) \ - var = func ( cfg.readEntry( #var, def)); \ - var##rule = readForceRule( cfg, QStringLiteral( #var "rule" ) ); +#define READ_MATCH_STRING(var, func) \ + var = settings->var() func; \ + var##match = static_cast(settings->var##match()) -#define READ_FORCE_RULE2( var, def, func, funcarg ) \ - var = func ( cfg.readEntry( #var, def),funcarg ); \ - var##rule = readForceRule( cfg, QStringLiteral( #var "rule" ) ); +#define READ_SET_RULE(var) \ + var = settings->var(); \ + var##rule = static_cast(settings->var##rule()) +#define READ_FORCE_RULE(var, func) \ + var = func(settings->var()); \ + var##rule = convertForceRule(settings->var##rule()) -Rules::Rules(const KConfigGroup& cfg) +Rules::Rules(const RuleSettings *settings) : temporary_state(0) { - readFromCfg(cfg); -} - -static int limit0to4(int i) -{ - return qMax(0, qMin(4, i)); + readFromSettings(settings); } -void Rules::readFromCfg(const KConfigGroup& cfg) +void Rules::readFromSettings(const RuleSettings *settings) { - description = cfg.readEntry("Description"); - if (description.isEmpty()) // capitalized first, lowercase for backwards compatibility - description = cfg.readEntry("description"); + description = settings->description(); + if (description.isEmpty()) { + description = settings->descriptionLegacy(); + } READ_MATCH_STRING(wmclass, .toLower().toLatin1()); - wmclasscomplete = cfg.readEntry("wmclasscomplete" , false); + wmclasscomplete = settings->wmclasscomplete(); READ_MATCH_STRING(windowrole, .toLower().toLatin1()); READ_MATCH_STRING(title,); READ_MATCH_STRING(clientmachine, .toLower().toLatin1()); - types = NET::WindowTypeMask(cfg.readEntry("types", NET::AllTypesMask)); - READ_FORCE_RULE2(placement, QString(), Placement::policyFromString, false); - READ_SET_RULE_DEF(position, , invalidPoint); - READ_SET_RULE(size, , QSize()); - if (size.isEmpty() && sizerule != (SetRule)Remember) + types = NET::WindowTypeMask(settings->types()); + READ_FORCE_RULE(placement,); + READ_SET_RULE(position); + READ_SET_RULE(size); + if (size.isEmpty() && sizerule != static_cast(Remember)) sizerule = UnusedSetRule; - READ_FORCE_RULE(minsize, , QSize()); + READ_FORCE_RULE(minsize,); if (!minsize.isValid()) minsize = QSize(1, 1); - READ_FORCE_RULE(maxsize, , QSize()); + READ_FORCE_RULE(maxsize,); if (maxsize.isEmpty()) maxsize = QSize(32767, 32767); - READ_FORCE_RULE(opacityactive, , 0); - if (opacityactive < 0 || opacityactive > 100) - opacityactive = 100; - READ_FORCE_RULE(opacityinactive, , 0); - if (opacityinactive < 0 || opacityinactive > 100) - opacityinactive = 100; - READ_SET_RULE(ignoregeometry, , false); - READ_SET_RULE(desktop, , 0); - READ_SET_RULE(screen, , 0); - READ_SET_RULE(activity, , QString()); - type = readType(cfg, QStringLiteral("type")); - typerule = type != NET::Unknown ? readForceRule(cfg, QStringLiteral("typerule")) : UnusedForceRule; - READ_SET_RULE(maximizevert, , false); - READ_SET_RULE(maximizehoriz, , false); - READ_SET_RULE(minimize, , false); - READ_SET_RULE(shade, , false); - READ_SET_RULE(skiptaskbar, , false); - READ_SET_RULE(skippager, , false); - READ_SET_RULE(skipswitcher, , false); - READ_SET_RULE(above, , false); - READ_SET_RULE(below, , false); - READ_SET_RULE(fullscreen, , false); - READ_SET_RULE(noborder, , false); - decocolor = readDecoColor(cfg); - decocolorrule = decocolor.isEmpty() ? UnusedForceRule : readForceRule(cfg, QStringLiteral("decocolorrule")); - READ_FORCE_RULE(blockcompositing, , false); - READ_FORCE_RULE(fsplevel, limit0to4, 0); // fsp is 0-4 - READ_FORCE_RULE(fpplevel, limit0to4, 0); // fpp is 0-4 - READ_FORCE_RULE(acceptfocus, , false); - READ_FORCE_RULE(closeable, , false); - READ_FORCE_RULE(autogroup, , false); - READ_FORCE_RULE(autogroupfg, , true); - READ_FORCE_RULE(autogroupid, , QString()); - READ_FORCE_RULE(strictgeometry, , false); - READ_SET_RULE(shortcut, , QString()); - READ_FORCE_RULE(disableglobalshortcuts, , false); - READ_SET_RULE(desktopfile, , QString()); + READ_FORCE_RULE(opacityactive,); + READ_FORCE_RULE(opacityinactive,); + READ_SET_RULE(ignoregeometry); + READ_SET_RULE(desktop); + READ_SET_RULE(screen); + READ_SET_RULE(activity); + READ_FORCE_RULE(type, static_cast); + if (type == NET::Unknown) + typerule = UnusedForceRule; + READ_SET_RULE(maximizevert); + READ_SET_RULE(maximizehoriz); + READ_SET_RULE(minimize); + READ_SET_RULE(shade); + READ_SET_RULE(skiptaskbar); + READ_SET_RULE(skippager); + READ_SET_RULE(skipswitcher); + READ_SET_RULE(above); + READ_SET_RULE(below); + READ_SET_RULE(fullscreen); + READ_SET_RULE(noborder); + + READ_FORCE_RULE(decocolor, getDecoColor); + if (decocolor.isEmpty()) + decocolorrule = UnusedForceRule; + + READ_FORCE_RULE(blockcompositing,); + READ_FORCE_RULE(fsplevel,); + READ_FORCE_RULE(fpplevel,); + READ_FORCE_RULE(acceptfocus,); + READ_FORCE_RULE(closeable,); + READ_FORCE_RULE(autogroup,); + READ_FORCE_RULE(autogroupfg,); + READ_FORCE_RULE(autogroupid,); + READ_FORCE_RULE(strictgeometry,); + READ_SET_RULE(shortcut); + READ_FORCE_RULE(disableglobalshortcuts,); + READ_SET_RULE(desktopfile); } #undef READ_MATCH_STRING #undef READ_SET_RULE #undef READ_FORCE_RULE #undef READ_FORCE_RULE2 -#define WRITE_MATCH_STRING( var, force ) \ - if ( !var.isEmpty() || force ) \ - { \ - cfg.writeEntry( #var, var ); \ - cfg.writeEntry( #var "match", (int)var##match ); \ - } \ - else \ +#define WRITE_MATCH_STRING(var, capital, force) \ + settings->set##capital##match(var##match); \ + if (!var.isEmpty() || force) \ { \ - cfg.deleteEntry( #var ); \ - cfg.deleteEntry( #var "match" ); \ + settings->set##capital(var); \ } -#define WRITE_SET_RULE( var, func ) \ - if ( var##rule != UnusedSetRule ) \ - { \ - cfg.writeEntry( #var, func ( var )); \ - cfg.writeEntry( #var "rule", (int)var##rule ); \ - } \ - else \ +#define WRITE_SET_RULE(var, capital, func) \ + settings->set##capital##rule(var##rule); \ + if (var##rule != UnusedSetRule) \ { \ - cfg.deleteEntry( #var ); \ - cfg.deleteEntry( #var "rule" ); \ + settings->set##capital(func(var)); \ } -#define WRITE_FORCE_RULE( var, func ) \ +#define WRITE_FORCE_RULE(var, capital, func) \ + settings->set##capital##rule(var##rule); \ if ( var##rule != UnusedForceRule ) \ { \ - cfg.writeEntry( #var, func ( var )); \ - cfg.writeEntry( #var "rule", (int)var##rule ); \ - } \ - else \ - { \ - cfg.deleteEntry( #var ); \ - cfg.deleteEntry( #var "rule" ); \ + settings->set##capital(func(var)); \ } -void Rules::write(KConfigGroup& cfg) const +void Rules::write(RuleSettings *settings) const { - cfg.writeEntry("Description", description); + settings->setDescription(description); // always write wmclass - WRITE_MATCH_STRING(wmclass, true); - cfg.writeEntry("wmclasscomplete", wmclasscomplete); - WRITE_MATCH_STRING(windowrole, false); - WRITE_MATCH_STRING(title, false); - WRITE_MATCH_STRING(clientmachine, false); - if (types != NET::AllTypesMask) - cfg.writeEntry("types", uint(types)); - else - cfg.deleteEntry("types"); - WRITE_FORCE_RULE(placement, Placement::policyToString); - WRITE_SET_RULE(position,); - WRITE_SET_RULE(size,); - WRITE_FORCE_RULE(minsize,); - WRITE_FORCE_RULE(maxsize,); - WRITE_FORCE_RULE(opacityactive,); - WRITE_FORCE_RULE(opacityinactive,); - WRITE_SET_RULE(ignoregeometry,); - WRITE_SET_RULE(desktop,); - WRITE_SET_RULE(screen,); - WRITE_SET_RULE(activity,); - WRITE_FORCE_RULE(type, int); - WRITE_SET_RULE(maximizevert,); - WRITE_SET_RULE(maximizehoriz,); - WRITE_SET_RULE(minimize,); - WRITE_SET_RULE(shade,); - WRITE_SET_RULE(skiptaskbar,); - WRITE_SET_RULE(skippager,); - WRITE_SET_RULE(skipswitcher,); - WRITE_SET_RULE(above,); - WRITE_SET_RULE(below,); - WRITE_SET_RULE(fullscreen,); - WRITE_SET_RULE(noborder,); + WRITE_MATCH_STRING(wmclass, Wmclass, true); + settings->setWmclasscomplete(wmclasscomplete); + WRITE_MATCH_STRING(windowrole, Windowrole, false); + WRITE_MATCH_STRING(title, Title, false); + WRITE_MATCH_STRING(clientmachine, Clientmachine, false); + settings->setTypes(types); + WRITE_FORCE_RULE(placement, Placement,); + WRITE_SET_RULE(position, Position,); + WRITE_SET_RULE(size, Size,); + WRITE_FORCE_RULE(minsize, Minsize,); + WRITE_FORCE_RULE(maxsize, Maxsize,); + WRITE_FORCE_RULE(opacityactive, Opacityactive,); + WRITE_FORCE_RULE(opacityinactive, Opacityinactive,); + WRITE_SET_RULE(ignoregeometry, Ignoregeometry,); + WRITE_SET_RULE(desktop, Desktop,); + WRITE_SET_RULE(screen, Screen,); + WRITE_SET_RULE(activity, Activity,); + WRITE_FORCE_RULE(type, Type,); + WRITE_SET_RULE(maximizevert, Maximizevert,); + WRITE_SET_RULE(maximizehoriz, Maximizehoriz,); + WRITE_SET_RULE(minimize, Minimize,); + WRITE_SET_RULE(shade, Shade,); + WRITE_SET_RULE(skiptaskbar, Skiptaskbar,); + WRITE_SET_RULE(skippager, Skippager,); + WRITE_SET_RULE(skipswitcher, Skipswitcher,); + WRITE_SET_RULE(above, Above,); + WRITE_SET_RULE(below, Below,); + WRITE_SET_RULE(fullscreen, Fullscreen,); + WRITE_SET_RULE(noborder, Noborder,); auto colorToString = [](const QString &value) -> QString { if (value.endsWith(QLatin1String(".colors"))) { return QFileInfo(value).baseName(); } else { return value; } }; - WRITE_FORCE_RULE(decocolor, colorToString); - WRITE_FORCE_RULE(blockcompositing,); - WRITE_FORCE_RULE(fsplevel,); - WRITE_FORCE_RULE(fpplevel,); - WRITE_FORCE_RULE(acceptfocus,); - WRITE_FORCE_RULE(closeable,); - WRITE_FORCE_RULE(autogroup,); - WRITE_FORCE_RULE(autogroupfg,); - WRITE_FORCE_RULE(autogroupid,); - WRITE_FORCE_RULE(strictgeometry,); - WRITE_SET_RULE(shortcut,); - WRITE_FORCE_RULE(disableglobalshortcuts,); - WRITE_SET_RULE(desktopfile,); + WRITE_FORCE_RULE(decocolor, Decocolor, colorToString); + WRITE_FORCE_RULE(blockcompositing, Blockcompositing,); + WRITE_FORCE_RULE(fsplevel, Fsplevel,); + WRITE_FORCE_RULE(fpplevel, Fpplevel,); + WRITE_FORCE_RULE(acceptfocus, Acceptfocus,); + WRITE_FORCE_RULE(closeable, Closeable,); + WRITE_FORCE_RULE(autogroup, Autogroup,); + WRITE_FORCE_RULE(autogroupfg, Autogroupfg,); + WRITE_FORCE_RULE(autogroupid, Autogroupid,); + WRITE_FORCE_RULE(strictgeometry, Strictgeometry,); + WRITE_SET_RULE(shortcut, Shortcut,); + WRITE_FORCE_RULE(disableglobalshortcuts, Disableglobalshortcuts,); + WRITE_SET_RULE(desktopfile, Desktopfile,); } #undef WRITE_MATCH_STRING @@ -340,33 +312,15 @@ && desktopfilerule == UnusedSetRule); } -Rules::SetRule Rules::readSetRule(const KConfigGroup& cfg, const QString& key) +Rules::ForceRule Rules::convertForceRule(int v) { - int v = cfg.readEntry(key, 0); - if (v >= DontAffect && v <= ForceTemporarily) - return static_cast< SetRule >(v); - return UnusedSetRule; -} - -Rules::ForceRule Rules::readForceRule(const KConfigGroup& cfg, const QString& key) -{ - int v = cfg.readEntry(key, 0); if (v == DontAffect || v == Force || v == ForceTemporarily) - return static_cast< ForceRule >(v); + return static_cast(v); return UnusedForceRule; } -NET::WindowType Rules::readType(const KConfigGroup& cfg, const QString& key) -{ - int v = cfg.readEntry(key, 0); - if (v >= NET::Normal && v <= NET::Splash) - return static_cast< NET::WindowType >(v); - return NET::Unknown; -} - -QString Rules::readDecoColor(const KConfigGroup &cfg) +QString Rules::getDecoColor(const QString &themeName) { - QString themeName = cfg.readEntry("decocolor", QString()); if (themeName.isEmpty()) { return QString(); } @@ -1067,14 +1021,7 @@ } else { m_config->reparseConfiguration(); } - int count = m_config->group("General").readEntry("count", 0); - for (int i = 1; - i <= count; - ++i) { - KConfigGroup cg(m_config, QString::number(i)); - Rules* rule = new Rules(cg); - m_rules.append(rule); - } + m_rules = RuleBookSettings(m_config).rules().toList(); } void RuleBook::save() @@ -1084,23 +1031,15 @@ qCWarning(KWIN_CORE) << "RuleBook::save invoked without prior invocation of RuleBook::load"; return; } - QStringList groups = m_config->groupList(); - for (QStringList::ConstIterator it = groups.constBegin(); - it != groups.constEnd(); - ++it) - m_config->deleteGroup(*it); - m_config->group("General").writeEntry("count", m_rules.count()); - int i = 1; - for (QList< Rules* >::ConstIterator it = m_rules.constBegin(); - it != m_rules.constEnd(); - ++it) { - if ((*it)->isTemporary()) - continue; - KConfigGroup cg(m_config, QString::number(i)); - (*it)->write(cg); - ++i; + QVector filteredRules; + for (const auto &rule : qAsConst(m_rules)) { + if (!rule->isTemporary()) { + filteredRules.append(rule); + } } - m_config->sync(); + RuleBookSettings settings(m_config); + settings.setRules(filteredRules); + settings.save(); } void RuleBook::temporaryRulesMessage(const QString& message) diff --git a/rulesettings.kcfg b/rulesettings.kcfg new file mode 100644 --- /dev/null +++ b/rulesettings.kcfg @@ -0,0 +1,435 @@ + + + + + + + + + + + + + + + false + + + + + + + Rules::UnimportantMatch + Rules::FirstStringMatch + Rules::LastStringMatch + + + + Rules::UnimportantMatch + + + + + + + + Rules::UnimportantMatch + Rules::FirstStringMatch + Rules::LastStringMatch + + + + + + + + Rules::UnimportantMatch + Rules::FirstStringMatch + Rules::LastStringMatch + + + + + + + + Rules::UnimportantMatch + Rules::FirstStringMatch + Rules::LastStringMatch + + + + + NET::AllTypesMask + + + + + + Placement::Smart + + + + Rules::UnusedForceRule + + + + + invalidPoint + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + + + + + Rules::UnusedForceRule + + + + + + + + + Rules::UnusedForceRule + + + + + 0 + 100 + 0 + + + + Rules::UnusedForceRule + + + + + 0 + 100 + 0 + + + + Rules::UnusedForceRule + + + + + false + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + 0 + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + 0 + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + NET::Normal + NET::Splash + NET::Unknown + + + + Rules::UnusedForceRule + + + + + false + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + false + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + false + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + false + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + false + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + false + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + false + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + false + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + false + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + false + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + false + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + + + + Rules::UnusedForceRule + + + + + false + + + + Rules::UnusedForceRule + + + + + 0 + 0 + 4 + + + + Rules::UnusedForceRule + + + + + 0 + 0 + 4 + + + + Rules::UnusedForceRule + + + + + false + + + + Rules::UnusedForceRule + + + + + false + + + + Rules::UnusedForceRule + + + + + false + + + + Rules::UnusedForceRule + + + + + true + + + + Rules::UnusedForceRule + + + + + + + + Rules::UnusedForceRule + + + + + false + + + + Rules::UnusedForceRule + + + + + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + + + false + + + + Rules::UnusedForceRule + + + + + + + + Rules::UnusedSetRule + static_cast<Rules::SetRule>(Rules::ForceTemporarily) + Rules::UnusedSetRule + + + diff --git a/rulesettings.kcfgc b/rulesettings.kcfgc new file mode 100644 --- /dev/null +++ b/rulesettings.kcfgc @@ -0,0 +1,7 @@ +File=rulesettings.kcfg +IncludeFiles=\"rules.h\",\"placement.h\",netwm_def.h +NameSpace=KWin +ClassName=RuleSettings +UseEnumTypes=true +Mutators=true +ParentInConstructor=true