[education/rkward] rkward: Handle addition/removal of kate plugin config pages

Thomas Friedrichsmeier null at kde.org
Mon Jul 22 22:34:28 BST 2024


Git commit 687ed19349277c0df3905a63398b4124e348394f by Thomas Friedrichsmeier.
Committed on 22/07/2024 at 21:34.
Pushed by tfry into branch 'master'.

Handle addition/removal of kate plugin config pages

M  +14   -0    rkward/autotests/core_test.cpp
M  +1    -0    rkward/rbackend/rkrinterface.cpp
M  +47   -18   rkward/settings/rksettings.cpp
M  +5    -0    rkward/settings/rksettings.h
M  +1    -1    rkward/settings/rksettingsmodule.h
M  +4    -5    rkward/settings/rksettingsmodulecommandeditor.cpp
M  +1    -1    rkward/settings/rksettingsmodulecommandeditor.h
M  +3    -2    rkward/settings/rksettingsmoduleconsole.cpp
M  +1    -1    rkward/settings/rksettingsmoduleconsole.h
M  +3    -2    rkward/settings/rksettingsmoduledebug.cpp
M  +1    -1    rkward/settings/rksettingsmoduledebug.h
M  +3    -2    rkward/settings/rksettingsmodulegeneral.cpp
M  +1    -1    rkward/settings/rksettingsmodulegeneral.h
M  +3    -2    rkward/settings/rksettingsmodulegraphics.cpp
M  +1    -1    rkward/settings/rksettingsmodulegraphics.h
M  +26   -8    rkward/settings/rksettingsmodulekateplugins.cpp
M  +5    -1    rkward/settings/rksettingsmodulekateplugins.h
M  +2    -2    rkward/settings/rksettingsmoduleobjectbrowser.cpp
M  +1    -1    rkward/settings/rksettingsmoduleobjectbrowser.h
M  +3    -2    rkward/settings/rksettingsmoduleoutput.cpp
M  +1    -1    rkward/settings/rksettingsmoduleoutput.h
M  +4    -2    rkward/settings/rksettingsmoduleplugins.cpp
M  +1    -1    rkward/settings/rksettingsmoduleplugins.h
M  +5    -4    rkward/settings/rksettingsmoduler.cpp
M  +2    -2    rkward/settings/rksettingsmoduler.h
M  +2    -2    rkward/settings/rksettingsmodulewatch.cpp
M  +1    -1    rkward/settings/rksettingsmodulewatch.h
M  +14   -12   rkward/windows/katepluginintegration.cpp
M  +1    -0    rkward/windows/rkcommandlog.cpp
M  +0    -1    rkward/windows/rkcommandlog.h
M  +1    -0    rkward/windows/rkmdiwindow.cpp
M  +1    -1    rkward/windows/rkmdiwindow.h

https://invent.kde.org/education/rkward/-/commit/687ed19349277c0df3905a63398b4124e348394f

diff --git a/rkward/autotests/core_test.cpp b/rkward/autotests/core_test.cpp
index 8c75d22bc..ece9603d0 100644
--- a/rkward/autotests/core_test.cpp
+++ b/rkward/autotests/core_test.cpp
@@ -32,6 +32,9 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include "../misc/rkcommonfunctions.h"
 #include "../misc/rkcommandlineargs.h"
 #include "../misc/rkxmlguipreviewarea.h"
+#include "../settings/rksettings.h"
+#include "../settings/rksettingsmodulekateplugins.h"
+#include "../windows/katepluginintegration.h"
 
 QElapsedTimer _test_timer;
 
@@ -435,6 +438,17 @@ private Q_SLOTS:
 		RKWorkplace::mainWorkplace()->openAnyUrl(QUrl("rkward://settings/graphics"));
 		QVERIFY(dialog == RKSettings::settings_dialog);  // shall be reused
 
+		// Load and unload a bunch of plugins (settings dialog will be modified, but of course, also plugin loading/unloading is given another round
+		// of testing.
+		auto plugins = RKSettingsModuleKatePlugins::pluginsToLoad();
+		QVERIFY(!plugins.isEmpty());
+		for (int i = 0; i < plugins.size(); ++i) {
+			auto plugins_b = plugins;
+			plugins_b.removeAt(i);
+			RKWardMainWindow::getMain()->katePluginIntegration()->loadPlugins(plugins_b);
+			dialog->applyAll(); // to assertain there are no dead pointers in the dialog's internal bookkeeping
+		}
+
 		dialog->close();
 		waitForAllFinished();
 		QVERIFY(!RKSettings::settings_dialog);
diff --git a/rkward/rbackend/rkrinterface.cpp b/rkward/rbackend/rkrinterface.cpp
index 4e763f32c..dde6812fc 100644
--- a/rkward/rbackend/rkrinterface.cpp
+++ b/rkward/rbackend/rkrinterface.cpp
@@ -11,6 +11,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include "rkrbackendprotocol_frontend.h"
 #include "../rkward.h"
 #include "../rkconsole.h"
+#include "../settings/rksettings.h"
 #include "../settings/rksettingsmoduler.h"
 #include "../settings/rksettingsmodulegeneral.h"
 #include "../settings/rksettingsmoduleoutput.h"
