diff --git a/kcms/CMakeLists.txt b/kcms/CMakeLists.txt --- a/kcms/CMakeLists.txt +++ b/kcms/CMakeLists.txt @@ -27,7 +27,8 @@ add_subdirectory( colors ) add_subdirectory( krdb ) add_subdirectory( style ) -add_subdirectory( desktoptheme ) +# add_subdirectory( desktoptheme ) +add_subdirectory( desktoptheme-qml ) add_subdirectory( standard_actions ) add_subdirectory( keys ) add_subdirectory( ksmserver ) diff --git a/kcms/desktoptheme-qml/CMakeLists.txt b/kcms/desktoptheme-qml/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/kcms/desktoptheme-qml/CMakeLists.txt @@ -0,0 +1,26 @@ +# KI18N Translation Domain for this library +add_definitions(-DTRANSLATION_DOMAIN=\"kcm_desktoptheme\") + +set(kcm_desktoptheme_SRCS + kcm.cpp +) + +add_library(kcm_desktoptheme MODULE ${kcm_desktoptheme_SRCS}) + +target_link_libraries(kcm_desktoptheme + KF5::CoreAddons + KF5::KCMUtils + KF5::I18n + KF5::Plasma + KF5::Declarative + KF5::QuickAddons + KF5::NewStuff +) + +kcoreaddons_desktop_to_json(kcm_desktoptheme "kcm_desktoptheme.desktop") + +#this desktop file is installed only for retrocompatibility with sycoca +install(FILES kcm_desktoptheme.desktop DESTINATION ${SERVICES_INSTALL_DIR}) +install(TARGETS kcm_desktoptheme DESTINATION ${PLUGIN_INSTALL_DIR}/kcms) + +kpackage_install_package(package kcm_desktoptheme kcms) diff --git a/kcms/desktoptheme-qml/Messages.sh b/kcms/desktoptheme-qml/Messages.sh new file mode 100755 --- /dev/null +++ b/kcms/desktoptheme-qml/Messages.sh @@ -0,0 +1,4 @@ +#! /usr/bin/env bash +$EXTRACTRC `find . -name "*.ui"` >> rc.cpp || exit 11 +$XGETTEXT `find . -name "*.cpp" -o -name "*.qml"` -o $podir/kcm_desktoptheme.pot +rm -f rc.cpp diff --git a/kcms/desktoptheme-qml/kcm.h b/kcms/desktoptheme-qml/kcm.h new file mode 100644 --- /dev/null +++ b/kcms/desktoptheme-qml/kcm.h @@ -0,0 +1,82 @@ +/* + Copyright (c) 2014 Marco Martin + Copyright (c) 2014 Vishesh Handa + Copyright (c) 2016 David Rosca + + 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. +*/ + +#ifndef _KCM_DESKTOPTHEME_H +#define _KCM_DESKTOPTHEME_H + +#include + +namespace Plasma { + class Svg; + class Theme; +} + +class QStandardItemModel; + +class KCMDesktopTheme : public KQuickAddons::ConfigModule +{ + Q_OBJECT + Q_PROPERTY(QStandardItemModel *desktopThemeModel READ desktopThemeModel CONSTANT) + Q_PROPERTY(QString selectedPlugin READ selectedPlugin WRITE setSelectedPlugin NOTIFY selectedPluginChanged) + +public: + enum Roles { + PluginNameRole = Qt::UserRole + 1, + ThemeNameRole, + IsLocalRole + }; + Q_ENUM(Roles) + + KCMDesktopTheme(QObject *parent, const QVariantList &args); + ~KCMDesktopTheme(); + + QStandardItemModel *desktopThemeModel() const; + + QString selectedPlugin() const; + void setSelectedPlugin(const QString &plugin); + + Q_INVOKABLE void getNewThemes(); + Q_INVOKABLE void installThemeFromFile(const QUrl &file); + Q_INVOKABLE void removeTheme(const QString &name); + + Q_INVOKABLE void applyPlasmaTheme(QQuickItem *item, const QString &themeName); + +Q_SIGNALS: + void selectedPluginChanged(const QString &plugin); + void showInfoMessage(const QString &infoMessage); + +public Q_SLOTS: + void load(); + void save(); + void defaults(); + +private: + void removeThemes(); + + QStandardItemModel *m_model; + QString m_selectedPlugin; + QStringList m_pendingRemoval; + Plasma::Theme *m_defaultTheme; + QHash m_themes; +}; + +Q_DECLARE_LOGGING_CATEGORY(KCM_DESKTOP_THEME) + +#endif // _KCM_DESKTOPTHEME_H diff --git a/kcms/desktoptheme-qml/kcm.cpp b/kcms/desktoptheme-qml/kcm.cpp new file mode 100644 --- /dev/null +++ b/kcms/desktoptheme-qml/kcm.cpp @@ -0,0 +1,271 @@ +/* This file is part of the KDE Project + Copyright (c) 2014 Marco Martin + Copyright (c) 2014 Vishesh Handa + Copyright (c) 2016 David Rosca + + 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 "kcm.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +Q_LOGGING_CATEGORY(KCM_DESKTOP_THEME, "kcm_desktoptheme") + +K_PLUGIN_FACTORY_WITH_JSON(KCMDesktopThemeFactory, "kcm_desktoptheme.json", registerPlugin();) + +KCMDesktopTheme::KCMDesktopTheme(QObject *parent, const QVariantList &args) + : KQuickAddons::ConfigModule(parent, args) + , m_defaultTheme(new Plasma::Theme(this)) +{ + //This flag seems to be needed in order for QQuickWidget to work + //see https://bugreports.qt-project.org/browse/QTBUG-40765 + //also, it seems to work only if set in the kcm, not in the systemsettings' main + qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); + qmlRegisterType(); + + KAboutData* about = new KAboutData(QStringLiteral("kcm_desktoptheme"), i18n("Configure Desktop Theme"), + QStringLiteral("0.1"), QString(), KAboutLicense::LGPL); + about->addAuthor(i18n("David Rosca"), QString(), QStringLiteral("nowrep@gmail.com")); + setAboutData(about); + setButtons(Apply | Default); + + m_model = new QStandardItemModel(this); + QHash roles = m_model->roleNames(); + roles[PluginNameRole] = "pluginName"; + roles[ThemeNameRole] = "themeName"; + roles[IsLocalRole] = "isLocal"; + m_model->setItemRoleNames(roles); +} + +KCMDesktopTheme::~KCMDesktopTheme() +{ + qDeleteAll(m_themes); + delete m_defaultTheme; +} + +QStandardItemModel *KCMDesktopTheme::desktopThemeModel() const +{ + return m_model; +} + +QString KCMDesktopTheme::selectedPlugin() const +{ + return m_selectedPlugin; +} + +void KCMDesktopTheme::setSelectedPlugin(const QString &plugin) +{ + if (m_selectedPlugin == plugin) { + return; + } + m_selectedPlugin = plugin; + Q_EMIT selectedPluginChanged(m_selectedPlugin); + setNeedsSave(true); +} + +void KCMDesktopTheme::getNewThemes() +{ + KNS3::DownloadDialog dialog(QStringLiteral("plasma-themes.knsrc")); + dialog.exec(); + KNS3::Entry::List entries = dialog.changedEntries(); + + if (!entries.isEmpty()) { + load(); + } +} + +void KCMDesktopTheme::installThemeFromFile(const QUrl &file) +{ + qCDebug(KCM_DESKTOP_THEME) << "Installing ... " << file; + + QString program = QStringLiteral("plasmapkg2"); + QStringList arguments; + arguments << QStringLiteral("-t") << QStringLiteral("theme") << QStringLiteral("-i") << file.toLocalFile(); + + qCDebug(KCM_DESKTOP_THEME) << program << arguments.join(QStringLiteral(" ")); + QProcess *myProcess = new QProcess(this); + connect(myProcess, static_cast(&QProcess::finished), + this, [this](int exitCode, QProcess::ExitStatus exitStatus) { + Q_UNUSED(exitStatus); + if (exitCode == 0) { + qCDebug(KCM_DESKTOP_THEME) << "Theme installed successfully :)"; + load(); + Q_EMIT showInfoMessage(i18n("Theme installed successfully.")); + } else { + qCWarning(KCM_DESKTOP_THEME) << "Theme installation failed."; + Q_EMIT showInfoMessage(i18n("Theme installation failed. (%1)", exitCode)); + } + }); + + connect(myProcess, static_cast(&QProcess::error), + this, [this](QProcess::ProcessError e) { + qCWarning(KCM_DESKTOP_THEME) << "Theme installation failed: " << e; + Q_EMIT showInfoMessage(i18n("Theme installation failed.")); + }); + + myProcess->start(program, arguments); +} + +void KCMDesktopTheme::removeTheme(const QString &name) +{ + Q_ASSERT(!m_pendingRemoval.contains(name)); + Q_ASSERT(!m_model->findItems(name).isEmpty()); + + m_pendingRemoval.append(name); + m_model->removeRow(m_model->findItems(name).at(0)->row()); + + setNeedsSave(true); +} + +void KCMDesktopTheme::applyPlasmaTheme(QQuickItem *item, const QString &themeName) +{ + if (!item) { + return; + } + + // Plasma::Theme *theme = m_themes[themeName]; + Plasma::Theme *theme = Q_NULLPTR; + if (!theme) { + theme = new Plasma::Theme(themeName); + m_themes[themeName] = theme; + } + + Q_FOREACH (Plasma::Svg *svg, item->findChildren()) { + svg->setTheme(theme); + svg->setUsingRenderingCache(false); + } +} + +void KCMDesktopTheme::load() +{ + m_pendingRemoval.clear(); + + // Get all desktop themes + QStringList themes; + const QStringList &packs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("plasma/desktoptheme"), QStandardPaths::LocateDirectory); + Q_FOREACH(const QString &ppath, packs) { + const QDir cd(ppath); + const QStringList &entries = cd.entryList(QDir::Dirs | QDir::Hidden); + Q_FOREACH(const QString pack, entries) { + const QString _metadata = ppath + QLatin1Char('/') + pack + QStringLiteral("/metadata.desktop"); + if ((pack != QLatin1String(".") && pack != QLatin1String("..")) && (QFile::exists(_metadata))) { + themes << _metadata; + } + } + } + + m_model->clear(); + + Q_FOREACH(const QString &theme, themes) { + int themeSepIndex = theme.lastIndexOf('/', -1); + QString themeRoot = theme.left(themeSepIndex); + int themeNameSepIndex = themeRoot.lastIndexOf('/', -1); + QString packageName = themeRoot.right(themeRoot.length() - themeNameSepIndex - 1); + + KDesktopFile df(theme); + + if (df.noDisplay()) { + continue; + } + + QString name = df.readName(); + if (name.isEmpty()) { + name = packageName; + } + const bool isLocal = QFileInfo(theme).isWritable(); + + // if (m_model->match(m_model->index(0, 0), PluginNameRole, packageName, 1, Qt::MatchExactly).isEmpty()) { + if (m_model->findItems(packageName).isEmpty()) { + QStandardItem *item = new QStandardItem; + item->setText(packageName); + item->setData(packageName, PluginNameRole); + item->setData(name, ThemeNameRole); + item->setData(isLocal, IsLocalRole); + m_model->appendRow(item); + } + } + + KConfigGroup cg(KSharedConfig::openConfig(QStringLiteral("plasmarc")), "Theme"); + setSelectedPlugin(cg.readEntry("name", m_defaultTheme->themeName())); + + setNeedsSave(false); +} + +void KCMDesktopTheme::save() +{ + if (m_defaultTheme->themeName() == m_selectedPlugin) { + return; + } + + m_defaultTheme->setThemeName(m_selectedPlugin); + removeThemes(); + setNeedsSave(false); +} + +void KCMDesktopTheme::defaults() +{ + setSelectedPlugin(QStringLiteral("default")); +} + +void KCMDesktopTheme::removeThemes() +{ + QString program = QStringLiteral("plasmapkg2"); + + Q_FOREACH (const QString &name, m_pendingRemoval) { + QStringList arguments; + arguments << QStringLiteral("-t") << QStringLiteral("theme") << QStringLiteral("-r") << name; + qCDebug(KCM_DESKTOP_THEME) << program << arguments.join(QStringLiteral(" ")); + QProcess *process = new QProcess(this); + connect(process, static_cast(&QProcess::finished), + this, [this, process](int exitCode, QProcess::ExitStatus exitStatus) { + Q_UNUSED(exitStatus); + if (exitCode == 0) { + qCDebug(KCM_DESKTOP_THEME) << "Theme removed successfully :)"; + load(); + } else { + qCWarning(KCM_DESKTOP_THEME) << "Theme removal failed."; + Q_EMIT showInfoMessage(i18n("Theme removal failed. (%1)", exitCode)); + } + process->deleteLater(); + }); + + connect(process, static_cast(&QProcess::error), + this, [this, process](QProcess::ProcessError e) { + qCWarning(KCM_DESKTOP_THEME) << "Theme removal failed: " << e; + Q_EMIT showInfoMessage(i18n("Theme removal failed.")); + process->deleteLater(); + }); + + process->start(program, arguments); + } +} + +#include "kcm.moc" diff --git a/kcms/desktoptheme-qml/kcm_desktoptheme.desktop b/kcms/desktoptheme-qml/kcm_desktoptheme.desktop new file mode 100644 --- /dev/null +++ b/kcms/desktoptheme-qml/kcm_desktoptheme.desktop @@ -0,0 +1,14 @@ +[Desktop Entry] +Icon=preferences-desktop +Exec=kcmshell5 kcm_desktoptheme + +Type=Service +X-KDE-ServiceTypes=KCModule +X-KDE-Library=kcm_desktoptheme +X-KDE-ParentApp=kcontrol +X-KDE-System-Settings-Parent-Category=workspacetheme +X-KDE-Weight=40 + +Name=Desktop Theme +Comment=Desktop Theme +X-KDE-Keywords=Desktop Theme diff --git a/kcms/desktoptheme-qml/package/contents/ui/Hand.qml b/kcms/desktoptheme-qml/package/contents/ui/Hand.qml new file mode 100644 --- /dev/null +++ b/kcms/desktoptheme-qml/package/contents/ui/Hand.qml @@ -0,0 +1,58 @@ +/* + * Copyright 2012 Viranch Mehta + * Copyright 2012 Marco Martin + * Copyright 2013 David Edmundson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.0 + +import org.kde.plasma.core 2.0 as PlasmaCore + +PlasmaCore.SvgItem { + id: secondHand + + property alias rotation: rotation.angle + property double svgScale + + width: naturalSize.width * svgScale + height: naturalSize.height * svgScale + anchors { + top: clock.verticalCenter + topMargin: -width/2 + horizontalCenter: clock.horizontalCenter + } + svg: clockSvg + smooth: !anim.running + transform: Rotation { + id: rotation + angle: 0 + origin { + x: width/2 + y: width/2 + } + Behavior on angle { + RotationAnimation { + id: anim + duration: 200 + direction: RotationAnimation.Clockwise + easing.type: Easing.OutElastic + easing.overshoot: 0.5 + } + } + } +} diff --git a/kcms/desktoptheme-qml/package/contents/ui/ThemePreview.qml b/kcms/desktoptheme-qml/package/contents/ui/ThemePreview.qml new file mode 100644 --- /dev/null +++ b/kcms/desktoptheme-qml/package/contents/ui/ThemePreview.qml @@ -0,0 +1,132 @@ +/* + Copyright (c) 2016 David Rosca + + 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.4 +import QtQuick.Layouts 1.1 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents + +Item { + id: root + property string themeName + + PlasmaCore.FrameSvgItem { + id: background + anchors.fill: parent + imagePath: themeName == "air" ? "widgets/panel-background" : "widgets/background" + } + + RowLayout { + id: contents + anchors { + fill: parent + topMargin: root.height / 8 + bottomMargin: root.height / 8 + leftMargin: root.width / 10 + rightMargin: root.width / 10 + } + + // Icons + ColumnLayout { + id: icons + Layout.fillHeight: true + + PlasmaCore.IconItem { + id: computerIcon + Layout.fillHeight: true + source: "computer" + } + + PlasmaCore.IconItem { + id: applicationsIcon + Layout.fillHeight: true + source: "applications-other" + } + + PlasmaCore.IconItem { + id: logoutIcon + Layout.fillHeight: true + source: "system-log-out" + } + } + + Item { + Layout.fillWidth: true + } + + // Analog clock + Item { + id: clock + Layout.fillHeight: true + Layout.preferredWidth: height + + property int hours : 9 + property int minutes : 5 + + PlasmaCore.Svg { + id: clockSvg + imagePath: "widgets/clock" + } + + PlasmaCore.SvgItem { + id: face + anchors.centerIn: parent + width: Math.min(parent.width, parent.height) + height: Math.min(parent.width, parent.height) + svg: clockSvg + elementId: "ClockFace" + } + + PlasmaCore.SvgItem { + anchors.fill: face + svg: clockSvg + elementId: "Glass" + width: naturalSize.width * face.width / face.naturalSize.width + height: naturalSize.height * face.width / face.naturalSize.width + } + + Hand { + anchors.topMargin: 3 + elementId: "HourHandShdow" + rotation: 180 + clock.hours * 30 + (clock.minutes/2) + svgScale: face.width / face.naturalSize.width + + } + Hand { + elementId: "HourHand" + rotation: 180 + clock.hours * 30 + (clock.minutes/2) + svgScale: face.width / face.naturalSize.width + } + + Hand { + anchors.topMargin: 3 + elementId: "MinuteHandShadow" + rotation: 180 + clock.minutes * 6 + svgScale: face.width / face.naturalSize.width + } + Hand { + elementId: "MinuteHand" + rotation: 180 + clock.minutes * 6 + svgScale: face.width / face.naturalSize.width + } + } + } + + Component.onCompleted: { + kcm.applyPlasmaTheme(root, themeName); + } +} diff --git a/kcms/desktoptheme-qml/package/contents/ui/main.qml b/kcms/desktoptheme-qml/package/contents/ui/main.qml new file mode 100644 --- /dev/null +++ b/kcms/desktoptheme-qml/package/contents/ui/main.qml @@ -0,0 +1,210 @@ +/* + Copyright (c) 2014 Marco Martin + Copyright (c) 2016 David Rosca + + 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.1 +import QtQuick.Layouts 1.1 +import QtQuick.Dialogs 1.0 +import QtQuick.Controls.Private 1.0 +import QtQuick.Controls 1.0 as QtControls + +import org.kde.kcm 1.0 +import org.kde.plasma.core 2.0 // for units + +Item { + implicitWidth: units.gridUnit * 20 + implicitHeight: units.gridUnit * 20 + + ConfigModule.quickHelp: i18n("This module lets you configure the desktop theme.") + + SystemPalette { + id: syspal + } + + ColumnLayout { + anchors.fill: parent + QtControls.ScrollView { + Layout.fillWidth: true + Layout.fillHeight: true + GridView { + id: grid + model: kcm.desktopThemeModel + cellWidth: Math.floor(grid.width / Math.max(Math.floor(grid.width / (units.gridUnit * 12)), 3)) + cellHeight: cellWidth / 1.6 + + delegate: Item { + property bool isLocal : model.isLocal + property string pluginName : model.pluginName + width: grid.cellWidth + height: grid.cellHeight + Rectangle { + anchors { + fill: parent + margins: units.smallSpacing + } + Connections { + target: kcm + onSelectedPluginChanged: { + if (kcm.selectedPlugin == model.pluginName) { + makeCurrentTimer.pendingIndex = index + } + } + } + Component.onCompleted: { + if (kcm.selectedPlugin == model.pluginName) { + makeCurrentTimer.pendingIndex = index + } + } + + Item { + anchors { + fill: parent + margins: units.smallSpacing * 2 + } + ThemePreview { + id: preview + anchors { + top: parent.top + left: parent.left + right: parent.right + bottom: label.top + } + themeName: model.pluginName + } + QtControls.Label { + id: label + anchors { + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + leftMargin: units.smallSpacing * 2 + rightMargin: units.smallSpacing * 2 + } + height: paintedHeight + width: parent.width + color: "black" + text: model.themeName + elide: Text.ElideRight + horizontalAlignment: Text.AlignHCenter + } + } + + Rectangle { + opacity: grid.currentIndex == index ? 1.0 : 0 + anchors.fill: parent + border.width: units.smallSpacing * 2 + border.color: syspal.highlight + color: "transparent" + Behavior on opacity { + PropertyAnimation { + duration: units.longDuration + easing.type: Easing.OutQuad + } + } + } + MouseArea { + anchors.fill: parent + hoverEnabled: true + onClicked: { + grid.currentIndex = index + kcm.selectedPlugin = model.pluginName + } + Timer { + interval: 1000 // FIXME TODO: Use platform value for tooltip activation delay. + running: parent.containsMouse && !parent.pressedButtons + onTriggered: { + Tooltip.showText(parent, Qt.point(parent.mouseX, parent.mouseY), model.themeName); + } + } + } + } + } + Timer { + id: makeCurrentTimer + interval: 100 + repeat: false + property int pendingIndex + onPendingIndexChanged: makeCurrentTimer.restart() + onTriggered: { + grid.currentIndex = pendingIndex + } + } + } + } + RowLayout { + QtControls.Button { + text: "Get new Theme" + iconName: "get-hot-new-stuff" + onClicked: kcm.getNewThemes() + } + + QtControls.Button { + text: "Install from File" + iconName: "document-import" + onClicked: fileDialog.open() + } + + QtControls.Button { + text: "Remove Theme" + iconName: "edit-delete" + enabled: grid.currentItem && grid.currentItem.isLocal + onClicked: { + kcm.removeTheme(grid.currentItem.pluginName); + updateSelectedPluginTimer.restart(); + } + } + + Item { + Layout.fillWidth: true + } + + QtControls.Label { + id: infoLabel + } + } + } + + Connections { + target: kcm + onShowInfoMessage: { + infoLabel.text = infoMessage; + hideInfoMessageTimer.restart(); + } + } + + Timer { + id: updateSelectedPluginTimer + interval: 100 + onTriggered: kcm.selectedPlugin = grid.currentItem.pluginName + } + + Timer { + id: hideInfoMessageTimer + interval: 20 * 1000 + onTriggered: { + infoLabel.text = "" + } + } + + FileDialog { + id: fileDialog + title: i18n("Open Theme") + folder: shortcuts.home + nameFilters: [ i18n("Theme Files (*.zip *.tar.gz *.tar.bz2)") ] + onAccepted: kcm.installThemeFromFile(fileUrls[0]) + } +} diff --git a/kcms/desktoptheme-qml/package/metadata.desktop b/kcms/desktoptheme-qml/package/metadata.desktop new file mode 100644 --- /dev/null +++ b/kcms/desktoptheme-qml/package/metadata.desktop @@ -0,0 +1,19 @@ +[Desktop Entry] +Name=Desktop Theme +Comment=Desktop Theme +Icon=preferences-desktop-theme +Encoding=UTF-8 +Keywords= +Type=Service +X-KDE-ParentApp= +X-KDE-PluginInfo-Author=David Rosca +X-KDE-PluginInfo-Email=nowrep@gmail.com +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-Name=kcm_desktoptheme +X-KDE-PluginInfo-Version= +X-KDE-PluginInfo-Website= +X-KDE-ServiceTypes=Plasma/Generic +X-Plasma-API=declarativeappletscript + +X-Plasma-MainScript=ui/main.qml +X-Plasma-RemoteLocation=