[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [kdevplatform] /: Fix crashy dialogs (found by krazy and by hand)
From: Christoph Roick <null () kde ! org>
Date: 2017-06-30 21:58:42
Message-ID: E1dR3w2-0003Fw-Ek () code ! kde ! org
[Download RAW message or body]
Git commit 7cda7c95d5bfa93f34c5a52df17480c248a8367c by Christoph Roick.
Committed on 30/06/2017 at 21:57.
Pushed by croick into branch 'master'.
Fix crashy dialogs (found by krazy and by hand)
Summary:
- use a wrapper class which simplifies the use of QPointer
for the creation of local QDialogs
- some false positives are marked
- some dialogs not identified by krazy have the main window
as parent, they may still cause a crash, when the program is killed
Test Plan:
Before:
- open "About KDevelop Platform" dialog
- "killall kdevelop" -> kdevelop closes (as intended), but with crash
After:
- open same dialog
- "killall kdevelop" -> kdevelop silently quits
Reviewers: #kdevelop, apol
Reviewed By: #kdevelop, apol
Subscribers: apol, anthonyfieroni, kdevelop-devel
Differential Revision: https://phabricator.kde.org/D6308
M +1 -2 language/codegen/basicrefactoring.cpp
M +5 -4 plugins/appwizard/appwizardplugin.cpp
M +11 -8 plugins/appwizard/projectselectionpage.cpp
M +6 -6 plugins/externalscript/externalscriptview.cpp
M +4 -4 plugins/filetemplates/templateclassassistant.cpp
M +6 -5 plugins/filetemplates/templateselectionpage.cpp
M +1 -1 plugins/git/gitplugin.cpp
M +2 -2 plugins/subversion/kdevsvnplugin.cpp
M +6 -5 plugins/subversion/svnjobbase.cpp
M +3 -3 shell/documentcontroller.cpp
M +15 -13 shell/environmentconfigurebutton.cpp
M +4 -2 shell/loadedpluginsdialog.cpp
M +5 -4 shell/mainwindow_actions.cpp
M +21 -17 shell/projectcontroller.cpp
M +1 -1 shell/sessioncontroller.cpp
M +16 -14 shell/settings/environmentwidget.cpp
M +4 -3 shell/settings/sourceformattersettings.cpp
M +15 -11 shell/settings/templatepage.cpp
M +2 -2 shell/uicontroller.cpp
A +86 -0 util/scopeddialog.h [License: GPL (v2+)]
M +4 -3 vcs/dvcs/dvcsplugin.cpp
M +2 -1 vcs/vcspluginhelper.cpp
https://commits.kde.org/kdevplatform/7cda7c95d5bfa93f34c5a52df17480c248a8367c
diff --git a/language/codegen/basicrefactoring.cpp \
b/language/codegen/basicrefactoring.cpp index f666b2444..68dc459e3 100644
--- a/language/codegen/basicrefactoring.cpp
+++ b/language/codegen/basicrefactoring.cpp
@@ -309,8 +309,7 @@ BasicRefactoring::NameAndCollector \
BasicRefactoring::newNameForDeclaration(const const auto text = \
renameDialog.edit->text().trimmed();
RefactoringProgressDialog refactoringProgress(i18n("Renaming \"%1\" to \"%2\"", \
declarationName, text), collector.data()); if (!collector->isReady()) {
- refactoringProgress.exec();
- if (refactoringProgress.result() != QDialog::Accepted) {
+ if (refactoringProgress.exec() != QDialog::Accepted) { // \
krazy:exclude=crashy return {};
}
}
diff --git a/plugins/appwizard/appwizardplugin.cpp \
b/plugins/appwizard/appwizardplugin.cpp index f0e6eb107..50a5f82ce 100644
--- a/plugins/appwizard/appwizardplugin.cpp
+++ b/plugins/appwizard/appwizardplugin.cpp
@@ -46,6 +46,7 @@
#include <interfaces/idocumentcontroller.h>
#include <interfaces/context.h>
#include <interfaces/contextmenuextension.h>
+#include <util/scopeddialog.h>
#include <vcs/vcsjob.h>
#include <vcs/interfaces/icentralizedversioncontrol.h>
#include <vcs/interfaces/idistributedversioncontrol.h>
@@ -84,16 +85,16 @@ void AppWizardPlugin::slotNewProject()
{
model()->refresh();
- AppWizardDialog dlg(core()->pluginController(), m_templatesModel);
+ ScopedDialog<AppWizardDialog> dlg(core()->pluginController(), m_templatesModel);
- if (dlg.exec() == QDialog::Accepted)
+ if (dlg->exec() == QDialog::Accepted)
{
- QString project = createProject( dlg.appInfo() );
+ QString project = createProject( dlg->appInfo() );
if (!project.isEmpty())
{
core()->projectController()->openProject(QUrl::fromLocalFile(project));
- KConfig templateConfig(dlg.appInfo().appTemplate);
+ KConfig templateConfig(dlg->appInfo().appTemplate);
KConfigGroup general(&templateConfig, "General");
const QStringList fileArgs = \
general.readEntry("ShowFilesAfterGeneration").split(QLatin1Char(','), \
QString::SkipEmptyParts); for (const auto& fileArg : fileArgs) {
diff --git a/plugins/appwizard/projectselectionpage.cpp \
b/plugins/appwizard/projectselectionpage.cpp index d7862e0ee..d4ec5e7cd 100644
--- a/plugins/appwizard/projectselectionpage.cpp
+++ b/plugins/appwizard/projectselectionpage.cpp
@@ -26,6 +26,7 @@
#include <language/codegen/templatepreviewicon.h>
#include <util/multilevellistview.h>
+#include <util/scopeddialog.h>
#include "ui_projectselectionpage.h"
#include "projecttemplatesmodel.h"
@@ -305,15 +306,15 @@ void ProjectSelectionPage::loadFileClicked()
QStringLiteral("application/x-bzip-compressed-tar"),
QStringLiteral("application/zip")
};
- QFileDialog fileDialog(this, i18n("Load Template From File"));
- fileDialog.setMimeTypeFilters(supportedMimeTypes);
- fileDialog.setFileMode(QFileDialog::ExistingFiles);
+ ScopedDialog<QFileDialog> fileDialog(this, i18n("Load Template From File"));
+ fileDialog->setMimeTypeFilters(supportedMimeTypes);
+ fileDialog->setFileMode(QFileDialog::ExistingFiles);
- if (!fileDialog.exec()) {
+ if (!fileDialog->exec()) {
return;
}
- for (const auto& fileName : fileDialog.selectedFiles()) {
+ for (const auto& fileName : fileDialog->selectedFiles()) {
QString destination = m_templatesModel->loadTemplateFile(fileName);
QModelIndexList indexes = m_templatesModel->templateIndexes(destination);
if (indexes.size() > 2)
@@ -326,10 +327,12 @@ void ProjectSelectionPage::loadFileClicked()
void ProjectSelectionPage::moreTemplatesClicked()
{
- KNS3::DownloadDialog dialog(QStringLiteral("kdevappwizard.knsrc"), this);
- dialog.exec();
+ ScopedDialog<KNS3::DownloadDialog> dialog(QStringLiteral("kdevappwizard.knsrc"), \
this);
- auto entries = dialog.changedEntries();
+ if (!dialog->exec())
+ return;
+
+ auto entries = dialog->changedEntries();
if (entries.isEmpty()) {
return;
}
diff --git a/plugins/externalscript/externalscriptview.cpp \
b/plugins/externalscript/externalscriptview.cpp index 22b78bf7e..ad34c4966 100644
--- a/plugins/externalscript/externalscriptview.cpp
+++ b/plugins/externalscript/externalscriptview.cpp
@@ -32,6 +32,8 @@
#include <KLocalizedString>
#include <KMessageBox>
+#include <util/scopeddialog.h>
+
ExternalScriptView::ExternalScriptView( ExternalScriptPlugin* plugin, QWidget* \
parent ) : QWidget( parent ), m_plugin( plugin )
@@ -135,9 +137,8 @@ bool ExternalScriptView::eventFilter( QObject* obj, QEvent* e )
void ExternalScriptView::addScript()
{
ExternalScriptItem* item = new ExternalScriptItem;
- EditExternalScript dlg( item, this );
- int ret = dlg.exec();
- if ( ret == QDialog::Accepted) {
+ KDevelop::ScopedDialog<EditExternalScript> dlg( item, this );
+ if ( dlg->exec() == QDialog::Accepted) {
m_plugin->model()->appendRow( item );
} else {
delete item;
@@ -170,9 +171,8 @@ void ExternalScriptView::editScript()
return;
}
- EditExternalScript dlg( item, this );
- int ret = dlg.exec();
- if (ret == QDialog::Accepted) {
+ KDevelop::ScopedDialog<EditExternalScript> dlg( item, this );
+ if (dlg->exec() == QDialog::Accepted) {
item->save();
}
}
diff --git a/plugins/filetemplates/templateclassassistant.cpp \
b/plugins/filetemplates/templateclassassistant.cpp index b9cf29005..da4237b5e 100644
--- a/plugins/filetemplates/templateclassassistant.cpp
+++ b/plugins/filetemplates/templateclassassistant.cpp
@@ -45,12 +45,12 @@
#include <project/projectmodel.h>
#include <project/interfaces/iprojectfilemanager.h>
#include <project/interfaces/ibuildsystemmanager.h>
+#include <util/scopeddialog.h>
#include <QDialog>
#include <QDialogButtonBox>
#include <QLabel>
#include <QListWidget>
-#include <QPointer>
#include <QPushButton>
#include <QVBoxLayout>
@@ -198,7 +198,7 @@ void TemplateClassAssistantPrivate::addFilesToTarget (const \
QHash< QString, QUrl else if (targets.size() > 1)
{
// More than one candidate target, show the chooser dialog
- QPointer<QDialog> d = new QDialog;
+ ScopedDialog<QDialog> d;
auto mainLayout = new QVBoxLayout(d);
mainLayout->addWidget(new QLabel(i18n("Choose one target to add the file or \
cancel if you do not want to do so."))); @@ -215,8 +215,8 @@ void \
TemplateClassAssistantPrivate::addFilesToTarget (const QHash< QString, QUrl \
QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); \
okButton->setDefault(true); okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
- d->connect(buttonBox, &QDialogButtonBox::accepted, d.data(), \
&QDialog::accept);
- d->connect(buttonBox, &QDialogButtonBox::rejected, d.data(), \
&QDialog::reject); + d->connect(buttonBox, &QDialogButtonBox::accepted, d, \
&QDialog::accept); + d->connect(buttonBox, &QDialogButtonBox::rejected, d, \
&QDialog::reject); mainLayout->addWidget(buttonBox);
if(d->exec() == QDialog::Accepted)
diff --git a/plugins/filetemplates/templateselectionpage.cpp \
b/plugins/filetemplates/templateselectionpage.cpp index 7f731c4cd..ae728ed36 100644
--- a/plugins/filetemplates/templateselectionpage.cpp
+++ b/plugins/filetemplates/templateselectionpage.cpp
@@ -32,6 +32,7 @@
#include <interfaces/iproject.h>
#include <interfaces/iprojectcontroller.h>
#include <interfaces/isession.h>
+#include <util/scopeddialog.h>
#include "ui_templateselection.h"
@@ -159,16 +160,16 @@ void TemplateSelectionPagePrivate::loadFileClicked()
QStringLiteral("application/x-bzip-compressed-tar"),
QStringLiteral("application/zip")
};
- QFileDialog dlg(page);
- dlg.setMimeTypeFilters(filters);
- dlg.setFileMode(QFileDialog::ExistingFiles);
+ ScopedDialog<QFileDialog> dlg(page);
+ dlg->setMimeTypeFilters(filters);
+ dlg->setFileMode(QFileDialog::ExistingFiles);
- if (!dlg.exec())
+ if (!dlg->exec())
{
return;
}
- foreach(const QString& fileName, dlg.selectedFiles())
+ foreach(const QString& fileName, dlg->selectedFiles())
{
QString destination = model->loadTemplateFile(fileName);
QModelIndexList indexes = model->templateIndexes(destination);
diff --git a/plugins/git/gitplugin.cpp b/plugins/git/gitplugin.cpp
index bc926bf51..f403d1ab9 100644
--- a/plugins/git/gitplugin.cpp
+++ b/plugins/git/gitplugin.cpp
@@ -516,7 +516,7 @@ void GitPlugin::addNotVersionedFiles(const QDir& dir, const \
QList<QUrl>& files)
if(!toadd.isEmpty()) {
VcsJob* job = add(toadd);
- job->exec();
+ job->exec(); // krazy:exclude=crashy
}
}
diff --git a/plugins/subversion/kdevsvnplugin.cpp \
b/plugins/subversion/kdevsvnplugin.cpp index e2016856d..d39674f39 100644
--- a/plugins/subversion/kdevsvnplugin.cpp
+++ b/plugins/subversion/kdevsvnplugin.cpp
@@ -404,7 +404,7 @@ void KDevSvnPlugin::ctxCopy()
dlg.urlRequester()->setMode(KFile::Directory | KFile::LocalOnly);
}
- if (dlg.exec() == QDialog::Accepted) {
+ if (dlg.exec() == QDialog::Accepted) { // krazy:exclude=crashy
KDevelop::ICore::self()->runController()->registerJob(copy(source, \
dlg.selectedUrl())); }
} else {
@@ -440,7 +440,7 @@ void KDevSvnPlugin::ctxMove()
dlg.urlRequester()->setMode(KFile::Directory | KFile::LocalOnly);
}
- if (dlg.exec() == QDialog::Accepted) {
+ if (dlg.exec() == QDialog::Accepted) { // krazy:exclude=crashy
KDevelop::ICore::self()->runController()->registerJob(move(source, \
dlg.selectedUrl())); }
} else {
diff --git a/plugins/subversion/svnjobbase.cpp b/plugins/subversion/svnjobbase.cpp
index c04df5e6f..0b7e4eeea 100644
--- a/plugins/subversion/svnjobbase.cpp
+++ b/plugins/subversion/svnjobbase.cpp
@@ -68,11 +68,12 @@ void SvnJobBase::askForLogin( const QString& realm )
qCDebug(PLUGIN_SVN) << "login";
KPasswordDialog dlg( nullptr, KPasswordDialog::ShowUsernameLine | \
KPasswordDialog::ShowKeepPassword ); dlg.setPrompt( i18n("Enter Login for: %1", \
realm ) );
- dlg.exec();
- internalJob()->m_login_username = dlg.username();
- internalJob()->m_login_password = dlg.password();
- internalJob()->m_maySave = dlg.keepPassword();
- internalJob()->m_guiSemaphore.release( 1 );
+ if (dlg.exec()) { // krazy:exclude=crashy
+ internalJob()->m_login_username = dlg.username();
+ internalJob()->m_login_password = dlg.password();
+ internalJob()->m_maySave = dlg.keepPassword();
+ internalJob()->m_guiSemaphore.release( 1 );
+ }
}
void SvnJobBase::showNotification( const QString& path, const QString& msg )
diff --git a/shell/documentcontroller.cpp b/shell/documentcontroller.cpp
index e4d656fde..724a51499 100644
--- a/shell/documentcontroller.cpp
+++ b/shell/documentcontroller.cpp
@@ -54,6 +54,7 @@ Boston, MA 02110-1301, USA.
#include <interfaces/iselectioncontroller.h>
#include <interfaces/context.h>
#include <project/projectmodel.h>
+#include <util/scopeddialog.h>
#include <util/path.h>
#include "core.h"
@@ -813,9 +814,8 @@ bool KDevelop::DocumentController::saveSomeDocuments(const QList< \
IDocument * > QList<IDocument*> checkSave = modifiedDocuments(list);
if (!checkSave.isEmpty()) {
- KSaveSelectDialog dialog(checkSave, qApp->activeWindow());
- if (dialog.exec() == QDialog::Rejected)
- return false;
+ ScopedDialog<KSaveSelectDialog> dialog(checkSave, qApp->activeWindow());
+ return dialog->exec();
}
}
diff --git a/shell/environmentconfigurebutton.cpp \
b/shell/environmentconfigurebutton.cpp index f48287421..f7f7221d9 100644
--- a/shell/environmentconfigurebutton.cpp
+++ b/shell/environmentconfigurebutton.cpp
@@ -29,6 +29,8 @@
#include <QIcon>
#include <QVBoxLayout>
+#include <util/scopeddialog.h>
+
#include <KLocalizedString>
namespace KDevelop {
@@ -43,31 +45,31 @@ public:
void showDialog()
{
- QDialog dlg(qApp->activeWindow());
+ ScopedDialog<QDialog> dlg(qApp->activeWindow());
QString selected;
if (selectionWidget) {
selected = selectionWidget->effectiveProfileName();
}
- EnvironmentPreferences prefs(selected, q);
+ auto prefs = new EnvironmentPreferences(selected, q);
// TODO: This should be implicit when constructing EnvironmentPreferences
- prefs.initConfigManager();
- prefs.reset();
+ prefs->initConfigManager();
+ prefs->reset();
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok
| QDialogButtonBox::Cancel);
- QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dlg, \
&QDialog::accept);
- QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dlg, \
&QDialog::reject); + QObject::connect(buttonBox, &QDialogButtonBox::accepted, \
dlg, &QDialog::accept); + QObject::connect(buttonBox, \
&QDialogButtonBox::rejected, dlg, &QDialog::reject); auto layout = new QVBoxLayout;
- layout->addWidget(&prefs);
+ layout->addWidget(prefs);
layout->addWidget(buttonBox);
- dlg.setLayout(layout);
- dlg.setWindowTitle(prefs.fullName());
- dlg.setWindowIcon(prefs.icon());
- dlg.resize(800, 600);
- if (dlg.exec() == QDialog::Accepted) {
- prefs.apply();
+ dlg->setLayout(layout);
+ dlg->setWindowTitle(prefs->fullName());
+ dlg->setWindowIcon(prefs->icon());
+ dlg->resize(800, 600);
+ if (dlg->exec() == QDialog::Accepted) {
+ prefs->apply();
emit q->environmentConfigured();
}
}
diff --git a/shell/loadedpluginsdialog.cpp b/shell/loadedpluginsdialog.cpp
index ed13541e4..3b5916c8a 100644
--- a/shell/loadedpluginsdialog.cpp
+++ b/shell/loadedpluginsdialog.cpp
@@ -34,6 +34,8 @@
#include <KTitleWidget>
#include <KWidgetItemDelegate>
+#include <util/scopeddialog.h>
+
#include "core.h"
#include "plugincontroller.h"
@@ -240,8 +242,8 @@ private Q_SLOTS:
if (p) {
KAboutData aboutData = KAboutData::fromPluginMetaData(pluginInfo(p));
if (!aboutData.componentName().isEmpty()) { // Be sure the about data is \
not completely empty
- KAboutApplicationDialog aboutPlugin(aboutData, itemView());
- aboutPlugin.exec();
+ KDevelop::ScopedDialog<KAboutApplicationDialog> \
aboutPlugin(aboutData, itemView()); + aboutPlugin->exec();
return;
}
}
diff --git a/shell/mainwindow_actions.cpp b/shell/mainwindow_actions.cpp
index 7bc17b29e..8b75f7417 100644
--- a/shell/mainwindow_actions.cpp
+++ b/shell/mainwindow_actions.cpp
@@ -40,6 +40,7 @@ Boston, MA 02110-1301, USA.
#include "loadedpluginsdialog.h"
#include <interfaces/itoolviewactionlistener.h>
+#include <util/scopeddialog.h>
namespace KDevelop {
@@ -206,14 +207,14 @@ void MainWindowPrivate::configureNotifications()
void MainWindowPrivate::showAboutPlatform()
{
- KAboutApplicationDialog dlg(Core::self()->aboutData(), m_mainWindow );
- dlg.exec();
+ ScopedDialog<KAboutApplicationDialog> dlg(Core::self()->aboutData(), \
m_mainWindow ); + dlg->exec();
}
void MainWindowPrivate::showLoadedPlugins()
{
- LoadedPluginsDialog dlg(m_mainWindow);
- dlg.exec();
+ ScopedDialog<LoadedPluginsDialog> dlg(m_mainWindow);
+ dlg->exec();
}
void MainWindowPrivate::contextMenuFileNew()
diff --git a/shell/projectcontroller.cpp b/shell/projectcontroller.cpp
index c0927d348..7e94e02bf 100644
--- a/shell/projectcontroller.cpp
+++ b/shell/projectcontroller.cpp
@@ -29,6 +29,7 @@ Boston, MA 02110-1301, USA.
#include <QLabel>
#include <QList>
#include <QMap>
+#include <QPointer>
#include <QPushButton>
#include <QRadioButton>
#include <QSet>
@@ -63,6 +64,7 @@ Boston, MA 02110-1301, USA.
#include <projectconfigpage.h>
#include <language/backgroundparser/parseprojectjob.h>
#include <interfaces/iruncontroller.h>
+#include <util/scopeddialog.h>
#include <vcs/widgets/vcsdiffpatchsources.h>
#include <vcs/widgets/vcscommitdialog.h>
@@ -419,13 +421,15 @@ QUrl ProjectDialogProvider::askProjectConfigLocation(bool \
fetch, const QUrl& sta
const QUrl& repoUrl, IPlugin* \
vcsOrProviderPlugin) {
Q_ASSERT(d);
- OpenProjectDialog dlg(fetch, startUrl, repoUrl, vcsOrProviderPlugin, \
Core::self()->uiController()->activeMainWindow());
- if(dlg.exec() == QDialog::Rejected)
+ ScopedDialog<OpenProjectDialog> dlg(fetch, startUrl, repoUrl, \
vcsOrProviderPlugin, + \
Core::self()->uiController()->activeMainWindow()); + if(dlg->exec() == \
QDialog::Rejected) { return QUrl();
+ }
- QUrl projectFileUrl = dlg.projectFileUrl();
- qCDebug(SHELL) << "selected project:" << projectFileUrl << dlg.projectName() << \
dlg.projectManager();
- if ( dlg.projectManager() == QLatin1String("<built-in>") ) {
+ QUrl projectFileUrl = dlg->projectFileUrl();
+ qCDebug(SHELL) << "selected project:" << projectFileUrl << dlg->projectName() << \
dlg->projectManager(); + if ( dlg->projectManager() == QLatin1String("<built-in>") \
) { return projectFileUrl;
}
@@ -435,11 +439,11 @@ QUrl ProjectDialogProvider::askProjectConfigLocation(bool \
fetch, const QUrl& sta {
// check whether config is equal
bool shouldAsk = true;
- if( projectFileUrl == dlg.selectedUrl() )
+ if( projectFileUrl == dlg->selectedUrl() )
{
if( projectFileUrl.isLocalFile() )
{
- shouldAsk = !equalProjectFile( projectFileUrl.toLocalFile(), &dlg );
+ shouldAsk = !equalProjectFile( projectFileUrl.toLocalFile(), dlg );
} else {
shouldAsk = false;
@@ -448,7 +452,7 @@ QUrl ProjectDialogProvider::askProjectConfigLocation(bool fetch, \
const QUrl& sta
auto downloadJob = KIO::file_copy(projectFileUrl, \
QUrl::fromLocalFile(tmpFile.fileName()));
KJobWidgets::setWindow(downloadJob, qApp->activeWindow());
if (downloadJob->exec()) {
- shouldAsk = !equalProjectFile(tmpFile.fileName(), &dlg);
+ shouldAsk = !equalProjectFile(tmpFile.fileName(), dlg);
}
}
}
@@ -483,12 +487,13 @@ QUrl ProjectDialogProvider::askProjectConfigLocation(bool \
fetch, const QUrl& sta }
if (writeProjectConfigToFile) {
- if (!writeProjectSettingsToConfigFile(projectFileUrl, &dlg)) {
+ if (!writeProjectSettingsToConfigFile(projectFileUrl, dlg)) {
KMessageBox::error(d->m_core->uiControllerInternal()->defaultMainWindow(),
i18n("Unable to create configuration file %1", \
projectFileUrl.url())); return QUrl();
}
}
+
return projectFileUrl;
}
@@ -785,10 +790,10 @@ void ProjectController::openProject( const QUrl &projectFile )
}
if ( ! existingSessions.isEmpty() ) {
- QDialog dialog(Core::self()->uiControllerInternal()->activeMainWindow());
- dialog.setWindowTitle(i18n("Project Already Open"));
+ ScopedDialog<QDialog> \
dialog(Core::self()->uiControllerInternal()->activeMainWindow()); + \
dialog->setWindowTitle(i18n("Project Already Open"));
- auto mainLayout = new QVBoxLayout(&dialog);
+ auto mainLayout = new QVBoxLayout(dialog);
mainLayout->addWidget(new QLabel(i18n("The project you're trying to open is \
already open in at least one "
"other session.<br>What do you \
want to do?"))); QGroupBox sessions;
@@ -808,12 +813,11 @@ void ProjectController::openProject( const QUrl &projectFile )
auto okButton = buttonBox->button(QDialogButtonBox::Ok);
okButton->setDefault(true);
okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
- connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
- connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
+ connect(buttonBox, &QDialogButtonBox::accepted, dialog, &QDialog::accept);
+ connect(buttonBox, &QDialogButtonBox::rejected, dialog, &QDialog::reject);
mainLayout->addWidget(buttonBox);
- bool success = dialog.exec();
- if (!success)
+ if (!dialog->exec())
return;
foreach ( const QObject* obj, sessions.children() ) {
@@ -1158,7 +1162,7 @@ void ProjectController::commitCurrentProject()
bool ret = showVcsDiff(patchSource);
if(!ret) {
- VcsCommitDialog *commitDialog = new VcsCommitDialog(patchSource);
+ ScopedDialog<VcsCommitDialog> commitDialog(patchSource);
commitDialog->setCommitCandidates(patchSource->infos());
commitDialog->exec();
}
diff --git a/shell/sessioncontroller.cpp b/shell/sessioncontroller.cpp
index 137aa7e05..bceb0177a 100644
--- a/shell/sessioncontroller.cpp
+++ b/shell/sessioncontroller.cpp
@@ -614,7 +614,7 @@ QString SessionController::showSessionChooserDialog(QString \
headerText, bool onl
///@todo We need a way to get a proper size-hint from the view, but \
unfortunately, that only seems possible after the view was shown. \
dialog.resize(QSize(900, 600));
- if(dialog.exec() != QDialog::Accepted)
+ if(dialog.exec() != QDialog::Accepted) // krazy:exclude=crashy
{
return QString();
}
diff --git a/shell/settings/environmentwidget.cpp \
b/shell/settings/environmentwidget.cpp index df43dcb76..b09624087 100644
--- a/shell/settings/environmentwidget.cpp
+++ b/shell/settings/environmentwidget.cpp
@@ -33,6 +33,8 @@ Boston, MA 02110-1301, USA.
#include <QHBoxLayout>
#include <QValidator>
+#include <util/scopeddialog.h>
+
#include <KLocalizedString>
#include "environmentprofilelistmodel.h"
@@ -176,10 +178,10 @@ void EnvironmentWidget::defaults( KConfig* config )
QString EnvironmentWidget::askNewProfileName(const QString& defaultName)
{
- QDialog dialog(this);
- dialog.setWindowTitle(i18n("Enter Name of New Environment Profile"));
+ ScopedDialog<QDialog> dialog(this);
+ dialog->setWindowTitle(i18n("Enter Name of New Environment Profile"));
- QVBoxLayout *layout = new QVBoxLayout(&dialog);
+ QVBoxLayout *layout = new QVBoxLayout(dialog);
auto editLayout = new QHBoxLayout;
@@ -193,11 +195,11 @@ QString EnvironmentWidget::askNewProfileName(const QString& \
defaultName) auto okButton = buttonBox->button(QDialogButtonBox::Ok);
okButton->setEnabled(false);
okButton->setDefault(true);
- dialog.connect(buttonBox, &QDialogButtonBox::accepted, &dialog, \
&QDialog::accept);
- dialog.connect(buttonBox, &QDialogButtonBox::rejected, &dialog, \
&QDialog::reject); + dialog->connect(buttonBox, &QDialogButtonBox::accepted, \
dialog, &QDialog::accept); + dialog->connect(buttonBox, \
&QDialogButtonBox::rejected, dialog, &QDialog::reject); \
layout->addWidget(buttonBox);
- auto validator = new ProfileNameValidator(m_environmentProfileListModel, \
&dialog); + auto validator = new \
ProfileNameValidator(m_environmentProfileListModel, dialog);
connect(edit, &QLineEdit::textChanged, validator, [validator, okButton](const \
QString& text) { int pos;
QString t(text);
@@ -208,7 +210,7 @@ QString EnvironmentWidget::askNewProfileName(const QString& \
defaultName) edit->setText(defaultName);
edit->selectAll();
- if (dialog.exec() != QDialog::Accepted) {
+ if (dialog->exec() != QDialog::Accepted) {
return {};
}
@@ -239,10 +241,10 @@ void EnvironmentWidget::onVariableInserted(int column, const \
QVariant& value)
void EnvironmentWidget::batchModeEditButtonClicked()
{
- QDialog dialog(this);
- dialog.setWindowTitle( i18n( "Batch Edit Mode" ) );
+ ScopedDialog<QDialog> dialog(this);
+ dialog->setWindowTitle( i18n( "Batch Edit Mode" ) );
- QVBoxLayout *layout = new QVBoxLayout(&dialog);
+ QVBoxLayout *layout = new QVBoxLayout(dialog);
auto edit = new QPlainTextEdit;
edit->setPlaceholderText(QStringLiteral("VARIABLE1=VALUE1\nVARIABLE2=VALUE2"));
@@ -259,13 +261,13 @@ void EnvironmentWidget::batchModeEditButtonClicked()
auto okButton = buttonBox->button(QDialogButtonBox::Ok);
okButton->setDefault(true);
okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
- dialog.connect(buttonBox, &QDialogButtonBox::accepted, &dialog, \
&QDialog::accept);
- dialog.connect(buttonBox, &QDialogButtonBox::rejected, &dialog, \
&QDialog::reject); + dialog->connect(buttonBox, &QDialogButtonBox::accepted, \
dialog, &QDialog::accept); + dialog->connect(buttonBox, \
&QDialogButtonBox::rejected, dialog, &QDialog::reject); \
layout->addWidget(buttonBox);
- dialog.resize(600, 400);
+ dialog->resize(600, 400);
- if ( dialog.exec() != QDialog::Accepted ) {
+ if ( dialog->exec() != QDialog::Accepted ) {
return;
}
diff --git a/shell/settings/sourceformattersettings.cpp \
b/shell/settings/sourceformattersettings.cpp index 19e036ea7..491a6a91d 100644
--- a/shell/settings/sourceformattersettings.cpp
+++ b/shell/settings/sourceformattersettings.cpp
@@ -38,6 +38,7 @@ Boston, MA 02110-1301, USA.
#include <shell/core.h>
#include <shell/plugincontroller.h>
#include <shell/languagecontroller.h>
+#include <util/scopeddialog.h>
#include "editstyledialog.h"
#include "debug.h"
@@ -401,10 +402,10 @@ void SourceFormatterSettings::editStyle()
QMimeType mimetype = l.mimetypes.first();
if( QScopedPointer<QObject>(fmt->formatter->editStyleWidget( mimetype )) ) {
- EditStyleDialog dlg( fmt->formatter, mimetype, *l.selectedStyle, this );
- if( dlg.exec() == QDialog::Accepted )
+ KDevelop::ScopedDialog<EditStyleDialog> dlg(fmt->formatter, mimetype, \
*l.selectedStyle, this); + if( dlg->exec() == QDialog::Accepted )
{
- l.selectedStyle->setContent(dlg.content());
+ l.selectedStyle->setContent(dlg->content());
}
updatePreview();
emit changed();
diff --git a/shell/settings/templatepage.cpp b/shell/settings/templatepage.cpp
index 64a566c5c..f7ce0883b 100644
--- a/shell/settings/templatepage.cpp
+++ b/shell/settings/templatepage.cpp
@@ -22,6 +22,7 @@
#include "ui_templatepage.h"
#include "qtcompat_p.h"
+#include <QFileDialog>
#include <interfaces/itemplateprovider.h>
#include <language/codegen/templatesmodel.h>
@@ -32,7 +33,7 @@
#include <KZip>
#include <KTar>
-#include <QFileDialog>
+#include <util/scopeddialog.h>
TemplatePage::TemplatePage (KDevelop::ITemplateProvider* provider, QWidget* parent) \
: QWidget (parent), m_provider(provider)
@@ -70,14 +71,14 @@ TemplatePage::~TemplatePage()
void TemplatePage::loadFromFile()
{
- QFileDialog fileDialog(this);
- fileDialog.setMimeTypeFilters(m_provider->supportedMimeTypes());
- fileDialog.setFileMode(QFileDialog::ExistingFiles);
- if (!fileDialog.exec()) {
+ KDevelop::ScopedDialog<QFileDialog> fileDialog(this);
+ fileDialog->setMimeTypeFilters(m_provider->supportedMimeTypes());
+ fileDialog->setFileMode(QFileDialog::ExistingFiles);
+ if (!fileDialog->exec()) {
return;
}
- for (const auto& file : fileDialog.selectedFiles()) {
+ for (const auto& file : fileDialog->selectedFiles()) {
m_provider->loadTemplate(file);
}
@@ -86,10 +87,13 @@ void TemplatePage::loadFromFile()
void TemplatePage::getMoreTemplates()
{
- KNS3::DownloadDialog dialog(m_provider->knsConfigurationFile(), this);
- dialog.exec();
+ KDevelop::ScopedDialog<KNS3::DownloadDialog> \
dialog(m_provider->knsConfigurationFile(), this); +
+ if (!dialog->exec()) {
+ return;
+ }
- if (!dialog.changedEntries().isEmpty())
+ if (!dialog->changedEntries().isEmpty())
{
m_provider->reload();
}
@@ -97,8 +101,8 @@ void TemplatePage::getMoreTemplates()
void TemplatePage::shareTemplates()
{
- KNS3::UploadDialog dialog(m_provider->knsConfigurationFile(), this);
- dialog.exec();
+ KDevelop::ScopedDialog<KNS3::UploadDialog> \
dialog(m_provider->knsConfigurationFile(), this); + dialog->exec();
}
void TemplatePage::currentIndexChanged(const QModelIndex& index)
diff --git a/shell/uicontroller.cpp b/shell/uicontroller.cpp
index 645598801..76a60f799 100644
--- a/shell/uicontroller.cpp
+++ b/shell/uicontroller.cpp
@@ -36,6 +36,7 @@
#include <sublime/holdupdates.h>
#include <interfaces/itoolviewactionlistener.h>
+#include <util/scopeddialog.h>
#include "core.h"
#include "configpage.h"
@@ -434,7 +435,7 @@ void UiController::selectNewToolViewToAdd(MainWindow *mw)
if (!mw || !mw->area())
return;
- QDialog *dia = new QDialog(mw);
+ ScopedDialog<QDialog> dia(mw);
dia->setWindowTitle(i18n("Select Tool View to Add"));
auto mainLayout = new QVBoxLayout(dia);
@@ -474,7 +475,6 @@ void UiController::selectNewToolViewToAdd(MainWindow *mw)
addNewToolView(mw, item);
}
}
- delete dia;
}
void UiController::addNewToolView(MainWindow *mw, QListWidgetItem* item)
diff --git a/util/scopeddialog.h b/util/scopeddialog.h
new file mode 100644
index 000000000..7c0cfd5f0
--- /dev/null
+++ b/util/scopeddialog.h
@@ -0,0 +1,86 @@
+/* This file is part of KDevelop
+ *
+ * Copyright 2017 Christoph Roick <chrisito@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef KDEVPLATFORM_SCOPEDDIALOG_H
+#define KDEVPLATFORM_SCOPEDDIALOG_H
+
+#include <QPointer>
+
+namespace KDevelop {
+
+/**
+ * Wrapper class for QDialogs which should not be instantiated on stack.
+ *
+ * Parents of QDialogs may be unintentionally deleted during the execution of the
+ * dialog and automatically delete their children. When returning to the calling
+ * function they get intentionally deleted again, which will lead to a crash. This
+ * can be circumvented by using a QPointer which keeps track of the QDialogs \
validity. + * See this
+ * <a href="https://blogs.kde.org/2009/03/26/how-crash-almost-every-qtkde-application-and-how-fix-it-0">blog \
entry</a> + * for explanation. The ScopedDialog utility allows using the dialog like \
a + * common pointer.
+ *
+ * Instead of
+ * \code
+ QFileDialog dlg(this);
+ if (dlg.exec())
+ return;
+ \endcode
+ simply use
+ * \code
+ ScopedDialog<QFileDialog> dlg(this);
+ if (dlg->exec())
+ return;
+ \endcode
+ without need to manually clean up afterwards.
+ */
+template<typename DialogType>
+class ScopedDialog {
+ public:
+ /// Construct the dialog with any set of allowed arguments
+ /// for the construction of DialogType
+ template<typename ... Arguments>
+ explicit ScopedDialog(Arguments ... args) : ptr(new DialogType(args...)) {
+ }
+ /// Automatically deletes the dialog if it is still present
+ ~ScopedDialog() {
+ delete ptr;
+ }
+
+ /// Access members of the dialog
+ DialogType* operator->() const {
+ return ptr;
+ }
+ /// Access the dialog
+ DialogType & operator*() const {
+ return *ptr;
+ }
+ /// Return the corresponding pointer
+ operator DialogType*() const {
+ return ptr;
+ }
+
+ private:
+ QPointer<DialogType> ptr;
+};
+
+}
+
+#endif // KDEVPLATFORM_SCOPEDDIALOG_H
diff --git a/vcs/dvcs/dvcsplugin.cpp b/vcs/dvcs/dvcsplugin.cpp
index d1be44f40..85d34387b 100644
--- a/vcs/dvcs/dvcsplugin.cpp
+++ b/vcs/dvcs/dvcsplugin.cpp
@@ -39,6 +39,7 @@
#include <interfaces/context.h>
#include <interfaces/contextmenuextension.h>
#include <interfaces/idocumentcontroller.h>
+#include <util/scopeddialog.h>
#include "dvcsjob.h"
#include "ui/dvcsimportmetadatawidget.h"
@@ -128,9 +129,9 @@ void DistributedVersionControlPlugin::ctxBranchManager()
ICore::self()->documentController()->saveAllDocuments();
- BranchManager branchManager(stripPathToDir(ctxUrlList.front().toLocalFile()),
- this, core()->uiController()->activeMainWindow());
- branchManager.exec();
+ ScopedDialog<BranchManager> \
branchManager(stripPathToDir(ctxUrlList.front().toLocalFile()), + \
this, core()->uiController()->activeMainWindow()); + branchManager->exec();
}
}
diff --git a/vcs/vcspluginhelper.cpp b/vcs/vcspluginhelper.cpp
index 19810b4d0..9778cd5a3 100644
--- a/vcs/vcspluginhelper.cpp
+++ b/vcs/vcspluginhelper.cpp
@@ -42,6 +42,7 @@
#include <interfaces/isession.h>
#include <interfaces/iuicontroller.h>
#include <util/path.h>
+#include <util/scopeddialog.h>
#include <vcs/interfaces/ibasicversioncontrol.h>
#include <vcs/models/vcsannotationmodel.h>
#include <vcs/widgets/vcseventwidget.h>
@@ -457,7 +458,7 @@ void VcsPluginHelper::commit()
bool ret = showVcsDiff(patchSource);
if(!ret) {
- VcsCommitDialog *commitDialog = new VcsCommitDialog(patchSource);
+ ScopedDialog<VcsCommitDialog> commitDialog(patchSource);
commitDialog->setCommitCandidates(patchSource->infos());
commitDialog->exec();
}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic