[education/rkward/kf5] rkward/windows: Make sure to delete "global" kate plugin tool windows in time (fixes segfault on exit in certain cases)

Thomas Friedrichsmeier null at kde.org
Wed Apr 10 16:12:08 BST 2024


Git commit 901d249b30512d13ec01ccbf716213372f3a7be9 by Thomas Friedrichsmeier.
Committed on 04/04/2024 at 09:10.
Pushed by tfry into branch 'kf5'.

Make sure to delete "global" kate plugin tool windows in time (fixes segfault on exit in certain cases)

M  +50   -44   rkward/windows/katepluginintegration.cpp
M  +2    -1    rkward/windows/katepluginintegration.h

https://invent.kde.org/education/rkward/-/commit/901d249b30512d13ec01ccbf716213372f3a7be9

diff --git a/rkward/windows/katepluginintegration.cpp b/rkward/windows/katepluginintegration.cpp
index ef85ccf3c..65fdac0e0 100644
--- a/rkward/windows/katepluginintegration.cpp
+++ b/rkward/windows/katepluginintegration.cpp
@@ -36,6 +36,50 @@ SPDX-License-Identifier: GPL-2.0-or-later
 
 #include "../debug.h"
 
+///  BEGIN  Helper class for tool windows
+class KatePluginWindow : public RKMDIWindow {
+	Q_OBJECT
+public:
+	KatePluginWindow(QWidget *parent, bool tool_window=true) : RKMDIWindow(parent, RKMDIWindow::KatePluginWindow, tool_window) {
+		RK_TRACE (APP);
+
+		QVBoxLayout *layout = new QVBoxLayout(this);
+		layout->setContentsMargins(0, 0, 0, 0);
+		setPart(new RKDummyPart(this, this));
+		initializeActivationSignals();
+		setFocusPolicy(Qt::ClickFocus);
+	}
+	~KatePluginWindow() {
+		RK_TRACE (APP);
+	}
+
+	void showEvent(QShowEvent *e) override {
+		RKMDIWindow::showEvent(e);
+		Q_EMIT toolVisibleChanged(true);
+	}
+
+	void hideEvent(QHideEvent *e) override {
+		RKMDIWindow::hideEvent(e);
+		Q_EMIT toolVisibleChanged(false);
+	}
+
+/** This is a bit lame, but the plugin does not add itself to the parent widget's layout by itself. So we need this override
+ *  to do that. Where did the good old KVBox go? */
+	void childEvent(QChildEvent *ev) override {
+		if ((ev->type() == QEvent::ChildAdded) && ev->child()->isWidgetType()) {
+			QWidget *widget = qobject_cast<QWidget *>(ev->child()); // clazy:exclude=child-event-qobject-cast - Cast to QWidget is ok, we checked for widgetType(), above
+			if (widget) {
+				layout()->addWidget(widget);
+				setFocusProxy(widget);
+			}
+		}
+		RKMDIWindow::childEvent(ev);
+	}
+Q_SIGNALS:
+	void toolVisibleChanged(bool);
+};
+
+///  END  Helper class for tool windows
 ///  BEGIN  KTextEditor::Application interface
 
 KatePluginIntegrationApp::KatePluginIntegrationApp(QObject *parent) : QObject (parent) {
@@ -184,6 +228,12 @@ void KatePluginIntegrationApp::saveConfigAndUnload() {
 		unloadPlugin(it.key());
 	}
 	known_plugins.clear();
+
+	// "Global" tool views such as the Diagnostic Window did not get unloaded with any plugin, but need to be torn down, while KXML (factory) is still availalbe
+	if (window->plugin_resources.contains(nullptr)) {
+		auto wins = window->plugin_resources[nullptr].windows;
+		for(auto win : wins) delete win;
+	}
 }
 
 QList<KTextEditor::MainWindow *> KatePluginIntegrationApp::mainWindows() {
@@ -304,7 +354,6 @@ KTextEditor::Plugin *KatePluginIntegrationApp::plugin(const QString &name) {
 ///  END  KTextEditor::Application interface
 ///  BEGIN  KTextEditor::MainWindow interface
 
-
 KatePluginIntegrationWindow::KatePluginIntegrationWindow(KatePluginIntegrationApp *parent) : QObject(parent), KXMLGUIClient() {
 	RK_TRACE(APP);
 
@@ -323,49 +372,6 @@ KatePluginIntegrationWindow::~KatePluginIntegrationWindow() {
 	delete dynamic_actions_client;
 }
 
-
-class KatePluginWindow : public RKMDIWindow {
-	Q_OBJECT
-public:
-	KatePluginWindow(QWidget *parent, bool tool_window=true) : RKMDIWindow(parent, RKMDIWindow::KatePluginWindow, tool_window) {
-		RK_TRACE (APP);
-
-		QVBoxLayout *layout = new QVBoxLayout(this);
-		layout->setContentsMargins(0, 0, 0, 0);
-		setPart(new RKDummyPart(this, this));
-		initializeActivationSignals();
-		setFocusPolicy(Qt::ClickFocus);
-	}
-	~KatePluginWindow() {
-		RK_TRACE (APP);
-	}
-
-	void showEvent(QShowEvent *e) override {
-		RKMDIWindow::showEvent(e);
-		Q_EMIT toolVisibleChanged(true);
-	}
-
-	void hideEvent(QHideEvent *e) override {
-		RKMDIWindow::hideEvent(e);
-		Q_EMIT toolVisibleChanged(false);
-	}
-
-/** This is a bit lame, but the plugin does not add itself to the parent widget's layout by itself. So we need this override
- *  to do that. Where did the good old KVBox go? */
-	void childEvent(QChildEvent *ev) override {
-		if ((ev->type() == QEvent::ChildAdded) && ev->child()->isWidgetType()) {
-			QWidget *widget = qobject_cast<QWidget *>(ev->child()); // clazy:exclude=child-event-qobject-cast - Cast to QWidget is ok, we checked for widgetType(), above
-			if (widget) {
-				layout()->addWidget(widget);
-				setFocusProxy(widget);
-			}
-		}
-		RKMDIWindow::childEvent(ev);
-	}
-Q_SIGNALS:
-	void toolVisibleChanged(bool);
-};
-
 QWidget* KatePluginIntegrationWindow::createToolView (KTextEditor::Plugin *plugin, const QString &identifier, KTextEditor::MainWindow::ToolViewPosition pos, const QIcon &icon, const QString &text) {
 	RK_TRACE (APP);
 
diff --git a/rkward/windows/katepluginintegration.h b/rkward/windows/katepluginintegration.h
index f8a52fd3e..f175c7972 100644
--- a/rkward/windows/katepluginintegration.h
+++ b/rkward/windows/katepluginintegration.h
@@ -64,6 +64,7 @@ friend class RKSettingsModuleKatePlugins;
 	QString idForPlugin(const KPluginMetaData &plugin) const;
 };
 
+class KatePluginWindow;
 class KatePluginIntegrationWindow : public QObject, public KXMLGUIClient {
 	Q_OBJECT
 public:
@@ -111,7 +112,7 @@ friend class KatePluginIntegrationApp;
 		PluginResources() : view(nullptr) {};
 		QObject *view;
 		QList<KXMLGUIClient*> clients;
-		QList<RKMDIWindow*> windows;
+		QList<KatePluginWindow*> windows;
 	};
 	QHash<QObject*, PluginResources> plugin_resources;
 



More information about the rkward-tracker mailing list