diff --git a/kcmkwin/kwindesktop/CMakeLists.txt b/kcmkwin/kwindesktop/CMakeLists.txt index af905048d..8cb9c5a61 100644 --- a/kcmkwin/kwindesktop/CMakeLists.txt +++ b/kcmkwin/kwindesktop/CMakeLists.txt @@ -1,27 +1,34 @@ include(ECMQMLModules) ecm_find_qmlmodule(org.kde.plasma.core 2.0) # KI18N Translation Domain for this library. add_definitions(-DTRANSLATION_DOMAIN=\"kcm_kwin_virtualdesktops\") ########### next target ############### -set(kcm_kwin_virtualdesktops_PART_SRCS virtualdesktops.cpp desktopsmodel.cpp ../../virtualdesktopsdbustypes.cpp) +set(kcm_kwin_virtualdesktops_PART_SRCS + virtualdesktops.cpp + animationsmodel.cpp + desktopsmodel.cpp + ../../virtualdesktopsdbustypes.cpp +) add_library(kcm_kwin_virtualdesktops MODULE ${kcm_kwin_virtualdesktops_PART_SRCS}) target_link_libraries(kcm_kwin_virtualdesktops Qt5::DBus KF5::I18n KF5::KCMUtils KF5::QuickAddons + KF5::XmlGui + kcmkwincommon ) kcoreaddons_desktop_to_json(kcm_kwin_virtualdesktops "kcm_kwin_virtualdesktops.desktop") ########### install files ############### install(TARGETS kcm_kwin_virtualdesktops DESTINATION ${KDE_INSTALL_PLUGINDIR}/kcms) install(FILES kcm_kwin_virtualdesktops.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) kpackage_install_package(package kcm_kwin_virtualdesktops kcms) diff --git a/kcmkwin/kwindesktop/animationsmodel.cpp b/kcmkwin/kwindesktop/animationsmodel.cpp new file mode 100644 index 000000000..c60e1b19e --- /dev/null +++ b/kcmkwin/kwindesktop/animationsmodel.cpp @@ -0,0 +1,154 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2018 Vlad Zagorodniy + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#include "animationsmodel.h" + +namespace KWin +{ + +AnimationsModel::AnimationsModel(QObject *parent) + : EffectModel(parent) +{ + connect(this, &AnimationsModel::currentIndexChanged, this, + [this] { + const QModelIndex index_ = index(m_currentIndex, 0); + if (!index_.isValid()) { + return; + } + const bool configurable = index_.data(ConfigurableRole).toBool(); + if (configurable != m_currentConfigurable) { + m_currentConfigurable = configurable; + emit currentConfigurableChanged(); + } + } + ); +} + +bool AnimationsModel::enabled() const +{ + return m_enabled; +} + +void AnimationsModel::setEnabled(bool enabled) +{ + if (m_enabled != enabled) { + m_enabled = enabled; + emit enabledChanged(); + } +} + +int AnimationsModel::currentIndex() const +{ + return m_currentIndex; +} + +void AnimationsModel::setCurrentIndex(int index) +{ + if (m_currentIndex != index) { + m_currentIndex = index; + emit currentIndexChanged(); + } +} + +bool AnimationsModel::currentConfigurable() const +{ + return m_currentConfigurable; +} + +bool AnimationsModel::shouldStore(const EffectData &data) const +{ + return data.untranslatedCategory.contains( + QStringLiteral("Virtual Desktop Switching Animation"), Qt::CaseInsensitive); +} + +EffectModel::Status AnimationsModel::status(int row) const +{ + return Status(data(index(row, 0), static_cast(EffectStatusRole)).toInt()); +} + +bool AnimationsModel::modelCurrentEnabled() const +{ + for (int i = 0; i < rowCount(); ++i) { + if (status(i) != Status::Disabled) { + return true; + } + } + + return false; +} + +int AnimationsModel::modelCurrentIndex() const +{ + for (int i = 0; i < rowCount(); ++i) { + if (status(i) != Status::Disabled) { + return i; + } + } + + return 0; +} + +void AnimationsModel::load() +{ + EffectModel::load(); + setEnabled(modelCurrentEnabled()); + setCurrentIndex(modelCurrentIndex()); +} + +void AnimationsModel::save() +{ + for (int i = 0; i < rowCount(); ++i) { + const auto status = (m_enabled && i == m_currentIndex) + ? EffectModel::Status::Enabled + : EffectModel::Status::Disabled; + updateEffectStatus(index(i, 0), status); + } + + EffectModel::save(); +} + +void AnimationsModel::defaults() +{ + EffectModel::defaults(); + setEnabled(modelCurrentEnabled()); + setCurrentIndex(modelCurrentIndex()); +} + +bool AnimationsModel::needsSave() const +{ + KConfigGroup kwinConfig(KSharedConfig::openConfig("kwinrc"), "Plugins"); + + for (int i = 0; i < rowCount(); ++i) { + const QModelIndex index_ = index(i, 0); + const bool enabledConfig = kwinConfig.readEntry( + index_.data(ServiceNameRole).toString() + QLatin1String("Enabled"), + index_.data(EnabledByDefaultRole).toBool() + ); + const bool enabled = (m_enabled && i == m_currentIndex); + + if (enabled != enabledConfig) { + return true; + } + } + + return false; +} + +} diff --git a/kcmkwin/kwindesktop/animationsmodel.h b/kcmkwin/kwindesktop/animationsmodel.h new file mode 100644 index 000000000..36b579edd --- /dev/null +++ b/kcmkwin/kwindesktop/animationsmodel.h @@ -0,0 +1,71 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2018 Vlad Zagorodniy + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +#pragma once + +#include "effectmodel.h" + +namespace KWin +{ + +class AnimationsModel : public EffectModel +{ + Q_OBJECT + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) + Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) + Q_PROPERTY(bool currentConfigurable READ currentConfigurable NOTIFY currentConfigurableChanged) + +public: + explicit AnimationsModel(QObject *parent = nullptr); + + bool enabled() const; + void setEnabled(bool enabled); + + int currentIndex() const; + void setCurrentIndex(int index); + + bool currentConfigurable() const; + + void load(); + void save(); + void defaults(); + bool needsSave() const; + +Q_SIGNALS: + void enabledChanged(); + void currentIndexChanged(); + void currentConfigurableChanged(); + +protected: + bool shouldStore(const EffectData &data) const override; + +private: + Status status(int row) const; + bool modelCurrentEnabled() const; + int modelCurrentIndex() const; + + bool m_enabled = false; + int m_currentIndex = -1; + bool m_currentConfigurable = false; + + Q_DISABLE_COPY(AnimationsModel) +}; + +} diff --git a/kcmkwin/kwindesktop/package/contents/ui/main.qml b/kcmkwin/kwindesktop/package/contents/ui/main.qml index d99e0fc75..e7641247d 100644 --- a/kcmkwin/kwindesktop/package/contents/ui/main.qml +++ b/kcmkwin/kwindesktop/package/contents/ui/main.qml @@ -1,255 +1,298 @@ /* * Copyright (C) 2018 Eike Hein * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ import QtQuick 2.1 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.4 as QtControls import org.kde.kirigami 2.5 as Kirigami import org.kde.plasma.core 2.1 as PlasmaCore import org.kde.kcm 1.2 ScrollViewKCM { id: root ConfigModule.quickHelp: i18n("Virtual Desktops") Connections { target: kcm.desktopsModel onReadyChanged: { rowsSpinBox.value = kcm.desktopsModel.rows; } onRowsChanged: { rowsSpinBox.value = kcm.desktopsModel.rows; } } Component { id: desktopsListItemComponent Kirigami.SwipeListItem { id: listItem contentItem: RowLayout { QtControls.TextField { id: nameField background: null leftPadding: Kirigami.Units.largeSpacing topPadding: 0 bottomPadding: 0 Layout.fillWidth: true Layout.alignment: Qt.AlignVCenter text: model.display readOnly: true onEditingFinished: { readOnly = true; Qt.callLater(kcm.desktopsModel.setDesktopName, model.Id, text); } } } actions: [ Kirigami.Action { enabled: !model.IsMissing iconName: "edit-rename" tooltip: i18nc("@info:tooltip", "Rename") onTriggered: { nameField.readOnly = false; nameField.selectAll(); nameField.forceActiveFocus(); } }, Kirigami.Action { enabled: !model.IsMissing iconName: "list-remove" tooltip: i18nc("@info:tooltip", "Remove") onTriggered: kcm.desktopsModel.removeDesktop(model.Id) }] } } header: ColumnLayout { id: messagesLayout spacing: Kirigami.Units.largeSpacing Kirigami.InlineMessage { Layout.fillWidth: true type: Kirigami.MessageType.Error text: kcm.desktopsModel.error visible: kcm.desktopsModel.error != "" } Kirigami.InlineMessage { Layout.fillWidth: true type: Kirigami.MessageType.Information text: i18n("Virtual desktops have been changed outside this settings application. Saving now will overwrite the changes.") visible: kcm.desktopsModel.serverModified } RowLayout { QtControls.Label { text: i18n("Rows:") } QtControls.SpinBox { id: rowsSpinBox from: 1 to: 20 onValueModified: kcm.desktopsModel.rows = value } Item { // Spacer Layout.fillWidth: true } QtControls.Button { Layout.alignment: Qt.AlignRight text: i18nc("@action:button", "Add") icon.name: "list-add" onClicked: kcm.desktopsModel.createDesktop(i18n("New Desktop")) } } } view: ListView { id: desktopsList model: kcm.desktopsModel.ready ? kcm.desktopsModel : null section.property: "DesktopRow" section.delegate: Kirigami.AbstractListItem { width: desktopsList.width backgroundColor: Kirigami.Theme.backgroundColor hoverEnabled: false supportsMouseEvents: false Kirigami.Theme.inherit: false Kirigami.Theme.colorSet: Kirigami.Theme.Window QtControls.Label { text: i18n("Row %1", section) } } delegate: Kirigami.DelegateRecycler { width: desktopsList.width sourceComponent: desktopsListItemComponent } } footer: ColumnLayout { Kirigami.FormLayout { anchors.horizontalCenter: parent.horizontalCenter Connections { target: kcm onNavWrapsChanged: navWraps.checked = kcm.navWraps onOsdEnabledChanged: osdEnabled.checked = kcm.osdEnabled onOsdDurationChanged: osdDuration.value = kcm.osdDuration onOsdTextOnlyChanged: osdTextOnly.checked = !kcm.osdTextOnly } QtControls.CheckBox { id: navWraps Kirigami.FormData.label: i18n("Options:") text: i18n("Navigation wraps around") checked: kcm.navWraps onCheckedChanged: kcm.navWraps = checked } + RowLayout { + Layout.fillWidth: true + + QtControls.CheckBox { + id: animationEnabled + + text: i18n("Show animation when switching:") + + checked: kcm.animationsModel.enabled + + onCheckedChanged: kcm.animationsModel.enabled = checked + } + + QtControls.ComboBox { + enabled: animationEnabled.checked + + model: kcm.animationsModel + textRole: "NameRole" + currentIndex: kcm.animationsModel.currentIndex + onActivated: kcm.animationsModel.currentIndex = currentIndex + } + + QtControls.Button { + enabled: animationEnabled.checked && kcm.animationsModel.currentConfigurable + + icon.name: "configure" + + onClicked: kcm.configureAnimation() + } + + QtControls.Button { + enabled: animationEnabled.checked + + icon.name: "dialog-information" + + onClicked: kcm.showAboutAnimation() + } + + Item { + Layout.fillWidth: true + } + } + RowLayout { Layout.fillWidth: true QtControls.CheckBox { id: osdEnabled text: i18n("Show on-screen display when switching:") checked: kcm.osdEnabled onCheckedChanged: kcm.osdEnabled = checked } QtControls.SpinBox { id: osdDuration enabled: osdEnabled.checked from: 0 to: 10000 stepSize: 100 textFromValue: function(value, locale) { return i18n("%1 ms", value)} value: kcm.osdDuration onValueChanged: kcm.osdDuration = value } } RowLayout { Layout.fillWidth: true Item { width: units.largeSpacing } QtControls.CheckBox { id: osdTextOnly enabled: osdEnabled.checked text: i18n("Show desktop layout indicators") checked: kcm.osdTextOnly onCheckedChanged: kcm.osdTextOnly = !checked } } } } } diff --git a/kcmkwin/kwindesktop/virtualdesktops.cpp b/kcmkwin/kwindesktop/virtualdesktops.cpp index b0a61b69a..99d441c80 100644 --- a/kcmkwin/kwindesktop/virtualdesktops.cpp +++ b/kcmkwin/kwindesktop/virtualdesktops.cpp @@ -1,205 +1,335 @@ /* * Copyright (C) 2018 Eike Hein + * Copyright (C) 2018 Vlad Zagorodniy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "virtualdesktops.h" +#include "animationsmodel.h" #include "desktopsmodel.h" +#include #include +#include #include #include #include +#include + +#include +#include +#include +#include K_PLUGIN_FACTORY_WITH_JSON(VirtualDesktopsFactory, "kcm_kwin_virtualdesktops.json", registerPlugin();) namespace KWin { VirtualDesktops::VirtualDesktops(QObject *parent, const QVariantList &args) : KQuickAddons::ConfigModule(parent, args) , m_kwinConfig(KSharedConfig::openConfig("kwinrc")) , m_desktopsModel(new KWin::DesktopsModel(this)) , m_navWraps(true) , m_osdEnabled(false) , m_osdDuration(1000) , m_osdTextOnly(false) + , m_animationsModel(new AnimationsModel(this)) { KAboutData *about = new KAboutData(QStringLiteral("kcm_kwin_virtualdesktops"), i18n("Configure Virtual Desktops"), QStringLiteral("2.0"), QString(), KAboutLicense::GPL); setAboutData(about); setButtons(Apply | Default); QObject::connect(m_desktopsModel, &KWin::DesktopsModel::userModifiedChanged, this, &VirtualDesktops::updateNeedsSave); + connect(m_animationsModel, &AnimationsModel::enabledChanged, + this, &VirtualDesktops::updateNeedsSave); + connect(m_animationsModel, &AnimationsModel::currentIndexChanged, + this, &VirtualDesktops::updateNeedsSave); } VirtualDesktops::~VirtualDesktops() { } QAbstractItemModel *VirtualDesktops::desktopsModel() const { return m_desktopsModel; } bool VirtualDesktops::navWraps() const { return m_navWraps; } void VirtualDesktops::setNavWraps(bool wraps) { if (m_navWraps != wraps) { m_navWraps = wraps; emit navWrapsChanged(); updateNeedsSave(); } } bool VirtualDesktops::osdEnabled() const { return m_osdEnabled; } void VirtualDesktops::setOsdEnabled(bool enabled) { if (m_osdEnabled != enabled) { m_osdEnabled = enabled; emit osdEnabledChanged(); updateNeedsSave(); } } int VirtualDesktops::osdDuration() const { return m_osdDuration; } void VirtualDesktops::setOsdDuration(int duration) { if (m_osdDuration != duration) { m_osdDuration = duration; emit osdDurationChanged(); updateNeedsSave(); } } int VirtualDesktops::osdTextOnly() const { return m_osdTextOnly; } void VirtualDesktops::setOsdTextOnly(bool textOnly) { if (m_osdTextOnly != textOnly) { m_osdTextOnly = textOnly; emit osdTextOnlyChanged(); updateNeedsSave(); } } +QAbstractItemModel *VirtualDesktops::animationsModel() const +{ + return m_animationsModel; +} + void VirtualDesktops::load() { KConfigGroup navConfig(m_kwinConfig, "Windows"); setNavWraps(navConfig.readEntry("RollOverDesktops", true)); KConfigGroup osdConfig(m_kwinConfig, "Plugins"); setOsdEnabled(osdConfig.readEntry("desktopchangeosdEnabled", false)); KConfigGroup osdSettings(m_kwinConfig, "Script-desktopchangeosd"); setOsdDuration(osdSettings.readEntry("PopupHideDelay", 1000)); setOsdTextOnly(osdSettings.readEntry("TextOnly", false)); + + m_animationsModel->load(); } void VirtualDesktops::save() { m_desktopsModel->syncWithServer(); + m_animationsModel->save(); KConfigGroup navConfig(m_kwinConfig, "Windows"); navConfig.writeEntry("RollOverDesktops", m_navWraps); KConfigGroup osdConfig(m_kwinConfig, "Plugins"); osdConfig.writeEntry("desktopchangeosdEnabled", m_osdEnabled); KConfigGroup osdSettings(m_kwinConfig, "Script-desktopchangeosd"); osdSettings.writeEntry("PopupHideDelay", m_osdDuration); osdSettings.writeEntry("TextOnly", m_osdTextOnly); m_kwinConfig->sync(); QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KWin"), QStringLiteral("org.kde.KWin"), QStringLiteral("reloadConfig")); QDBusConnection::sessionBus().send(message); setNeedsSave(false); } void VirtualDesktops::defaults() { m_desktopsModel->setRows(1); + m_animationsModel->defaults(); setNavWraps(true); setOsdEnabled(false); setOsdDuration(1000); setOsdTextOnly(false); } +void VirtualDesktops::configureAnimation() +{ + const QModelIndex index = m_animationsModel->index(m_animationsModel->currentIndex(), 0); + if (!index.isValid()) { + return; + } + + const QString name = index.data(AnimationsModel::NameRole).toString(); + const QString serviceName = index.data(AnimationsModel::ServiceNameRole).toString(); + + QPointer configDialog = new QDialog(); + + KCModule *kcm = KPluginTrader::createInstanceFromQuery( + QStringLiteral("kwin/effects/configs/"), + QString(), + QStringLiteral("'%1' in [X-KDE-ParentComponents]").arg(serviceName), + configDialog + ); + + if (!kcm) { + delete configDialog; + return; + } + + configDialog->setWindowTitle(name); + configDialog->setLayout(new QVBoxLayout); + + auto buttons = new QDialogButtonBox( + QDialogButtonBox::Ok | + QDialogButtonBox::Cancel | + QDialogButtonBox::RestoreDefaults, + configDialog + ); + QObject::connect(buttons, &QDialogButtonBox::accepted, configDialog, &QDialog::accept); + QObject::connect(buttons, &QDialogButtonBox::rejected, configDialog, &QDialog::reject); + QObject::connect(buttons->button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, kcm, &KCModule::defaults); + + auto showWidget = new QWidget(configDialog); + auto layout = new QVBoxLayout; + showWidget->setLayout(layout); + layout->addWidget(kcm); + configDialog->layout()->addWidget(showWidget); + configDialog->layout()->addWidget(buttons); + + if (configDialog->exec() == QDialog::Accepted) { + kcm->save(); + } else if (!configDialog.isNull()) { + kcm->load(); + } + + delete configDialog; +} + +void VirtualDesktops::showAboutAnimation() +{ + const QModelIndex index = m_animationsModel->index(m_animationsModel->currentIndex(), 0); + if (!index.isValid()) { + return; + } + + const QString name = index.data(AnimationsModel::NameRole).toString(); + const QString comment = index.data(AnimationsModel::DescriptionRole).toString(); + const QString author = index.data(AnimationsModel::AuthorNameRole).toString(); + const QString email = index.data(AnimationsModel::AuthorEmailRole).toString(); + const QString website = index.data(AnimationsModel::WebsiteRole).toString(); + const QString version = index.data(AnimationsModel::VersionRole).toString(); + const QString license = index.data(AnimationsModel::LicenseRole).toString(); + const QString icon = index.data(AnimationsModel::IconNameRole).toString(); + + const KAboutLicense::LicenseKey licenseType = KAboutLicense::byKeyword(license).key(); + + KAboutData aboutData( + name, // Plugin name + name, // Display name + version, // Version + comment, // Short description + licenseType, // License + QString(), // Copyright statement + QString(), // Other text + website.toLatin1() // Home page + ); + aboutData.setProgramLogo(icon); + + const QStringList authors = author.split(','); + const QStringList emails = email.split(','); + + if (authors.count() == emails.count()) { + int i = 0; + for (const QString &author : authors) { + if (!author.isEmpty()) { + aboutData.addAuthor(i18n(author.toUtf8()), QString(), emails[i]); + } + i++; + } + } + + QPointer aboutPlugin = new KAboutApplicationDialog(aboutData); + aboutPlugin->exec(); + + delete aboutPlugin; +} + void VirtualDesktops::updateNeedsSave() { bool needsSave = false; if (m_desktopsModel->userModified()) { needsSave = true; } + if (m_animationsModel->needsSave()) { + needsSave = true; + } + KConfigGroup navConfig(m_kwinConfig, "Windows"); if (m_navWraps != navConfig.readEntry("RollOverDesktops", true)) { needsSave = true; } KConfigGroup osdConfig(m_kwinConfig, "Plugins"); if (m_osdEnabled != osdConfig.readEntry("desktopchangeosdEnabled", false)) { needsSave = true; } KConfigGroup osdSettings(m_kwinConfig, "Script-desktopchangeosd"); if (m_osdDuration != osdSettings.readEntry("PopupHideDelay", 1000)) { needsSave = true; } if (m_osdTextOnly != osdSettings.readEntry("TextOnly", false)) { needsSave = true; } setNeedsSave(needsSave); } } #include "virtualdesktops.moc" diff --git a/kcmkwin/kwindesktop/virtualdesktops.h b/kcmkwin/kwindesktop/virtualdesktops.h index a230985bf..fcef65dad 100644 --- a/kcmkwin/kwindesktop/virtualdesktops.h +++ b/kcmkwin/kwindesktop/virtualdesktops.h @@ -1,82 +1,91 @@ /* * Copyright (C) 2018 Eike Hein + * Copyright (C) 2018 Vlad Zagorodniy * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef VIRTUALDESKTOPS_H #define VIRTUALDESKTOPS_H #include #include namespace KWin { +class AnimationsModel; class DesktopsModel; class VirtualDesktops : public KQuickAddons::ConfigModule { Q_OBJECT Q_PROPERTY(QAbstractItemModel* desktopsModel READ desktopsModel CONSTANT) Q_PROPERTY(bool navWraps READ navWraps WRITE setNavWraps NOTIFY navWrapsChanged) Q_PROPERTY(bool osdEnabled READ osdEnabled WRITE setOsdEnabled NOTIFY osdEnabledChanged) Q_PROPERTY(int osdDuration READ osdDuration WRITE setOsdDuration NOTIFY osdDurationChanged) Q_PROPERTY(bool osdTextOnly READ osdTextOnly WRITE setOsdTextOnly NOTIFY osdTextOnlyChanged) + Q_PROPERTY(QAbstractItemModel *animationsModel READ animationsModel CONSTANT) public: explicit VirtualDesktops(QObject *parent = nullptr, const QVariantList &list = QVariantList()); ~VirtualDesktops() override; QAbstractItemModel *desktopsModel() const; bool navWraps() const; void setNavWraps(bool wraps); bool osdEnabled() const; void setOsdEnabled(bool enabled); int osdDuration() const; void setOsdDuration(int duration); int osdTextOnly() const; void setOsdTextOnly(bool textOnly); + QAbstractItemModel *animationsModel() const; + Q_SIGNALS: void navWrapsChanged() const; void osdEnabledChanged() const; void osdDurationChanged() const; void osdTextOnlyChanged() const; public Q_SLOTS: void load() override; void save() override; void defaults() override; + void configureAnimation(); + void showAboutAnimation(); + private Q_SLOTS: void updateNeedsSave(); private: KSharedConfigPtr m_kwinConfig; DesktopsModel *m_desktopsModel; bool m_navWraps; bool m_osdEnabled; int m_osdDuration; bool m_osdTextOnly; + AnimationsModel *m_animationsModel; }; } #endif