[kcmkwin/kwindecoration] Import a new decoration configuration module

Following features are supported:
* finds all plugins
** finds all themes for a theme-engine plugin
* renders previews for the plugin/themes
* loads currently used plugin/theme
* saves selected plugin/theme
* triggers config reload in KWin

Following features are currently not supported:
* Search
* Plugin configuration
* GHNS
* Button configuration
This commit is contained in:
Martin Gräßlin 2014-10-31 07:53:04 +01:00
parent fcec334b3c
commit 8dd0a8163f
26 changed files with 2476 additions and 2285 deletions

View file

@ -22,6 +22,7 @@ find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
Core
DBus
Quick
QuickWidgets
Script
UiTools
Widgets

View file

@ -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)

View file

@ -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 )

View file

@ -0,0 +1,51 @@
/*
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "plugin.h"
#include "previewbridge.h"
#include "previewclient.h"
#include "previewitem.h"
#include "previewsettings.h"
#include <KDecoration2/Decoration>
#include <KDecoration2/DecorationShadow>
#include <qqml.h>
namespace KDecoration2
{
namespace Preview
{
void Plugin::registerTypes(const char *uri)
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("org.kde.kwin.private.kdecoration"));
qmlRegisterType<KDecoration2::Preview::PreviewBridge>(uri, 1, 0, "Bridge");
qmlRegisterType<KDecoration2::Preview::Settings>(uri, 1, 0, "Settings");
qmlRegisterType<KDecoration2::Preview::PreviewItem>(uri, 1, 0, "Decoration");
qmlRegisterType<KDecoration2::Preview::PreviewClient>();
qmlRegisterType<KDecoration2::Decoration>();
qmlRegisterType<KDecoration2::DecorationShadow>();
}
}
}
#include "plugin.moc"

View file

@ -0,0 +1,41 @@
/*
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef KDECOARTIONS_PREVIEW_PLUGIN_H
#define KDECOARTIONS_PREVIEW_PLUGIN_H
#include <QQmlExtensionPlugin>
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

View file

@ -0,0 +1,165 @@
/*
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "previewbridge.h"
#include "previewclient.h"
#include "previewitem.h"
#include "previewsettings.h"
#include <KDecoration2/DecoratedClient>
#include <KDecoration2/Decoration>
#include <KPluginLoader>
#include <KPluginFactory>
#include <KPluginTrader>
#include <QDebug>
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<DecoratedClientPrivate> PreviewBridge::createClient(DecoratedClient *client, Decoration *decoration)
{
auto ptr = std::unique_ptr<PreviewClient>(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<DecorationSettingsPrivate> PreviewBridge::settings(DecorationSettings *parent)
{
auto ptr = std::unique_ptr<PreviewSettings>(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<KDecoration2::Decoration>(parent, QVariantList({args}));
}
}
}

View file

@ -0,0 +1,92 @@
/*
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef KDECOARTIONS_PREVIEW_BRIDGE_H
#define KDECOARTIONS_PREVIEW_BRIDGE_H
#include <KDecoration2/Private/DecorationBridge>
#include <QList>
#include <QPointer>
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<DecoratedClientPrivate> createClient(DecoratedClient *client, Decoration *decoration) override;
void update(Decoration* decoration, const QRect& geometry) override;
std::unique_ptr<DecorationSettingsPrivate> 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<PreviewItem*> m_previewItems;
QString m_plugin;
QString m_theme;
QPointer<KPluginFactory> m_factory;
bool m_valid;
};
}
}
Q_DECLARE_METATYPE(KDecoration2::Preview::PreviewBridge *)
#endif

View file

@ -0,0 +1,463 @@
/*
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "previewclient.h"
#include <KDecoration2/Decoration>
#include <KDecoration2/DecoratedClient>
#include <KColorScheme>
#include <KColorSchemeManager>
#include <QDebug>
#include <QModelIndex>
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

View file

@ -0,0 +1,212 @@
/*
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef KDECOARTIONS_PREVIEW_CLIENT_H
#define KDECOARTIONS_PREVIEW_CLIENT_H
#include <KDecoration2/Private/DecoratedClientPrivate>
#include <QObject>
#include <QPalette>
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

View file

@ -0,0 +1,374 @@
/*
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "previewitem.h"
#include "previewbridge.h"
#include "previewsettings.h"
#include "previewclient.h"
#include <KDecoration2/Decoration>
#include <KDecoration2/DecorationSettings>
#include <KDecoration2/DecorationShadow>
#include <KDecoration2/DecoratedClient>
#include <QCursor>
#include <QPainter>
#include <QQmlContext>
#include <QQmlEngine>
#include <QDebug>
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<void (QQuickItem::*)()>(&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);
}
}
}

View file

@ -0,0 +1,100 @@
/*
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef KDECOARTIONS_PREVIEW_ITEM_H
#define KDECOARTIONS_PREVIEW_ITEM_H
#include <QQuickPaintedItem>
#include <QPointer>
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<KDecoration2::Preview::PreviewBridge> m_bridge;
QPointer<KDecoration2::Preview::Settings> m_settings;
QPointer<KDecoration2::Preview::PreviewClient> m_client;
};
} // Preview
} // KDecoration2
#endif

View file

@ -0,0 +1,325 @@
/*
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "previewsettings.h"
#include "previewbridge.h"
#include <QFontDatabase>
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<int, QByteArray> 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<BorderSize>(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<int, QByteArray> 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>({
DecorationButtonType::Menu,
DecorationButtonType::OnAllDesktops
}), this))
, m_rightButtons(new ButtonsModel(QList<DecorationButtonType>({
DecorationButtonType::QuickHelp,
DecorationButtonType::Minimize,
DecorationButtonType::Maximize,
DecorationButtonType::Close
}), this))
, m_availableButtons(new ButtonsModel(QList<DecorationButtonType>({
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<DecorationButtonType>());
}
void PreviewSettings::addButtonToRight(int row)
{
QModelIndex index = m_availableButtons->index(row);
if (!index.isValid()) {
return;
}
m_rightButtons->add(index.data(Qt::UserRole).value<DecorationButtonType>());
}
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<BorderSize>();
}
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<KDecoration2::DecorationSettings>::create(m_bridge.data());
}
emit settingsChanged();
}
QSharedPointer<DecorationSettings> Settings::settings() const
{
return m_settings;
}
DecorationSettings *Settings::settingsPointer() const
{
return m_settings.data();
}
}
}

View file

@ -0,0 +1,184 @@
/*
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef KDECOARTIONS_PREVIEW_SETTINGS_H
#define KDECOARTIONS_PREVIEW_SETTINGS_H
#include <KDecoration2/Private/DecorationSettingsPrivate>
#include <KDecoration2/DecorationSettings>
#include <QObject>
#include <QAbstractListModel>
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<BorderSize> m_borders = QList<BorderSize>({
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<DecorationSettings> settings() const;
DecorationSettings *settingsPointer() const;
Q_SIGNALS:
void bridgeChanged();
void settingsChanged();
private:
void createSettings();
QPointer<PreviewBridge> m_bridge;
QSharedPointer<KDecoration2::DecorationSettings> m_settings;
};
}
}
#endif

View file

@ -0,0 +1,2 @@
module org.kde.kwin.private.kdecoration
plugin kdecorationprivatedeclarative

View file

@ -1,370 +1,164 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2009 Martin Gräßlin <mgraesslin@kde.org>
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 <http://www.gnu.org/licenses/>.
*********************************************************************/
/*
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "decorationmodel.h"
#include "preview.h"
// kwin
#include <kdecorationfactory.h>
// Qt
#include <QDir>
#include <QFileInfo>
#include <QApplication>
#include <QStandardPaths>
// KDecoration2
#include <KDecoration2/DecorationSettings>
#include <KDecoration2/Decoration>
// KDE
#include <KConfigGroup>
#include <KDesktopFile>
#include <KLocalizedString>
#include <KServiceTypeTrader>
#include <KPluginInfo>
#include <KPluginLoader>
#include <KPluginFactory>
#include <KPluginTrader>
#include "kwindecoration.h"
// Qt
#include <QDebug>
/* 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<int, QByteArray> 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<int, QByteArray> 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<QObject> themeFinder(factory->create<QObject>(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<KDecorationDefines::DecorationButton> &left, const QList<KDecorationDefines::DecorationButton> &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

View file

@ -1,139 +1,59 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
/*
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef KDECORATION_DECORATIONS_MODEL_H
#define KDECORATION_DECORATIONS_MODEL_H
Copyright (C) 2009 Martin Gräßlin <mgraesslin@kde.org>
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 <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_DECORATIONMODEL_H
#define KWIN_DECORATIONMODEL_H
#include <QAbstractListModel>
#include <QPixmap>
#include <KConfig>
#include <KSharedConfig>
#include <kdecoration.h>
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<KDecorationDefines::DecorationButton>& left, const QList<KDecorationDefines::DecorationButton>& 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<DecorationModelData> m_decorations;
KDecorationPlugins* m_plugins;
KDecorationPreview* m_preview;
bool m_customButtons;
KSharedConfigPtr m_config;
QScopedPointer<KDecorationPreviewOptions> m_options;
struct Data {
QString pluginName;
QString themeName;
QString visibleName;
};
std::vector<Data> m_plugins;
};
} // namespace KWin
}
}
#endif // KWIN_DECORATIONMODEL_H
#endif

View file

@ -0,0 +1,128 @@
/*
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "kcm.h"
#include "decorationmodel.h"
// KDE
#include <KConfigGroup>
#include <KPluginFactory>
#include <KSharedConfig>
// Qt
#include <QDBusConnection>
#include <QDBusMessage>
#include <QQmlContext>
#include <QQmlEngine>
#include <QQuickItem>
#include <QQuickWidget>
#include <QStandardPaths>
#include <QVBoxLayout>
K_PLUGIN_FACTORY(KDecorationFactory,
registerPlugin<KDecoration2::Configuration::ConfigurationModule>();
)
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<QQuickItem*>("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<QQuickItem*>("listView")) {
listView->setProperty("currentIndex", index.isValid() ? index.row() : -1);
}
KCModule::load();
}
void ConfigurationModule::save()
{
if (auto listView = m_view->rootObject()->findChild<QQuickItem*>("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<QQuickItem*>("listView")) {
const QModelIndex index = m_model->findDecoration(s_defaultPlugin);
listView->setProperty("currentIndex", index.isValid() ? index.row() : -1);
}
KCModule::defaults();
}
}
}
#include "kcm.moc"

View file

@ -0,0 +1,61 @@
/*
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef KDECORATIONS_KCM_H
#define KDECORATIONS_KCM_H
#include <kcmodule.h>
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

View file

@ -1,600 +0,0 @@
/*
This is the new kwindecoration kcontrol module
Copyright (c) 2001
Karol Szwed <gallium@kde.org>
http://gallium.n3.net/
Copyright 2009, 2010 Martin Gräßlin <mgraesslin@kde.org>
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) <rik@kde.org>
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 <QtDBus/QtDBus>
#include <QSortFilterProxyModel>
#include <QScrollBar>
#include <QUiLoader>
#include <QtCore/QStandardPaths>
#include <QQmlContext>
#include <QQuickItem>
#include <QQuickView>
// KDE
#include <KAboutData>
#include <kconfigloader.h>
#include <KLocalizedString>
#include <KLocalizedTranslator>
#include <KMessageBox>
#include <KNewStuff3/KNS3/DownloadDialog>
#include <KConfigDialogManager>
#include <KPluginFactory>
// KCModule plugin interface
// =========================
K_PLUGIN_FACTORY(KWinDecoFactory,
registerPlugin<KWin::KWinDecorationModule>();
)
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<Aurorae::AuroraeTheme>("org.kde.kwin.aurorae", 0, 1, "AuroraeTheme");
qmlRegisterType<PreviewItem>("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("<h1>Installation error</h1>"
"The resource<h2>kwin/kcm_kwindecoration/main.qml</h2>could not be located in any application data path."
"<h2>Please contact your distribution</h2>"
"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<int>(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("<h1>Window Manager Decoration</h1>"
"<p>This module allows you to choose the window border decorations, "
"as well as titlebar button positions and custom decoration options.</p>"
"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."
"<p>You can configure each theme. There are different options specific for each theme.</p>"
"<p>On the \"Buttons\" tab check the \"Use custom titlebar button positions\" box "
"and you can change the positions of the buttons to your liking.</p>");
}
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<KNS3::DownloadDialog> 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<QDialog> 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<KDecorationDefines::BorderSize>(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<QKeyEvent*>(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<QObject*>("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<QWheelEvent*>(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<KDecorationDefines::DecorationButton> &DecorationButtons::leftButtons() const
{
return m_leftButtons;
}
const QList<KDecorationDefines::DecorationButton> &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<DecorationButton> &leftButtons)
{
if (m_leftButtons == leftButtons) {
return;
}
m_leftButtons = leftButtons;
emit leftButtonsChanged();
}
void DecorationButtons::setRightButtons(const QList<DecorationButton> &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"

View file

@ -1,143 +0,0 @@
/*
This is the new kwindecoration kcontrol module
Copyright (c) 2001
Karol Szwed <gallium@kde.org>
http://gallium.n3.net/
Copyright 2009, 2010 Martin Gräßlin <mgraesslin@kde.org>
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) <rik@kde.org>
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 <kcmodule.h>
#include <KSharedConfig>
#include <kdecoration.h>
#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<DecorationButton> &leftButtons() const;
const QList<DecorationButton> &rightButtons() const;
void setCustomPositions(bool set);
void setLeftButtons(const QList<KDecorationDefines::DecorationButton> &buttons);
void setRightButtons(const QList<KDecorationDefines::DecorationButton> &buttons);
public Q_SLOTS:
void resetToDefaults();
Q_SIGNALS:
void customPositionsChanged();
void leftButtonsChanged();
void rightButtonsChanged();
private:
bool m_customPositions;
QList<DecorationButton> m_leftButtons;
QList<DecorationButton> 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<QQuickView> m_listView;
KLocalizedTranslator *m_translator;
};
} //namespace
#endif

View file

@ -1,630 +0,0 @@
/*
*
* Copyright (c) 2003 Lubos Lunak <l.lunak@kde.org>
* Copyright (c) 2013 Martin Gräßlin <mgraesslin@kde.org>
*
* 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 <KLocalizedString>
#include <kconfig.h>
#include <QApplication>
#include <QPainter>
#include <QMouseEvent>
#include <kdecorationfactory.h>
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<DecorationButton> &left, const QList<DecorationButton> &right)
{
customTitleButtonsLeft = left;
customTitleButtonsRight = right;
updateSettings();
}
bool KDecorationPreviewPlugins::provides(Requirement)
{
return false;
}
#include "preview.moc"

View file

@ -1,210 +0,0 @@
/*
*
* Copyright (c) 2003 Lubos Lunak <l.lunak@kde.org>
* Copyright (c) 2013 Martin Gräßlin <mgraesslin@kde.org>
*
* 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 <QWidget>
#include <QQuickPaintedItem>
#include <kdecoration.h>
#include <kdecorationbridge.h>
#include <kdecoration_plugins_p.h>
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<KDecorationPlugins> m_plugins;
QScopedPointer<KDecorationPreviewBridge> m_activeBridge;
QScopedPointer<KDecorationPreviewBridge> 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 &region) 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<DecorationButton> &left, const QList<DecorationButton> &right);
private:
BorderSize customBorderSize;
bool customButtonsChanged;
bool customButtons;
QList<DecorationButton> customTitleButtonsLeft;
QList<DecorationButton> customTitleButtonsRight;
};
class KDecorationPreviewPlugins
: public KDecorationPlugins
{
public:
explicit KDecorationPreviewPlugins(const KSharedConfigPtr &cfg);
virtual bool provides(Requirement);
};
inline KDecorationPreviewPlugins::KDecorationPreviewPlugins(const KSharedConfigPtr &cfg)
: KDecorationPlugins(cfg)
{
}
#endif

View file

@ -1,73 +0,0 @@
/********************************************************************
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
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 <http://www.gnu.org/licenses/>.
*********************************************************************/
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();
}
}
}
}

View file

@ -1,52 +0,0 @@
/********************************************************************
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
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 <http://www.gnu.org/licenses/>.
*********************************************************************/
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
}
}
}

View file

@ -1,47 +0,0 @@
/********************************************************************
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
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 <http://www.gnu.org/licenses/>.
*********************************************************************/
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;
}
}

View file

@ -1,63 +1,85 @@
/********************************************************************
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
Copyright (C) 2012 Nuno Pinheiro <nuno@oxygen-icons.org>
/*
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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 <http://www.gnu.org/licenses/>.
*********************************************************************/
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;
}
}
}
}