[ark] /: Introduce settings page to configure plugins

Elvis Angelaccio null at kde.org
Mon Dec 19 16:02:34 UTC 2016


Git commit cdaebc21b8fcde2001cc1fcd3239534cd904e65c by Elvis Angelaccio.
Committed on 19/12/2016 at 15:58.
Pushed by elvisangelaccio into branch 'master'.

Introduce settings page to configure plugins

This commit adds a page in the settings dialog where the user can enable/disable
plugins. The page contains a QTreeWidget which is not supported by
KConfigDialog out of the box, so some glue-code is necessary to
properly handle the Apply/Default buttons. ArkSettings stores a list of
disabled plugins (by default, all plugins are enabled).
If a plugin is not valid because of missing executables, the respective
item in the view is disabled and a warning is displayed in a tooltip.

Differential Revision: D3716
Task: T1984
GUI:

M  +2    -0    kerfuffle/CMakeLists.txt
M  +4    -0    kerfuffle/ark.kcfg
M  +6    -1    kerfuffle/plugin.cpp
M  +6    -0    kerfuffle/plugin.h
M  +3    -7    kerfuffle/pluginmanager.cpp
A  +108  -0    kerfuffle/pluginsettingspage.cpp     [License: BSD]
A  +59   -0    kerfuffle/pluginsettingspage.h     [License: BSD]
A  +38   -0    kerfuffle/pluginsettingspage.ui
M  +2    -0    part/part.cpp

https://commits.kde.org/ark/cdaebc21b8fcde2001cc1fcd3239534cd904e65c

diff --git a/kerfuffle/CMakeLists.txt b/kerfuffle/CMakeLists.txt
index 4bc4c441..8f846f6e 100644
--- a/kerfuffle/CMakeLists.txt
+++ b/kerfuffle/CMakeLists.txt
@@ -22,6 +22,7 @@ set(kerfuffle_SRCS
     mimetypes.cpp
     plugin.cpp
     pluginmanager.cpp
+    pluginsettingspage.cpp
     archiveentry.cpp
     options.cpp
 )
@@ -33,6 +34,7 @@ ki18n_wrap_ui(kerfuffle_SRCS
     extractiondialog.ui
     extractionsettingspage.ui
     generalsettingspage.ui
+    pluginsettingspage.ui
     previewsettingspage.ui
     propertiesdialog.ui
     compressionoptionswidget.ui
diff --git a/kerfuffle/ark.kcfg b/kerfuffle/ark.kcfg
index 2910cf7e..4777bfb6 100644
--- a/kerfuffle/ark.kcfg
+++ b/kerfuffle/ark.kcfg
@@ -46,6 +46,10 @@
 			<default>true</default>
 		</entry>
 	</group>
+	<group name="Plugins">
+		<entry name="disabledPlugins" type="StringList">
+		</entry>
+	</group>
 	<group name="Preview">
 		<entry name="limitPreviewFileSize" type="Bool">
 			<label>Whether to limit the preview according to file size.</label>
diff --git a/kerfuffle/plugin.cpp b/kerfuffle/plugin.cpp
index 4503492e..7c179b6a 100644
--- a/kerfuffle/plugin.cpp
+++ b/kerfuffle/plugin.cpp
@@ -93,9 +93,14 @@ KPluginMetaData Plugin::metaData() const
     return m_metaData;
 }
 
+bool Plugin::hasRequiredExecutables() const
+{
+    return findExecutables(readOnlyExecutables());
+}
+
 bool Plugin::isValid() const
 {
-    return isEnabled() && m_metaData.isValid() && findExecutables(readOnlyExecutables());
+    return isEnabled() && m_metaData.isValid() && hasRequiredExecutables();
 }
 
 bool Plugin::findExecutables(const QStringList &executables)
diff --git a/kerfuffle/plugin.h b/kerfuffle/plugin.h
index 17da7670..7558e6a8 100644
--- a/kerfuffle/plugin.h
+++ b/kerfuffle/plugin.h
@@ -86,6 +86,12 @@ public:
     KPluginMetaData metaData() const;
 
     /**
+     * @return Whether the executables required for a functional plugin are installed.
+     * This is true if all the read-only executables are found in the path.
+     */
+    bool hasRequiredExecutables() const;
+
+    /**
      * @return Whether the plugin is ready to be used.
      * This implies isEnabled(), while an enabled plugin may not be valid.
      * A read-write plugin downgraded to read-only is still valid.
diff --git a/kerfuffle/pluginmanager.cpp b/kerfuffle/pluginmanager.cpp
index 13edf1a0..883724e8 100644
--- a/kerfuffle/pluginmanager.cpp
+++ b/kerfuffle/pluginmanager.cpp
@@ -26,6 +26,8 @@
  */
 
 #include "pluginmanager.h"
