[kdevelop/kdevelop] plugins: Some preferences pages leak their UI

Martin Bednar <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit dc92a46cbe170901e40928ffbf937bf7f8986dd9 by Martin Bednar, on behalf of Martin Bednár.
Committed on 06/08/2026 at 17:13.
Pushed by bednar into branch 'master'.

Some preferences pages leak their UI

Some plugins leak their UI objects when the preferences are closed.
Fix it by using std::unique_ptr for the UI.

Note that in order to use unique_ptr with forward declaration, the
enclosing class' destructor must be defined out of the header.
(Technically after the contained class is completely resolved)

Fixed plugins
Android,Clazy, custombuildsystem, noproject (includesanddefines),
Docker, Meson (config, rewriter), patchreview, perfoce, qmakebuilder.

M  +1    -1    plugins/android/androidpreferences.cpp
M  +1    -1    plugins/android/androidpreferences.h
M  +2    -3    plugins/clazy/config/globalconfigpage.cpp
M  +1    -1    plugins/clazy/config/globalconfigpage.h
M  +2    -0    plugins/custom-buildsystem/configwidget.cpp
M  +2    -1    plugins/custom-buildsystem/configwidget.h
M  +2    -0    plugins/custom-buildsystem/custombuildsystemconfigwidget.cpp
M  +2    -1    plugins/custom-buildsystem/custombuildsystemconfigwidget.h
M  +2    -0    plugins/custom-definesandincludes/noprojectincludesanddefines/noprojectcustomincludepaths.cpp
M  +2    -1    plugins/custom-definesandincludes/noprojectincludesanddefines/noprojectcustomincludepaths.h
M  +1    -1    plugins/docker/dockerpreferences.cpp
M  +1    -1    plugins/docker/dockerpreferences.h
M  +1    -1    plugins/meson/settings/mesonconfigpage.cpp
M  +1    -1    plugins/meson/settings/mesonconfigpage.h
M  +4    -2    plugins/meson/settings/mesonrewriterinput.cpp
M  +3    -2    plugins/meson/settings/mesonrewriterinput.h
M  +3    -1    plugins/meson/settings/mesonrewriterpage.cpp
M  +2    -2    plugins/meson/settings/mesonrewriterpage.h
M  +1    -1    plugins/patchreview/localpatchsource.h
M  +4    -0    plugins/perforce/ui/perforceimportmetadatawidget.cpp
M  +5    -3    plugins/perforce/ui/perforceimportmetadatawidget.h
M  +1    -1    plugins/qmakebuilder/qmakebuilderpreferences.cpp
M  +1    -1    plugins/qmakebuilder/qmakebuilderpreferences.h

https://invent.kde.org/kdevelop/kdevelop/-/commit/dc92a46cbe170901e40928ffbf937bf7f8986dd9

diff --git a/plugins/android/androidpreferences.cpp b/plugins/android/androidpreferences.cpp
index 860573fc6d..f03461fa2a 100644
--- a/plugins/android/androidpreferences.cpp
+++ b/plugins/android/androidpreferences.cpp
@@ -9,8 +9,8 @@
 
 AndroidPreferences::AndroidPreferences(KDevelop::IPlugin* plugin, KCoreConfigSkeleton* config, QWidget* parent)
     : KDevelop::ConfigPage(plugin, config, parent)
+    , m_prefsUi(new Ui::AndroidPreferences)
 {
-    auto m_prefsUi = new Ui::AndroidPreferences;
     m_prefsUi->setupUi(this);
 }
 
diff --git a/plugins/android/androidpreferences.h b/plugins/android/androidpreferences.h
index 746f6d9c8a..3ac356dfe3 100644
--- a/plugins/android/androidpreferences.h
+++ b/plugins/android/androidpreferences.h
@@ -22,7 +22,7 @@ class AndroidPreferences : public KDevelop::ConfigPage
         KDevelop::ConfigPage::ConfigPageType configPageType() const override;
         QString name() const override;
     private:
-        QScopedPointer<Ui::AndroidPreferences> m_prefsUi;
+        std::unique_ptr<Ui::AndroidPreferences> m_prefsUi;
 };
 
 #endif
