StudioWelcome: fix crashes when setupWizard fails

Task-number: QDS-13209
Change-Id: I5751de9d5a5c8065a7cbad91c048d7d4d60de238
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Tim Jenssen
2024-07-11 13:22:36 +02:00
parent 49bb87287c
commit 19f5099c93
3 changed files with 18 additions and 14 deletions

View File

@@ -49,7 +49,7 @@ QString uniqueProjectName(const QString &path)
/***********************/ /***********************/
QdsNewDialog::QdsNewDialog(QWidget *parent) QdsNewDialog::QdsNewDialog(QWidget *parent)
: m_dialog{new QQuickWidget(parent)} : m_dialog{Utils::makeUniqueObjectPtr<QQuickWidget>(parent)}
, m_categoryModel{new PresetCategoryModel(&m_presetData, this)} , m_categoryModel{new PresetCategoryModel(&m_presetData, this)}
, m_presetModel{new PresetModel(&m_presetData, this)} , m_presetModel{new PresetModel(&m_presetData, this)}
, m_screenSizeModel{new ScreenSizeModel(this)} , m_screenSizeModel{new ScreenSizeModel(this)}
@@ -57,7 +57,7 @@ QdsNewDialog::QdsNewDialog(QWidget *parent)
, m_recentsStore{"RecentPresets.json", StorePolicy::UniqueValues} , m_recentsStore{"RecentPresets.json", StorePolicy::UniqueValues}
, m_userPresetsStore{"UserPresets.json", StorePolicy::UniqueNames} , m_userPresetsStore{"UserPresets.json", StorePolicy::UniqueNames}
{ {
setParent(m_dialog); connect(m_dialog.get(), &QObject::destroyed, this, &QObject::deleteLater);
m_recentsStore.setReverseOrder(); m_recentsStore.setReverseOrder();
m_recentsStore.setMaximum(10); m_recentsStore.setMaximum(10);
@@ -89,9 +89,10 @@ QdsNewDialog::QdsNewDialog(QWidget *parent)
m_dialog->installEventFilter(this); m_dialog->installEventFilter(this);
QObject::connect(&m_wizard, &WizardHandler::wizardCreationFailed, this, [this] { QObject::connect(&m_wizard, &WizardHandler::wizardCreationFailed, this, [this] {
QMessageBox::critical(m_dialog, tr("New Project"), tr("Failed to initialize data.")); // TODO: if the dialog itself could react on the error
// the would not be necessary
QMessageBox::critical(m_dialog.get(), tr("New Project"), tr("Failed to initialize data."));
reject(); reject();
deleteLater();
}); });
QObject::connect(m_styleModel.data(), &StyleModel::modelAboutToBeReset, this, [this] { QObject::connect(m_styleModel.data(), &StyleModel::modelAboutToBeReset, this, [this] {
@@ -101,7 +102,7 @@ QdsNewDialog::QdsNewDialog(QWidget *parent)
bool QdsNewDialog::eventFilter(QObject *obj, QEvent *event) bool QdsNewDialog::eventFilter(QObject *obj, QEvent *event)
{ {
if (obj == m_dialog && event->type() == QEvent::KeyPress if (obj == m_dialog.get() && event->type() == QEvent::KeyPress
&& static_cast<QKeyEvent *>(event)->key() == Qt::Key_Escape) { && static_cast<QKeyEvent *>(event)->key() == Qt::Key_Escape) {
reject(); reject();
return true; return true;
@@ -314,7 +315,7 @@ void QdsNewDialog::setWizardFactories(QList<Core::IWizardFactory *> factories_,
{ {
Utils::Id platform = Utils::Id::fromSetting("Desktop"); Utils::Id platform = Utils::Id::fromSetting("Desktop");
WizardFactories factories{factories_, m_dialog, platform}; WizardFactories factories{factories_, m_dialog.get(), platform};
std::vector<UserPresetData> recents = m_recentsStore.fetchAll(); std::vector<UserPresetData> recents = m_recentsStore.fetchAll();
std::vector<UserPresetData> userPresets = m_userPresetsStore.fetchAll(); std::vector<UserPresetData> userPresets = m_userPresetsStore.fetchAll();
@@ -404,8 +405,6 @@ void QdsNewDialog::accept()
m_recentsStore.save(preset); m_recentsStore.save(preset);
m_dialog->close(); m_dialog->close();
m_dialog->deleteLater();
m_dialog = nullptr;
} }
void QdsNewDialog::reject() void QdsNewDialog::reject()
@@ -415,12 +414,13 @@ void QdsNewDialog::reject()
m_wizard.destroyWizard(); m_wizard.destroyWizard();
m_dialog->close(); m_dialog->close();
m_dialog = nullptr; m_dialog.reset();
} }
QString QdsNewDialog::chooseProjectLocation() QString QdsNewDialog::chooseProjectLocation()
{ {
Utils::FilePath newPath = Utils::FileUtils::getExistingDirectory(m_dialog, tr("Choose Directory"), Utils::FilePath newPath = Utils::FileUtils::getExistingDirectory(m_dialog.get(),
tr("Choose Directory"),
m_qmlProjectLocation); m_qmlProjectLocation);
return QDir::toNativeSeparators(newPath.toString()); return QDir::toNativeSeparators(newPath.toString());
@@ -473,7 +473,7 @@ void QdsNewDialog::savePresetDialogAccept()
UserPresetData preset = currentUserPresetData(m_qmlPresetName); UserPresetData preset = currentUserPresetData(m_qmlPresetName);
if (!m_userPresetsStore.save(preset)) { if (!m_userPresetsStore.save(preset)) {
QMessageBox::warning(m_dialog, QMessageBox::warning(m_dialog.get(),
tr("Save Preset"), tr("Save Preset"),
tr("A preset with this name already exists.")); tr("A preset with this name already exists."));
return; return;

View File

@@ -7,6 +7,7 @@
#include <coreplugin/dialogs/newdialog.h> #include <coreplugin/dialogs/newdialog.h>
#include <utils/infolabel.h> #include <utils/infolabel.h>
#include <utils/uniqueobjectptr.h>
#include "wizardhandler.h" #include "wizardhandler.h"
#include "presetmodel.h" #include "presetmodel.h"
@@ -64,7 +65,7 @@ public:
explicit QdsNewDialog(QWidget *parent); explicit QdsNewDialog(QWidget *parent);
QWidget *widget() override { return m_dialog; } QWidget *widget() override { return m_dialog.get(); }
void setWizardFactories(QList<Core::IWizardFactory *> factories, const Utils::FilePath &defaultLocation, void setWizardFactories(QList<Core::IWizardFactory *> factories, const Utils::FilePath &defaultLocation,
const QVariantMap &extraVariables) override; const QVariantMap &extraVariables) override;
@@ -139,7 +140,7 @@ private slots:
void onWizardCreated(QStandardItemModel *screenSizeModel, QStandardItemModel *styleModel); void onWizardCreated(QStandardItemModel *screenSizeModel, QStandardItemModel *styleModel);
private: private:
QQuickWidget *m_dialog = nullptr; Utils::UniqueObjectPtr<QQuickWidget> m_dialog;
PresetData m_presetData; PresetData m_presetData;
QPointer<PresetCategoryModel> m_categoryModel; QPointer<PresetCategoryModel> m_categoryModel;

View File

@@ -53,7 +53,10 @@ void WizardHandler::setupWizard()
initializeProjectPage(m_wizard->page(0)); initializeProjectPage(m_wizard->page(0));
initializeFieldsPage(m_wizard->page(1)); initializeFieldsPage(m_wizard->page(1));
if (!m_detailsPage) {
emit wizardCreationFailed();
return;
}
auto *screenFactorModel = getScreenFactorModel(m_detailsPage); auto *screenFactorModel = getScreenFactorModel(m_detailsPage);
auto *styleModel = getStyleModel(m_detailsPage); auto *styleModel = getStyleModel(m_detailsPage);