+#include "ark_debug.h"
+#include "settings.h"
 
 #include <KConfigGroup>
 #include <KPluginLoader>
@@ -195,12 +197,6 @@ QVector<Plugin*> PluginManager::filterBy(const QVector<Plugin*> &plugins, const
 void PluginManager::loadPlugins()
 {
     const QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins(QStringLiteral("kerfuffle"));
-    // This class might be used from executables other than ark (e.g. the tests),
-    // so we need to specify the name of the config file.
-    // TODO: once we have a GUI in the settings dialog,
-    // use this group to write whether a plugin gets disabled.
-    const KConfigGroup conf(KSharedConfig::openConfig(QStringLiteral("arkrc")), "EnabledPlugins");
-
     QSet<QString> addedPlugins;
     foreach (const KPluginMetaData &metaData, plugins) {
         const auto pluginId = metaData.pluginId();
@@ -210,7 +206,7 @@ void PluginManager::loadPlugins()
         }
 
         Plugin *plugin = new Plugin(this, metaData);
-        plugin->setEnabled(conf.readEntry(pluginId, true));
+        plugin->setEnabled(!ArkSettings::disabledPlugins().contains(pluginId));
         addedPlugins << pluginId;
         m_plugins << plugin;
     }
diff --git a/kerfuffle/pluginsettingspage.cpp b/kerfuffle/pluginsettingspage.cpp
new file mode 100644
index 00000000..a3cbf168
--- /dev/null
+++ b/kerfuffle/pluginsettingspage.cpp
@@ -0,0 +1,108 @@
+/*
+ * ark -- archiver for the KDE project
+ *
+ * Copyright (C) 2016 Elvis Angelaccio <elvis.angelaccio at kde.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ( INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "pluginsettingspage.h"
+#include "ark_debug.h"
+
+#include <QTreeWidget>
+
+#include <KConfigDialogManager>
+
+namespace Kerfuffle
+{
+
+PluginSettingsPage::PluginSettingsPage(QWidget *parent, const QString &name, const QString &iconName)
+    : SettingsPage(parent, name, iconName)
+{
+    setupUi(this);
+
+    foreach (const auto plugin, m_pluginManager.installedPlugins()) {
+        const auto metaData = plugin->metaData();
+        auto item = new QTreeWidgetItem(kcfg_disabledPlugins);
+        item->setData(0, Qt::UserRole, QVariant::fromValue(plugin));
+        item->setText(0, metaData.name());
+        item->setText(1, metaData.description());
+        item->setCheckState(0, plugin->isEnabled() ? Qt::Checked : Qt::Unchecked);
+        if (!plugin->isEnabled()) {
+            m_toBeDisabled << metaData.pluginId();
+        }
+        if (!plugin->hasRequiredExecutables()) {
+            item->setDisabled(true);
+            for (int i : {0, 1}) {
+                item->setToolTip(i, i18n("The plugin cannot be used because one or more required executables are missing. Check your installation."));
+            }
+        }
+    }
+
+    kcfg_disabledPlugins->resizeColumnToContents(0);
+    connect(kcfg_disabledPlugins, &QTreeWidget::itemChanged, this, &PluginSettingsPage::slotItemChanged);
+
+    // Set the custom property that KConfigDialogManager will use to update the settings.
+    kcfg_disabledPlugins->setProperty("kcfg_property", QByteArray("disabledPlugins"));
+    // Tell KConfigDialogManager to monitor the itemChanged signal for a QTreeWidget instance in the dialog.
+    KConfigDialogManager::changedMap()->insert(QString::fromLatin1(QTreeWidget::staticMetaObject.className()),
+                                               SIGNAL(itemChanged(QTreeWidgetItem*,int)));
+}
+
+void PluginSettingsPage::slotSettingsChanged()
+{
+    m_toBeDisabled.clear();
+}
+
+void PluginSettingsPage::slotDefaultsButtonClicked()
+{
+    // KConfigDialogManager doesn't know how to reset the QTreeWidget,  we need to do it manually.
+    QTreeWidgetItemIterator iterator(kcfg_disabledPlugins);
+    while (*iterator) {
+        auto item = *iterator;
+        // By default every plugin is enabled.
+        item->setCheckState(0, Qt::Checked);
+        iterator++;
+    }
+}
+
+void PluginSettingsPage::slotItemChanged(QTreeWidgetItem *item)
+{
+    auto plugin = item->data(0, Qt::UserRole).value<Plugin*>();
+    if (!plugin) {
+        return;
+    }
+
+    const auto pluginId = plugin->metaData().pluginId();
+    plugin->setEnabled(item->checkState(0) == Qt::Checked);
+    // If unchecked, add to the list of plugins that will be disabled.
+    m_toBeDisabled.removeAll(pluginId);
+    if (!plugin->isEnabled()) {
+        m_toBeDisabled << pluginId;
+    }
+    // Enable the Apply button by setting the property.
+    qCDebug(ARK) << "Going to disable the following plugins:" << m_toBeDisabled;
+    kcfg_disabledPlugins->setProperty("disabledPlugins", m_toBeDisabled);
+}
+
+}
+
diff --git a/kerfuffle/pluginsettingspage.h b/kerfuffle/pluginsettingspage.h
new file mode 100644
index 00000000..2b5390ab
--- /dev/null
+++ b/kerfuffle/pluginsettingspage.h
@@ -0,0 +1,59 @@
+/*
+ * ark -- archiver for the KDE project
+ *
+ * Copyright (C) 2016 Elvis Angelaccio <elvis.angelaccio at kde.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ( INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PLUGINSETTINGSPAGE_H
+#define PLUGINSETTINGSPAGE_H
+
+#include "settingspage.h"
+#include "pluginmanager.h"
+#include "ui_pluginsettingspage.h"
+
+class QTreeWidgetItem;
+
+namespace Kerfuffle
+{
+class KERFUFFLE_EXPORT PluginSettingsPage : public SettingsPage, public Ui::PluginSettingsPage
+{
+    Q_OBJECT
+
+public:
+    explicit PluginSettingsPage(QWidget *parent = Q_NULLPTR, const QString &name = QString(), const QString &iconName = QString());
+
+public slots:
+    void slotSettingsChanged() Q_DECL_OVERRIDE;
+    void slotDefaultsButtonClicked() Q_DECL_OVERRIDE;
+
+private slots:
+    void slotItemChanged(QTreeWidgetItem *item);
+
+private:
+    QStringList m_toBeDisabled;  // List of plugins that will be disabled upon clicking the Apply button.
+    PluginManager m_pluginManager;
+};
+}
+
+#endif
diff --git a/kerfuffle/pluginsettingspage.ui b/kerfuffle/pluginsettingspage.ui
new file mode 100644
index 00000000..2b35eff1
--- /dev/null
+++ b/kerfuffle/pluginsettingspage.ui
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PluginSettingsPage</class>
+ <widget class="QWidget" name="PluginSettingsPage">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>547</width>
+    <height>487</height>
+   </rect>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QTreeWidget" name="kcfg_disabledPlugins">
+     <property name="rootIsDecorated">
+      <bool>false</bool>
+     </property>
+     <property name="columnCount">
+      <number>2</number>
+     </property>
+     <column>
+      <property name="text">
+       <string extracomment="@title:column">Name</string>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string extracomment="@title:column">Description</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/part/part.cpp b/part/part.cpp
index 8246492d..21cc3476 100644
--- a/part/part.cpp
+++ b/part/part.cpp
@@ -40,6 +40,7 @@
 #include "settings.h"
 #include "previewsettingspage.h"
 #include "propertiesdialog.h"
+#include "pluginsettingspage.h"
 #include "pluginmanager.h"
 
 #include <KAboutData>
@@ -797,6 +798,7 @@ QList<Kerfuffle::SettingsPage*> Part::settingsPages(QWidget *parent) const
     QList<SettingsPage*> pages;
     pages.append(new GeneralSettingsPage(parent, i18nc("@title:tab", "General Settings"), QStringLiteral("go-home")));
     pages.append(new ExtractionSettingsPage(parent, i18nc("@title:tab", "Extraction Settings"), QStringLiteral("archive-extract")));
+    pages.append(new PluginSettingsPage(parent, i18nc("@title:tab", "Plugin Settings"), QStringLiteral("plugins")));
     pages.append(new PreviewSettingsPage(parent, i18nc("@title:tab", "Preview Settings"), QStringLiteral("document-preview-archive")));
 
     return pages;


More information about the kde-doc-english mailing list