diff --git a/kcms/ksplash/kcm.cpp b/kcms/ksplash/kcm.cpp index 4d321cc9c..565932015 100644 --- a/kcms/ksplash/kcm.cpp +++ b/kcms/ksplash/kcm.cpp @@ -1,212 +1,227 @@ /* This file is part of the KDE Project Copyright (c) 2014 Marco Martin Copyright (c) 2014 Vishesh Handa 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 #include #include #include K_PLUGIN_FACTORY_WITH_JSON(KCMSplashScreenFactory, "kcm_splashscreen.json", registerPlugin();) KCMSplashScreen::KCMSplashScreen(QObject* parent, const QVariantList& args) : KQuickAddons::ConfigModule(parent, args) , m_config(QStringLiteral("ksplashrc")) , m_configGroup(m_config.group("KSplash")) { qmlRegisterType(); KAboutData* about = new KAboutData(QStringLiteral("kcm_splashscreen"), i18n("Splash Screen"), QStringLiteral("0.1"), QString(), KAboutLicense::LGPL); about->addAuthor(i18n("Marco Martin"), QString(), QStringLiteral("mart@kde.org")); setAboutData(about); setButtons(Help | Apply | Default); m_model = new QStandardItemModel(this); QHash roles = m_model->roleNames(); roles[PluginNameRole] = "pluginName"; roles[ScreenhotRole] = "screenshot"; roles[DescriptionRole] = "description"; m_model->setItemRoleNames(roles); loadModel(); } QList KCMSplashScreen::availablePackages(const QString &component) { QList packages; QStringList paths; const QStringList dataPaths = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); for (const QString &path : dataPaths) { QDir dir(path + QStringLiteral("/plasma/look-and-feel")); paths << dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); } for (const QString &path : paths) { Plasma::Package pkg = Plasma::PluginLoader::self()->loadPackage(QStringLiteral("Plasma/LookAndFeel")); pkg.setPath(path); pkg.setFallbackPackage(Plasma::Package()); if (component.isEmpty() || !pkg.filePath(component.toUtf8()).isEmpty()) { packages << pkg; } } return packages; } QStandardItemModel *KCMSplashScreen::splashModel() { return m_model; } QString KCMSplashScreen::selectedPlugin() const { return m_selectedPlugin; } void KCMSplashScreen::setSelectedPlugin(const QString &plugin) { if (m_selectedPlugin == plugin) { return; } if (!m_selectedPlugin.isEmpty()) { setNeedsSave(true); } m_selectedPlugin = plugin; emit selectedPluginChanged(); emit selectedPluginIndexChanged(); } void KCMSplashScreen::getNewClicked() { KNS3::DownloadDialog dialog("ksplash.knsrc", nullptr); if (dialog.exec()) { KNS3::Entry::List list = dialog.changedEntries(); if (!list.isEmpty()) { loadModel(); } } } void KCMSplashScreen::loadModel() { m_model->clear(); const QList pkgs = availablePackages(QStringLiteral("splashmainscript")); for (const Plasma::Package &pkg : pkgs) { QStandardItem* row = new QStandardItem(pkg.metadata().name()); row->setData(pkg.metadata().pluginName(), PluginNameRole); row->setData(pkg.filePath("previews", QStringLiteral("splash.png")), ScreenhotRole); row->setData(pkg.metadata().comment(), DescriptionRole); m_model->appendRow(row); } m_model->sort(0 /*column*/); QStandardItem* row = new QStandardItem(i18n("None")); row->setData("None", PluginNameRole); row->setData(i18n("No splash screen will be shown"), DescriptionRole); m_model->insertRow(0, row); emit selectedPluginIndexChanged(); } void KCMSplashScreen::load() { m_package = Plasma::PluginLoader::self()->loadPackage(QStringLiteral("Plasma/LookAndFeel")); KConfigGroup cg(KSharedConfig::openConfig(QStringLiteral("kdeglobals")), "KDE"); const QString packageName = cg.readEntry("LookAndFeelPackage", QString()); if (!packageName.isEmpty()) { m_package.setPath(packageName); } QString currentPlugin = m_configGroup.readEntry("Theme", QString()); if (currentPlugin.isEmpty()) { currentPlugin = m_package.metadata().pluginName(); } setSelectedPlugin(currentPlugin); setNeedsSave(false); } void KCMSplashScreen::save() { if (m_selectedPlugin.isEmpty()) { return; } else if (m_selectedPlugin == QLatin1String("None")) { m_configGroup.writeEntry("Theme", m_selectedPlugin); m_configGroup.writeEntry("Engine", "none"); } else { m_configGroup.writeEntry("Theme", m_selectedPlugin); m_configGroup.writeEntry("Engine", "KSplashQML"); } m_configGroup.sync(); setNeedsSave(false); } void KCMSplashScreen::defaults() { if (!m_package.metadata().isValid()) { return; } setSelectedPlugin(m_package.metadata().pluginName()); } int KCMSplashScreen::selectedPluginIndex() const { for (int i = 0; i < m_model->rowCount(); ++i) { if (m_model->data(m_model->index(i, 0), PluginNameRole).toString() == m_selectedPlugin) { return i; } } return -1; } +bool KCMSplashScreen::testing() const +{ + return m_testProcess; +} + void KCMSplashScreen::test(const QString &plugin) { - if (plugin.isEmpty() || plugin == QLatin1String("None")) { + if (plugin.isEmpty() || plugin == QLatin1String("None") || m_testProcess) { return; } - QProcess proc; - QStringList arguments; - arguments << plugin << QStringLiteral("--test"); - if (proc.execute(QStringLiteral("ksplashqml"), arguments)) { - QMessageBox::critical(nullptr, i18n("Error"), i18n("Failed to successfully test the splash screen.")); - } + m_testProcess = new QProcess(this); + connect(m_testProcess, &QProcess::errorOccurred, this, [this](QProcess::ProcessError error) { + Q_UNUSED(error); + emit testingFailed(); + }); + connect(m_testProcess, QOverload::of(&QProcess::finished), this, + [this](int exitCode, QProcess::ExitStatus exitStatus) { + Q_UNUSED(exitCode); + Q_UNUSED(exitStatus); + + m_testProcess->deleteLater(); + m_testProcess = nullptr; + emit testingChanged(); + }); + + emit testingChanged(); + m_testProcess->start(QStringLiteral("ksplashqml"), {plugin, QStringLiteral("--test")}); } #include "kcm.moc" diff --git a/kcms/ksplash/kcm.h b/kcms/ksplash/kcm.h index 6ac8f0ee2..966977f2b 100644 --- a/kcms/ksplash/kcm.h +++ b/kcms/ksplash/kcm.h @@ -1,77 +1,85 @@ /* Copyright (c) 2014 Marco Martin Copyright (c) 2014 Vishesh Handa 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_SEARCH_H #define _KCM_SEARCH_H #include #include #include #include class QStandardItemModel; class KCMSplashScreen : public KQuickAddons::ConfigModule { Q_OBJECT Q_PROPERTY(QStandardItemModel *splashModel READ splashModel CONSTANT) Q_PROPERTY(QString selectedPlugin READ selectedPlugin WRITE setSelectedPlugin NOTIFY selectedPluginChanged) Q_PROPERTY(int selectedPluginIndex READ selectedPluginIndex NOTIFY selectedPluginIndexChanged) + Q_PROPERTY(bool testing READ testing NOTIFY testingChanged) public: enum Roles { PluginNameRole = Qt::UserRole +1, ScreenhotRole, DescriptionRole }; KCMSplashScreen(QObject* parent, const QVariantList& args); QList availablePackages(const QString &component); QStandardItemModel *splashModel(); QString selectedPlugin() const; void setSelectedPlugin(const QString &plugin); int selectedPluginIndex() const; + bool testing() const; + void loadModel(); public Q_SLOTS: void getNewClicked(); void load() override; void save() override; void defaults() override; void test(const QString &plugin); Q_SIGNALS: void selectedPluginChanged(); void selectedPluginIndexChanged(); + void testingChanged(); + void testingFailed(); + private: QStandardItemModel *m_model; Plasma::Package m_package; QString m_selectedPlugin; + QProcess *m_testProcess = nullptr; + KConfig m_config; KConfigGroup m_configGroup; }; #endif diff --git a/kcms/ksplash/package/contents/ui/main.qml b/kcms/ksplash/package/contents/ui/main.qml index 582f0b010..1c4397c6d 100644 --- a/kcms/ksplash/package/contents/ui/main.qml +++ b/kcms/ksplash/package/contents/ui/main.qml @@ -1,68 +1,87 @@ /* Copyright (c) 2014 Marco Martin 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.Controls 1.0 as QtControls import org.kde.kirigami 2.4 as Kirigami import org.kde.kconfig 1.0 // for KAuthorized import org.kde.kcm 1.1 as KCM KCM.GridViewKCM { KCM.ConfigModule.quickHelp: i18n("This module lets you choose the splash screen theme.") + enabled: !kcm.testing + view.model: kcm.splashModel //NOTE: pay attention to never break this binding view.currentIndex: kcm.selectedPluginIndex + + // putting the InlineMessage as header item causes it to show up initially despite visible false + header: ColumnLayout { + Kirigami.InlineMessage { + id: testingFailedLabel + Layout.fillWidth: true + showCloseButton: true + type: Kirigami.MessageType.Error + text: i18n("Failed to test the splash screen.") + + Connections { + target: kcm + onTestingFailed: testingFailedLabel.visible = true + } + } + } + view.delegate: KCM.GridDelegate { id: delegate text: model.display toolTip: model.description thumbnailAvailable: !!model.screenshot thumbnail: Image { anchors.fill: parent source: model.screenshot || "" } actions: [ Kirigami.Action { visible: model.pluginName !== "None" iconName: "media-playback-start" tooltip: i18n("Preview Splash Screen") onTriggered: kcm.test(model.pluginName) } ] onClicked: { kcm.selectedPlugin = model.pluginName; view.forceActiveFocus(); } } footer: RowLayout { Item { Layout.fillWidth: true } QtControls.Button { iconName: "get-hot-new-stuff" text: i18n("&Get New Splash Screens...") onClicked: kcm.getNewClicked(); visible: KAuthorized.authorize("ghns") } } }