File indexing completed on 2024-11-10 04:56:52

0001 /*
0002     SPDX-FileCopyrightText: 2011 Tamas Krutki <ktamasw@gmail.com>
0003     SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 #include "module.h"
0008 
0009 #include <QDBusConnection>
0010 #include <QDBusMessage>
0011 #include <QDBusPendingCall>
0012 #include <QFileDialog>
0013 #include <QStringList>
0014 
0015 #include <KCMultiDialog>
0016 #include <KConfigGroup>
0017 #include <KLocalizedString>
0018 #include <KPackage/Package>
0019 #include <KPackage/PackageJob>
0020 #include <KPackage/PackageLoader>
0021 #include <KSharedConfig>
0022 
0023 #include "kwinscriptsdata.h"
0024 
0025 Module::Module(QObject *parent, const KPluginMetaData &data)
0026     : KQuickConfigModule(parent, data)
0027     , m_kwinScriptsData(new KWinScriptsData(this))
0028     , m_model(new KPluginModel(this))
0029 {
0030     // Hide the help button, because there is no help
0031     setButtons(Apply | Default);
0032     connect(m_model, &KPluginModel::isSaveNeededChanged, this, [this]() {
0033         setNeedsSave(m_model->isSaveNeeded() || !m_pendingDeletions.isEmpty());
0034     });
0035     connect(m_model, &KPluginModel::defaulted, this, [this](bool defaulted) {
0036         setRepresentsDefaults(defaulted);
0037     });
0038     m_model->setConfig(KSharedConfig::openConfig("kwinrc")->group(QStringLiteral("Plugins")));
0039 }
0040 
0041 void Module::onGHNSEntriesChanged()
0042 {
0043     m_model->clear();
0044     m_model->addPlugins(m_kwinScriptsData->pluginMetaDataList(), QString());
0045 }
0046 
0047 void Module::importScript()
0048 {
0049     QString path = QFileDialog::getOpenFileName(nullptr, i18n("Import KWin Script"), QDir::homePath(),
0050                                                 i18n("*.kwinscript|KWin scripts (*.kwinscript)"));
0051 
0052     if (path.isNull()) {
0053         return;
0054     }
0055 
0056     using namespace KPackage;
0057 
0058     auto job = PackageJob::update(QStringLiteral("KWin/Script"), path);
0059     connect(job, &KJob::result, this, [job, this]() {
0060         if (job->error() != KJob::NoError) {
0061             setErrorMessage(i18nc("Placeholder is error message returned from the install service", "Cannot import selected script.\n%1", job->errorString()));
0062             return;
0063         }
0064 
0065         m_infoMessage = i18nc("Placeholder is name of the script that was imported", "The script \"%1\" was successfully imported.", job->package().metadata().name());
0066         m_errorMessage.clear();
0067         Q_EMIT messageChanged();
0068 
0069         m_model->clear();
0070         m_model->addPlugins(m_kwinScriptsData->pluginMetaDataList(), QString());
0071 
0072         setNeedsSave(false);
0073     });
0074 }
0075 
0076 void Module::configure(const KPluginMetaData &data)
0077 {
0078     auto dialog = new KCMultiDialog();
0079     dialog->addModule(data, QVariantList{data.pluginId(), QStringLiteral("KWin/Script")});
0080     dialog->setAttribute(Qt::WA_DeleteOnClose);
0081     dialog->show();
0082 }
0083 
0084 void Module::togglePendingDeletion(const KPluginMetaData &data)
0085 {
0086     if (m_pendingDeletions.contains(data)) {
0087         m_pendingDeletions.removeOne(data);
0088     } else {
0089         m_pendingDeletions.append(data);
0090     }
0091     setNeedsSave(m_model->isSaveNeeded() || !m_pendingDeletions.isEmpty());
0092     Q_EMIT pendingDeletionsChanged();
0093 }
0094 
0095 void Module::defaults()
0096 {
0097     m_model->defaults();
0098     m_pendingDeletions.clear();
0099     Q_EMIT pendingDeletionsChanged();
0100 
0101     setNeedsSave(m_model->isSaveNeeded());
0102 }
0103 
0104 void Module::load()
0105 {
0106     m_model->clear();
0107     m_model->addPlugins(m_kwinScriptsData->pluginMetaDataList(), QString());
0108     m_pendingDeletions.clear();
0109     Q_EMIT pendingDeletionsChanged();
0110 
0111     setNeedsSave(false);
0112 }
0113 
0114 void Module::save()
0115 {
0116     using namespace KPackage;
0117     for (const KPluginMetaData &info : std::as_const(m_pendingDeletions)) {
0118         // We can get the package root from the entry path
0119         QDir root = QFileInfo(info.fileName()).dir();
0120         root.cdUp();
0121         KJob *uninstallJob = PackageJob::uninstall(QStringLiteral("KWin/Script"), info.pluginId(), root.absolutePath());
0122         connect(uninstallJob, &KJob::result, this, [this, uninstallJob]() {
0123             if (!uninstallJob->errorString().isEmpty()) {
0124                 setErrorMessage(i18n("Error when uninstalling KWin Script: %1", uninstallJob->errorString()));
0125             } else {
0126                 load(); // Make sure to reload the KCM to deleted entries to disappear
0127             }
0128         });
0129     }
0130 
0131     m_infoMessage.clear();
0132     Q_EMIT messageChanged();
0133     m_pendingDeletions.clear();
0134     Q_EMIT pendingDeletionsChanged();
0135 
0136     m_model->save();
0137     QDBusMessage message = QDBusMessage::createMethodCall("org.kde.KWin", "/Scripting", "org.kde.kwin.Scripting", "start");
0138     QDBusConnection::sessionBus().asyncCall(message);
0139 
0140     setNeedsSave(false);
0141 }
0142 
0143 K_PLUGIN_FACTORY_WITH_JSON(KcmKWinScriptsFactory, "kcm_kwin_scripts.json",
0144                            registerPlugin<Module>();
0145                            registerPlugin<KWinScriptsData>();)
0146 
0147 #include "module.moc"
0148 
0149 #include "moc_module.cpp"