diff --git a/plugins/clazy/config/globalconfigpage.cpp b/plugins/clazy/config/globalconfigpage.cpp
index 8d75419cc7..eb8c71f2e6 100644
--- a/plugins/clazy/config/globalconfigpage.cpp
+++ b/plugins/clazy/config/globalconfigpage.cpp
@@ -15,12 +15,11 @@ namespace Clazy
 {
 
 GlobalConfigPage::GlobalConfigPage(CheckSetSelectionManager* checkSetSelectionManager,
-                                   const QSharedPointer<const ChecksDB>& db,
-                                   KDevelop::IPlugin* plugin, QWidget* parent)
+                                   const QSharedPointer<const ChecksDB>& db, KDevelop::IPlugin* plugin, QWidget* parent)
     : ConfigPage(plugin, GlobalSettings::self(), parent)
+    , ui(new Ui::GlobalConfigPage())
     , m_checkSetSelectionManager(checkSetSelectionManager)
 {
-    ui = new Ui::GlobalConfigPage();
     ui->setupUi(this);
     ui->checksets->setCheckSetSelectionManager(checkSetSelectionManager, db);
 
diff --git a/plugins/clazy/config/globalconfigpage.h b/plugins/clazy/config/globalconfigpage.h
index afff227690..aa0d3f3ed2 100644
--- a/plugins/clazy/config/globalconfigpage.h
+++ b/plugins/clazy/config/globalconfigpage.h
@@ -41,7 +41,7 @@ public:
     void reset() override;
 
 private:
-    Ui::GlobalConfigPage* ui;
+    std::unique_ptr<Ui::GlobalConfigPage> ui;
     CheckSetSelectionManager* const m_checkSetSelectionManager;
 };
 
diff --git a/plugins/custom-buildsystem/configwidget.cpp b/plugins/custom-buildsystem/configwidget.cpp
index 3b485c5bf2..497df7b0f7 100644
--- a/plugins/custom-buildsystem/configwidget.cpp
+++ b/plugins/custom-buildsystem/configwidget.cpp
@@ -39,6 +39,8 @@ ConfigWidget::ConfigWidget( QWidget* parent )
     connect( ui->actionExecutable->lineEdit(), &KLineEdit::textEdited, this, QOverload<const QString&>::of(&ConfigWidget::actionExecutableChanged) );
 }
 
+ConfigWidget::~ConfigWidget() noexcept = default;
+
 CustomBuildSystemConfig ConfigWidget::config() const
 {
     CustomBuildSystemConfig c;
diff --git a/plugins/custom-buildsystem/configwidget.h b/plugins/custom-buildsystem/configwidget.h
index 2a5887b2e0..42462bf725 100644
--- a/plugins/custom-buildsystem/configwidget.h
+++ b/plugins/custom-buildsystem/configwidget.h
@@ -26,6 +26,7 @@ class ConfigWidget : public QWidget
 Q_OBJECT
 public:
     explicit ConfigWidget( QWidget* parent = nullptr );
+    ~ConfigWidget() override;
     void loadConfig(const CustomBuildSystemConfig& cfg);
     CustomBuildSystemConfig config() const;
     void clear();
@@ -42,7 +43,7 @@ private:
     template<typename F>
     void applyChange(F toolChanger);
 
-    Ui::ConfigWidget* ui;
+    std::unique_ptr<Ui::ConfigWidget> ui;
     QVector<CustomBuildSystemTool> m_tools;
     void setTool( const CustomBuildSystemTool& tool );
 };
diff --git a/plugins/custom-buildsystem/custombuildsystemconfigwidget.cpp b/plugins/custom-buildsystem/custombuildsystemconfigwidget.cpp
index 2ba6f2c111..c5f975dca1 100644
--- a/plugins/custom-buildsystem/custombuildsystemconfigwidget.cpp
+++ b/plugins/custom-buildsystem/custombuildsystemconfigwidget.cpp
@@ -55,6 +55,8 @@ CustomBuildSystemConfigWidget::CustomBuildSystemConfigWidget( QWidget* parent )
     connect( this, &CustomBuildSystemConfigWidget::changed, this, &CustomBuildSystemConfigWidget::verify );
 }
 
