Core: Fix memory leak in InfoBarEntry

Use like

    InfoBarEntry info(id, text);
    info.setShowDefaultCancelButton(false);

leaked the infoWidgetCloseButton.

Fix the memory leak and improve the API to avoid inconsistent state.

Change-Id: If2e06a8a5239e4f902a883da82122c3a27df48a6
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Nikolai Kosjar
2017-01-17 17:43:44 +01:00
parent e2e78c6a5d
commit b250c073b5
3 changed files with 22 additions and 15 deletions

View File

@@ -59,18 +59,22 @@ void InfoBarEntry::setCustomButtonInfo(const QString &_buttonText, CallBack call
void InfoBarEntry::setCancelButtonInfo(CallBack callBack) void InfoBarEntry::setCancelButtonInfo(CallBack callBack)
{ {
m_useCancelButton = true;
m_cancelButtonCallBack = callBack; m_cancelButtonCallBack = callBack;
} }
void InfoBarEntry::setCancelButtonInfo(const QString &_cancelButtonText, CallBack callBack) void InfoBarEntry::setCancelButtonInfo(const QString &_cancelButtonText, CallBack callBack)
{ {
m_useCancelButton = true;
cancelButtonText = _cancelButtonText; cancelButtonText = _cancelButtonText;
m_cancelButtonCallBack = callBack; m_cancelButtonCallBack = callBack;
} }
void InfoBarEntry::setShowDefaultCancelButton(bool yesno) void InfoBarEntry::removeCancelButton()
{ {
m_showDefaultCancelButton = yesno; m_useCancelButton = false;
cancelButtonText.clear();
m_cancelButtonCallBack = nullptr;
} }
void InfoBarEntry::setDetailsWidgetCreator(const InfoBarEntry::DetailsWidgetCreator &creator) void InfoBarEntry::setDetailsWidgetCreator(const InfoBarEntry::DetailsWidgetCreator &creator)
@@ -283,17 +287,20 @@ void InfoBarDisplay::update()
}); });
} }
QToolButton *infoWidgetCloseButton = new QToolButton; QToolButton *infoWidgetCloseButton = nullptr;
// need to connect to cancelObjectbefore connecting to cancelButtonClicked, if (info.m_useCancelButton) {
// because the latter removes the button and with it any connect infoWidgetCloseButton = new QToolButton;
if (info.m_cancelButtonCallBack) // need to connect to cancelObjectbefore connecting to cancelButtonClicked,
connect(infoWidgetCloseButton, &QAbstractButton::clicked, info.m_cancelButtonCallBack); // because the latter removes the button and with it any connect
connect(infoWidgetCloseButton, &QAbstractButton::clicked, this, [this, id] { if (info.m_cancelButtonCallBack)
m_infoBar->suppressInfo(id); connect(infoWidgetCloseButton, &QAbstractButton::clicked, info.m_cancelButtonCallBack);
}); connect(infoWidgetCloseButton, &QAbstractButton::clicked, this, [this, id] {
m_infoBar->suppressInfo(id);
});
}
if (info.cancelButtonText.isEmpty()) { if (info.cancelButtonText.isEmpty()) {
if (info.m_showDefaultCancelButton) { if (infoWidgetCloseButton) {
infoWidgetCloseButton->setAutoRaise(true); infoWidgetCloseButton->setAutoRaise(true);
infoWidgetCloseButton->setIcon(Utils::Icons::CLOSE_FOREGROUND.icon()); infoWidgetCloseButton->setIcon(Utils::Icons::CLOSE_FOREGROUND.icon());
infoWidgetCloseButton->setToolTip(tr("Close")); infoWidgetCloseButton->setToolTip(tr("Close"));
@@ -302,7 +309,7 @@ void InfoBarDisplay::update()
if (infoWidgetSuppressButton) if (infoWidgetSuppressButton)
hbox->addWidget(infoWidgetSuppressButton); hbox->addWidget(infoWidgetSuppressButton);
if (info.m_showDefaultCancelButton) if (infoWidgetCloseButton)
hbox->addWidget(infoWidgetCloseButton); hbox->addWidget(infoWidgetCloseButton);
} else { } else {
infoWidgetCloseButton->setText(info.cancelButtonText); infoWidgetCloseButton->setText(info.cancelButtonText);

View File

@@ -58,7 +58,7 @@ public:
void setCustomButtonInfo(const QString &_buttonText, CallBack callBack); void setCustomButtonInfo(const QString &_buttonText, CallBack callBack);
void setCancelButtonInfo(CallBack callBack); void setCancelButtonInfo(CallBack callBack);
void setCancelButtonInfo(const QString &_cancelButtonText, CallBack callBack); void setCancelButtonInfo(const QString &_cancelButtonText, CallBack callBack);
void setShowDefaultCancelButton(bool yesno); void removeCancelButton();
using DetailsWidgetCreator = std::function<QWidget*()>; using DetailsWidgetCreator = std::function<QWidget*()>;
void setDetailsWidgetCreator(const DetailsWidgetCreator &creator); void setDetailsWidgetCreator(const DetailsWidgetCreator &creator);
@@ -72,7 +72,7 @@ private:
CallBack m_cancelButtonCallBack; CallBack m_cancelButtonCallBack;
GlobalSuppressionMode globalSuppression; GlobalSuppressionMode globalSuppression;
DetailsWidgetCreator m_detailsWidgetCreator; DetailsWidgetCreator m_detailsWidgetCreator;
bool m_showDefaultCancelButton = true; bool m_useCancelButton = true;
friend class InfoBar; friend class InfoBar;
friend class InfoBarDisplay; friend class InfoBarDisplay;
}; };

View File

@@ -140,7 +140,7 @@ static InfoBarEntry createMinimizableInfo(const Id &id,
QTC_CHECK(minimizer); QTC_CHECK(minimizer);
InfoBarEntry info(id, text); InfoBarEntry info(id, text);
info.setShowDefaultCancelButton(false); info.removeCancelButton();
// The minimizer() might delete the "Minimize" button immediately and as // The minimizer() might delete the "Minimize" button immediately and as
// result invalid reads will happen in QToolButton::mouseReleaseEvent(). // result invalid reads will happen in QToolButton::mouseReleaseEvent().
// Avoid this by running the minimizer in the next event loop iteration. // Avoid this by running the minimizer in the next event loop iteration.