diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e7531a8e0..dd392a62fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,7 @@ find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS Core DBus Quick + QuickWidgets Script UiTools Widgets diff --git a/kcmkwin/kwindecoration/CMakeLists.txt b/kcmkwin/kwindecoration/CMakeLists.txt index e5d45bc7e7..82b1ef244a 100644 --- a/kcmkwin/kwindecoration/CMakeLists.txt +++ b/kcmkwin/kwindecoration/CMakeLists.txt @@ -1,23 +1,14 @@ # KI18N Translation Domain for this library add_definitions(-DTRANSLATION_DOMAIN=\"kcmkwindecoration\") -# need a header file from Aurorae sources -include_directories( - ${KWIN_SOURCE_DIR}/clients/aurorae/src/lib - ../utils/ -) - -set(AURORAE_SOURCE_DIR ${KWIN_SOURCE_DIR}/clients/aurorae/src/lib/) +add_subdirectory(declarative-plugin) set(kcm_kwindecoration_PART_SRCS - kwindecoration.cpp + kcm.cpp buttons.cpp - buttonsconfigdialog.cpp +# buttonsconfigdialog.cpp configdialog.cpp - preview.cpp decorationmodel.cpp - ${AURORAE_SOURCE_DIR}/auroraetheme.cpp - ${AURORAE_SOURCE_DIR}/themeconfig.cpp ) ki18n_wrap_ui(kcm_kwindecoration_PART_SRCS @@ -29,14 +20,17 @@ ki18n_wrap_ui(kcm_kwindecoration_PART_SRCS add_library(kcm_kwindecoration MODULE ${kcm_kwindecoration_PART_SRCS}) target_link_libraries(kcm_kwindecoration - kdecorations + KDecoration2::KDecoration Qt5::DBus Qt5::Quick + Qt5::QuickWidgets Qt5::UiTools KF5::Completion KF5::ConfigWidgets KF5::I18n KF5::NewStuff + KF5::WindowSystem + KF5::Service ) install(TARGETS kcm_kwindecoration DESTINATION ${PLUGIN_INSTALL_DIR} ) @@ -45,7 +39,4 @@ install(TARGETS kcm_kwindecoration DESTINATION ${PLUGIN_INSTALL_DIR} ) install( FILES kwindecoration.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) install( FILES qml/main.qml - qml/AuroraeDecoration.qml - qml/AuroraePreview.qml - qml/DecorationPreview.qml DESTINATION ${DATA_INSTALL_DIR}/kwin/kcm_kwindecoration) diff --git a/kcmkwin/kwindecoration/declarative-plugin/CMakeLists.txt b/kcmkwin/kwindecoration/declarative-plugin/CMakeLists.txt new file mode 100644 index 0000000000..7d5c492250 --- /dev/null +++ b/kcmkwin/kwindecoration/declarative-plugin/CMakeLists.txt @@ -0,0 +1,20 @@ +set(plugin_SRCS + previewbridge.cpp + previewclient.cpp + previewitem.cpp + previewsettings.cpp + plugin.cpp +) + +add_library(kdecorationprivatedeclarative SHARED ${plugin_SRCS}) +target_link_libraries(kdecorationprivatedeclarative + KDecoration2::KDecoration + KDecoration2::KDecoration2Private + Qt5::Quick + KF5::CoreAddons + KF5::ConfigWidgets + KF5::Service +) + +install(TARGETS kdecorationprivatedeclarative DESTINATION ${QML_INSTALL_DIR}/org/kde/kwin/private/kdecoration ) +install(FILES qmldir DESTINATION ${QML_INSTALL_DIR}/org/kde/kwin/private/kdecoration ) diff --git a/kcmkwin/kwindecoration/declarative-plugin/plugin.cpp b/kcmkwin/kwindecoration/declarative-plugin/plugin.cpp new file mode 100644 index 0000000000..6339d3b3a7 --- /dev/null +++ b/kcmkwin/kwindecoration/declarative-plugin/plugin.cpp @@ -0,0 +1,51 @@ +/* + * Copyright 2014 Martin Gräßlin + * + * 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 "plugin.h" +#include "previewbridge.h" +#include "previewclient.h" +#include "previewitem.h" +#include "previewsettings.h" + +#include +#include + +#include + +namespace KDecoration2 +{ +namespace Preview +{ + +void Plugin::registerTypes(const char *uri) +{ + Q_ASSERT(QLatin1String(uri) == QLatin1String("org.kde.kwin.private.kdecoration")); + qmlRegisterType(uri, 1, 0, "Bridge"); + qmlRegisterType(uri, 1, 0, "Settings"); + qmlRegisterType(uri, 1, 0, "Decoration"); + qmlRegisterType(); + qmlRegisterType(); + qmlRegisterType(); +} + +} +} + +#include "plugin.moc" + diff --git a/kcmkwin/kwindecoration/declarative-plugin/plugin.h b/kcmkwin/kwindecoration/declarative-plugin/plugin.h new file mode 100644 index 0000000000..574bdb290b --- /dev/null +++ b/kcmkwin/kwindecoration/declarative-plugin/plugin.h @@ -0,0 +1,41 @@ +/* + * Copyright 2014 Martin Gräßlin + * + * 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 KDECOARTIONS_PREVIEW_PLUGIN_H +#define KDECOARTIONS_PREVIEW_PLUGIN_H + +#include + +namespace KDecoration2 +{ +namespace Preview +{ + +class Plugin : public QQmlExtensionPlugin +{ + Q_PLUGIN_METADATA(IID "org.kde.kdecoration2") + Q_OBJECT +public: + void registerTypes(const char *uri) override; +}; + +} +} + +#endif diff --git a/kcmkwin/kwindecoration/declarative-plugin/previewbridge.cpp b/kcmkwin/kwindecoration/declarative-plugin/previewbridge.cpp new file mode 100644 index 0000000000..d6e7dbe26d --- /dev/null +++ b/kcmkwin/kwindecoration/declarative-plugin/previewbridge.cpp @@ -0,0 +1,165 @@ +/* + * Copyright 2014 Martin Gräßlin + * + * 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 "previewbridge.h" +#include "previewclient.h" +#include "previewitem.h" +#include "previewsettings.h" + +#include +#include + +#include +#include +#include + +#include + +namespace KDecoration2 +{ +namespace Preview +{ + +static const QString s_pluginName = QStringLiteral("org.kde.kdecoration2"); + +PreviewBridge::PreviewBridge(QObject *parent) + : DecorationBridge(parent) + , m_lastCreatedClient(nullptr) + , m_lastCreatedSettings(nullptr) + , m_valid(false) +{ + connect(this, &PreviewBridge::pluginChanged, this, &PreviewBridge::createFactory); +} + +PreviewBridge::~PreviewBridge() = default; + +std::unique_ptr PreviewBridge::createClient(DecoratedClient *client, Decoration *decoration) +{ + auto ptr = std::unique_ptr(new PreviewClient(client, decoration)); + m_lastCreatedClient = ptr.get(); + return std::move(ptr); +} + +void PreviewBridge::update(Decoration *decoration, const QRect &geometry) +{ + Q_UNUSED(geometry) + auto it = std::find_if(m_previewItems.constBegin(), m_previewItems.constEnd(), [decoration](PreviewItem *item) { + return item->decoration() == decoration; + }); + if (it != m_previewItems.constEnd()) { + (*it)->update(); + } +} + +std::unique_ptr PreviewBridge::settings(DecorationSettings *parent) +{ + auto ptr = std::unique_ptr(new PreviewSettings(parent)); + m_lastCreatedSettings = ptr.get(); + return std::move(ptr); +} + +void PreviewBridge::registerPreviewItem(PreviewItem *item) +{ + m_previewItems.append(item); +} + +void PreviewBridge::unregisterPreviewItem(PreviewItem *item) +{ + m_previewItems.removeAll(item); +} + +void PreviewBridge::setPlugin(const QString &plugin) +{ + if (m_plugin == plugin) { + return; + } + m_plugin = plugin; + qDebug() << "Plugin changed to: " << m_plugin; + emit pluginChanged(); +} + +QString PreviewBridge::theme() const +{ + return m_theme; +} + +void PreviewBridge::setTheme(const QString &theme) +{ + if (m_theme == theme) { + return; + } + m_theme = theme; + emit themeChanged(); +} + +QString PreviewBridge::plugin() const +{ + return m_plugin; +} + +void PreviewBridge::createFactory() +{ + m_factory.clear(); + if (m_plugin.isNull()) { + setValid(false); + qDebug() <<"Plugin not set"; + return; + } + const auto offers = KPluginTrader::self()->query(s_pluginName, + s_pluginName, + QStringLiteral("[X-KDE-PluginInfo-Name] == '%1'").arg(m_plugin)); + if (offers.isEmpty()) { + setValid(false); + qDebug() << "no offers"; + return; + } + KPluginLoader loader(offers.first().libraryPath()); + m_factory = loader.factory(); + qDebug() << "Factory: " << !m_factory.isNull(); + setValid(!m_factory.isNull()); +} + +bool PreviewBridge::isValid() const +{ + return m_valid; +} + +void PreviewBridge::setValid(bool valid) +{ + if (m_valid == valid) { + return; + } + m_valid = valid; + emit validChanged(); +} + +Decoration *PreviewBridge::createDecoration(QObject *parent) +{ + if (!m_valid) { + return nullptr; + } + QVariantMap args({ {QStringLiteral("bridge"), QVariant::fromValue(this)} }); + if (!m_theme.isNull()) { + args.insert(QStringLiteral("theme"), m_theme); + } + return m_factory->create(parent, QVariantList({args})); +} + +} +} diff --git a/kcmkwin/kwindecoration/declarative-plugin/previewbridge.h b/kcmkwin/kwindecoration/declarative-plugin/previewbridge.h new file mode 100644 index 0000000000..52814376b9 --- /dev/null +++ b/kcmkwin/kwindecoration/declarative-plugin/previewbridge.h @@ -0,0 +1,92 @@ +/* + * Copyright 2014 Martin Gräßlin + * + * 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 KDECOARTIONS_PREVIEW_BRIDGE_H +#define KDECOARTIONS_PREVIEW_BRIDGE_H + +#include + +#include +#include + +class KPluginFactory; + +namespace KDecoration2 +{ +namespace Preview +{ + +class PreviewClient; +class PreviewItem; +class PreviewSettings; + +class PreviewBridge : public DecorationBridge +{ + Q_OBJECT + Q_PROPERTY(QString plugin READ plugin WRITE setPlugin NOTIFY pluginChanged) + Q_PROPERTY(QString theme READ theme WRITE setTheme NOTIFY themeChanged) + Q_PROPERTY(bool valid READ isValid NOTIFY validChanged) +public: + explicit PreviewBridge(QObject *parent = nullptr); + virtual ~PreviewBridge(); + std::unique_ptr createClient(DecoratedClient *client, Decoration *decoration) override; + void update(Decoration* decoration, const QRect& geometry) override; + std::unique_ptr settings(DecorationSettings *parent) override; + + PreviewClient *lastCreatedClient() { + return m_lastCreatedClient; + } + PreviewSettings *lastCreatedSettings() { + return m_lastCreatedSettings; + } + + void registerPreviewItem(PreviewItem *item); + void unregisterPreviewItem(PreviewItem *item); + + void setPlugin(const QString &plugin); + QString plugin() const; + void setTheme(const QString &theme); + QString theme() const; + bool isValid() const; + + KDecoration2::Decoration *createDecoration(QObject *parent = nullptr); + +Q_SIGNALS: + void pluginChanged(); + void themeChanged(); + void validChanged(); + +private: + void createFactory(); + void setValid(bool valid); + PreviewClient *m_lastCreatedClient; + PreviewSettings *m_lastCreatedSettings; + QList m_previewItems; + QString m_plugin; + QString m_theme; + QPointer m_factory; + bool m_valid; +}; + +} +} + +Q_DECLARE_METATYPE(KDecoration2::Preview::PreviewBridge *) + +#endif diff --git a/kcmkwin/kwindecoration/declarative-plugin/previewclient.cpp b/kcmkwin/kwindecoration/declarative-plugin/previewclient.cpp new file mode 100644 index 0000000000..25da62ee17 --- /dev/null +++ b/kcmkwin/kwindecoration/declarative-plugin/previewclient.cpp @@ -0,0 +1,463 @@ +/* + * Copyright 2014 Martin Gräßlin + * + * 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 "previewclient.h" +#include +#include + +#include +#include + +#include +#include + +namespace KDecoration2 +{ +namespace Preview +{ + +PreviewClient::PreviewClient(DecoratedClient *c, Decoration *decoration) + : QObject(decoration) + , DecoratedClientPrivate(c, decoration) + , m_colorSchemeManager(new KColorSchemeManager(this)) + , m_colorSchemeIndex(0) + , m_icon(QIcon::fromTheme(QStringLiteral("start-here-kde"))) + , m_iconName(m_icon.name()) + , m_active(true) + , m_closeable(true) + , m_keepBelow(false) + , m_keepAbove(false) + , m_maximizable(true) + , m_maximizedHorizontally(false) + , m_maximizedVertically(false) + , m_minimizable(true) + , m_modal(false) + , m_movable(true) + , m_resizable(true) + , m_shadeable(true) + , m_shaded(false) + , m_providesContextHelp(false) + , m_desktop(1) + , m_width(0) + , m_height(0) + , m_bordersTopEdge(false) + , m_bordersLeftEdge(false) + , m_bordersRightEdge(false) + , m_bordersBottomEdge(false) +{ + connect(this, &PreviewClient::captionChanged, c, &DecoratedClient::captionChanged); + connect(this, &PreviewClient::activeChanged, c, &DecoratedClient::activeChanged); + connect(this, &PreviewClient::closeableChanged, c, &DecoratedClient::closeableChanged); + connect(this, &PreviewClient::keepAboveChanged, c, &DecoratedClient::keepAboveChanged); + connect(this, &PreviewClient::keepBelowChanged, c, &DecoratedClient::keepBelowChanged); + connect(this, &PreviewClient::maximizableChanged, c, &DecoratedClient::maximizeableChanged); + connect(this, &PreviewClient::maximizedChanged, c, &DecoratedClient::maximizedChanged); + connect(this, &PreviewClient::maximizedVerticallyChanged, c, &DecoratedClient::maximizedVerticallyChanged); + connect(this, &PreviewClient::maximizedHorizontallyChanged, c, &DecoratedClient::maximizedHorizontallyChanged); + connect(this, &PreviewClient::minimizableChanged, c, &DecoratedClient::minimizeableChanged); +// connect(this, &PreviewClient::modalChanged, c, &DecoratedClient::modalChanged); + connect(this, &PreviewClient::movableChanged, c, &DecoratedClient::moveableChanged); + connect(this, &PreviewClient::onAllDesktopsChanged, c, &DecoratedClient::onAllDesktopsChanged); + connect(this, &PreviewClient::resizableChanged, c, &DecoratedClient::resizeableChanged); + connect(this, &PreviewClient::shadeableChanged, c, &DecoratedClient::shadeableChanged); + connect(this, &PreviewClient::shadedChanged, c, &DecoratedClient::shadedChanged); + connect(this, &PreviewClient::providesContextHelpChanged, c, &DecoratedClient::providesContextHelpChanged); + connect(this, &PreviewClient::onAllDesktopsChanged, c, &DecoratedClient::onAllDesktopsChanged); + connect(this, &PreviewClient::widthChanged, c, &DecoratedClient::widthChanged); + connect(this, &PreviewClient::heightChanged, c, &DecoratedClient::heightChanged); + connect(this, &PreviewClient::iconChanged, c, &DecoratedClient::iconChanged); + connect(this, &PreviewClient::paletteChanged, c, &DecoratedClient::paletteChanged); +// connect(this, &PreviewClient::, c, &DecoratedClient::); + connect(this, &PreviewClient::maximizedVerticallyChanged, this, + [this]() { + emit maximizedChanged(isMaximized()); + } + ); + connect(this, &PreviewClient::maximizedHorizontallyChanged, this, + [this]() { + emit maximizedChanged(isMaximized()); + } + ); + connect(this, &PreviewClient::iconNameChanged, this, + [this]() { + m_icon = QIcon::fromTheme(m_iconName); + emit iconChanged(m_icon); + } + ); + connect(this, &PreviewClient::desktopChanged, this, + [this]() { + emit onAllDesktopsChanged(isOnAllDesktops()); + } + ); + connect(this, &PreviewClient::colorSchemeIndexChanged, this, + [this]() { + const QModelIndex index = m_colorSchemeManager->model()->index(m_colorSchemeIndex, 0); + qDebug() << "Scheme: " << index.data(Qt::UserRole).toString(); + m_palette = KColorScheme::createApplicationPalette(KSharedConfig::openConfig(index.data(Qt::UserRole).toString())); + emit paletteChanged(m_palette); + } + ); + connect(decoration, &Decoration::titleBarDoubleClicked, this, + [this]() { + if (!isMaximizeable()) { + return; + } + const bool maximize = !isMaximized(); + setMaximizedHorizontally(maximize); + setMaximizedVertically(maximize); + } + ); + auto emitEdgesChanged = [this, c]() { + c->borderingScreenEdgesChanged(borderingScreenEdges()); + }; + connect(this, &PreviewClient::bordersTopEdgeChanged, this, emitEdgesChanged); + connect(this, &PreviewClient::bordersLeftEdgeChanged, this, emitEdgesChanged); + connect(this, &PreviewClient::bordersRightEdgeChanged, this, emitEdgesChanged); + connect(this, &PreviewClient::bordersBottomEdgeChanged, this, emitEdgesChanged); +} + +PreviewClient::~PreviewClient() = default; + +void PreviewClient::setIcon(const QIcon &pixmap) +{ + m_icon = pixmap; + emit iconChanged(m_icon); +} + +int PreviewClient::width() const +{ + return m_width; +} + +int PreviewClient::height() const +{ + return m_height; +} + +QString PreviewClient::caption() const +{ + return m_caption; +} + +WId PreviewClient::decorationId() const +{ + return 0; +} + +int PreviewClient::desktop() const +{ + return m_desktop; +} + +void PreviewClient::setDesktop(int desktop) +{ + if (desktop == 0) { + desktop = 1; + } + if (m_desktop == desktop) { + return; + } + m_desktop = desktop; + emit desktopChanged(m_desktop); +} + +QIcon PreviewClient::icon() const +{ + return m_icon; +} + +QString PreviewClient::iconName() const +{ + return m_iconName; +} + +bool PreviewClient::isActive() const +{ + return m_active; +} + +bool PreviewClient::isCloseable() const +{ + return m_closeable; +} + +bool PreviewClient::isKeepAbove() const +{ + return m_keepAbove; +} + +bool PreviewClient::isKeepBelow() const +{ + return m_keepBelow; +} + +bool PreviewClient::isMaximizeable() const +{ + return m_maximizable; +} + +bool PreviewClient::isMaximized() const +{ + return isMaximizedHorizontally() && isMaximizedVertically(); +} + +bool PreviewClient::isMaximizedHorizontally() const +{ + return m_maximizedHorizontally; +} + +bool PreviewClient::isMaximizedVertically() const +{ + return m_maximizedVertically; +} + +bool PreviewClient::isMinimizeable() const +{ + return m_minimizable; +} + +bool PreviewClient::isModal() const +{ + return m_modal; +} + +bool PreviewClient::isMoveable() const +{ + return m_movable; +} + +bool PreviewClient::isOnAllDesktops() const +{ + return desktop() == -1; +} + +bool PreviewClient::isResizeable() const +{ + return m_resizable; +} + +bool PreviewClient::isShadeable() const +{ + return m_shadeable; +} + +bool PreviewClient::isShaded() const +{ + return m_shaded; +} + +bool PreviewClient::providesContextHelp() const +{ + return m_providesContextHelp; +} + +WId PreviewClient::windowId() const +{ + return 0; +} + +QPalette PreviewClient::palette() const +{ + return m_palette; +} + +QAbstractItemModel *PreviewClient::colorSchemeModel() const +{ + return m_colorSchemeManager->model(); +} + +int PreviewClient::colorSchemeIndex() const +{ + return m_colorSchemeIndex; +} + +void PreviewClient::setColorSchemeIndex(int index) +{ + if (m_colorSchemeIndex == index) { + return; + } + m_colorSchemeIndex = index; + emit colorSchemeIndexChanged(m_colorSchemeIndex); +} + +Qt::Edges PreviewClient::borderingScreenEdges() const +{ + Qt::Edges edges; + if (m_bordersBottomEdge) { + edges |= Qt::BottomEdge; + } + if (m_bordersLeftEdge) { + edges |= Qt::LeftEdge; + } + if (m_bordersRightEdge) { + edges |= Qt::RightEdge; + } + if (m_bordersTopEdge) { + edges |= Qt::TopEdge; + } + return edges; +} + +bool PreviewClient::bordersBottomEdge() const +{ + return m_bordersBottomEdge; +} + +bool PreviewClient::bordersLeftEdge() const +{ + return m_bordersLeftEdge; +} + +bool PreviewClient::bordersRightEdge() const +{ + return m_bordersRightEdge; +} + +bool PreviewClient::bordersTopEdge() const +{ + return m_bordersTopEdge; +} + +void PreviewClient::setBordersBottomEdge(bool enabled) +{ + if (m_bordersBottomEdge == enabled) { + return; + } + m_bordersBottomEdge = enabled; + emit bordersBottomEdgeChanged(enabled); +} + +void PreviewClient::setBordersLeftEdge(bool enabled) +{ + if (m_bordersLeftEdge == enabled) { + return; + } + m_bordersLeftEdge = enabled; + emit bordersLeftEdgeChanged(enabled); +} + +void PreviewClient::setBordersRightEdge(bool enabled) +{ + if (m_bordersRightEdge == enabled) { + return; + } + m_bordersRightEdge = enabled; + emit bordersRightEdgeChanged(enabled); +} + +void PreviewClient::setBordersTopEdge(bool enabled) +{ + if (m_bordersTopEdge == enabled) { + return; + } + m_bordersTopEdge = enabled; + emit bordersTopEdgeChanged(enabled); +} + +void PreviewClient::requestClose() +{ + emit closeRequested(); +} + +void PreviewClient::requestContextHelp() +{ + qDebug() << "context help requested"; +} + +void PreviewClient::requestMaximize(Qt::MouseButtons buttons) +{ + if (buttons.testFlag(Qt::LeftButton)) { + const bool set = !isMaximized(); + setMaximizedHorizontally(set); + setMaximizedVertically(set); + } else if (buttons.testFlag(Qt::RightButton)) { + setMaximizedHorizontally(!isMaximizedHorizontally()); + } else if (buttons.testFlag(Qt::MiddleButton)) { + setMaximizedVertically(!isMaximizedVertically()); + } +} + +void PreviewClient::requestMinimize() +{ + emit minimizeRequested(); +} + +void PreviewClient::requestToggleKeepAbove() +{ + setKeepAbove(!isKeepAbove()); +} + +void PreviewClient::requestToggleKeepBelow() +{ + setKeepBelow(!isKeepBelow()); +} + +void PreviewClient::requestShowWindowMenu() +{ + emit showWindowMenuRequested(); +} + +void PreviewClient::requestToggleOnAllDesktops() +{ + setDesktop(isOnAllDesktops() ? 1 : -1); +} + +void PreviewClient::requestToggleShade() +{ + setShaded(!isShaded()); +} + +#define SETTER(type, name, variable) \ +void PreviewClient::name(type variable) \ +{ \ + if (m_##variable == variable) { \ + return; \ + } \ + qDebug() << "Setting " << #variable << ":" << variable;\ + m_##variable = variable; \ + emit variable##Changed(m_##variable); \ +} + +#define SETTER2(name, variable) SETTER(bool, name, variable) + +SETTER(const QString &, setCaption, caption) +SETTER(const QString &, setIconName, iconName) +SETTER(int, setWidth, width) +SETTER(int, setHeight, height) + +SETTER2(setActive, active) +SETTER2(setCloseable, closeable) +SETTER2(setMaximizable, maximizable) +SETTER2(setKeepBelow, keepBelow) +SETTER2(setKeepAbove, keepAbove) +SETTER2(setMaximizedHorizontally, maximizedHorizontally) +SETTER2(setMaximizedVertically, maximizedVertically) +SETTER2(setMinimizable, minimizable) +SETTER2(setModal, modal) +SETTER2(setMovable, movable) +SETTER2(setResizable, resizable) +SETTER2(setShadeable, shadeable) +SETTER2(setShaded, shaded) +SETTER2(setProvidesContextHelp, providesContextHelp) + +#undef SETTER2 +#undef SETTER + +} // namespace Preview +} // namespace KDecoration2 diff --git a/kcmkwin/kwindecoration/declarative-plugin/previewclient.h b/kcmkwin/kwindecoration/declarative-plugin/previewclient.h new file mode 100644 index 0000000000..dfd52817c2 --- /dev/null +++ b/kcmkwin/kwindecoration/declarative-plugin/previewclient.h @@ -0,0 +1,212 @@ +/* + * Copyright 2014 Martin Gräßlin + * + * 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 KDECOARTIONS_PREVIEW_CLIENT_H +#define KDECOARTIONS_PREVIEW_CLIENT_H + +#include +#include +#include + +class KColorSchemeManager; +class QAbstractItemModel; + +namespace KDecoration2 +{ +namespace Preview +{ +class PreviewClient : public QObject, public DecoratedClientPrivate +{ + Q_OBJECT + Q_PROPERTY(KDecoration2::Decoration *decoration READ decoration CONSTANT) + Q_PROPERTY(QString caption READ caption WRITE setCaption NOTIFY captionChanged) + Q_PROPERTY(QIcon icon READ icon WRITE setIcon NOTIFY iconChanged) + Q_PROPERTY(QString iconName READ iconName WRITE setIconName NOTIFY iconNameChanged) + Q_PROPERTY(QAbstractItemModel *colorSchemeModel READ colorSchemeModel CONSTANT) + Q_PROPERTY(int colorSchemeIndex READ colorSchemeIndex WRITE setColorSchemeIndex NOTIFY colorSchemeIndexChanged) + Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged) + Q_PROPERTY(bool closeable READ isCloseable WRITE setCloseable NOTIFY closeableChanged) + Q_PROPERTY(bool keepAbove READ isKeepAbove WRITE setKeepAbove NOTIFY keepAboveChanged) + Q_PROPERTY(bool keepBelow READ isKeepBelow WRITE setKeepBelow NOTIFY keepBelowChanged) + Q_PROPERTY(bool maximizable READ isMaximizeable WRITE setMaximizable NOTIFY maximizableChanged) + Q_PROPERTY(bool maximized READ isMaximized NOTIFY maximizedChanged) + Q_PROPERTY(bool maximizedVertically READ isMaximizedVertically WRITE setMaximizedVertically NOTIFY maximizedVerticallyChanged) + Q_PROPERTY(bool maximizedHorizontally READ isMaximizedHorizontally WRITE setMaximizedHorizontally NOTIFY maximizedHorizontallyChanged) + Q_PROPERTY(bool minimizable READ isMinimizeable WRITE setMinimizable NOTIFY minimizableChanged) + Q_PROPERTY(bool modal READ isModal WRITE setModal NOTIFY modalChanged) + Q_PROPERTY(bool movable READ isMoveable WRITE setMovable NOTIFY movableChanged) + Q_PROPERTY(int desktop READ desktop WRITE setDesktop NOTIFY desktopChanged) + Q_PROPERTY(bool onAllDesktops READ isOnAllDesktops NOTIFY onAllDesktopsChanged) + Q_PROPERTY(bool resizable READ isResizeable WRITE setResizable NOTIFY resizableChanged) + Q_PROPERTY(bool shadeable READ isShadeable WRITE setShadeable NOTIFY shadeableChanged) + Q_PROPERTY(bool shaded READ isShaded WRITE setShaded NOTIFY shadedChanged) + Q_PROPERTY(bool providesContextHelp READ providesContextHelp WRITE setProvidesContextHelp NOTIFY providesContextHelpChanged) + Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged) + Q_PROPERTY(int height READ height WRITE setHeight NOTIFY heightChanged) + Q_PROPERTY(bool bordersTopEdge READ bordersTopEdge WRITE setBordersTopEdge NOTIFY bordersTopEdgeChanged) + Q_PROPERTY(bool bordersLeftEdge READ bordersLeftEdge WRITE setBordersLeftEdge NOTIFY bordersLeftEdgeChanged) + Q_PROPERTY(bool bordersRightEdge READ bordersRightEdge WRITE setBordersRightEdge NOTIFY bordersRightEdgeChanged) + Q_PROPERTY(bool bordersBottomEdge READ bordersBottomEdge WRITE setBordersBottomEdge NOTIFY bordersBottomEdgeChanged) +public: + explicit PreviewClient(DecoratedClient *client, Decoration *decoration); + virtual ~PreviewClient(); + + QString caption() const override; + WId decorationId() const override; + WId windowId() const override; + int desktop() const override; + QIcon icon() const override; + bool isActive() const override; + bool isCloseable() const override; + bool isKeepAbove() const override; + bool isKeepBelow() const override; + bool isMaximizeable() const override; + bool isMaximized() const override; + bool isMaximizedVertically() const override; + bool isMaximizedHorizontally() const override; + bool isMinimizeable() const override; + bool isModal() const override; + bool isMoveable() const override; + bool isOnAllDesktops() const override; + bool isResizeable() const override; + bool isShadeable() const override; + bool isShaded() const override; + bool providesContextHelp() const override; + + int width() const override; + int height() const override; + QPalette palette() const override; + Qt::Edges borderingScreenEdges() const override; + + void requestClose() override; + void requestContextHelp() override; + void requestMaximize(Qt::MouseButtons buttons) override; + void requestMinimize() override; + void requestToggleKeepAbove() override; + void requestToggleKeepBelow() override; + void requestToggleShade() override; + void requestShowWindowMenu() override; + void requestToggleOnAllDesktops() override; + + void setCaption(const QString &caption); + void setActive(bool active); + void setCloseable(bool closeable); + void setMaximizable(bool maximizable); + void setKeepBelow(bool keepBelow); + void setKeepAbove(bool keepAbove); + void setMaximizedHorizontally(bool maximized); + void setMaximizedVertically(bool maximized); + void setMinimizable(bool minimizable); + void setModal(bool modal); + void setMovable(bool movable); + void setResizable(bool resizable); + void setShadeable(bool shadeable); + void setShaded(bool shaded); + void setProvidesContextHelp(bool contextHelp); + void setDesktop(int desktop); + + void setWidth(int width); + void setHeight(int height); + + QString iconName() const; + void setIconName(const QString &icon); + void setIcon(const QIcon &icon); + + QAbstractItemModel *colorSchemeModel() const; + int colorSchemeIndex() const; + void setColorSchemeIndex(int index); + + bool bordersTopEdge() const; + bool bordersLeftEdge() const; + bool bordersRightEdge() const; + bool bordersBottomEdge() const; + + void setBordersTopEdge(bool enabled); + void setBordersLeftEdge(bool enabled); + void setBordersRightEdge(bool enabled); + void setBordersBottomEdge(bool enabled); + +Q_SIGNALS: + void captionChanged(const QString &); + void iconChanged(const QIcon &); + void iconNameChanged(const QString &); + void activeChanged(bool); + void closeableChanged(bool); + void keepAboveChanged(bool); + void keepBelowChanged(bool); + void maximizableChanged(bool); + void maximizedChanged(bool); + void maximizedVerticallyChanged(bool); + void maximizedHorizontallyChanged(bool); + void minimizableChanged(bool); + void modalChanged(bool); + void movableChanged(bool); + void onAllDesktopsChanged(bool); + void resizableChanged(bool); + void shadeableChanged(bool); + void shadedChanged(bool); + void providesContextHelpChanged(bool); + void desktopChanged(int); + void widthChanged(int); + void heightChanged(int); + void colorSchemeIndexChanged(int); + void paletteChanged(const QPalette&); + void bordersTopEdgeChanged(bool); + void bordersLeftEdgeChanged(bool); + void bordersRightEdgeChanged(bool); + void bordersBottomEdgeChanged(bool); + + void showWindowMenuRequested(); + void minimizeRequested(); + void closeRequested(); + +private: + KColorSchemeManager *m_colorSchemeManager; + int m_colorSchemeIndex; + QString m_caption; + QIcon m_icon; + QString m_iconName; + QPalette m_palette; + bool m_active; + bool m_closeable; + bool m_keepBelow; + bool m_keepAbove; + bool m_maximizable; + bool m_maximizedHorizontally; + bool m_maximizedVertically; + bool m_minimizable; + bool m_modal; + bool m_movable; + bool m_resizable; + bool m_shadeable; + bool m_shaded; + bool m_providesContextHelp; + int m_desktop; + int m_width; + int m_height; + bool m_bordersTopEdge; + bool m_bordersLeftEdge; + bool m_bordersRightEdge; + bool m_bordersBottomEdge; +}; + +} // namespace Preview +} // namespace KDecoration2 + +#endif diff --git a/kcmkwin/kwindecoration/declarative-plugin/previewitem.cpp b/kcmkwin/kwindecoration/declarative-plugin/previewitem.cpp new file mode 100644 index 0000000000..105031a9b1 --- /dev/null +++ b/kcmkwin/kwindecoration/declarative-plugin/previewitem.cpp @@ -0,0 +1,374 @@ +/* + * Copyright 2014 Martin Gräßlin + * + * 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 "previewitem.h" +#include "previewbridge.h" +#include "previewsettings.h" +#include "previewclient.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace KDecoration2 +{ +namespace Preview +{ + +PreviewItem::PreviewItem(QQuickItem *parent) + : QQuickPaintedItem(parent) + , m_decoration(nullptr) + , m_windowColor(QPalette().background().color()) +{ + setAcceptHoverEvents(true); + setFiltersChildMouseEvents(true); + setAcceptedMouseButtons(Qt::MouseButtons(~Qt::NoButton)); + connect(this, &PreviewItem::widthChanged, this, &PreviewItem::syncSize); + connect(this, &PreviewItem::heightChanged, this, &PreviewItem::syncSize); + connect(this, &PreviewItem::bridgeChanged, this, &PreviewItem::createDecoration); + connect(this, &PreviewItem::settingsChanged, this, &PreviewItem::createDecoration); +} + +PreviewItem::~PreviewItem() +{ + if (m_bridge){ + m_bridge->unregisterPreviewItem(this); + } +} + +void PreviewItem::componentComplete() +{ + QQuickPaintedItem::componentComplete(); + createDecoration(); + if (m_decoration) { + m_decoration->setSettings(m_settings->settings()); + m_decoration->init(); + syncSize(); + } +} + +void PreviewItem::createDecoration() +{ + if (m_bridge.isNull() || m_settings.isNull() || m_decoration) { + return; + } + m_decoration = m_bridge->createDecoration(this); + if (!m_decoration) { + return; + } + m_decoration->setProperty("visualParent", QVariant::fromValue(this)); + m_client = m_bridge->lastCreatedClient(); + connect(m_decoration, &Decoration::bordersChanged, this, &PreviewItem::syncSize); + connect(m_decoration, &Decoration::shadowChanged, this, &PreviewItem::syncSize); + emit decorationChanged(m_decoration); +} + +Decoration *PreviewItem::decoration() const +{ + return m_decoration; +} + +void PreviewItem::setDecoration(Decoration *deco) +{ + if (m_decoration == deco) { + return; + } + auto updateSlot = static_cast(&QQuickItem::update); + if (m_decoration) { + disconnect(m_decoration, &Decoration::bordersChanged, this, updateSlot); + } + m_decoration = deco; + m_decoration->setProperty("visualParent", QVariant::fromValue(this)); + connect(m_decoration, &Decoration::bordersChanged, this, updateSlot); + connect(m_decoration, &Decoration::windowFrameSectionChanged, this, + [this](Qt::WindowFrameSection section) { + switch (section) { + case Qt::TopRightSection: + case Qt::BottomLeftSection: + setCursor(Qt::SizeBDiagCursor); + return; + case Qt::TopLeftSection: + case Qt::BottomRightSection: + setCursor(Qt::SizeFDiagCursor); + return; + case Qt::TopSection: + case Qt::BottomSection: + setCursor(Qt::SizeVerCursor); + return; + case Qt::LeftSection: + case Qt::RightSection: + setCursor(Qt::SizeHorCursor); + return; + default: + setCursor(Qt::ArrowCursor); + } + } + ); + emit decorationChanged(m_decoration); +} + +QColor PreviewItem::windowColor() const +{ + return m_windowColor; +} + +void PreviewItem::setWindowColor(const QColor &color) +{ + if (m_windowColor == color) { + return; + } + m_windowColor = color; + emit windowColorChanged(m_windowColor); + update(); +} + +void PreviewItem::paint(QPainter *painter) +{ + if (!m_decoration) { + return; + } + int paddingLeft = 0; + int paddingTop = 0; + int paddingRight = 0; + int paddingBottom = 0; + paintShadow(painter, paddingLeft, paddingRight, paddingTop, paddingBottom); + m_decoration->paint(painter); + if (m_drawBackground) { + painter->fillRect(m_decoration->borderLeft(), m_decoration->borderTop(), + width() - m_decoration->borderLeft() - m_decoration->borderRight() - paddingLeft - paddingRight, + height() - m_decoration->borderTop() - m_decoration->borderBottom() - paddingTop - paddingBottom, + m_windowColor); + } +} + +void PreviewItem::paintShadow(QPainter *painter, int &paddingLeft, int &paddingRight, int &paddingTop, int &paddingBottom) +{ + const DecorationShadow *shadow = ((const Decoration*)(m_decoration))->shadow(); + if (!shadow) { + return; + } + paddingLeft = shadow->paddingLeft(); + paddingTop = shadow->paddingTop(); + paddingRight = shadow->paddingRight(); + paddingBottom = shadow->paddingBottom(); + const QImage img = shadow->shadow(); + if (img.isNull()) { + return; + } + const QRect topLeft = QRect(QPoint(0, 0), shadow->topLeft()); + const QRect top = QRect(QPoint(topLeft.width(), 0), shadow->top()); + const QRect topRight = QRect(QPoint(topLeft.width() + top.width(), 0), shadow->topRight()); + const QRect right = QRect(QPoint(topLeft.width() + top.width(), topRight.height()), shadow->right()); + const QRect left = QRect(QPoint(0, topLeft.height()), shadow->left()); + const QRect bottomLeft = QRect(QPoint(0, topLeft.height() + left.height()), shadow->bottomLeft()); + const QRect bottom = QRect(QPoint(bottomLeft.width(), img.height() - shadow->bottom().height()), shadow->bottom()); + const QRect bottomRight = QRect(QPoint(bottomLeft.width() + bottom.width(), topRight.height() + right.height()), shadow->bottomRight()); + + painter->translate(paddingLeft, paddingTop); + + // top left + painter->drawImage(QPoint(-paddingLeft, -paddingTop), img, topLeft); + // top + painter->drawImage(QRect(-paddingLeft + topLeft.width(), -paddingTop, width() - topLeft.width() - topRight.width(), top.height()), img, top); + // top right + painter->drawImage(QPoint(width() - topRight.width() - paddingLeft, -paddingTop), img, topRight); + // right + painter->drawImage(QRect(width() - right.width() - paddingLeft, -paddingTop + topRight.height(), right.width(), height() - topRight.height() - bottomRight.height()), img, right); + // bottom right + painter->drawImage(QPoint(width() - paddingLeft - bottomRight.width(), height() - paddingTop - bottomRight.height()), img, bottomRight); + // bottom + painter->drawImage(QRect(-paddingLeft + bottomLeft.width(), height() - bottom.height() - paddingTop, width() - bottomLeft.width() - bottomRight.width(), bottom.height()), img, bottom); + // bottom left + painter->drawImage(QPoint(-paddingLeft, height() - bottomLeft.height() - paddingTop), img, bottomLeft); + // left + painter->drawImage(QRect(-paddingLeft, -paddingTop + topLeft.height(), left.width(), height() - topLeft.height() - bottomLeft.height()), img, left); +} + +void PreviewItem::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (const DecorationShadow *shadow = ((const Decoration*)(m_decoration))->shadow()) { + QMouseEvent e(event->type(), + event->localPos() - QPointF(shadow->paddingLeft(), shadow->paddingTop()), + event->button(), + event->buttons(), + event->modifiers()); + QCoreApplication::instance()->sendEvent(decoration(), &e); + } else { + QCoreApplication::instance()->sendEvent(decoration(), event); + } +} + +void PreviewItem::mousePressEvent(QMouseEvent *event) +{ + if (const DecorationShadow *shadow = ((const Decoration*)(m_decoration))->shadow()) { + QMouseEvent e(event->type(), + event->localPos() - QPointF(shadow->paddingLeft(), shadow->paddingTop()), + event->button(), + event->buttons(), + event->modifiers()); + QCoreApplication::instance()->sendEvent(decoration(), &e); + } else { + QCoreApplication::instance()->sendEvent(decoration(), event); + } +} + +void PreviewItem::mouseReleaseEvent(QMouseEvent *event) +{ + if (const DecorationShadow *shadow = ((const Decoration*)(m_decoration))->shadow()) { + QMouseEvent e(event->type(), + event->localPos() - QPointF(shadow->paddingLeft(), shadow->paddingTop()), + event->button(), + event->buttons(), + event->modifiers()); + QCoreApplication::instance()->sendEvent(decoration(), &e); + } else { + QCoreApplication::instance()->sendEvent(decoration(), event); + } +} + +void PreviewItem::mouseMoveEvent(QMouseEvent *event) +{ + if (const DecorationShadow *shadow = ((const Decoration*)(m_decoration))->shadow()) { + QMouseEvent e(event->type(), + event->localPos() - QPointF(shadow->paddingLeft(), shadow->paddingTop()), + event->button(), + event->buttons(), + event->modifiers()); + QCoreApplication::instance()->sendEvent(decoration(), &e); + } else { + QCoreApplication::instance()->sendEvent(decoration(), event); + } +} + +void PreviewItem::hoverEnterEvent(QHoverEvent *event) +{ + if (const DecorationShadow *shadow = ((const Decoration*)(m_decoration))->shadow()) { + QHoverEvent e(event->type(), + event->posF() - QPointF(shadow->paddingLeft(), shadow->paddingTop()), + event->oldPosF() - QPointF(shadow->paddingLeft(), shadow->paddingTop()), + event->modifiers()); + QCoreApplication::instance()->sendEvent(decoration(), &e); + } else { + QCoreApplication::instance()->sendEvent(decoration(), event); + } +} + +void PreviewItem::hoverLeaveEvent(QHoverEvent *event) +{ + if (const DecorationShadow *shadow = ((const Decoration*)(m_decoration))->shadow()) { + QHoverEvent e(event->type(), + event->posF() - QPointF(shadow->paddingLeft(), shadow->paddingTop()), + event->oldPosF() - QPointF(shadow->paddingLeft(), shadow->paddingTop()), + event->modifiers()); + QCoreApplication::instance()->sendEvent(decoration(), &e); + } else { + QCoreApplication::instance()->sendEvent(decoration(), event); + } +} + +void PreviewItem::hoverMoveEvent(QHoverEvent *event) +{ + if (const DecorationShadow *shadow = ((const Decoration*)(m_decoration))->shadow()) { + QHoverEvent e(event->type(), + event->posF() - QPointF(shadow->paddingLeft(), shadow->paddingTop()), + event->oldPosF() - QPointF(shadow->paddingLeft(), shadow->paddingTop()), + event->modifiers()); + QCoreApplication::instance()->sendEvent(decoration(), &e); + } else { + QCoreApplication::instance()->sendEvent(decoration(), event); + } +} + +bool PreviewItem::isDrawingBackground() const +{ + return m_drawBackground; +} + +void PreviewItem::setDrawingBackground(bool set) +{ + if (m_drawBackground == set) { + return; + } + m_drawBackground = set; + emit drawingBackgroundChanged(set); +} + +PreviewBridge *PreviewItem::bridge() const +{ + return m_bridge.data(); +} + +void PreviewItem::setBridge(PreviewBridge *bridge) +{ + if (m_bridge == bridge) { + return; + } + if (m_bridge) { + m_bridge->unregisterPreviewItem(this); + } + m_bridge = bridge; + if (m_bridge) { + m_bridge->registerPreviewItem(this); + } + emit bridgeChanged(); +} + +Settings *PreviewItem::settings() const +{ + return m_settings.data(); +} + +void PreviewItem::setSettings(Settings *settings) +{ + if (m_settings == settings) { + return; + } + m_settings = settings; + emit settingsChanged(); +} + +PreviewClient *PreviewItem::client() +{ + return m_client.data(); +} + +void PreviewItem::syncSize() +{ + if (!m_client) { + return; + } + int widthOffset = 0; + int heightOffset = 0; + auto shadow = m_decoration->shadow(); + if (shadow) { + widthOffset = shadow->paddingLeft() + shadow->paddingRight(); + heightOffset = shadow->paddingTop() + shadow->paddingBottom(); + } + m_client->setWidth(width() - m_decoration->borderLeft() - m_decoration->borderRight() - widthOffset); + m_client->setHeight(height() - m_decoration->borderTop() - m_decoration->borderBottom() - heightOffset); +} + +} +} diff --git a/kcmkwin/kwindecoration/declarative-plugin/previewitem.h b/kcmkwin/kwindecoration/declarative-plugin/previewitem.h new file mode 100644 index 0000000000..c210314956 --- /dev/null +++ b/kcmkwin/kwindecoration/declarative-plugin/previewitem.h @@ -0,0 +1,100 @@ +/* + * Copyright 2014 Martin Gräßlin + * + * 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 KDECOARTIONS_PREVIEW_ITEM_H +#define KDECOARTIONS_PREVIEW_ITEM_H + +#include +#include + +namespace KDecoration2 +{ +class Decoration; +class DecorationSettings; + +namespace Preview +{ +class PreviewBridge; +class PreviewClient; +class Settings; + +class PreviewItem : public QQuickPaintedItem +{ + Q_OBJECT + Q_PROPERTY(KDecoration2::Decoration *decoration READ decoration NOTIFY decorationChanged) + Q_PROPERTY(KDecoration2::Preview::PreviewBridge *bridge READ bridge WRITE setBridge NOTIFY bridgeChanged) + Q_PROPERTY(KDecoration2::Preview::Settings *settings READ settings WRITE setSettings NOTIFY settingsChanged) + Q_PROPERTY(KDecoration2::Preview::PreviewClient *client READ client) + Q_PROPERTY(QColor windowColor READ windowColor WRITE setWindowColor NOTIFY windowColorChanged) + Q_PROPERTY(bool drawBackground READ isDrawingBackground WRITE setDrawingBackground NOTIFY drawingBackgroundChanged) +public: + PreviewItem(QQuickItem *parent = nullptr); + virtual ~PreviewItem(); + void paint(QPainter *painter); + + KDecoration2::Decoration *decoration() const; + void setDecoration(KDecoration2::Decoration *deco); + + QColor windowColor() const; + void setWindowColor(const QColor &color); + + bool isDrawingBackground() const; + void setDrawingBackground(bool set); + + PreviewBridge *bridge() const; + void setBridge(PreviewBridge *bridge); + + Settings *settings() const; + void setSettings(Settings *settings); + + PreviewClient *client(); + +Q_SIGNALS: + void decorationChanged(KDecoration2::Decoration *deco); + void windowColorChanged(const QColor &color); + void drawingBackgroundChanged(bool); + void bridgeChanged(); + void settingsChanged(); + +protected: + void mouseDoubleClickEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void hoverEnterEvent(QHoverEvent *event) override; + void hoverLeaveEvent(QHoverEvent *event) override; + void hoverMoveEvent(QHoverEvent *event) override; + void componentComplete() override; + +private: + void paintShadow(QPainter *painter, int &paddingLeft, int &paddingRight, int &paddingTop, int &paddingBottom); + void syncSize(); + void createDecoration(); + Decoration *m_decoration; + QColor m_windowColor; + bool m_drawBackground = true; + QPointer m_bridge; + QPointer m_settings; + QPointer m_client; +}; + +} // Preview +} // KDecoration2 + +#endif diff --git a/kcmkwin/kwindecoration/declarative-plugin/previewsettings.cpp b/kcmkwin/kwindecoration/declarative-plugin/previewsettings.cpp new file mode 100644 index 0000000000..1db0971f81 --- /dev/null +++ b/kcmkwin/kwindecoration/declarative-plugin/previewsettings.cpp @@ -0,0 +1,325 @@ +/* + * Copyright 2014 Martin Gräßlin + * + * 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 "previewsettings.h" +#include "previewbridge.h" + +#include + +namespace KDecoration2 +{ + +namespace Preview +{ + +ButtonsModel::ButtonsModel(const QList< DecorationButtonType > &buttons, QObject *parent) + : QAbstractListModel(parent) + , m_buttons(buttons) +{ +} + +ButtonsModel::~ButtonsModel() = default; + +int ButtonsModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } + return m_buttons.count(); +} + +QVariant ButtonsModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || + index.row() < 0 || + index.row() >= m_buttons.count() || + index.column() != 0) { + return QVariant(); + } + switch (role) { + case Qt::DisplayRole: + return QVariant::fromValue(m_buttons.at(index.row())); + case Qt::UserRole: + return QVariant::fromValue(m_buttons.at(index.row())); + } + return QVariant(); +} + +QHash< int, QByteArray > ButtonsModel::roleNames() const +{ + QHash roles; + roles.insert(Qt::DisplayRole, QByteArrayLiteral("display")); + return roles; +} + +void ButtonsModel::remove(int row) +{ + if (row < 0 || row >= m_buttons.count()) { + return; + } + beginRemoveRows(QModelIndex(), row, row); + m_buttons.removeAt(row); + endRemoveRows(); +} + +void ButtonsModel::down(int index) +{ + if (m_buttons.count() < 2 || index == m_buttons.count() -1) { + return; + } + beginMoveRows(QModelIndex(), index, index, QModelIndex(), index + 2); + m_buttons.move(index, index + 1); + endMoveRows(); +} + +void ButtonsModel::up(int index) +{ + if (m_buttons.count() < 2 || index == 0) { + return; + } + beginMoveRows(QModelIndex(), index, index, QModelIndex(), index -1); + m_buttons.move(index, index - 1); + endMoveRows(); +} + +void ButtonsModel::add(DecorationButtonType type) +{ + beginInsertRows(QModelIndex(), m_buttons.count(), m_buttons.count()); + m_buttons.append(type); + endInsertRows(); +} + +BorderSizesModel::BorderSizesModel(QObject *parent) + : QAbstractListModel(parent) +{ +} + +BorderSizesModel::~BorderSizesModel() = default; + +QVariant BorderSizesModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() < 0 || index.row() >= m_borders.count() || index.column() != 0) { + return QVariant(); + } + if (role != Qt::DisplayRole && role != Qt::UserRole) { + return QVariant(); + } + return QVariant::fromValue(m_borders.at(index.row())); +} + +int BorderSizesModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } + return m_borders.count(); +} + +QHash< int, QByteArray > BorderSizesModel::roleNames() const +{ + QHash roles; + roles.insert(Qt::DisplayRole, QByteArrayLiteral("display")); + return roles; +} + +PreviewSettings::PreviewSettings(DecorationSettings *parent) + : QObject() + , DecorationSettingsPrivate(parent) + , m_alphaChannelSupported(true) + , m_onAllDesktopsAvailable(true) + , m_closeOnDoubleClick(false) + , m_leftButtons(new ButtonsModel(QList({ + DecorationButtonType::Menu, + DecorationButtonType::OnAllDesktops + }), this)) + , m_rightButtons(new ButtonsModel(QList({ + DecorationButtonType::QuickHelp, + DecorationButtonType::Minimize, + DecorationButtonType::Maximize, + DecorationButtonType::Close + }), this)) + , m_availableButtons(new ButtonsModel(QList({ + DecorationButtonType::Menu, + DecorationButtonType::ApplicationMenu, + DecorationButtonType::OnAllDesktops, + DecorationButtonType::Minimize, + DecorationButtonType::Maximize, + DecorationButtonType::Close, + DecorationButtonType::QuickHelp, + DecorationButtonType::Shade, + DecorationButtonType::KeepBelow, + DecorationButtonType::KeepAbove + }), this)) + , m_borderSizes(new BorderSizesModel(this)) + , m_borderSize(int(BorderSize::Normal)) + , m_font(QFontDatabase::systemFont(QFontDatabase::TitleFont)) +{ + connect(this, &PreviewSettings::alphaChannelSupportedChanged, parent, &DecorationSettings::alphaChannelSupportedChanged); + connect(this, &PreviewSettings::onAllDesktopsAvailableChanged, parent, &DecorationSettings::onAllDesktopsAvailableChanged); + connect(this, &PreviewSettings::closeOnDoubleClickOnMenuChanged, parent, &DecorationSettings::closeOnDoubleClickOnMenuChanged); + connect(this, &PreviewSettings::fontChanged, parent, &DecorationSettings::fontChanged); + auto updateLeft = [this, parent]() { + parent->decorationButtonsLeftChanged(decorationButtonsLeft()); + }; + auto updateRight = [this, parent]() { + parent->decorationButtonsRightChanged(decorationButtonsRight()); + }; + connect(m_leftButtons, &QAbstractItemModel::rowsRemoved, this, updateLeft); + connect(m_leftButtons, &QAbstractItemModel::rowsMoved, this, updateLeft); + connect(m_leftButtons, &QAbstractItemModel::rowsInserted, this, updateLeft); + connect(m_rightButtons, &QAbstractItemModel::rowsRemoved, this, updateRight); + connect(m_rightButtons, &QAbstractItemModel::rowsMoved, this, updateRight); + connect(m_rightButtons, &QAbstractItemModel::rowsInserted, this, updateRight); +} + +PreviewSettings::~PreviewSettings() = default; + +bool PreviewSettings::isAlphaChannelSupported() const +{ + return m_alphaChannelSupported; +} + +bool PreviewSettings::isOnAllDesktopsAvailable() const +{ + return m_onAllDesktopsAvailable; +} + +void PreviewSettings::setAlphaChannelSupported(bool supported) +{ + if (m_alphaChannelSupported == supported) { + return; + } + m_alphaChannelSupported = supported; + emit alphaChannelSupportedChanged(m_alphaChannelSupported); +} + +void PreviewSettings::setOnAllDesktopsAvailable(bool available) +{ + if (m_onAllDesktopsAvailable == available) { + return; + } + m_onAllDesktopsAvailable = available; + emit onAllDesktopsAvailableChanged(m_onAllDesktopsAvailable); +} + +void PreviewSettings::setCloseOnDoubleClickOnMenu(bool enabled) +{ + if (m_closeOnDoubleClick == enabled) { + return; + } + m_closeOnDoubleClick = enabled; + emit closeOnDoubleClickOnMenuChanged(enabled); +} + +QList< DecorationButtonType > PreviewSettings::decorationButtonsLeft() const +{ + return m_leftButtons->buttons(); +} + +QList< DecorationButtonType > PreviewSettings::decorationButtonsRight() const +{ + return m_rightButtons->buttons(); +} + +void PreviewSettings::addButtonToLeft(int row) +{ + QModelIndex index = m_availableButtons->index(row); + if (!index.isValid()) { + return; + } + m_leftButtons->add(index.data(Qt::UserRole).value()); +} + +void PreviewSettings::addButtonToRight(int row) +{ + QModelIndex index = m_availableButtons->index(row); + if (!index.isValid()) { + return; + } + m_rightButtons->add(index.data(Qt::UserRole).value()); +} + +void PreviewSettings::setBorderSizesIndex(int index) +{ + if (m_borderSize == index) { + return; + } + m_borderSize = index; + emit borderSizesIndexChanged(index); + emit decorationSettings()->borderSizeChanged(borderSize()); +} + +BorderSize PreviewSettings::borderSize() const +{ + return m_borderSizes->index(m_borderSize).data(Qt::UserRole).value(); +} + +void PreviewSettings::setFont(const QFont &font) +{ + if (m_font == font) { + return; + } + m_font = font; + emit fontChanged(m_font); +} + +Settings::Settings(QObject *parent) + : QObject(parent) +{ + connect(this, &Settings::bridgeChanged, this, &Settings::createSettings); +} + +Settings::~Settings() = default; + +void Settings::setBridge(PreviewBridge *bridge) +{ + if (m_bridge == bridge) { + return; + } + m_bridge = bridge; + emit bridgeChanged(); +} + +PreviewBridge *Settings::bridge() const +{ + return m_bridge.data(); +} + +void Settings::createSettings() +{ + if (m_bridge.isNull()) { + m_settings.clear(); + } else { + m_settings = QSharedPointer::create(m_bridge.data()); + } + emit settingsChanged(); +} + +QSharedPointer Settings::settings() const +{ + return m_settings; +} + +DecorationSettings *Settings::settingsPointer() const +{ + return m_settings.data(); +} + +} +} diff --git a/kcmkwin/kwindecoration/declarative-plugin/previewsettings.h b/kcmkwin/kwindecoration/declarative-plugin/previewsettings.h new file mode 100644 index 0000000000..1b5a43c254 --- /dev/null +++ b/kcmkwin/kwindecoration/declarative-plugin/previewsettings.h @@ -0,0 +1,184 @@ +/* + * Copyright 2014 Martin Gräßlin + * + * 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 KDECOARTIONS_PREVIEW_SETTINGS_H +#define KDECOARTIONS_PREVIEW_SETTINGS_H + +#include +#include +#include +#include + +namespace KDecoration2 +{ + +namespace Preview +{ +class PreviewBridge; + +class ButtonsModel : public QAbstractListModel +{ + Q_OBJECT +public: + explicit ButtonsModel(const QList< DecorationButtonType > &buttons, QObject *parent = 0); + virtual ~ButtonsModel(); + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QHash< int, QByteArray > roleNames() const override; + + QList< DecorationButtonType > buttons() const { + return m_buttons; + } + + Q_INVOKABLE void remove(int index); + Q_INVOKABLE void up(int index); + Q_INVOKABLE void down(int index); + + void add(DecorationButtonType type); + +private: + QList< DecorationButtonType > m_buttons; +}; + +class BorderSizesModel : public QAbstractListModel +{ + Q_OBJECT +public: + explicit BorderSizesModel(QObject *parent = 0); + virtual ~BorderSizesModel(); + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QHash< int, QByteArray > roleNames() const override; +private: + QList m_borders = QList({ + BorderSize::None, + BorderSize::NoSides, + BorderSize::Tiny, + BorderSize::Normal, + BorderSize::Large, + BorderSize::VeryLarge, + BorderSize::Huge, + BorderSize::VeryHuge, + BorderSize::Oversized + }); +}; + +class PreviewSettings : public QObject, public DecorationSettingsPrivate +{ + Q_OBJECT + Q_PROPERTY(bool onAllDesktopsAvailable READ isOnAllDesktopsAvailable WRITE setOnAllDesktopsAvailable NOTIFY onAllDesktopsAvailableChanged) + Q_PROPERTY(bool alphaChannelSupported READ isAlphaChannelSupported WRITE setAlphaChannelSupported NOTIFY alphaChannelSupportedChanged) + Q_PROPERTY(bool closeOnDoubleClickOnMenu READ isCloseOnDoubleClickOnMenu WRITE setCloseOnDoubleClickOnMenu NOTIFY closeOnDoubleClickOnMenuChanged) + Q_PROPERTY(QAbstractItemModel *leftButtonsModel READ leftButtonsModel CONSTANT) + Q_PROPERTY(QAbstractItemModel *rightButtonsModel READ rightButtonsModel CONSTANT) + Q_PROPERTY(QAbstractItemModel *availableButtonsModel READ availableButtonsModel CONSTANT) + Q_PROPERTY(QAbstractItemModel *borderSizesModel READ borderSizesModel CONSTANT) + Q_PROPERTY(int borderSizesIndex READ borderSizesIndex WRITE setBorderSizesIndex NOTIFY borderSizesIndexChanged) + Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged) +public: + explicit PreviewSettings(DecorationSettings *parent); + virtual ~PreviewSettings(); + bool isAlphaChannelSupported() const override; + bool isOnAllDesktopsAvailable() const override; + bool isCloseOnDoubleClickOnMenu() const override { + return m_closeOnDoubleClick; + } + BorderSize borderSize() const override; + + void setOnAllDesktopsAvailable(bool available); + void setAlphaChannelSupported(bool supported); + void setCloseOnDoubleClickOnMenu(bool enabled); + + QAbstractItemModel *leftButtonsModel() const { + return m_leftButtons; + } + QAbstractItemModel *rightButtonsModel() const { + return m_rightButtons; + } + QAbstractItemModel *availableButtonsModel() const { + return m_availableButtons; + } + QAbstractItemModel *borderSizesModel() const { + return m_borderSizes; + } + + QList< DecorationButtonType > decorationButtonsLeft() const override; + QList< DecorationButtonType > decorationButtonsRight() const override; + + Q_INVOKABLE void addButtonToLeft(int row); + Q_INVOKABLE void addButtonToRight(int row); + + int borderSizesIndex() const { + return m_borderSize; + } + void setBorderSizesIndex(int index); + + QFont font() const { + return m_font; + } + void setFont(const QFont &font); + +Q_SIGNALS: + void onAllDesktopsAvailableChanged(bool); + void alphaChannelSupportedChanged(bool); + void closeOnDoubleClickOnMenuChanged(bool); + void borderSizesIndexChanged(int); + void fontChanged(const QFont &); + +private: + bool m_alphaChannelSupported; + bool m_onAllDesktopsAvailable; + bool m_closeOnDoubleClick; + ButtonsModel *m_leftButtons; + ButtonsModel *m_rightButtons; + ButtonsModel *m_availableButtons; + BorderSizesModel *m_borderSizes; + int m_borderSize; + QFont m_font; +}; + +class Settings : public QObject +{ + Q_OBJECT + Q_PROPERTY(KDecoration2::Preview::PreviewBridge *bridge READ bridge WRITE setBridge NOTIFY bridgeChanged) + Q_PROPERTY(KDecoration2::DecorationSettings *settings READ settingsPointer NOTIFY settingsChanged) +public: + explicit Settings(QObject *parent = nullptr); + virtual ~Settings(); + + PreviewBridge *bridge() const; + void setBridge(PreviewBridge *bridge); + + QSharedPointer settings() const; + DecorationSettings *settingsPointer() const; + +Q_SIGNALS: + void bridgeChanged(); + void settingsChanged(); + +private: + void createSettings(); + QPointer m_bridge; + QSharedPointer m_settings; +}; + +} +} + +#endif diff --git a/kcmkwin/kwindecoration/declarative-plugin/qmldir b/kcmkwin/kwindecoration/declarative-plugin/qmldir new file mode 100644 index 0000000000..42770220aa --- /dev/null +++ b/kcmkwin/kwindecoration/declarative-plugin/qmldir @@ -0,0 +1,2 @@ +module org.kde.kwin.private.kdecoration +plugin kdecorationprivatedeclarative diff --git a/kcmkwin/kwindecoration/decorationmodel.cpp b/kcmkwin/kwindecoration/decorationmodel.cpp index cea9d20de3..ccd2476251 100644 --- a/kcmkwin/kwindecoration/decorationmodel.cpp +++ b/kcmkwin/kwindecoration/decorationmodel.cpp @@ -1,370 +1,164 @@ -/******************************************************************** - KWin - the KDE window manager - This file is part of the KDE project. - -Copyright (C) 2009 Martin Gräßlin - -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 . -*********************************************************************/ +/* + * Copyright 2014 Martin Gräßlin + * + * 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 "decorationmodel.h" -#include "preview.h" -// kwin -#include -// Qt -#include -#include -#include -#include +// KDecoration2 +#include +#include // KDE -#include -#include -#include -#include #include +#include +#include #include -#include "kwindecoration.h" +// Qt +#include -/* WARNING ------------------------------------------------------------------------- -* it is *ABSOLUTELY* mandatory to manage loadPlugin() and destroyPreviousPlugin() -* using disablePreview() -* -* loadPlugin() moves the present factory pointer to "old_fact" which is then deleted -* by the succeeding destroyPreviousPlugin() -* -* So if you loaded a new plugin and that changed the current factory, call disablePreview() -* BEFORE the following destroyPreviousPlugin() destroys the factory for the current m_preview->deco->factory -* (which is invoked on deco deconstruction) -* WARNING ------------------------------------------------------------------------ */ - -static const QString s_auroraePluginName = QStringLiteral("aurorae"); - -namespace KWin +namespace KDecoration2 { -DecorationModel::DecorationModel(KSharedConfigPtr config, QObject* parent) +namespace Configuration +{ +static const QString s_pluginName = QStringLiteral("org.kde.kdecoration2"); + +DecorationsModel::DecorationsModel(QObject *parent) : QAbstractListModel(parent) - , m_plugins(new KDecorationPreviewPlugins(config)) - , m_preview(new KDecorationPreview()) - , m_customButtons(false) - , m_options(new KDecorationPreviewOptions) { - QHash roleNames; - roleNames[Qt::DisplayRole] = "display"; - roleNames[TypeRole] = "type"; - roleNames[AuroraeNameRole] = "auroraeThemeName"; - roleNames[QmlMainScriptRole] = "mainScript"; - roleNames[BorderSizeRole] = "borderSize"; - roleNames[ButtonSizeRole] = "buttonSize"; - roleNames[LibraryNameRole] = "library"; - setRoleNames(roleNames); - m_config = KSharedConfig::openConfig("auroraerc"); - findDecorations(); } -DecorationModel::~DecorationModel() +DecorationsModel::~DecorationsModel() = default; + +int DecorationsModel::rowCount(const QModelIndex &parent) const { - delete m_preview; - delete m_plugins; + if (parent.isValid()) { + return 0; + } + return m_plugins.size(); } -void DecorationModel::reload() +QVariant DecorationsModel::data(const QModelIndex &index, int role) const { - m_decorations.clear(); - findDecorations(); + if (!index.isValid() || index.column() != 0 || index.row() < 0 || index.row() >= int(m_plugins.size())) { + return QVariant(); + } + const Data &d = m_plugins.at(index.row()); + switch (role) { + case Qt::DisplayRole: + return d.visibleName; + case Qt::UserRole +4: + return d.pluginName; + case Qt::UserRole +5: + return d.themeName; + } + + return QVariant(); } -// Find all theme desktop files in all 'data' dirs owned by kwin. -// And insert these into a DecorationInfo structure -void DecorationModel::findDecorations() +QHash< int, QByteArray > DecorationsModel::roleNames() const +{ + QHash roles({ + {Qt::DisplayRole, QByteArrayLiteral("display")}, + {Qt::UserRole + 4, QByteArrayLiteral("plugin")}, + {Qt::UserRole + 5, QByteArrayLiteral("theme")} + }); + return roles; +} + +static bool isThemeEngine(const QVariantMap &decoSettingsMap) +{ + auto it = decoSettingsMap.find(QStringLiteral("themes")); + if (it == decoSettingsMap.end()) { + return false; + } + return it.value().toBool(); +} + +static QString themeListKeyword(const QVariantMap &decoSettingsMap) +{ + auto it = decoSettingsMap.find(QStringLiteral("themeListKeyword")); + if (it == decoSettingsMap.end()) { + return QString(); + } + return it.value().toString(); +} + +void DecorationsModel::init() { beginResetModel(); - const auto decorations = KPluginTrader::self()->query(QStringLiteral("kwin/kdecorations")); - for (const KPluginInfo &plugin : decorations) { - if (plugin.pluginName() == s_auroraePluginName) { - // read the Aurorae themes - findAuroraeThemes(); + const auto plugins = KPluginTrader::self()->query(s_pluginName, s_pluginName); + for (const auto &info : plugins) { + KPluginLoader loader(info.libraryPath()); + KPluginFactory *factory = loader.factory(); + if (!factory) { continue; } - DecorationModelData data; - data.name = plugin.name(); - data.pluginName = plugin.pluginName(); - data.type = DecorationModelData::NativeDecoration; - data.borderSize = KDecorationDefines::BorderNormal; - data.closeDblClick = false; - data.comment = plugin.comment(); - data.author = plugin.author(); - data.email = plugin.email(); - data.version = plugin.version(); - data.license = plugin.license(); - data.website = plugin.website(); - m_decorations.append(data); - } + auto metadata = loader.metaData().value(QStringLiteral("MetaData")).toObject().value(s_pluginName); + if (!metadata.isUndefined()) { + const auto decoSettingsMap = metadata.toObject().toVariantMap(); + if (isThemeEngine(decoSettingsMap)) { + const QString keyword = themeListKeyword(decoSettingsMap); + if (keyword.isNull()) { + // We cannot list the themes + continue; + } + QScopedPointer themeFinder(factory->create(keyword)); + if (themeFinder.isNull()) { + continue; + } + QVariant themes = themeFinder->property("themes"); + if (!themes.isValid()) { + continue; + } + const auto themesMap = themes.toMap(); + for (auto it = themesMap.begin(); it != themesMap.end(); ++it) { + Data d; + d.pluginName = info.pluginName(); + d.themeName = it.value().toString(); + d.visibleName = it.key(); + m_plugins.emplace_back(std::move(d)); + } - KService::List offers = KServiceTypeTrader::self()->query("KWin/Decoration"); - foreach (KService::Ptr service, offers) { - DecorationModelData data; - data.name = service->name(); - data.pluginName = s_auroraePluginName; - data.type = DecorationModelData::QmlDecoration; - data.auroraeName = service->property("X-KDE-PluginInfo-Name").toString(); - QString scriptName = service->property("X-Plasma-MainScript").toString(); - data.configTranslationDomain = service->property(QStringLiteral("X-KWin-Config-TranslationDomain")).toString(); - data.qmlPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kwin/decorations/" + data.auroraeName + "/contents/" + scriptName); - if (data.qmlPath.isEmpty()) { - // not a valid QML theme - continue; + // it's a theme engine, we don't want to show this entry + continue; + } } - KConfigGroup config(m_config, data.auroraeName); - data.borderSize = (KDecorationDefines::BorderSize)config.readEntry< int >("BorderSize", KDecorationDefines::BorderNormal); - data.buttonSize = (KDecorationDefines::BorderSize)config.readEntry< int >("ButtonSize", KDecorationDefines::BorderNormal); - data.closeDblClick = config.readEntry< bool >("CloseOnDoubleClickMenuButton", false); - data.comment = service->comment(); - KPluginInfo info(service); - data.author = info.author(); - data.email= info.email(); - data.version = info.version(); - data.license = info.license(); - data.website = info.website(); - m_decorations.append(data); + Data data; + data.pluginName = info.pluginName(); + data.visibleName = info.name().isEmpty() ? info.pluginName() : info.name(); + + m_plugins.emplace_back(std::move(data)); } - qSort(m_decorations.begin(), m_decorations.end(), DecorationModelData::less); endResetModel(); } -void DecorationModel::findAuroraeThemes() +QModelIndex DecorationsModel::findDecoration(const QString &pluginName, const QString &themeName) const { - // get all destop themes - QStringList themes; - const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, "aurorae/themes/", QStandardPaths::LocateDirectory); - QStringList themeDirectories; - for (const QString & dir : dirs) { - QDir directory = QDir(dir); - for (const QString &themeDir : directory.entryList(QDir::AllDirs | QDir::NoDotAndDotDot)) { - themeDirectories << dir + themeDir; + auto it = std::find_if(m_plugins.cbegin(), m_plugins.cend(), + [pluginName, themeName](const Data &d) { + return d.pluginName == pluginName && d.themeName == themeName; } + ); + if (it == m_plugins.cend()) { + return QModelIndex(); } - for (const QString &dir : themeDirectories) { - for (const QString & file : QDir(dir).entryList(QStringList() << QStringLiteral("metadata.desktop"))) { - themes.append(dir + '/' + file); - } - } - foreach (const QString & theme, themes) { - int themeSepIndex = theme.lastIndexOf('/', -1); - QString themeRoot = theme.left(themeSepIndex); - int themeNameSepIndex = themeRoot.lastIndexOf('/', -1); - QString packageName = themeRoot.right(themeRoot.length() - themeNameSepIndex - 1); - - KDesktopFile df(theme); - QString name = df.readName(); - if (name.isEmpty()) { - name = packageName; - } - - DecorationModelData data; - data.name = name; - data.pluginName = s_auroraePluginName; - data.type = DecorationModelData::AuroraeDecoration; - data.auroraeName = packageName; - KConfigGroup config(m_config, data.auroraeName); - data.borderSize = (KDecorationDefines::BorderSize)config.readEntry< int >("BorderSize", KDecorationDefines::BorderNormal); - data.buttonSize = (KDecorationDefines::BorderSize)config.readEntry< int >("ButtonSize", KDecorationDefines::BorderNormal); - data.closeDblClick = config.readEntry< bool >("CloseOnDoubleClickMenuButton", false); - metaData(data, df); - m_decorations.append(data); - } + const auto distance = std::distance(m_plugins.cbegin(), it); + return createIndex(distance, 0); } -void DecorationModel::metaData(DecorationModelData& data, const KDesktopFile& df) -{ - data.comment = df.readComment(); - data.author = df.desktopGroup().readEntry("X-KDE-PluginInfo-Author", QString()); - data.email = df.desktopGroup().readEntry("X-KDE-PluginInfo-Email", QString()); - data.version = df.desktopGroup().readEntry("X-KDE-PluginInfo-Version", QString()); - data.license = df.desktopGroup().readEntry("X-KDE-PluginInfo-License", QString()); - data.website = df.desktopGroup().readEntry("X-KDE-PluginInfo-Website", QString()); } - -int DecorationModel::rowCount(const QModelIndex& parent) const -{ - Q_UNUSED(parent) - return m_decorations.count(); } - -QVariant DecorationModel::data(const QModelIndex& index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - switch(role) { - case Qt::DisplayRole: - case NameRole: - return m_decorations[ index.row()].name; - case LibraryNameRole: - return m_decorations[ index.row()].pluginName; - case TypeRole: - return m_decorations[ index.row()].type; - case AuroraeNameRole: - return m_decorations[ index.row()].auroraeName; - case PackageDescriptionRole: - return m_decorations[ index.row()].comment; - case PackageAuthorRole: - return m_decorations[ index.row()].author; - case PackageEmailRole: - return m_decorations[ index.row()].email; - case PackageWebsiteRole: - return m_decorations[ index.row()].website; - case PackageVersionRole: - return m_decorations[ index.row()].version; - case PackageLicenseRole: - return m_decorations[ index.row()].license; - case BorderSizeRole: - return static_cast< int >(m_decorations[ index.row()].borderSize); - case BorderSizesRole: { - QList< QVariant > sizes; - const bool mustDisablePreview = m_plugins->factory() && m_plugins->factory() == m_preview->factory(); - if (m_plugins->loadPlugin(m_decorations[index.row()].pluginName) && m_plugins->factory()) { - foreach (KDecorationDefines::BorderSize size, m_plugins->factory()->borderSizes()) // krazy:exclude=foreach - sizes << int(size); - if (mustDisablePreview) // it's nuked with destroyPreviousPlugin() - m_preview->disablePreview(); // so we need to get rid of m_preview->deco first - m_plugins->destroyPreviousPlugin(); - } - return sizes; - } - case ButtonSizeRole: - if (m_decorations[ index.row()].type == DecorationModelData::AuroraeDecoration || - m_decorations[ index.row()].type == DecorationModelData::QmlDecoration) - return static_cast< int >(m_decorations[ index.row()].buttonSize); - else - return QVariant(); - case QmlMainScriptRole: - return m_decorations[ index.row()].qmlPath; - case CloseOnDblClickRole: - return m_decorations[index.row()].closeDblClick; - case ConfigTranslationDomain: - return m_decorations[index.row()].configTranslationDomain; - default: - return QVariant(); - } -} - -bool DecorationModel::setData(const QModelIndex& index, const QVariant& value, int role) -{ - if (!index.isValid() || (role != BorderSizeRole && role != ButtonSizeRole && role != CloseOnDblClickRole)) - return QAbstractItemModel::setData(index, value, role); - - const DecorationModelData::DecorationType type = m_decorations[ index.row()].type; - - if (role == BorderSizeRole) { - m_decorations[ index.row()].borderSize = (KDecorationDefines::BorderSize)value.toInt(); - if (type == DecorationModelData::AuroraeDecoration || type == DecorationModelData::QmlDecoration) { - KConfigGroup config(m_config, m_decorations[ index.row()].auroraeName); - config.writeEntry("BorderSize", value.toInt()); - config.sync(); - } - emit dataChanged(index, index); - emit configChanged(m_decorations[ index.row()].auroraeName); - return true; - } - if (role == ButtonSizeRole && (type == DecorationModelData::AuroraeDecoration || type == DecorationModelData::QmlDecoration)) { - m_decorations[ index.row()].buttonSize = (KDecorationDefines::BorderSize)value.toInt(); - KConfigGroup config(m_config, m_decorations[ index.row()].auroraeName); - config.writeEntry("ButtonSize", value.toInt()); - config.sync(); - emit dataChanged(index, index); - emit configChanged(m_decorations[ index.row()].auroraeName); - return true; - } - if (role == CloseOnDblClickRole && (type == DecorationModelData::AuroraeDecoration || type == DecorationModelData::QmlDecoration)) { - if (m_decorations[ index.row()].closeDblClick == value.toBool()) { - return false; - } - m_decorations[ index.row()].closeDblClick = value.toBool(); - KConfigGroup config(m_config, m_decorations[ index.row()].auroraeName); - config.writeEntry("CloseOnDoubleClickMenuButton", value.toBool()); - config.sync(); - emit dataChanged(index, index); - emit configChanged(m_decorations[ index.row()].auroraeName); - return true; - } - return QAbstractItemModel::setData(index, value, role); -} - - -void DecorationModel::changeButtons(const KWin::DecorationButtons *buttons) -{ - m_customButtons = buttons->customPositions(); - m_options->setCustomTitleButtonsEnabled(m_customButtons); - m_options->setCustomTitleButtons(buttons->leftButtons(), buttons->rightButtons()); -} - -void DecorationModel::setButtons(bool custom, const QList &left, const QList &right) -{ - m_customButtons = custom; - m_options->setCustomTitleButtons(left, right); -} - -QModelIndex DecorationModel::indexOfLibrary(const QString& libraryName) const -{ - for (int i = 0; i < m_decorations.count(); i++) { - if (m_decorations.at(i).pluginName.compare(libraryName) == 0) - return index(i); - } - return QModelIndex(); -} - -QModelIndex DecorationModel::indexOfName(const QString& decoName) const -{ - for (int i = 0; i < m_decorations.count(); i++) { - if (m_decorations.at(i).name.compare(decoName) == 0) - return index(i); - } - return QModelIndex(); -} - -QModelIndex DecorationModel::indexOfAuroraeName(const QString &auroraeName, const QString &type) const -{ - for (int i = 0; i < m_decorations.count(); i++) { - const DecorationModelData& data = m_decorations.at(i); - if (type == "aurorae" && data.type == DecorationModelData::AuroraeDecoration && - data.auroraeName.compare(auroraeName) == 0) - return index(i); - if (type == "qml" && data.type == DecorationModelData::QmlDecoration && - data.auroraeName.compare(auroraeName) == 0) - return index(i); - } - return QModelIndex(); -} - -void DecorationModel::setBorderSize(const QModelIndex& index, KDecorationDefines::BorderSize size) -{ - if (!index.isValid() || m_decorations[ index.row()].type == DecorationModelData::AuroraeDecoration || m_decorations[ index.row()].type == DecorationModelData::QmlDecoration) - return; - m_decorations[ index.row()].borderSize = size; -} - -QVariant DecorationModel::readConfig(const QString &themeName, const QString &key, const QVariant &defaultValue) -{ - return m_config->group(themeName).readEntry(key, defaultValue); -} - -void DecorationModel::notifyConfigChanged(const QModelIndex &index) -{ - if (!index.isValid()) { - return; - } - emit configChanged(m_decorations[index.row()].auroraeName); -} - -} // namespace KWin diff --git a/kcmkwin/kwindecoration/decorationmodel.h b/kcmkwin/kwindecoration/decorationmodel.h index 5c018c5e0e..97825ae97f 100644 --- a/kcmkwin/kwindecoration/decorationmodel.h +++ b/kcmkwin/kwindecoration/decorationmodel.h @@ -1,139 +1,59 @@ -/******************************************************************** - KWin - the KDE window manager - This file is part of the KDE project. +/* + * Copyright 2014 Martin Gräßlin + * + * 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 KDECORATION_DECORATIONS_MODEL_H +#define KDECORATION_DECORATIONS_MODEL_H -Copyright (C) 2009 Martin Gräßlin - -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 KWIN_DECORATIONMODEL_H -#define KWIN_DECORATIONMODEL_H #include -#include -#include -#include -#include -class QWidget; -class KDesktopFile; -class KDecorationPlugins; -class KDecorationPreview; -class KDecorationPreviewOptions; - -namespace KWin +namespace KDecoration2 { -class DecorationButtons; - -class DecorationModelData +namespace Configuration { -public: - enum DecorationType { - NativeDecoration = 0, - AuroraeDecoration = 1, - QmlDecoration = 2 - }; - QString name; - QString pluginName; - DecorationType type; - QString comment; - QString author; - QString email; - QString website; - QString version; - QString license; - QString auroraeName; - QString qmlPath; - QString configTranslationDomain; - KDecorationDefines::BorderSize borderSize; - KDecorationDefines::BorderSize buttonSize; - /** - * Whether the window gets closed on double clicking the Menu Button. - * Only applies for Aurorae and QML Decoration. - **/ - bool closeDblClick; - static bool less(const DecorationModelData& a, const DecorationModelData& b) { - return a.name < b.name; - } -}; - -class DecorationModel : public QAbstractListModel +class DecorationsModel : public QAbstractListModel { Q_OBJECT public: - enum { - NameRole = Qt::UserRole, - LibraryNameRole = Qt::UserRole + 1, - TypeRole = Qt::UserRole + 3, - AuroraeNameRole = Qt::UserRole + 4, - PackageDescriptionRole = Qt::UserRole + 5, - PackageAuthorRole = Qt::UserRole + 6, - PackageEmailRole = Qt::UserRole + 7, - PackageWebsiteRole = Qt::UserRole + 8, - PackageVersionRole = Qt::UserRole + 9, - PackageLicenseRole = Qt::UserRole + 10, - BorderSizeRole = Qt::UserRole + 11, - BorderSizesRole = Qt::UserRole + 12, - ButtonSizeRole = Qt::UserRole + 13, - QmlMainScriptRole = Qt::UserRole + 14, - CloseOnDblClickRole = Qt::UserRole + 15, - ConfigTranslationDomain = Qt::UserRole + 16 - }; - explicit DecorationModel(KSharedConfigPtr config, QObject* parent = nullptr); - ~DecorationModel(); + explicit DecorationsModel(QObject *parent = nullptr); + virtual ~DecorationsModel(); - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; - virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QHash< int, QByteArray > roleNames() const override; - void reload(); + QModelIndex findDecoration(const QString &pluginName, const QString &themeName = QString()) const; - /** - * Changes the button state and regenerates the preview. - */ - void changeButtons(const DecorationButtons *buttons); - /** - * Changes the button state without regenerating the preview. - */ - void setButtons(bool custom, const QList& left, const QList& right); +public Q_SLOTS: + void init(); - void setBorderSize(const QModelIndex& index, KDecorationDefines::BorderSize size); - - QModelIndex indexOfLibrary(const QString& libraryName) const; - QModelIndex indexOfName(const QString& decoName) const; - QModelIndex indexOfAuroraeName(const QString& auroraeName, const QString& type) const; - - Q_INVOKABLE QVariant readConfig(const QString &themeName, const QString &key, const QVariant &defaultValue = QVariant()); - - void notifyConfigChanged(const QModelIndex &index); - -Q_SIGNALS: - void configChanged(QString themeName); private: - void findDecorations(); - void findAuroraeThemes(); - void metaData(DecorationModelData& data, const KDesktopFile& df); - QList m_decorations; - KDecorationPlugins* m_plugins; - KDecorationPreview* m_preview; - bool m_customButtons; - KSharedConfigPtr m_config; - QScopedPointer m_options; + struct Data { + QString pluginName; + QString themeName; + QString visibleName; + }; + std::vector m_plugins; }; -} // namespace KWin +} +} -#endif // KWIN_DECORATIONMODEL_H +#endif diff --git a/kcmkwin/kwindecoration/kcm.cpp b/kcmkwin/kwindecoration/kcm.cpp new file mode 100644 index 0000000000..cd0caf3b2b --- /dev/null +++ b/kcmkwin/kwindecoration/kcm.cpp @@ -0,0 +1,128 @@ +/* + * Copyright 2014 Martin Gräßlin + * + * 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 "kcm.h" +#include "decorationmodel.h" + +// KDE +#include +#include +#include +// Qt +#include +#include +#include +#include +#include +#include +#include +#include + +K_PLUGIN_FACTORY(KDecorationFactory, + registerPlugin(); + ) + +namespace KDecoration2 +{ + +namespace Configuration +{ +static const QString s_pluginName = QStringLiteral("org.kde.kdecoration2"); +static const QString s_defaultPlugin = QStringLiteral("org.kde.breeze"); + +ConfigurationModule::ConfigurationModule(QWidget *parent, const QVariantList &args) + : KCModule(parent, args) + , m_view(new QQuickWidget(this)) + , m_model(new DecorationsModel(this)) +{ + m_view->rootContext()->setContextProperty(QStringLiteral("decorationsModel"), m_model); + m_view->rootContext()->setContextProperty("highlightColor", QPalette().color(QPalette::Highlight)); + m_view->setResizeMode(QQuickWidget::SizeRootObjectToView); + m_view->setSource(QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kwin/kcm_kwindecoration/main.qml")))); + if (m_view->status() == QQuickWidget::Ready) { + auto listView = m_view->rootObject()->findChild("listView"); + if (listView) { + connect(listView, SIGNAL(currentIndexChanged()), this, SLOT(changed())); + } + } + + QVBoxLayout *l = new QVBoxLayout(this); + l->addWidget(m_view); + QMetaObject::invokeMethod(m_model, "init", Qt::QueuedConnection); +} + +ConfigurationModule::~ConfigurationModule() = default; + +void ConfigurationModule::showEvent(QShowEvent *ev) +{ + KCModule::showEvent(ev); +} + +void ConfigurationModule::load() +{ + const KConfigGroup config = KSharedConfig::openConfig("kwinrc")->group(s_pluginName); + const QString plugin = config.readEntry("library", s_defaultPlugin); + const QString theme = config.readEntry("theme", QString()); + const QModelIndex index = m_model->findDecoration(plugin, theme); + if (auto listView = m_view->rootObject()->findChild("listView")) { + listView->setProperty("currentIndex", index.isValid() ? index.row() : -1); + } + KCModule::load(); +} + +void ConfigurationModule::save() +{ + if (auto listView = m_view->rootObject()->findChild("listView")) { + const int currentIndex = listView->property("currentIndex").toInt(); + if (currentIndex != -1) { + const QModelIndex index = m_model->index(currentIndex, 0); + if (index.isValid()) { + KConfigGroup config = KSharedConfig::openConfig("kwinrc")->group(s_pluginName); + config.writeEntry("library", index.data(Qt::UserRole + 4).toString()); + const QString theme = index.data(Qt::UserRole +5).toString(); + if (theme.isEmpty()) { + config.deleteEntry("theme"); + } else { + config.writeEntry("theme", theme); + } + config.sync(); + } + } + } + KCModule::save(); + // Send signal to all kwin instances + QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KWin"), + QStringLiteral("org.kde.KWin"), + QStringLiteral("reloadConfig")); + QDBusConnection::sessionBus().send(message); +} + +void ConfigurationModule::defaults() +{ + if (auto listView = m_view->rootObject()->findChild("listView")) { + const QModelIndex index = m_model->findDecoration(s_defaultPlugin); + listView->setProperty("currentIndex", index.isValid() ? index.row() : -1); + } + KCModule::defaults(); +} + +} +} + +#include "kcm.moc" diff --git a/kcmkwin/kwindecoration/kcm.h b/kcmkwin/kwindecoration/kcm.h new file mode 100644 index 0000000000..e3d352aa86 --- /dev/null +++ b/kcmkwin/kwindecoration/kcm.h @@ -0,0 +1,61 @@ +/* + * Copyright 2014 Martin Gräßlin + * + * 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 KDECORATIONS_KCM_H +#define KDECORATIONS_KCM_H + +#include + +class QQuickWidget; + +namespace KDecoration2 +{ +namespace Preview +{ +class PreviewBridge; +} +namespace Configuration +{ +class DecorationsModel; + +class ConfigurationModule : public KCModule +{ + Q_OBJECT +public: + explicit ConfigurationModule(QWidget *parent = nullptr, const QVariantList &args = QVariantList()); + virtual ~ConfigurationModule(); + +public Q_SLOTS: + void defaults() override; + void load() override; + void save() override; + +protected: + void showEvent(QShowEvent *ev) override; + +private: + QQuickWidget *m_view; + DecorationsModel *m_model; +}; + +} + +} + +#endif diff --git a/kcmkwin/kwindecoration/kwindecoration.cpp b/kcmkwin/kwindecoration/kwindecoration.cpp deleted file mode 100644 index 87c962d90a..0000000000 --- a/kcmkwin/kwindecoration/kwindecoration.cpp +++ /dev/null @@ -1,600 +0,0 @@ -/* - This is the new kwindecoration kcontrol module - - Copyright (c) 2001 - Karol Szwed - http://gallium.n3.net/ - Copyright 2009, 2010 Martin Gräßlin - - Supports new kwin configuration plugins, and titlebar button position - modification via dnd interface. - - Based on original "kwintheme" (Window Borders) - Copyright (C) 2001 Rik Hemsley (rikkus) - - 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. - -*/ -// own -#include "kwindecoration.h" -#include "buttonsconfigdialog.h" -#include "configdialog.h" -#include "decorationmodel.h" -#include "auroraetheme.h" -#include "preview.h" -// Qt -#include -#include -#include -#include -#include -#include -#include -#include -// KDE -#include -#include -#include -#include -#include -#include -#include -#include - -// KCModule plugin interface -// ========================= -K_PLUGIN_FACTORY(KWinDecoFactory, - registerPlugin(); - ) - -namespace KWin -{ - -static const QString s_defaultPluginName = QStringLiteral("Oxygen"); - -KWinDecorationForm::KWinDecorationForm(QWidget* parent) - : QWidget(parent) -{ - setupUi(this); -} - - -KWinDecorationModule::KWinDecorationModule(QWidget* parent, const QVariantList &) - : KCModule(parent) - , kwinConfig(KSharedConfig::openConfig("kwinrc")) - , m_showTooltips(false) - , m_model(nullptr) - , m_proxyModel(nullptr) - , m_configLoaded(false) - , m_decorationButtons(new DecorationButtons(this)) - , m_listView(new QQuickView()) - , m_translator(new KLocalizedTranslator(this)) -{ - qmlRegisterType("org.kde.kwin.aurorae", 0, 1, "AuroraeTheme"); - qmlRegisterType("org.kde.kwin.kcmdecoration", 0, 1, "PreviewItem"); - m_ui = new KWinDecorationForm(this); - m_ui->configureDecorationButton->setIcon(QIcon::fromTheme("configure")); - m_ui->configureButtonsButton->setIcon(QIcon::fromTheme("configure")); - m_ui->ghnsButton->setIcon(QIcon::fromTheme("get-hot-new-stuff")); - QWidget *container = QWidget::createWindowContainer(m_listView.data(), m_ui->decorationList->viewport()); - QVBoxLayout *containerLayout = new QVBoxLayout(m_ui->decorationList->viewport()); - containerLayout->addWidget(container); - QVBoxLayout* layout = new QVBoxLayout(this); - layout->addWidget(m_ui); - - KAboutData *about = - new KAboutData(QStringLiteral("kcmkwindecoration"), - i18n("Window Decoration Control Module"), - QString(), QString(), KAboutLicense::GPL, - i18n("(c) 2001 Karol Szwed")); - about->addAuthor(i18n("Karol Szwed"), QString(), "gallium@kde.org"); - setAboutData(about); - - QCoreApplication::instance()->installTranslator(m_translator); -} - - -KWinDecorationModule::~KWinDecorationModule() -{ -} - -void KWinDecorationModule::showEvent(QShowEvent *ev) -{ - KCModule::showEvent(ev); - init(); -} - -void KWinDecorationModule::init() -{ - if (m_model) { - // init already called - return; - } - const QString mainQmlPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kwin/kcm_kwindecoration/main.qml"); - if (mainQmlPath.isNull()) { - KMessageBox::error(this, i18n("