+CustomBuildSystemConfigWidget::~CustomBuildSystemConfigWidget() noexcept = default;
+
 void CustomBuildSystemConfigWidget::loadDefaults()
 {
 }
diff --git a/plugins/custom-buildsystem/custombuildsystemconfigwidget.h b/plugins/custom-buildsystem/custombuildsystemconfigwidget.h
index 1904b99f20..a68023f024 100644
--- a/plugins/custom-buildsystem/custombuildsystemconfigwidget.h
+++ b/plugins/custom-buildsystem/custombuildsystemconfigwidget.h
@@ -23,6 +23,7 @@ class CustomBuildSystemConfigWidget : public QWidget
 Q_OBJECT
 public:
     explicit CustomBuildSystemConfigWidget( QWidget* parent );
+    ~CustomBuildSystemConfigWidget() override;
     void loadFrom( KConfig* );
     void saveTo(KConfig* cfg);
     void loadDefaults();
@@ -37,7 +38,7 @@ private Q_SLOTS:
     void verify();
 private:
     void saveConfig( KConfigGroup& grp, const CustomBuildSystemConfig& c, int index );
-    Ui::CustomBuildSystemConfigWidget* ui;
+    std::unique_ptr<Ui::CustomBuildSystemConfigWidget> ui;
     QVector<CustomBuildSystemConfig> configs;
 };
 
diff --git a/plugins/custom-definesandincludes/noprojectincludesanddefines/noprojectcustomincludepaths.cpp b/plugins/custom-definesandincludes/noprojectincludesanddefines/noprojectcustomincludepaths.cpp
index f1e1399cf3..c05c641f82 100644
--- a/plugins/custom-definesandincludes/noprojectincludesanddefines/noprojectcustomincludepaths.cpp
+++ b/plugins/custom-definesandincludes/noprojectincludesanddefines/noprojectcustomincludepaths.cpp
@@ -36,6 +36,8 @@ QString NoProjectCustomIncludePaths::storageDirectory() const
     return m_ui->storageDirectory->url().toLocalFile();
 }
 
+NoProjectCustomIncludePaths::~NoProjectCustomIncludePaths() noexcept = default;
+
 void NoProjectCustomIncludePaths::appendCustomIncludePath(const QString& path)
 {
     m_ui->customIncludePaths->appendPlainText(path);
diff --git a/plugins/custom-definesandincludes/noprojectincludesanddefines/noprojectcustomincludepaths.h b/plugins/custom-definesandincludes/noprojectincludesanddefines/noprojectcustomincludepaths.h
index 5055734b66..90804f2d56 100644
--- a/plugins/custom-definesandincludes/noprojectincludesanddefines/noprojectcustomincludepaths.h
+++ b/plugins/custom-definesandincludes/noprojectincludesanddefines/noprojectcustomincludepaths.h
@@ -21,6 +21,7 @@ class NoProjectCustomIncludePaths : public QDialog
 
 public:
     explicit NoProjectCustomIncludePaths( QWidget* parent = nullptr );
+    ~NoProjectCustomIncludePaths() override;
 
     void setStorageDirectory( const QString& path );
     QString storageDirectory() const;
@@ -30,7 +31,7 @@ public:
     void setCustomIncludePaths(const QString& paths);
 
 private:
-    Ui::CustomIncludePaths* m_ui;
+    std::unique_ptr<Ui::CustomIncludePaths> m_ui;
 
 private Q_SLOTS:
     void openAddIncludeDirectoryDialog();
diff --git a/plugins/docker/dockerpreferences.cpp b/plugins/docker/dockerpreferences.cpp
index 7a6e455919..87a9ce405b 100644
--- a/plugins/docker/dockerpreferences.cpp
+++ b/plugins/docker/dockerpreferences.cpp
@@ -9,8 +9,8 @@
 
 DockerPreferences::DockerPreferences(KDevelop::IPlugin* plugin, KCoreConfigSkeleton* config, QWidget* parent)
     : KDevelop::ConfigPage(plugin, config, parent)
+    , m_prefsUi(new Ui::DockerPreferences)
 {
-    auto m_prefsUi = new Ui::DockerPreferences;
     m_prefsUi->setupUi(this);
 }
 
diff --git a/plugins/docker/dockerpreferences.h b/plugins/docker/dockerpreferences.h
index 78f7a0e0f6..2704380324 100644
--- a/plugins/docker/dockerpreferences.h
+++ b/plugins/docker/dockerpreferences.h
@@ -22,7 +22,7 @@ public:
     KDevelop::ConfigPage::ConfigPageType configPageType() const override;
     QString name() const override;
 private:
-    QScopedPointer<Ui::DockerPreferences> m_prefsUi;
+    std::unique_ptr<Ui::DockerPreferences> m_prefsUi;
 };
 
 #endif
