diff --git a/kcmkwin/kwinrules/CMakeLists.txt b/kcmkwin/kwinrules/CMakeLists.txt
--- a/kcmkwin/kwinrules/CMakeLists.txt
+++ b/kcmkwin/kwinrules/CMakeLists.txt
@@ -1,14 +1,23 @@
# KI18N Translation Domain for this library
add_definitions(-DTRANSLATION_DOMAIN=\"kcmkwinrules\")
add_definitions(-DKCMRULES)
+
########### next target ###############
include_directories(../../)
-set(kwinrules_MOC_HDRS yesnobox.h ../../cursor.h ../../plugins/platforms/x11/standalone/x11cursor.h)
+set(kwinrules_MOC_HDRS ../../cursor.h ../../plugins/platforms/x11/standalone/x11cursor.h)
qt5_wrap_cpp(kwinrules_MOC_SRCS ${kwinrules_MOC_HDRS})
-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)
+set(kwinrules_SRCS
+ ../../rulebooksettings.cpp
+ optionsmodel.cpp
+ ruleitem.cpp
+ rulesmodel.cpp
+ rulesdialog.cpp
+ main.cpp
+ kwinsrc.cpp
+ ${kwinrules_MOC_SRCS}
+)
kconfig_add_kcfg_files(kwinrules_SRCS ../../rulesettings.kcfgc)
kconfig_add_kcfg_files(kwinrules_SRCS ../../rulebooksettingsbase.kcfgc)
@@ -24,6 +33,7 @@
set(kcm_libs
Qt5::Concurrent
Qt5::X11Extras
+ Qt5::QuickWidgets
KF5::Completion
KF5::ConfigWidgets
@@ -43,13 +53,33 @@
########### next target ###############
-set(kcm_kwinrules_PART_SRCS kcm.cpp ${kwinrules_SRCS})
+set(kcmkwinrules_qml_SRCS
+ kcmrules.cpp
+ ${kwinrules_SRCS}
+)
+
+add_library(kcm_kwinrules_qml MODULE ${kcmkwinrules_qml_SRCS})
+
+target_link_libraries(kcm_kwinrules_qml
+ Qt5::Quick
+
+ KF5::I18n
+ KF5::ConfigWidgets
+ KF5::CoreAddons
+ KF5::QuickAddons
+ KF5::WindowSystem
+
+ ${kcm_libs}
+ ${kwin_kcm_rules_XCB_LIBS}
+)
-add_library(kcm_kwinrules MODULE ${kcm_kwinrules_PART_SRCS})
+kcoreaddons_desktop_to_json(kcm_kwinrules_qml "kcm_kwinrules_qml.desktop" SERVICE_TYPES kcmodule.desktop)
-target_link_libraries(kcm_kwinrules ${kcm_libs} ${kwin_kcm_rules_XCB_LIBS})
+# This desktop file is installed only for retrocompatibility with sycoca
+install(TARGETS kcm_kwinrules_qml DESTINATION ${KDE_INSTALL_PLUGINDIR}/kcms)
+install(FILES kcm_kwinrules_qml.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR})
-install(TARGETS kcm_kwinrules DESTINATION ${PLUGIN_INSTALL_DIR})
+kpackage_install_package(package kcm_kwinrules_qml kcms)
########### install files ###############
diff --git a/kcmkwin/kwinrules/detectwidget.h b/kcmkwin/kwinrules/detectwidget.h
deleted file mode 100644
--- a/kcmkwin/kwinrules/detectwidget.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2004 Lubos Lunak
- *
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-
-#ifndef __DETECTWIDGET_H__
-#define __DETECTWIDGET_H__
-
-#include
-#include
-
-#include "../../rules.h"
-//Added by qt3to4:
-#include
-#include
-
-#include "ui_detectwidget.h"
-
-namespace KWin
-{
-
-class DetectWidget
- : public QWidget, public Ui_DetectWidget
-{
- Q_OBJECT
-public:
- explicit DetectWidget(QWidget* parent = nullptr);
-};
-
-class DetectDialog
- : public QDialog
-{
- Q_OBJECT
-public:
- explicit DetectDialog(QWidget* parent = nullptr, const char* name = nullptr);
- void detect(int secs = 0);
- QByteArray selectedClass() const;
- bool selectedWholeClass() const;
- QByteArray selectedRole() const;
- bool selectedWholeApp() const;
- NET::WindowType selectedType() const;
- QString selectedTitle() const;
- Rules::StringMatch titleMatch() const;
- QByteArray selectedMachine() const;
-
- const QVariantMap &windowInfo() const {
- return m_windowInfo;
- }
-
-Q_SIGNALS:
- void detectionDone(bool);
-private Q_SLOTS:
- void selectWindow();
-private:
- void executeDialog();
- QByteArray wmclass_class;
- QByteArray wmclass_name;
- QByteArray role;
- NET::WindowType type;
- QString title;
- QByteArray extrarole;
- QByteArray machine;
- DetectWidget* widget;
- QVariantMap m_windowInfo;
-};
-
-} // namespace
-
-#endif
diff --git a/kcmkwin/kwinrules/detectwidget.cpp b/kcmkwin/kwinrules/detectwidget.cpp
deleted file mode 100644
--- a/kcmkwin/kwinrules/detectwidget.cpp
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2004 Lubos Lunak
- *
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "detectwidget.h"
-#include "../../plugins/platforms/x11/standalone/x11cursor.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-Q_DECLARE_METATYPE(NET::WindowType)
-
-namespace KWin
-{
-
-DetectWidget::DetectWidget(QWidget* parent)
- : QWidget(parent)
-{
- setupUi(this);
-}
-
-DetectDialog::DetectDialog(QWidget* parent, const char* name)
- : QDialog(parent)
-{
- setObjectName(name);
- setModal(true);
- setLayout(new QVBoxLayout);
-
- widget = new DetectWidget(this);
- layout()->addWidget(widget);
-
- QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel, this);
- layout()->addWidget(buttons);
-
- connect(buttons, SIGNAL(accepted()), SLOT(accept()));
- connect(buttons, SIGNAL(rejected()), SLOT(reject()));
-}
-
-void DetectDialog::detect(int secs)
-{
- QTimer::singleShot(secs*1000, this, SLOT(selectWindow()));
-}
-
-void DetectDialog::executeDialog()
-{
- static const char* const types[] = {
- I18N_NOOP("Normal Window"),
- I18N_NOOP("Desktop"),
- I18N_NOOP("Dock (panel)"),
- I18N_NOOP("Toolbar"),
- I18N_NOOP("Torn-Off Menu"),
- I18N_NOOP("Dialog Window"),
- I18N_NOOP("Override Type"),
- I18N_NOOP("Standalone Menubar"),
- I18N_NOOP("Utility Window"),
- I18N_NOOP("Splash Screen")
- };
- widget->class_label->setText(wmclass_class + QLatin1String(" (") + wmclass_name + ' ' + wmclass_class + ')');
- widget->role_label->setText(role);
- widget->match_role->setEnabled(!role.isEmpty());
- if (type == NET::Unknown)
- widget->type_label->setText(i18n("Unknown - will be treated as Normal Window"));
- else
- widget->type_label->setText(i18n(types[ type ]));
- widget->title_label->setText(title);
- widget->machine_label->setText(machine);
- widget->adjustSize();
- adjustSize();
- if (width() < 4*height()/3)
- resize(4*height()/3, height());
- emit detectionDone(exec() == QDialog::Accepted);
-}
-
-QByteArray DetectDialog::selectedClass() const
-{
- if (widget->match_whole_class->isChecked())
- return wmclass_name + ' ' + wmclass_class;
- return wmclass_class;
-}
-
-bool DetectDialog::selectedWholeClass() const
-{
- return widget->match_whole_class->isChecked();
-}
-
-QByteArray DetectDialog::selectedRole() const
-{
- if (widget->match_role->isChecked())
- return role;
- return "";
-}
-
-QString DetectDialog::selectedTitle() const
-{
- return title;
-}
-
-Rules::StringMatch DetectDialog::titleMatch() const
-{
- return widget->match_title->isChecked() ? Rules::ExactMatch : Rules::UnimportantMatch;
-}
-
-bool DetectDialog::selectedWholeApp() const
-{
- return !widget->match_type->isChecked();
-}
-
-NET::WindowType DetectDialog::selectedType() const
-{
- return type;
-}
-
-QByteArray DetectDialog::selectedMachine() const
-{
- return machine;
-}
-
-void DetectDialog::selectWindow()
-{
- QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KWin"),
- QStringLiteral("/KWin"),
- QStringLiteral("org.kde.KWin"),
- QStringLiteral("queryWindowInfo"));
- QDBusPendingReply async = QDBusConnection::sessionBus().asyncCall(message);
-
- QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(async, this);
- connect(callWatcher, &QDBusPendingCallWatcher::finished, this,
- [this](QDBusPendingCallWatcher *self) {
- QDBusPendingReply reply = *self;
- self->deleteLater();
- if (!reply.isValid()) {
- emit detectionDone(false);
- return;
- }
- m_windowInfo = reply.value();
- wmclass_class = m_windowInfo.value("resourceClass").toByteArray();
- wmclass_name = m_windowInfo.value("resourceName").toByteArray();
- role = m_windowInfo.value("role").toByteArray();
- type = m_windowInfo.value("type").value();
- title = m_windowInfo.value("caption").toString();
- machine = m_windowInfo.value("clientMachine").toByteArray();
- executeDialog();
- }
- );
-}
-
-} // namespace
-
diff --git a/kcmkwin/kwinrules/detectwidget.ui b/kcmkwin/kwinrules/detectwidget.ui
deleted file mode 100644
--- a/kcmkwin/kwinrules/detectwidget.ui
+++ /dev/null
@@ -1,229 +0,0 @@
-
-
- KWin::DetectWidget
-
-
-
- 0
- 0
- 450
- 300
-
-
-
- -
-
-
- Information About Selected Window
-
-
- true
-
-
-
- 0
-
-
-
-
-
- Class:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- false
-
-
-
- -
-
-
-
- true
-
-
-
-
-
-
- false
-
-
-
- -
-
-
- Role:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- false
-
-
-
- -
-
-
-
- true
-
-
-
-
-
-
- false
-
-
-
- -
-
-
- Type:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- false
-
-
-
- -
-
-
-
- true
-
-
-
-
-
-
- false
-
-
-
- -
-
-
- Title:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- false
-
-
-
- -
-
-
-
- true
-
-
-
-
-
-
- false
-
-
-
- -
-
-
- Machine:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- false
-
-
-
- -
-
-
-
- true
-
-
-
-
-
-
- false
-
-
-
-
-
-
- -
-
-
- Match by primary class name and
-
-
- true
-
-
-
-
-
-
- Secondary class name (resulting in term in brackets)
-
-
-
- -
-
-
- Window role (can be used to select windows by function)
-
-
-
- -
-
-
- Window type (eg. all dialogs, but not the main windows)
-
-
-
- -
-
-
- Window title (very specific, can fail due to content changes or translation)
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Expanding
-
-
-
- 20
- 0
-
-
-
-
-
-
-
-
-
diff --git a/kcmkwin/kwinrules/editshortcut.ui b/kcmkwin/kwinrules/editshortcut.ui
deleted file mode 100644
--- a/kcmkwin/kwinrules/editshortcut.ui
+++ /dev/null
@@ -1,161 +0,0 @@
-
- EditShortcut
-
-
-
- 0
- 0
- 1194
- 447
-
-
-
- -
-
-
- A single shortcut can be easily assigned or cleared using the two buttons. Only shortcuts with modifiers can be used.<p>
-It is possible to have several possible shortcuts, and the first available shortcut will be used. The shortcuts are specified using shortcut sets separated by " - ". One set is specified as <i>base</i>+(<i>list</i>), where base are modifiers and list is a list of keys.<br>
-For example "<b>Shift+Alt+(123) Shift+Ctrl+(ABC)</b>" will first try <b>Shift+Alt+1</b>, then others with <b>Shift+Ctrl+C</b> as the last one.
-
-
- Qt::RichText
-
-
- true
-
-
-
- -
-
-
- QFrame::HLine
-
-
- QFrame::Sunken
-
-
-
- -
-
-
- -
-
-
-
-
-
- Qt::Vertical
-
-
- QSizePolicy::Expanding
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- &Single Shortcut
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Expanding
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- C&lear
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Expanding
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
-
- QFrame::HLine
-
-
- QFrame::Sunken
-
-
-
-
-
-
-
- KLineEdit
- QWidget
-
-
-
-
-
-
- pushButton1
- clicked()
- EditShortcut
- editShortcut()
-
-
- 20
- 20
-
-
- 20
- 20
-
-
-
-
- pushButton2
- clicked()
- EditShortcut
- clearShortcut()
-
-
- 20
- 20
-
-
- 20
- 20
-
-
-
-
-
diff --git a/kcmkwin/kwinrules/kcm.cpp b/kcmkwin/kwinrules/kcm.cpp
deleted file mode 100644
--- a/kcmkwin/kwinrules/kcm.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (c) 2004 Lubos Lunak
- *
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "kcm.h"
-
-#include
-//Added by qt3to4:
-#include
-#include
-#include
-#include
-#include
-
-#include "ruleslist.h"
-#include
-#include
-
-K_PLUGIN_FACTORY(KCMRulesFactory,
- registerPlugin();
- )
-
-namespace KWin
-{
-
-KCMRules::KCMRules(QWidget *parent, const QVariantList &)
- : KCModule(parent)
-{
- QVBoxLayout *layout = new QVBoxLayout(this);
- layout->setContentsMargins(0, 0, 0, 0);
-
- widget = new KCMRulesList(this);
- layout->addWidget(widget);
- connect(widget, SIGNAL(changed(bool)), SLOT(moduleChanged(bool)));
- KAboutData *about = new KAboutData(QStringLiteral("kcmkwinrules"),
- i18n("Window-Specific Settings Configuration Module"),
- QString(), QString(), KAboutLicense::GPL, i18n("(c) 2004 KWin and KControl Authors"));
- about->addAuthor(i18n("Lubos Lunak"), QString(), "l.lunak@kde.org");
- setAboutData(about);
- setButtons(KCModule::Help | KCModule::Apply);
-}
-
-void KCMRules::load()
-{
- widget->load();
- emit KCModule::changed(false);
-}
-
-void KCMRules::save()
-{
- widget->save();
- emit KCModule::changed(false);
- // Send signal to all kwin instances
- QDBusMessage message =
- QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig");
- QDBusConnection::sessionBus().send(message);
-
-}
-
-QString KCMRules::quickHelp() const
-{
- return i18n("Window-specific Settings
Here you can customize window settings specifically only"
- " for some windows.
"
- " Please note that this configuration will not take effect if you do not use"
- " KWin as your window manager. If you do use a different window manager, please refer to its documentation"
- " for how to customize window behavior.
");
-}
-
-void KCMRules::moduleChanged(bool state)
-{
- emit KCModule::changed(state);
-}
-
-}
-
-// i18n freeze :-/
-#if 0
-I18N_NOOP("Remember settings separately for every window")
-I18N_NOOP("Show internal settings for remembering")
-I18N_NOOP("Internal setting for remembering")
-#endif
-
-
-#include "kcm.moc"
diff --git a/kcmkwin/kwinrules/kcm_kwinrules_qml.desktop b/kcmkwin/kwinrules/kcm_kwinrules_qml.desktop
new file mode 100644
--- /dev/null
+++ b/kcmkwin/kwinrules/kcm_kwinrules_qml.desktop
@@ -0,0 +1,164 @@
+[Desktop Entry]
+Exec=kcmshell5 kwinrules_qml
+Icon=preferences-system-windows-actions
+Categories=Qt;KDE;X-KDE-settings-looknfeel;
+Type=Service
+
+X-KDE-ServiceTypes=KCModule
+X-KDE-Library=kcm_kwinrules_qml
+X-KDE-ParentApp=kcontrol
+X-KDE-System-Settings-Parent-Category=windowmanagement
+X-KDE-Weight=120
+
+X-KDE-FormFactors=desktop,tablet
+
+Name=Window Rules
+Name[ar]=قواعد النوافذ
+Name[bg]=Правила за прозорци
+Name[bs]=Pravila prozora
+Name[ca]=Regles de les finestres
+Name[ca@valencia]=Regles de les finestres
+Name[cs]=Pravidla oken
+Name[da]=Vinduesregler
+Name[de]=Fensterregeln
+Name[el]=Κανόνες παραθύρου
+Name[en_GB]=Window Rules
+Name[es]=Reglas de las ventanas
+Name[et]=Akna reeglid
+Name[eu]=Leihoaren arauak
+Name[fi]=Ikkunasäännöt
+Name[fr]=Règles de la fenêtre
+Name[ga]=Rialacha Fuinneog
+Name[gl]=Regras da xanela
+Name[gu]=વિન્ડો નિયમો
+Name[he]=כללי חלון
+Name[hi]=विंडो निय
+Name[hr]=Pravila prozora
+Name[hu]=Ablakszabályok
+Name[ia]=Regulas de fenestra
+Name[id]=Peraturan Window
+Name[is]=Gluggahegðunarreglur
+Name[it]=Regole delle finestre
+Name[ja]=ウィンドウルール
+Name[kk]=Терезе тәртібі
+Name[km]=ក្បួនបង្អួច
+Name[kn]=ವಿಂಡೋ ನಿಯಮಗಳು
+Name[ko]=창 규칙
+Name[lt]=Langų taisyklės
+Name[lv]=Loga noteikumi
+Name[mr]=चौकट नियम
+Name[nb]=Vindusregler
+Name[nds]=Finsterbedregen
+Name[nl]=Vensterregels
+Name[nn]=Vindaugsreglar
+Name[pa]=ਵਿੰਡੋ ਨਿਯਮ
+Name[pl]=Zasady okien
+Name[pt]=Regras das Janelas
+Name[pt_BR]=Regras das janelas
+Name[ro]=Reguli fereastră
+Name[ru]=Особые параметры окон
+Name[si]=කවුළු නීති
+Name[sk]=Pravidlá okien
+Name[sl]=Pravila za okna
+Name[sr]=Правила прозора
+Name[sr@ijekavian]=Правила прозора
+Name[sr@ijekavianlatin]=Pravila prozora
+Name[sr@latin]=Pravila prozora
+Name[sv]=Fönsterregler
+Name[th]=กฎต่าง ๆ ของหน้าต่าง
+Name[tr]=Pencere Kuralları
+Name[ug]=كۆزنەك بەلگىلىمىسى
+Name[uk]=Правила вікон
+Name[wa]=Rîles des finiesses
+Name[x-test]=xxWindow Rulesxx
+Name[zh_CN]=窗口规则
+Name[zh_TW]=視窗規則
+
+Comment=Individual Window Behavior
+Comment[bs]=Ponašanje pojedinog prozora
+Comment[ca]=Comportament individual de les finestres
+Comment[ca@valencia]=Comportament individual de les finestres
+Comment[cs]=Chování individuálních oken
+Comment[da]=Opførsel af enkeltvinduer
+Comment[de]=Individuelles Fensterverhalten
+Comment[el]=Συμπεριφορά ανεξάρτητου παραθύρου
+Comment[en_GB]=Individual Window Behaviour
+Comment[es]=Comportamiento de las ventanas individuales
+Comment[et]=Konkreetse akna käitumine
+Comment[eu]=Leihoen banakako portaera
+Comment[fi]=Yksittäisten ikkunoiden toiminta
+Comment[fr]=Comportement individuel des fenêtres
+Comment[gl]=Comportamento individual das xanelas
+Comment[he]=התנהגות חלונות ספציפים
+Comment[hu]=Egyéni ablakműveletek
+Comment[ia]=Comportamento de fenestra individual
+Comment[id]=Perilaku Window Individu
+Comment[it]=Comportamento della singola finestra
+Comment[ja]=個別のウィンドウの挙動
+Comment[ko]=개별 창 동작
+Comment[lt]=Individuali langų elgsena
+Comment[nb]=Oppførsel for individuelle vinduer
+Comment[nds]=Bedregen vun enkelte Finstern
+Comment[nl]=Individueel venstergedrag
+Comment[nn]=Åtferd for einskildvindauge
+Comment[pa]=ਵੱਖ-ਵੱਖ ਵਿੰਡੋ ਰਵੱਈਆ
+Comment[pl]=Wyjątkowe okna
+Comment[pt]=Comportamento das Janelas Individuais
+Comment[pt_BR]=Comportamento das janelas individuais
+Comment[ru]=Особые параметры конкретных окон
+Comment[sk]=Individuálne správanie okien
+Comment[sl]=Obnašanje posameznih oken
+Comment[sr]=Понашање појединачних прозора
+Comment[sr@ijekavian]=Понашање појединачних прозора
+Comment[sr@ijekavianlatin]=Ponašanje pojedinačnih prozora
+Comment[sr@latin]=Ponašanje pojedinačnih prozora
+Comment[sv]=Individuellt fönsterbeteende
+Comment[tr]=Bireysel Pencere Davranışı
+Comment[uk]=Поведінка окремих вікон
+Comment[x-test]=xxIndividual Window Behaviorxx
+Comment[zh_CN]=个别窗口行为
+Comment[zh_TW]=個別視窗行為
+
+X-KDE-Keywords=size,position,state,window behavior,windows,specific,workarounds,remember,rules
+X-KDE-Keywords[bs]=veličina,pozicija,grad,reagiranje prozora,prozori,specifičan,workarounds,sjećati se,pravila
+X-KDE-Keywords[ca]=mida,posició,estat,comportament de la finestra,finestres,específic,solucions alternatives,recorda,regles
+X-KDE-Keywords[ca@valencia]=mida,posició,estat,comportament de la finestra,finestres,específic,solucions alternatives,recorda,regles
+X-KDE-Keywords[da]=størrelse,position,tilstand,vinduesopførsel,vinduer,specifikt,workarounds,husk,regler
+X-KDE-Keywords[de]=Größe,Position,Status,Fensterverhalten,Fenster,Regeln
+X-KDE-Keywords[el]=μέγεθος,θέση,κατάσταση,συμπεριφορά παραθύρου,παράθυρα,ειδική,εναλλακτικές,απομνημόνευση,κανόνες
+X-KDE-Keywords[en_GB]=size,position,state,window behaviour,windows,specific,workarounds,remember,rules
+X-KDE-Keywords[es]=tamaño,posición,estado,comportamiento de las ventanas,ventanas,específicos,soluciones,recordatorio,reglas
+X-KDE-Keywords[et]=suurus,asukoht,olek,akende käitumine,aknad,meeldejätmine,reeglid
+X-KDE-Keywords[eu]=tamaina,posizio,egoera,leihoaren portaera,leihoak,zehatz,konponbide,gogorarazpen,arau
+X-KDE-Keywords[fi]=koko,sijainti,tila,ikkunoiden toiminta,ikkunat,erikoisasetukset,ikkunakohtaiset,korjaukset,muista,muistaminen,säännöt
+X-KDE-Keywords[fr]=taille, position, état, comportement de la fenêtre, fenêtres, spécifique, contournements, rappel, règles
+X-KDE-Keywords[ga]=méid,ionad,staid,oibriú na bhfuinneog,fuinneoga,sainiúil,réitigh seiftithe,meabhraigh,rialacha
+X-KDE-Keywords[gl]=tamaño,posición,estado,comportamento da xanela,xanelas,específico,regra
+X-KDE-Keywords[hu]=méret,elhelyezkedés,állapot,ablakműködés,ablakok,specifikus,kerülő megoldások,megjegyzés,szabályok
+X-KDE-Keywords[ia]=grandor,position,stato,comportamento de fenestra,fenestras,specific,workarounds,memora,regulas
+X-KDE-Keywords[id]=ukuran,posisi,kondisi,perilaku window,window,spesifik,sekeliling,ingat,peraturan
+X-KDE-Keywords[it]=dimensione,posizione,stato,comportamento della finestra,finestre,specifico,espedienti,ricorda,regole
+X-KDE-Keywords[kk]=size,position,state,window behavior,windows,specific,workarounds,remember,rules
+X-KDE-Keywords[km]=size,position,state,window behavior,windows,specific,workarounds,remember,rules
+X-KDE-Keywords[ko]=size,position,state,window behavior,windows,specific,workarounds,remember,rules,크기,위치,창 행동,창,창 지정,규칙
+X-KDE-Keywords[lt]=dydis,pozicija,vieta,būsena,busena,lango elgsena,langų elgsena,langu elgsena,langas,langai,apėjimas,apejimas,apėjimai,apejimai,specifiniai,tam tikri,tam tikros,tam tikrų,tam tikru,įsiminti,isiminti,atsiminti,prisiminti,taisyklės,taisykles
+X-KDE-Keywords[nb]=størrelse,plassering,vindusoppførsel,vindu,bestemt,løsninger,husk,regler
+X-KDE-Keywords[nds]=Grött,Positschoon,Tostand,Finsterbedregen,Finstern,besünner,Ümto,wohren,Regeln
+X-KDE-Keywords[nl]=grootte,positie,status,venstergedrag,vensters,specifiek,er omheen gewerkt,herinneren,regels
+X-KDE-Keywords[nn]=storleik,plassering,tilstand,vindaugsåtferd,vindauge,einskild,løysingar,unntak,hugs,reglar
+X-KDE-Keywords[pl]=rozmiar,pozycja,stan,zachowanie okna,okna,specyficzne,obejścia,zapamiętaj,reguły
+X-KDE-Keywords[pt]=tamanho,posição,estado,comportamento da janela,janelas,específico,alternativas,recordar,regras
+X-KDE-Keywords[pt_BR]=tamanho,posição,estado,comportamento da janela,janelas,específico,alternativas,lembrar,regras
+X-KDE-Keywords[ru]=size,position,state,window behavior,windows,specific,workarounds,remember,rules,размер,позиция,состояние,поведение окон,окна,специальный,специальные возможности,запомнить,правила
+X-KDE-Keywords[sk]=veľkosť,poloha,stav,správanie okien,okná,špecifický,workaroundy,pamätať,pravidlá
+X-KDE-Keywords[sl]=velikost,položaj,stanje,obnašanje oken,okna,določeno,popravki,pomnjenje,pravila
+X-KDE-Keywords[sr]=size,position,state,window behavior,windows,specific,workarounds,remember,rules,величина,положај,стање,понашање прозора,прозор,заобилазак,запамти,правила
+X-KDE-Keywords[sr@ijekavian]=size,position,state,window behavior,windows,specific,workarounds,remember,rules,величина,положај,стање,понашање прозора,прозор,заобилазак,запамти,правила
+X-KDE-Keywords[sr@ijekavianlatin]=size,position,state,window behavior,windows,specific,workarounds,remember,rules,veličina,položaj,stanje,ponašanje prozora,prozor,zaobilazak,zapamti,pravila
+X-KDE-Keywords[sr@latin]=size,position,state,window behavior,windows,specific,workarounds,remember,rules,veličina,položaj,stanje,ponašanje prozora,prozor,zaobilazak,zapamti,pravila
+X-KDE-Keywords[sv]=storlek,position,tillstånd,fönsterbeteende,fönster,specifik,kom ihåg,regler
+X-KDE-Keywords[tr]=boyut,konum,durum,pencere davranışı,pencere,özel,etrafından dolanmalar,anımsa,kurallar
+X-KDE-Keywords[uk]=size,position,state,window behavior,windows,specific,workarounds,remember,rules,розмір,розташування,місце,стан,поведінка,вікно,вікна,поведінка вікон,окрема,специфічна,окремо,запам’ятати,пам’ять,правило,правила
+X-KDE-Keywords[x-test]=xxsizexx,xxpositionxx,xxstatexx,xxwindow behaviorxx,xxwindowsxx,xxspecificxx,xxworkaroundsxx,xxrememberxx,xxrulesxx
+X-KDE-Keywords[zh_CN]=size,position,state,window behavior,windows,specific,workarounds,remember,rules,大小,位置,窗口行为,特定,记住,规则
+X-KDE-Keywords[zh_TW]=size,position,state,window behavior,windows,specific,workarounds,remember,rules
diff --git a/kcmkwin/kwinrules/kcmrules.h b/kcmkwin/kwinrules/kcmrules.h
new file mode 100644
--- /dev/null
+++ b/kcmkwin/kwinrules/kcmrules.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2020 Ismael Asensio
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#include
+#include "rulebooksettings.h"
+#include "rulesmodel.h"
+
+#include
+
+#include
+
+
+namespace KWin
+{
+
+class KCMKWinRules : public KQuickAddons::ConfigModule
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QStringList ruleBookModel READ ruleBookModel NOTIFY ruleBookModelChanged)
+ Q_PROPERTY(int editingIndex READ editingIndex NOTIFY editingIndexChanged)
+ Q_PROPERTY(RulesModel *rulesModel MEMBER m_rulesModel CONSTANT)
+
+public:
+ explicit KCMKWinRules(QObject *parent, const QVariantList &arguments);
+ ~KCMKWinRules() override;
+
+ Q_INVOKABLE void editRule(int index);
+
+ Q_INVOKABLE void createRule();
+ Q_INVOKABLE void removeRule(int index);
+ Q_INVOKABLE void moveRule(int sourceIndex, int destIndex);
+
+ Q_INVOKABLE void exportRule(int index);
+ Q_INVOKABLE void importRules();
+
+public slots:
+ void load() override;
+ void save() override;
+
+signals:
+ void ruleBookModelChanged();
+ void editingIndexChanged();
+
+private slots:
+ void updateNeedsSave();
+ void updateState();
+
+private:
+ QStringList ruleBookModel() const;
+ int editingIndex() const;
+ void saveCurrentRule();
+
+private:
+ RuleBookSettings *m_ruleBook;
+ QVector m_rules;
+ RulesModel* m_rulesModel;
+
+ int m_editingIndex = -1;
+};
+
+} // namespace
diff --git a/kcmkwin/kwinrules/kcmrules.cpp b/kcmkwin/kwinrules/kcmrules.cpp
new file mode 100644
--- /dev/null
+++ b/kcmkwin/kwinrules/kcmrules.cpp
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2004 Lubos Lunak
+ * Copyright (c) 2020 Ismael Asensio
+ *
+ * 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 .
+ */
+
+#include "kcmrules.h"
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+
+namespace
+{
+ const QString s_configFile { QLatin1String("kwinrulesrc") };
+}
+
+namespace KWin
+{
+
+KCMKWinRules::KCMKWinRules(QObject *parent, const QVariantList &arguments)
+ : KQuickAddons::ConfigModule(parent, arguments)
+ , m_ruleBook(new RuleBookSettings(this))
+ , m_rulesModel(new RulesModel(this))
+{
+ auto about = new KAboutData(QStringLiteral("kcm_kwinrules_qml"),
+ i18n("Window Rules"),
+ QStringLiteral("1.0"),
+ QString(),
+ KAboutLicense::GPL);
+ about->addAuthor(i18n("Ismael Asensio"),
+ i18n("Author"),
+ QStringLiteral("isma.af@gmail.com"));
+ setAboutData(about);
+
+ setQuickHelp(i18n("Window-specific Settings
Here you can customize window settings specifically only"
+ " for some windows."
+ " Please note that this configuration will not take effect if you do not use"
+ " KWin as your window manager. If you do use a different window manager, please refer to its documentation"
+ " for how to customize window behavior.
"));
+
+ connect(m_rulesModel, &RulesModel::descriptionChanged, this, [this]{
+ if (m_editingIndex >=0 && m_editingIndex < m_ruleBook->count()) {
+ m_rules.at(m_editingIndex)->description = m_rulesModel->description();
+ emit ruleBookModelChanged();
+ }
+ } );
+ connect(m_rulesModel, &RulesModel::dataChanged, this, &KCMKWinRules::updateNeedsSave);
+}
+
+KCMKWinRules::~KCMKWinRules() {
+ qDeleteAll(m_rules);
+}
+
+
+QStringList KCMKWinRules::ruleBookModel() const
+{
+ QStringList ruleDescriptionList;
+ for (const Rules *rule : qAsConst(m_rules)) {
+ ruleDescriptionList.append(rule->description);
+ }
+ return ruleDescriptionList;
+}
+
+
+void KCMKWinRules::load()
+{
+ m_ruleBook->load();
+ m_rules = m_ruleBook->rules();
+
+ setNeedsSave(false);
+ emit ruleBookModelChanged();
+
+ // Check if current index is no longer valid
+ if (m_editingIndex >= m_rules.count()) {
+ m_editingIndex = -1;
+ pop();
+ emit editingIndexChanged();
+ }
+ // Reset current index for rule editor
+ if (m_editingIndex > 0) {
+ m_rulesModel->importFromRules(m_rules.at(m_editingIndex));
+ }
+}
+
+void KCMKWinRules::save()
+{
+ saveCurrentRule();
+ m_ruleBook->setRules(m_rules);
+ m_ruleBook->save();
+
+ QDBusMessage message = QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig");
+ QDBusConnection::sessionBus().send(message);
+}
+
+void KCMKWinRules::updateState()
+{
+ m_ruleBook->setCount(m_rules.count());
+
+ emit editingIndexChanged();
+ emit ruleBookModelChanged();
+
+ updateNeedsSave();
+}
+
+void KCMKWinRules::updateNeedsSave()
+{
+ setNeedsSave(true);
+ emit needsSaveChanged();
+}
+
+void KCMKWinRules::saveCurrentRule()
+{
+ if (m_editingIndex < 0) {
+ return;
+ }
+ if (needsSave()) {
+ delete(m_rules[m_editingIndex]);
+ m_rules[m_editingIndex] = m_rulesModel->exportToRules();
+ }
+}
+
+
+int KCMKWinRules::editingIndex() const
+{
+ return m_editingIndex;
+}
+
+void KCMKWinRules::editRule(int index)
+{
+ if (index < 0 || index >= m_rules.count()) {
+ return;
+ }
+ saveCurrentRule();
+
+ m_editingIndex = index;
+ m_rulesModel->importFromRules(m_rules.at(m_editingIndex));
+
+ emit editingIndexChanged();
+
+ // Show and move to Rules Editor page
+ if (depth() < 2) {
+ push(QStringLiteral("RulesEditor.qml"));
+ }
+ setCurrentIndex(1);
+}
+
+void KCMKWinRules::createRule()
+{
+
+ m_rules.append(new Rules());
+ updateState();
+
+ const int newIndex = m_rules.count() - 1;
+ editRule(newIndex);
+
+ saveCurrentRule();
+}
+
+void KCMKWinRules::removeRule(int index)
+{
+ if (index < 0 || index >= m_rules.count()) {
+ return;
+ }
+
+ if (m_editingIndex == index) {
+ m_editingIndex = -1;
+ pop();
+ }
+
+ delete(m_rules.at(index));
+ m_rules.removeAt(index);
+
+ updateState();
+}
+
+void KCMKWinRules::moveRule(int sourceIndex, int destIndex)
+{
+ const int lastIndex = m_rules.count() - 1;
+ if (sourceIndex == destIndex
+ || (sourceIndex < 0 || sourceIndex > lastIndex)
+ || (destIndex < 0 || destIndex > lastIndex)) {
+ return;
+ }
+
+ m_rules.move(sourceIndex, destIndex);
+
+ if (m_editingIndex == sourceIndex) {
+ m_editingIndex = destIndex;
+ emit editingIndexChanged();
+ } else if (m_editingIndex > sourceIndex && m_editingIndex <= destIndex) {
+ m_editingIndex -= 1;
+ emit editingIndexChanged();
+ } else if (m_editingIndex < sourceIndex && m_editingIndex >= destIndex) {
+ m_editingIndex += 1;
+ emit editingIndexChanged();
+ }
+
+ emit ruleBookModelChanged();
+}
+
+void KCMKWinRules::exportRule(int index)
+{
+ Q_ASSERT(index >= 0 && index < m_rules.count());
+
+ saveCurrentRule();
+
+ const QString description = m_rules.at(index)->description;
+ const QString defaultPath = QDir(QDir::home()).filePath(description + QStringLiteral(".kwinrule"));
+ const QString path = QFileDialog::getSaveFileName(nullptr, i18n("Export Rules"), defaultPath,
+ i18n("KWin Rules (*.kwinrule)"));
+ if (path.isEmpty())
+ return;
+
+ const auto config = KSharedConfig::openConfig(path, KConfig::SimpleConfig);
+ RuleSettings settings(config, m_rules.at(index)->description);
+
+ settings.setDefaults();
+ m_rules.at(index)->write(&settings);
+ settings.save();
+}
+
+void KCMKWinRules::importRules()
+{
+ QString path = QFileDialog::getOpenFileName(nullptr,
+ i18n("Import Rules"),
+ QDir::home().absolutePath(),
+ i18n("KWin Rules (*.kwinrule)"));
+
+ if (path.isEmpty()) {
+ return;
+ }
+
+ const auto config = KSharedConfig::openConfig(path, KConfig::SimpleConfig);
+ const QStringList groups = config->groupList();
+ if (groups.isEmpty()) {
+ return;
+ }
+
+ for (const QString &groupName : groups) {
+ RuleSettings settings(config, groupName);
+
+ const bool remove = settings.deleteRule();
+ const QString importDescription = settings.description();
+ if (importDescription.isEmpty()) {
+ continue;
+ }
+
+ // Try to find a rule with the same description to replace
+ int newIndex = -2;
+ for (int index = 0; index < m_rules.count(); index++) {
+ if (m_rules.at(index)->description == importDescription) {
+ newIndex = index;
+ break;
+ }
+ }
+
+ if (remove) {
+ removeRule(newIndex);
+ continue;
+ }
+
+ Rules *newRule = new Rules(&settings);
+
+ if (newIndex < 0) {
+ m_rules.append(newRule);
+ } else {
+ delete m_rules[newIndex];
+ m_rules[newIndex] = newRule;
+ }
+
+ // Reset rule editor if the current rule changed when importing
+ if (m_editingIndex == newIndex) {
+ m_rulesModel->importFromRules(m_rules.at(m_editingIndex));
+ }
+ }
+
+ updateState();
+}
+
+K_PLUGIN_CLASS_WITH_JSON(KCMKWinRules, "kcm_kwinrules_qml.json");
+
+} // namespace
+
+#include "kcmrules.moc"
diff --git a/kcmkwin/kwinrules/main.cpp b/kcmkwin/kwinrules/main.cpp
--- a/kcmkwin/kwinrules/main.cpp
+++ b/kcmkwin/kwinrules/main.cpp
@@ -22,8 +22,8 @@
#include
#include
-#include "ruleswidget.h"
#include "rulebooksettings.h"
+#include "rulesdialog.h"
#include "../../rules.h"
#include
diff --git a/kcmkwin/kwinrules/optionsmodel.h b/kcmkwin/kwinrules/optionsmodel.h
new file mode 100644
--- /dev/null
+++ b/kcmkwin/kwinrules/optionsmodel.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2020 Ismael Asensio
+ *
+ * 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 .
+ */
+
+#ifndef KWIN_OPTIONS_MODEL_H
+#define KWIN_OPTIONS_MODEL_H
+
+#include
+
+#include
+#include
+#include
+
+
+namespace KWin {
+
+class OptionsModel : public QAbstractListModel
+{
+ Q_OBJECT
+ //TODO: After Qt 5.14 the QML ComboBox will allow to use the valueRole directly
+ // instead of changing the index. Remove this exposed property
+ Q_PROPERTY(int selectedIndex READ selectedIndex NOTIFY selectedIndexChanged)
+
+public:
+ struct Data {
+ Data(const QVariant &value, const QString &text, const QIcon &icon = {}, const QString &description = {})
+ : value(value)
+ , text(text)
+ , icon(icon)
+ , description(description)
+ {}
+ Data(const QVariant &value, const QString &text, const QString &description)
+ : value(value)
+ , text(text)
+ , description(description)
+ {}
+
+ QVariant value;
+ QString text;
+ QIcon icon;
+ QString description;
+ };
+
+public:
+ OptionsModel() : QAbstractListModel(), m_data(), m_index(0) {};
+ OptionsModel(const QList &data) : QAbstractListModel(), m_data(data), m_index(0) {};
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ QHash roleNames() const override;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+
+ QVariant value() const;
+ void setValue(QVariant value);
+ void resetValue();
+
+ void updateModelData(const QList &data);
+
+ //TODO: Remove after Qt 5.14
+ int selectedIndex() const;
+
+signals:
+ void selectedIndexChanged(int index);
+
+public:
+ QList m_data;
+
+protected:
+ int m_index = 0;
+};
+
+class RulePolicy : public OptionsModel
+{
+public:
+ enum Type {
+ NoPolicy,
+ StringMatch,
+ SetRule,
+ ForceRule
+ };
+
+public:
+ RulePolicy(Type type)
+ : OptionsModel(policyOptions(type))
+ , m_type(type)
+ {};
+
+ Type type() const;
+ int value() const;
+ QString policyKey(const QString &key) const;
+
+private:
+ static QList policyOptions(RulePolicy::Type type);
+
+private:
+ Type m_type;
+};
+
+} //namespace
+
+#endif //KWIN_OPTIONS_MODEL_H
diff --git a/kcmkwin/kwinrules/optionsmodel.cpp b/kcmkwin/kwinrules/optionsmodel.cpp
new file mode 100644
--- /dev/null
+++ b/kcmkwin/kwinrules/optionsmodel.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2020 Ismael Asensio
+ *
+ * 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 .
+ */
+
+#include "optionsmodel.h"
+
+#include
+
+
+namespace KWin
+{
+
+QHash OptionsModel::roleNames() const
+{
+ return {
+ {Qt::DisplayRole, QByteArrayLiteral("text")},
+ {Qt::UserRole, QByteArrayLiteral("value")},
+ {Qt::DecorationRole, QByteArrayLiteral("icon")},
+ {Qt::ToolTipRole, QByteArrayLiteral("description")},
+ {Qt::UserRole + 1, QByteArrayLiteral("iconName")},
+ };
+}
+
+int OptionsModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid()) {
+ return 0;
+ }
+ return m_data.size();
+}
+
+QVariant OptionsModel::data(const QModelIndex &index, int role) const
+{
+ if (!checkIndex(index, CheckIndexOption::IndexIsValid | CheckIndexOption::ParentIsInvalid)) {
+ return QVariant();
+ }
+
+ const Data data = m_data.at(index.row());
+
+ switch (role) {
+ case Qt::DisplayRole:
+ return data.text;
+ case Qt::UserRole:
+ return data.value;
+ case Qt::DecorationRole:
+ return data.icon;
+ case Qt::UserRole + 1:
+ return data.icon.name();
+ case Qt::ToolTipRole:
+ return data.description;
+ }
+ return QVariant();
+}
+
+int OptionsModel::selectedIndex() const
+{
+ return m_index;
+}
+
+QVariant OptionsModel::value() const
+{
+ if (m_data.isEmpty()) {
+ return QVariant();
+ }
+ return m_data.at(m_index).value;
+}
+
+void OptionsModel::setValue(QVariant value)
+{
+ if (this->value() == value) {
+ return;
+ }
+ for (int index = 0; index < m_data.count(); index++) {
+ if (m_data.at(index).value != value) {
+ continue;
+ }
+ if (m_index != index) {
+ m_index = index;
+ emit selectedIndexChanged(index);
+ }
+ }
+}
+
+void OptionsModel::resetValue()
+{
+ m_index = 0;
+ emit selectedIndexChanged(m_index);
+}
+
+void OptionsModel::updateModelData(const QList &data) {
+ beginResetModel();
+ m_data = data;
+ endResetModel();
+}
+
+
+RulePolicy::Type RulePolicy::type() const
+{
+ return m_type;
+}
+
+int RulePolicy::value() const
+{
+ if (m_type == RulePolicy::NoPolicy) {
+ return Rules::Apply; // To simplify external checks when rule has no policy
+ }
+ return OptionsModel::value().toInt();
+}
+
+QString RulePolicy::policyKey(const QString &key) const
+{
+ switch (m_type) {
+ case NoPolicy:
+ return QString();
+ case StringMatch:
+ return QStringLiteral("%1match").arg(key);
+ case SetRule:
+ case ForceRule:
+ return QStringLiteral("%1rule").arg(key);
+ }
+
+ return QString();
+}
+
+QList RulePolicy::policyOptions(RulePolicy::Type type)
+{
+ static const auto stringMatchOptions = QList {
+ {Rules::UnimportantMatch, i18n("Unimportant")},
+ {Rules::ExactMatch, i18n("Exact Match")},
+ {Rules::SubstringMatch, i18n("Substring Match")},
+ {Rules::RegExpMatch, i18n("Regular Expression")}
+ };
+
+ static const auto setRuleOptions = QList {
+ {Rules::DontAffect,
+ i18n("Do Not Affect"),
+ i18n("The window property will not be affected and therefore the default handling for it will be used."
+ "\nSpecifying this will block more generic window settings from taking effect.")},
+ {Rules::Apply,
+ i18n("Apply Initially"),
+ i18n("The window property will be only set to the given value after the window is created."
+ "\nNo further changes will be affected.")},
+ {Rules::Remember,
+ i18n("Remember"),
+ i18n("The value of the window property will be remembered and, every time the window"
+ " is created, the last remembered value will be applied.")},
+ {Rules::Force,
+ i18n("Force"),
+ i18n("The window property will be always forced to the given value.")},
+ {Rules::ApplyNow,
+ i18n("Apply Now"),
+ i18n("The window property will be set to the given value immediately and will not be affected later"
+ "\n(this action will be deleted afterwards).")},
+ {Rules::ForceTemporarily,
+ i18n("Force Temporarily"),
+ i18n("The window property will be forced to the given value until it is hidden"
+ "\n(this action will be deleted after the window is hidden).")}
+ };
+
+ static auto forceRuleOptions = QList {
+ setRuleOptions.at(0), // Rules::DontAffect
+ setRuleOptions.at(3), // Rules::Force
+ setRuleOptions.at(5), // Rules::ForceTemporarily
+ };
+
+ switch (type) {
+ case NoPolicy:
+ return {};
+ case StringMatch:
+ return stringMatchOptions;
+ case SetRule:
+ return setRuleOptions;
+ case ForceRule:
+ return forceRuleOptions;
+ }
+ return {};
+}
+
+} //namespace
diff --git a/kcmkwin/kwinrules/package/contents/ui/OptionsComboBox.qml b/kcmkwin/kwinrules/package/contents/ui/OptionsComboBox.qml
new file mode 100644
--- /dev/null
+++ b/kcmkwin/kwinrules/package/contents/ui/OptionsComboBox.qml
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2020 Ismael Asensio
+ *
+ * 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 .
+ */
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.12 as QQC2
+
+import org.kde.kirigami 2.10 as Kirigami
+
+
+QQC2.ComboBox {
+ id: optionsCombo
+
+ textRole: "text"
+ //FIXME: After Qt 5.14 this can be replaced by the new implemented properties:
+ // valueRole: "value"`
+ // currentValue: model.value
+
+ property var currentValue
+ property var values: []
+
+ currentIndex: model.selectedIndex
+
+ onActivated: (index) => {
+ currentValue = values[index];
+ }
+
+ delegate: QQC2.ItemDelegate {
+ highlighted: optionsCombo.highlightedIndex == index
+ width: parent.width
+
+ contentItem: RowLayout {
+ Kirigami.Icon {
+ source: model.icon
+ Layout.preferredHeight: Kirigami.Units.iconSizes.small
+ Layout.preferredWidth: Kirigami.Units.iconSizes.small
+ }
+ QQC2.Label {
+ text: model.text
+ color: highlighted ? Kirigami.Theme.highlightedTextColor : Kirigami.Theme.textColor
+ Layout.fillWidth: true
+ }
+ }
+
+ QQC2.ToolTip {
+ text: model.description
+ visible: hovered && (model.description != "")
+ }
+
+ Component.onCompleted: {
+ values[index] = model.value;
+ optionsCombo.popup.width = Math.max(implicitWidth, optionsCombo.width, optionsCombo.popup.width);
+ }
+ }
+}
diff --git a/kcmkwin/kwinrules/package/contents/ui/RuleItemDelegate.qml b/kcmkwin/kwinrules/package/contents/ui/RuleItemDelegate.qml
new file mode 100644
--- /dev/null
+++ b/kcmkwin/kwinrules/package/contents/ui/RuleItemDelegate.qml
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2020 Ismael Asensio
+ *
+ * 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 .
+ */
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.12 as QQC2
+import org.kde.kirigami 2.10 as Kirigami
+
+Kirigami.AbstractListItem {
+ id: ruleDelegate
+
+ property bool ruleEnabled: model.enabled
+
+ Kirigami.Theme.colorSet: Kirigami.Theme.View
+
+ RowLayout {
+ anchors {
+ left: parent.left
+ right: parent.right
+ margins: Kirigami.Units.smallSpacing
+ }
+
+ QQC2.CheckBox {
+ id: itemEnabled
+ opacity: model.selectable ? 1 : 0
+ checked: model.enabled
+ onToggled: { model.enabled = checked; }
+ }
+
+ Kirigami.Icon {
+ id: itemIcon
+ source: model.icon
+ Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium
+ Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
+ Layout.rightMargin: Kirigami.Units.smallSpacing
+ QQC2.ToolTip {
+ text: model.description
+ visible: hovered && (model.description != "")
+ }
+ }
+
+ QQC2.Label {
+ text: model.name
+ Layout.minimumWidth: 12 * Kirigami.Units.gridUnit
+ elide: Text.ElideRight
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ OptionsComboBox {
+ id: policyCombo
+ Layout.minimumWidth: 6 * Kirigami.Units.gridUnit
+ Layout.maximumWidth: 12 * Kirigami.Units.gridUnit
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignVCenter
+ flat: true
+
+ visible: count > 0
+ enabled: ruleEnabled
+
+ model: policyModel
+ onActivated: {
+ policy = currentValue;
+ }
+ }
+
+ ValueEditor {
+ id: valueEditor
+ Layout.minimumWidth: 9 * Kirigami.Units.gridUnit
+ Layout.maximumWidth: policyCombo.visible ? 20 * Kirigami.Units.gridUnit
+ : 32 * Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
+
+ enabled: model.enabled
+
+ ruleValue: model.value
+ ruleOptions: model.options
+ controlType: model.type
+
+ onValueEdited: (value) => {
+ model.value = value;
+ }
+ }
+ }
+}
diff --git a/kcmkwin/kwinrules/package/contents/ui/RulesEditor.qml b/kcmkwin/kwinrules/package/contents/ui/RulesEditor.qml
new file mode 100644
--- /dev/null
+++ b/kcmkwin/kwinrules/package/contents/ui/RulesEditor.qml
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2020 Ismael Asensio
+ *
+ * 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 .
+ */
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.12 as QQC2
+import org.kde.kirigami 2.10 as Kirigami
+import org.kde.kcm 1.2
+
+
+ScrollViewKCM {
+ id: rulesEditor
+ property var rulesModel: kcm.rulesModel
+
+ title: rulesModel.description
+
+ header: RowLayout {
+ id: filterBar
+ Kirigami.SearchField {
+ id: searchField
+
+ Layout.fillWidth: true
+ placeholderText: i18n("Search...")
+ focusSequence: "Ctrl+F"
+
+ onTextChanged: {
+ rulesModel.filter.searchText = text;
+ }
+ }
+ QQC2.ToolButton {
+ id: showAllButton
+ icon.name: checked ? 'view-visible' : 'view-hidden'
+ text: i18n("Show All Rules")
+ checkable: true
+ enabled: searchField.text.trim() == ""
+ Binding {
+ target: rulesModel.filter
+ property: "showAll"
+ value: showAllButton.checked
+ }
+ }
+ }
+
+ view: ListView {
+ id: rulesView
+ clip: true
+
+ model: rulesModel.filter
+ delegate: RuleItemDelegate {}
+ section {
+ property: "section"
+ delegate: Kirigami.ListSectionHeader { label: section }
+ }
+ }
+
+ // FIXME: InlineMessage.qml:241:13: QML Label: Binding loop detected for property "verticalAlignment"
+ footer: GridLayout {
+ id: kcmFooter
+ columns: 2
+
+ QQC2.Button {
+ Layout.fillWidth: true
+ text: i18n("Detect window properties")
+ icon.name: "edit-find" // TODO: Better icon for "Detect window properties"
+ onClicked: {
+ rulesModel.detectWindowProperties(detection_delay.value);
+ }
+ }
+
+ QQC2.SpinBox {
+ id: detection_delay
+ from: 0
+ to: 30
+ textFromValue: (value, locale) => {
+ return (value == 0) ? i18n("Instantly")
+ : i18np("After 1 second", "After %1 seconds", value)
+ }
+ }
+
+ Kirigami.InlineMessage {
+ id: warningMessage
+
+ Layout.columnSpan: kcmFooter.columns
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ visible: rulesModel.showWarning
+ text: i18n("You have specified the window class as unimportant.\n" +
+ "This means the settings will possibly apply to windows from all " +
+ "applications. If you really want to create a generic setting, it is " +
+ "recommended you at least limit the window types to avoid special window " +
+ "types.")
+ }
+ }
+}
diff --git a/kcmkwin/kwinrules/package/contents/ui/RulesList.qml b/kcmkwin/kwinrules/package/contents/ui/RulesList.qml
new file mode 100644
--- /dev/null
+++ b/kcmkwin/kwinrules/package/contents/ui/RulesList.qml
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2020 Ismael Asensio
+ *
+ * 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 .
+ */
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.12 as QQC2
+import org.kde.kcm 1.2
+import org.kde.kirigami 2.5 as Kirigami
+
+ScrollViewKCM {
+ id: rulesListKCM
+
+ property int dragIndex: -1
+ property int dropIndex: -1
+
+ // FIXME: ScrollViewKCM.qml:73:13: QML Control: Binding loop detected for property "implicitHeight"
+ implicitWidth: Kirigami.Units.gridUnit * 35
+ implicitHeight: Kirigami.Units.gridUnit * 25
+
+ ConfigModule.columnWidth: Kirigami.Units.gridUnit * 22
+ ConfigModule.buttons: ConfigModule.Apply
+
+ view: ListView {
+ id: ruleBookView
+ clip: true
+
+ model: kcm.ruleBookModel
+ delegate: Kirigami.DelegateRecycler {
+ width: ruleBookView.width
+ sourceComponent: ruleBookDelegate
+ }
+ currentIndex: kcm.editingIndex
+
+ Rectangle {
+ id: dropIndicator
+ x: 0
+ z: 100
+ width: parent.width
+ height: Kirigami.Units.smallSpacing
+ color: Kirigami.Theme.highlightColor
+ visible: (dropIndex >= 0) && (dropIndex != dragIndex)
+
+ Connections {
+ target: rulesListKCM
+ onDropIndexChanged: {
+ if (dropIndex >= 0) {
+ // TODO: After Qt 5.13 we can use ListView.itemAtIndex(index)
+ var dropItem = ruleBookView.contentItem.children[dropIndex];
+ dropIndicator.y = (dropIndex < dragIndex) ? dropItem.y : dropItem.y + dropItem.height;
+ }
+ }
+ }
+ }
+ }
+
+ footer: Kirigami.ActionToolBar {
+ Layout.fillWidth: true
+ alignment: Qt.AlignRight
+
+ actions: [
+ Kirigami.Action {
+ text: i18n("Import")
+ iconName: "document-import"
+ onTriggered: kcm.importRules();
+ }
+ ,
+ Kirigami.Action {
+ text: i18n("New")
+ iconName: "list-add-symbolic"
+ onTriggered: kcm.createRule();
+ }
+ ]
+ }
+
+ Component {
+ id: ruleBookDelegate
+ Kirigami.AbstractListItem {
+ id: ruleBookItem
+
+ RowLayout {
+ //FIXME: If not used within DelegateRecycler, item goes on top of the first item when clicked
+ //FIXME: Improve visuals and behavior when dragging on the list.
+ Kirigami.ListItemDragHandle {
+ listItem: ruleBookItem
+ listView: ruleBookView
+ onMoveRequested: {
+ dragIndex = oldIndex;
+ dropIndex = newIndex;
+ }
+ onDropped: {
+ if (dropIndex >= 0 && dropIndex != dragIndex) {
+ kcm.moveRule(dragIndex, dropIndex);
+ }
+ dragIndex = -1;
+ dropIndex = -1;
+ }
+ }
+
+ QQC2.Label {
+ text: modelData
+ }
+
+ Kirigami.ActionToolBar {
+ Layout.fillWidth: true
+ alignment: Qt.AlignRight
+ display: QQC2.Button.IconOnly
+ opacity: ruleBookItem.hovered ? 1 : 0
+ focus: false
+
+ actions: [
+ Kirigami.Action {
+ text: i18n("Edit")
+ iconName: "edit-entry"
+ onTriggered: kcm.editRule(index);
+ }
+ ,
+ Kirigami.Action {
+ text: i18n("Export")
+ iconName: "document-export"
+ onTriggered: kcm.exportRule(index);
+ }
+ ,
+ Kirigami.Action {
+ text: i18n("Delete")
+ iconName: "entry-delete"
+ onTriggered: kcm.removeRule(index);
+ }
+ ]
+ }
+ }
+ }
+ }
+}
diff --git a/kcmkwin/kwinrules/package/contents/ui/ValueEditor.qml b/kcmkwin/kwinrules/package/contents/ui/ValueEditor.qml
new file mode 100644
--- /dev/null
+++ b/kcmkwin/kwinrules/package/contents/ui/ValueEditor.qml
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2020 Ismael Asensio
+ *
+ * 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 .
+ */
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.12 as QQC2
+
+import org.kde.kirigami 2.10 as Kirigami
+import org.kde.kquickcontrols 2.0 as KQC
+import org.kde.kcms.kwinrules 1.0
+
+
+Loader {
+ id: valueEditor
+ focus: true
+
+ property var ruleValue
+ property var ruleOptions
+ property int controlType
+
+ signal valueEdited(var value)
+
+ sourceComponent: {
+ switch (controlType) {
+ case RuleItem.Boolean: return booleanEditor
+ case RuleItem.String: return stringEditor
+ case RuleItem.Integer: return integerEditor
+ case RuleItem.Option: return optionEditor
+ case RuleItem.FlagsOption: return flagsEditor
+ case RuleItem.Percentage: return percentageEditor
+ case RuleItem.Coordinate: return coordinateEditor
+ case RuleItem.Shortcut: return shortcutEditor
+ default: return emptyEditor
+ }
+ }
+
+ Component {
+ id: emptyEditor
+ Item {}
+ }
+
+ Component {
+ id: booleanEditor
+ RowLayout {
+ Item {
+ Layout.fillWidth: true
+ }
+ QQC2.Switch {
+ text: checked ? i18n("Yes") : i18n("No")
+ checked: ruleValue
+ onToggled: valueEditor.valueEdited(checked)
+ }
+ }
+ }
+
+ Component {
+ id: stringEditor
+ QQC2.TextField {
+ property bool isTextEdited: false
+ text: ruleValue
+ onTextEdited: { isTextEdited = true; }
+ onEditingFinished: {
+ if (isTextEdited) { valueEditor.valueEdited(text); }
+ isTextEdited = false;
+ }
+ }
+ }
+
+ Component {
+ id: integerEditor
+ QQC2.SpinBox {
+ editable: true
+ value: ruleValue
+ onValueModified: valueEditor.valueEdited(value)
+ }
+ }
+
+ Component {
+ id: optionEditor
+ OptionsComboBox {
+ flat: true
+ model: ruleOptions
+ onActivated: (index) => {
+ valueEditor.valueEdited(currentValue);
+ }
+ }
+ }
+
+ Component {
+ id: flagsEditor
+ RowLayout {
+ Layout.minimumWidth: 10 * Kirigami.Units.gridUnit
+ Layout.alignment: Qt.AlignRight;
+ spacing: 0
+ Repeater {
+ id: flagsRepeater
+ model: ruleOptions
+
+ QQC2.ToolButton {
+ property int bit: model.value
+ icon.name: model.iconName
+ checkable: true
+ checked: (ruleValue & (1 << bit)) == (1 << bit)
+ QQC2.ToolTip.text: model.text
+ QQC2.ToolTip.visible: hovered
+ onToggled: {
+ valueEditor.valueEdited((ruleValue & ~(1 << bit)) | (checked << bit));
+ }
+ }
+ }
+ }
+ }
+
+ Component {
+ id: percentageEditor
+ RowLayout {
+ QQC2.Slider {
+ id: slider
+ Layout.fillWidth: true
+ from: 0
+ to: 100
+ value: ruleValue
+ onMoved: valueEditor.valueEdited(Math.round(slider.value))
+ }
+ QQC2.Label {
+ text: i18n("%1 %", Math.round(slider.value))
+ width: 2 * Kirigami.Units.gridUnit
+ }
+ }
+ }
+
+ Component {
+ id: coordinateEditor
+ RowLayout {
+ id: coordItem
+ spacing: Kirigami.Units.smallSpacing
+
+ property var coords: ruleValue ? ruleValue.split(',') : [0, 0]
+ property int coordWidth: (coordItem.width - coordSeparator.width) / 2 - coordItem.spacing
+
+ QQC2.SpinBox {
+ id: coordX
+ editable: true
+ implicitWidth: coordWidth
+ from: 0
+ to: 4098
+ value: coords[0]
+ onValueModified: valueEditor.valueEdited(coordX.value + "," + coordY.value)
+ }
+ QQC2.Label {
+ id: coordSeparator
+ text: i18nc("(x, y) coordinates separator in size/position","x")
+ horizontalAlignment: Text.AlignHCenter
+ }
+ QQC2.SpinBox {
+ id: coordY
+ editable: true
+ from: 0
+ to: 4098
+ implicitWidth: coordWidth
+ value: coords[1]
+ onValueModified: valueEditor.valueEdited(coordX.value + "," + coordY.value)
+ }
+ }
+ }
+
+ Component {
+ id: shortcutEditor
+ RowLayout {
+ Item {
+ Layout.fillWidth: true
+ }
+ KQC.KeySequenceItem {
+ keySequence: ruleValue
+ onCaptureFinished: valueEditor.valueEdited(keySequence)
+ }
+ }
+ }
+}
diff --git a/kcmkwin/kwinrules/package/metadata.desktop b/kcmkwin/kwinrules/package/metadata.desktop
new file mode 100644
--- /dev/null
+++ b/kcmkwin/kwinrules/package/metadata.desktop
@@ -0,0 +1,19 @@
+[Desktop Entry]
+Icon=preferences-system-windows-actions
+Type=Service
+Keywords=
+X-KDE-ParentApp=
+X-KDE-System-Settings-Parent-Category=applicationstyle
+X-KDE-PluginInfo-Author=Ismael Asensio
+X-KDE-PluginInfo-Email=isma.af@gmail.com
+X-KDE-PluginInfo-License=GPL-2.0+
+X-KDE-PluginInfo-Name=kcm_kwinrules_qml
+X-KDE-PluginInfo-Version=
+X-KDE-PluginInfo-Website=https://www.kde.org/plasma-desktop
+X-KDE-ServiceTypes=Plasma/Generic
+X-Plasma-API=declarativeappletscript
+X-Plasma-MainScript=ui/RulesList.qml
+X-KDE-FormFactors=desktop,tablet
+
+Name=Window Rules (QML)
+Comment=Individual Window Behavior
diff --git a/kcmkwin/kwinrules/regenerateindex.sh b/kcmkwin/kwinrules/regenerateindex.sh
new file mode 100644
--- /dev/null
+++ b/kcmkwin/kwinrules/regenerateindex.sh
@@ -0,0 +1 @@
+/home/isma/kde/usr/bin/kpackagetool5 --generate-index -g -p /home/isma/kde/usr/share/kpackage/kcms
diff --git a/kcmkwin/kwinrules/ruleitem.h b/kcmkwin/kwinrules/ruleitem.h
new file mode 100644
--- /dev/null
+++ b/kcmkwin/kwinrules/ruleitem.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2020 Ismael Asensio
+ *
+ * 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 .
+ */
+
+#ifndef KWIN_RULEITEM_H
+#define KWIN_RULEITEM_H
+
+#include "optionsmodel.h"
+
+#include
+
+
+namespace KWin
+{
+
+class RuleItemPrivate;
+
+class RuleItem : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum Type {
+ Undefined,
+ Boolean,
+ String,
+ Integer,
+ Option,
+ FlagsOption,
+ Percentage,
+ Coordinate,
+ Shortcut
+ };
+ Q_ENUM(Type)
+
+ enum Flags {
+ NoFlags = 0,
+ AlwaysEnabled = 1u << 0,
+ StartEnabled = 1u << 1,
+ AffectsWarning = 1u << 2,
+ AffectsDescription = 1u << 3,
+ AllFlags = 0b1111
+ };
+
+public:
+ RuleItem() {};
+ RuleItem(const QString &key,
+ const RulePolicy::Type policyType,
+ const Type type,
+ const QString &name,
+ const QString §ion,
+ const QString &iconName = QStringLiteral("window"),
+ const QList &options = {}
+ );
+ ~RuleItem();
+
+ QString key() const;
+ QString name() const;
+ QString section() const;
+ QIcon icon() const;
+ QString iconName() const;
+
+ bool isEnabled() const;
+ void setEnabled(bool enabled);
+
+ QString description() const;
+ void setDescription(const QString &description);
+
+ bool hasFlag(uint flag) const;
+ void setFlags(uint flags, bool active=true);
+
+ Type type() const;
+ QVariant value() const;
+ void setValue(QVariant value);
+
+ QVariant options() const;
+ void setOptionsData(const QList &data);
+
+ RulePolicy::Type policyType() const;
+ int policy() const; // int belongs to anonymous enum in Rules::
+ void setPolicy(int policy); // int belongs to anonymous enum in Rules::
+ QVariant policyModel() const;
+ QString policyKey() const;
+
+ void reset();
+
+private:
+ static QVariant typedValue(const QVariant &value, const Type type);
+
+private:
+ RuleItemPrivate *d;
+ RulePolicy *p;
+ OptionsModel *o;
+};
+
+} //namespace
+
+#endif //KWIN_RULEITEM_H
diff --git a/kcmkwin/kwinrules/ruleitem.cpp b/kcmkwin/kwinrules/ruleitem.cpp
new file mode 100644
--- /dev/null
+++ b/kcmkwin/kwinrules/ruleitem.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2020 Ismael Asensio
+ *
+ * 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 .
+ */
+
+#include "ruleitem.h"
+
+
+namespace KWin
+{
+
+class RuleItemPrivate
+{
+public:
+ RuleItemPrivate(const QString &key, const QString &name, const QString §ion, const QString &iconName)
+ : m_key(key)
+ , m_name(name)
+ , m_section(section)
+ , m_icon(QIcon::fromTheme(iconName))
+ , m_enabled(false)
+ , m_flags(0)
+ {};
+
+public:
+ QString m_key;
+ QString m_name;
+ QString m_section;
+ QIcon m_icon;
+
+ bool m_enabled;
+
+ QString m_description;
+ uint m_flags;
+
+ RuleItem::Type m_type;
+ QVariant m_value;
+};
+
+
+RuleItem::RuleItem(const QString &key,
+ const RulePolicy::Type policyType,
+ const RuleItem::Type type,
+ const QString &name,
+ const QString §ion,
+ const QString &iconName,
+ const QList &options
+ )
+ : d(new RuleItemPrivate(key, name, section, iconName))
+ , p(new RulePolicy(policyType))
+ , o(nullptr)
+{
+ d->m_type = type;
+ if (type == Option || type == FlagsOption) {
+ o = new OptionsModel(options);
+ }
+
+ reset();
+}
+
+RuleItem::~RuleItem()
+{
+ delete d;
+ delete p;
+ delete o;
+}
+
+void RuleItem::reset()
+{
+ d->m_enabled = hasFlag(AlwaysEnabled) | hasFlag(StartEnabled);
+ d->m_value = typedValue(QVariant(), d->m_type);
+ p->resetValue();
+ if (o) {
+ o->resetValue();
+ }
+}
+
+QString RuleItem::key() const
+{
+ return d->m_key;
+}
+
+QString RuleItem::name() const
+{
+ return d->m_name;
+}
+
+QString RuleItem::section() const
+{
+ return d->m_section;
+}
+
+QString RuleItem::iconName() const
+{
+ return d->m_icon.name();
+}
+
+QIcon RuleItem::icon() const
+{
+ return d->m_icon;
+}
+
+QString RuleItem::description() const
+{
+ return d->m_description;
+}
+
+void RuleItem::setDescription(const QString& description)
+{
+ d->m_description = description;
+}
+
+bool RuleItem::isEnabled() const
+{
+ return d->m_enabled;
+}
+
+void RuleItem::setEnabled(bool enabled)
+{
+ d->m_enabled = enabled | hasFlag(AlwaysEnabled);
+}
+
+bool RuleItem::hasFlag(uint flag) const
+{
+ return (d->m_flags & flag) == flag;
+}
+
+void RuleItem::setFlags(uint flags, bool active)
+{
+ if (active) {
+ d->m_flags |= flags;
+ } else {
+ d->m_flags &= (AllFlags ^ flags);
+ }
+}
+
+RuleItem::Type RuleItem::type() const
+{
+ return d->m_type;
+}
+
+QVariant RuleItem::value() const
+{
+ if (d->m_type == Option) {
+ return o->value();
+ }
+ return d->m_value;
+}
+
+void RuleItem::setValue(QVariant value)
+{
+ if (d->m_type == Option) {
+ o->setValue(value);
+ }
+ d->m_value = typedValue(value, d->m_type);
+}
+
+QVariant RuleItem::options() const
+{
+ if (!o) {
+ return QVariant();
+ }
+ return QVariant::fromValue(o);
+}
+
+void RuleItem::setOptionsData(const QList &data)
+{
+ if (!o) {
+ if (d->m_type != Option && d->m_type != FlagsOption) {
+ return;
+ }
+ o = new OptionsModel();
+ }
+ o->updateModelData(data);
+ o->setValue(d->m_value);
+}
+
+int RuleItem::policy() const
+{
+ return p->value();
+}
+
+void RuleItem::setPolicy(int policy)
+{
+ p->setValue(policy);
+}
+
+RulePolicy::Type RuleItem::policyType() const
+{
+ return p->type();
+}
+
+QVariant RuleItem::policyModel() const
+{
+ return QVariant::fromValue(p);
+}
+
+QString RuleItem::policyKey() const
+{
+ return p->policyKey(d->m_key);
+}
+
+QVariant RuleItem::typedValue(const QVariant &value, const RuleItem::Type type)
+{
+ switch (type) {
+ case Undefined:
+ case Option:
+ return value;
+ case Boolean:
+ return value.toBool();
+ case Integer:
+ case Percentage:
+ return value.toInt();
+ case FlagsOption:
+ // HACK: Currently, the only user of this is "types" property
+ if (value.toInt() == -1) { //NET:AllTypesMask
+ return 0x3FF - 0x040; //All possible flags minus NET::Override (deprecated)
+ }
+ return value.toInt();
+ case Coordinate:
+ if (value.toString().isEmpty()) {
+ return QStringLiteral("0,0");
+ }
+ return value.toString();
+ case String:
+ case Shortcut:
+ return value.toString();
+ }
+
+ return value;
+}
+
+} //namespace
+
diff --git a/kcmkwin/kwinrules/kcm.h b/kcmkwin/kwinrules/rulesdialog.h
rename from kcmkwin/kwinrules/kcm.h
rename to kcmkwin/kwinrules/rulesdialog.h
--- a/kcmkwin/kwinrules/kcm.h
+++ b/kcmkwin/kwinrules/rulesdialog.h
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004 Lubos Lunak
+ * Copyright (c) 2020 Ismael Asensio
*
* 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
@@ -16,35 +17,37 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#ifndef KWIN_RULESDIALOG_H
+#define KWIN_RULESDIALOG_H
-#ifndef __KCM_H__
-#define __KCM_H__
+#include "rulesmodel.h"
+#include "../../rules.h"
-#include
-#include
-
-class KConfig;
+#include
namespace KWin
{
-class KCMRulesList;
+class Rules;
-class KCMRules
- : public KCModule
+class RulesDialog : public QDialog
{
Q_OBJECT
+
public:
- KCMRules(QWidget *parent, const QVariantList &args);
- void load() override;
- void save() override;
- QString quickHelp() const override;
-protected Q_SLOTS:
- void moduleChanged(bool state);
+ explicit RulesDialog(QWidget* parent = nullptr, const char* name = nullptr);
+
+ Rules* edit(Rules* r, const QVariantMap& info, bool show_hints);
+
+protected:
+ void accept() override;
+
private:
- KCMRulesList* widget;
+ RulesModel* m_rulesModel;
+ QWidget *m_quickWidget;
+ Rules* m_rules;
};
} // namespace
-#endif
+#endif // KWIN_RULESDIALOG_H
diff --git a/kcmkwin/kwinrules/rulesdialog.cpp b/kcmkwin/kwinrules/rulesdialog.cpp
new file mode 100644
--- /dev/null
+++ b/kcmkwin/kwinrules/rulesdialog.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2004 Lubos Lunak
+ * Copyright (c) 2020 Ismael Asensio
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "rulesdialog.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+
+namespace KWin
+{
+
+RulesDialog::RulesDialog(QWidget* parent, const char* name)
+ : QDialog(parent)
+ , m_rulesModel(new RulesModel(this))
+{
+ setObjectName(name);
+ setModal(true);
+ setWindowTitle(i18n("Edit Window-Specific Settings"));
+ setWindowIcon(QIcon::fromTheme("preferences-system-windows-actions"));
+ setLayout(new QVBoxLayout);
+
+ // Init RuleEditor QML QuickView
+ QQuickView *quickView = new QQuickView();
+ quickView->setSource(QUrl::fromLocalFile(QStandardPaths::locate(
+ QStandardPaths::GenericDataLocation,
+ QStringLiteral("kpackage/kcms/kcm_kwinrules_qml/contents/ui/RulesEditor.qml"))));
+ quickView->setResizeMode(QQuickView::SizeRootObjectToView);
+ quickView->rootObject()->setProperty("rulesModel", QVariant::fromValue(m_rulesModel));
+
+ m_quickWidget = QWidget::createWindowContainer(quickView, this);
+ m_quickWidget->setMinimumSize(QSize(680, 700));
+ layout()->addWidget(m_quickWidget);
+
+ QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
+ connect(buttons, SIGNAL(accepted()), SLOT(accept()));
+ connect(buttons, SIGNAL(rejected()), SLOT(reject()));
+ layout()->addWidget(buttons);
+}
+
+// window is set only for Alt+F3/Window-specific settings, because the dialog
+// is then related to one specific window
+Rules* RulesDialog::edit(Rules* r, const QVariantMap& info, bool show_hints)
+{
+ Q_UNUSED(show_hints);
+
+ m_rules = r;
+
+ m_rulesModel->importFromRules(m_rules);
+ if (!info.isEmpty()) {
+ m_rulesModel->prefillProperties(info);
+ }
+
+ exec();
+
+ return m_rules;
+}
+
+void RulesDialog::accept()
+{
+ m_rules = m_rulesModel->exportToRules();
+ QDialog::accept();
+}
+
+}
diff --git a/kcmkwin/kwinrules/ruleslist.h b/kcmkwin/kwinrules/ruleslist.h
deleted file mode 100644
--- a/kcmkwin/kwinrules/ruleslist.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2004 Lubos Lunak
- *
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-
-#ifndef __RULESLIST_H__
-#define __RULESLIST_H__
-
-#include "ui_ruleslist.h"
-#include "rulebooksettings.h"
-
-namespace KWin
-{
-class Rules;
-
-class KCMRulesList
- : public QWidget, Ui_KCMRulesList
-{
- Q_OBJECT
-public:
- explicit KCMRulesList(QWidget* parent = nullptr);
- ~KCMRulesList() override;
- void load();
- void save();
-Q_SIGNALS:
- void changed(bool);
-private Q_SLOTS:
- void newClicked();
- void modifyClicked();
- void deleteClicked();
- void moveupClicked();
- void movedownClicked();
- void exportClicked();
- void importClicked();
- void activeChanged();
-private:
- QVector m_rules;
- RuleBookSettings m_settings;
-};
-
-} // namespace
-
-#endif
diff --git a/kcmkwin/kwinrules/ruleslist.cpp b/kcmkwin/kwinrules/ruleslist.cpp
deleted file mode 100644
--- a/kcmkwin/kwinrules/ruleslist.cpp
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (c) 2004 Lubos Lunak
- *
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "ruleslist.h"
-
-#include
-#include
-#include
-
-#include "../../rules.h"
-#include "rulesettings.h"
-#include "ruleswidget.h"
-
-namespace KWin
-{
-
-KCMRulesList::KCMRulesList(QWidget* parent)
- : QWidget(parent)
-{
- setupUi(this);
- // connect both current/selected, so that current==selected (stupid QListBox :( )
- connect(rules_listbox, SIGNAL(itemChanged(QListWidgetItem*)),
- SLOT(activeChanged()));
- connect(rules_listbox, SIGNAL(itemSelectionChanged()),
- SLOT(activeChanged()));
- connect(new_button, SIGNAL(clicked()),
- SLOT(newClicked()));
- connect(modify_button, SIGNAL(clicked()),
- SLOT(modifyClicked()));
- connect(delete_button, SIGNAL(clicked()),
- SLOT(deleteClicked()));
- connect(moveup_button, SIGNAL(clicked()),
- SLOT(moveupClicked()));
- connect(movedown_button, SIGNAL(clicked()),
- SLOT(movedownClicked()));
- connect(export_button, SIGNAL(clicked()),
- SLOT(exportClicked()));
- connect(import_button, SIGNAL(clicked()),
- SLOT(importClicked()));
- connect(rules_listbox, SIGNAL(itemDoubleClicked(QListWidgetItem*)),
- SLOT(modifyClicked()));
- load();
-}
-
-KCMRulesList::~KCMRulesList()
-{
- qDeleteAll(m_rules);
- m_rules.clear();
-}
-
-void KCMRulesList::activeChanged()
-{
- QListWidgetItem *item = rules_listbox->currentItem();
- int itemRow = rules_listbox->row(item);
-
- if (item != nullptr) // make current==selected
- rules_listbox->setCurrentItem(item, QItemSelectionModel::ClearAndSelect);
- modify_button->setEnabled(item != nullptr);
- delete_button->setEnabled(item != nullptr);
- export_button->setEnabled(item != nullptr);
- moveup_button->setEnabled(item != nullptr && itemRow > 0);
- movedown_button->setEnabled(item != nullptr && itemRow < (rules_listbox->count() - 1));
-}
-
-void KCMRulesList::newClicked()
-{
- RulesDialog dlg(this);
- Rules* rule = dlg.edit(nullptr, {}, false);
- if (rule == nullptr)
- return;
- int pos = rules_listbox->currentRow() + 1;
- rules_listbox->insertItem(pos , rule->description);
- rules_listbox->setCurrentRow(pos, QItemSelectionModel::ClearAndSelect);
- m_rules.insert(m_rules.begin() + pos, rule);
- emit changed(true);
-}
-
-void KCMRulesList::modifyClicked()
-{
- int pos = rules_listbox->currentRow();
- if (pos == -1)
- return;
- RulesDialog dlg(this);
- Rules *rule = dlg.edit(m_rules[pos], {}, false);
- if (rule == m_rules[pos])
- return;
- delete m_rules[pos];
- m_rules[pos] = rule;
- rules_listbox->item(pos)->setText(rule->description);
- emit changed(true);
-}
-
-void KCMRulesList::deleteClicked()
-{
- int pos = rules_listbox->currentRow();
- Q_ASSERT(pos != -1);
- delete rules_listbox->takeItem(pos);
- m_rules.erase(m_rules.begin() + pos);
- emit changed(true);
-}
-
-void KCMRulesList::moveupClicked()
-{
- int pos = rules_listbox->currentRow();
- Q_ASSERT(pos != -1);
- if (pos > 0) {
- QListWidgetItem * item = rules_listbox->takeItem(pos);
- rules_listbox->insertItem(pos - 1 , item);
- rules_listbox->setCurrentItem(item, QItemSelectionModel::ClearAndSelect);
- Rules *rule = m_rules[pos];
- m_rules[pos] = m_rules[pos - 1];
- m_rules[pos - 1] = rule;
- }
- emit changed(true);
-}
-
-void KCMRulesList::movedownClicked()
-{
- int pos = rules_listbox->currentRow();
- Q_ASSERT(pos != -1);
- if (pos < int(rules_listbox->count()) - 1) {
- QListWidgetItem * item = rules_listbox->takeItem(pos);
- rules_listbox->insertItem(pos + 1 , item);
- rules_listbox->setCurrentItem(item, QItemSelectionModel::ClearAndSelect);
- Rules *rule = m_rules[pos];
- m_rules[pos] = m_rules[pos + 1];
- m_rules[pos + 1] = rule;
- }
- emit changed(true);
-}
-
-void KCMRulesList::exportClicked()
-{
- int pos = rules_listbox->currentRow();
- Q_ASSERT(pos != -1);
- QString path = QFileDialog::getSaveFileName(this, i18n("Export Rules"), QDir::home().absolutePath(),
- i18n("KWin Rules (*.kwinrule)"));
- if (path.isEmpty())
- return;
- 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;
- const auto config = KSharedConfig::openConfig(path, KConfig::SimpleConfig);
- QStringList groups = config->groupList();
- if (groups.isEmpty())
- return;
-
- int pos = qMax(0, rules_listbox->currentRow());
- 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 < m_rules.count(); ++i) {
- if (m_rules[i]->description == new_rule->description) {
- delete m_rules[i];
- if (remove) {
- m_rules.remove(i);
- delete rules_listbox->takeItem(i);
- delete new_rule;
- pos = qMax(0, rules_listbox->currentRow()); // might have changed!
- } else
- m_rules[i] = new_rule;
- new_rule = nullptr;
- break;
- }
- }
-
- // don't add "to be deleted" if not present
- if (remove) {
- delete new_rule;
- new_rule = nullptr;
- }
-
- // plain insertion
- if (new_rule) {
- m_rules.insert(pos, new_rule);
- rules_listbox->insertItem(pos++, new_rule->description);
- }
- }
- emit changed(true);
-}
-
-void KCMRulesList::load()
-{
- rules_listbox->clear();
- m_settings.load();
- m_rules = m_settings.rules();
- for (const auto rule : qAsConst(m_rules)) {
- rules_listbox->addItem(rule->description);
- }
-
- if (m_rules.count() > 0)
- rules_listbox->setCurrentItem(rules_listbox->item(0));
- else
- rules_listbox->setCurrentItem(nullptr);
- activeChanged();
-}
-
-void KCMRulesList::save()
-{
- m_settings.setRules(m_rules);
- m_settings.save();
-}
-
-} // namespace
-
diff --git a/kcmkwin/kwinrules/ruleslist.ui b/kcmkwin/kwinrules/ruleslist.ui
deleted file mode 100644
--- a/kcmkwin/kwinrules/ruleslist.ui
+++ /dev/null
@@ -1,122 +0,0 @@
-
-
- KWin::KCMRulesList
-
-
-
- 0
- 0
- 600
- 480
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
- -
-
-
- -
-
-
- &New...
-
-
-
- -
-
-
- &Modify...
-
-
-
- -
-
-
- Delete
-
-
-
-
-
-
- -
-
-
- Move &Up
-
-
-
- -
-
-
- Move &Down
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Expanding
-
-
-
- 20
- 294
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- &Import
-
-
-
- -
-
-
- &Export
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
-
-
-
-
-
diff --git a/kcmkwin/kwinrules/rulesmodel.h b/kcmkwin/kwinrules/rulesmodel.h
new file mode 100644
--- /dev/null
+++ b/kcmkwin/kwinrules/rulesmodel.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2020 Ismael Asensio
+ *
+ * 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 .
+ */
+
+#ifndef KWIN_RULES_MODEL_H
+#define KWIN_RULES_MODEL_H
+
+#include "ruleitem.h"
+#include "rulesettings.h"
+#include
+
+#include
+#include
+#include
+
+#ifdef KWIN_BUILD_ACTIVITIES
+#include
+#endif
+
+
+namespace KWin
+{
+
+class RulesFilterModel;
+
+class RulesModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString description READ description NOTIFY descriptionChanged)
+ Q_PROPERTY(bool showWarning READ isWarningShown NOTIFY showWarningChanged)
+ Q_PROPERTY(RulesFilterModel *filter MEMBER m_filterModel CONSTANT)
+
+public:
+ enum RulesRole {
+ NameRole = Qt::DisplayRole,
+ DescriptionRole = Qt::ToolTipRole,
+ IconRole = Qt::DecorationRole,
+ IconNameRole = Qt::UserRole + 1,
+ KeyRole,
+ SectionRole,
+ EnabledRole,
+ SelectableRole,
+ ValueRole,
+ TypeRole,
+ PolicyRole,
+ PolicyModelRole,
+ OptionsModelRole
+ };
+
+public:
+ explicit RulesModel(QObject *parent = nullptr);
+ ~RulesModel();
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ QHash roleNames() const override;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ bool setData(const QModelIndex & index, const QVariant & value, int role) override;
+
+ bool hasRule(const QString &key) const;
+ RuleItem *ruleItem(const QString &key) const;
+
+ void readFromSettings(RuleSettings *settings);
+ void writeToSettings(RuleSettings *settings) const;
+
+ void importFromRules(Rules *rules);
+ Rules *exportToRules() const;
+
+ void prefillProperties(const QVariantMap &info);
+
+ QString description() const;
+ bool isWarningShown() const;
+
+public slots:
+ void detectWindowProperties(int secs);
+
+signals:
+ void descriptionChanged();
+ void showWarningChanged();
+
+private:
+ void populateRuleList();
+ RuleItem *addRule(RuleItem *rule);
+ QString defaultDescription() const;
+
+ static const QHash x11PropertyHash();
+
+ QList windowTypesModelData() const;
+ QList virtualDesktopsModelData() const;
+ QList activitiesModelData() const;
+ QList placementModelData() const;
+ QList focusModelData() const;
+ QList colorSchemesModelData() const;
+
+private slots:
+ void selectX11Window();
+
+private:
+ QList m_ruleList;
+ QHash m_rules;
+ RulesFilterModel *m_filterModel;
+#ifdef KWIN_BUILD_ACTIVITIES
+ KActivities::Consumer *m_activities;
+#endif
+};
+
+
+class RulesFilterModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+ Q_PROPERTY(bool showAll READ showAll WRITE setShowAll NOTIFY showAllChanged)
+ Q_PROPERTY(QString searchText WRITE setSearchText)
+
+public:
+ explicit RulesFilterModel(QObject *parent) : QSortFilterProxyModel(parent) {};
+ bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
+
+ void setSearchText(const QString &text);
+ bool showAll() const;
+ void setShowAll(bool showAll);
+
+signals:
+ void showAllChanged();
+
+private:
+ bool m_isSearching = false;
+ bool m_showAll = false;
+};
+
+}
+
+#endif
diff --git a/kcmkwin/kwinrules/rulesmodel.cpp b/kcmkwin/kwinrules/rulesmodel.cpp
new file mode 100644
--- /dev/null
+++ b/kcmkwin/kwinrules/rulesmodel.cpp
@@ -0,0 +1,847 @@
+/*
+ * Copyright (c) 2004 Lubos Lunak
+ * Copyright (c) 2020 Ismael Asensio
+ *
+ * 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 .
+ */
+
+#include "rulesmodel.h"
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+
+namespace KWin
+{
+
+RulesModel::RulesModel(QObject *parent)
+ : QAbstractListModel(parent)
+ , m_filterModel(new RulesFilterModel(this))
+{
+ qmlRegisterUncreatableType("org.kde.kcms.kwinrules", 1, 0, "RuleItem",
+ QStringLiteral("Do not create objects of type RuleItem"));
+ qmlRegisterUncreatableType("org.kde.kcms.kwinrules", 1, 0, "RulesFilterModel",
+ QStringLiteral("Do not create objects of type RulesFilterModel"));
+
+ m_filterModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+ m_filterModel->setSourceModel(this);
+
+ populateRuleList();
+}
+
+RulesModel::~RulesModel()
+{
+}
+
+QHash< int, QByteArray > RulesModel::roleNames() const
+{
+ return {
+ {KeyRole, QByteArrayLiteral("key")},
+ {NameRole, QByteArrayLiteral("name")},
+ {IconRole, QByteArrayLiteral("icon")},
+ {IconNameRole, QByteArrayLiteral("iconName")},
+ {SectionRole, QByteArrayLiteral("section")},
+ {DescriptionRole, QByteArrayLiteral("description")},
+ {EnabledRole, QByteArrayLiteral("enabled")},
+ {SelectableRole, QByteArrayLiteral("selectable")},
+ {ValueRole, QByteArrayLiteral("value")},
+ {TypeRole, QByteArrayLiteral("type")},
+ {PolicyRole, QByteArrayLiteral("policy")},
+ {PolicyModelRole, QByteArrayLiteral("policyModel")},
+ {OptionsModelRole, QByteArrayLiteral("options")},
+ };
+}
+
+int RulesModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid()) {
+ return 0;
+ }
+ return m_ruleList.size();
+}
+
+QVariant RulesModel::data(const QModelIndex &index, int role) const
+{
+ if (!checkIndex(index, CheckIndexOption::IndexIsValid | CheckIndexOption::ParentIsInvalid)) {
+ return QVariant();
+ }
+
+ const RuleItem *rule = m_ruleList.at(index.row());
+
+ switch (role) {
+ case KeyRole:
+ return rule->key();
+ case NameRole:
+ return rule->name();
+ case IconRole:
+ return rule->icon();
+ case IconNameRole:
+ return rule->iconName();
+ case DescriptionRole:
+ return rule->description();
+ case SectionRole:
+ return rule->section();
+ case EnabledRole:
+ return rule->isEnabled();
+ case SelectableRole:
+ return !rule->hasFlag(RuleItem::AlwaysEnabled);
+ case ValueRole:
+ return rule->value();
+ case TypeRole:
+ return rule->type();
+ case PolicyRole:
+ return rule->policy();
+ case PolicyModelRole:
+ return rule->policyModel();
+ case OptionsModelRole:
+ return rule->options();
+ }
+ return QVariant();
+}
+
+bool RulesModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (!checkIndex(index, CheckIndexOption::IndexIsValid | CheckIndexOption::ParentIsInvalid)) {
+ return false;
+ }
+
+ RuleItem *rule = m_ruleList.at(index.row());
+
+ switch (role) {
+ case EnabledRole:
+ if (value.toBool() == rule->isEnabled()) {
+ return true;
+ }
+ rule->setEnabled(value.toBool());
+ break;
+ case ValueRole:
+ if (value == rule->value()) {
+ return true;
+ }
+ rule->setValue(value);
+ break;
+ case PolicyRole:
+ if (value.toInt() == rule->policy()) {
+ return true;
+ }
+ rule->setPolicy(value.toInt());
+ break;
+ default:
+ return false;
+ }
+
+ emit dataChanged(index, index, QVector{role});
+
+ if (rule->hasFlag(RuleItem::AffectsDescription)) {
+ emit descriptionChanged();
+ }
+ if (rule->hasFlag(RuleItem::AffectsWarning)) {
+ emit showWarningChanged();
+ }
+
+ return true;
+}
+
+RuleItem *RulesModel::addRule(RuleItem *rule)
+{
+ m_ruleList << rule;
+ m_rules.insert(rule->key(), rule);
+
+ return rule;
+}
+
+bool RulesModel::hasRule(const QString& key) const
+{
+ return m_rules.contains(key);
+}
+
+
+RuleItem *RulesModel::ruleItem(const QString& key) const
+{
+ return m_rules.value(key);
+}
+
+QString RulesModel::description() const
+{
+ const QString desc = m_rules["description"]->value().toString();
+ if (!desc.isEmpty()) {
+ return desc;
+ }
+ return defaultDescription();
+}
+
+QString RulesModel::defaultDescription() const
+{
+ const QString wmclass = m_rules["wmclass"]->value().toString();
+ const QString title = m_rules["title"]->isEnabled() ? m_rules["title"]->value().toString() : QString();
+
+ if (!title.isEmpty()) {
+ return i18n("Window settings for %1", title);
+ }
+ if (!wmclass.isEmpty()) {
+ return i18n("Settings for %1", wmclass);
+ }
+
+ return i18n("New window settings");
+}
+
+bool RulesModel::isWarningShown() const
+{
+ const bool no_wmclass = !m_rules["wmclass"]->isEnabled()
+ || m_rules["wmclass"]->policy() == Rules::UnimportantMatch;
+ const bool alltypes = !m_rules["types"]->isEnabled()
+ || (m_rules["types"]->value() == 0)
+ || (m_rules["types"]->value() == NET::AllTypesMask)
+ || ((m_rules["types"]->value().toInt() | (1 << NET::Override)) == 0x3FF);
+
+ return (no_wmclass && alltypes);
+}
+
+
+void RulesModel::readFromSettings(RuleSettings *settings)
+{
+ beginResetModel();
+
+ for (RuleItem *rule : qAsConst(m_ruleList)) {
+ const KConfigSkeletonItem *configItem = settings->findItem(rule->key());
+ const KConfigSkeletonItem *configPolicyItem = settings->findItem(rule->policyKey());
+
+ if (!configItem
+ || (configPolicyItem && configPolicyItem->property() == Rules::Unused)
+ || (configItem->property().toString().isEmpty())) {
+ rule->reset();
+ continue;
+ }
+
+ rule->setEnabled(true);
+
+ const QVariant value = configItem->property();
+ rule->setValue(value);
+
+ if (rule->policyType() != RulePolicy::NoPolicy) {
+ const int policy = configPolicyItem->property().toInt();
+ rule->setPolicy(policy);
+ }
+ }
+
+ endResetModel();
+
+ emit descriptionChanged();
+ emit showWarningChanged();
+}
+
+void RulesModel::writeToSettings(RuleSettings *settings) const
+{
+ const QString description = m_rules["description"]->value().toString();
+ if (description.isEmpty()) {
+ m_rules["description"]->setValue(defaultDescription());
+ }
+
+ for (const RuleItem *rule : qAsConst(m_ruleList)) {
+ KConfigSkeletonItem *configItem = settings->findItem(rule->key());
+ KConfigSkeletonItem *configPolicyItem = settings->findItem(rule->policyKey());
+
+ Q_ASSERT (configItem);
+
+ if (rule->isEnabled()) {
+ configItem->setProperty(rule->value());
+ if (configPolicyItem) {
+ configPolicyItem->setProperty(rule->policy());
+ }
+ } else {
+ if (configPolicyItem) {
+ configPolicyItem->setProperty(Rules::Unused);
+ } else {
+ // Rules without policy gets deactivated by an empty string
+ configItem->setProperty(QString());
+ }
+ }
+ }
+}
+
+void RulesModel::importFromRules(Rules* rules)
+{
+ QTemporaryFile tempFile;
+ if (!tempFile.open()) {
+ return;
+ }
+ const auto cfg = KSharedConfig::openConfig(tempFile.fileName(), KConfig::SimpleConfig);
+ RuleSettings *settings = new RuleSettings(cfg, QStringLiteral("tempSettings"));
+
+ settings->setDefaults();
+ if (rules) {
+ rules->write(settings);
+ }
+ readFromSettings(settings);
+
+ delete(settings);
+}
+
+Rules *RulesModel::exportToRules() const
+{
+ QTemporaryFile tempFile;
+ if (!tempFile.open()) {
+ return nullptr;
+ }
+ const auto cfg = KSharedConfig::openConfig(tempFile.fileName(), KConfig::SimpleConfig);
+
+ RuleSettings *settings = new RuleSettings(cfg, QStringLiteral("tempSettings"));
+
+ writeToSettings(settings);
+ Rules *rules = new Rules(settings);
+
+ delete(settings);
+ return rules;
+}
+
+
+void RulesModel::populateRuleList()
+{
+ qDeleteAll(m_ruleList);
+ m_ruleList.clear();
+
+ //Rule description
+ addRule(new RuleItem(QLatin1String("description"),
+ RulePolicy::NoPolicy, RuleItem::String,
+ i18n("Description"), i18n("Window matching"),
+ QStringLiteral("entry-edit")));
+ m_rules["description"]->setFlags(RuleItem::AlwaysEnabled | RuleItem::AffectsDescription);
+
+ // Window matching
+ addRule(new RuleItem(QLatin1String("wmclass"),
+ RulePolicy::StringMatch, RuleItem::String,
+ i18n("Window class (application)"), i18n("Window matching"),
+ QStringLiteral("window")));
+ m_rules["wmclass"]->setFlags(RuleItem::AlwaysEnabled | RuleItem::AffectsWarning | RuleItem::AffectsDescription);
+
+ addRule(new RuleItem(QLatin1String("wmclasscomplete"),
+ RulePolicy::NoPolicy, RuleItem::Boolean,
+ i18n("Match whole window class"), i18n("Window matching"),
+ QStringLiteral("window")));
+ m_rules["wmclasscomplete"]->setFlags(RuleItem::AlwaysEnabled);
+
+ addRule(new RuleItem(QLatin1String("types"),
+ RulePolicy::NoPolicy, RuleItem::FlagsOption,
+ i18n("Window types"), i18n("Window matching"),
+ QStringLiteral("window-duplicate"),
+ windowTypesModelData()));
+ m_rules["types"]->setFlags(RuleItem::AlwaysEnabled | RuleItem::AffectsWarning );
+
+ addRule(new RuleItem(QLatin1String("windowrole"),
+ RulePolicy::NoPolicy, RuleItem::String,
+ i18n("Window role"), i18n("Window matching"),
+ QStringLiteral("dialog-object-properties")));
+
+ addRule(new RuleItem(QLatin1String("title"),
+ RulePolicy::StringMatch, RuleItem::String,
+ i18n("Window title"), i18n("Window matching"),
+ QStringLiteral("edit-comment")));
+ m_rules["title"]->setFlags(RuleItem::AffectsDescription);
+
+ addRule(new RuleItem(QLatin1String("clientmachine"),
+ RulePolicy::StringMatch, RuleItem::String,
+ i18n("Machine (hostname)"), i18n("Window matching"),
+ QStringLiteral("computer")));
+
+ // Size & Position
+ addRule(new RuleItem(QLatin1String("position"),
+ RulePolicy::SetRule, RuleItem::Coordinate,
+ i18n("Position"), i18n("Size & Position"),
+ QStringLiteral("transform-move")));
+
+ addRule(new RuleItem(QLatin1String("size"),
+ RulePolicy::SetRule, RuleItem::Coordinate,
+ i18n("Size"), i18n("Size & Position"),
+ QStringLiteral("image-resize-symbolic")));
+
+ addRule(new RuleItem(QLatin1String("maximizehoriz"),
+ RulePolicy::SetRule, RuleItem::Boolean,
+ i18n("Maximized horizontally"), i18n("Size & Position"),
+ QStringLiteral("resizecol")));
+
+ addRule(new RuleItem(QLatin1String("maximizevert"),
+ RulePolicy::SetRule, RuleItem::Boolean,
+ i18n("Maximized vertically"), i18n("Size & Position"),
+ QStringLiteral("resizerow")));
+
+ addRule(new RuleItem(QLatin1String("desktop"),
+ RulePolicy::SetRule, RuleItem::Option,
+ i18n("Virtual Desktop"), i18n("Size & Position"),
+ QStringLiteral("virtual-desktops"),
+ virtualDesktopsModelData()));
+
+#ifdef KWIN_BUILD_ACTIVITIES
+ m_activities = new KActivities::Consumer(this);
+
+ addRule(new RuleItem(QLatin1String("activity"),
+ RulePolicy::SetRule, RuleItem::Option,
+ i18n("Activity"), i18n("Size & Position"),
+ QStringLiteral("activities"),
+ activitiesModelData()));
+
+ // Activites consumer may update the available activities later
+ connect(m_activities, &KActivities::Consumer::activitiesChanged,
+ this, [this] { m_rules["activity"]->setOptionsData(activitiesModelData()); });
+ connect(m_activities, &KActivities::Consumer::serviceStatusChanged,
+ this, [this] { m_rules["activity"]->setOptionsData(activitiesModelData()); });
+
+#endif
+
+ addRule(new RuleItem(QLatin1String("screen"),
+ RulePolicy::SetRule, RuleItem::Integer,
+ i18n("Screen"), i18n("Size & Position"),
+ QStringLiteral("osd-shutd-screen")));
+
+ addRule(new RuleItem(QLatin1String("fullscreen"),
+ RulePolicy::SetRule, RuleItem::Boolean,
+ i18n("Fullscreen"), i18n("Size & Position"),
+ QStringLiteral("view-fullscreen")));
+
+ addRule(new RuleItem(QLatin1String("minimize"),
+ RulePolicy::SetRule, RuleItem::Boolean,
+ i18n("Minimized"), i18n("Size & Position"),
+ QStringLiteral("window-minimize")));
+
+ addRule(new RuleItem(QLatin1String("shade"),
+ RulePolicy::SetRule, RuleItem::Boolean,
+ i18n("Shaded"), i18n("Size & Position"),
+ QStringLiteral("window-shade")));
+
+ addRule(new RuleItem(QLatin1String("placement"),
+ RulePolicy::ForceRule, RuleItem::Option,
+ i18n("Initial placement"), i18n("Size & Position"),
+ QStringLiteral("region"),
+ placementModelData()));
+
+ addRule(new RuleItem(QLatin1String("ignoregeometry"),
+ RulePolicy::SetRule, RuleItem::Boolean,
+ i18n("Ignore requested geometry"), i18n("Size & Position"),
+ QStringLiteral("view-time-schedule-baselined-remove")));
+ m_rules["ignoregeometry"]->setDescription(i18n("Windows can ask to appear in a certain position.\n"
+ "By default this overrides the placement strategy\n"
+ "what might be nasty if the client abuses the feature\n"
+ "to unconditionally popup in the middle of your screen."));
+
+ addRule(new RuleItem(QLatin1String("minsize"),
+ RulePolicy::ForceRule, RuleItem::Coordinate,
+ i18n("Minimum Size"), i18n("Size & Position"),
+ QStringLiteral("image-resize-symbolic")));
+
+ addRule(new RuleItem(QLatin1String("maxsize"),
+ RulePolicy::ForceRule, RuleItem::Coordinate,
+ i18n("Maximum Size"), i18n("Size & Position"),
+ QStringLiteral("image-resize-symbolic")));
+
+ addRule(new RuleItem(QLatin1String("strictgeometry"),
+ RulePolicy::ForceRule, RuleItem::Boolean,
+ i18n("Obey geometry restrictions"), i18n("Size & Position"),
+ QStringLiteral("transform-crop-and-resize")));
+ m_rules["strictgeometry"]->setDescription(i18n("Eg. terminals or video players can ask to keep a certain aspect ratio\n"
+ "or only grow by values larger than one\n"
+ "(eg. by the dimensions of one character).\n"
+ "This may be pointless and the restriction prevents arbitrary dimensions\n"
+ "like your complete screen area."));
+
+ // Arrangement & Access
+ addRule(new RuleItem(QLatin1String("above"),
+ RulePolicy::SetRule, RuleItem::Boolean,
+ i18n("Keep above"), i18n("Arrangement & Access"),
+ QStringLiteral("window-keep-above")));
+
+ addRule(new RuleItem(QLatin1String("below"),
+ RulePolicy::SetRule, RuleItem::Boolean,
+ i18n("Keep below"), i18n("Arrangement & Access"),
+ QStringLiteral("window-keep-below")));
+
+ addRule(new RuleItem(QLatin1String("skiptaskbar"),
+ RulePolicy::SetRule, RuleItem::Boolean,
+ i18n("Skip taskbar"), i18n("Arrangement & Access"),
+ QStringLiteral("kt-show-statusbar")));
+ m_rules["skiptaskbar"]->setDescription(i18n("Window shall (not) appear in the taskbar."));
+
+ addRule(new RuleItem(QLatin1String("skippager"),
+ RulePolicy::SetRule, RuleItem::Boolean,
+ i18n("Skip pager"), i18n("Arrangement & Access"),
+ QStringLiteral("org.kde.plasma.pager")));
+ m_rules["skippager"]->setDescription(i18n("Window shall (not) appear in the manager for virtual desktops"));
+
+ addRule(new RuleItem(QLatin1String("skipswitcher"),
+ RulePolicy::SetRule, RuleItem::Boolean,
+ i18n("Skip switcher"), i18n("Arrangement & Access"),
+ QStringLiteral("preferences-system-windows-effect-flipswitch")));
+ m_rules["skipswitcher"]->setDescription(i18n("Window shall (not) appear in the Alt+Tab list"));
+
+ addRule(new RuleItem(QLatin1String("shortcut"),
+ RulePolicy::SetRule, RuleItem::Shortcut,
+ i18n("Shortcut"), i18n("Arrangement & Access"),
+ QStringLiteral("configure-shortcuts")));
+
+ // Appearance & Fixes
+ addRule(new RuleItem(QLatin1String("noborder"),
+ RulePolicy::SetRule, RuleItem::Boolean,
+ i18n("No titlebar and frame"), i18n("Appearance & Fixes"),
+ QStringLiteral("dialog-cancel")));
+
+ addRule(new RuleItem(QLatin1String("decocolor"),
+ RulePolicy::ForceRule, RuleItem::Option,
+ i18n("Titlebar color scheme"), i18n("Appearance & Fixes"),
+ QStringLiteral("preferences-desktop-theme"),
+ colorSchemesModelData()));
+
+ addRule(new RuleItem(QLatin1String("opacityactive"),
+ RulePolicy::ForceRule, RuleItem::Percentage,
+ i18n("Active opacity"), i18n("Appearance & Fixes"),
+ QStringLiteral("edit-opacity")));
+
+ addRule(new RuleItem(QLatin1String("opacityinactive"),
+ RulePolicy::ForceRule, RuleItem::Percentage,
+ i18n("Inactive opacity"), i18n("Appearance & Fixes"),
+ QStringLiteral("edit-opacity")));
+
+ addRule(new RuleItem(QLatin1String("fsplevel"),
+ RulePolicy::ForceRule, RuleItem::Option,
+ i18n("Focus stealing prevention"), i18n("Appearance & Fixes"),
+ QStringLiteral("preferences-system-windows-effect-glide"),
+ focusModelData()));
+ m_rules["fsplevel"]->setDescription(i18n("KWin tries to prevent windows from taking the focus\n"
+ "(\"activate\") while you're working in another window,\n"
+ "but this may sometimes fail or superact.\n"
+ "\"None\" will unconditionally allow this window to get the focus while\n"
+ "\"Extreme\" will completely prevent it from taking the focus."));
+
+ addRule(new RuleItem(QLatin1String("fpplevel"),
+ RulePolicy::ForceRule, RuleItem::Option,
+ i18n("Focus protection"), i18n("Appearance & Fixes"),
+ QStringLiteral("preferences-system-windows-effect-minimize"),
+ focusModelData()));
+ m_rules["fpplevel"]->setDescription(i18n("This controls the focus protection of the currently active window.\n"
+ "None will always give the focus away,\n"
+ "Extreme will keep it.\n"
+ "Otherwise it's interleaved with the stealing prevention\n"
+ "assigned to the window that wants the focus."));
+
+ addRule(new RuleItem(QLatin1String("acceptfocus"),
+ RulePolicy::ForceRule, RuleItem::Boolean,
+ i18n("Accept focus"), i18n("Appearance & Fixes"),
+ QStringLiteral("preferences-desktop-cursors")));
+ m_rules["acceptfocus"]->setDescription(i18n("Windows may prevent to get the focus (activate) when being clicked.\n"
+ "On the other hand you might wish to prevent a window\n"
+ "from getting focused on a mouse click."));
+
+ addRule(new RuleItem(QLatin1String("disableglobalshortcuts"),
+ RulePolicy::ForceRule, RuleItem::Boolean,
+ i18n("Ignore global shortcuts"), i18n("Appearance & Fixes"),
+ QStringLiteral("input-keyboard-virtual-off")));
+ m_rules["disableglobalshortcuts"]->setDescription(i18n("When used, a window will receive\n"
+ "all keyboard inputs while it is active, including Alt+Tab etc.\n"
+ "This is especially interesting for emulators or virtual machines.\n"
+ "\n"
+ "Be warned:\n"
+ "you won't be able to Alt+Tab out of the window\n"
+ "nor use any other global shortcut (such as Alt+F2 to show KRunner)\n"
+ "while it's active!"));
+
+ addRule(new RuleItem(QLatin1String("closeable"),
+ RulePolicy::ForceRule, RuleItem::Boolean,
+ i18n("Closeable"), i18n("Appearance & Fixes"),
+ QStringLiteral("dialog-close")));
+
+ addRule(new RuleItem(QLatin1String("type"),
+ RulePolicy::ForceRule, RuleItem::Option,
+ i18n("Set window type"), i18n("Appearance & Fixes"),
+ QStringLiteral("window-duplicate"),
+ windowTypesModelData()));
+
+ addRule(new RuleItem(QLatin1String("desktopfile"),
+ RulePolicy::SetRule, RuleItem::String,
+ i18n("Desktop file name"), i18n("Appearance & Fixes"),
+ QStringLiteral("application-x-desktop")));
+
+ addRule(new RuleItem(QLatin1String("blockcompositing"),
+ RulePolicy::ForceRule, RuleItem::Boolean,
+ i18n("Block compositing"), i18n("Appearance & Fixes"),
+ QStringLiteral("composite-track-on")));
+}
+
+
+const QHash RulesModel::x11PropertyHash()
+{
+ static const auto propertyToRule = QHash {
+ /* The original detection dialog allows to choose depending on "Match complete window class":
+ * if Match Complete == false: wmclass = "resourceClass"
+ * if Match Complete == true: wmclass = "resourceName" + " " + "resourceClass"
+ */
+ { "resourceName", "wmclass" },
+ { "caption", "title" },
+ { "role", "windowrole" },
+ { "clientMachine", "clientmachine" },
+ { "x11DesktopNumber", "desktop" },
+ { "maximizeHorizontal", "maximizehoriz" },
+ { "maximizeVertical", "maximizevert" },
+ { "minimized", "minimize" },
+ { "shaded", "shade" },
+ { "fullscreen", "fullscreen" },
+ { "keepAbove", "above" },
+ { "keepBelow", "below" },
+ { "noBorder", "noborder" },
+ { "skipTaskbar", "skiptaskbar" },
+ { "skipPager", "skippager" },
+ { "skipSwitcher", "skipswitcher" },
+ { "type", "type" },
+ { "desktopFile", "desktopfile" }
+ };
+ return propertyToRule;
+};
+
+void RulesModel::prefillProperties(const QVariantMap &info)
+{
+ beginResetModel();
+
+ // Properties that cannot be directly applied via x11PropertyHash
+ const QString position = QStringLiteral("%1,%2").arg(info.value("x").toInt())
+ .arg(info.value("y").toInt());
+ const QString size = QStringLiteral("%1,%2").arg(info.value("width").toInt())
+ .arg(info.value("height").toInt());
+
+ if (!m_rules["position"]->isEnabled()) {
+ m_rules["position"]->setValue(position);
+ }
+ if (!m_rules["size"]->isEnabled()) {
+ m_rules["size"]->setValue(size);
+ }
+ if (!m_rules["minsize"]->isEnabled()) {
+ m_rules["minsize"]->setValue(size);
+ }
+ if (!m_rules["maxsize"]->isEnabled()) {
+ m_rules["maxsize"]->setValue(size);
+ }
+
+ NET::WindowType window_type = static_cast(info.value("type", 0).toInt());
+ if (!m_rules["types"]->isEnabled() || m_rules["types"]->value() == 0) {
+ if (window_type == NET::Unknown) {
+ window_type = NET::Normal;
+ }
+ m_rules["types"]->setValue(1 << window_type);
+ }
+
+ const auto ruleForProperty = x11PropertyHash();
+ for (QString &property : info.keys()) {
+ if (!ruleForProperty.contains(property)) {
+ continue;
+ }
+ const QString ruleKey = ruleForProperty.value(property, QString());
+ Q_ASSERT(hasRule(ruleKey));
+
+ // Only prefill disabled or empty properties
+ if (!m_rules[ruleKey]->isEnabled() || m_rules[ruleKey]->value().toString().isEmpty()) {
+ m_rules[ruleKey]->setValue(info.value(property));
+ }
+ }
+
+ endResetModel();
+
+ emit descriptionChanged();
+ emit showWarningChanged();
+}
+
+
+QList RulesModel::windowTypesModelData() const
+{
+ static const auto modelData = QList {
+ //TODO: Find/create better icons
+ { NET::Normal, i18n("Normal Window") , QIcon::fromTheme("window") },
+ { NET::Dialog, i18n("Dialog Window") , QIcon::fromTheme("window-duplicate") },
+ { NET::Utility, i18n("Utility Window") , QIcon::fromTheme("dialog-object-properties") },
+ { NET::Dock, i18n("Dock (panel)") , QIcon::fromTheme("list-remove") },
+ { NET::Toolbar, i18n("Toolbar") , QIcon::fromTheme("tools") },
+ { NET::Menu, i18n("Torn-Off Menu") , QIcon::fromTheme("overflow-menu-left") },
+ { NET::Splash, i18n("Splash Screen") , QIcon::fromTheme("embosstool") },
+ { NET::Desktop, i18n("Desktop") , QIcon::fromTheme("desktop") },
+ // { NET::Override, i18n("Unmanaged Window") }, deprecated
+ { NET::TopMenu, i18n("Standalone Menubar"), QIcon::fromTheme("open-menu-symbolic") }
+ };
+ return modelData;
+}
+
+QList RulesModel::virtualDesktopsModelData() const
+{
+ QList modelData;
+ for (int desktopId = 1; desktopId <= KWindowSystem::numberOfDesktops(); ++desktopId) {
+ modelData << OptionsModel::Data{
+ desktopId,
+ QString::number(desktopId).rightJustified(2) + QStringLiteral(": ") + KWindowSystem::desktopName(desktopId),
+ QIcon::fromTheme("virtual-desktops")
+ };
+ }
+ modelData << OptionsModel::Data{ NET::OnAllDesktops, i18n("All Desktops"), QIcon::fromTheme("window-pin") };
+ return modelData;
+}
+
+
+QList RulesModel::activitiesModelData() const
+{
+#ifdef KWIN_BUILD_ACTIVITIES
+ QList modelData;
+
+ // NULL_ID from kactivities/src/lib/core/consumer.cpp
+ modelData << OptionsModel::Data{
+ QString::fromLatin1("00000000-0000-0000-0000-000000000000"),
+ i18n("All Activities"),
+ QIcon::fromTheme("activities")
+ };
+
+ const auto activities = m_activities->activities(KActivities::Info::Running);
+ if (m_activities->serviceStatus() == KActivities::Consumer::Running) {
+ for (const QString &activityId : activities) {
+ const KActivities::Info info(activityId);
+ modelData << OptionsModel::Data{ activityId, info.name(), QIcon::fromTheme(info.icon()) };
+ }
+ }
+
+ return modelData;
+#else
+ return {};
+#endif
+}
+
+QList RulesModel::placementModelData() const
+{
+ // From "placement.h" : Placement rule is stored as a string, not the enum value
+ static const auto modelData = QList {
+ { Placement::policyToString(Placement::Default), i18n("Default") },
+ { Placement::policyToString(Placement::NoPlacement), i18n("No Placement") },
+ { Placement::policyToString(Placement::Smart), i18n("Minimal Overlapping") },
+ { Placement::policyToString(Placement::Maximizing), i18n("Maximized") },
+ { Placement::policyToString(Placement::Cascade), i18n("Cascaded") },
+ { Placement::policyToString(Placement::Centered), i18n("Centered") },
+ { Placement::policyToString(Placement::Random), i18n("Random") },
+ { Placement::policyToString(Placement::ZeroCornered), i18n("In Top-Left Corner") },
+ { Placement::policyToString(Placement::UnderMouse), i18n("Under Mouse") },
+ { Placement::policyToString(Placement::OnMainWindow), i18n("On Main Window") }
+ };
+ return modelData;
+}
+
+QList RulesModel::focusModelData() const
+{
+ static const auto modelData = QList {
+ { 0, i18n("None") },
+ { 1, i18n("Low") },
+ { 2, i18n("Normal") },
+ { 3, i18n("High") },
+ { 4, i18n("Extreme") }
+ };
+ return modelData;
+}
+
+QList RulesModel::colorSchemesModelData() const
+{
+ QList modelData;
+
+ KColorSchemeManager schemes;
+ QAbstractItemModel *schemesModel = schemes.model();
+
+ // Skip row 0, which is Default scheme
+ for (int r = 1; r < schemesModel->rowCount(); r++) {
+ const QModelIndex index = schemesModel->index(r, 0);
+ modelData << OptionsModel::Data{
+ QFileInfo(index.data(Qt::UserRole).toString()).baseName(),
+ index.data(Qt::DisplayRole).toString(),
+ index.data(Qt::DecorationRole).value()
+ };
+ }
+
+ return modelData;
+}
+
+
+bool RulesFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
+{
+ if (m_isSearching) {
+ return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
+ }
+ if (m_showAll) {
+ return true;
+ }
+
+ return sourceModel()->index(source_row, 0).data(RulesModel::EnabledRole).toBool();
+}
+
+void RulesFilterModel::setSearchText(const QString &text)
+{
+ const QString searchText = text.trimmed();
+ m_isSearching = !searchText.isEmpty();
+ setFilterFixedString(searchText);
+}
+
+bool RulesFilterModel::showAll() const
+{
+ return m_showAll;
+}
+
+void RulesFilterModel::setShowAll(bool showAll)
+{
+ if (m_showAll == showAll) {
+ return;
+ }
+
+ m_showAll = showAll;
+ invalidateFilter();
+ emit showAllChanged();
+}
+
+
+void RulesModel::detectWindowProperties(int secs)
+{
+ QTimer::singleShot(secs*1000, this, &RulesModel::selectX11Window);
+}
+
+void RulesModel::selectX11Window()
+{
+ QDBusMessage message = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KWin"),
+ QStringLiteral("/KWin"),
+ QStringLiteral("org.kde.KWin"),
+ QStringLiteral("queryWindowInfo"));
+
+ QDBusPendingReply async = QDBusConnection::sessionBus().asyncCall(message);
+
+ QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(async, this);
+ connect(callWatcher, &QDBusPendingCallWatcher::finished, this,
+ [this](QDBusPendingCallWatcher *self) {
+ QDBusPendingReply reply = *self;
+ self->deleteLater();
+ if (!reply.isValid()) {
+ return;
+ }
+ const QVariantMap windowInfo = reply.value();
+ //TODO: Improve UI to suggest/select the detected properties.
+ // For now, just prefill unused rules
+ prefillProperties(windowInfo);
+ }
+ );
+}
+
+} //namespace
diff --git a/kcmkwin/kwinrules/ruleswidget.h b/kcmkwin/kwinrules/ruleswidget.h
deleted file mode 100644
--- a/kcmkwin/kwinrules/ruleswidget.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (c) 2004 Lubos Lunak
- *
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-
-#ifndef __RULESWIDGET_H__
-#define __RULESWIDGET_H__
-
-#include
-
-#include
-#include
-
-#include "ui_ruleswidgetbase.h"
-#include "ui_editshortcut.h"
-
-#ifdef KWIN_BUILD_ACTIVITIES
-namespace KActivities {
- class Consumer;
-} // namespace KActivities
-#endif
-
-namespace KWin
-{
-
-class Rules;
-class DetectDialog;
-
-class RulesWidget
- : public QWidget, public Ui::RulesWidgetBase
-{
- Q_OBJECT
-public:
- explicit RulesWidget(QWidget* parent = nullptr);
- void setRules(Rules* r);
- Rules* rules() const;
- bool finalCheck();
- void prepareWindowSpecific(const QVariantMap &info);
-Q_SIGNALS:
- void changed(bool state);
-protected Q_SLOTS:
- void detectClicked();
- void wmclassMatchChanged();
- void roleMatchChanged();
- void titleMatchChanged();
- void machineMatchChanged();
- void shortcutEditClicked();
-private Q_SLOTS:
- // geometry tab
- void updateEnableposition();
- void updateEnablesize();
- void updateEnabledesktop();
- void updateEnablescreen();
-#ifdef KWIN_BUILD_ACTIVITIES
- void updateEnableactivity();
-#endif
- void updateEnablemaximizehoriz();
- void updateEnablemaximizevert();
- void updateEnableminimize();
- void updateEnableshade();
- void updateEnablefullscreen();
- void updateEnableplacement();
- // preferences tab
- void updateEnableabove();
- void updateEnablebelow();
- void updateEnablenoborder();
- void updateEnabledecocolor();
- void updateEnableskiptaskbar();
- void updateEnableskippager();
- void updateEnableskipswitcher();
- void updateEnableacceptfocus();
- void updateEnablecloseable();
- void updateEnableautogroup();
- void updateEnableautogroupfg();
- void updateEnableautogroupid();
- void updateEnableopacityactive();
- void updateEnableopacityinactive();
- // workarounds tab
- void updateEnablefsplevel();
- void updateEnablefpplevel();
- void updateEnabletype();
- void updateEnableignoregeometry();
- void updateEnableminsize();
- void updateEnablemaxsize();
- void updateEnablestrictgeometry();
- void updateEnableshortcut();
- void updateEnabledisableglobalshortcuts();
- void updateEnableblockcompositing();
- void updateEnabledesktopfile();
- // internal
- void detected(bool);
-private:
- int desktopToCombo(int d) const;
- int comboToDesktop(int val) const;
-#ifdef KWIN_BUILD_ACTIVITIES
- int activityToCombo(const QString &d) const;
- QString comboToActivity(int val) const;
- void updateActivitiesList();
- KActivities::Consumer *m_activities;
- QString m_selectedActivityId; // we need this for async activity loading
-#endif
- int comboToTiling(int val) const;
- int inc(int i) const { return i+1; }
- int dec(int i) const { return i-1; }
- void prefillUnusedValues(const QVariantMap& info);
- DetectDialog* detect_dlg;
- bool detect_dlg_ok;
-};
-
-class RulesDialog
- : public QDialog
-{
- Q_OBJECT
-public:
- explicit RulesDialog(QWidget* parent = nullptr, const char* name = nullptr);
- Rules* edit(Rules* r, const QVariantMap& info, bool show_hints);
-protected:
- void accept() override;
-private Q_SLOTS:
- void displayHints();
-private:
- RulesWidget* widget;
- Rules* rules;
-};
-
-class EditShortcut
- : public QWidget, public Ui_EditShortcut
-{
- Q_OBJECT
-public:
- explicit EditShortcut(QWidget* parent = nullptr);
-protected Q_SLOTS:
- void editShortcut();
- void clearShortcut();
-};
-
-class EditShortcutDialog
- : public QDialog
-{
- Q_OBJECT
-public:
- explicit EditShortcutDialog(QWidget* parent = nullptr, const char* name = nullptr);
- void setShortcut(const QString& cut);
- QString shortcut() const;
-private:
- EditShortcut* widget;
-};
-
-// slightly duped from utils.cpp
-class ShortcutDialog
- : public QDialog
-{
- Q_OBJECT
-public:
- explicit ShortcutDialog(const QKeySequence& cut, QWidget* parent = nullptr);
- void accept() override;
- QKeySequence shortcut() const;
-private:
- KKeySequenceWidget* widget;
-};
-
-} // namespace
-
-#endif
diff --git a/kcmkwin/kwinrules/ruleswidget.cpp b/kcmkwin/kwinrules/ruleswidget.cpp
deleted file mode 100644
--- a/kcmkwin/kwinrules/ruleswidget.cpp
+++ /dev/null
@@ -1,970 +0,0 @@
-/*
- * Copyright (c) 2004 Lubos Lunak
- *
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "ruleswidget.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#ifdef KWIN_BUILD_ACTIVITIES
-#include
-#endif
-
-#include
-#include
-#include
-
-#include "../../rules.h"
-
-#include "detectwidget.h"
-
-Q_DECLARE_METATYPE(NET::WindowType)
-
-namespace KWin
-{
-
-#define SETUP( var, type ) \
- connect( enable_##var, SIGNAL(toggled(bool)), rule_##var, SLOT(setEnabled(bool))); \
- connect( enable_##var, SIGNAL(toggled(bool)), this, SLOT(updateEnable##var())); \
- connect( rule_##var, SIGNAL(activated(int)), this, SLOT(updateEnable##var())); \
- enable_##var->setWhatsThis( enableDesc ); \
- rule_##var->setWhatsThis( type##RuleDesc );
-
-RulesWidget::RulesWidget(QWidget* parent)
- : detect_dlg(nullptr)
-{
- Q_UNUSED(parent);
- setupUi(this);
- QRegularExpressionValidator* validator = new QRegularExpressionValidator(QRegularExpression("[0-9\\-+,xX:]*"), this);
- maxsize->setValidator(validator);
- minsize->setValidator(validator);
- position->setValidator(validator);
- Ui::RulesWidgetBase::size->setValidator(validator);
-
- QString enableDesc =
- i18n("Enable this checkbox to alter this window property for the specified window(s).");
- QString setRuleDesc =
- i18n("Specify how the window property should be affected:"
- "- Do Not Affect: The window property will not be affected and therefore"
- " the default handling for it will be used. Specifying this will block more generic"
- " window settings from taking effect.
"
- "- Apply Initially: The window property will be only set to the given value"
- " after the window is created. No further changes will be affected.
"
- "- Remember: The value of the window property will be remembered and every"
- " time the window is created, the last remembered value will be applied.
"
- "- Force: The window property will be always forced to the given value.
"
- "- Apply Now: The window property will be set to the given value immediately"
- " and will not be affected later (this action will be deleted afterwards).
"
- "- Force temporarily: The window property will be forced to the given value"
- " until it is hidden (this action will be deleted after the window is hidden).
"
- "
");
- QString forceRuleDesc =
- i18n("Specify how the window property should be affected:"
- "- Do Not Affect: The window property will not be affected and therefore"
- " the default handling for it will be used. Specifying this will block more generic"
- " window settings from taking effect.
"
- "- Force: The window property will be always forced to the given value.
"
- "- Force temporarily: The window property will be forced to the given value"
- " until it is hidden (this action will be deleted after the window is hidden).
"
- "
");
- // window tabs have enable signals done in designer
- // geometry tab
- SETUP(position, set);
- SETUP(size, set);
- SETUP(desktop, set);
- SETUP(screen, set);
-#ifdef KWIN_BUILD_ACTIVITIES
- SETUP(activity, set);
-#endif
- SETUP(maximizehoriz, set);
- SETUP(maximizevert, set);
- SETUP(minimize, set);
- SETUP(shade, set);
- SETUP(fullscreen, set);
- SETUP(placement, force);
- // preferences tab
- SETUP(above, set);
- SETUP(below, set);
- SETUP(noborder, set);
- SETUP(decocolor, force);
- SETUP(skiptaskbar, set);
- SETUP(skippager, set);
- SETUP(skipswitcher, set);
- SETUP(acceptfocus, force);
- SETUP(closeable, force);
- SETUP(autogroup, force);
- SETUP(autogroupfg, force);
- SETUP(autogroupid, force);
- SETUP(opacityactive, force);
- SETUP(opacityinactive, force);
- SETUP(shortcut, force);
- // workarounds tab
- SETUP(fsplevel, force);
- SETUP(fpplevel, force);
- SETUP(type, force);
- SETUP(desktopfile, set);
- SETUP(ignoregeometry, set);
- SETUP(minsize, force);
- SETUP(maxsize, force);
- SETUP(strictgeometry, force);
- SETUP(disableglobalshortcuts, force);
- SETUP(blockcompositing, force);
-
- connect (shortcut_edit, SIGNAL(clicked()), SLOT(shortcutEditClicked()));
-
- edit_reg_wmclass->hide();
- edit_reg_role->hide();
- edit_reg_title->hide();
- edit_reg_machine->hide();
-
-#ifndef KWIN_BUILD_ACTIVITIES
- rule_activity->hide();
- enable_activity->hide();
- activity->hide();
-#endif
- int i;
- for (i = 1;
- i <= KWindowSystem::numberOfDesktops();
- ++i)
- desktop->addItem(QString::number(i).rightJustified(2) + ':' + KWindowSystem::desktopName(i));
- desktop->addItem(i18n("All Desktops"));
-
-#ifdef KWIN_BUILD_ACTIVITIES
- m_activities = new KActivities::Consumer(this);
- connect(m_activities, &KActivities::Consumer::activitiesChanged,
- this, [this] { updateActivitiesList(); });
- connect(m_activities, &KActivities::Consumer::serviceStatusChanged,
- this, [this] { updateActivitiesList(); });
- updateActivitiesList();
-#endif
-
- KColorSchemeManager *schemes = new KColorSchemeManager(this);
- decocolor->setModel(schemes->model());
-
- // hide autogrouping as it's currently not supported
- // BUG 370301
- line_11->hide();
- enable_autogroup->hide();
- autogroup->hide();
- rule_autogroup->hide();
- enable_autogroupid->hide();
- autogroupid->hide();
- rule_autogroupid->hide();
- enable_autogroupfg->hide();
- autogroupfg->hide();
- rule_autogroupfg->hide();
-}
-
-#undef SETUP
-
-#define UPDATE_ENABLE_SLOT(var) \
- void RulesWidget::updateEnable##var() \
- { \
- /* leave the label readable label_##var->setEnabled( enable_##var->isChecked() && rule_##var->currentIndex() != 0 );*/ \
- Ui::RulesWidgetBase::var->setEnabled( enable_##var->isChecked() && rule_##var->currentIndex() != 0 ); \
- }
-
-// geometry tab
-UPDATE_ENABLE_SLOT(position)
-UPDATE_ENABLE_SLOT(size)
-UPDATE_ENABLE_SLOT(desktop)
-UPDATE_ENABLE_SLOT(screen)
-#ifdef KWIN_BUILD_ACTIVITIES
-UPDATE_ENABLE_SLOT(activity)
-#endif
-UPDATE_ENABLE_SLOT(maximizehoriz)
-UPDATE_ENABLE_SLOT(maximizevert)
-UPDATE_ENABLE_SLOT(minimize)
-UPDATE_ENABLE_SLOT(shade)
-UPDATE_ENABLE_SLOT(fullscreen)
-UPDATE_ENABLE_SLOT(placement)
-// preferences tab
-UPDATE_ENABLE_SLOT(above)
-UPDATE_ENABLE_SLOT(below)
-UPDATE_ENABLE_SLOT(noborder)
-UPDATE_ENABLE_SLOT(decocolor)
-UPDATE_ENABLE_SLOT(skiptaskbar)
-UPDATE_ENABLE_SLOT(skippager)
-UPDATE_ENABLE_SLOT(skipswitcher)
-UPDATE_ENABLE_SLOT(acceptfocus)
-UPDATE_ENABLE_SLOT(closeable)
-UPDATE_ENABLE_SLOT(autogroup)
-UPDATE_ENABLE_SLOT(autogroupfg)
-UPDATE_ENABLE_SLOT(autogroupid)
-UPDATE_ENABLE_SLOT(opacityactive)
-UPDATE_ENABLE_SLOT(opacityinactive)
-void RulesWidget::updateEnableshortcut()
-{
- shortcut->setEnabled(enable_shortcut->isChecked() && rule_shortcut->currentIndex() != 0);
- shortcut_edit->setEnabled(enable_shortcut->isChecked() && rule_shortcut->currentIndex() != 0);
-}
-// workarounds tab
-UPDATE_ENABLE_SLOT(fsplevel)
-UPDATE_ENABLE_SLOT(fpplevel)
-UPDATE_ENABLE_SLOT(type)
-UPDATE_ENABLE_SLOT(ignoregeometry)
-UPDATE_ENABLE_SLOT(minsize)
-UPDATE_ENABLE_SLOT(maxsize)
-UPDATE_ENABLE_SLOT(strictgeometry)
-UPDATE_ENABLE_SLOT(disableglobalshortcuts)
-UPDATE_ENABLE_SLOT(blockcompositing)
-UPDATE_ENABLE_SLOT(desktopfile)
-
-#undef UPDATE_ENABLE_SLOT
-
-static const int set_rule_to_combo[] = {
- 0, // Unused
- 0, // Don't Affect
- 3, // Force
- 1, // Apply
- 2, // Remember
- 4, // ApplyNow
- 5 // ForceTemporarily
-};
-
-static const Rules::SetRule combo_to_set_rule[] = {
- (Rules::SetRule)Rules::DontAffect,
- (Rules::SetRule)Rules::Apply,
- (Rules::SetRule)Rules::Remember,
- (Rules::SetRule)Rules::Force,
- (Rules::SetRule)Rules::ApplyNow,
- (Rules::SetRule)Rules::ForceTemporarily
-};
-
-static const int force_rule_to_combo[] = {
- 0, // Unused
- 0, // Don't Affect
- 1, // Force
- 0, // Apply
- 0, // Remember
- 0, // ApplyNow
- 2 // ForceTemporarily
-};
-
-static const Rules::ForceRule combo_to_force_rule[] = {
- (Rules::ForceRule)Rules::DontAffect,
- (Rules::ForceRule)Rules::Force,
- (Rules::ForceRule)Rules::ForceTemporarily
-};
-
-static QString positionToStr(const QPoint& p)
-{
- if (p == invalidPoint)
- return QString();
- return QString::number(p.x()) + ',' + QString::number(p.y());
-}
-
-static QPoint strToPosition(const QString& str)
-{
- // two numbers, with + or -, separated by any of , x X :
- QRegExp reg("\\s*([+-]?[0-9]*)\\s*[,xX:]\\s*([+-]?[0-9]*)\\s*");
- if (!reg.exactMatch(str))
- return invalidPoint;
- return QPoint(reg.cap(1).toInt(), reg.cap(2).toInt());
-}
-
-static QString sizeToStr(const QSize& s)
-{
- if (!s.isValid())
- return QString();
- return QString::number(s.width()) + ',' + QString::number(s.height());
-}
-
-static QSize strToSize(const QString& str)
-{
- // two numbers, with + or -, separated by any of , x X :
- QRegExp reg("\\s*([+-]?[0-9]*)\\s*[,xX:]\\s*([+-]?[0-9]*)\\s*");
- if (!reg.exactMatch(str))
- return QSize();
- return QSize(reg.cap(1).toInt(), reg.cap(2).toInt());
-}
-
-int RulesWidget::desktopToCombo(int d) const
-{
- if (d >= 1 && d < desktop->count())
- return d - 1;
- return desktop->count() - 1; // on all desktops
-}
-
-int RulesWidget::comboToDesktop(int val) const
-{
- if (val == desktop->count() - 1)
- return NET::OnAllDesktops;
- return val + 1;
-}
-
-#ifdef KWIN_BUILD_ACTIVITIES
-int RulesWidget::activityToCombo(const QString &d) const
-{
- // TODO: ivan - do a multiselection list
- for (int i = 0; i < activity->count(); i++) {
- if (activity->itemData(i).toString() == d) {
- return i;
- }
- }
-
- return activity->count() - 1; // on all activities
-}
-
-QString RulesWidget::comboToActivity(int val) const
-{
- // TODO: ivan - do a multiselection list
- if (val < 0 || val >= activity->count())
- return QString();
-
- return activity->itemData(val).toString();
-}
-
-void RulesWidget::updateActivitiesList()
-{
- activity->clear();
-
- // cloned from kactivities/src/lib/core/consumer.cpp
- #define NULL_UUID "00000000-0000-0000-0000-000000000000"
- activity->addItem(i18n("All Activities"), QString::fromLatin1(NULL_UUID));
- #undef NULL_UUID
-
- if (m_activities->serviceStatus() == KActivities::Consumer::Running) {
- foreach (const QString & activityId, m_activities->activities(KActivities::Info::Running)) {
- const KActivities::Info info(activityId);
- activity->addItem(info.name(), activityId);
- }
- }
-
- auto rules = this->rules();
- if (rules->activityrule == Rules::UnusedSetRule) {
- enable_activity->setChecked(false);
- Ui::RulesWidgetBase::activity->setCurrentIndex(0);
- } else {
- enable_activity->setChecked(true);
- Ui::RulesWidgetBase::activity->setCurrentIndex(activityToCombo(m_selectedActivityId));
- }
- updateEnableactivity();
-}
-#endif
-
-static int placementToCombo(Placement::Policy placement)
-{
- static const int conv[] = {
- 1, // NoPlacement
- 0, // Default
- 0, // Unknown
- 6, // Random
- 2, // Smart
- 4, // Cascade
- 5, // Centered
- 7, // ZeroCornered
- 8, // UnderMouse
- 9, // OnMainWindow
- 3 // Maximizing
- };
- return conv[ placement ];
-}
-
-static Placement::Policy comboToPlacement(int val)
-{
- static const Placement::Policy conv[] = {
- Placement::Default,
- Placement::NoPlacement,
- Placement::Smart,
- Placement::Maximizing,
- Placement::Cascade,
- Placement::Centered,
- Placement::Random,
- Placement::ZeroCornered,
- Placement::UnderMouse,
- Placement::OnMainWindow
- // no Placement::Unknown
- };
- return conv[ val ];
-}
-
-static int typeToCombo(NET::WindowType type)
-{
- if (type < NET::Normal || type > NET::Splash ||
- type == NET::Override) // The user must NOT set a window to be unmanaged.
- // This case is not handled in KWin and will lead to segfaults.
- // Even iff it was supported, it would mean to allow the user to shoot himself
- // since an unmanaged window has to manage itself, what is probably not the case when the hint is not set.
- // Rule opportunity might be a relict from the Motif Hint window times of KDE1
- return 0; // Normal
- static const int conv[] = {
- 0, // Normal
- 7, // Desktop
- 3, // Dock
- 4, // Toolbar
- 5, // Menu
- 1, // Dialog
- 8, // Override - ignored.
- 9, // TopMenu
- 2, // Utility
- 6 // Splash
- };
- return conv[ type ];
-}
-
-static NET::WindowType comboToType(int val)
-{
- static const NET::WindowType conv[] = {
- NET::Normal,
- NET::Dialog,
- NET::Utility,
- NET::Dock,
- NET::Toolbar,
- NET::Menu,
- NET::Splash,
- NET::Desktop,
- NET::TopMenu
- };
- return conv[ val ];
-}
-
-#define GENERIC_RULE( var, func, Type, type, uimethod, uimethod0 ) \
- if ( rules->var##rule == Rules::Unused##Type##Rule ) \
- { \
- enable_##var->setChecked( false ); \
- rule_##var->setCurrentIndex( 0 ); \
- Ui::RulesWidgetBase::var->uimethod0; \
- updateEnable##var(); \
- } \
- else \
- { \
- enable_##var->setChecked( true ); \
- rule_##var->setCurrentIndex( type##_rule_to_combo[ rules->var##rule ] ); \
- Ui::RulesWidgetBase::var->uimethod( func( rules->var )); \
- updateEnable##var(); \
- }
-
-#define CHECKBOX_SET_RULE( var, func ) GENERIC_RULE( var, func, Set, set, setChecked, setChecked( false ))
-#define LINEEDIT_SET_RULE( var, func ) GENERIC_RULE( var, func, Set, set, setText, setText( QString() ))
-#define COMBOBOX_SET_RULE( var, func ) GENERIC_RULE( var, func, Set, set, setCurrentIndex, setCurrentIndex( 0 ))
-#define SPINBOX_SET_RULE( var, func ) GENERIC_RULE( var, func, Set, set, setValue, setValue(0))
-#define CHECKBOX_FORCE_RULE( var, func ) GENERIC_RULE( var, func, Force, force, setChecked, setChecked( false ))
-#define LINEEDIT_FORCE_RULE( var, func ) GENERIC_RULE( var, func, Force, force, setText, setText( QString() ))
-#define COMBOBOX_FORCE_RULE( var, func ) GENERIC_RULE( var, func, Force, force, setCurrentIndex, setCurrentIndex( 0 ))
-#define SPINBOX_FORCE_RULE( var, func ) GENERIC_RULE( var, func, Force, force, setValue, setValue(0))
-
-void RulesWidget::setRules(Rules* rules)
-{
- Rules tmp;
- if (rules == nullptr)
- rules = &tmp; // empty
- description->setText(rules->description);
- wmclass->setText(rules->wmclass);
- whole_wmclass->setChecked(rules->wmclasscomplete);
- wmclass_match->setCurrentIndex(rules->wmclassmatch);
- wmclassMatchChanged();
- role->setText(rules->windowrole);
- role_match->setCurrentIndex(rules->windowrolematch);
- roleMatchChanged();
- types->item(0)->setSelected(rules->types & NET::NormalMask);
- types->item(1)->setSelected(rules->types & NET::DialogMask);
- types->item(2)->setSelected(rules->types & NET::UtilityMask);
- types->item(3)->setSelected(rules->types & NET::DockMask);
- types->item(4)->setSelected(rules->types & NET::ToolbarMask);
- types->item(5)->setSelected(rules->types & NET::MenuMask);
- types->item(6)->setSelected(rules->types & NET::SplashMask);
- types->item(7)->setSelected(rules->types & NET::DesktopMask);
- types->item(8)->setSelected(rules->types & NET::OverrideMask);
- types->item(9)->setSelected(rules->types & NET::TopMenuMask);
- title->setText(rules->title);
- title_match->setCurrentIndex(rules->titlematch);
- titleMatchChanged();
- machine->setText(rules->clientmachine);
- machine_match->setCurrentIndex(rules->clientmachinematch);
- machineMatchChanged();
- LINEEDIT_SET_RULE(position, positionToStr);
- LINEEDIT_SET_RULE(size, sizeToStr);
- COMBOBOX_SET_RULE(desktop, desktopToCombo);
- SPINBOX_SET_RULE(screen, inc);
-#ifdef KWIN_BUILD_ACTIVITIES
- m_selectedActivityId = rules->activity;
- COMBOBOX_SET_RULE(activity, activityToCombo);
-#endif
- CHECKBOX_SET_RULE(maximizehoriz,);
- CHECKBOX_SET_RULE(maximizevert,);
- CHECKBOX_SET_RULE(minimize,);
- CHECKBOX_SET_RULE(shade,);
- CHECKBOX_SET_RULE(fullscreen,);
- COMBOBOX_FORCE_RULE(placement, placementToCombo);
- CHECKBOX_SET_RULE(above,);
- CHECKBOX_SET_RULE(below,);
- CHECKBOX_SET_RULE(noborder,);
- auto decoColorToCombo = [this](const QString &value) {
- for (int i = 0; i < decocolor->count(); ++i) {
- if (decocolor->itemData(i).toString() == value) {
- return i;
- }
- }
- // search for Breeze
- for (int i = 0; i < decocolor->count(); ++i) {
- if (QFileInfo(decocolor->itemData(i).toString()).baseName() == QStringLiteral("Breeze")) {
- return i;
- }
- }
- return 0;
- };
- COMBOBOX_FORCE_RULE(decocolor, decoColorToCombo);
- CHECKBOX_SET_RULE(skiptaskbar,);
- CHECKBOX_SET_RULE(skippager,);
- CHECKBOX_SET_RULE(skipswitcher,);
- CHECKBOX_FORCE_RULE(acceptfocus,);
- CHECKBOX_FORCE_RULE(closeable,);
- CHECKBOX_FORCE_RULE(autogroup,);
- CHECKBOX_FORCE_RULE(autogroupfg,);
- LINEEDIT_FORCE_RULE(autogroupid,);
- SPINBOX_FORCE_RULE(opacityactive,);
- SPINBOX_FORCE_RULE(opacityinactive,);
- LINEEDIT_SET_RULE(shortcut,);
- COMBOBOX_FORCE_RULE(fsplevel,);
- COMBOBOX_FORCE_RULE(fpplevel,);
- COMBOBOX_FORCE_RULE(type, typeToCombo);
- CHECKBOX_SET_RULE(ignoregeometry,);
- LINEEDIT_FORCE_RULE(minsize, sizeToStr);
- LINEEDIT_FORCE_RULE(maxsize, sizeToStr);
- CHECKBOX_FORCE_RULE(strictgeometry,);
- CHECKBOX_FORCE_RULE(disableglobalshortcuts,);
- CHECKBOX_FORCE_RULE(blockcompositing,);
- LINEEDIT_SET_RULE(desktopfile,)
-}
-
-#undef GENERIC_RULE
-#undef CHECKBOX_SET_RULE
-#undef LINEEDIT_SET_RULE
-#undef COMBOBOX_SET_RULE
-#undef SPINBOX_SET_RULE
-#undef CHECKBOX_FORCE_RULE
-#undef LINEEDIT_FORCE_RULE
-#undef COMBOBOX_FORCE_RULE
-#undef SPINBOX_FORCE_RULE
-
-#define GENERIC_RULE( var, func, Type, type, uimethod ) \
- if ( enable_##var->isChecked() && rule_##var->currentIndex() >= 0) \
- { \
- rules->var##rule = combo_to_##type##_rule[ rule_##var->currentIndex() ]; \
- rules->var = func( Ui::RulesWidgetBase::var->uimethod()); \
- } \
- else \
- rules->var##rule = Rules::Unused##Type##Rule;
-
-#define CHECKBOX_SET_RULE( var, func ) GENERIC_RULE( var, func, Set, set, isChecked )
-#define LINEEDIT_SET_RULE( var, func ) GENERIC_RULE( var, func, Set, set, text )
-#define COMBOBOX_SET_RULE( var, func ) GENERIC_RULE( var, func, Set, set, currentIndex )
-#define SPINBOX_SET_RULE( var, func ) GENERIC_RULE( var, func, Set, set, value)
-#define CHECKBOX_FORCE_RULE( var, func ) GENERIC_RULE( var, func, Force, force, isChecked )
-#define LINEEDIT_FORCE_RULE( var, func ) GENERIC_RULE( var, func, Force, force, text )
-#define COMBOBOX_FORCE_RULE( var, func ) GENERIC_RULE( var, func, Force, force, currentIndex )
-#define SPINBOX_FORCE_RULE( var, func ) GENERIC_RULE( var, func, Force, force, value)
-
-Rules* RulesWidget::rules() const
-{
- Rules* rules = new Rules();
- rules->description = description->text();
- rules->wmclass = wmclass->text().toUtf8();
- rules->wmclasscomplete = whole_wmclass->isChecked();
- rules->wmclassmatch = static_cast< Rules::StringMatch >(wmclass_match->currentIndex());
- rules->windowrole = role->text().toUtf8();
- rules->windowrolematch = static_cast< Rules::StringMatch >(role_match->currentIndex());
- rules->types = {};
- bool all_types = true;
- for (int i = 0;
- i < types->count();
- ++i)
- if (!types->item(i)->isSelected())
- all_types = false;
- if (all_types) // if all types are selected, use AllTypesMask (for future expansion)
- rules->types = NET::AllTypesMask;
- else {
- rules->types |= types->item(0)->isSelected() ? NET::NormalMask : NET::WindowTypeMask(0);
- rules->types |= types->item(1)->isSelected() ? NET::DialogMask : NET::WindowTypeMask(0);
- rules->types |= types->item(2)->isSelected() ? NET::UtilityMask : NET::WindowTypeMask(0);
- rules->types |= types->item(3)->isSelected() ? NET::DockMask : NET::WindowTypeMask(0);
- rules->types |= types->item(4)->isSelected() ? NET::ToolbarMask : NET::WindowTypeMask(0);
- rules->types |= types->item(5)->isSelected() ? NET::MenuMask : NET::WindowTypeMask(0);
- rules->types |= types->item(6)->isSelected() ? NET::SplashMask : NET::WindowTypeMask(0);
- rules->types |= types->item(7)->isSelected() ? NET::DesktopMask : NET::WindowTypeMask(0);
- rules->types |= types->item(8)->isSelected() ? NET::OverrideMask : NET::WindowTypeMask(0);
- rules->types |= types->item(9)->isSelected() ? NET::TopMenuMask : NET::WindowTypeMask(0);
- }
- rules->title = title->text();
- rules->titlematch = static_cast< Rules::StringMatch >(title_match->currentIndex());
- rules->clientmachine = machine->text().toUtf8();
- rules->clientmachinematch = static_cast< Rules::StringMatch >(machine_match->currentIndex());
- LINEEDIT_SET_RULE(position, strToPosition);
- LINEEDIT_SET_RULE(size, strToSize);
- COMBOBOX_SET_RULE(desktop, comboToDesktop);
- SPINBOX_SET_RULE(screen, dec);
-#ifdef KWIN_BUILD_ACTIVITIES
- COMBOBOX_SET_RULE(activity, comboToActivity);
-#endif
- CHECKBOX_SET_RULE(maximizehoriz,);
- CHECKBOX_SET_RULE(maximizevert,);
- CHECKBOX_SET_RULE(minimize,);
- CHECKBOX_SET_RULE(shade,);
- CHECKBOX_SET_RULE(fullscreen,);
- COMBOBOX_FORCE_RULE(placement, comboToPlacement);
- CHECKBOX_SET_RULE(above,);
- CHECKBOX_SET_RULE(below,);
- CHECKBOX_SET_RULE(noborder,);
- auto comboToDecocolor = [this](int index) -> QString {
- return decocolor->itemData(index).toString();
- };
- COMBOBOX_FORCE_RULE(decocolor, comboToDecocolor);
- CHECKBOX_SET_RULE(skiptaskbar,);
- CHECKBOX_SET_RULE(skippager,);
- CHECKBOX_SET_RULE(skipswitcher,);
- CHECKBOX_FORCE_RULE(acceptfocus,);
- CHECKBOX_FORCE_RULE(closeable,);
- CHECKBOX_FORCE_RULE(autogroup,);
- CHECKBOX_FORCE_RULE(autogroupfg,);
- LINEEDIT_FORCE_RULE(autogroupid,);
- SPINBOX_FORCE_RULE(opacityactive,);
- SPINBOX_FORCE_RULE(opacityinactive,);
- LINEEDIT_SET_RULE(shortcut,);
- COMBOBOX_FORCE_RULE(fsplevel,);
- COMBOBOX_FORCE_RULE(fpplevel,);
- COMBOBOX_FORCE_RULE(type, comboToType);
- CHECKBOX_SET_RULE(ignoregeometry,);
- LINEEDIT_FORCE_RULE(minsize, strToSize);
- LINEEDIT_FORCE_RULE(maxsize, strToSize);
- CHECKBOX_FORCE_RULE(strictgeometry,);
- CHECKBOX_FORCE_RULE(disableglobalshortcuts,);
- CHECKBOX_FORCE_RULE(blockcompositing,);
- LINEEDIT_SET_RULE(desktopfile,);
- return rules;
-}
-
-#undef GENERIC_RULE
-#undef CHECKBOX_SET_RULE
-#undef LINEEDIT_SET_RULE
-#undef COMBOBOX_SET_RULE
-#undef SPINBOX_SET_RULE
-#undef CHECKBOX_FORCE_RULE
-#undef LINEEDIT_FORCE_RULE
-#undef COMBOBOX_FORCE_RULE
-#undef SPINBOX_FORCE_RULE
-
-#define STRING_MATCH_COMBO( type ) \
- void RulesWidget::type##MatchChanged() \
- { \
- edit_reg_##type->setEnabled( type##_match->currentIndex() == Rules::RegExpMatch ); \
- type->setEnabled( type##_match->currentIndex() != Rules::UnimportantMatch ); \
- }
-
-STRING_MATCH_COMBO(wmclass)
-STRING_MATCH_COMBO(role)
-STRING_MATCH_COMBO(title)
-STRING_MATCH_COMBO(machine)
-
-#undef STRING_MATCH_COMBO
-
-void RulesWidget::detectClicked()
-{
- Q_ASSERT(detect_dlg == nullptr);
- detect_dlg = new DetectDialog;
- connect(detect_dlg, SIGNAL(detectionDone(bool)), this, SLOT(detected(bool)));
- detect_dlg->detect(Ui::RulesWidgetBase::detection_delay->value());
- Ui::RulesWidgetBase::detect->setEnabled(false);
-}
-
-void RulesWidget::detected(bool ok)
-{
- if (ok) {
- wmclass->setText(detect_dlg->selectedClass());
- wmclass_match->setCurrentIndex(Rules::ExactMatch);
- wmclassMatchChanged(); // grrr
- whole_wmclass->setChecked(detect_dlg->selectedWholeClass());
- role->setText(detect_dlg->selectedRole());
- role_match->setCurrentIndex(detect_dlg->selectedRole().isEmpty()
- ? Rules::UnimportantMatch : Rules::ExactMatch);
- roleMatchChanged();
- if (detect_dlg->selectedWholeApp()) {
- for (int i = 0;
- i < types->count();
- ++i)
- types->item(i)->setSelected(true);
- } else {
- NET::WindowType type = detect_dlg->selectedType();
- for (int i = 0;
- i < types->count();
- ++i)
- types->item(i)->setSelected(false);
- types->item(typeToCombo(type))->setSelected(true);
- }
- title->setText(detect_dlg->selectedTitle());
- title_match->setCurrentIndex(detect_dlg->titleMatch());
- titleMatchChanged();
- machine->setText(detect_dlg->selectedMachine());
- machine_match->setCurrentIndex(Rules::UnimportantMatch);
- machineMatchChanged();
- // prefill values from to window to settings which already set
- prefillUnusedValues(detect_dlg->windowInfo());
- }
- delete detect_dlg;
- detect_dlg = nullptr;
- detect_dlg_ok = ok;
- Ui::RulesWidgetBase::detect->setEnabled(true);
-}
-
-#define GENERIC_PREFILL( var, func, info, uimethod ) \
- if ( !enable_##var->isChecked()) \
- { \
- Ui::RulesWidgetBase::var->uimethod( func( info )); \
- }
-
-#define CHECKBOX_PREFILL( var, func, info ) GENERIC_PREFILL( var, func, info, setChecked )
-#define LINEEDIT_PREFILL( var, func, info ) GENERIC_PREFILL( var, func, info, setText )
-#define COMBOBOX_PREFILL( var, func, info ) GENERIC_PREFILL( var, func, info, setCurrentIndex )
-#define SPINBOX_PREFILL( var, func, info ) GENERIC_PREFILL( var, func, info, setValue )
-
-void RulesWidget::prefillUnusedValues(const QVariantMap& info)
-{
- const QSize windowSize{info.value("width").toInt(), info.value("height").toInt()};
- LINEEDIT_PREFILL(position, positionToStr, QPoint(info.value("x").toInt(), info.value("y").toInt()));
- LINEEDIT_PREFILL(size, sizeToStr, windowSize);
- COMBOBOX_PREFILL(desktop, desktopToCombo, info.value("x11DesktopNumber").toInt());
- // COMBOBOX_PREFILL(activity, activityToCombo, info.activity()); // TODO: ivan
- CHECKBOX_PREFILL(maximizehoriz, , info.value("maximizeHorizontal").toBool());
- CHECKBOX_PREFILL(maximizevert, , info.value("maximizeVertical").toBool());
- CHECKBOX_PREFILL(minimize, , info.value("minimized").toBool());
- CHECKBOX_PREFILL(shade, , info.value("shaded").toBool());
- CHECKBOX_PREFILL(fullscreen, , info.value("fullscreen").toBool());
- //COMBOBOX_PREFILL( placement, placementToCombo );
- CHECKBOX_PREFILL(above, , info.value("keepAbove").toBool());
- CHECKBOX_PREFILL(below, , info.value("keepBelow").toBool());
- CHECKBOX_PREFILL(noborder, , info.value("noBorder").toBool());
- CHECKBOX_PREFILL(skiptaskbar, , info.value("skipTaskbar").toBool());
- CHECKBOX_PREFILL(skippager, , info.value("skipPager").toBool());
- CHECKBOX_PREFILL(skipswitcher, , info.value("skipSwitcher").toBool());
- //CHECKBOX_PREFILL( acceptfocus, );
- //CHECKBOX_PREFILL( closeable, );
- //CHECKBOX_PREFILL( autogroup, );
- //CHECKBOX_PREFILL( autogroupfg, );
- //LINEEDIT_PREFILL( autogroupid, );
- SPINBOX_PREFILL(opacityactive, , 100 /*get the actual opacity somehow*/);
- SPINBOX_PREFILL(opacityinactive, , 100 /*get the actual opacity somehow*/);
- //LINEEDIT_PREFILL( shortcut, );
- //COMBOBOX_PREFILL( fsplevel, );
- //COMBOBOX_PREFILL( fpplevel, );
- COMBOBOX_PREFILL(type, typeToCombo, info.value("type").value());
- //CHECKBOX_PREFILL( ignoregeometry, );
- LINEEDIT_PREFILL(minsize, sizeToStr, windowSize);
- LINEEDIT_PREFILL(maxsize, sizeToStr, windowSize);
- //CHECKBOX_PREFILL( strictgeometry, );
- //CHECKBOX_PREFILL( disableglobalshortcuts, );
- //CHECKBOX_PREFILL( blockcompositing, );
- LINEEDIT_PREFILL(desktopfile, , info.value("desktopFile").toString());
-}
-
-#undef GENERIC_PREFILL
-#undef CHECKBOX_PREFILL
-#undef LINEEDIT_PREFILL
-#undef COMBOBOX_PREFILL
-#undef SPINBOX_PREFILL
-
-bool RulesWidget::finalCheck()
-{
- if (description->text().isEmpty()) {
- if (!wmclass->text().isEmpty())
- description->setText(i18n("Settings for %1", wmclass->text()));
- else
- description->setText(i18n("Unnamed entry"));
- }
- bool all_types = true;
- for (int i = 0;
- i < types->count();
- ++i)
- if (!types->item(i)->isSelected())
- all_types = false;
- if (wmclass_match->currentIndex() == Rules::UnimportantMatch && all_types) {
- if (KMessageBox::warningContinueCancel(window(),
- i18n("You have specified the window class as unimportant.\n"
- "This means the settings will possibly apply to windows from all applications. "
- "If you really want to create a generic setting, it is recommended you at least "
- "limit the window types to avoid special window types.")) != KMessageBox::Continue)
- return false;
- }
- return true;
-}
-
-void RulesWidget::prepareWindowSpecific(const QVariantMap &info)
-{
- tabs->setCurrentIndex(1); // geometry tab, skip tab for window identification
- prefillUnusedValues(info);
-}
-
-void RulesWidget::shortcutEditClicked()
-{
- QPointer dlg = new EditShortcutDialog(window());
- dlg->setShortcut(shortcut->text());
- if (dlg->exec() == QDialog::Accepted)
- shortcut->setText(dlg->shortcut());
- delete dlg;
-}
-
-RulesDialog::RulesDialog(QWidget* parent, const char* name)
- : QDialog(parent)
-{
- setObjectName(name);
- setModal(true);
- setWindowTitle(i18n("Edit Window-Specific Settings"));
- setWindowIcon(QIcon::fromTheme("preferences-system-windows-actions"));
-
- setLayout(new QVBoxLayout);
- widget = new RulesWidget(this);
- layout()->addWidget(widget);
-
- QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
- connect(buttons, SIGNAL(accepted()), SLOT(accept()));
- connect(buttons, SIGNAL(rejected()), SLOT(reject()));
- layout()->addWidget(buttons);
-}
-
-// window is set only for Alt+F3/Window-specific settings, because the dialog
-// is then related to one specific window
-Rules* RulesDialog::edit(Rules* r, const QVariantMap& info, bool show_hints)
-{
- rules = r;
- widget->setRules(rules);
- if (!info.isEmpty())
- {
- widget->prepareWindowSpecific(info);
- }
- if (show_hints)
- QTimer::singleShot(0, this, SLOT(displayHints()));
- exec();
- return rules;
-}
-
-void RulesDialog::displayHints()
-{
- QString str = "";
- str += i18n("This configuration dialog allows altering settings only for the selected window"
- " or application. Find the setting you want to affect, enable the setting using the checkbox,"
- " select in what way the setting should be affected and to which value.");
-#if 0 // maybe later
- str += "
" + i18n("Consult the documentation for more details.");
-#endif
- str += "
";
- KMessageBox::information(this, str, QString(), "displayhints");
-}
-
-void RulesDialog::accept()
-{
- if (!widget->finalCheck())
- return;
- rules = widget->rules();
- QDialog::accept();
-}
-
-EditShortcut::EditShortcut(QWidget* parent)
- : QWidget(parent)
-{
- setupUi(this);
-}
-
-void EditShortcut::editShortcut()
-{
- QPointer< ShortcutDialog > dlg = new ShortcutDialog(QKeySequence(shortcut->text()), window());
- if (dlg->exec() == QDialog::Accepted)
- shortcut->setText(dlg->shortcut().toString());
- delete dlg;
-}
-
-void EditShortcut::clearShortcut()
-{
- shortcut->clear();
-}
-
-EditShortcutDialog::EditShortcutDialog(QWidget* parent, const char* name)
- : QDialog(parent)
- , widget(new EditShortcut(this))
-{
- setObjectName(name);
- setModal(true);
- setWindowTitle(i18n("Edit Shortcut"));
-
- setLayout(new QVBoxLayout);
-
- QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
- connect(buttons, SIGNAL(accepted()), SLOT(accept()));
- connect(buttons, SIGNAL(rejected()), SLOT(reject()));
-
- layout()->addWidget(widget);
- layout()->addWidget(buttons);
-}
-
-void EditShortcutDialog::setShortcut(const QString& cut)
-{
- widget->shortcut->setText(cut);
-}
-
-QString EditShortcutDialog::shortcut() const
-{
- return widget->shortcut->text();
-}
-
-ShortcutDialog::ShortcutDialog(const QKeySequence& cut, QWidget* parent)
- : QDialog(parent)
- , widget(new KKeySequenceWidget(this))
-{
- widget->setKeySequence(cut);
- // It's a global shortcut so don't allow multikey shortcuts
- widget->setMultiKeyShortcutsAllowed(false);
-
- QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
- connect(buttons, SIGNAL(accepted()), SLOT(accept()));
- connect(buttons, SIGNAL(rejected()), SLOT(reject()));
-
- setLayout(new QVBoxLayout);
- layout()->addWidget(widget);
- layout()->addWidget(buttons);
-}
-
-void ShortcutDialog::accept()
-{
- QKeySequence seq = shortcut();
- if (!seq.isEmpty()) {
- if (seq[0] == Qt::Key_Escape) {
- reject();
- return;
- }
- if (seq[0] == Qt::Key_Space
- || (seq[0] & Qt::KeyboardModifierMask) == 0) {
- // clear
- widget->clearKeySequence();
- QDialog::accept();
- return;
- }
- }
- QDialog::accept();
-}
-
-QKeySequence ShortcutDialog::shortcut() const
-{
- return widget->keySequence();
-}
-
-} // namespace
-
diff --git a/kcmkwin/kwinrules/ruleswidgetbase.ui b/kcmkwin/kwinrules/ruleswidgetbase.ui
deleted file mode 100644
--- a/kcmkwin/kwinrules/ruleswidgetbase.ui
+++ /dev/null
@@ -1,2834 +0,0 @@
-
-
- KWin::RulesWidgetBase
-
-
-
- 0
- 0
- 592
- 588
-
-
-
- -
-
-
- 0
-
-
-
- &Window matching
-
-
-
-
-
-
- &Description:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- false
-
-
- description
-
-
-
- -
-
-
- -
-
-
- Window &class (application):
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- false
-
-
- wmclass
-
-
-
- -
-
-
-
-
- Unimportant
-
-
- -
-
- Exact Match
-
-
- -
-
- Substring Match
-
-
- -
-
- Regular Expression
-
-
-
-
- -
-
-
- -
-
-
- false
-
-
- Edit
-
-
-
-
-
-
- -
-
-
- Match w&hole window class
-
-
-
- -
-
-
- Window ro&le:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- false
-
-
- role
-
-
-
- -
-
-
-
-
- Unimportant
-
-
- -
-
- Exact Match
-
-
- -
-
- Substring Match
-
-
- -
-
- Regular Expression
-
-
-
-
- -
-
-
- -
-
-
- false
-
-
- Edit
-
-
-
- -
-
-
- Window &types:
-
-
- Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing
-
-
- false
-
-
- types
-
-
-
- -
-
-
- Window t&itle:
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- false
-
-
- title
-
-
-
- -
-
-
-
-
- Unimportant
-
-
- -
-
- Exact Match
-
-
- -
-
- Substring Match
-
-
- -
-
- Regular Expression
-
-
-
-
- -
-
-
- false
-
-
- Edit
-
-
-
-
-
-
- -
-
-
- &Machine (hostname):
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
- false
-
-
- machine
-
-
-
- -
-
-
-
-
- Unimportant
-
-
- -
-
- Exact Match
-
-
- -
-
- Substring Match
-
-
- -
-
- Regular Expression
-
-
-
-
- -
-
-
- false
-
-
- Edit
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- -
-
-
- -
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- &Detect Window Properties
-
-
-
- -
-
-
- s delay
-
-
- 30
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- false
-
-
- Qt::ScrollBarAsNeeded
-
-
- Qt::ScrollBarAsNeeded
-
-
- true
-
-
- false
-
-
- QAbstractItemView::NoDragDrop
-
-
- false
-
-
- QAbstractItemView::ExtendedSelection
-
-
- QListView::Static
-
-
- QListView::TopToBottom
-
-
- true
-
-
- QListView::Adjust
-
-
- 0
-
-
- QListView::ListMode
-
-
- true
-
-
-
-
- Normal Window
-
-
- -
-
- Dialog Window
-
-
- -
-
- Utility Window
-
-
- -
-
- Dock (panel)
-
-
- -
-
- Toolbar
-
-
- -
-
- Torn-Off Menu
-
-
- -
-
- Splash Screen
-
-
- -
-
- Desktop
-
-
- -
-
- Unmanaged Window
-
-
- -
-
- Standalone Menubar
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
-
-
-
-
- &Size && Position
-
-
- -
-
-
- &Position
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
- x,y
-
-
- 0123456789-+,xX:
-
-
-
- -
-
-
- &Size
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
- width,height
-
-
- 0123456789-+,xX:
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- Maximized &horizontally
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- Maximized &vertically
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- &Desktop
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Activit&y
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- false
-
-
- 1
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- &Fullscreen
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- M&inimized
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- Sh&aded
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
-
- Default
-
-
- -
-
- No Placement
-
-
- -
-
- Minimal Overlapping
-
-
- -
-
- Maximized
-
-
- -
-
- Cascaded
-
-
- -
-
- Centered
-
-
- -
-
- Random
-
-
- -
-
- In Top-Left Corner
-
-
- -
-
- Under Mouse
-
-
- -
-
- On Main Window
-
-
-
-
- -
-
-
-
-
-
- Initial p&lacement
-
-
-
- -
-
-
- Windows can ask to appear in a certain position.
-By default this overrides the placement strategy
-what might be nasty if the client abuses the feature
-to unconditionally popup in the middle of your screen.
-
-
- Ignore requested &geometry
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- M&inimum size
-
-
-
- -
-
-
- false
-
-
- width,height
-
-
- 0123456789-+,xX:
-
-
-
- -
-
-
- M&aximum size
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
- width,height
-
-
- 0123456789-+,xX:
-
-
-
- -
-
-
- Eg. terminals or video players can ask to keep a certain aspect ratio
-or only grow by values larger than one
-(eg. by the dimensions of one character).
-This may be pointless and the restriction prevents arbitrary dimensions
-like your complete screen area.
-
-
- Qt::LeftToRight
-
-
- Obey geometry restrictions
-
-
-
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Expanding
-
-
-
- 20
- 16
-
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- Screen
-
-
-
-
-
-
-
- &Arrangement && Access
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- Window shall (not) appear in the manager for virtual desktops
-
-
- Skip pa&ger
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- Window shall (not) appear in the taskbar.
-
-
- Skip &taskbar
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- Window shall (not) appear in the Alt+Tab list
-
-
- Skip &switcher
-
-
-
- -
-
-
- false
-
-
- Edit...
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 20
- 8
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- Shortcut
-
-
-
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- Keep &above
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Autog&roup in foreground
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- Keep &below
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- Autogroup by I&D
-
-
-
- -
-
-
- Autogroup with &identical
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
-
-
-
-
- Appearance && &Fixes
-
-
- -
-
-
- &No titlebar and frame
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- Titlebar color &scheme
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- A&ctive opacity
-
-
-
- -
-
-
- false
-
-
- %
-
-
- 100
-
-
- 100
-
-
-
- -
-
-
- I&nactive opacity
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
- %
-
-
- 100
-
-
- 100
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 20
- 8
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 20
- 8
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- KWin tries to prevent windows from taking the focus
-("activate") while you're working in another window,
-but this may sometimes fail or superact.
-"None" will unconditionally allow this window to get the focus while
-"Extreme" will completely prevent it from taking the focus.
-
-
- &Focus stealing prevention
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
-
- None
-
-
- -
-
- Low
-
-
- -
-
- Normal
-
-
- -
-
- High
-
-
- -
-
- Extreme
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- This controls the focus protection of the currently active window.
-None will always give the focus away,
-Extreme will keep it.
-Otherwise it's interleaved with the stealing prevention
-assigned to the window that wants the focus.
-
-
- Focus protection
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
-
- None
-
-
- -
-
- Low
-
-
- -
-
- Normal
-
-
- -
-
- High
-
-
- -
-
- Extreme
-
-
-
-
- -
-
-
- Windows may prevent to get the focus (activate) when being clicked.
-On the other hand you might wish to prevent a window
-from getting focused on a mouse click.
-
-
- Accept &focus
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- When used, a window will receive
-all keyboard inputs while it is active, including Alt+Tab etc.
-This is especially interesting for emulators or virtual machines.
-
-Be warned:
-you won't be able to Alt+Tab out of the window
-nor use any other global shortcut (such as Alt+F2 to show KRunner)
-while it's active!
-
-
- Ignore global shortcuts
-
-
-
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- &Closeable
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- Window &type
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
-
- Normal Window
-
-
- -
-
- Dialog Window
-
-
- -
-
- Utility Window
-
-
- -
-
- Dock (panel)
-
-
- -
-
- Toolbar
-
-
- -
-
- Torn-Off Menu
-
-
- -
-
- Splash Screen
-
-
- -
-
- Desktop
-
-
- -
-
- Standalone Menubar
-
-
-
-
- -
-
-
- Desktop file name
-
-
-
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Apply Initially
-
-
- -
-
- Remember
-
-
- -
-
- Force
-
-
- -
-
- Apply Now
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
- org.kde.kwin
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- Block compositing
-
-
-
- -
-
-
- false
-
-
-
-
- Do Not Affect
-
-
- -
-
- Force
-
-
- -
-
- Force Temporarily
-
-
-
-
- -
-
-
- false
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
-
-
-
-
-
-
- KLineEdit
- QLineEdit
-
-
-
- KComboBox
- QComboBox
-
-
-
- YesNoBox
- QWidget
-
- 1
-
-
-
- description
- detect
- detection_delay
- wmclass_match
- wmclass
- edit_reg_wmclass
- whole_wmclass
- role_match
- role
- edit_reg_role
- types
- title_match
- title
- edit_reg_title
- machine_match
- machine
- edit_reg_machine
- enable_position
- rule_position
- position
- enable_size
- rule_size
- size
- enable_maximizehoriz
- rule_maximizehoriz
- enable_maximizevert
- rule_maximizevert
- enable_desktop
- rule_desktop
- desktop
- enable_activity
- rule_activity
- activity
- enable_screen
- rule_screen
- screen
- enable_fullscreen
- rule_fullscreen
- enable_minimize
- rule_minimize
- enable_shade
- rule_shade
- enable_placement
- rule_placement
- placement
- enable_ignoregeometry
- rule_ignoregeometry
- enable_minsize
- rule_minsize
- minsize
- enable_maxsize
- rule_maxsize
- maxsize
- enable_strictgeometry
- rule_strictgeometry
- enable_above
- rule_above
- enable_below
- rule_below
- enable_autogroup
- rule_autogroup
- enable_autogroupfg
- rule_autogroupfg
- enable_autogroupid
- rule_autogroupid
- autogroupid
- enable_skiptaskbar
- rule_skiptaskbar
- enable_skippager
- rule_skippager
- enable_skipswitcher
- rule_skipswitcher
- enable_shortcut
- rule_shortcut
- shortcut
- shortcut_edit
- enable_noborder
- rule_noborder
- enable_decocolor
- rule_decocolor
- decocolor
- enable_opacityactive
- rule_opacityactive
- opacityactive
- enable_opacityinactive
- rule_opacityinactive
- opacityinactive
- enable_fsplevel
- rule_fsplevel
- fsplevel
- enable_fpplevel
- rule_fpplevel
- fpplevel
- enable_acceptfocus
- rule_acceptfocus
- enable_disableglobalshortcuts
- rule_disableglobalshortcuts
- enable_closeable
- rule_closeable
- enable_type
- rule_type
- type
- enable_desktopfile
- rule_desktopfile
- desktopfile
- enable_blockcompositing
- rule_blockcompositing
- tabs
-
-
-
-
- detect
- clicked()
- KWin::RulesWidgetBase
- detectClicked()
-
-
- 285
- 124
-
-
- 20
- 20
-
-
-
-
- wmclass_match
- activated(int)
- KWin::RulesWidgetBase
- wmclassMatchChanged()
-
-
- 297
- 196
-
-
- 20
- 20
-
-
-
-
- role_match
- activated(int)
- KWin::RulesWidgetBase
- roleMatchChanged()
-
-
- 297
- 254
-
-
- 20
- 20
-
-
-
-
- title_match
- activated(int)
- KWin::RulesWidgetBase
- titleMatchChanged()
-
-
- 231
- 482
-
-
- 242
- 293
-
-
-
-
- machine_match
- activated(int)
- KWin::RulesWidgetBase
- machineMatchChanged()
-
-
- 194
- 509
-
-
- 242
- 293
-
-
-
-
-
diff --git a/kcmkwin/kwinrules/yesnobox.h b/kcmkwin/kwinrules/yesnobox.h
deleted file mode 100644
--- a/kcmkwin/kwinrules/yesnobox.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2011 Thomas Lübking
- *
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-
-#ifndef YESNOBOX_H
-#define YESNOBOX_H
-
-#include
-#include
-
-#include
-
-class YesNoBox : public QWidget {
- Q_OBJECT
-public:
- explicit YesNoBox( QWidget *parent ) : QWidget(parent)
- {
- QHBoxLayout *l = new QHBoxLayout(this);
- l->setContentsMargins(0, 0, 0, 0);
- l->addWidget(yes = new QRadioButton(i18n("Yes"), this));
- l->addWidget(no = new QRadioButton(i18n("No"), this));
- l->addStretch(100);
- no->setChecked(true);
- connect(yes, SIGNAL(clicked(bool)), this, SIGNAL(clicked(bool)));
- connect(yes, SIGNAL(toggled(bool)), this, SIGNAL(toggled(bool)));
- connect(no, SIGNAL(clicked(bool)), this, SLOT(noClicked(bool)));
- }
- bool isChecked() { return yes->isChecked(); }
-public Q_SLOTS:
- void setChecked(bool b) { yes->setChecked(b); }
- void toggle() { yes->toggle(); }
-
-Q_SIGNALS:
- void clicked(bool checked = false);
- void toggled(bool checked);
-private Q_SLOTS:
- void noClicked(bool checked) { emit clicked(!checked); }
-private:
- QRadioButton *yes, *no;
-};
-
-#endif // YESNOBOX_H