Installation error

" - "The resource

kwin/kcm_kwindecoration/main.qml

could not be located in any application data path." - "

Please contact your distribution

" - "The application will now abort"), i18n("Installation Error")); - abort(); - } - KConfigGroup style(kwinConfig, "Style"); - - // Set up the decoration lists and other UI settings - m_model = new DecorationModel(kwinConfig, this); - m_proxyModel = new QSortFilterProxyModel(this); - m_proxyModel->setSourceModel(m_model); - m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); - - m_listView->setResizeMode(QQuickView::SizeRootObjectToView); - m_listView->rootContext()->setContextProperty("decorationModel", m_proxyModel); - m_listView->rootContext()->setContextProperty("decorationBaseModel", m_model); - m_listView->rootContext()->setContextProperty("options", m_decorationButtons); - m_listView->rootContext()->setContextProperty("highlightColor", m_ui->decorationList->palette().color(QPalette::Highlight)); - m_listView->rootContext()->setContextProperty("auroraeSource", QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kwin/aurorae/aurorae.qml")); - m_listView->rootContext()->setContextProperty("decorationActiveCaptionColor", KDecoration::options()->color(ColorFont, true)); - m_listView->rootContext()->setContextProperty("decorationInactiveCaptionColor", KDecoration::options()->color(ColorFont, false)); - m_listView->rootContext()->setContextProperty("decorationActiveTitleBarColor", KDecoration::options()->color(ColorTitleBar, true)); - m_listView->rootContext()->setContextProperty("decorationInactiveTitleBarColor", KDecoration::options()->color(ColorTitleBar, false)); - m_listView->setSource(QUrl::fromLocalFile(mainQmlPath)); - - readConfig(style); - - connect(m_listView->rootObject(), SIGNAL(currentIndexChanged()), SLOT(slotSelectionChanged())); - connect(m_ui->configureButtonsButton, SIGNAL(clicked(bool)), this, SLOT(slotConfigureButtons())); - connect(m_ui->ghnsButton, SIGNAL(clicked(bool)), SLOT(slotGHNSClicked())); - connect(m_ui->searchEdit, SIGNAL(textChanged(QString)), m_proxyModel, SLOT(setFilterFixedString(QString))); - connect(m_ui->searchEdit, SIGNAL(textChanged(QString)), m_listView->rootObject(), SLOT(returnToBounds()), Qt::QueuedConnection); - connect(m_ui->searchEdit, SIGNAL(textChanged(QString)), SLOT(updateScrollbarRange()), Qt::QueuedConnection); - connect(m_ui->configureDecorationButton, SIGNAL(clicked(bool)), SLOT(slotConfigureDecoration())); - - m_ui->decorationList->disconnect(m_ui->decorationList->verticalScrollBar()); - m_ui->decorationList->verticalScrollBar()->disconnect(m_ui->decorationList); - connect(m_listView->rootObject(), SIGNAL(contentYChanged()), SLOT(updateScrollbarValue())); - connect(m_listView->rootObject(), SIGNAL(contentHeightChanged()), SLOT(updateScrollbarRange())); - connect(m_ui->decorationList->verticalScrollBar(), SIGNAL(rangeChanged(int,int)), SLOT(updateScrollbarRange())); - connect(m_ui->decorationList->verticalScrollBar(), SIGNAL(valueChanged(int)), SLOT(updateViewPosition(int))); - - m_ui->decorationList->installEventFilter(this); - m_ui->decorationList->viewport()->installEventFilter(this); - QMetaObject::invokeMethod(this, "updatePreviews", Qt::QueuedConnection); - updateScrollbarRange(); -} - -// This is the selection handler setting -void KWinDecorationModule::slotSelectionChanged() -{ - emit KCModule::changed(true); -} - -// Reads the kwin config settings, and sets all UI controls to those settings -// Updating the config plugin if required -void KWinDecorationModule::readConfig(const KConfigGroup & conf) -{ - m_showTooltips = conf.readEntry("ShowToolTips", true); - - // Find the corresponding decoration name to that of - // the current plugin library name - - QString libraryName = conf.readEntry("PluginLib", s_defaultPluginName); - - if (libraryName.isEmpty()) { - // Selected decoration doesn't exist, use the default - libraryName = s_defaultPluginName; - } - - const int bsize = conf.readEntry("BorderSize", (int)BorderNormal); - BorderSize borderSize = BorderNormal; - if (bsize >= BorderTiny && bsize < BordersCount) - borderSize = static_cast< BorderSize >(bsize); - if (libraryName == "aurorae") { - KConfig auroraeConfig("auroraerc"); - KConfigGroup group(&auroraeConfig, "Engine"); - const QString themeName = group.readEntry("ThemeName", "example-deco"); - const QString type = group.readEntry("EngineType", "aurorae"); - const QModelIndex index = m_proxyModel->mapFromSource(m_model->indexOfAuroraeName(themeName, type)); - if (index.isValid()) { - m_listView->rootObject()->setProperty("currentIndex", index.row()); - } - } else { - const QModelIndex index = m_proxyModel->mapFromSource(m_model->indexOfLibrary(libraryName)); - if (index.isValid()) { - m_model->setBorderSize(index, borderSize); - m_listView->rootObject()->setProperty("currentIndex", index.row()); - } - } - - // Buttons tab - // ============ - m_decorationButtons->setCustomPositions(conf.readEntry("CustomButtonPositions", false)); - // Menu and onAllDesktops buttons are default on LHS - m_decorationButtons->setLeftButtons(KDecorationOptions::readDecorationButtons(conf, "ButtonsOnLeft", - KDecorationOptions::defaultTitleButtonsLeft())); - // Help, Minimize, Maximize and Close are default on RHS - m_decorationButtons->setRightButtons(KDecorationOptions::readDecorationButtons(conf, "ButtonsOnRight", - KDecorationOptions::defaultTitleButtonsRight())); - if (m_configLoaded) - m_model->changeButtons(m_decorationButtons); - else { - m_configLoaded = true; - m_model->setButtons(m_decorationButtons->customPositions(), m_decorationButtons->leftButtons(), m_decorationButtons->rightButtons()); - } - - emit KCModule::changed(false); -} - - -// Writes the selected user configuration to the kwin config file -void KWinDecorationModule::writeConfig(KConfigGroup & conf) -{ - const QModelIndex index = m_proxyModel->mapToSource(m_proxyModel->index(m_listView->rootObject()->property("currentIndex").toInt(), 0)); - const QString libName = m_model->data(index, DecorationModel::LibraryNameRole).toString(); - - // General settings - conf.writeEntry("PluginLib", libName); - conf.writeEntry("CustomButtonPositions", m_decorationButtons->customPositions()); - conf.writeEntry("ShowToolTips", m_showTooltips); - - // Button settings - KDecorationOptions::writeDecorationButtons(conf, "ButtonsOnLeft", m_decorationButtons->leftButtons()); - KDecorationOptions::writeDecorationButtons(conf, "ButtonsOnRight", m_decorationButtons->rightButtons()); - conf.writeEntry("BorderSize", - static_cast(m_model->data(index, DecorationModel::BorderSizeRole).toInt())); - - if (m_model->data(index, DecorationModel::TypeRole).toInt() == DecorationModelData::AuroraeDecoration || - m_model->data(index, DecorationModel::TypeRole).toInt() == DecorationModelData::QmlDecoration) { - KConfig auroraeConfig("auroraerc"); - KConfigGroup group(&auroraeConfig, "Engine"); - group.writeEntry("ThemeName", m_model->data(index, DecorationModel::AuroraeNameRole).toString()); - if (m_model->data(index, DecorationModel::TypeRole).toInt() == DecorationModelData::QmlDecoration) { - group.writeEntry("EngineType", "qml"); - } else { - group.deleteEntry("EngineType"); - } - group.sync(); - } - - // We saved, so tell kcmodule that there have been no new user changes made. - emit KCModule::changed(false); -} - - -// Virutal functions required by KCModule -void KWinDecorationModule::load() -{ - const KConfigGroup config(kwinConfig, "Style"); - - // Reset by re-reading the config - readConfig(config); -} - - -void KWinDecorationModule::save() -{ - KConfigGroup config(kwinConfig, "Style"); - writeConfig(config); - config.sync(); - - // Send signal to all kwin instances - QDBusMessage message = - QDBusMessage::createSignal("/KWin", "org.kde.KWin", "reloadConfig"); - QDBusConnection::sessionBus().send(message); -} - - -void KWinDecorationModule::defaults() -{ - // Set the KDE defaults - m_showTooltips = true; - const QModelIndex index = m_proxyModel->mapFromSource(m_model->indexOfName(i18n("Oxygen"))); - if (index.isValid()) - m_listView->rootObject()->setProperty("currentIndex", index.row()); - - m_decorationButtons->resetToDefaults(); - - m_model->changeButtons(m_decorationButtons); - - emit changed(true); -} - -QString KWinDecorationModule::quickHelp() const -{ - return i18n("

