From 2c0554c187adb4ef886affd193b8149afa199d13 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Wed, 11 Jul 2018 08:25:07 +0200 Subject: [PATCH] ProjectExplorer: Fix memory leaks in tree models Fix widgets being leaked by the ToolChainOptionsPage. This page created widgets and stored them in the tree node and never deleted them. The fix is to put all the widgets into one QStackedWidget, so that this will clean up once the page is destroyed. Change-Id: Ic02824a4c52771d8962dc594176077c2e139fb84 Reviewed-by: Tobias Hunger --- src/plugins/android/androidtoolchain.cpp | 4 ++-- src/plugins/android/androidtoolchain.h | 2 +- src/plugins/nim/project/nimtoolchain.cpp | 4 ++-- src/plugins/nim/project/nimtoolchain.h | 2 +- .../projectexplorer/customtoolchain.cpp | 4 ++-- src/plugins/projectexplorer/customtoolchain.h | 2 +- src/plugins/projectexplorer/gcctoolchain.cpp | 4 ++-- src/plugins/projectexplorer/gcctoolchain.h | 2 +- src/plugins/projectexplorer/msvctoolchain.cpp | 8 +++---- src/plugins/projectexplorer/msvctoolchain.h | 4 ++-- src/plugins/projectexplorer/toolchain.h | 2 +- .../projectexplorer/toolchainoptionspage.cpp | 24 +++++++++++-------- .../toolchainsettingsaccessor.cpp | 3 ++- src/plugins/qnx/qnxtoolchain.cpp | 4 ++-- src/plugins/qnx/qnxtoolchain.h | 2 +- 15 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/plugins/android/androidtoolchain.cpp b/src/plugins/android/androidtoolchain.cpp index f8d0535c7e5..6fb7e67bbf2 100644 --- a/src/plugins/android/androidtoolchain.cpp +++ b/src/plugins/android/androidtoolchain.cpp @@ -181,9 +181,9 @@ bool AndroidToolChain::operator ==(const ToolChain &tc) const return m_ndkToolChainVersion == static_cast(tc).m_ndkToolChainVersion; } -ToolChainConfigWidget *AndroidToolChain::configurationWidget() +std::unique_ptr AndroidToolChain::createConfigurationWidget() { - return new AndroidToolChainConfigWidget(this); + return std::make_unique(this); } FileName AndroidToolChain::suggestedDebugger() const diff --git a/src/plugins/android/androidtoolchain.h b/src/plugins/android/androidtoolchain.h index 4d37e4ae079..0352bfe94e9 100644 --- a/src/plugins/android/androidtoolchain.h +++ b/src/plugins/android/androidtoolchain.h @@ -44,7 +44,7 @@ public: bool operator ==(const ProjectExplorer::ToolChain &) const override; - ProjectExplorer::ToolChainConfigWidget *configurationWidget() override; + std::unique_ptr createConfigurationWidget() override; Utils::FileName suggestedDebugger() const override; Utils::FileName suggestedGdbServer() const; diff --git a/src/plugins/nim/project/nimtoolchain.cpp b/src/plugins/nim/project/nimtoolchain.cpp index cd41c178693..56f6f3f9a9f 100644 --- a/src/plugins/nim/project/nimtoolchain.cpp +++ b/src/plugins/nim/project/nimtoolchain.cpp @@ -136,9 +136,9 @@ IOutputParser *NimToolChain::outputParser() const return nullptr; } -ToolChainConfigWidget *NimToolChain::configurationWidget() +std::unique_ptr NimToolChain::createConfigurationWidget() { - return new NimToolChainConfigWidget(this); + return std::make_unique(this); } ToolChain *NimToolChain::clone() const diff --git a/src/plugins/nim/project/nimtoolchain.h b/src/plugins/nim/project/nimtoolchain.h index 2da07dd2e23..4e6ee118c12 100644 --- a/src/plugins/nim/project/nimtoolchain.h +++ b/src/plugins/nim/project/nimtoolchain.h @@ -54,7 +54,7 @@ public: QString compilerVersion() const; void setCompilerCommand(const Utils::FileName &compilerCommand); ProjectExplorer::IOutputParser *outputParser() const final; - ProjectExplorer::ToolChainConfigWidget *configurationWidget() final; + std::unique_ptr createConfigurationWidget() final; ProjectExplorer::ToolChain *clone() const final; QVariantMap toMap() const final; diff --git a/src/plugins/projectexplorer/customtoolchain.cpp b/src/plugins/projectexplorer/customtoolchain.cpp index 68c663bbc92..1bdf90db23b 100644 --- a/src/plugins/projectexplorer/customtoolchain.cpp +++ b/src/plugins/projectexplorer/customtoolchain.cpp @@ -412,9 +412,9 @@ QList CustomToolChain::parsers() return result; } -ToolChainConfigWidget *CustomToolChain::configurationWidget() +std::unique_ptr CustomToolChain::createConfigurationWidget() { - return new Internal::CustomToolChainConfigWidget(this); + return std::make_unique(this); } namespace Internal { diff --git a/src/plugins/projectexplorer/customtoolchain.h b/src/plugins/projectexplorer/customtoolchain.h index 75ba190c66f..b0554f0d068 100644 --- a/src/plugins/projectexplorer/customtoolchain.h +++ b/src/plugins/projectexplorer/customtoolchain.h @@ -90,7 +90,7 @@ public: QVariantMap toMap() const override; bool fromMap(const QVariantMap &data) override; - ToolChainConfigWidget *configurationWidget() override; + std::unique_ptr createConfigurationWidget() override; bool operator ==(const ToolChain &) const override; diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index 27413c22ea5..101594befe8 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -861,9 +861,9 @@ bool GccToolChain::operator ==(const ToolChain &other) const && m_platformLinkerFlags == gccTc->m_platformLinkerFlags; } -ToolChainConfigWidget *GccToolChain::configurationWidget() +std::unique_ptr GccToolChain::createConfigurationWidget() { - return new GccToolChainConfigWidget(this); + return std::make_unique(this); } void GccToolChain::updateSupportedAbis() const diff --git a/src/plugins/projectexplorer/gcctoolchain.h b/src/plugins/projectexplorer/gcctoolchain.h index 2a0ca0e17d5..7cc6d60e6f1 100644 --- a/src/plugins/projectexplorer/gcctoolchain.h +++ b/src/plugins/projectexplorer/gcctoolchain.h @@ -158,7 +158,7 @@ public: QVariantMap toMap() const override; bool fromMap(const QVariantMap &data) override; - ToolChainConfigWidget *configurationWidget() override; + std::unique_ptr createConfigurationWidget() override; bool operator ==(const ToolChain &) const override; diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp index 9a68a596899..220d8509dc4 100644 --- a/src/plugins/projectexplorer/msvctoolchain.cpp +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -764,9 +764,9 @@ bool MsvcToolChain::fromMap(const QVariantMap &data) } -ToolChainConfigWidget *MsvcToolChain::configurationWidget() +std::unique_ptr MsvcToolChain::createConfigurationWidget() { - return new MsvcToolChainConfigWidget(this); + return std::make_unique(this); } ToolChain *MsvcToolChain::clone() const @@ -1048,9 +1048,9 @@ bool ClangClToolChain::fromMap(const QVariantMap &data) return true; } -ToolChainConfigWidget *ClangClToolChain::configurationWidget() +std::unique_ptr ClangClToolChain::createConfigurationWidget() { - return new ClangClToolChainConfigWidget(this); + return std::make_unique(this); } void ClangClToolChain::resetMsvcToolChain(const MsvcToolChain *base) diff --git a/src/plugins/projectexplorer/msvctoolchain.h b/src/plugins/projectexplorer/msvctoolchain.h index 8510cece09b..88ba1523cdd 100644 --- a/src/plugins/projectexplorer/msvctoolchain.h +++ b/src/plugins/projectexplorer/msvctoolchain.h @@ -73,7 +73,7 @@ public: QVariantMap toMap() const override; bool fromMap(const QVariantMap &data) override; - ToolChainConfigWidget *configurationWidget() override; + std::unique_ptr createConfigurationWidget() override; ToolChain *clone() const override; @@ -127,7 +127,7 @@ public: ToolChain *clone() const override; QVariantMap toMap() const override; bool fromMap(const QVariantMap &data) override; - ToolChainConfigWidget *configurationWidget() override; + std::unique_ptr createConfigurationWidget() override; const QList &msvcToolchains() const; QString clangPath() const { return m_clangPath; } diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h index 0f463bf8010..7b41968d063 100644 --- a/src/plugins/projectexplorer/toolchain.h +++ b/src/plugins/projectexplorer/toolchain.h @@ -146,7 +146,7 @@ public: virtual bool operator ==(const ToolChain &) const; - virtual ToolChainConfigWidget *configurationWidget() = 0; + virtual std::unique_ptr createConfigurationWidget() = 0; virtual bool canClone() const; virtual ToolChain *clone() const = 0; diff --git a/src/plugins/projectexplorer/toolchainoptionspage.cpp b/src/plugins/projectexplorer/toolchainoptionspage.cpp index 562c7c6d62b..eff7f3a408e 100644 --- a/src/plugins/projectexplorer/toolchainoptionspage.cpp +++ b/src/plugins/projectexplorer/toolchainoptionspage.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -60,11 +61,12 @@ namespace Internal { class ToolChainTreeItem : public TreeItem { public: - ToolChainTreeItem(ToolChain *tc, bool c) : + ToolChainTreeItem(QStackedWidget *parentWidget, ToolChain *tc, bool c) : toolChain(tc), changed(c) { - widget = tc->configurationWidget(); + widget = tc->createConfigurationWidget().release(); if (widget) { + parentWidget->addWidget(widget); if (tc->isAutoDetected()) widget->makeReadOnly(); QObject::connect(widget, &ToolChainConfigWidget::dirty, @@ -132,9 +134,6 @@ public: m_model.rootItem()->appendChild(autoRoot); m_model.rootItem()->appendChild(manualRoot); - foreach (ToolChain *tc, ToolChainManager::toolChains()) - insertToolChain(tc); - m_toolChainView = new QTreeView(this); m_toolChainView->setUniformRowHeights(true); m_toolChainView->setSelectionMode(QAbstractItemView::SingleSelection); @@ -174,6 +173,12 @@ public: m_container->setState(DetailsWidget::NoSummary); m_container->setVisible(false); + m_widgetStack = new QStackedWidget; + m_container->setWidget(m_widgetStack); + + foreach (ToolChain *tc, ToolChainManager::toolChains()) + insertToolChain(tc); + auto buttonLayout = new QVBoxLayout; buttonLayout->setSpacing(6); buttonLayout->setContentsMargins(0, 0, 0, 0); @@ -234,6 +239,7 @@ public: QList m_factories; QTreeView *m_toolChainView; DetailsWidget *m_container; + QStackedWidget *m_widgetStack; QPushButton *m_addButton; QPushButton *m_cloneButton; QPushButton *m_delButton; @@ -260,8 +266,9 @@ void ToolChainOptionsWidget::markForRemoval(ToolChainTreeItem *item) ToolChainTreeItem *ToolChainOptionsWidget::insertToolChain(ToolChain *tc, bool changed) { StaticTreeItem *parent = parentForToolChain(tc); - auto item = new ToolChainTreeItem(tc, changed); + auto item = new ToolChainTreeItem(m_widgetStack, tc, changed); parent->appendChild(item); + return item; } @@ -308,13 +315,10 @@ StaticTreeItem *ToolChainOptionsWidget::parentForToolChain(ToolChain *tc) void ToolChainOptionsWidget::toolChainSelectionChanged() { ToolChainTreeItem *item = currentTreeItem(); - QWidget *oldWidget = m_container->takeWidget(); // Prevent deletion. - if (oldWidget) - oldWidget->setVisible(false); QWidget *currentTcWidget = item ? item->widget : nullptr; - m_container->setWidget(currentTcWidget); + m_widgetStack->setCurrentWidget(currentTcWidget); m_container->setVisible(currentTcWidget); updateState(); } diff --git a/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp b/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp index 39b465bea48..3d4329ffb44 100644 --- a/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp +++ b/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp @@ -281,6 +281,7 @@ QList ToolChainSettingsAccessor::toolChains(const QVariantMap &data #include "headerpath.h" #include "abi.h" +#include "toolchainconfigwidget.h" #include #include @@ -318,7 +319,7 @@ public: QString makeCommand(const Environment &env) const override { Q_UNUSED(env); return QString("make"); } FileName compilerCommand() const override { return Utils::FileName::fromString("/tmp/test/gcc"); } IOutputParser *outputParser() const override { return nullptr; } - ToolChainConfigWidget *configurationWidget() override { return nullptr; } + std::unique_ptr createConfigurationWidget() override { return nullptr; } TTC *clone() const override { return new TTC(*this); } bool operator ==(const ToolChain &other) const override { if (!ToolChain::operator==(other)) diff --git a/src/plugins/qnx/qnxtoolchain.cpp b/src/plugins/qnx/qnxtoolchain.cpp index 219c089e670..63c9c3dc568 100644 --- a/src/plugins/qnx/qnxtoolchain.cpp +++ b/src/plugins/qnx/qnxtoolchain.cpp @@ -118,9 +118,9 @@ QString QnxToolChain::typeDisplayName() const return QnxToolChainFactory::tr("QCC"); } -ToolChainConfigWidget *QnxToolChain::configurationWidget() +std::unique_ptr QnxToolChain::createConfigurationWidget() { - return new QnxToolChainConfigWidget(this); + return std::make_unique(this); } void QnxToolChain::addToEnvironment(Environment &env) const diff --git a/src/plugins/qnx/qnxtoolchain.h b/src/plugins/qnx/qnxtoolchain.h index 1d930a80d3d..8fe11673fda 100644 --- a/src/plugins/qnx/qnxtoolchain.h +++ b/src/plugins/qnx/qnxtoolchain.h @@ -39,7 +39,7 @@ public: QString typeDisplayName() const override; - ProjectExplorer::ToolChainConfigWidget *configurationWidget() override; + std::unique_ptr createConfigurationWidget() override; void addToEnvironment(Utils::Environment &env) const override; Utils::FileNameList suggestedMkspecList() const override;