diff --git a/rkward/settings/rksettings.cpp b/rkward/settings/rksettings.cpp
index 2edbf9c69..6d12c7671 100644
--- a/rkward/settings/rksettings.cpp
+++ b/rkward/settings/rksettings.cpp
@@ -79,25 +79,27 @@ void RKSettings::initDialogPages() {
 	RK_ASSERT(pages.isEmpty());
 
 	for (auto it = modules.constBegin(); it != modules.constEnd(); ++it) {
-		auto pagewidgets = (*it)->createPages(this);
-		for (auto pit = pagewidgets.constBegin(); pit != pagewidgets.constEnd(); ++pit) {
-			auto widget = *pit;
-			RK_ASSERT(widget->pageid != RKSettingsModule::no_page_id); // all toplevel pages shall have an id
-			auto superp = widget->superpageid;
-			KPageWidgetItem *page;
-			if (superp.isEmpty()) {
-				page = addPage(widget, widget->windowTitle());
-			} else {
-				auto superpage = findPage(superp);
-				RK_ASSERT(superpage);
-				page = addSubPage(superpage, widget, widget->windowTitle());
-			}
-			page->setHeader(widget->longCaption());
-			page->setIcon(widget->windowIcon());
-			connect(widget, &RKSettingsModuleWidget::settingsChanged, this, [this]() { button(QDialogButtonBox::Apply)->setEnabled(true); });
-			pages.append(page);
-		}
+		(*it)->createPages(this);
+	}
+}
+
+void RKSettings::addSettingsPage(RKSettingsModuleWidget *widget) {
+	RK_TRACE(SETTINGS);
+
+	RK_ASSERT(widget->pageid != RKSettingsModule::no_page_id); // all toplevel pages shall have an id
+	auto superp = widget->superpageid;
+	KPageWidgetItem *page;
+	if (superp.isEmpty()) {
+		page = addPage(widget, widget->windowTitle());
+	} else {
+		auto superpage = findPage(superp);
+		RK_ASSERT(superpage);
+		page = addSubPage(superpage, widget, widget->windowTitle());
 	}
+	page->setHeader(widget->longCaption());
+	page->setIcon(widget->windowIcon());
+	connect(widget, &RKSettingsModuleWidget::settingsChanged, this, [this]() { button(QDialogButtonBox::Apply)->setEnabled(true); });
+	pages.append(page);
 }
 
 KPageWidgetItem* RKSettings::findPage(const RKSettingsModule::PageId id) const {
@@ -139,14 +141,26 @@ void RKSettings::helpClicked () {
 void RKSettings::applyAll() {
 	RK_TRACE (SETTINGS);
 
+	// NOTE: This is shoddy design, but also kind of difficult: While applying the changes of the kate plugin page, pages may be added/removed
+	//       to this very dialog. I.e. while looping over the pages, they'd get modified (and even deleted!). Can't have that, so for now, we
+	//       special-case the kate plugins page, and handle it last.
+	auto kate_plugin_page = findPage(RKSettingsModuleKatePlugins::page_id);
+	RK_ASSERT(kate_plugin_page);
 	QSet<RKSettingsModule*> changed_modules;
 	for (auto it = pages.constBegin(); it != pages.constEnd(); ++it) {
+		if ((*it) == kate_plugin_page) continue;
 		auto w = static_cast<RKSettingsModuleWidget*>((*it)->widget());
 		if (w->hasChanges()) {
 			w->doApply();
 			changed_modules.insert(w->parentModule());
 		}
 	}
+	auto kateconfig = static_cast<RKSettingsModuleWidget*>(kate_plugin_page->widget());
+	if (kateconfig->hasChanges()) {
+		kateconfig->doApply();
+		changed_modules.insert(kateconfig->parentModule());
+	}
+
 	for (auto it = changed_modules.constBegin(); it != changed_modules.constEnd(); ++it) {
 		(*it)->syncConfig(KSharedConfig::openConfig().data(), RKConfigBase::SaveConfig);
 		Q_EMIT (*it)->settingsChanged();
@@ -154,6 +168,21 @@ void RKSettings::applyAll() {
 	button(QDialogButtonBox::Apply)->setEnabled(false);
 }
 
+void RKSettings::removeSettingsPage(RKSettingsModuleWidget *which) {
+	RK_TRACE(SETTINGS);
+
+	auto it = std::find_if(pages.constBegin(), pages.constEnd(), [which](KPageWidgetItem* p) {
+		return (p->widget() == which);
+	});
+	RK_ASSERT(it != pages.constEnd());
+	if (it != pages.constEnd()) {
+		auto pi = *it;
+		pages.removeAll(pi);
+		(pi)->deleteLater();
+		KPageDialog::removePage(pi);
+	}
+}
+
 void RKSettings::loadSettings(KConfig *config) {
 	RK_TRACE(SETTINGS);
 
diff --git a/rkward/settings/rksettings.h b/rkward/settings/rksettings.h
index 39d609485..2715ce501 100644
--- a/rkward/settings/rksettings.h
+++ b/rkward/settings/rksettings.h
@@ -35,6 +35,7 @@ public:
 	static QList<RKSetupWizardItem*> validateSettingsInteractive ();
 
 	void enableApply ();
+	void addSettingsPage(RKSettingsModuleWidget *which);
 public Q_SLOTS:
 	void pageChange (KPageWidgetItem *current, KPageWidgetItem *before);
 protected:
@@ -53,6 +54,10 @@ friend class RKWardCoreTest;
 	KPageWidgetItem *findPage(const RKSettingsModule::PageId id) const;
 
 	static RKSettings *settings_dialog;
+
+friend class RKSettingsModuleKatePlugins;
+	/** dynamically remove the given page from the dialog (for pages provided by plugins, which might get unloaded) */
+	void removeSettingsPage(RKSettingsModuleWidget *which);
 };
 
 #endif
diff --git a/rkward/settings/rksettingsmodule.h b/rkward/settings/rksettingsmodule.h
index e2fec3f93..29716022c 100644
--- a/rkward/settings/rksettingsmodule.h
+++ b/rkward/settings/rksettingsmodule.h
@@ -146,7 +146,7 @@ be inserted into this chain. It's safe to use this unconditionally, as if there
 Q_SIGNALS:
 	void settingsChanged();
 protected:
-	virtual QList<RKSettingsModuleWidget*> createPages(QWidget *parent) = 0;
+	virtual void createPages(RKSettings *parent) = 0;
 private:
 friend class RKSettings;
 	static RCommandChain *chain;
diff --git a/rkward/settings/rksettingsmodulecommandeditor.cpp b/rkward/settings/rksettingsmodulecommandeditor.cpp
index 755d5aaa4..49bfc920a 100644
--- a/rkward/settings/rksettingsmodulecommandeditor.cpp
+++ b/rkward/settings/rksettingsmodulecommandeditor.cpp
@@ -26,6 +26,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include "../misc/rkstandardicons.h"
 #include "../core/robject.h"
 #include "../misc/rkstyle.h"
+#include "rksettings.h"
 
 #include "../debug.h"
 
@@ -201,16 +202,14 @@ QString RKTextEditorConfigPageWrapper::longCaption() const {
 	return page->fullName();
 }
 
-QList<RKSettingsModuleWidget*> RKSettingsModuleCommandEditor::createPages(QWidget *parent) {
+void RKSettingsModuleCommandEditor::createPages(RKSettings *parent) {
 	RK_TRACE(SETTINGS);
-	QList<RKSettingsModuleWidget*> ret;
-	ret.append(new RKSettingsPageCommandEditor(parent, this));
+	parent->addSettingsPage(new RKSettingsPageCommandEditor(parent, this));
 	auto ed = KTextEditor::Editor::instance();
 	int n = ed->configPages();
 	for (int i = 0; i < n; ++i) {
-		ret.append(new RKTextEditorConfigPageWrapper(parent, this, RKSettingsModuleCommandEditor::page_id, ed->configPage(i, parent)));
+		parent->addSettingsPage(new RKTextEditorConfigPageWrapper(parent, this, RKSettingsModuleCommandEditor::page_id, ed->configPage(i, parent)));
 	}
-	return ret;
 }
 
 QString completionTypeToConfigKey (int cat) {
diff --git a/rkward/settings/rksettingsmodulecommandeditor.h b/rkward/settings/rksettingsmodulecommandeditor.h
index bcf069e35..a7e65d607 100644
--- a/rkward/settings/rksettingsmodulecommandeditor.h
+++ b/rkward/settings/rksettingsmodulecommandeditor.h
@@ -88,7 +88,7 @@ public:
 	~RKSettingsModuleCommandEditor() override;
 	
 	void syncConfig(KConfig *config, RKConfigBase::ConfigSyncAction) override;
-	QList<RKSettingsModuleWidget*> createPages(QWidget *parent) override;
+	void createPages(RKSettings *parent) override;
 
 	static const RKCodeCompletionSettings* completionSettings() { return &completion_settings; };
 
diff --git a/rkward/settings/rksettingsmoduleconsole.cpp b/rkward/settings/rksettingsmoduleconsole.cpp
index a4dcade14..67adcd11d 100644
--- a/rkward/settings/rksettingsmoduleconsole.cpp
+++ b/rkward/settings/rksettingsmoduleconsole.cpp
@@ -20,6 +20,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include "../misc/rkspinbox.h"
 #include "../misc/rkstandardicons.h"
 #include "../misc/rkstyle.h"
+#include "rksettings.h"
 
 #include "../debug.h"
 
@@ -93,8 +94,8 @@ RKSettingsModuleConsole::RKSettingsModuleConsole(QObject *parent) : RKSettingsMo
 	RK_TRACE(SETTINGS);
 }
 
-QList<RKSettingsModuleWidget*> RKSettingsModuleConsole::createPages(QWidget *parent) {
-	return QList<RKSettingsModuleWidget*>{ new RKSettingsPageConsole(parent, this) };
+void RKSettingsModuleConsole::createPages(RKSettings *parent) {
+	parent->addSettingsPage(new RKSettingsPageConsole(parent, this));
 }
 
 RKSettingsModuleConsole::~RKSettingsModuleConsole () {
diff --git a/rkward/settings/rksettingsmoduleconsole.h b/rkward/settings/rksettingsmoduleconsole.h
index f7e311de3..aa32135f0 100644
--- a/rkward/settings/rksettingsmoduleconsole.h
+++ b/rkward/settings/rksettingsmoduleconsole.h
@@ -27,7 +27,7 @@ public:
 	~RKSettingsModuleConsole() override;
 
 	void syncConfig(KConfig *config, RKConfigBase::ConfigSyncAction) override;
-	QList<RKSettingsModuleWidget*> createPages(QWidget *parent) override;
+	void createPages(RKSettings *parent) override;
 	static constexpr PageId page_id = QLatin1String("console");
 
 	static bool saveHistory () { return save_history; };
diff --git a/rkward/settings/rksettingsmoduledebug.cpp b/rkward/settings/rksettingsmoduledebug.cpp
index aa7eaf219..d372d7ff3 100644
--- a/rkward/settings/rksettingsmoduledebug.cpp
+++ b/rkward/settings/rksettingsmoduledebug.cpp
@@ -21,6 +21,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include "../misc/rkspinbox.h"
 #include "../misc/rkcommonfunctions.h"
 #include "../misc/rkstyle.h"
+#include "rksettings.h"
 
 #include "../debug.h"
 
@@ -114,8 +115,8 @@ RKSettingsModuleDebug::~RKSettingsModuleDebug () {
 	RK_TRACE (SETTINGS);
 }
 
-QList<RKSettingsModuleWidget*> RKSettingsModuleDebug::createPages(QWidget *parent) {
-	return QList<RKSettingsModuleWidget*>{ new RKSettingsPageDebug(parent, this) };
+void RKSettingsModuleDebug::createPages(RKSettings *parent) {
+	parent->addSettingsPage(new RKSettingsPageDebug(parent, this));
 }
 
 void RKSettingsModuleDebug::syncConfig(KConfig*, RKConfigBase::ConfigSyncAction) {
diff --git a/rkward/settings/rksettingsmoduledebug.h b/rkward/settings/rksettingsmoduledebug.h
index c3924940f..15cd4e709 100644
--- a/rkward/settings/rksettingsmoduledebug.h
+++ b/rkward/settings/rksettingsmoduledebug.h
@@ -25,7 +25,7 @@ public:
 	~RKSettingsModuleDebug() override;
 
 	void syncConfig(KConfig *config, RKConfigBase::ConfigSyncAction) override;
-	QList<RKSettingsModuleWidget*> createPages(QWidget *parent) override;
+	void createPages(RKSettings *parent) override;
 	static constexpr PageId page_id = QLatin1String("debug");
 
 	// static members are declared in debug.h and defined in main.cpp
diff --git a/rkward/settings/rksettingsmodulegeneral.cpp b/rkward/settings/rksettingsmodulegeneral.cpp
index 6b0bea6b3..8db0eda97 100644
--- a/rkward/settings/rksettingsmodulegeneral.cpp
+++ b/rkward/settings/rksettingsmodulegeneral.cpp
@@ -25,6 +25,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include "../misc/rkcommandlineargs.h"
 #include "../misc/rkstandardicons.h"
 #include "../misc/rkstyle.h"
+#include "rksettings.h"
 
 #include "../version.h"
 #include "../debug.h"
@@ -162,8 +163,8 @@ RKSettingsModuleGeneral::~RKSettingsModuleGeneral() {
 	RK_TRACE (SETTINGS);
 }
 
-QList<RKSettingsModuleWidget*> RKSettingsModuleGeneral::createPages(QWidget *parent) {
-	return QList<RKSettingsModuleWidget*>{ new RKSettingsPageGeneral(parent, this) };
+void RKSettingsModuleGeneral::createPages(RKSettings *parent) {
+	parent->addSettingsPage(new RKSettingsPageGeneral(parent, this));
 }
 
 QString RKSettingsModuleGeneral::initialWorkingDirectory () {
diff --git a/rkward/settings/rksettingsmodulegeneral.h b/rkward/settings/rksettingsmodulegeneral.h
index da0207895..f42c9ce4c 100644
--- a/rkward/settings/rksettingsmodulegeneral.h
+++ b/rkward/settings/rksettingsmodulegeneral.h
@@ -43,7 +43,7 @@ public:
 	};
 
 	void syncConfig(KConfig *config, RKConfigBase::ConfigSyncAction) override;
-	QList<RKSettingsModuleWidget*> createPages(QWidget *parent) override;
+	void createPages(RKSettings *parent) override;
 	static constexpr PageId page_id = QLatin1String("general");
 
 /// returns the directory-name where the logfiles should reside
diff --git a/rkward/settings/rksettingsmodulegraphics.cpp b/rkward/settings/rksettingsmodulegraphics.cpp
index 95abf4f56..12498f875 100644
--- a/rkward/settings/rksettingsmodulegraphics.cpp
+++ b/rkward/settings/rksettingsmodulegraphics.cpp
@@ -26,6 +26,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include "../misc/rkcommonfunctions.h"
 #include "../misc/rkstandardicons.h"
 #include "../core/robject.h"
+#include "rksettings.h"
 #include "../debug.h"
 
 // static members
@@ -183,8 +184,8 @@ RKSettingsModuleGraphics::~RKSettingsModuleGraphics() {
 	RK_TRACE (SETTINGS);
 }
 
-QList<RKSettingsModuleWidget*> RKSettingsModuleGraphics::createPages(QWidget *parent) {
-	return QList<RKSettingsModuleWidget*>{ new RKSettingsPageGraphics(parent, this) };
+void RKSettingsModuleGraphics::createPages(RKSettings *parent) {
+	parent->addSettingsPage(new RKSettingsPageGraphics(parent, this));
 }
 
 void RKSettingsModuleGraphics::syncConfig(KConfig *config, RKConfigBase::ConfigSyncAction a) {
diff --git a/rkward/settings/rksettingsmodulegraphics.h b/rkward/settings/rksettingsmodulegraphics.h
index 36f93f2f8..1530a08c9 100644
--- a/rkward/settings/rksettingsmodulegraphics.h
+++ b/rkward/settings/rksettingsmodulegraphics.h
@@ -34,7 +34,7 @@ public:
 	static bool kdePrintingEnabled () { return options_kde_printing; };
 
 	void syncConfig(KConfig *config, RKConfigBase::ConfigSyncAction) override;
-	QList<RKSettingsModuleWidget*> createPages(QWidget *parent) override;
+	void createPages(RKSettings *parent) override;
 	static constexpr PageId page_id = QLatin1String("graphics");
 
 	enum DefaultDevice {
diff --git a/rkward/settings/rksettingsmodulekateplugins.cpp b/rkward/settings/rksettingsmodulekateplugins.cpp
index 94169d099..8802416dc 100644
--- a/rkward/settings/rksettingsmodulekateplugins.cpp
+++ b/rkward/settings/rksettingsmodulekateplugins.cpp
@@ -17,9 +17,12 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include <KConfigGroup>
 #include <KConfig>
 #include <KTextEditor/Plugin>
+#include <KTextEditor/Editor>
+#include <KTextEditor/Application>
 
 #include "rksettingsmoduleplugins.h"
 #include "rksettingsmodulecommandeditor.h"
+#include "rksettings.h"
 #include "../windows/katepluginintegration.h"
 #include "../misc/rkcommonfunctions.h"
 #include "../rkward.h"
@@ -75,7 +78,7 @@ public:
 		for (int i = plugin_table->topLevelItemCount() - 1; i >= 0; --i) {
 			QTreeWidgetItem *item = plugin_table->topLevelItem(i);
 			if (item->checkState(0) == Qt::Checked) {
-				p.append (item->data(1, Qt::UserRole).toString());
+				p.append(item->data(1, Qt::UserRole).toString());
 			}
 		}
 		RKSettingsModuleKatePlugins::plugins_to_load = p;
@@ -93,18 +96,33 @@ RKSettingsModuleKatePlugins::~RKSettingsModuleKatePlugins() {
 	RK_TRACE(SETTINGS);
 }
 
-QList<RKSettingsModuleWidget*> RKSettingsModuleKatePlugins::createPages(QWidget *parent) {
+void RKSettingsModuleKatePlugins::addPluginSettingsPages(RKSettings *parent, KTextEditor::Plugin *plugin) {
 	RK_TRACE(SETTINGS);
 
-	QList<RKSettingsModuleWidget*> ret { new RKSettingsPageKatePlugins(parent, this) };
+	for (int i = 0; i < plugin->configPages(); ++i) {
+		auto _page = plugin->configPage(i, nullptr);
+		auto page = new RKTextEditorConfigPageWrapper(parent, this, RKSettingsModuleKatePlugins::page_id, _page);
+		parent->addSettingsPage(page);
+		connect(KTextEditor::Editor::instance()->application(), &KTextEditor::Application::pluginDeleted, page, [parent, plugin, page](QString, const KTextEditor::Plugin *plug) {
+			if (plug == plugin) parent->removeSettingsPage(page);
+			// NOTE: The page will be deleted, above, thus also removing this connection
+		});
+	}
+}
+
+void RKSettingsModuleKatePlugins::createPages(RKSettings *parent) {
+	RK_TRACE(SETTINGS);
+
+	parent->addSettingsPage(new RKSettingsPageKatePlugins(parent, this));
+
 	auto loaded_plugins = RKWardMainWindow::getMain()->katePluginIntegration()->loadedPlugins();
 	for (auto it = loaded_plugins.constBegin(); it != loaded_plugins.constEnd(); ++it) {
-		auto p = *it;
-		for (int i = 0; i < p->configPages(); ++i) {
-			ret.append(new RKTextEditorConfigPageWrapper(parent, this, RKSettingsModuleKatePlugins::page_id, p->configPage(i, nullptr)));
-		}
+		addPluginSettingsPages(parent, *it);
 	}
-	return ret;
+	// any future plugins loaded during the lifetime of the settings dialog
+	connect(KTextEditor::Editor::instance()->application(), &KTextEditor::Application::pluginCreated, parent, [this, parent](QString, KTextEditor::Plugin *plugin) {
+		addPluginSettingsPages(parent, plugin);
+	});
 }
 
 void RKSettingsModuleKatePlugins::syncConfig(KConfig *config, RKConfigBase::ConfigSyncAction a) {
diff --git a/rkward/settings/rksettingsmodulekateplugins.h b/rkward/settings/rksettingsmodulekateplugins.h
index 9c42500c0..fc3ab6f0b 100644
--- a/rkward/settings/rksettingsmodulekateplugins.h
+++ b/rkward/settings/rksettingsmodulekateplugins.h
@@ -12,6 +12,9 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include <QStringList>
 
 class QTreeWidget;
+namespace KTextEditor {
+	class Plugin;
+}
 
 /** The settings-module for kate plugin specific settings
 @author Thomas Friedrichsmeier
@@ -22,11 +25,12 @@ public:
 	~RKSettingsModuleKatePlugins() override;
 
 	void syncConfig(KConfig *config, RKConfigBase::ConfigSyncAction) override;
-	QList<RKSettingsModuleWidget*> createPages(QWidget *parent) override;
+	void createPages(RKSettings *parent) override;
 	static constexpr PageId page_id = QLatin1String("kateplugins");
 
 	static QStringList pluginsToLoad() { return plugins_to_load; };
 private:
+	void addPluginSettingsPages(RKSettings *parent, KTextEditor::Plugin *plugin);
 friend class RKSettingsPageKatePlugins;
 	static RKConfigValue<QStringList> plugins_to_load;
 };
diff --git a/rkward/settings/rksettingsmoduleobjectbrowser.cpp b/rkward/settings/rksettingsmoduleobjectbrowser.cpp
index 86137a5e0..6a2fad254 100644
--- a/rkward/settings/rksettingsmoduleobjectbrowser.cpp
+++ b/rkward/settings/rksettingsmoduleobjectbrowser.cpp
@@ -70,8 +70,8 @@ RKSettingsModuleObjectBrowser::~RKSettingsModuleObjectBrowser () {
 	RK_TRACE (SETTINGS);
 }
 
-QList<RKSettingsModuleWidget*> RKSettingsModuleObjectBrowser::createPages(QWidget *parent) {
-	return QList<RKSettingsModuleWidget*>{ new RKSettingsPageObjectBrowser(parent, this) };
+void RKSettingsModuleObjectBrowser::createPages(RKSettings *parent) {
+	parent->addSettingsPage(new RKSettingsPageObjectBrowser(parent, this));;
 }
 
 //static
diff --git a/rkward/settings/rksettingsmoduleobjectbrowser.h b/rkward/settings/rksettingsmoduleobjectbrowser.h
index e5b3245f6..8865cb8e6 100644
--- a/rkward/settings/rksettingsmoduleobjectbrowser.h
+++ b/rkward/settings/rksettingsmoduleobjectbrowser.h
@@ -26,7 +26,7 @@ public:
 	~RKSettingsModuleObjectBrowser() override;
 
 	void syncConfig(KConfig *config, RKConfigBase::ConfigSyncAction) override;
-	QList<RKSettingsModuleWidget*> createPages(QWidget *parent) override;
+	void createPages(RKSettings *parent) override;
 	static constexpr PageId page_id = QLatin1String("browser");
 
 	static bool isDefaultForWorkspace (RKObjectListViewSettings::PersistentSettings setting) { return workspace_settings[setting]; };
diff --git a/rkward/settings/rksettingsmoduleoutput.cpp b/rkward/settings/rksettingsmoduleoutput.cpp
index 03aa67801..c5d135179 100644
--- a/rkward/settings/rksettingsmoduleoutput.cpp
+++ b/rkward/settings/rksettingsmoduleoutput.cpp
@@ -23,6 +23,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include "../misc/rkspinbox.h"
 #include "../misc/rkstandardicons.h"
 #include "../rbackend/rkrinterface.h"
+#include "rksettings.h"
 #include "../debug.h"
 
 // static members
@@ -208,8 +209,8 @@ RKSettingsModuleOutput::~RKSettingsModuleOutput() {
 	RK_TRACE (SETTINGS);
 }
 
-QList<RKSettingsModuleWidget*> RKSettingsModuleOutput::createPages(QWidget *parent) {
-	return QList<RKSettingsModuleWidget*>{ new RKSettingsPageOutput(parent, this) };
+void RKSettingsModuleOutput::createPages(RKSettings *parent) {
+	parent->addSettingsPage(new RKSettingsPageOutput(parent, this));
 }
 
 void RKSettingsModuleOutput::syncConfig(KConfig *config, RKConfigBase::ConfigSyncAction a) {
diff --git a/rkward/settings/rksettingsmoduleoutput.h b/rkward/settings/rksettingsmoduleoutput.h
index 665696544..aecef3585 100644
--- a/rkward/settings/rksettingsmoduleoutput.h
+++ b/rkward/settings/rksettingsmoduleoutput.h
@@ -63,7 +63,7 @@ public:
 	~RKSettingsModuleOutput() override;
 
 	void syncConfig(KConfig *config, RKConfigBase::ConfigSyncAction) override;
-	QList<RKSettingsModuleWidget*> createPages(QWidget *parent) override;
+	void createPages(RKSettings *parent) override;
 	static constexpr PageId page_id = QLatin1String("output");
 
 /** generate the commands needed to set the R run time options */
diff --git a/rkward/settings/rksettingsmoduleplugins.cpp b/rkward/settings/rksettingsmoduleplugins.cpp
index 1d010e9d0..eb3d9e05d 100644
--- a/rkward/settings/rksettingsmoduleplugins.cpp
+++ b/rkward/settings/rksettingsmoduleplugins.cpp
@@ -32,6 +32,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include "../plugin/rkcomponentmap.h"
 #include "../dialogs/rkloadlibsdialog.h"
 #include "rksettingsmodulegeneral.h"
+#include "rksettings.h"
 
 #include "../debug.h"
 
@@ -115,8 +116,9 @@ RKSettingsModulePlugins::~RKSettingsModulePlugins() {
 	RK_TRACE (SETTINGS);
 }
 
-QList<RKSettingsModuleWidget*> RKSettingsModulePlugins::createPages(QWidget *parent) {
-	return QList<RKSettingsModuleWidget*>{ new RKSettingsHeaderPage(parent, this), new RKSettingsPagePlugins(parent, this) };
+void RKSettingsModulePlugins::createPages(RKSettings *parent) {
+	parent->addSettingsPage(new RKSettingsHeaderPage(parent, this));
+	parent->addSettingsPage(new RKSettingsPagePlugins(parent, this));
 }
 
 RKSettingsModulePlugins::RKPluginMapList RKSettingsModulePlugins::setPluginMaps(const RKPluginMapList &new_list) {
diff --git a/rkward/settings/rksettingsmoduleplugins.h b/rkward/settings/rksettingsmoduleplugins.h
index 89b8117b0..a839016fe 100644
--- a/rkward/settings/rksettingsmoduleplugins.h
+++ b/rkward/settings/rksettingsmoduleplugins.h
@@ -31,7 +31,7 @@ public:
 	enum PluginPrefs { PreferDialog=0, PreferRecommended=1, PreferWizard=2 };
 
 	void syncConfig(KConfig *config, RKConfigBase::ConfigSyncAction) override;
-	QList<RKSettingsModuleWidget*> createPages(QWidget *parent) override;
+	void createPages(RKSettings *parent) override;
 	static constexpr PageId page_id = QLatin1String("plugins");
 	static constexpr PageId addons_superpage_id = QLatin1String("addons");
 
diff --git a/rkward/settings/rksettingsmoduler.cpp b/rkward/settings/rksettingsmoduler.cpp
index 59a803ff3..6623aa160 100755
--- a/rkward/settings/rksettingsmoduler.cpp
+++ b/rkward/settings/rksettingsmoduler.cpp
@@ -36,6 +36,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include "../rbackend/rksessionvars.h"
 #include "../plugin/rkcomponentmap.h"
 #include "../misc/rkstyle.h"
+#include "rksettings.h"
 
 #include "../debug.h"
 
@@ -222,8 +223,8 @@ RKSettingsModuleR::~RKSettingsModuleR() {
 	RK_TRACE (SETTINGS);
 }
 
-QList<RKSettingsModuleWidget*> RKSettingsModuleR::createPages(QWidget *parent) {
-	return QList<RKSettingsModuleWidget*>{ new RKSettingsPageR(parent, this) };
+void RKSettingsModuleR::createPages(RKSettings *parent) {
+	parent->addSettingsPage(new RKSettingsPageR(parent, this));
 }
 
 static QLatin1String RTrueFalse(bool val) {
@@ -443,8 +444,8 @@ RKSettingsModuleRPackages::~RKSettingsModuleRPackages () {
 	RK_TRACE (SETTINGS);
 }
 
-QList<RKSettingsModuleWidget*> RKSettingsModuleRPackages::createPages(QWidget *parent) {
-	return QList<RKSettingsModuleWidget*>{ new RKSettingsPageRPackages(parent, this) };
+void RKSettingsModuleRPackages::createPages(RKSettings *parent) {
+	parent->addSettingsPage(new RKSettingsPageRPackages(parent, this));
 }
 
 void RKSettingsModuleRPackages::addLibraryLocation (const QString& new_loc, RCommandChain *chain) {
diff --git a/rkward/settings/rksettingsmoduler.h b/rkward/settings/rksettingsmoduler.h
index 2267ade3e..f9cdf3d13 100644
--- a/rkward/settings/rksettingsmoduler.h
+++ b/rkward/settings/rksettingsmoduler.h
@@ -30,7 +30,7 @@ public:
 	~RKSettingsModuleR() override;
 
 	void syncConfig(KConfig *config, RKConfigBase::ConfigSyncAction) override;
-	QList<RKSettingsModuleWidget*> createPages(QWidget *parent) override;
+	void createPages(RKSettings *parent) override;
 	static constexpr PageId page_id = QLatin1String("rbackend");
 
 /** generate the commands needed to set the R run time options */
@@ -80,7 +80,7 @@ public:
 	~RKSettingsModuleRPackages() override;
 
 	void syncConfig(KConfig *config, RKConfigBase::ConfigSyncAction) override;
-	QList<RKSettingsModuleWidget*> createPages(QWidget *parent) override;
+	void createPages(RKSettings *parent) override;
 	void validateSettingsInteractive (QList<RKSetupWizardItem*>*) override;
 	static constexpr PageId page_id = QLatin1String("rpackages");
 
diff --git a/rkward/settings/rksettingsmodulewatch.cpp b/rkward/settings/rksettingsmodulewatch.cpp
index cd6f9ef6d..9de1136fc 100644
--- a/rkward/settings/rksettingsmodulewatch.cpp
+++ b/rkward/settings/rksettingsmodulewatch.cpp
@@ -233,8 +233,8 @@ RKSettingsModuleWatch::~RKSettingsModuleWatch() {
 	RK_TRACE(SETTINGS);
 }
 
-QList<RKSettingsModuleWidget*> RKSettingsModuleWatch::createPages(QWidget *parent) {
-	return QList<RKSettingsModuleWidget*>{ new RKSettingsPageWatch(parent, this) };
+void RKSettingsModuleWatch::createPages(RKSettings *parent) {
+	parent->addSettingsPage(new RKSettingsPageWatch(parent, this));
 }
 
 //static
diff --git a/rkward/settings/rksettingsmodulewatch.h b/rkward/settings/rksettingsmodulewatch.h
index d4f587766..4d1100f9e 100644
--- a/rkward/settings/rksettingsmodulewatch.h
+++ b/rkward/settings/rksettingsmodulewatch.h
@@ -27,7 +27,7 @@ public:
 	~RKSettingsModuleWatch() override;
 
 	void syncConfig(KConfig *config, RKConfigBase::ConfigSyncAction) override;
-	QList<RKSettingsModuleWidget*> createPages(QWidget *parent) override;
+	void createPages(RKSettings *parent) override;
 	static constexpr PageId page_id = QLatin1String("commandlog");
 
 	static bool shouldShowInput (RCommand *command);
diff --git a/rkward/windows/katepluginintegration.cpp b/rkward/windows/katepluginintegration.cpp
index 6fe77c25b..b4199c87f 100644
--- a/rkward/windows/katepluginintegration.cpp
+++ b/rkward/windows/katepluginintegration.cpp
@@ -152,7 +152,7 @@ QObject* KatePluginIntegrationApp::loadPlugin (const QString& identifier) {
 	KTextEditor::Plugin *plugin = KPluginFactory::instantiatePlugin<KTextEditor::Plugin>(known_plugins[identifier].data, this, QVariantList() << identifier).plugin;
 	if (plugin) {
 		known_plugins[identifier].plugin = plugin;
-		Q_EMIT KTextEditor::Editor::instance()->application()->pluginCreated(identifier, plugin);
+		Q_EMIT app->pluginCreated(identifier, plugin);
 		QObject* created = mainWindow()->createPluginView(plugin);
 		if (created) {
 			Q_EMIT mainWindow()->main->pluginViewCreated(identifier, created);
@@ -162,12 +162,12 @@ QObject* KatePluginIntegrationApp::loadPlugin (const QString& identifier) {
 				KConfigGroup group = KSharedConfig::openConfig()->group(QStringLiteral("KatePlugin:%1:").arg(identifier));
 				interface->readSessionConfig(group);
 			}
-			interface = qobject_cast<KTextEditor::SessionConfigInterface *>(plugin);
-			if (interface) {
-				// NOTE: The session interface may be implemented in either the view or the plugin (or neither or both)
-				KConfigGroup group = KSharedConfig::openConfig()->group(QStringLiteral("KatePlugin_plugin:%1:").arg(identifier));
-				interface->readSessionConfig(group);
-			}
+		}
+		auto interface = qobject_cast<KTextEditor::SessionConfigInterface *>(plugin);
+		if (interface) {
+			// NOTE: The session interface may be implemented in either the view or the plugin (or neither or both)
+			KConfigGroup group = KSharedConfig::openConfig()->group(QStringLiteral("KatePlugin_plugin:%1:").arg(identifier));
+			interface->readSessionConfig(group);
 		}
 		return plugin;
 	}
@@ -224,11 +224,13 @@ void KatePluginIntegrationApp::unloadPlugin(const QString &identifier) {
 			KConfigGroup group = KSharedConfig::openConfig()->group(QStringLiteral("KatePlugin:%1:").arg(identifier));
 			interface->writeSessionConfig(group);
 		}
-		interface = qobject_cast<KTextEditor::SessionConfigInterface *>(info.plugin);
-		if (interface) {
-			KConfigGroup group = KSharedConfig::openConfig()->group(QStringLiteral("KatePlugin_plugin:%1:").arg(identifier));
-			interface->writeSessionConfig(group);
-		}
+	}
+	auto interface = qobject_cast<KTextEditor::SessionConfigInterface *>(info.plugin);
+	if (interface) {
+		KConfigGroup group = KSharedConfig::openConfig()->group(QStringLiteral("KatePlugin_plugin:%1:").arg(identifier));
+		interface->writeSessionConfig(group);
+	}
+	if (view) {
 		Q_EMIT mainWindow()->main->pluginViewDeleted(identifier, view);
 		delete view;
 	}
diff --git a/rkward/windows/rkcommandlog.cpp b/rkward/windows/rkcommandlog.cpp
index 8e654e2e1..5761f7afc 100644
--- a/rkward/windows/rkcommandlog.cpp
+++ b/rkward/windows/rkcommandlog.cpp
@@ -9,6 +9,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
 
 #include "../rbackend/rkrinterface.h"
 #include "../rkconsole.h"
+#include "../settings/rksettings.h"
 #include "../settings/rksettingsmodulewatch.h"
 #include "../misc/rkstandardactions.h"
 #include "rkcommandeditorwindow.h"
diff --git a/rkward/windows/rkcommandlog.h b/rkward/windows/rkcommandlog.h
index 517dfe4f3..4efff6cbc 100644
--- a/rkward/windows/rkcommandlog.h
+++ b/rkward/windows/rkcommandlog.h
@@ -12,7 +12,6 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include <qtextedit.h>
 
 #include "rkmdiwindow.h"
-#include "../settings/rksettings.h"
 #include "../rbackend/rcommand.h"
 
 class RKCommandLogView;
diff --git a/rkward/windows/rkmdiwindow.cpp b/rkward/windows/rkmdiwindow.cpp
index fe0a84a4f..f146391ac 100644
--- a/rkward/windows/rkmdiwindow.cpp
+++ b/rkward/windows/rkmdiwindow.cpp
@@ -28,6 +28,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
 #include "rktoolwindowbar.h"
 #include "rktoolwindowlist.h"
 #include "../settings/rksettingsmodulegeneral.h"
+#include "../settings/rksettings.h"
 #include "../misc/rkstandardicons.h"
 #include "../misc/rkxmlguisyncer.h"
 #include "../rbackend/rcommand.h"
diff --git a/rkward/windows/rkmdiwindow.h b/rkward/windows/rkmdiwindow.h
index 2f28516e6..eb7ab9b13 100644
--- a/rkward/windows/rkmdiwindow.h
+++ b/rkward/windows/rkmdiwindow.h
@@ -15,7 +15,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
 
 #include <KParts/Part>
 
-#include "../settings/rksettings.h"
+#include "../settings/rksettingsmodule.h"
 
 class QEvent;
 class QPaintEvent;



More information about the rkward-tracker mailing list