diff --git a/plugins/meson/settings/mesonconfigpage.cpp b/plugins/meson/settings/mesonconfigpage.cpp
index 7bc29a89a8..1c7ad7bed1 100644
--- a/plugins/meson/settings/mesonconfigpage.cpp
+++ b/plugins/meson/settings/mesonconfigpage.cpp
@@ -27,12 +27,12 @@ using namespace KDevelop;
 MesonConfigPage::MesonConfigPage(IPlugin* plugin, IProject* project, QWidget* parent)
     : ConfigPage(plugin, nullptr, parent)
     , m_project(project)
+    , m_ui(new Ui::MesonConfigPage)
 {
     Q_ASSERT(project); // Catch errors early
     auto* mgr = dynamic_cast<MesonManager*>(m_project->buildSystemManager());
     Q_ASSERT(mgr); // This dialog only works with the MesonManager
 
-    m_ui = new Ui::MesonConfigPage;
     m_ui->setupUi(this);
     m_ui->advanced->setSupportedBackends(mgr->supportedMesonBackends());
 
diff --git a/plugins/meson/settings/mesonconfigpage.h b/plugins/meson/settings/mesonconfigpage.h
index d835d5aaf0..5c8dc5925f 100644
--- a/plugins/meson/settings/mesonconfigpage.h
+++ b/plugins/meson/settings/mesonconfigpage.h
@@ -51,7 +51,7 @@ private:
 
 private:
     KDevelop::IProject* m_project = nullptr;
-    Ui::MesonConfigPage* m_ui = nullptr;
+    std::unique_ptr<Ui::MesonConfigPage> m_ui;
     Meson::MesonConfig m_config;
     Meson::BuildDir m_current;
     bool m_configChanged = false;
diff --git a/plugins/meson/settings/mesonrewriterinput.cpp b/plugins/meson/settings/mesonrewriterinput.cpp
index 22f1122fb7..70ac99d9ae 100644
--- a/plugins/meson/settings/mesonrewriterinput.cpp
+++ b/plugins/meson/settings/mesonrewriterinput.cpp
@@ -17,10 +17,10 @@
 
 MesonRewriterInputBase::MesonRewriterInputBase(const QString& name, const QString& kwarg, QWidget* parent)
     : QWidget(parent)
+    , m_ui(new Ui::MesonRewriterInputBase)
     , m_name(name)
     , m_kwarg(kwarg)
 {
-    m_ui = new Ui::MesonRewriterInputBase;
     m_ui->setupUi(this);
     m_ui->l_name->setText(m_name + QLatin1Char(':'));
 
@@ -169,15 +169,17 @@ QJsonValue MesonRewriterInputString::value()
 
 MesonRewriterOptionContainer::MesonRewriterOptionContainer(MesonOptViewPtr optView, QWidget* parent)
     : QWidget(parent)
+    , m_ui(new Ui::MesonRewriterOptionContainer)
     , m_optView(optView)
 {
-    m_ui = new Ui::MesonRewriterOptionContainer;
     m_ui->setupUi(this);
     m_ui->h_layout->insertWidget(0, m_optView.get());
 
     connect(optView.get(), &MesonOptionBaseView::configChanged, this, [this]() { emit configChanged(); });
 }
 
+MesonRewriterOptionContainer::~MesonRewriterOptionContainer() noexcept = default;
+
 void MesonRewriterOptionContainer::deleteMe()
 {
     m_markedForDeletion = true;
diff --git a/plugins/meson/settings/mesonrewriterinput.h b/plugins/meson/settings/mesonrewriterinput.h
index 90669ff9ce..c3fdba084c 100644
--- a/plugins/meson/settings/mesonrewriterinput.h
+++ b/plugins/meson/settings/mesonrewriterinput.h
@@ -66,7 +66,7 @@ Q_SIGNALS:
     void configChanged();
 
 private:
-    Ui::MesonRewriterInputBase* m_ui = nullptr;
+    std::unique_ptr<Ui::MesonRewriterInputBase> m_ui;
     QString m_name;
     QString m_kwarg;
     bool m_enabled = false;
@@ -101,6 +101,7 @@ class MesonRewriterOptionContainer : public QWidget
 
 public:
     MesonRewriterOptionContainer(MesonOptViewPtr optView, QWidget* parent);
+    ~MesonRewriterOptionContainer() override;
 
     bool shouldDelete() const;
     bool hasChanged() const;
@@ -113,7 +114,7 @@ Q_SIGNALS:
     void configChanged();
 
 private:
-    Ui::MesonRewriterOptionContainer* m_ui = nullptr;
+    std::unique_ptr<Ui::MesonRewriterOptionContainer> m_ui;
     MesonOptViewPtr m_optView = nullptr;
 
     bool m_markedForDeletion = false;
diff --git a/plugins/meson/settings/mesonrewriterpage.cpp b/plugins/meson/settings/mesonrewriterpage.cpp
index 505048d938..5a8ac70f9d 100644
--- a/plugins/meson/settings/mesonrewriterpage.cpp
+++ b/plugins/meson/settings/mesonrewriterpage.cpp
@@ -52,10 +52,10 @@ private:
 MesonRewriterPage::MesonRewriterPage(IPlugin* plugin, IProject* project, QWidget* parent)
     : ConfigPage(plugin, nullptr, parent)
     , m_project(project)
+    , m_ui(new Ui::MesonRewriterPage)
 {
     Q_ASSERT(m_project);
 
-    m_ui = new Ui::MesonRewriterPage;
     m_ui->setupUi(this);
 
     m_projectKwargs = constructPojectInputs();
@@ -70,6 +70,8 @@ MesonRewriterPage::MesonRewriterPage(IPlugin* plugin, IProject* project, QWidget
     reset();
 }
 
+MesonRewriterPage::~MesonRewriterPage() noexcept = default;
+
 #define STRING_INPUT(name, id) new MesonRewriterInputString(QStringLiteral(name), QStringLiteral(id), this)
 
 QVector<MesonRewriterInputBase*> MesonRewriterPage::constructPojectInputs()
diff --git a/plugins/meson/settings/mesonrewriterpage.h b/plugins/meson/settings/mesonrewriterpage.h
index 9c8c5dc497..664f2d5922 100644
--- a/plugins/meson/settings/mesonrewriterpage.h
+++ b/plugins/meson/settings/mesonrewriterpage.h
@@ -32,7 +32,7 @@ public:
 
 public:
     explicit MesonRewriterPage(KDevelop::IPlugin* plugin, KDevelop::IProject* project, QWidget* parent = nullptr);
-
+    ~MesonRewriterPage() override;
     QString name() const override;
     QString fullName() const override;
     QIcon icon() const override;
@@ -56,7 +56,7 @@ private:
 
 private:
     KDevelop::IProject* m_project = nullptr;
-    Ui::MesonRewriterPage* m_ui = nullptr;
+    std::unique_ptr<Ui::MesonRewriterPage> m_ui;
     bool m_configChanged = false;
     State m_state = START;
     MesonOptsPtr m_opts = nullptr;
diff --git a/plugins/patchreview/localpatchsource.h b/plugins/patchreview/localpatchsource.h
index 12808a3e87..3c406b7280 100644
--- a/plugins/patchreview/localpatchsource.h
+++ b/plugins/patchreview/localpatchsource.h
@@ -73,7 +73,7 @@ public Q_SLOTS:
 
 private:
     LocalPatchSource* m_lpatch;
-    Ui::LocalPatchWidget* m_ui;
+    std::unique_ptr<Ui::LocalPatchWidget> m_ui;
 };
 
 #endif // KDEVPLATFORM_PLUGIN_LOCALPATCHSOURCE_H
diff --git a/plugins/perforce/ui/perforceimportmetadatawidget.cpp b/plugins/perforce/ui/perforceimportmetadatawidget.cpp
index ac55478ea8..7a99cb144e 100644
--- a/plugins/perforce/ui/perforceimportmetadatawidget.cpp
+++ b/plugins/perforce/ui/perforceimportmetadatawidget.cpp
@@ -13,6 +13,8 @@
 #include <QTextStream>
 #include <QStandardPaths>
 
+#include "ui_perforceimportmetadatawidget.h"
+
 using namespace KDevelop;
 
 PerforceImportMetadataWidget::PerforceImportMetadataWidget(QWidget* parent)
@@ -51,6 +53,8 @@ PerforceImportMetadataWidget::PerforceImportMetadataWidget(QWidget* parent)
     connect(m_ui->testP4setupButton, &QPushButton::pressed, this, &PerforceImportMetadataWidget::testP4setup);
 }
 
+PerforceImportMetadataWidget::~PerforceImportMetadataWidget() noexcept = default;
+
 QUrl PerforceImportMetadataWidget::source() const
 {
     return m_ui->sourceLoc->url();
diff --git a/plugins/perforce/ui/perforceimportmetadatawidget.h b/plugins/perforce/ui/perforceimportmetadatawidget.h
index e8e1ca9b1e..c83873070f 100644
--- a/plugins/perforce/ui/perforceimportmetadatawidget.h
+++ b/plugins/perforce/ui/perforceimportmetadatawidget.h
@@ -7,8 +7,9 @@
 #ifndef KDEVPLATFORM_PERFORCEIMPORTMETADATAWIDGET_H
 #define KDEVPLATFORM_PERFORCEIMPORTMETADATAWIDGET_H
 
-#include "ui_perforceimportmetadatawidget.h"
-
+namespace Ui {
+class PerforceImportMetadataWidget;
+}
 #include <vcs/widgets/vcsimportmetadatawidget.h>
 
 /**
@@ -22,6 +23,7 @@ class PerforceImportMetadataWidget
 
 public:
     explicit PerforceImportMetadataWidget(QWidget* parent = nullptr);
+    ~PerforceImportMetadataWidget() override;
 
     QUrl source() const override;
     KDevelop::VcsLocation destination() const override;
@@ -43,7 +45,7 @@ private:
 
     bool validateP4user(const QString& projectDir) const;
 
-    Ui::PerforceImportMetadataWidget* m_ui;
+    std::unique_ptr<Ui::PerforceImportMetadataWidget> m_ui;
     QString m_errorDescription;
 };
 
diff --git a/plugins/qmakebuilder/qmakebuilderpreferences.cpp b/plugins/qmakebuilder/qmakebuilderpreferences.cpp
index 2adf81af9b..7f65450487 100644
--- a/plugins/qmakebuilder/qmakebuilderpreferences.cpp
+++ b/plugins/qmakebuilder/qmakebuilderpreferences.cpp
@@ -26,8 +26,8 @@ QMakeBuilderPreferences::QMakeBuilderPreferences(KDevelop::IPlugin* plugin,
                                                  const KDevelop::ProjectConfigOptions& options, QWidget* parent)
     : KDevelop::ConfigPage(plugin, nullptr, parent)
     , m_project(options.project)
+    , m_prefsUi(new Ui::QMakeConfig)
 {
-    m_prefsUi = new Ui::QMakeConfig;
     m_prefsUi->setupUi(this);
 
     m_chooserUi = new QMakeBuildDirChooser(m_project);
diff --git a/plugins/qmakebuilder/qmakebuilderpreferences.h b/plugins/qmakebuilder/qmakebuilderpreferences.h
index e9056069d8..2628d1f2ef 100644
--- a/plugins/qmakebuilder/qmakebuilderpreferences.h
+++ b/plugins/qmakebuilder/qmakebuilderpreferences.h
@@ -42,7 +42,7 @@ public Q_SLOTS:
 private:
     KDevelop::IProject* m_project;
 
-    Ui::QMakeConfig* m_prefsUi;
+    std::unique_ptr<Ui::QMakeConfig> m_prefsUi;
     QMakeBuildDirChooser* m_chooserUi;
 };
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.