[kcmkwin/kwindecoration] Rewrite the KWin decorations settings as a ConfigModule
Summary: * Wrote new KCM based on KQuickAddons::ConfigModule. * Remade QMLs for Buttons and Themes tabs. * Updated bridge model code for new plugin lookup API (fixes warnings). * Fixed decoration shadow changing messing with the previews sizes. * Fixed button drag and drop issues (see D18104). * Fixed default settings button behavior and detection of settings changes. * Updated Get Hot New Stuff. * Removed apply button in previewbridge.cpp: After applying changes, a theme's KCModule is invalidated. BUG: 389431 BUG: 350122 BUG: 346222 BUG: 342816 BUG: 397595 {F6574963} | {F6574962} | {F6574961} | {F6574960} Test Plan: * Verified saving and loading for every setting * Checked shadows of Breeze and Oxygen * Tested all possible drag&drop operations on both sides of the fake titlebar * Changed color schemes (with `kcmshell5 colors`) while showing the Themes tab to see if all previews update correctly their palettes * Tested on a fresh Neon-developer account, via kcmshell and systemsettings Reviewers: #vdg, abetts, ngraham, #kwin, davidedmundson Reviewed By: #vdg, #kwin, davidedmundson Subscribers: zzag, GB_2, ngraham, broulik, kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D18458
This commit is contained in:
parent
698b40dbbd
commit
8350c0f2ce
25 changed files with 1109 additions and 1048 deletions
|
@ -3,39 +3,28 @@ add_definitions(-DTRANSLATION_DOMAIN=\"kcmkwindecoration\")
|
|||
|
||||
add_subdirectory(declarative-plugin)
|
||||
|
||||
set(kcm_kwindecoration_PART_SRCS
|
||||
set(kcmkwindecoration_SRCS
|
||||
kcm.cpp
|
||||
utils.cpp
|
||||
decorationmodel.cpp
|
||||
declarative-plugin/buttonsmodel.cpp
|
||||
)
|
||||
|
||||
ki18n_wrap_ui(kcm_kwindecoration_PART_SRCS
|
||||
kcm.ui
|
||||
)
|
||||
add_library(kcm_kwindecoration MODULE ${kcmkwindecoration_SRCS})
|
||||
|
||||
add_library(kcm_kwindecoration MODULE ${kcm_kwindecoration_PART_SRCS})
|
||||
target_link_libraries(kcm_kwindecoration
|
||||
KDecoration2::KDecoration
|
||||
Qt5::DBus
|
||||
Qt5::Quick
|
||||
Qt5::QuickWidgets
|
||||
Qt5::UiTools
|
||||
KF5::Completion
|
||||
KF5::ConfigWidgets
|
||||
KF5::Declarative
|
||||
KF5::I18n
|
||||
KF5::QuickAddons
|
||||
KF5::NewStuff
|
||||
KF5::WindowSystem
|
||||
KF5::Service
|
||||
Qt5::Quick
|
||||
)
|
||||
install(TARGETS kcm_kwindecoration DESTINATION ${PLUGIN_INSTALL_DIR} )
|
||||
|
||||
########### install files ###############
|
||||
kcoreaddons_desktop_to_json(kcm_kwindecoration "kwindecoration.desktop" SERVICE_TYPES kcmodule.desktop)
|
||||
|
||||
install( FILES kwindecoration.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
|
||||
install( FILES
|
||||
qml/main.qml
|
||||
qml/Buttons.qml
|
||||
qml/ButtonGroup.qml
|
||||
qml/Previews.qml
|
||||
DESTINATION ${DATA_INSTALL_DIR}/kwin/kcm_kwindecoration)
|
||||
# This desktop file is installed only for retrocompatibility with sycoca
|
||||
install(FILES kwindecoration.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR})
|
||||
install(FILES window-decorations.knsrc DESTINATION ${KDE_INSTALL_CONFDIR})
|
||||
install(TARGETS kcm_kwindecoration DESTINATION ${KDE_INSTALL_PLUGINDIR}/kcms)
|
||||
|
||||
kpackage_install_package(package kcm_kwindecoration kcms)
|
||||
|
|
6
kcmkwin/kwindecoration/Messages.sh
Normal file → Executable file
6
kcmkwin/kwindecoration/Messages.sh
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!bin/sh
|
||||
$EXTRACTRC `find . -name \*.rc -o -name \*.ui -o -name \*.kcfg` >> rc.cpp
|
||||
$XGETTEXT `find . -name \*.qml -o -name \*.cpp -o -name \*.h` -o $podir/kcmkwindecoration.pot
|
||||
#! /usr/bin/env bash
|
||||
$EXTRACTRC `find . -name "*.ui"` >> rc.cpp || exit 11
|
||||
$XGETTEXT `find . -name "*.cpp" -o -name "*.qml"` -o $podir/kcmkwindecoration.pot
|
||||
rm -f rc.cpp
|
||||
|
|
|
@ -153,8 +153,8 @@ void ButtonsModel::add(DecorationButtonType type)
|
|||
|
||||
void ButtonsModel::add(int index, int type)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), index + 1, index+1);
|
||||
m_buttons.insert(index+1, KDecoration2::DecorationButtonType(type));
|
||||
beginInsertRows(QModelIndex(), index, index);
|
||||
m_buttons.insert(index, KDecoration2::DecorationButtonType(type));
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
|
@ -178,6 +178,24 @@ void ButtonsModel::move(int sourceIndex, int targetIndex)
|
|||
endMoveRows();
|
||||
}
|
||||
|
||||
void ButtonsModel::clear()
|
||||
{
|
||||
beginResetModel();
|
||||
m_buttons.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void ButtonsModel::replace(const QVector< DecorationButtonType > &buttons)
|
||||
{
|
||||
if (buttons.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
beginResetModel();
|
||||
m_buttons = buttons;
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,11 +45,13 @@ public:
|
|||
return m_buttons;
|
||||
}
|
||||
|
||||
Q_INVOKABLE void clear();
|
||||
Q_INVOKABLE void remove(int index);
|
||||
Q_INVOKABLE void up(int index);
|
||||
Q_INVOKABLE void down(int index);
|
||||
Q_INVOKABLE void move(int sourceIndex, int targetIndex);
|
||||
|
||||
void replace(const QVector< DecorationButtonType > &buttons);
|
||||
void add(DecorationButtonType type);
|
||||
Q_INVOKABLE void add(int index, int type);
|
||||
|
||||
|
|
|
@ -97,7 +97,6 @@ void PreviewBridge::setPlugin(const QString &plugin)
|
|||
return;
|
||||
}
|
||||
m_plugin = plugin;
|
||||
qDebug() << "Plugin changed to: " << m_plugin;
|
||||
emit pluginChanged();
|
||||
}
|
||||
|
||||
|
@ -123,22 +122,20 @@ QString PreviewBridge::plugin() const
|
|||
void PreviewBridge::createFactory()
|
||||
{
|
||||
m_factory.clear();
|
||||
|
||||
if (m_plugin.isNull()) {
|
||||
setValid(false);
|
||||
qDebug() <<"Plugin not set";
|
||||
qWarning() << "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;
|
||||
|
||||
const auto offers = KPluginTrader::self()->query(s_pluginName, s_pluginName);
|
||||
auto item = std::find_if(offers.constBegin(), offers.constEnd(), [this](const auto &plugin) { return plugin.pluginName() == m_plugin; });
|
||||
if (item != offers.constEnd()) {
|
||||
KPluginLoader loader(item->libraryPath());
|
||||
m_factory = loader.factory();
|
||||
}
|
||||
KPluginLoader loader(offers.first().libraryPath());
|
||||
m_factory = loader.factory();
|
||||
qDebug() << "Factory: " << !m_factory.isNull();
|
||||
|
||||
setValid(!m_factory.isNull());
|
||||
}
|
||||
|
||||
|
@ -212,22 +209,17 @@ void PreviewBridge::configure()
|
|||
|
||||
QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok |
|
||||
QDialogButtonBox::Cancel |
|
||||
QDialogButtonBox::Apply |
|
||||
QDialogButtonBox::RestoreDefaults |
|
||||
QDialogButtonBox::Reset,
|
||||
&dialog);
|
||||
|
||||
QPushButton *apply = buttons->button(QDialogButtonBox::Apply);
|
||||
QPushButton *reset = buttons->button(QDialogButtonBox::Reset);
|
||||
apply->setEnabled(false);
|
||||
reset->setEnabled(false);
|
||||
// Here we connect our buttons with the dialog
|
||||
connect(buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
|
||||
connect(buttons, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
|
||||
connect(apply, &QPushButton::clicked, this, save);
|
||||
connect(reset, &QPushButton::clicked, kcm, &KCModule::load);
|
||||
auto changedSignal = static_cast<void(KCModule::*)(bool)>(&KCModule::changed);
|
||||
connect(kcm, changedSignal, apply, &QPushButton::setEnabled);
|
||||
connect(kcm, changedSignal, reset, &QPushButton::setEnabled);
|
||||
connect(buttons->button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, kcm, &KCModule::defaults);
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#include <KDecoration2/Decoration>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
|
||||
namespace KDecoration2
|
||||
{
|
||||
|
@ -132,7 +132,17 @@ void PreviewButtonItem::paint(QPainter *painter)
|
|||
if (!m_button) {
|
||||
return;
|
||||
}
|
||||
m_button->paint(painter, QRect(0, 0, width(), height()));
|
||||
QRect size { 0, 0, (int)width(), (int)height() };
|
||||
m_button->paint(painter, size);
|
||||
painter->setCompositionMode(QPainter::CompositionMode_SourceAtop);
|
||||
painter->fillRect(size, m_color);
|
||||
}
|
||||
|
||||
void PreviewButtonItem::setColor(const QColor color)
|
||||
{
|
||||
m_color = color;
|
||||
m_color.setAlpha(127);
|
||||
update();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#define KDECOARTIONS_PREVIEW_BUTTON_ITEM_H
|
||||
|
||||
#include <QQuickPaintedItem>
|
||||
#include <QColor>
|
||||
#include <QPointer>
|
||||
#include <KDecoration2/DecorationButton>
|
||||
|
||||
|
@ -39,6 +40,7 @@ class PreviewButtonItem : public QQuickPaintedItem
|
|||
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(int type READ typeAsInt WRITE setType NOTIFY typeChanged)
|
||||
Q_PROPERTY(QColor color READ color WRITE setColor)
|
||||
|
||||
public:
|
||||
explicit PreviewButtonItem(QQuickItem *parent = nullptr);
|
||||
|
@ -56,6 +58,9 @@ public:
|
|||
void setType(KDecoration2::DecorationButtonType type);
|
||||
void setType(int type);
|
||||
|
||||
const QColor &color() const { return m_color; }
|
||||
void setColor(const QColor color);
|
||||
|
||||
Q_SIGNALS:
|
||||
void bridgeChanged();
|
||||
void typeChanged();
|
||||
|
@ -67,6 +72,7 @@ protected:
|
|||
private:
|
||||
void createButton();
|
||||
void syncGeometry();
|
||||
QColor m_color;
|
||||
QPointer<KDecoration2::Preview::PreviewBridge> m_bridge;
|
||||
QPointer<KDecoration2::Preview::Settings> m_settings;
|
||||
KDecoration2::Decoration *m_decoration = nullptr;
|
||||
|
|
|
@ -69,7 +69,6 @@ PreviewClient::PreviewClient(DecoratedClient *c, Decoration *decoration)
|
|||
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);
|
||||
|
@ -81,7 +80,6 @@ PreviewClient::PreviewClient(DecoratedClient *c, Decoration *decoration)
|
|||
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());
|
||||
|
@ -353,12 +351,11 @@ void PreviewClient::setBordersTopEdge(bool enabled)
|
|||
|
||||
void PreviewClient::requestShowToolTip(const QString &text)
|
||||
{
|
||||
qDebug() << "tooltip show requested with text:" << text;
|
||||
Q_UNUSED(text);
|
||||
}
|
||||
|
||||
void PreviewClient::requestHideToolTip()
|
||||
{
|
||||
qDebug() << "tooltip hide requested";
|
||||
}
|
||||
|
||||
void PreviewClient::requestClose()
|
||||
|
@ -368,7 +365,6 @@ void PreviewClient::requestClose()
|
|||
|
||||
void PreviewClient::requestContextHelp()
|
||||
{
|
||||
qDebug() << "context help requested";
|
||||
}
|
||||
|
||||
void PreviewClient::requestToggleMaximization(Qt::MouseButtons buttons)
|
||||
|
@ -431,7 +427,6 @@ void PreviewClient::name(type variable) \
|
|||
if (m_##variable == variable) { \
|
||||
return; \
|
||||
} \
|
||||
qDebug() << "Setting " << #variable << ":" << variable;\
|
||||
m_##variable = variable; \
|
||||
emit variable##Changed(m_##variable); \
|
||||
}
|
||||
|
|
|
@ -78,15 +78,9 @@ void PreviewItem::createDecoration()
|
|||
if (m_bridge.isNull() || m_settings.isNull() || m_decoration) {
|
||||
return;
|
||||
}
|
||||
m_decoration = m_bridge->createDecoration(0);
|
||||
if (!m_decoration) {
|
||||
return;
|
||||
}
|
||||
m_decoration->setProperty("visualParent", QVariant::fromValue(this));
|
||||
Decoration *decoration = m_bridge->createDecoration(0);
|
||||
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);
|
||||
setDecoration(decoration);
|
||||
}
|
||||
|
||||
Decoration *PreviewItem::decoration() const
|
||||
|
@ -96,41 +90,15 @@ Decoration *PreviewItem::decoration() const
|
|||
|
||||
void PreviewItem::setDecoration(Decoration *deco)
|
||||
{
|
||||
if (m_decoration == deco) {
|
||||
if (!deco || 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::sectionUnderMouseChanged, 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);
|
||||
}
|
||||
}
|
||||
);
|
||||
connect(m_decoration, &KDecoration2::Decoration::shadowChanged, this, &PreviewItem::shadowChanged);
|
||||
connect(m_decoration, &Decoration::bordersChanged, this, &PreviewItem::syncSize);
|
||||
connect(m_decoration, &Decoration::shadowChanged, this, &PreviewItem::syncSize);
|
||||
connect(m_decoration, &Decoration::shadowChanged, this, &PreviewItem::shadowChanged);
|
||||
emit decorationChanged(m_decoration);
|
||||
}
|
||||
|
||||
|
|
|
@ -60,14 +60,13 @@ QVariant DecorationsModel::data(const QModelIndex &index, int role) const
|
|||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return d.visibleName;
|
||||
case Qt::UserRole +4:
|
||||
case PluginNameRole:
|
||||
return d.pluginName;
|
||||
case Qt::UserRole +5:
|
||||
case ThemeNameRole:
|
||||
return d.themeName;
|
||||
case Qt::UserRole +6:
|
||||
case ConfigurationRole:
|
||||
return d.configuration;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
@ -75,9 +74,9 @@ QHash< int, QByteArray > DecorationsModel::roleNames() const
|
|||
{
|
||||
QHash<int, QByteArray> roles({
|
||||
{Qt::DisplayRole, QByteArrayLiteral("display")},
|
||||
{Qt::UserRole + 4, QByteArrayLiteral("plugin")},
|
||||
{Qt::UserRole + 5, QByteArrayLiteral("theme")},
|
||||
{Qt::UserRole +6, QByteArrayLiteral("configureable")}
|
||||
{PluginNameRole, QByteArrayLiteral("plugin")},
|
||||
{ThemeNameRole, QByteArrayLiteral("theme")},
|
||||
{ConfigurationRole, QByteArrayLiteral("configureable")}
|
||||
});
|
||||
return roles;
|
||||
}
|
||||
|
@ -134,8 +133,8 @@ void DecorationsModel::init()
|
|||
if (!metadata.isUndefined()) {
|
||||
const auto decoSettingsMap = metadata.toObject().toVariantMap();
|
||||
const QString &kns = findKNewStuff(decoSettingsMap);
|
||||
if (!kns.isEmpty()) {
|
||||
m_knsProvides.insert(kns, info.name().isEmpty() ? info.pluginName() : info.name());
|
||||
if (!kns.isEmpty() && !m_knsProviders.contains(kns)) {
|
||||
m_knsProviders.append(kns);
|
||||
}
|
||||
if (isThemeEngine(decoSettingsMap)) {
|
||||
const QString keyword = themeListKeyword(decoSettingsMap);
|
||||
|
@ -171,6 +170,7 @@ void DecorationsModel::init()
|
|||
Data data;
|
||||
data.pluginName = info.pluginName();
|
||||
data.visibleName = info.name().isEmpty() ? info.pluginName() : info.name();
|
||||
data.themeName = data.visibleName;
|
||||
data.configuration = config;
|
||||
|
||||
m_plugins.emplace_back(std::move(data));
|
||||
|
|
|
@ -31,6 +31,13 @@ namespace Configuration
|
|||
class DecorationsModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum DecorationRole {
|
||||
PluginNameRole = Qt::UserRole + 1,
|
||||
ThemeNameRole,
|
||||
ConfigurationRole,
|
||||
};
|
||||
|
||||
public:
|
||||
explicit DecorationsModel(QObject *parent = nullptr);
|
||||
virtual ~DecorationsModel();
|
||||
|
@ -41,8 +48,8 @@ public:
|
|||
|
||||
QModelIndex findDecoration(const QString &pluginName, const QString &themeName = QString()) const;
|
||||
|
||||
QMap<QString, QString> knsProviders() const {
|
||||
return m_knsProvides;
|
||||
QStringList knsProviders() const {
|
||||
return m_knsProviders;
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
|
@ -56,7 +63,7 @@ private:
|
|||
bool configuration = false;
|
||||
};
|
||||
std::vector<Data> m_plugins;
|
||||
QMap<QString, QString> m_knsProvides;
|
||||
QStringList m_knsProviders;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,432 +1,314 @@
|
|||
/*
|
||||
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
* Copyright (c) 2019 Valerio Pilo <vpilo@coldshock.net>
|
||||
*
|
||||
* 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 library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* You should have received a copy of the GNU Library General Public License
|
||||
* along with this library; see the file COPYING.LIB. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "kcm.h"
|
||||
#include "decorationmodel.h"
|
||||
#include "declarative-plugin/buttonsmodel.h"
|
||||
#include <config-kwin.h>
|
||||
|
||||
// KDE
|
||||
#include <KAboutData>
|
||||
#include <KConfigGroup>
|
||||
#include <KLocalizedString>
|
||||
#include <KPluginFactory>
|
||||
#include <KSharedConfig>
|
||||
#include <KDecoration2/DecorationButton>
|
||||
#include <KNewStuff3/KNS3/DownloadDialog>
|
||||
#include <kdeclarative/kdeclarative.h>
|
||||
// Qt
|
||||
#include <KNSCore/Engine>
|
||||
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusMessage>
|
||||
#include <QFontDatabase>
|
||||
#include <QMenu>
|
||||
#include <QQmlContext>
|
||||
#include <QQmlEngine>
|
||||
#include <QDebug>
|
||||
#include <QQuickItem>
|
||||
#include <QQuickView>
|
||||
#include <QQuickWindow>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QStandardPaths>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
K_PLUGIN_FACTORY(KDecorationFactory,
|
||||
registerPlugin<KDecoration2::Configuration::ConfigurationModule>();
|
||||
)
|
||||
#include <KNewStuff3/KNS3/DownloadDialog>
|
||||
|
||||
|
||||
K_PLUGIN_FACTORY_WITH_JSON(KCMKWinDecorationFactory, "kwindecoration.json", registerPlugin<KCMKWinDecoration>();)
|
||||
|
||||
Q_DECLARE_METATYPE(KDecoration2::BorderSize)
|
||||
|
||||
namespace KDecoration2
|
||||
{
|
||||
|
||||
namespace Configuration
|
||||
namespace
|
||||
{
|
||||
static const QString s_pluginName = QStringLiteral("org.kde.kdecoration2");
|
||||
const QString s_configFile { QStringLiteral("kwinrc") };
|
||||
const QString s_configGroup { QStringLiteral("org.kde.kdecoration2") };
|
||||
const QString s_configPlugin { QStringLiteral("library") };
|
||||
const QString s_configTheme { QStringLiteral("theme") };
|
||||
const QString s_configBorderSize { QStringLiteral("BorderSize") };
|
||||
const QString s_configCloseOnDoubleClickOnMenu { QStringLiteral("CloseOnDoubleClickOnMenu") };
|
||||
const QString s_configDecoButtonsOnLeft { QStringLiteral("ButtonsOnLeft") };
|
||||
const QString s_configDecoButtonsOnRight { QStringLiteral("ButtonsOnRight") };
|
||||
|
||||
const KDecoration2::BorderSize s_defaultBorderSize = KDecoration2::BorderSize::Normal;
|
||||
const bool s_defaultCloseOnDoubleClickOnMenu = false;
|
||||
|
||||
const DecorationButtonsList s_defaultDecoButtonsOnLeft {
|
||||
KDecoration2::DecorationButtonType::Menu,
|
||||
KDecoration2::DecorationButtonType::OnAllDesktops
|
||||
};
|
||||
const DecorationButtonsList s_defaultDecoButtonsOnRight {
|
||||
KDecoration2::DecorationButtonType::ContextHelp,
|
||||
KDecoration2::DecorationButtonType::Minimize,
|
||||
KDecoration2::DecorationButtonType::Maximize,
|
||||
KDecoration2::DecorationButtonType::Close
|
||||
};
|
||||
|
||||
#if HAVE_BREEZE_DECO
|
||||
static const QString s_defaultPlugin = QStringLiteral(BREEZE_KDECORATION_PLUGIN_ID);
|
||||
static const QString s_defaultTheme;
|
||||
const QString s_defaultPlugin { QStringLiteral(BREEZE_KDECORATION_PLUGIN_ID) };
|
||||
const QString s_defaultTheme { QStringLiteral("Breeze") };
|
||||
#else
|
||||
static const QString s_defaultPlugin = QStringLiteral("org.kde.kwin.aurorae");
|
||||
static const QString s_defaultTheme = QStringLiteral("kwin4_decoration_qml_plastik");
|
||||
const QString s_defaultPlugin { QStringLiteral("org.kde.kwin.aurorae") };
|
||||
const QString s_defaultTheme { QStringLiteral("kwin4_decoration_qml_plastik") };
|
||||
#endif
|
||||
static const QString s_borderSizeNormal = QStringLiteral("Normal");
|
||||
static const QString s_ghnsIcon = QStringLiteral("get-hot-new-stuff");
|
||||
|
||||
ConfigurationForm::ConfigurationForm(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
}
|
||||
|
||||
static bool s_loading = false;
|
||||
|
||||
ConfigurationModule::ConfigurationModule(QWidget *parent, const QVariantList &args)
|
||||
: KCModule(parent, args)
|
||||
, m_model(new DecorationsModel(this))
|
||||
, m_proxyModel(new QSortFilterProxyModel(this))
|
||||
, m_ui(new ConfigurationForm(this))
|
||||
, m_leftButtons(new Preview::ButtonsModel(QVector<DecorationButtonType>(), this))
|
||||
, m_rightButtons(new Preview::ButtonsModel(QVector<DecorationButtonType>(), this))
|
||||
, m_availableButtons(new Preview::ButtonsModel(this))
|
||||
KCMKWinDecoration::KCMKWinDecoration(QObject *parent, const QVariantList &arguments)
|
||||
: KQuickAddons::ConfigModule(parent, arguments)
|
||||
, m_themesModel(new KDecoration2::Configuration::DecorationsModel(this))
|
||||
, m_proxyThemesModel(new QSortFilterProxyModel(this))
|
||||
, m_leftButtonsModel(new KDecoration2::Preview::ButtonsModel(DecorationButtonsList(), this))
|
||||
, m_rightButtonsModel(new KDecoration2::Preview::ButtonsModel(DecorationButtonsList(), this))
|
||||
, m_availableButtonsModel(new KDecoration2::Preview::ButtonsModel(this))
|
||||
, m_savedSettings{ s_defaultBorderSize, -2 /* for setTheme() */, false, s_defaultDecoButtonsOnLeft, s_defaultDecoButtonsOnRight }
|
||||
, m_currentSettings(m_savedSettings)
|
||||
{
|
||||
m_proxyModel->setSourceModel(m_model);
|
||||
m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_proxyModel->sort(0);
|
||||
connect(m_ui->filter, &QLineEdit::textChanged, m_proxyModel, &QSortFilterProxyModel::setFilterFixedString);
|
||||
auto about = new KAboutData(QStringLiteral("kcm_kwindecoration"),
|
||||
i18n("Configure window titlebars and borders"),
|
||||
QStringLiteral("1.0"),
|
||||
QString(),
|
||||
KAboutLicense::GPL);
|
||||
about->addAuthor(i18n("Valerio Pilo"),
|
||||
i18n("Author"),
|
||||
QStringLiteral("vpilo@coldshock.net"));
|
||||
setAboutData(about);
|
||||
|
||||
m_quickView = new QQuickView(0);
|
||||
KDeclarative::KDeclarative kdeclarative;
|
||||
kdeclarative.setDeclarativeEngine(m_quickView->engine());
|
||||
kdeclarative.setTranslationDomain(QStringLiteral(TRANSLATION_DOMAIN));
|
||||
kdeclarative.setupContext();
|
||||
kdeclarative.setupEngine(m_quickView->engine());
|
||||
qmlRegisterType<QAbstractListModel>();
|
||||
qmlRegisterType<QSortFilterProxyModel>();
|
||||
|
||||
qmlRegisterType<QAbstractItemModel>();
|
||||
QWidget *widget = QWidget::createWindowContainer(m_quickView, this);
|
||||
QVBoxLayout* layout = new QVBoxLayout(m_ui->view);
|
||||
layout->setContentsMargins(0,0,0,0);
|
||||
layout->addWidget(widget);
|
||||
m_proxyThemesModel->setSourceModel(m_themesModel);
|
||||
m_proxyThemesModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_proxyThemesModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
m_proxyThemesModel->sort(0);
|
||||
|
||||
m_quickView->rootContext()->setContextProperty(QStringLiteral("decorationsModel"), m_proxyModel);
|
||||
updateColors();
|
||||
m_quickView->rootContext()->setContextProperty("_borderSizesIndex", 3); // 3 is normal
|
||||
m_quickView->rootContext()->setContextProperty("leftButtons", m_leftButtons);
|
||||
m_quickView->rootContext()->setContextProperty("rightButtons", m_rightButtons);
|
||||
m_quickView->rootContext()->setContextProperty("availableButtons", m_availableButtons);
|
||||
m_quickView->rootContext()->setContextProperty("initialThemeIndex", -1);
|
||||
connect(m_leftButtonsModel, &QAbstractItemModel::rowsInserted, this, &KCMKWinDecoration::updateNeedsSave);
|
||||
connect(m_leftButtonsModel, &QAbstractItemModel::rowsMoved, this, &KCMKWinDecoration::updateNeedsSave);
|
||||
connect(m_leftButtonsModel, &QAbstractItemModel::rowsRemoved, this, &KCMKWinDecoration::updateNeedsSave);
|
||||
connect(m_leftButtonsModel, &QAbstractItemModel::modelReset, this, &KCMKWinDecoration::updateNeedsSave);
|
||||
connect(m_rightButtonsModel, &QAbstractItemModel::rowsInserted, this, &KCMKWinDecoration::updateNeedsSave);
|
||||
connect(m_rightButtonsModel, &QAbstractItemModel::rowsMoved, this, &KCMKWinDecoration::updateNeedsSave);
|
||||
connect(m_rightButtonsModel, &QAbstractItemModel::rowsRemoved, this, &KCMKWinDecoration::updateNeedsSave);
|
||||
connect(m_rightButtonsModel, &QAbstractItemModel::modelReset, this, &KCMKWinDecoration::updateNeedsSave);
|
||||
|
||||
m_quickView->rootContext()->setContextProperty("titleFont", QFontDatabase::systemFont(QFontDatabase::TitleFont));
|
||||
m_quickView->setResizeMode(QQuickView::SizeRootObjectToView);
|
||||
m_quickView->setSource(QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kwin/kcm_kwindecoration/main.qml"))));
|
||||
if (m_quickView->status() == QQuickView::Ready) {
|
||||
auto listView = m_quickView->rootObject()->findChild<QQuickItem*>("listView");
|
||||
if (listView) {
|
||||
connect(listView, SIGNAL(userChangedSelection()), this, SLOT(changed()));
|
||||
// Update the themes when the color scheme or a theme's settings change
|
||||
QDBusConnection::sessionBus()
|
||||
.connect(QString(), QStringLiteral("/KWin"), QStringLiteral("org.kde.KWin"), QStringLiteral("reloadConfig"),
|
||||
this,
|
||||
SLOT(reloadKWinSettings()));
|
||||
|
||||
QMetaObject::invokeMethod(m_themesModel, "init", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void KCMKWinDecoration::reloadKWinSettings()
|
||||
{
|
||||
QMetaObject::invokeMethod(m_themesModel, "init", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void KCMKWinDecoration::getNewStuff(QQuickItem *context)
|
||||
{
|
||||
if (!m_newStuffDialog) {
|
||||
m_newStuffDialog = new KNS3::DownloadDialog(QStringLiteral("window-decorations.knsrc"));
|
||||
m_newStuffDialog->setWindowTitle(i18n("Download New Window Decorations"));
|
||||
m_newStuffDialog->setWindowModality(Qt::WindowModal);
|
||||
connect(m_newStuffDialog, &KNS3::DownloadDialog::accepted, this, &KCMKWinDecoration::load);
|
||||
}
|
||||
|
||||
if (context && context->window()) {
|
||||
m_newStuffDialog->winId(); // so it creates the windowHandle()
|
||||
m_newStuffDialog->windowHandle()->setTransientParent(context->window());
|
||||
}
|
||||
|
||||
m_newStuffDialog->show();
|
||||
}
|
||||
|
||||
void KCMKWinDecoration::load()
|
||||
{
|
||||
const KConfigGroup config = KSharedConfig::openConfig(s_configFile)->group(s_configGroup);
|
||||
|
||||
const QString plugin = config.readEntry(s_configPlugin, s_defaultPlugin);
|
||||
const QString theme = config.readEntry(s_configTheme, s_defaultTheme);
|
||||
int themeIndex = m_proxyThemesModel->mapFromSource(m_themesModel->findDecoration(plugin, theme)).row();
|
||||
if (themeIndex < 0) {
|
||||
qWarning() << "Plugin" << plugin << "and theme" << theme << "not found";
|
||||
} else {
|
||||
qDebug() << "Current theme: plugin" << plugin << "and theme" << theme;
|
||||
}
|
||||
setTheme(themeIndex);
|
||||
|
||||
setCloseOnDoubleClickOnMenu(config.readEntry(s_configCloseOnDoubleClickOnMenu, s_defaultCloseOnDoubleClickOnMenu));
|
||||
|
||||
const QString defaultSizeName = Utils::borderSizeToString(s_defaultBorderSize);
|
||||
setBorderSize(Utils::stringToBorderSize(config.readEntry(s_configBorderSize, defaultSizeName)));
|
||||
|
||||
m_leftButtonsModel->replace(Utils::readDecorationButtons(config, s_configDecoButtonsOnLeft, s_defaultDecoButtonsOnLeft));
|
||||
m_rightButtonsModel->replace(Utils::readDecorationButtons(config, s_configDecoButtonsOnRight, s_defaultDecoButtonsOnRight));
|
||||
m_currentSettings.buttonsOnLeft = m_leftButtonsModel->buttons();
|
||||
m_currentSettings.buttonsOnRight = m_rightButtonsModel->buttons();
|
||||
|
||||
m_savedSettings = m_currentSettings;
|
||||
|
||||
updateNeedsSave();
|
||||
}
|
||||
|
||||
void KCMKWinDecoration::save()
|
||||
{
|
||||
KConfigGroup config = KSharedConfig::openConfig(s_configFile)->group(s_configGroup);
|
||||
|
||||
if (m_currentSettings.themeIndex >= 0) {
|
||||
const QModelIndex index = m_proxyThemesModel->index(m_currentSettings.themeIndex, 0);
|
||||
if (index.isValid()) {
|
||||
const QString plugin = index.data(KDecoration2::Configuration::DecorationsModel::PluginNameRole).toString();
|
||||
const QString theme = index.data(KDecoration2::Configuration::DecorationsModel::ThemeNameRole).toString();
|
||||
config.writeEntry(s_configPlugin, plugin);
|
||||
config.writeEntry(s_configTheme, theme);
|
||||
qDebug() << "Saved theme: plugin" << plugin << "and theme" << theme;
|
||||
} else {
|
||||
qWarning() << "Cannot match theme index" << m_currentSettings.themeIndex << "in model";
|
||||
}
|
||||
}
|
||||
|
||||
m_ui->tabWidget->tabBar()->disconnect();
|
||||
auto setCurrentTab = [this](int index) {
|
||||
if (index == 0)
|
||||
m_ui->doubleClickMessage->hide();
|
||||
m_ui->filter->setVisible(index == 0);
|
||||
m_ui->knsButton->setVisible(index == 0);
|
||||
if (auto themeList = m_quickView->rootObject()->findChild<QQuickItem*>("themeList")) {
|
||||
themeList->setVisible(index == 0);
|
||||
}
|
||||
m_ui->borderSizesLabel->setVisible(index == 0);
|
||||
m_ui->borderSizesCombo->setVisible(index == 0);
|
||||
|
||||
m_ui->closeWindowsDoubleClick->setVisible(index == 1);
|
||||
if (auto buttonLayout = m_quickView->rootObject()->findChild<QQuickItem*>("buttonLayout")) {
|
||||
buttonLayout->setVisible(index == 1);
|
||||
}
|
||||
};
|
||||
connect(m_ui->tabWidget->tabBar(), &QTabBar::currentChanged, this, setCurrentTab);
|
||||
setCurrentTab(0);
|
||||
|
||||
m_ui->doubleClickMessage->setVisible(false);
|
||||
m_ui->doubleClickMessage->setText(i18n("Close by double clicking:\n To open the menu, keep the button pressed until it appears."));
|
||||
m_ui->doubleClickMessage->setCloseButtonVisible(true);
|
||||
m_ui->borderSizesCombo->setItemData(0, QVariant::fromValue(BorderSize::None));
|
||||
m_ui->borderSizesCombo->setItemData(1, QVariant::fromValue(BorderSize::NoSides));
|
||||
m_ui->borderSizesCombo->setItemData(2, QVariant::fromValue(BorderSize::Tiny));
|
||||
m_ui->borderSizesCombo->setItemData(3, QVariant::fromValue(BorderSize::Normal));
|
||||
m_ui->borderSizesCombo->setItemData(4, QVariant::fromValue(BorderSize::Large));
|
||||
m_ui->borderSizesCombo->setItemData(5, QVariant::fromValue(BorderSize::VeryLarge));
|
||||
m_ui->borderSizesCombo->setItemData(6, QVariant::fromValue(BorderSize::Huge));
|
||||
m_ui->borderSizesCombo->setItemData(7, QVariant::fromValue(BorderSize::VeryHuge));
|
||||
m_ui->borderSizesCombo->setItemData(8, QVariant::fromValue(BorderSize::Oversized));
|
||||
m_ui->knsButton->setIcon(QIcon::fromTheme(s_ghnsIcon));
|
||||
|
||||
auto changedSlot = static_cast<void (ConfigurationModule::*)()>(&ConfigurationModule::changed);
|
||||
connect(m_ui->closeWindowsDoubleClick, &QCheckBox::stateChanged, this, changedSlot);
|
||||
connect(m_ui->closeWindowsDoubleClick, &QCheckBox::toggled, this,
|
||||
[this] (bool toggled) {
|
||||
if (s_loading) {
|
||||
return;
|
||||
}
|
||||
if (toggled)
|
||||
m_ui->doubleClickMessage->animatedShow();
|
||||
else
|
||||
m_ui->doubleClickMessage->animatedHide();
|
||||
}
|
||||
);
|
||||
connect(m_ui->borderSizesCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this, [this] (int index) {
|
||||
auto listView = m_quickView->rootObject()->findChild<QQuickItem*>("listView");
|
||||
if (listView) {
|
||||
listView->setProperty("borderSizesIndex", index);
|
||||
}
|
||||
changed();
|
||||
}
|
||||
);
|
||||
connect(m_model, &QAbstractItemModel::modelReset, this,
|
||||
[this] {
|
||||
const auto &kns = m_model->knsProviders();
|
||||
m_ui->knsButton->setEnabled(!kns.isEmpty());
|
||||
if (kns.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (kns.count() > 1) {
|
||||
QMenu *menu = new QMenu(m_ui->knsButton);
|
||||
for (auto it = kns.begin(); it != kns.end(); ++it) {
|
||||
QAction *action = menu->addAction(QIcon::fromTheme(s_ghnsIcon), it.value());
|
||||
action->setData(it.key());
|
||||
connect(action, &QAction::triggered, this, [this, action] { showKNS(action->data().toString());});
|
||||
}
|
||||
m_ui->knsButton->setMenu(menu);
|
||||
}
|
||||
}
|
||||
);
|
||||
connect(m_ui->knsButton, &QPushButton::clicked, this,
|
||||
[this] {
|
||||
const auto &kns = m_model->knsProviders();
|
||||
if (kns.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
showKNS(kns.firstKey());
|
||||
}
|
||||
);
|
||||
connect(m_leftButtons, &QAbstractItemModel::rowsInserted, this, changedSlot);
|
||||
connect(m_leftButtons, &QAbstractItemModel::rowsMoved, this, changedSlot);
|
||||
connect(m_leftButtons, &QAbstractItemModel::rowsRemoved, this, changedSlot);
|
||||
connect(m_rightButtons, &QAbstractItemModel::rowsInserted, this, changedSlot);
|
||||
connect(m_rightButtons, &QAbstractItemModel::rowsMoved, this, changedSlot);
|
||||
connect(m_rightButtons, &QAbstractItemModel::rowsRemoved, this, changedSlot);
|
||||
|
||||
QVBoxLayout *l = new QVBoxLayout(this);
|
||||
l->addWidget(m_ui);
|
||||
QMetaObject::invokeMethod(m_model, "init", Qt::QueuedConnection);
|
||||
|
||||
m_ui->installEventFilter(this);
|
||||
}
|
||||
|
||||
ConfigurationModule::~ConfigurationModule() = default;
|
||||
|
||||
void ConfigurationModule::showEvent(QShowEvent *ev)
|
||||
{
|
||||
KCModule::showEvent(ev);
|
||||
}
|
||||
|
||||
static const QMap<QString, KDecoration2::BorderSize> s_sizes = QMap<QString, KDecoration2::BorderSize>({
|
||||
{QStringLiteral("None"), BorderSize::None},
|
||||
{QStringLiteral("NoSides"), BorderSize::NoSides},
|
||||
{QStringLiteral("Tiny"), BorderSize::Tiny},
|
||||
{s_borderSizeNormal, BorderSize::Normal},
|
||||
{QStringLiteral("Large"), BorderSize::Large},
|
||||
{QStringLiteral("VeryLarge"), BorderSize::VeryLarge},
|
||||
{QStringLiteral("Huge"), BorderSize::Huge},
|
||||
{QStringLiteral("VeryHuge"), BorderSize::VeryHuge},
|
||||
{QStringLiteral("Oversized"), BorderSize::Oversized}
|
||||
});
|
||||
|
||||
static BorderSize stringToSize(const QString &name)
|
||||
{
|
||||
auto it = s_sizes.constFind(name);
|
||||
if (it == s_sizes.constEnd()) {
|
||||
// non sense values are interpreted just like normal
|
||||
return BorderSize::Normal;
|
||||
}
|
||||
return it.value();
|
||||
}
|
||||
|
||||
static QString sizeToString(BorderSize size)
|
||||
{
|
||||
return s_sizes.key(size, s_borderSizeNormal);
|
||||
}
|
||||
|
||||
static QHash<KDecoration2::DecorationButtonType, QChar> s_buttonNames;
|
||||
static void initButtons()
|
||||
{
|
||||
if (!s_buttonNames.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
s_buttonNames[KDecoration2::DecorationButtonType::Menu] = QChar('M');
|
||||
s_buttonNames[KDecoration2::DecorationButtonType::ApplicationMenu] = QChar('N');
|
||||
s_buttonNames[KDecoration2::DecorationButtonType::OnAllDesktops] = QChar('S');
|
||||
s_buttonNames[KDecoration2::DecorationButtonType::ContextHelp] = QChar('H');
|
||||
s_buttonNames[KDecoration2::DecorationButtonType::Minimize] = QChar('I');
|
||||
s_buttonNames[KDecoration2::DecorationButtonType::Maximize] = QChar('A');
|
||||
s_buttonNames[KDecoration2::DecorationButtonType::Close] = QChar('X');
|
||||
s_buttonNames[KDecoration2::DecorationButtonType::KeepAbove] = QChar('F');
|
||||
s_buttonNames[KDecoration2::DecorationButtonType::KeepBelow] = QChar('B');
|
||||
s_buttonNames[KDecoration2::DecorationButtonType::Shade] = QChar('L');
|
||||
}
|
||||
|
||||
static QString buttonsToString(const QVector<KDecoration2::DecorationButtonType> &buttons)
|
||||
{
|
||||
auto buttonToString = [](KDecoration2::DecorationButtonType button) -> QChar {
|
||||
const auto it = s_buttonNames.constFind(button);
|
||||
if (it != s_buttonNames.constEnd()) {
|
||||
return it.value();
|
||||
}
|
||||
return QChar();
|
||||
};
|
||||
QString ret;
|
||||
for (auto button : buttons) {
|
||||
ret.append(buttonToString(button));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
QVector< KDecoration2::DecorationButtonType > readDecorationButtons(const KConfigGroup &config,
|
||||
const char *key,
|
||||
const QVector< KDecoration2::DecorationButtonType > &defaultValue)
|
||||
{
|
||||
initButtons();
|
||||
auto buttonsFromString = [](const QString &buttons) -> QVector<KDecoration2::DecorationButtonType> {
|
||||
QVector<KDecoration2::DecorationButtonType> ret;
|
||||
for (auto it = buttons.begin(); it != buttons.end(); ++it) {
|
||||
for (auto it2 = s_buttonNames.constBegin(); it2 != s_buttonNames.constEnd(); ++it2) {
|
||||
if (it2.value() == (*it)) {
|
||||
ret << it2.key();
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
return buttonsFromString(config.readEntry(key, buttonsToString(defaultValue)));
|
||||
}
|
||||
|
||||
void ConfigurationModule::load()
|
||||
{
|
||||
s_loading = true;
|
||||
const KConfigGroup config = KSharedConfig::openConfig("kwinrc")->group(s_pluginName);
|
||||
const QString plugin = config.readEntry("library", s_defaultPlugin);
|
||||
const QString theme = config.readEntry("theme", s_defaultTheme);
|
||||
m_ui->closeWindowsDoubleClick->setChecked(config.readEntry("CloseOnDoubleClickOnMenu", false));
|
||||
const QVariant border = QVariant::fromValue(stringToSize(config.readEntry("BorderSize", s_borderSizeNormal)));
|
||||
m_ui->borderSizesCombo->setCurrentIndex(m_ui->borderSizesCombo->findData(border));
|
||||
|
||||
int themeIndex = m_proxyModel->mapFromSource(m_model->findDecoration(plugin, theme)).row();
|
||||
m_quickView->rootContext()->setContextProperty("initialThemeIndex", themeIndex);
|
||||
|
||||
// buttons
|
||||
const auto &left = readDecorationButtons(config, "ButtonsOnLeft", QVector<KDecoration2::DecorationButtonType >{
|
||||
KDecoration2::DecorationButtonType::Menu,
|
||||
KDecoration2::DecorationButtonType::OnAllDesktops
|
||||
});
|
||||
while (m_leftButtons->rowCount() > 0) {
|
||||
m_leftButtons->remove(0);
|
||||
}
|
||||
for (auto it = left.begin(); it != left.end(); ++it) {
|
||||
m_leftButtons->add(*it);
|
||||
}
|
||||
const auto &right = readDecorationButtons(config, "ButtonsOnRight", QVector<KDecoration2::DecorationButtonType >{
|
||||
KDecoration2::DecorationButtonType::ContextHelp,
|
||||
KDecoration2::DecorationButtonType::Minimize,
|
||||
KDecoration2::DecorationButtonType::Maximize,
|
||||
KDecoration2::DecorationButtonType::Close
|
||||
});
|
||||
while (m_rightButtons->rowCount() > 0) {
|
||||
m_rightButtons->remove(0);
|
||||
}
|
||||
for (auto it = right.begin(); it != right.end(); ++it) {
|
||||
m_rightButtons->add(*it);
|
||||
}
|
||||
|
||||
KCModule::load();
|
||||
s_loading = false;
|
||||
}
|
||||
|
||||
void ConfigurationModule::save()
|
||||
{
|
||||
KConfigGroup config = KSharedConfig::openConfig("kwinrc")->group(s_pluginName);
|
||||
config.writeEntry("CloseOnDoubleClickOnMenu", m_ui->closeWindowsDoubleClick->isChecked());
|
||||
config.writeEntry("BorderSize", sizeToString(m_ui->borderSizesCombo->currentData().value<BorderSize>()));
|
||||
if (auto listView = m_quickView->rootObject()->findChild<QQuickItem*>("listView")) {
|
||||
const int currentIndex = listView->property("currentIndex").toInt();
|
||||
if (currentIndex != -1) {
|
||||
const QModelIndex index = m_proxyModel->index(currentIndex, 0);
|
||||
if (index.isValid()) {
|
||||
config.writeEntry("library", index.data(Qt::UserRole + 4).toString());
|
||||
const QString theme = index.data(Qt::UserRole +5).toString();
|
||||
config.writeEntry("theme", theme);
|
||||
}
|
||||
}
|
||||
}
|
||||
config.writeEntry("ButtonsOnLeft", buttonsToString(m_leftButtons->buttons()));
|
||||
config.writeEntry("ButtonsOnRight", buttonsToString(m_rightButtons->buttons()));
|
||||
config.writeEntry(s_configCloseOnDoubleClickOnMenu, m_currentSettings.closeOnDoubleClickOnMenu);
|
||||
config.writeEntry(s_configBorderSize, Utils::borderSizeToString(m_currentSettings.borderSize));
|
||||
config.writeEntry(s_configDecoButtonsOnLeft, Utils::buttonsToString(m_currentSettings.buttonsOnLeft));
|
||||
config.writeEntry(s_configDecoButtonsOnRight, Utils::buttonsToString(m_currentSettings.buttonsOnRight));
|
||||
config.sync();
|
||||
KCModule::save();
|
||||
// Send signal to all kwin instances
|
||||
|
||||
m_savedSettings = m_currentSettings;
|
||||
|
||||
// Send a signal to all kwin instances
|
||||
QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KWin"),
|
||||
QStringLiteral("org.kde.KWin"),
|
||||
QStringLiteral("reloadConfig"));
|
||||
QDBusConnection::sessionBus().send(message);
|
||||
|
||||
updateNeedsSave();
|
||||
}
|
||||
|
||||
void ConfigurationModule::defaults()
|
||||
void KCMKWinDecoration::defaults()
|
||||
{
|
||||
if (auto listView = m_quickView->rootObject()->findChild<QQuickItem*>("listView")) {
|
||||
const QModelIndex index = m_proxyModel->mapFromSource(m_model->findDecoration(s_defaultPlugin));
|
||||
listView->setProperty("currentIndex", index.isValid() ? index.row() : -1);
|
||||
int themeIndex = m_proxyThemesModel->mapFromSource(m_themesModel->findDecoration(s_defaultPlugin, s_defaultTheme)).row();
|
||||
if (themeIndex < 0) {
|
||||
qWarning() << "Default plugin" << s_defaultPlugin << "and theme" << s_defaultTheme << "not found";
|
||||
}
|
||||
m_ui->borderSizesCombo->setCurrentIndex(m_ui->borderSizesCombo->findData(QVariant::fromValue(stringToSize(s_borderSizeNormal))));
|
||||
m_ui->closeWindowsDoubleClick->setChecked(false);
|
||||
KCModule::defaults();
|
||||
setTheme(themeIndex);
|
||||
setBorderSize(s_defaultBorderSize);
|
||||
setCloseOnDoubleClickOnMenu(s_defaultCloseOnDoubleClickOnMenu);
|
||||
|
||||
m_leftButtonsModel->replace(s_defaultDecoButtonsOnLeft);
|
||||
m_rightButtonsModel->replace(s_defaultDecoButtonsOnRight);
|
||||
|
||||
updateNeedsSave();
|
||||
}
|
||||
|
||||
void ConfigurationModule::showKNS(const QString &config)
|
||||
void KCMKWinDecoration::updateNeedsSave()
|
||||
{
|
||||
QPointer<KNS3::DownloadDialog> downloadDialog = new KNS3::DownloadDialog(config, this);
|
||||
if (downloadDialog->exec() == QDialog::Accepted && !downloadDialog->changedEntries().isEmpty()) {
|
||||
auto listView = m_quickView->rootObject()->findChild<QQuickItem*>("listView");
|
||||
QString selectedPluginName;
|
||||
QString selectedThemeName;
|
||||
if (listView) {
|
||||
const QModelIndex index = m_proxyModel->index(listView->property("currentIndex").toInt(), 0);
|
||||
if (index.isValid()) {
|
||||
selectedPluginName = index.data(Qt::UserRole + 4).toString();
|
||||
selectedThemeName = index.data(Qt::UserRole + 5).toString();
|
||||
}
|
||||
}
|
||||
m_model->init();
|
||||
if (!selectedPluginName.isEmpty()) {
|
||||
const QModelIndex index = m_model->findDecoration(selectedPluginName, selectedThemeName);
|
||||
const QModelIndex proxyIndex = m_proxyModel->mapFromSource(index);
|
||||
if (listView) {
|
||||
listView->setProperty("currentIndex", proxyIndex.isValid() ? proxyIndex.row() : -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
delete downloadDialog;
|
||||
m_currentSettings.buttonsOnLeft = m_leftButtonsModel->buttons();
|
||||
m_currentSettings.buttonsOnRight = m_rightButtonsModel->buttons();
|
||||
|
||||
setNeedsSave(m_savedSettings.closeOnDoubleClickOnMenu != m_currentSettings.closeOnDoubleClickOnMenu
|
||||
|| m_savedSettings.borderSize != m_currentSettings.borderSize
|
||||
|| m_savedSettings.themeIndex != m_currentSettings.themeIndex
|
||||
|| m_savedSettings.buttonsOnLeft != m_currentSettings.buttonsOnLeft
|
||||
|| m_savedSettings.buttonsOnRight != m_currentSettings.buttonsOnRight);
|
||||
}
|
||||
|
||||
bool ConfigurationModule::eventFilter(QObject *watched, QEvent *e)
|
||||
QSortFilterProxyModel *KCMKWinDecoration::themesModel() const
|
||||
{
|
||||
if (watched != m_ui) {
|
||||
return false;
|
||||
}
|
||||
if (e->type() == QEvent::PaletteChange) {
|
||||
updateColors();
|
||||
}
|
||||
return false;
|
||||
return m_proxyThemesModel;
|
||||
}
|
||||
|
||||
void ConfigurationModule::updateColors()
|
||||
QAbstractListModel *KCMKWinDecoration::leftButtonsModel()
|
||||
{
|
||||
m_quickView->rootContext()->setContextProperty("backgroundColor", m_ui->palette().color(QPalette::Active, QPalette::Window));
|
||||
m_quickView->rootContext()->setContextProperty("highlightColor", m_ui->palette().color(QPalette::Active, QPalette::Shadow));
|
||||
m_quickView->rootContext()->setContextProperty("baseColor", m_ui->palette().color(QPalette::Active, QPalette::Base));
|
||||
return m_leftButtonsModel;
|
||||
}
|
||||
|
||||
QAbstractListModel *KCMKWinDecoration::rightButtonsModel()
|
||||
{
|
||||
return m_rightButtonsModel;
|
||||
}
|
||||
|
||||
QAbstractListModel *KCMKWinDecoration::availableButtonsModel() const
|
||||
{
|
||||
return m_availableButtonsModel;
|
||||
}
|
||||
|
||||
QStringList KCMKWinDecoration::borderSizesModel() const
|
||||
{
|
||||
return Utils::getBorderSizeNames().values();
|
||||
}
|
||||
|
||||
int KCMKWinDecoration::borderSize() const
|
||||
{
|
||||
return Utils::getBorderSizeNames().keys().indexOf(m_currentSettings.borderSize);
|
||||
}
|
||||
|
||||
int KCMKWinDecoration::theme() const
|
||||
{
|
||||
return m_currentSettings.themeIndex;
|
||||
}
|
||||
|
||||
bool KCMKWinDecoration::closeOnDoubleClickOnMenu() const
|
||||
{
|
||||
return m_currentSettings.closeOnDoubleClickOnMenu;
|
||||
}
|
||||
|
||||
void KCMKWinDecoration::setBorderSize(int index)
|
||||
{
|
||||
setBorderSize(Utils::getBorderSizeNames().keys().at(index));
|
||||
}
|
||||
|
||||
void KCMKWinDecoration::setBorderSize(KDecoration2::BorderSize size)
|
||||
{
|
||||
if (m_currentSettings.borderSize == size) {
|
||||
return;
|
||||
}
|
||||
m_currentSettings.borderSize = size;
|
||||
emit borderSizeChanged();
|
||||
updateNeedsSave();
|
||||
}
|
||||
|
||||
void KCMKWinDecoration::setTheme(int index)
|
||||
{
|
||||
// The initial themeIndex is set to -2 to always initially apply a theme, any theme
|
||||
if (m_currentSettings.themeIndex == index) {
|
||||
return;
|
||||
}
|
||||
m_currentSettings.themeIndex = index;
|
||||
emit themeChanged();
|
||||
updateNeedsSave();
|
||||
}
|
||||
|
||||
void KCMKWinDecoration::setCloseOnDoubleClickOnMenu(bool enable)
|
||||
{
|
||||
if (m_currentSettings.closeOnDoubleClickOnMenu == enable) {
|
||||
return;
|
||||
}
|
||||
m_currentSettings.closeOnDoubleClickOnMenu = enable;
|
||||
emit closeOnDoubleClickOnMenuChanged();
|
||||
updateNeedsSave();
|
||||
}
|
||||
|
||||
#include "kcm.moc"
|
||||
|
|
|
@ -1,80 +1,116 @@
|
|||
/*
|
||||
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
* Copyright (c) 2019 Valerio Pilo <vpilo@coldshock.net>
|
||||
*
|
||||
* 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 library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* You should have received a copy of the GNU Library General Public License
|
||||
* along with this library; see the file COPYING.LIB. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#ifndef KDECORATIONS_KCM_H
|
||||
#define KDECORATIONS_KCM_H
|
||||
|
||||
#include <kcmodule.h>
|
||||
#include <ui_kcm.h>
|
||||
#include <QAbstractItemModel>
|
||||
#pragma once
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include <KQuickAddons/ConfigModule>
|
||||
|
||||
|
||||
class QAbstractItemModel;
|
||||
class QSortFilterProxyModel;
|
||||
class QQuickView;
|
||||
class QQuickItem;
|
||||
|
||||
namespace KNS3
|
||||
{
|
||||
class DownloadDialog;
|
||||
}
|
||||
|
||||
namespace KDecoration2
|
||||
{
|
||||
enum class BorderSize;
|
||||
|
||||
namespace Preview
|
||||
{
|
||||
class PreviewBridge;
|
||||
class ButtonsModel;
|
||||
}
|
||||
namespace Configuration
|
||||
{
|
||||
class DecorationsModel;
|
||||
}
|
||||
}
|
||||
|
||||
class ConfigurationForm : public QWidget, public Ui::KCMForm
|
||||
{
|
||||
public:
|
||||
explicit ConfigurationForm(QWidget* parent);
|
||||
};
|
||||
|
||||
class ConfigurationModule : public KCModule
|
||||
class KCMKWinDecoration : public KQuickAddons::ConfigModule
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ConfigurationModule(QWidget *parent = nullptr, const QVariantList &args = QVariantList());
|
||||
virtual ~ConfigurationModule();
|
||||
Q_PROPERTY(QSortFilterProxyModel *themesModel READ themesModel CONSTANT)
|
||||
Q_PROPERTY(QStringList borderSizesModel READ borderSizesModel CONSTANT)
|
||||
Q_PROPERTY(int borderSize READ borderSize WRITE setBorderSize NOTIFY borderSizeChanged)
|
||||
Q_PROPERTY(int theme READ theme WRITE setTheme NOTIFY themeChanged)
|
||||
Q_PROPERTY(QAbstractListModel *leftButtonsModel READ leftButtonsModel NOTIFY buttonsChanged)
|
||||
Q_PROPERTY(QAbstractListModel *rightButtonsModel READ rightButtonsModel NOTIFY buttonsChanged)
|
||||
Q_PROPERTY(QAbstractListModel *availableButtonsModel READ availableButtonsModel CONSTANT)
|
||||
Q_PROPERTY(bool closeOnDoubleClickOnMenu READ closeOnDoubleClickOnMenu WRITE setCloseOnDoubleClickOnMenu NOTIFY closeOnDoubleClickOnMenuChanged)
|
||||
|
||||
bool eventFilter(QObject *watched, QEvent *e) override;
|
||||
public:
|
||||
KCMKWinDecoration(QObject *parent, const QVariantList &arguments);
|
||||
|
||||
QSortFilterProxyModel *themesModel() const;
|
||||
QAbstractListModel *leftButtonsModel();
|
||||
QAbstractListModel *rightButtonsModel();
|
||||
QAbstractListModel *availableButtonsModel() const;
|
||||
QStringList borderSizesModel() const;
|
||||
int borderSize() const;
|
||||
int theme() const;
|
||||
bool closeOnDoubleClickOnMenu() const;
|
||||
|
||||
void setBorderSize(int index);
|
||||
void setBorderSize(KDecoration2::BorderSize size);
|
||||
void setTheme(int index);
|
||||
void setCloseOnDoubleClickOnMenu(bool enable);
|
||||
|
||||
Q_INVOKABLE void getNewStuff(QQuickItem *context);
|
||||
|
||||
Q_SIGNALS:
|
||||
void themeChanged();
|
||||
void buttonsChanged();
|
||||
void borderSizeChanged();
|
||||
void closeOnDoubleClickOnMenuChanged();
|
||||
|
||||
public Q_SLOTS:
|
||||
void defaults() override;
|
||||
void load() override;
|
||||
void save() override;
|
||||
void defaults() override;
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *ev) override;
|
||||
private Q_SLOTS:
|
||||
void updateNeedsSave();
|
||||
void reloadKWinSettings();
|
||||
|
||||
private:
|
||||
void showKNS(const QString &config);
|
||||
void updateColors();
|
||||
DecorationsModel *m_model;
|
||||
QSortFilterProxyModel *m_proxyModel;
|
||||
ConfigurationForm *m_ui;
|
||||
QQuickView *m_quickView;
|
||||
Preview::ButtonsModel *m_leftButtons;
|
||||
Preview::ButtonsModel *m_rightButtons;
|
||||
Preview::ButtonsModel *m_availableButtons;
|
||||
KDecoration2::Configuration::DecorationsModel *m_themesModel;
|
||||
QSortFilterProxyModel *m_proxyThemesModel;
|
||||
|
||||
KDecoration2::Preview::ButtonsModel *m_leftButtonsModel;
|
||||
KDecoration2::Preview::ButtonsModel *m_rightButtonsModel;
|
||||
KDecoration2::Preview::ButtonsModel *m_availableButtonsModel;
|
||||
|
||||
QPointer<KNS3::DownloadDialog> m_newStuffDialog;
|
||||
|
||||
struct Settings
|
||||
{
|
||||
KDecoration2::BorderSize borderSize;
|
||||
int themeIndex;
|
||||
bool closeOnDoubleClickOnMenu;
|
||||
DecorationButtonsList buttonsOnLeft;
|
||||
DecorationButtonsList buttonsOnRight;
|
||||
};
|
||||
|
||||
Settings m_savedSettings;
|
||||
Settings m_currentSettings;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,182 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>KCMForm</class>
|
||||
<widget class="QWidget" name="KCMForm">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>386</width>
|
||||
<height>272</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="theTab">
|
||||
<attribute name="title">
|
||||
<string>Theme</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="filter">
|
||||
<property name="placeholderText">
|
||||
<string>Search...</string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="closeWindowsDoubleClick">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Check this option if you want windows to be closed when you double click the menu button."/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Close windows by double clicking &the menu button</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="KMessageWidget" name="doubleClickMessage"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="view">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="borderSizesLabel">
|
||||
<property name="text">
|
||||
<string>Border si&ze:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>borderSizesCombo</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="KComboBox" name="borderSizesCombo">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">No Borders</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">No Side Borders</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">Tiny</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">Normal</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">Large</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">Very Large</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">Huge</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">Very Huge</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="@item:inlistbox Border size:">Oversized</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="borderSizesSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="knsButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Get New Window Decorations...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Buttons</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>KComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>kcombobox.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>KMessageWidget</class>
|
||||
<extends>QFrame</extends>
|
||||
<header location="global">kmessagewidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -1,15 +1,15 @@
|
|||
[Desktop Entry]
|
||||
Exec=kcmshell5 kwindecoration
|
||||
Icon=preferences-system-windows-action
|
||||
Exec=kcmshell5 kwindecoration
|
||||
|
||||
Categories=Qt;KDE;X-KDE-settings-looknfeel;
|
||||
Type=Service
|
||||
X-KDE-ServiceTypes=KCModule
|
||||
X-DocPath=kcontrol/kwindecoration/index.html
|
||||
|
||||
X-KDE-Library=kcm_kwindecoration
|
||||
X-KDE-ParentApp=kcontrol
|
||||
|
||||
X-KDE-System-Settings-Parent-Category=applicationstyle
|
||||
X-KDE-Weight=40
|
||||
X-DocPath=kcontrol/kwindecoration/index.html
|
||||
|
||||
Name=Window Decorations
|
||||
Name[ar]=زخارف النوافذ
|
||||
|
@ -72,50 +72,7 @@ Name[x-test]=xxWindow Decorationsxx
|
|||
Name[zh_CN]=窗口装饰
|
||||
Name[zh_TW]=視窗裝飾
|
||||
|
||||
Comment=Look and Feel of Window Titles
|
||||
Comment[bs]=Izgled i osjećaj naslova prozora
|
||||
Comment[ca]=Aspecte i comportament dels títols de les finestres
|
||||
Comment[ca@valencia]=Aspecte i comportament dels títols de les finestres
|
||||
Comment[cs]=Vzhled a dekorace titulků oken
|
||||
Comment[da]=Udseendet af vinduestitler
|
||||
Comment[de]=Erscheinungsbild von Fenstertiteln
|
||||
Comment[el]=Διαμόρφωση της εμφάνισης και αίσθησης του τίτλου των παραθύρων
|
||||
Comment[en_GB]=Look and Feel of Window Titles
|
||||
Comment[es]=Aspecto visual de los títulos de las ventanas
|
||||
Comment[et]=Akna tiitliribade välimus ja tunnetus
|
||||
Comment[eu]=Leiho-tituluen itxura eta izaera
|
||||
Comment[fi]=Ikkunoiden kehysten ulkoasu
|
||||
Comment[fr]=Apparence des titres de fenêtre
|
||||
Comment[gl]=Aparencia e o comportamento dos títulos das xanelas
|
||||
Comment[he]=הגדרת המראה והתחושה של מסגרות החלונות
|
||||
Comment[hu]=Az ablakok címsorának megjelenése
|
||||
Comment[ia]=Semblantia de titulos de fenestra
|
||||
Comment[id]=Look and Feel pada Judul Window
|
||||
Comment[it]=Aspetto dei titoli delle finestre
|
||||
Comment[ja]=ウィンドウタイトルの外観を設定
|
||||
Comment[ko]=창 제목 표시줄의 모습과 느낌 설정
|
||||
Comment[lt]=Langų antraščių išvaizda ir elgsena
|
||||
Comment[nb]=Utseende og virkemåte for vindustitlene
|
||||
Comment[nds]=Dat Utsehn vun de Finstertiteln instellen
|
||||
Comment[nl]=Uiterlijk en gedrag van venstertitels
|
||||
Comment[nn]=Utsjånad og åtferd for vindaugstitlar
|
||||
Comment[pa]=ਵਿੰਡੋ ਟਾਇਟਲਾਂ ਦੇ ਰੰਗ-ਰੂਪ ਦੀ ਸੰਰਚਨਾ
|
||||
Comment[pl]=Tytuły okien - wrażenia wzrokowe i dotykowe
|
||||
Comment[pt]=Aparência e Comportamento dos Títulos das Janelas
|
||||
Comment[pt_BR]=Aparência do título das janelas
|
||||
Comment[ru]=Настройка внешнего вида заголовков окон
|
||||
Comment[sk]=Nastavenie vzhľadu titulkov okien
|
||||
Comment[sl]=Videz in občutek naslovnih vrstic okna
|
||||
Comment[sr]=Изглед и осећај за наслове прозора
|
||||
Comment[sr@ijekavian]=Изглед и осјећај за наслове прозора
|
||||
Comment[sr@ijekavianlatin]=Izgled i osjećaj za naslove prozora
|
||||
Comment[sr@latin]=Izgled i osećaj za naslove prozora
|
||||
Comment[sv]=Namnlisternas utseende och känsla
|
||||
Comment[tr]=Pencere Başlıklarının Görünüm ve Davranışlarını Yapılandır
|
||||
Comment[uk]=Вигляд і поведінка смужок заголовків вікон
|
||||
Comment[x-test]=xxLook and Feel of Window Titlesxx
|
||||
Comment[zh_CN]=窗口标题的观感
|
||||
Comment[zh_TW]=視窗標題列的外觀與感覺
|
||||
Comment=Configure window titlebars and borders
|
||||
|
||||
X-KDE-Keywords=kwin,window,manager,border,style,theme,look,feel,layout,button,handle,edge,kwm,decoration
|
||||
X-KDE-Keywords[bs]=kwin,prozor,upravitelj,granica,stil,tema,izgled,osjećati,izgled,dugme,držati,ivica,kwm,dekoracija
|
||||
|
@ -160,6 +117,3 @@ X-KDE-Keywords[uk]=kwin,window,manager,border,style,theme,look,feel,layout,butto
|
|||
X-KDE-Keywords[x-test]=xxkwinxx,xxwindowxx,xxmanagerxx,xxborderxx,xxstylexx,xxthemexx,xxlookxx,xxfeelxx,xxlayoutxx,xxbuttonxx,xxhandlexx,xxedgexx,xxkwmxx,xxdecorationxx
|
||||
X-KDE-Keywords[zh_CN]=kwin,window,manager,border,style,theme,look,feel,layout,button,handle,edge,kwm,decoration,窗口,管理,边框,样式,主题,外怪,布局,按钮,边界,装饰
|
||||
X-KDE-Keywords[zh_TW]=kwin,window,manager,border,style,theme,look,feel,layout,button,handle,edge,kwm,decoration
|
||||
|
||||
Categories=Qt;KDE;X-KDE-settings-looknfeel;
|
||||
|
||||
|
|
|
@ -17,24 +17,22 @@
|
|||
* 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 QtQuick.Layouts 1.1
|
||||
import QtQuick 2.7
|
||||
import org.kde.kwin.private.kdecoration 1.0 as KDecoration
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore;
|
||||
|
||||
ListView {
|
||||
id: view
|
||||
property string key
|
||||
property bool dragging: false
|
||||
property int iconSize: units.iconSizes.small
|
||||
orientation: ListView.Horizontal
|
||||
interactive: false
|
||||
spacing: units.smallSpacing
|
||||
implicitHeight: units.iconSizes.small
|
||||
implicitWidth: count * (units.iconSizes.small + units.smallSpacing) - Math.min(1, count) * units.smallSpacing
|
||||
implicitHeight: iconSize
|
||||
implicitWidth: count * (iconSize + units.smallSpacing) - Math.min(1, count) * units.smallSpacing
|
||||
delegate: Item {
|
||||
width: units.iconSizes.small
|
||||
height: units.iconSizes.small
|
||||
width: iconSize
|
||||
height: iconSize
|
||||
KDecoration.Button {
|
||||
id: button
|
||||
property int itemIndex: index
|
||||
|
@ -42,10 +40,13 @@ ListView {
|
|||
bridge: bridgeItem.bridge
|
||||
settings: settingsItem
|
||||
type: model["button"]
|
||||
width: iconSize
|
||||
height: iconSize
|
||||
anchors.fill: Drag.active ? undefined : parent
|
||||
Drag.keys: [ "decoButtonRemove", view.key ]
|
||||
Drag.active: dragArea.drag.active
|
||||
Drag.onActiveChanged: view.dragging = Drag.active
|
||||
color: palette.windowText
|
||||
}
|
||||
MouseArea {
|
||||
id: dragArea
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
* Copyright (c) 2019 Valerio Pilo <vpilo@coldshock.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
|
@ -17,16 +18,18 @@
|
|||
* 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.3
|
||||
import QtQuick.Controls 1.2
|
||||
import QtQuick.Controls 2.0 as QQC2
|
||||
import QtQuick.Layouts 1.1
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls 2.4 as Controls
|
||||
import org.kde.plasma.core 2.0 as PlasmaCore
|
||||
import org.kde.kwin.private.kdecoration 1.0 as KDecoration
|
||||
import org.kde.kquickcontrolsaddons 2.0 as KQuickControlsAddons;
|
||||
|
||||
Item {
|
||||
objectName: "buttonLayout"
|
||||
Layout.preferredHeight: layout.height
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
property int buttonIconSize: units.iconSizes.medium
|
||||
property int titleBarSpacing: units.iconSizes.smallMedium
|
||||
|
||||
KDecoration.Bridge {
|
||||
id: bridgeItem
|
||||
plugin: "org.kde.breeze"
|
||||
|
@ -35,58 +38,62 @@ Item {
|
|||
id: settingsItem
|
||||
bridge: bridgeItem.bridge
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
border.width: Math.ceil(units.gridUnit / 16.0)
|
||||
border.color: highlightColor
|
||||
color: baseColor
|
||||
Layout.fillWidth: true
|
||||
color: palette.base
|
||||
radius: units.smallSpacing
|
||||
height: fakeWindow.height
|
||||
Layout.margins: units.smallSpacing
|
||||
|
||||
ColumnLayout {
|
||||
id: layout
|
||||
id: fakeWindow
|
||||
width: parent.width
|
||||
height: titlebarRect.height + availableGrid.height + dragHint.height + 5*layout.spacing
|
||||
|
||||
Rectangle {
|
||||
id: titlebarRect
|
||||
height: buttonPreviewRow.height + units.smallSpacing
|
||||
border.width: Math.ceil(units.gridUnit / 16.0)
|
||||
border.color: highlightColor
|
||||
color: backgroundColor
|
||||
id: titleBar
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: -border.width // prevent a double top border
|
||||
height: buttonPreviewRow.height + 2 * titleBarSpacing
|
||||
radius: units.smallSpacing
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.0; color: palette.midlight }
|
||||
GradientStop { position: 1.0; color: palette.window }
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: buttonPreviewRow
|
||||
anchors.top: parent.top;
|
||||
anchors.left: parent.left;
|
||||
anchors.right: parent.right;
|
||||
anchors.margins: units.smallSpacing / 2
|
||||
height: Math.max(units.iconSizes.small, titlebar.implicitHeight) + units.smallSpacing/2
|
||||
ButtonGroup {
|
||||
id: leftButtonsView
|
||||
height: buttonPreviewRow.height
|
||||
model: leftButtons
|
||||
key: "decoButtonLeft"
|
||||
}
|
||||
QQC2.Label {
|
||||
id: titlebar
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font: titleFont
|
||||
text: i18n("Titlebar")
|
||||
anchors {
|
||||
margins: titleBarSpacing
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: parent.top
|
||||
}
|
||||
|
||||
ButtonGroup {
|
||||
id: leftButtonsView
|
||||
iconSize: buttonIconSize
|
||||
model: kcm.leftButtonsModel
|
||||
key: "decoButtonLeft"
|
||||
}
|
||||
Controls.Label {
|
||||
id: titleBarLabel
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.bold: true
|
||||
text: i18n("Titlebar")
|
||||
}
|
||||
ButtonGroup {
|
||||
id: rightButtonsView
|
||||
height: buttonPreviewRow.height
|
||||
model: rightButtons
|
||||
iconSize: buttonIconSize
|
||||
model: kcm.rightButtonsModel
|
||||
key: "decoButtonRight"
|
||||
}
|
||||
}
|
||||
DropArea {
|
||||
id: titleBarDropArea
|
||||
anchors {
|
||||
fill: titlebarRect
|
||||
leftMargin: -units.iconSizes.small
|
||||
topMargin: -units.iconSizes.small
|
||||
rightMargin: +units.iconSizes.small
|
||||
bottomMargin: +units.iconSizes.small
|
||||
fill: parent
|
||||
margins: -titleBarSpacing
|
||||
}
|
||||
keys: [ "decoButtonAdd", "decoButtonRight", "decoButtonLeft" ]
|
||||
onEntered: {
|
||||
|
@ -105,9 +112,13 @@ Item {
|
|||
return;
|
||||
}
|
||||
var point = mapToItem(view, drag.x, drag.y);
|
||||
var index = view.indexAt(point.x, point.y);
|
||||
if (index == -1 && (view.x + view.width <= drag.x)) {
|
||||
index = view.count - 1;
|
||||
var index = 0
|
||||
for(var childIndex = 0 ; childIndex < (view.count - 1) ; childIndex++) {
|
||||
var child = view.contentItem.children[childIndex]
|
||||
if (child.x > point.x) {
|
||||
break
|
||||
}
|
||||
index = childIndex + 1
|
||||
}
|
||||
if (drop.keys.indexOf("decoButtonAdd") != -1) {
|
||||
view.model.add(index, drag.source.type);
|
||||
|
@ -138,52 +149,64 @@ Item {
|
|||
}
|
||||
}
|
||||
GridView {
|
||||
id: availableGrid
|
||||
id: availableButtonsGrid
|
||||
Layout.fillWidth: true
|
||||
model: availableButtons
|
||||
Layout.minimumHeight: availableButtonsGrid.cellHeight * 2
|
||||
Layout.margins: units.largeSpacing
|
||||
model: kcm.availableButtonsModel
|
||||
interactive: false
|
||||
height: Math.ceil(cellHeight * 3)
|
||||
delegate: Item {
|
||||
id: availableDelegate
|
||||
Layout.margins: units.gridUnit
|
||||
width: availableGrid.cellWidth
|
||||
height: availableGrid.cellHeight
|
||||
Layout.margins: units.largeSpacing
|
||||
width: availableButtonsGrid.cellWidth
|
||||
height: availableButtonsGrid.cellHeight
|
||||
opacity: (leftButtonsView.dragging || rightButtonsView.dragging) ? 0.25 : 1.0
|
||||
KDecoration.Button {
|
||||
id: availableButton
|
||||
anchors.centerIn: Drag.active ? undefined : parent
|
||||
bridge: bridgeItem.bridge
|
||||
settings: settingsItem
|
||||
type: model["button"]
|
||||
width: units.iconSizes.small
|
||||
height: units.iconSizes.small
|
||||
Drag.keys: [ "decoButtonAdd" ]
|
||||
Drag.active: dragArea.drag.active
|
||||
Rectangle {
|
||||
id: availableButtonFrame
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: palette.window
|
||||
radius: units.smallSpacing
|
||||
width: buttonIconSize + units.largeSpacing
|
||||
height: buttonIconSize + units.largeSpacing
|
||||
|
||||
KDecoration.Button {
|
||||
id: availableButton
|
||||
anchors.centerIn: Drag.active ? undefined : availableButtonFrame
|
||||
bridge: bridgeItem.bridge
|
||||
settings: settingsItem
|
||||
type: model["button"]
|
||||
width: buttonIconSize
|
||||
height: buttonIconSize
|
||||
Drag.keys: [ "decoButtonAdd" ]
|
||||
Drag.active: dragArea.drag.active
|
||||
color: palette.windowText
|
||||
}
|
||||
MouseArea {
|
||||
id: dragArea
|
||||
anchors.fill: availableButton
|
||||
drag.target: availableButton
|
||||
cursorShape: Qt.SizeAllCursor
|
||||
onReleased: {
|
||||
if (availableButton.Drag.target) {
|
||||
availableButton.Drag.drop();
|
||||
} else {
|
||||
availableButton.Drag.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
QQC2.Label {
|
||||
Controls.Label {
|
||||
id: iconLabel
|
||||
text: model["display"]
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignTop
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.top: availableButtonFrame.bottom
|
||||
anchors.topMargin: units.smallSpacing
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
elide: Text.ElideRight
|
||||
wrapMode: Text.Wrap
|
||||
height: 2 * dragHint.implicitHeight + lineHeight
|
||||
}
|
||||
MouseArea {
|
||||
id: dragArea
|
||||
anchors.fill: availableButton
|
||||
drag.target: availableButton
|
||||
cursorShape: Qt.SizeAllCursor
|
||||
onReleased: {
|
||||
if (availableButton.Drag.target) {
|
||||
availableButton.Drag.drop();
|
||||
} else {
|
||||
availableButton.Drag.cancel();
|
||||
}
|
||||
}
|
||||
height: 2 * implicitHeight + lineHeight
|
||||
}
|
||||
}
|
||||
DropArea {
|
||||
|
@ -198,17 +221,17 @@ Item {
|
|||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
opacity: (leftButtonsView.dragging || rightButtonsView.dragging) ? 1.0 : 0.0
|
||||
QQC2.Label {
|
||||
Controls.Label {
|
||||
text: i18n("Drop here to remove button")
|
||||
font.weight: Font.Bold
|
||||
Layout.bottomMargin: units.smallSpacing
|
||||
}
|
||||
KQuickControlsAddons.QIconItem {
|
||||
PlasmaCore.IconItem {
|
||||
id: icon
|
||||
width: units.iconSizes.smallMedium
|
||||
height: units.iconSizes.smallMedium
|
||||
icon: "emblem-remove"
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
source: "emblem-remove"
|
||||
}
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
|
@ -218,11 +241,12 @@ Item {
|
|||
}
|
||||
Text {
|
||||
id: dragHint
|
||||
opacity: (leftButtonsView.dragging || rightButtonsView.dragging || availableGrid.dragging) ? 0.0 : 0.50
|
||||
color: palette.windowText
|
||||
opacity: (leftButtonsView.dragging || rightButtonsView.dragging || availableButtonsGrid.dragging) ? 0.0 : 1.0
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: units.smallSpacing
|
||||
Layout.topMargin: titleBarSpacing
|
||||
Layout.bottomMargin: titleBarSpacing
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignTop
|
||||
wrapMode: Text.NoWrap
|
||||
text: i18n("Drag buttons between here and the titlebar")
|
||||
}
|
126
kcmkwin/kwindecoration/package/contents/ui/Themes.qml
Normal file
126
kcmkwin/kwindecoration/package/contents/ui/Themes.qml
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>
|
||||
* Copyright (c) 2019 Valerio Pilo <vpilo@coldshock.net>
|
||||
*
|
||||
* 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.7
|
||||
import org.kde.kcm 1.1 as KCM
|
||||
import org.kde.kirigami 2.2 as Kirigami
|
||||
import org.kde.kwin.private.kdecoration 1.0 as KDecoration
|
||||
|
||||
KCM.GridView {
|
||||
property int cellSpacing: 2 * units.largeSpacing
|
||||
property int previewWidth: 18 * units.gridUnit
|
||||
property int previewHeight: previewWidth / 1.7
|
||||
|
||||
function updateDecoration(item, marginTopLeft, marginBottomRight) {
|
||||
var mainMargin = units.largeSpacing
|
||||
var shd = item.shadow
|
||||
item.anchors.leftMargin = mainMargin + marginTopLeft - (shd ? shd.paddingLeft : 0)
|
||||
item.anchors.rightMargin = mainMargin + marginBottomRight - (shd ? shd.paddingRight : 0)
|
||||
item.anchors.topMargin = mainMargin + marginTopLeft - (shd ? shd.paddingTop : 0)
|
||||
item.anchors.bottomMargin = mainMargin + marginBottomRight - (shd ? shd.paddingBottom : 0)
|
||||
}
|
||||
|
||||
view.model: kcm.themesModel
|
||||
view.currentIndex: kcm.theme
|
||||
view.onCurrentIndexChanged: kcm.theme = view.currentIndex
|
||||
view.onContentHeightChanged: view.positionViewAtIndex(view.currentIndex, GridView.Visible)
|
||||
|
||||
view.cellWidth: previewWidth + cellSpacing
|
||||
view.cellHeight: previewHeight + cellSpacing
|
||||
|
||||
view.delegate: KCM.GridDelegate {
|
||||
text: model.display
|
||||
|
||||
thumbnailAvailable: true
|
||||
thumbnail: Rectangle {
|
||||
anchors.fill: parent
|
||||
width: previewWidth
|
||||
height: previewHeight
|
||||
color: palette.base
|
||||
clip: true
|
||||
|
||||
// Workaround: the thumbnail size can't be otherwise changed
|
||||
Component.onCompleted: {
|
||||
parent.parent.width = previewWidth
|
||||
parent.parent.height = previewHeight
|
||||
}
|
||||
|
||||
KDecoration.Bridge {
|
||||
id: bridgeItem
|
||||
plugin: model.plugin
|
||||
theme: model.theme
|
||||
}
|
||||
KDecoration.Settings {
|
||||
id: settingsItem
|
||||
bridge: bridgeItem.bridge
|
||||
}
|
||||
KDecoration.Decoration {
|
||||
id: inactivePreview
|
||||
bridge: bridgeItem.bridge
|
||||
settings: settingsItem
|
||||
anchors.fill: parent
|
||||
onShadowChanged: updateDecoration(inactivePreview, 0, client.decoration.titleBar.height)
|
||||
Component.onCompleted: {
|
||||
client.active = false
|
||||
client.caption = model.display
|
||||
updateDecoration(inactivePreview, 0, client.decoration.titleBar.height)
|
||||
}
|
||||
}
|
||||
KDecoration.Decoration {
|
||||
id: activePreview
|
||||
bridge: bridgeItem.bridge
|
||||
settings: settingsItem
|
||||
anchors.fill: parent
|
||||
onShadowChanged: updateDecoration(activePreview, client.decoration.titleBar.height, 0)
|
||||
Component.onCompleted: {
|
||||
client.active = true
|
||||
client.caption = model.display
|
||||
updateDecoration(activePreview, client.decoration.titleBar.height, 0)
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: view.currentIndex = index
|
||||
}
|
||||
Connections {
|
||||
target: kcm
|
||||
onBorderSizeChanged: settingsItem.borderSizesIndex = kcm.borderSize
|
||||
}
|
||||
}
|
||||
actions: [
|
||||
Kirigami.Action {
|
||||
iconName: "edit-entry"
|
||||
tooltip: i18n("Edit %1 Theme", model.display)
|
||||
enabled: model.configureable
|
||||
onTriggered: {
|
||||
view.currentIndex = index
|
||||
bridgeItem.bridge.configure()
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
onClicked: view.currentIndex = index
|
||||
}
|
||||
Connections {
|
||||
target: kcm
|
||||
onThemeChanged: view.currentIndex = kcm.theme
|
||||
}
|
||||
}
|
||||
|
127
kcmkwin/kwindecoration/package/contents/ui/main.qml
Normal file
127
kcmkwin/kwindecoration/package/contents/ui/main.qml
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
Copyright (c) 2019 Valerio Pilo <vpilo@coldshock.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License version 2 as published by the Free Software Foundation.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls 2.4 as Controls
|
||||
import org.kde.kcm 1.1 as KCM
|
||||
import org.kde.kconfig 1.0 // for KAuthorized
|
||||
import org.kde.kirigami 2.4 as Kirigami
|
||||
|
||||
Kirigami.Page {
|
||||
KCM.ConfigModule.quickHelp: i18n("This module lets you configure the window decorations.")
|
||||
KCM.ConfigModule.buttons: KCM.ConfigModule.Help | KCM.ConfigModule.Default | KCM.ConfigModule.Apply
|
||||
title: kcm.name
|
||||
|
||||
SystemPalette {
|
||||
id: palette
|
||||
colorGroup: SystemPalette.Active
|
||||
}
|
||||
|
||||
// To match SimpleKCM's borders of Page + headerParent/footerParent (also specified in raw pixels)
|
||||
leftPadding: Kirigami.Settings.isMobile ? 0 : 8
|
||||
topPadding: leftPadding
|
||||
rightPadding: leftPadding
|
||||
bottomPadding: leftPadding
|
||||
|
||||
ColumnLayout {
|
||||
id: tabLayout
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
Controls.TabBar {
|
||||
id: tabBar
|
||||
Layout.fillWidth: true
|
||||
|
||||
Controls.TabButton {
|
||||
text: i18nc("tab label", "Theme")
|
||||
}
|
||||
|
||||
Controls.TabButton {
|
||||
text: i18nc("tab label", "Titlebar Buttons")
|
||||
}
|
||||
}
|
||||
Controls.Frame {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
StackLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
currentIndex: tabBar.currentIndex
|
||||
|
||||
ColumnLayout {
|
||||
Themes {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Controls.Label {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
text: i18nc("combobox label", "Window border size:")
|
||||
}
|
||||
|
||||
Controls.ComboBox {
|
||||
id: borderSizeComboBox
|
||||
model: kcm.borderSizesModel
|
||||
currentIndex: kcm.borderSize
|
||||
onActivated: {
|
||||
kcm.borderSize = currentIndex
|
||||
}
|
||||
}
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
Controls.Button {
|
||||
text: i18nc("button text", "Get New Window Decorations...")
|
||||
icon.name: "get-hot-new-stuff"
|
||||
onClicked: kcm.getNewStuff(this)
|
||||
visible: KAuthorized.authorize("ghns")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Buttons {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
Controls.CheckBox {
|
||||
id: closeOnDoubleClickOnMenuCheckBox
|
||||
text: i18nc("checkbox label", "Close windows by double clicking the menu button")
|
||||
checked: kcm.closeOnDoubleClickOnMenu
|
||||
onToggled: {
|
||||
kcm.closeOnDoubleClickOnMenu = checked
|
||||
infoLabel.visible = checked
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.InlineMessage {
|
||||
Layout.fillWidth: true
|
||||
id: infoLabel
|
||||
type: Kirigami.MessageType.Information
|
||||
text: i18nc("popup tip", "Close by double clicking: Keep the window's Menu button pressed until it appears.")
|
||||
showCloseButton: true
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
77
kcmkwin/kwindecoration/package/metadata.desktop
Normal file
77
kcmkwin/kwindecoration/package/metadata.desktop
Normal file
|
@ -0,0 +1,77 @@
|
|||
[Desktop Entry]
|
||||
Icon=preferences-system-windows-action
|
||||
Type=Service
|
||||
Keywords=
|
||||
X-KDE-ParentApp=
|
||||
X-KDE-System-Settings-Parent-Category=applicationstyle
|
||||
X-KDE-PluginInfo-Author=Valerio Pilo
|
||||
X-KDE-PluginInfo-Email=vpilo@coldshock.net
|
||||
X-KDE-PluginInfo-License=GPL-2.0+
|
||||
X-KDE-PluginInfo-Name=kcm_kwindecoration
|
||||
X-KDE-PluginInfo-Version=
|
||||
X-KDE-PluginInfo-Website=https://www.kde.org/plasma-desktop
|
||||
X-KDE-ServiceTypes=Plasma/Generic
|
||||
X-Plasma-API=declarativeappletscript
|
||||
X-Plasma-MainScript=ui/main.qml
|
||||
|
||||
Name=Window Decorations
|
||||
Name[ar]=زخارف النوافذ
|
||||
Name[bg]=Декорации на прозорците
|
||||
Name[bs]=Dekoracije prozora
|
||||
Name[ca]=Decoració de les finestres
|
||||
Name[ca@valencia]=Decoració de les finestres
|
||||
Name[cs]=Dekorace oken
|
||||
Name[da]=Vinduesdekorationer
|
||||
Name[de]=Fensterdekoration
|
||||
Name[el]=Διακοσμήσεις παραθύρου
|
||||
Name[en_GB]=Window Decorations
|
||||
Name[es]=Decoración de ventanas
|
||||
Name[et]=Akna dekoratsioonid
|
||||
Name[eu]=Leiho-apaindurak
|
||||
Name[fi]=Ikkunakehykset
|
||||
Name[fr]=Décorations de fenêtres
|
||||
Name[ga]=Maisiúcháin Fhuinneog
|
||||
Name[gl]=Decoración da xanela
|
||||
Name[he]=מסגרת חלון
|
||||
Name[hi]=विंडो सजावट
|
||||
Name[hr]=Ukrasi prozora
|
||||
Name[hu]=Ablakdekorációk
|
||||
Name[ia]=Decorationes de fenestra
|
||||
Name[id]=Dekorasi Window
|
||||
Name[is]=Gluggaskreytingar
|
||||
Name[it]=Decorazioni delle finestre
|
||||
Name[ja]=ウィンドウの飾り
|
||||
Name[kk]=Терезенің безендірулері
|
||||
Name[km]=ការតុបតែងបង្អួច
|
||||
Name[kn]=ವಿಂಡೋ ಅಲಂಕಾರಗಳು
|
||||
Name[ko]=창 장식
|
||||
Name[lt]=Lango dekoracijos
|
||||
Name[lv]=Logu dekorācijas
|
||||
Name[mr]=चौकट सजावट
|
||||
Name[nb]=Vinduspynt
|
||||
Name[nds]=Finstern opfladusen
|
||||
Name[nl]=Vensterdecoraties
|
||||
Name[nn]=Vindaugspynt
|
||||
Name[pa]=ਵਿੰਡੋ ਸਜਾਵਟ
|
||||
Name[pl]=Wygląd okien
|
||||
Name[pt]=Decorações das Janelas
|
||||
Name[pt_BR]=Decorações da janela
|
||||
Name[ro]=Decorații fereastră
|
||||
Name[ru]=Оформление окон
|
||||
Name[si]=කවුළු සැරසිලි
|
||||
Name[sk]=Dekorácie okien
|
||||
Name[sl]=Okraski oken
|
||||
Name[sr]=Декорације прозора
|
||||
Name[sr@ijekavian]=Декорације прозора
|
||||
Name[sr@ijekavianlatin]=Dekoracije prozora
|
||||
Name[sr@latin]=Dekoracije prozora
|
||||
Name[sv]=Fönsterdekorationer
|
||||
Name[th]=ส่วนตกแต่งหน้าต่าง
|
||||
Name[tr]=Pencere Dekorasyonları
|
||||
Name[ug]=كۆزنەك بېزەكلىرى
|
||||
Name[uk]=Обрамлення вікон
|
||||
Name[wa]=Gåyotaedjes des fniesses
|
||||
Name[x-test]=xxWindow Decorationsxx
|
||||
Name[zh_CN]=窗口装饰
|
||||
Name[zh_TW]=視窗裝飾
|
||||
Comment=Configure window titlebars and borders
|
|
@ -1,160 +0,0 @@
|
|||
/*
|
||||
* 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 QtQuick.Layouts 1.1
|
||||
import org.kde.kwin.private.kdecoration 1.0 as KDecoration
|
||||
|
||||
ScrollView {
|
||||
objectName: "themeList"
|
||||
frameVisible: true
|
||||
GridView {
|
||||
id: gridView
|
||||
objectName: "listView"
|
||||
signal userChangedSelection()
|
||||
model: decorationsModel
|
||||
cellWidth: 20 * units.gridUnit
|
||||
cellHeight: cellWidth / 1.6
|
||||
highlightFollowsCurrentItem: true
|
||||
onContentHeightChanged: {
|
||||
if (gridView.currentIndex == -1 && initialThemeIndex != -1) {
|
||||
gridView.currentIndex = initialThemeIndex
|
||||
}
|
||||
gridView.positionViewAtIndex(gridView.currentIndex, GridView.Visible)
|
||||
}
|
||||
Rectangle {
|
||||
z: -1
|
||||
anchors.fill: parent
|
||||
color: baseColor
|
||||
}
|
||||
highlight: Rectangle {
|
||||
color: highlightColor
|
||||
opacity: 0.6
|
||||
}
|
||||
highlightMoveDuration: units.longDuration
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
property int borderSizesIndex: 3 // 3 == Normal
|
||||
delegate: Item {
|
||||
width: gridView.cellWidth
|
||||
height: gridView.cellHeight
|
||||
KDecoration.Bridge {
|
||||
id: bridgeItem
|
||||
plugin: model["plugin"]
|
||||
theme: model["theme"]
|
||||
}
|
||||
KDecoration.Settings {
|
||||
id: settingsItem
|
||||
bridge: bridgeItem.bridge
|
||||
borderSizesIndex: gridView.borderSizesIndex
|
||||
}
|
||||
Component.onCompleted: {
|
||||
if (gridView.currentIndex == -1 && initialThemeIndex != -1) {
|
||||
gridView.currentIndex = initialThemeIndex
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
hoverEnabled: false
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
gridView.currentIndex = index
|
||||
gridView.userChangedSelection()
|
||||
}
|
||||
}
|
||||
ColumnLayout {
|
||||
id: decorationPreviews
|
||||
property string themeName: model["display"]
|
||||
anchors.fill: parent
|
||||
Item {
|
||||
KDecoration.Decoration {
|
||||
id: inactivePreview
|
||||
bridge: bridgeItem.bridge
|
||||
settings: settingsItem
|
||||
anchors.fill: parent
|
||||
Component.onCompleted: {
|
||||
client.caption = decorationPreviews.themeName
|
||||
client.active = false;
|
||||
anchors.leftMargin = Qt.binding(function() { return 40 - (inactivePreview.shadow ? inactivePreview.shadow.paddingLeft : 0);});
|
||||
anchors.rightMargin = Qt.binding(function() { return 10 - (inactivePreview.shadow ? inactivePreview.shadow.paddingRight : 0);});
|
||||
anchors.topMargin = Qt.binding(function() { return 10 - (inactivePreview.shadow ? inactivePreview.shadow.paddingTop : 0);});
|
||||
anchors.bottomMargin = Qt.binding(function() { return 40 - (inactivePreview.shadow ? inactivePreview.shadow.paddingBottom : 0);});
|
||||
}
|
||||
}
|
||||
KDecoration.Decoration {
|
||||
id: activePreview
|
||||
bridge: bridgeItem.bridge
|
||||
settings: settingsItem
|
||||
anchors.fill: parent
|
||||
Component.onCompleted: {
|
||||
client.caption = decorationPreviews.themeName
|
||||
client.active = true;
|
||||
anchors.leftMargin = Qt.binding(function() { return 10 - (activePreview.shadow ? activePreview.shadow.paddingLeft : 0);});
|
||||
anchors.rightMargin = Qt.binding(function() { return 40 - (activePreview.shadow ? activePreview.shadow.paddingRight : 0);});
|
||||
anchors.topMargin = Qt.binding(function() { return 40 - (activePreview.shadow ? activePreview.shadow.paddingTop : 0);});
|
||||
anchors.bottomMargin = Qt.binding(function() { return 10 - (activePreview.shadow ? activePreview.shadow.paddingBottom : 0);});
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
hoverEnabled: false
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
gridView.currentIndex = index
|
||||
gridView.userChangedSelection()
|
||||
}
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
/* Create an invisible rectangle that's the same size as the inner content rect
|
||||
of the foreground window preview so that we can center the button within it.
|
||||
We have to center rather than using anchors because the button width varies
|
||||
with different localizations */
|
||||
Item {
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: 10
|
||||
right: parent.right
|
||||
rightMargin: 40
|
||||
top: parent.top
|
||||
topMargin: 68
|
||||
bottom: parent.bottom
|
||||
bottomMargin: 10
|
||||
}
|
||||
Button {
|
||||
id: configureButton
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
enabled: model["configureable"]
|
||||
iconName: "configure"
|
||||
text: i18n("Configure %1...", decorationPreviews.themeName)
|
||||
onClicked: {
|
||||
gridView.currentIndex = index
|
||||
gridView.userChangedSelection()
|
||||
bridgeItem.bridge.configure()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Layout.preferredHeight: 20 * units.gridUnit
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* 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 QtQuick.Layouts 1.1
|
||||
|
||||
Rectangle {
|
||||
color: backgroundColor
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
Previews {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
Buttons {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
119
kcmkwin/kwindecoration/utils.cpp
Normal file
119
kcmkwin/kwindecoration/utils.cpp
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Valerio Pilo <vpilo@coldshock.net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public License
|
||||
* along with this library; see the file COPYING.LIB. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include <KConfigGroup>
|
||||
#include <KLocalizedString>
|
||||
|
||||
namespace
|
||||
{
|
||||
const QMap<QString, KDecoration2::BorderSize> s_borderSizes {
|
||||
{ QStringLiteral("None"), KDecoration2::BorderSize::None },
|
||||
{ QStringLiteral("NoSides"), KDecoration2::BorderSize::NoSides },
|
||||
{ QStringLiteral("Tiny"), KDecoration2::BorderSize::Tiny },
|
||||
{ QStringLiteral("Normal"), KDecoration2::BorderSize::Normal },
|
||||
{ QStringLiteral("Large"), KDecoration2::BorderSize::Large },
|
||||
{ QStringLiteral("VeryLarge"), KDecoration2::BorderSize::VeryLarge },
|
||||
{ QStringLiteral("Huge"), KDecoration2::BorderSize::Huge },
|
||||
{ QStringLiteral("VeryHuge"), KDecoration2::BorderSize::VeryHuge },
|
||||
{ QStringLiteral("Oversized"), KDecoration2::BorderSize::Oversized }
|
||||
};
|
||||
const QMap<KDecoration2::BorderSize, QString> s_borderSizeNames {
|
||||
{ KDecoration2::BorderSize::None, i18n("No Borders") },
|
||||
{ KDecoration2::BorderSize::NoSides, i18n("No Side Borders") },
|
||||
{ KDecoration2::BorderSize::Tiny, i18n("Tiny") },
|
||||
{ KDecoration2::BorderSize::Normal, i18n("Normal") },
|
||||
{ KDecoration2::BorderSize::Large, i18n("Large") },
|
||||
{ KDecoration2::BorderSize::VeryLarge, i18n("Very Large") },
|
||||
{ KDecoration2::BorderSize::Huge, i18n("Huge") },
|
||||
{ KDecoration2::BorderSize::VeryHuge, i18n("Very Huge") },
|
||||
{ KDecoration2::BorderSize::Oversized, i18n("Oversized") }
|
||||
};
|
||||
|
||||
const QHash<KDecoration2::DecorationButtonType, QChar> s_buttonNames {
|
||||
{KDecoration2::DecorationButtonType::Menu, QChar('M') },
|
||||
{KDecoration2::DecorationButtonType::ApplicationMenu, QChar('N') },
|
||||
{KDecoration2::DecorationButtonType::OnAllDesktops, QChar('S') },
|
||||
{KDecoration2::DecorationButtonType::ContextHelp, QChar('H') },
|
||||
{KDecoration2::DecorationButtonType::Minimize, QChar('I') },
|
||||
{KDecoration2::DecorationButtonType::Maximize, QChar('A') },
|
||||
{KDecoration2::DecorationButtonType::Close, QChar('X') },
|
||||
{KDecoration2::DecorationButtonType::KeepAbove, QChar('F') },
|
||||
{KDecoration2::DecorationButtonType::KeepBelow, QChar('B') },
|
||||
{KDecoration2::DecorationButtonType::Shade, QChar('L') }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
|
||||
QString buttonsToString(const DecorationButtonsList &buttons)
|
||||
{
|
||||
auto buttonToString = [](KDecoration2::DecorationButtonType button) -> QChar {
|
||||
const auto it = s_buttonNames.constFind(button);
|
||||
if (it != s_buttonNames.constEnd()) {
|
||||
return it.value();
|
||||
}
|
||||
return QChar();
|
||||
};
|
||||
QString ret;
|
||||
for (auto button : buttons) {
|
||||
ret.append(buttonToString(button));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
DecorationButtonsList readDecorationButtons(const KConfigGroup &config, const QString &key, const DecorationButtonsList &defaultValue)
|
||||
{
|
||||
auto buttonsFromString = [](const QString &buttons) -> DecorationButtonsList {
|
||||
DecorationButtonsList ret;
|
||||
for (auto it = buttons.begin(); it != buttons.end(); ++it) {
|
||||
for (auto it2 = s_buttonNames.constBegin(); it2 != s_buttonNames.constEnd(); ++it2) {
|
||||
if (it2.value() == (*it)) {
|
||||
ret << it2.key();
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
return buttonsFromString(config.readEntry(key, buttonsToString(defaultValue)));
|
||||
}
|
||||
|
||||
KDecoration2::BorderSize stringToBorderSize(const QString &name)
|
||||
{
|
||||
auto it = s_borderSizes.constFind(name);
|
||||
if (it == s_borderSizes.constEnd()) {
|
||||
// non sense values are interpreted just like normal
|
||||
return KDecoration2::BorderSize::Normal;
|
||||
}
|
||||
return it.value();
|
||||
}
|
||||
|
||||
QString borderSizeToString(KDecoration2::BorderSize size)
|
||||
{
|
||||
return s_borderSizes.key(size);
|
||||
}
|
||||
|
||||
const QMap<KDecoration2::BorderSize, QString> &getBorderSizeNames()
|
||||
{
|
||||
return s_borderSizeNames;
|
||||
}
|
||||
|
||||
} // namespace Utils
|
40
kcmkwin/kwindecoration/utils.h
Normal file
40
kcmkwin/kwindecoration/utils.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Valerio Pilo <vpilo@coldshock.net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public License
|
||||
* along with this library; see the file COPYING.LIB. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <KDecoration2/DecorationButton>
|
||||
#include <KSharedConfig>
|
||||
|
||||
#include <QVector>
|
||||
|
||||
|
||||
using DecorationButtonsList = QVector<KDecoration2::DecorationButtonType>;
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
|
||||
QString buttonsToString(const DecorationButtonsList &buttons);
|
||||
DecorationButtonsList readDecorationButtons(const KConfigGroup &config, const QString &key, const DecorationButtonsList &defaultValue);
|
||||
|
||||
KDecoration2::BorderSize stringToBorderSize(const QString &name);
|
||||
QString borderSizeToString(KDecoration2::BorderSize size);
|
||||
|
||||
const QMap<KDecoration2::BorderSize, QString> &getBorderSizeNames();
|
||||
|
||||
}
|
67
kcmkwin/kwindecoration/window-decorations.knsrc
Normal file
67
kcmkwin/kwindecoration/window-decorations.knsrc
Normal file
|
@ -0,0 +1,67 @@
|
|||
[KNewStuff3]
|
||||
Name=Window Decorations
|
||||
Name[ar]=زخارف النوافذ
|
||||
Name[bg]=Декорации на прозорците
|
||||
Name[bs]=Dekoracije prozora
|
||||
Name[ca]=Decoració de les finestres
|
||||
Name[ca@valencia]=Decoració de les finestres
|
||||
Name[cs]=Dekorace oken
|
||||
Name[da]=Vinduesdekorationer
|
||||
Name[de]=Fensterdekoration
|
||||
Name[el]=Διακοσμήσεις παραθύρου
|
||||
Name[en_GB]=Window Decorations
|
||||
Name[es]=Decoración de ventanas
|
||||
Name[et]=Akna dekoratsioonid
|
||||
Name[eu]=Leiho-apaindurak
|
||||
Name[fi]=Ikkunakehykset
|
||||
Name[fr]=Décorations de fenêtres
|
||||
Name[ga]=Maisiúcháin Fhuinneog
|
||||
Name[gl]=Decoración da xanela
|
||||
Name[he]=מסגרת חלון
|
||||
Name[hi]=विंडो सजावट
|
||||
Name[hr]=Ukrasi prozora
|
||||
Name[hu]=Ablakdekorációk
|
||||
Name[ia]=Decorationes de fenestra
|
||||
Name[id]=Dekorasi Window
|
||||
Name[is]=Gluggaskreytingar
|
||||
Name[it]=Decorazioni delle finestre
|
||||
Name[ja]=ウィンドウの飾り
|
||||
Name[kk]=Терезенің безендірулері
|
||||
Name[km]=ការតុបតែងបង្អួច
|
||||
Name[kn]=ವಿಂಡೋ ಅಲಂಕಾರಗಳು
|
||||
Name[ko]=창 장식
|
||||
Name[lt]=Lango dekoracijos
|
||||
Name[lv]=Logu dekorācijas
|
||||
Name[mr]=चौकट सजावट
|
||||
Name[nb]=Vinduspynt
|
||||
Name[nds]=Finstern opfladusen
|
||||
Name[nl]=Vensterdecoraties
|
||||
Name[nn]=Vindaugspynt
|
||||
Name[pa]=ਵਿੰਡੋ ਸਜਾਵਟ
|
||||
Name[pl]=Wygląd okien
|
||||
Name[pt]=Decorações das Janelas
|
||||
Name[pt_BR]=Decorações da janela
|
||||
Name[ro]=Decorații fereastră
|
||||
Name[ru]=Оформление окон
|
||||
Name[si]=කවුළු සැරසිලි
|
||||
Name[sk]=Dekorácie okien
|
||||
Name[sl]=Okraski oken
|
||||
Name[sr]=Декорације прозора
|
||||
Name[sr@ijekavian]=Декорације прозора
|
||||
Name[sr@ijekavianlatin]=Dekoracije prozora
|
||||
Name[sr@latin]=Dekoracije prozora
|
||||
Name[sv]=Fönsterdekorationer
|
||||
Name[th]=ส่วนตกแต่งหน้าต่าง
|
||||
Name[tr]=Pencere Dekorasyonları
|
||||
Name[ug]=كۆزنەك بېزەكلىرى
|
||||
Name[uk]=Обрамлення вікон
|
||||
Name[wa]=Gåyotaedjes des fniesses
|
||||
Name[x-test]=xxWindow Decorationsxx
|
||||
Name[zh_CN]=窗口装饰
|
||||
Name[zh_TW]=視窗裝飾
|
||||
|
||||
ProvidersUrl=https://autoconfig.kde.org/ocs/providers.xml
|
||||
Categories=Various Plasma Styles,Aurorae Themes
|
||||
TargetDir=themes
|
||||
StandardResource=tmp
|
||||
Uncompress=archive
|
Loading…
Reference in a new issue