Window Manager Decoration

" - "

This module allows you to choose the window border decorations, " - "as well as titlebar button positions and custom decoration options.

" - "To choose a theme for your window decoration click on its name and apply your choice by clicking the \"Apply\" button below." - " If you do not want to apply your choice you can click the \"Reset\" button to discard your changes." - "

You can configure each theme. There are different options specific for each theme.

" - "

On the \"Buttons\" tab check the \"Use custom titlebar button positions\" box " - "and you can change the positions of the buttons to your liking.

"); -} - -void KWinDecorationModule::slotConfigureButtons() -{ - QPointer< KWinDecorationButtonsConfigDialog > configDialog = new KWinDecorationButtonsConfigDialog(m_decorationButtons, m_showTooltips, this); - if (configDialog->exec() == QDialog::Accepted) { - m_decorationButtons->setCustomPositions(configDialog->customPositions()); - m_showTooltips = configDialog->showTooltips(); - m_decorationButtons->setLeftButtons(configDialog->buttonsLeft()); - m_decorationButtons->setRightButtons(configDialog->buttonsRight()); - m_model->changeButtons(m_decorationButtons); - emit changed(true); - } - - delete configDialog; -} - -void KWinDecorationModule::slotGHNSClicked() -{ - QPointer downloadDialog = new KNS3::DownloadDialog("aurorae.knsrc", this); - if (downloadDialog->exec() == QDialog::Accepted) { - if (!downloadDialog->changedEntries().isEmpty()) { - const QModelIndex index = m_proxyModel->mapToSource(m_proxyModel->index(m_listView->rootObject()->property("currentIndex").toInt(), 0)); - const QString libraryName = m_model->data(index, DecorationModel::LibraryNameRole).toString(); - bool aurorae = m_model->data(index, DecorationModel::TypeRole).toInt() == DecorationModelData::AuroraeDecoration; - bool qml = m_model->data(index, DecorationModel::TypeRole).toInt() == DecorationModelData::QmlDecoration; - const QString auroraeName = m_model->data(index, DecorationModel::AuroraeNameRole).toString(); - m_model->reload(); - if (aurorae) { - const QModelIndex proxyIndex = m_proxyModel->mapFromSource(m_model->indexOfAuroraeName(auroraeName, "aurorae")); - if (proxyIndex.isValid()) - m_listView->rootObject()->setProperty("currentIndex", proxyIndex.row()); - } else if (qml) { - const QModelIndex proxyIndex = m_proxyModel->mapFromSource(m_model->indexOfAuroraeName(auroraeName, "qml")); - if (proxyIndex.isValid()) - m_listView->rootObject()->setProperty("currentIndex", proxyIndex.row()); - } else { - const QModelIndex proxyIndex = m_proxyModel->mapFromSource(m_model->indexOfLibrary(libraryName)); - if (proxyIndex.isValid()) - m_listView->rootObject()->setProperty("currentIndex", proxyIndex.row()); - } - } - } - delete downloadDialog; -} - -void KWinDecorationModule::slotConfigureDecoration() -{ - const QModelIndex index = m_proxyModel->mapToSource(m_proxyModel->index(m_listView->rootObject()->property("currentIndex").toInt(), 0)); - bool reload = false; - if (index.data(DecorationModel::TypeRole).toInt() == DecorationModelData::AuroraeDecoration || - index.data(DecorationModel::TypeRole).toInt() == DecorationModelData::QmlDecoration) { - QPointer dlg = new QDialog(this); - dlg->setWindowTitle(i18n("Decoration Options")); - KWinAuroraeConfigForm *form = new KWinAuroraeConfigForm(dlg); - form->enableNoSideBorderSupport(index.data(DecorationModel::TypeRole).toInt() == DecorationModelData::QmlDecoration); - dlg->setLayout(new QVBoxLayout); - QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, dlg.data()); - connect(buttons, SIGNAL(accepted()), dlg, SLOT(accept())); - connect(buttons, SIGNAL(rejected()), dlg, SLOT(reject())); - dlg->layout()->addWidget(form); - dlg->layout()->addWidget(buttons); - - form->borderSizesCombo->setCurrentIndex(index.data(DecorationModel::BorderSizeRole).toInt()); - form->buttonSizesCombo->setCurrentIndex(index.data(DecorationModel::ButtonSizeRole).toInt()); - form->closeWindowsDoubleClick->setChecked(index.data(DecorationModel::CloseOnDblClickRole).toBool()); - form->doubleClickMessage->setCloseButtonVisible(true); - form->doubleClickMessage->setText(i18n("Close by double clicking:\n To open the menu, keep the button pressed until it appears.")); - form->doubleClickMessage->setVisible(false); - connect(form->closeWindowsDoubleClick, &QCheckBox::toggled, [form](bool toggled) { - if (!toggled) { - return; - } - form->doubleClickMessage->animatedShow(); - }); - // in case of QmlDecoration look for a config.ui in the package structure - KConfigDialogManager *configManager = nullptr; - if (index.data(DecorationModel::TypeRole).toInt() == DecorationModelData::QmlDecoration) { - const QString packageName = index.data(DecorationModel::AuroraeNameRole).toString(); - const QString uiPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kwin/decorations/" + packageName + "/contents/ui/config.ui"); - const QString configPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kwin/decorations/" + packageName + "/contents/config/main.xml"); - if (!uiPath.isEmpty() && !configPath.isEmpty()) { - // load the KConfigSkeleton - QFile configFile(configPath); - KSharedConfigPtr auroraeConfig = KSharedConfig::openConfig("auroraerc"); - KConfigGroup configGroup = auroraeConfig->group(packageName); - KConfigLoader *skeleton = new KConfigLoader(configGroup, &configFile, dlg); - // load the ui file - m_translator->setTranslationDomain(index.data(DecorationModel::ConfigTranslationDomain).toString()); - QUiLoader *loader = new QUiLoader(dlg); - loader->setLanguageChangeEnabled(true); - QFile uiFile(uiPath); - uiFile.open(QFile::ReadOnly); - QWidget *customConfigForm = loader->load(&uiFile, form); - m_translator->addContextToMonitor(customConfigForm->objectName()); - uiFile.close(); - form->layout()->addWidget(customConfigForm); - // connect the ui file with the skeleton - configManager = new KConfigDialogManager(customConfigForm, skeleton); - configManager->updateWidgets(); - - // send a custom event to the translator to retranslate using our translator - QEvent le(QEvent::LanguageChange); - QCoreApplication::sendEvent(customConfigForm, &le); - } - } - if (dlg->exec() == QDialog::Accepted) { - m_model->setData(index, form->borderSizesCombo->currentIndex(), DecorationModel::BorderSizeRole); - m_model->setData(index, form->buttonSizesCombo->currentIndex(), DecorationModel::ButtonSizeRole); - m_model->setData(index, form->closeWindowsDoubleClick->isChecked(), DecorationModel::CloseOnDblClickRole); - if (configManager && configManager->hasChanged()) { - // we have a config manager and the settings changed - configManager->updateSettings(); - m_model->notifyConfigChanged(index); - } - reload = true; - } - delete dlg; - } else { - QString name = index.data(DecorationModel::LibraryNameRole).toString(); - QList< QVariant > borderSizes = index.data(DecorationModel::BorderSizesRole).toList(); - const KDecorationDefines::BorderSize size = - static_cast(index.data(DecorationModel::BorderSizeRole).toInt()); - QPointer< KWinDecorationConfigDialog > configDialog = - new KWinDecorationConfigDialog(name, borderSizes, size, this); - if (configDialog->exec() == QDialog::Accepted) { - m_model->setData(index, configDialog->borderSize(), DecorationModel::BorderSizeRole); - reload = true; - } - - delete configDialog; - } - if (reload) { - save(); - } -} - -bool KWinDecorationModule::eventFilter(QObject *o, QEvent *e) -{ - if (o == m_ui->decorationList) { - if (e->type() == QEvent::Resize) - updateScrollbarRange(); - else if (e->type() == QEvent::KeyPress) { - int d = 0; - const int currentRow = m_listView->rootObject()->property("currentIndex").toInt(); - const int key = static_cast(e)->key(); - switch (key) { - case Qt::Key_Home: - d = -currentRow; - break; - case Qt::Key_End: - d = m_proxyModel->rowCount() - (1 + currentRow); - break; - case Qt::Key_Up: - d = -1; - break; - case Qt::Key_Down: - d = 1; - break; - case Qt::Key_PageUp: - case Qt::Key_PageDown: - d = 150; - if (QObject *decoItem = m_listView->rootObject()->findChild("decorationItem")) { - QVariant v = decoItem->property("height"); - if (v.isValid()) - d = v.toInt(); - } - if (d > 0) - d = qMax(m_ui->decorationList->height() / d, 1); - if (key == Qt::Key_PageUp) - d = -d; - break; - default: - break; - } - if (d) { - d = qMin(qMax(0, currentRow + d), m_proxyModel->rowCount()); - m_listView->rootObject()->setProperty("currentIndex", d); - return true; - } - } - } else if (m_ui->decorationList->viewport()) { - if (e->type() == QEvent::Wheel) { - return static_cast(e)->orientation() == Qt::Horizontal; - } - } - return KCModule::eventFilter(o, e); -} - -void KWinDecorationModule::updateScrollbarRange() -{ - m_ui->decorationList->verticalScrollBar()->blockSignals(true); - const bool atMinimum = m_listView->rootObject()->property("atYBeginning").toBool(); - const int h = m_listView->rootObject()->property("contentHeight").toInt(); - const int y = atMinimum ? m_listView->rootObject()->property("contentY").toInt() : 0; - m_ui->decorationList->verticalScrollBar()->setRange(y, y + h - m_ui->decorationList->height()); - m_ui->decorationList->verticalScrollBar()->setPageStep(m_ui->decorationList->verticalScrollBar()->maximum()/m_model->rowCount()); - m_ui->decorationList->verticalScrollBar()->blockSignals(false); -} - -void KWinDecorationModule::updateScrollbarValue() -{ - const int v = m_listView->rootObject()->property("contentY").toInt(); - m_ui->decorationList->verticalScrollBar()->blockSignals(true); // skippig this will kill kinetic scrolling but the scrollwidth is too low - m_ui->decorationList->verticalScrollBar()->setValue(v); - m_ui->decorationList->verticalScrollBar()->blockSignals(false); -} - -void KWinDecorationModule::updateViewPosition(int v) -{ - m_listView->rootObject()->setProperty("contentY", v); -} - -DecorationButtons::DecorationButtons(QObject *parent) - : QObject(parent) - , m_customPositions(false) - , m_leftButtons() - , m_rightButtons() -{ - setLeftButtons(KDecorationOptions::defaultTitleButtonsLeft()); - setRightButtons(KDecorationOptions::defaultTitleButtonsRight()); -} - -DecorationButtons::~DecorationButtons() -{ -} - -bool DecorationButtons::customPositions() const -{ - return m_customPositions; -} - -const QList &DecorationButtons::leftButtons() const -{ - return m_leftButtons; -} - -const QList &DecorationButtons::rightButtons() const -{ - return m_rightButtons; -} - -void DecorationButtons::setCustomPositions(bool set) -{ - if (m_customPositions == set) { - return; - } - m_customPositions = set; - emit customPositionsChanged(); -} - -void DecorationButtons::setLeftButtons(const QList &leftButtons) -{ - if (m_leftButtons == leftButtons) { - return; - } - m_leftButtons = leftButtons; - emit leftButtonsChanged(); -} - -void DecorationButtons::setRightButtons(const QList &rightButtons) -{ - if (m_rightButtons == rightButtons) { - return; - } - m_rightButtons = rightButtons; - emit rightButtonsChanged(); -} - -void DecorationButtons::resetToDefaults() -{ - setCustomPositions(false); - setLeftButtons(KDecorationOptions::defaultTitleButtonsLeft()); - setRightButtons(KDecorationOptions::defaultTitleButtonsRight()); -} - -} // namespace KWin - -#include "kwindecoration.moc" diff --git a/kcmkwin/kwindecoration/kwindecoration.h b/kcmkwin/kwindecoration/kwindecoration.h deleted file mode 100644 index beb2ee01c5..0000000000 --- a/kcmkwin/kwindecoration/kwindecoration.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - This is the new kwindecoration kcontrol module - - Copyright (c) 2001 - Karol Szwed - http://gallium.n3.net/ - Copyright 2009, 2010 Martin Gräßlin - - Supports new kwin configuration plugins, and titlebar button position - modification via dnd interface. - - Based on original "kwintheme" (Window Borders) - Copyright (C) 2001 Rik Hemsley (rikkus) - - 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 KWINDECORATION_H -#define KWINDECORATION_H - -#include -#include - -#include - -#include "ui_decoration.h" - -class QQuickView; -class QSortFilterProxyModel; -class KLocalizedTranslator; -namespace KWin -{ - -class DecorationModel; - -class KWinDecorationForm : public QWidget, public Ui::KWinDecorationForm -{ - Q_OBJECT - -public: - explicit KWinDecorationForm(QWidget* parent); -}; - -class DecorationButtons : public QObject, public KDecorationDefines -{ - Q_OBJECT - Q_PROPERTY(bool customButtonPositions READ customPositions WRITE setCustomPositions NOTIFY customPositionsChanged) -public: - explicit DecorationButtons(QObject *parent = nullptr); - virtual ~DecorationButtons(); - - bool customPositions() const; - const QList &leftButtons() const; - const QList &rightButtons() const; - - void setCustomPositions(bool set); - void setLeftButtons(const QList &buttons); - void setRightButtons(const QList &buttons); - -public Q_SLOTS: - void resetToDefaults(); - -Q_SIGNALS: - void customPositionsChanged(); - void leftButtonsChanged(); - void rightButtonsChanged(); - -private: - bool m_customPositions; - QList m_leftButtons; - QList m_rightButtons; -}; - -class KWinDecorationModule : public KCModule, public KDecorationDefines -{ - Q_OBJECT - -public: - KWinDecorationModule(QWidget* parent, const QVariantList &); - ~KWinDecorationModule(); - - virtual void load(); - virtual void save(); - virtual void defaults(); - - QString quickHelp() const; - -Q_SIGNALS: - void pluginLoad(const KConfigGroup& conf); - void pluginSave(KConfigGroup &conf); - void pluginDefaults(); - -protected: - bool eventFilter(QObject *o, QEvent *e); - virtual void showEvent(QShowEvent *ev); - -protected Q_SLOTS: - // Allows us to turn "save" on - void slotSelectionChanged(); - void slotConfigureButtons(); - void slotGHNSClicked(); - void slotConfigureDecoration(); - -private: - void init(); - void readConfig(const KConfigGroup& conf); - void writeConfig(KConfigGroup &conf); -private Q_SLOTS: - void updateScrollbarRange(); - void updateScrollbarValue(); - void updateViewPosition(int v); -private: - KSharedConfigPtr kwinConfig; - - KWinDecorationForm* m_ui; - bool m_showTooltips; - - DecorationModel* m_model; - QSortFilterProxyModel* m_proxyModel; - bool m_configLoaded; - DecorationButtons *m_decorationButtons; - - QScopedPointer m_listView; - - KLocalizedTranslator *m_translator; -}; - -} //namespace - -#endif diff --git a/kcmkwin/kwindecoration/preview.cpp b/kcmkwin/kwindecoration/preview.cpp deleted file mode 100644 index 26d357da6c..0000000000 --- a/kcmkwin/kwindecoration/preview.cpp +++ /dev/null @@ -1,630 +0,0 @@ -/* - * - * Copyright (c) 2003 Lubos Lunak - * Copyright (c) 2013 Martin Gräßlin - * - * 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 "preview.h" - -#include -#include -#include -#include -#include - -#include - -static const int SMALL_OFFSET = 10; -static const int LARGE_OFFSET = 40; - -PreviewItem::PreviewItem(QQuickItem *parent) - : QQuickPaintedItem(parent) - , m_plugins(new KDecorationPreviewPlugins(KSharedConfig::openConfig(QStringLiteral("kwinrc")))) - , m_activeBridge(new KDecorationPreviewBridge(this, true)) - , m_inactiveBridge(new KDecorationPreviewBridge(this, false)) - , m_activeDecoration(nullptr) - , m_inactiveDecoration(nullptr) - , m_activeEntered(nullptr) - , m_inactiveEntered(nullptr) -{ - setFlag(ItemHasContents, true); - setAcceptHoverEvents(true); - connect(this, &PreviewItem::libraryChanged, this, &PreviewItem::loadDecorationPlugin); -} - -PreviewItem::~PreviewItem() -{ - delete m_activeDecoration; - delete m_inactiveDecoration; -} - -void PreviewItem::setLibraryName(const QString &library) -{ - if (library == m_libraryName || library.isEmpty()) { - return; - } - m_libraryName = library; - emit libraryChanged(); -} - -void PreviewItem::loadDecorationPlugin() -{ - const bool loaded = m_plugins->loadPlugin(m_libraryName); - if (!loaded) { - return; - } - m_plugins->destroyPreviousPlugin(); - connect(m_plugins->factory(), &KDecorationFactory::recreateDecorations, - this, &PreviewItem::recreateDecorations, Qt::QueuedConnection); - recreateDecorations(); -} - -void PreviewItem::recreateDecorations() -{ - delete m_activeDecoration; - delete m_inactiveDecoration; - m_activeEntered = nullptr; - m_inactiveEntered = nullptr; - m_activeDecoration = m_plugins->createDecoration(m_activeBridge.data()); - m_inactiveDecoration = m_plugins->createDecoration(m_inactiveBridge.data()); - - if (m_activeDecoration) { - m_activeDecoration->init(); - if (m_activeDecoration->widget()) { - m_activeDecoration->widget()->installEventFilter(this); - } - } - if (m_inactiveDecoration) { - m_inactiveDecoration->init(); - if (m_inactiveDecoration->widget()) { - m_inactiveDecoration->widget()->installEventFilter(this); - } - } - updatePreview(); -} - -void PreviewItem::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) -{ - QQuickPaintedItem::geometryChanged(newGeometry, oldGeometry); - updatePreview(); -} - -void PreviewItem::updatePreview() -{ - if (width() == 0 && height() == 0) { - return; - } - if (!m_activeDecoration && !m_inactiveDecoration) { - return; - } - const QSize size(width() - 50, height() - 50); - updateSize(size, m_activeDecoration, m_activeBuffer); - updateSize(size, m_inactiveDecoration, m_inactiveBuffer); - - render(&m_activeBuffer, m_activeDecoration); - render(&m_inactiveBuffer, m_inactiveDecoration); - update(); -} - -void PreviewItem::updateSize(const QSize &baseSize, KDecoration *decoration, QImage &buffer) -{ - if (!decoration) { - return; - } - int left, right, top, bottom; - left = right = top = bottom = 0; - decoration->padding(left, right, top, bottom); - const QSize size = baseSize + QSize(left + right, top + bottom); - if (decoration->geometry().size() != size) { - decoration->resize(size); - } - if (buffer.isNull() || buffer.size() != size) { - buffer = QImage(size, QImage::Format_ARGB32_Premultiplied); - } -} - -void PreviewItem::render(QImage* image, KDecoration* decoration) -{ - image->fill(Qt::transparent); - decoration->render(image, QRegion()); -} - -void PreviewItem::paint(QPainter *painter) -{ - int paddingLeft, paddingRigth, paddingTop, paddingBottom; - paddingLeft = paddingRigth = paddingTop = paddingBottom = 0; - if (m_inactiveDecoration) { - m_inactiveDecoration->padding(paddingLeft, paddingRigth, paddingTop, paddingBottom); - } - - painter->drawImage(LARGE_OFFSET - paddingLeft, SMALL_OFFSET - paddingTop, m_inactiveBuffer); - - paddingLeft = paddingRigth = paddingTop = paddingBottom = 0; - if (m_activeDecoration) { - m_activeDecoration->padding(paddingLeft, paddingRigth, paddingTop, paddingBottom); - } - painter->drawImage(SMALL_OFFSET - paddingLeft, LARGE_OFFSET - paddingTop, m_activeBuffer); -} - -void PreviewItem::hoverMoveEvent(QHoverEvent* event) -{ - QQuickItem::hoverMoveEvent(event); - const int w = width() - LARGE_OFFSET - SMALL_OFFSET; - const int h = height() - LARGE_OFFSET - SMALL_OFFSET; - forwardMoveEvent(event, QRect(SMALL_OFFSET, LARGE_OFFSET, w, h), m_activeDecoration, &m_activeEntered); - forwardMoveEvent(event, QRect(LARGE_OFFSET, SMALL_OFFSET, w, h), m_inactiveDecoration, &m_inactiveEntered); -} - -void PreviewItem::forwardMoveEvent(QHoverEvent *event, const QRect &geo, KDecoration *deco, QWidget **entered) -{ - auto leaveEvent = [](QWidget **widget) { - if (!(*widget)) { - return; - } - // send old one a leave event - QEvent leave(QEvent::Leave); - QApplication::sendEvent(*widget, &leave); - *widget = nullptr; - }; - if (geo.contains(event->pos()) && deco && deco->widget()) { - int paddingLeft, paddingRigth, paddingTop, paddingBottom; - paddingLeft = paddingRigth = paddingTop = paddingBottom = 0; - deco->padding(paddingLeft, paddingRigth, paddingTop, paddingBottom); - const QPoint widgetPos = event->pos() - geo.topLeft() + QPoint(paddingLeft, paddingTop); - if (QWidget *widget = deco->widget()->childAt(widgetPos)) { - if (widget != *entered) { - leaveEvent(entered); - // send enter event - *entered = widget; - QEnterEvent enter(widgetPos - widget->geometry().topLeft(), widgetPos, event->pos()); - QApplication::sendEvent(*entered, &enter); - } - } else { - leaveEvent(entered); - } - } else { - leaveEvent(entered); - } -} - -void PreviewItem::updateDecoration(KDecorationPreviewBridge *bridge) -{ - if (bridge == m_activeBridge.data()) { - render(&m_activeBuffer, m_activeDecoration); - } else if (bridge == m_inactiveBridge.data()) { - render(&m_inactiveBuffer, m_inactiveDecoration); - } - update(); -} - -KDecorationPreview::KDecorationPreview(QWidget* parent) - : QWidget(parent) -{ - bridge[Active] = new KDecorationPreviewBridge(this, true); - bridge[Inactive] = new KDecorationPreviewBridge(this, false); - - deco[Active] = deco[Inactive] = NULL; - - setMinimumSize(100, 100); -} - -KDecorationPreview::~KDecorationPreview() -{ - for (int i = 0; i < NumWindows; i++) { - delete deco[i]; - delete bridge[i]; - } -} - -void KDecorationPreview::disablePreview() -{ - delete deco[Active]; - delete deco[Inactive]; - deco[Active] = deco[Inactive] = NULL; -} - -KDecorationFactory *KDecorationPreview::factory() const -{ - return deco[Active] ? deco[Active]->factory() : 0; -} - -QRect KDecorationPreview::windowGeometry(bool active) const -{ - QWidget *widget = active ? deco[Active]->widget() : deco[Inactive]->widget(); - return widget->geometry(); -} - -QRegion KDecorationPreview::unobscuredRegion(bool active, const QRegion& r) const -{ - Q_UNUSED(active) - return r; -} - -KDecorationPreviewBridge::KDecorationPreviewBridge(KDecorationPreview* p, bool a) - : preview(p) - , m_previewItem(nullptr) - , active(a) -{ -} - -KDecorationPreviewBridge::KDecorationPreviewBridge(PreviewItem *p, bool a) - : preview(nullptr) - , m_previewItem(p) - , active(a) -{ -} - -Qt::WindowFlags KDecorationPreviewBridge::initialWFlags() const -{ - return 0; -} - -bool KDecorationPreviewBridge::isActive() const -{ - return active; -} - -bool KDecorationPreviewBridge::isCloseable() const -{ - return true; -} - -bool KDecorationPreviewBridge::isMaximizable() const -{ - return true; -} - -KDecoration::MaximizeMode KDecorationPreviewBridge::maximizeMode() const -{ - return KDecoration::MaximizeRestore; -} - -KDecoration::QuickTileMode KDecorationPreviewBridge::quickTileMode() const -{ - return KDecoration::QuickTileNone; -} - -bool KDecorationPreviewBridge::isMinimizable() const -{ - return true; -} - -bool KDecorationPreviewBridge::providesContextHelp() const -{ - return true; -} - -int KDecorationPreviewBridge::desktop() const -{ - return 1; -} - -bool KDecorationPreviewBridge::isOnAllDesktopsAvailable() const -{ - return true; -} - -bool KDecorationPreviewBridge::isModal() const -{ - return false; -} - -bool KDecorationPreviewBridge::isShadeable() const -{ - return true; -} - -bool KDecorationPreviewBridge::isShade() const -{ - return false; -} - -bool KDecorationPreviewBridge::isSetShade() const -{ - return false; -} - -bool KDecorationPreviewBridge::keepAbove() const -{ - return false; -} - -bool KDecorationPreviewBridge::keepBelow() const -{ - return false; -} - -bool KDecorationPreviewBridge::isMovable() const -{ - return true; -} - -bool KDecorationPreviewBridge::isResizable() const -{ - return true; -} - -NET::WindowType KDecorationPreviewBridge::windowType(unsigned long) const -{ - return NET::Normal; -} - -QIcon KDecorationPreviewBridge::icon() const -{ - return QIcon::fromTheme(QStringLiteral("xorg")); -} - -QString KDecorationPreviewBridge::caption() const -{ - return active ? i18n("Active Window") : i18n("Inactive Window"); -} - -void KDecorationPreviewBridge::processMousePressEvent(QMouseEvent*) -{ -} - -void KDecorationPreviewBridge::showWindowMenu(const QRect &) -{ -} - -void KDecorationPreviewBridge::showWindowMenu(const QPoint &) -{ -} - -void KDecorationPreviewBridge::showApplicationMenu(const QPoint &) -{ -} - -bool KDecorationPreviewBridge::menuAvailable() const -{ - return false; -} - -void KDecorationPreviewBridge::performWindowOperation(WindowOperation) -{ -} - -void KDecorationPreviewBridge::setMask(const QRegion& reg, int mode) -{ - Q_UNUSED(reg) - Q_UNUSED(mode) -} - -bool KDecorationPreviewBridge::isPreview() const -{ - return true; -} - -QRect KDecorationPreviewBridge::geometry() const -{ - if (preview) { - return preview->windowGeometry(active); - } - return QRect(); -} - -QRect KDecorationPreviewBridge::iconGeometry() const -{ - return QRect(); -} - -QRegion KDecorationPreviewBridge::unobscuredRegion(const QRegion& r) const -{ - return preview->unobscuredRegion(active, r); -} - -WId KDecorationPreviewBridge::windowId() const -{ - return 0; // no decorated window -} - -void KDecorationPreviewBridge::closeWindow() -{ -} - -void KDecorationPreviewBridge::maximize(MaximizeMode) -{ -} - -void KDecorationPreviewBridge::minimize() -{ -} - -void KDecorationPreviewBridge::showContextHelp() -{ -} - -void KDecorationPreviewBridge::setDesktop(int) -{ -} - -void KDecorationPreviewBridge::titlebarDblClickOperation() -{ -} - -void KDecorationPreviewBridge::titlebarMouseWheelOperation(int) -{ -} - -void KDecorationPreviewBridge::setShade(bool) -{ -} - -void KDecorationPreviewBridge::setKeepAbove(bool) -{ -} - -void KDecorationPreviewBridge::setKeepBelow(bool) -{ -} - -int KDecorationPreviewBridge::currentDesktop() const -{ - return 1; -} - -void KDecorationPreviewBridge::grabXServer(bool) -{ -} - -bool KDecorationPreviewBridge::compositingActive() const -{ - return true; -} - -QRect KDecorationPreviewBridge::transparentRect() const -{ - return QRect(); -} - -// Window tabbing - -int KDecorationPreviewBridge::tabCount() const -{ - return 1; -} - -QString KDecorationPreviewBridge::caption(int) const -{ - return active ? "Active Window" : "Inactive Window"; -} - -QIcon KDecorationPreviewBridge::icon(int) const -{ - return icon(); -} - -long KDecorationPreviewBridge::tabId(int) const -{ - return 0; -} - -long KDecorationPreviewBridge::currentTabId() const -{ - return 0; -} - -void KDecorationPreviewBridge::setCurrentTab(long) -{ -} - -void KDecorationPreviewBridge::tab_A_before_B(long, long) -{ -} - -void KDecorationPreviewBridge::tab_A_behind_B(long, long) -{ -} - -void KDecorationPreviewBridge::untab(long, const QRect&) -{ -} - -void KDecorationPreviewBridge::closeTab(long) -{ -} - -void KDecorationPreviewBridge::closeTabGroup() -{ -} - -void KDecorationPreviewBridge::showWindowMenu(const QPoint &, long) -{ -} - -void KDecorationPreviewBridge::update(const QRegion&) -{ - if (m_previewItem) { - // call update - m_previewItem->updateDecoration(this); - } -} - -KDecoration::WindowOperation KDecorationPreviewBridge::buttonToWindowOperation(Qt::MouseButtons) -{ - return KDecoration::NoOp; -} - -QPalette KDecorationPreviewBridge::palette() const -{ - return QApplication::palette(); -} - -KDecorationPreviewOptions::KDecorationPreviewOptions() -{ - customBorderSize = BordersCount; // invalid - customButtonsChanged = false; // invalid - customButtons = true; - customTitleButtonsLeft.clear(); // invalid - customTitleButtonsRight.clear(); // invalid - updateSettings(); -} - -KDecorationPreviewOptions::~KDecorationPreviewOptions() -{ -} - -void KDecorationPreviewOptions::updateSettings() -{ - KConfig cfg("kwinrc"); - KDecorationOptions::updateSettings(&cfg); - - // set custom border size/buttons - if (customBorderSize != BordersCount) - setBorderSize(customBorderSize); - if (customButtonsChanged) - setCustomButtonPositions(customButtons); - if (customButtons) { - if (!customTitleButtonsLeft.isEmpty()) - setTitleButtonsLeft(customTitleButtonsLeft); - if (!customTitleButtonsRight.isEmpty()) - setTitleButtonsRight(customTitleButtonsRight); - } else { - setTitleButtonsLeft(KDecorationOptions::defaultTitleButtonsLeft()); - setTitleButtonsRight(KDecorationOptions::defaultTitleButtonsRight()); - } -} - -void KDecorationPreviewOptions::setCustomBorderSize(BorderSize size) -{ - customBorderSize = size; - - updateSettings(); -} - -void KDecorationPreviewOptions::setCustomTitleButtonsEnabled(bool enabled) -{ - customButtonsChanged = true; - customButtons = enabled; - - updateSettings(); -} - -void KDecorationPreviewOptions::setCustomTitleButtons(const QList &left, const QList &right) -{ - customTitleButtonsLeft = left; - customTitleButtonsRight = right; - - updateSettings(); -} - -bool KDecorationPreviewPlugins::provides(Requirement) -{ - return false; -} - -#include "preview.moc" diff --git a/kcmkwin/kwindecoration/preview.h b/kcmkwin/kwindecoration/preview.h deleted file mode 100644 index 2dd6d8d130..0000000000 --- a/kcmkwin/kwindecoration/preview.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - * - * Copyright (c) 2003 Lubos Lunak - * Copyright (c) 2013 Martin Gräßlin - * - * 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 KWINDECORATION_PREVIEW_H -#define KWINDECORATION_PREVIEW_H - -#include -#include -#include -#include -#include - -class KDecorationPreviewBridge; -class KDecorationPreviewOptions; -class QMouseEvent; - -class PreviewItem : public QQuickPaintedItem -{ - Q_OBJECT - Q_PROPERTY(QString library READ libraryName WRITE setLibraryName NOTIFY libraryChanged) -public: - PreviewItem(QQuickItem *parent = nullptr); - virtual ~PreviewItem(); - virtual void paint(QPainter *painter); - - void setLibraryName(const QString &library); - const QString &libraryName() const { - return m_libraryName; - } - void updateDecoration(KDecorationPreviewBridge *bridge); - -Q_SIGNALS: - void libraryChanged(); - -protected: - virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); - virtual void hoverMoveEvent(QHoverEvent *event); - -private Q_SLOTS: - void loadDecorationPlugin(); - void recreateDecorations(); - -private: - void updatePreview(); - void updateSize(const QSize &size, KDecoration *decoration, QImage &buffer); - void render(QImage *image, KDecoration *decoration); - void forwardMoveEvent(QHoverEvent *event, const QRect &geo, KDecoration *deco, QWidget **entered); - QScopedPointer m_plugins; - QScopedPointer m_activeBridge; - QScopedPointer m_inactiveBridge; - KDecoration *m_activeDecoration; - KDecoration *m_inactiveDecoration; - QWidget *m_activeEntered; - QWidget *m_inactiveEntered; - QString m_libraryName; - QImage m_activeBuffer; - QImage m_inactiveBuffer; -}; - -class KDecorationPreview - : public QWidget -{ - Q_OBJECT -public: - // Note: Windows can't be added or removed without making changes to - // the code, since parts of it assume there's just an active - // and an inactive window. - enum Windows { Inactive = 0, Active, NumWindows }; - - explicit KDecorationPreview(QWidget* parent = nullptr); - virtual ~KDecorationPreview(); - void disablePreview(); - KDecorationFactory *factory() const; - QRegion unobscuredRegion(bool, const QRegion&) const; - QRect windowGeometry(bool) const; -private: - KDecorationPreviewBridge* bridge[NumWindows]; - KDecoration* deco[NumWindows]; -}; - -class KDecorationPreviewBridge - : public KDecorationBridge -{ -public: - KDecorationPreviewBridge(KDecorationPreview* preview, bool active); - KDecorationPreviewBridge(PreviewItem* preview, bool active); - virtual bool isActive() const override; - virtual bool isCloseable() const override; - virtual bool isMaximizable() const override; - virtual MaximizeMode maximizeMode() const override; - virtual QuickTileMode quickTileMode() const override; - virtual bool isMinimizable() const override; - virtual bool providesContextHelp() const override; - virtual int desktop() const override; - bool isOnAllDesktopsAvailable() const override; - virtual bool isModal() const override; - virtual bool isShadeable() const override; - virtual bool isShade() const override; - virtual bool isSetShade() const override; - virtual bool keepAbove() const override; - virtual bool keepBelow() const override; - virtual bool isMovable() const override; - virtual bool isResizable() const override; - virtual NET::WindowType windowType(unsigned long supported_types) const override; - virtual QIcon icon() const override; - virtual QString caption() const override; - virtual void processMousePressEvent(QMouseEvent*) override; - virtual void showWindowMenu(const QRect &) override; - virtual void showWindowMenu(const QPoint &) override; - virtual void showApplicationMenu(const QPoint &) override; - virtual bool menuAvailable() const override; - virtual void performWindowOperation(WindowOperation) override; - virtual void setMask(const QRegion&, int) override; - virtual bool isPreview() const override; - virtual QRect geometry() const override; - virtual QRect iconGeometry() const override; - virtual QRegion unobscuredRegion(const QRegion& r) const override; - virtual WId windowId() const override; - virtual void closeWindow() override; - virtual void maximize(MaximizeMode mode) override; - virtual void minimize() override; - virtual void showContextHelp() override; - virtual void setDesktop(int desktop) override; - virtual void titlebarDblClickOperation() override; - virtual void titlebarMouseWheelOperation(int delta) override; - virtual void setShade(bool set) override; - virtual void setKeepAbove(bool) override; - virtual void setKeepBelow(bool) override; - virtual int currentDesktop() const override; - virtual Qt::WindowFlags initialWFlags() const override; - virtual void grabXServer(bool grab) override; - - virtual bool compositingActive() const override; - virtual QRect transparentRect() const override; - - virtual void update(const QRegion ®ion) override; - virtual QPalette palette() const override; - - // Window tabbing - virtual QString caption(int idx) const override; - virtual void closeTab(long id) override; - virtual void closeTabGroup() override; - virtual long currentTabId() const override; - virtual QIcon icon(int idx) const override; - virtual void setCurrentTab(long id) override; - virtual void showWindowMenu(const QPoint &, long id) override; - virtual void tab_A_before_B(long A, long B) override; - virtual void tab_A_behind_B(long A, long B) override; - virtual int tabCount() const override; - virtual long tabId(int idx) const override; - virtual void untab(long id, const QRect& newGeom) override; - virtual WindowOperation buttonToWindowOperation(Qt::MouseButtons button) override; - -private: - KDecorationPreview* preview; - PreviewItem *m_previewItem; - bool active; -}; - -class KDecorationPreviewOptions - : public KDecorationOptions -{ -public: - KDecorationPreviewOptions(); - virtual ~KDecorationPreviewOptions(); - void updateSettings(); - - void setCustomBorderSize(BorderSize size); - void setCustomTitleButtonsEnabled(bool enabled); - void setCustomTitleButtons(const QList &left, const QList &right); - -private: - BorderSize customBorderSize; - bool customButtonsChanged; - bool customButtons; - QList customTitleButtonsLeft; - QList customTitleButtonsRight; -}; - -class KDecorationPreviewPlugins - : public KDecorationPlugins -{ -public: - explicit KDecorationPreviewPlugins(const KSharedConfigPtr &cfg); - virtual bool provides(Requirement); -}; - -inline KDecorationPreviewPlugins::KDecorationPreviewPlugins(const KSharedConfigPtr &cfg) - : KDecorationPlugins(cfg) -{ -} - -#endif diff --git a/kcmkwin/kwindecoration/qml/AuroraeDecoration.qml b/kcmkwin/kwindecoration/qml/AuroraeDecoration.qml deleted file mode 100644 index 72513d6791..0000000000 --- a/kcmkwin/kwindecoration/qml/AuroraeDecoration.qml +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************** -Copyright (C) 2012 Martin Gräßlin - -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 . -*********************************************************************/ -import QtQuick 2.0 - -Item { - property alias active: decoration.active - property alias source: auroraeLoader.source - QtObject { - signal configChanged - id: decoration - property bool active: false - property string caption: display - property int desktop: 1 - property variant icon: "xorg" - property bool closeable: true - property bool maximizeable: true - property bool minimizeable: true - property bool modal: false - property bool moveable: true - property bool onAllDesktops: false - property bool preview: true - property bool resizeable: true - property bool setShade: false - property bool shade: false - property bool shadeable: false - property bool keepAbove: false - property bool keepBelow: false - property bool maximized: false - property bool providesContextHelp: true - property bool appMenu: true - property string leftButtons: "MS" - property string rightButtons: "HIA__X" - function titleMouseMoved() {} - function readConfig(key, defaultValue) { - if (key == "BorderSize") { - return borderSize; - } else if (key == "ButtonSize") { - return buttonSize; - } else { - return decorationBaseModel.readConfig(auroraeThemeName, key, defaultValue); - } - } - // just to not cause warnings - signal buttonsChanged() - signal fontChanged() - } - Loader { - id: auroraeLoader - anchors.fill: parent - } - Connections { - target: decorationBaseModel - onConfigChanged: { - if (auroraeThemeName == themeName) { - decoration.configChanged(); - } - } - } -} diff --git a/kcmkwin/kwindecoration/qml/AuroraePreview.qml b/kcmkwin/kwindecoration/qml/AuroraePreview.qml deleted file mode 100644 index 32e9f5ca62..0000000000 --- a/kcmkwin/kwindecoration/qml/AuroraePreview.qml +++ /dev/null @@ -1,52 +0,0 @@ -/******************************************************************** -Copyright (C) 2012 Martin Gräßlin - -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 . -*********************************************************************/ -import QtQuick 2.0 -import org.kde.kwin.aurorae 0.1 - -Item { - id: aurorae - AuroraeTheme { - id: auroraeTheme - Component.onCompleted: { - auroraeTheme.loadTheme(auroraeThemeName); - inactiveAurorae.source = auroraeSource; - activeAurorae.source = auroraeSource; - } - } - AuroraeDecoration { - id: inactiveAurorae - active: false - anchors { - fill: parent - leftMargin: 40 - auroraeTheme.paddingLeft - rightMargin: 10 - auroraeTheme.paddingRight - topMargin: 10 - auroraeTheme.paddingTop - bottomMargin: 40 - auroraeTheme.paddingBottom - } - } - AuroraeDecoration { - id: activeAurorae - active: true - anchors { - fill: parent - leftMargin: 10 - auroraeTheme.paddingLeft - rightMargin: 40 - auroraeTheme.paddingRight - topMargin: 40 - auroraeTheme.paddingTop - bottomMargin: 10 - auroraeTheme.paddingBottom - } - } -} diff --git a/kcmkwin/kwindecoration/qml/DecorationPreview.qml b/kcmkwin/kwindecoration/qml/DecorationPreview.qml deleted file mode 100644 index 20185f4e55..0000000000 --- a/kcmkwin/kwindecoration/qml/DecorationPreview.qml +++ /dev/null @@ -1,47 +0,0 @@ -/******************************************************************** -Copyright (C) 2012 Martin Gräßlin - -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 . -*********************************************************************/ -import QtQuick 2.0 - -Item { - id: decorationPreview - AuroraeDecoration { - id: inactiveDecoration - active: false - anchors { - fill: parent - leftMargin: 40 - rightMargin: 10 - topMargin: 10 - bottomMargin: 40 - } - } - AuroraeDecoration { - id: activeDecoration - active: true - anchors { - fill: parent - leftMargin: 10 - rightMargin: 40 - topMargin: 40 - bottomMargin: 10 - } - } - Component.onCompleted: { - inactiveDecoration.source = mainScript; - activeDecoration.source = mainScript; - } -} diff --git a/kcmkwin/kwindecoration/qml/main.qml b/kcmkwin/kwindecoration/qml/main.qml index d209bdd79a..0eb3faba10 100644 --- a/kcmkwin/kwindecoration/qml/main.qml +++ b/kcmkwin/kwindecoration/qml/main.qml @@ -1,63 +1,85 @@ -/******************************************************************** -Copyright (C) 2012 Martin Gräßlin -Copyright (C) 2012 Nuno Pinheiro +/* + * Copyright 2014 Martin Gräßlin + * + * 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.1 +import QtQuick.Controls 1.2 +import org.kde.kwin.private.kdecoration 1.0 as KDecoration -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 . -*********************************************************************/ -import QtQuick 2.0 -import org.kde.kwin.kcmdecoration 0.1 - -ListView { - id: listView - x: 0 - y: 0 - model: decorationModel - highlight: Rectangle { - width: listView.width - height: 150 - color: highlightColor - opacity: 0.5 - } - highlightMoveDuration: 250 - boundsBehavior: Flickable.StopAtBounds - delegate: Item { - objectName: "decorationItem" - width: listView.width - height: 150 - PreviewItem { - id: preview - anchors.fill: parent - visible: type == 0 - Component.onCompleted: { - if (type == 0) { - preview.library = model.library; +ScrollView { + ListView { + id: listView + objectName: "listView" + model: decorationsModel + highlight: Rectangle { + width: listView.width + height: 150 + color: highlightColor + opacity: 0.5 + } + highlightMoveDuration: 250 + boundsBehavior: Flickable.StopAtBounds + delegate: Item { + width: listView.width + height: 150 + KDecoration.Bridge { + id: bridgeItem + plugin: model["plugin"] + theme: model["theme"] + } + KDecoration.Settings { + id: settingsItem + bridge: bridgeItem + } + KDecoration.Decoration { + id: inactivePreview + bridge: bridgeItem + settings: settingsItem + anchors.fill: parent + Component.onCompleted: { + client.caption = Qt.binding(function() { return model["display"]; }); + client.active = false; + anchors.leftMargin = Qt.binding(function() { return 40 - (inactivePreview.decoration.shadow ? inactivePreview.decoration.shadow.paddingLeft : 0);}); + anchors.rightMargin = Qt.binding(function() { return 10 - (inactivePreview.decoration.shadow ? inactivePreview.decoration.shadow.paddingRight : 0);}); + anchors.topMargin = Qt.binding(function() { return 10 - (inactivePreview.decoration.shadow ? inactivePreview.decoration.shadow.paddingTop : 0);}); + anchors.bottomMargin = Qt.binding(function() { return 40 - (inactivePreview.decoration.shadow ? inactivePreview.decoration.shadow.paddingBottom : 0);}); } } - } - Loader { - source: type == 1 ? "AuroraePreview.qml" : "" - anchors.fill: parent - } - Loader { - source: type == 2 ? "DecorationPreview.qml" : "" - anchors.fill: parent - } - MouseArea { - hoverEnabled: false - anchors.fill: parent - onClicked: { - listView.currentIndex = index; + KDecoration.Decoration { + id: activePreview + bridge: bridgeItem + settings: settingsItem + anchors.fill: parent + Component.onCompleted: { + client.caption = Qt.binding(function() { return model["display"]; }); + client.active = true; + anchors.leftMargin = Qt.binding(function() { return 10 - (activePreview.decoration.shadow ? activePreview.decoration.shadow.paddingLeft : 0);}); + anchors.rightMargin = Qt.binding(function() { return 40 - (activePreview.decoration.shadow ? activePreview.decoration.shadow.paddingRight : 0);}); + anchors.topMargin = Qt.binding(function() { return 40 - (activePreview.decoration.shadow ? activePreview.decoration.shadow.paddingTop : 0);}); + anchors.bottomMargin = Qt.binding(function() { return 10 - (activePreview.decoration.shadow ? activePreview.decoration.shadow.paddingBottom : 0);}); + } + } + MouseArea { + hoverEnabled: false + anchors.fill: parent + onClicked: { + listView.currentIndex = index; + } } } }