Close subwindows gracefully, prompt save on quit
This commit is contained in:
parent
a960456c6e
commit
b60e54c07c
8 changed files with 100 additions and 72 deletions
|
@ -43,7 +43,7 @@ public:
|
||||||
public:
|
public:
|
||||||
Ui::MainWindow* ui;
|
Ui::MainWindow* ui;
|
||||||
QObject *parent = nullptr;
|
QObject *parent = nullptr;
|
||||||
Project *project = nullptr;
|
QPointer<Project> project = nullptr;
|
||||||
Map *map = nullptr;
|
Map *map = nullptr;
|
||||||
Settings *settings;
|
Settings *settings;
|
||||||
void saveProject();
|
void saveProject();
|
||||||
|
|
|
@ -295,7 +295,7 @@ private slots:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Ui::MainWindow *ui;
|
Ui::MainWindow *ui;
|
||||||
Editor *editor = nullptr;
|
QPointer<Editor> editor = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QLabel *label_MapRulerStatus = nullptr;
|
QLabel *label_MapRulerStatus = nullptr;
|
||||||
|
@ -331,7 +331,6 @@ private:
|
||||||
|
|
||||||
bool isProgrammaticEventTabChange;
|
bool isProgrammaticEventTabChange;
|
||||||
bool projectHasUnsavedChanges;
|
bool projectHasUnsavedChanges;
|
||||||
bool projectOpenFailure = false;
|
|
||||||
bool newMapDefaultsSet = false;
|
bool newMapDefaultsSet = false;
|
||||||
|
|
||||||
MapSortOrder mapSortOrder;
|
MapSortOrder mapSortOrder;
|
||||||
|
@ -348,7 +347,9 @@ private:
|
||||||
void openSubWindow(QWidget * window);
|
void openSubWindow(QWidget * window);
|
||||||
QString getExistingDirectory(QString);
|
QString getExistingDirectory(QString);
|
||||||
bool openProject(const QString &dir, bool initial = false);
|
bool openProject(const QString &dir, bool initial = false);
|
||||||
|
bool closeProject();
|
||||||
void showProjectOpenFailure();
|
void showProjectOpenFailure();
|
||||||
|
void saveGlobalConfigs();
|
||||||
bool setInitialMap();
|
bool setInitialMap();
|
||||||
void setRecentMap(QString map_name);
|
void setRecentMap(QString map_name);
|
||||||
QStandardItem* createMapItem(QString mapName, int groupNum, int inGroupNum);
|
QStandardItem* createMapItem(QString mapName, int groupNum, int inGroupNum);
|
||||||
|
@ -379,7 +380,7 @@ private:
|
||||||
void setTheme(QString);
|
void setTheme(QString);
|
||||||
void updateTilesetEditor();
|
void updateTilesetEditor();
|
||||||
Event::Group getEventGroupFromTabWidget(QWidget *tab);
|
Event::Group getEventGroupFromTabWidget(QWidget *tab);
|
||||||
void closeSupplementaryWindows();
|
bool closeSupplementaryWindows();
|
||||||
void setWindowDisabled(bool);
|
void setWindowDisabled(bool);
|
||||||
|
|
||||||
void initTilesetEditor();
|
void initTilesetEditor();
|
||||||
|
|
|
@ -79,10 +79,11 @@ void Editor::saveUiFields() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::closeProject() {
|
void Editor::closeProject() {
|
||||||
if (this->project) {
|
if (!this->project)
|
||||||
delete this->project;
|
return;
|
||||||
this->project = nullptr;
|
|
||||||
}
|
Scripting::cb_ProjectClosed(this->project->root);
|
||||||
|
delete this->project;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::setEditingMap() {
|
void Editor::setEditingMap() {
|
||||||
|
|
|
@ -71,6 +71,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
{
|
{
|
||||||
delete label_MapRulerStatus;
|
delete label_MapRulerStatus;
|
||||||
|
delete editor;
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,8 +478,12 @@ void MainWindow::setTheme(QString theme) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWindow::openProject(const QString &dir, bool initial) {
|
bool MainWindow::openProject(const QString &dir, bool initial) {
|
||||||
|
if (!this->closeProject()) {
|
||||||
|
logInfo("Aborted project open.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (dir.isNull() || dir.length() <= 0) {
|
if (dir.isNull() || dir.length() <= 0) {
|
||||||
projectOpenFailure = true;
|
|
||||||
if (!initial) setWindowDisabled(true);
|
if (!initial) setWindowDisabled(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -486,7 +491,6 @@ bool MainWindow::openProject(const QString &dir, bool initial) {
|
||||||
const QString projectString = QString("%1project '%2'").arg(initial ? "recent " : "").arg(QDir::toNativeSeparators(dir));
|
const QString projectString = QString("%1project '%2'").arg(initial ? "recent " : "").arg(QDir::toNativeSeparators(dir));
|
||||||
|
|
||||||
if (!QDir(dir).exists()) {
|
if (!QDir(dir).exists()) {
|
||||||
projectOpenFailure = true;
|
|
||||||
const QString errorMsg = QString("Failed to open %1: No such directory").arg(projectString);
|
const QString errorMsg = QString("Failed to open %1: No such directory").arg(projectString);
|
||||||
this->statusBar()->showMessage(errorMsg);
|
this->statusBar()->showMessage(errorMsg);
|
||||||
if (initial) {
|
if (initial) {
|
||||||
|
@ -503,43 +507,30 @@ bool MainWindow::openProject(const QString &dir, bool initial) {
|
||||||
this->statusBar()->showMessage(openMessage);
|
this->statusBar()->showMessage(openMessage);
|
||||||
logInfo(openMessage);
|
logInfo(openMessage);
|
||||||
|
|
||||||
|
// TODO: Don't save these yet
|
||||||
userConfig.setProjectDir(dir);
|
userConfig.setProjectDir(dir);
|
||||||
userConfig.load();
|
userConfig.load();
|
||||||
projectConfig.setProjectDir(dir);
|
projectConfig.setProjectDir(dir);
|
||||||
projectConfig.load();
|
projectConfig.load();
|
||||||
|
|
||||||
this->closeSupplementaryWindows();
|
|
||||||
this->newMapDefaultsSet = false;
|
this->newMapDefaultsSet = false;
|
||||||
|
|
||||||
if (isProjectOpen())
|
|
||||||
Scripting::cb_ProjectClosed(editor->project->root);
|
|
||||||
Scripting::init(this);
|
Scripting::init(this);
|
||||||
|
|
||||||
bool already_open = isProjectOpen() && (editor->project->root == dir);
|
this->editor->project = new Project(this);
|
||||||
if (!already_open) {
|
QObject::connect(this->editor->project, &Project::reloadProject, this, &MainWindow::on_action_Reload_Project_triggered);
|
||||||
editor->closeProject();
|
QObject::connect(this->editor->project, &Project::mapCacheCleared, this, &MainWindow::onMapCacheCleared);
|
||||||
editor->project = new Project(this);
|
QObject::connect(this->editor->project, &Project::uncheckMonitorFilesAction, [this]() {
|
||||||
QObject::connect(editor->project, &Project::reloadProject, this, &MainWindow::on_action_Reload_Project_triggered);
|
porymapConfig.setMonitorFiles(false);
|
||||||
QObject::connect(editor->project, &Project::mapCacheCleared, this, &MainWindow::onMapCacheCleared);
|
if (this->preferenceEditor)
|
||||||
QObject::connect(editor->project, &Project::uncheckMonitorFilesAction, [this]() {
|
this->preferenceEditor->updateFields();
|
||||||
porymapConfig.setMonitorFiles(false);
|
});
|
||||||
if (this->preferenceEditor)
|
this->editor->project->set_root(dir);
|
||||||
this->preferenceEditor->updateFields();
|
|
||||||
});
|
|
||||||
editor->project->set_root(dir);
|
|
||||||
} else {
|
|
||||||
editor->project->fileWatcher.removePaths(editor->project->fileWatcher.files());
|
|
||||||
editor->project->clearMapCache();
|
|
||||||
editor->project->clearTilesetCache();
|
|
||||||
}
|
|
||||||
|
|
||||||
this->projectOpenFailure = !(loadDataStructures()
|
if (!(loadDataStructures() && populateMapList() && setInitialMap())) {
|
||||||
&& populateMapList()
|
|
||||||
&& setInitialMap());
|
|
||||||
|
|
||||||
if (this->projectOpenFailure) {
|
|
||||||
this->statusBar()->showMessage(QString("Failed to open %1").arg(projectString));
|
this->statusBar()->showMessage(QString("Failed to open %1").arg(projectString));
|
||||||
showProjectOpenFailure();
|
showProjectOpenFailure();
|
||||||
|
delete this->editor->project;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,7 +559,7 @@ void MainWindow::showProjectOpenFailure() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWindow::isProjectOpen() {
|
bool MainWindow::isProjectOpen() {
|
||||||
return !projectOpenFailure && editor && editor->project;
|
return editor && editor->project;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MainWindow::setInitialMap() {
|
bool MainWindow::setInitialMap() {
|
||||||
|
@ -1228,12 +1219,10 @@ void MainWindow::openNewMapPopupWindow() {
|
||||||
}
|
}
|
||||||
if (!this->newMapPrompt) {
|
if (!this->newMapPrompt) {
|
||||||
this->newMapPrompt = new NewMapPopup(this, this->editor->project);
|
this->newMapPrompt = new NewMapPopup(this, this->editor->project);
|
||||||
|
connect(this->newMapPrompt, &NewMapPopup::applied, this, &MainWindow::onNewMapCreated);
|
||||||
}
|
}
|
||||||
|
|
||||||
openSubWindow(this->newMapPrompt);
|
openSubWindow(this->newMapPrompt);
|
||||||
|
|
||||||
connect(this->newMapPrompt, &NewMapPopup::applied, this, &MainWindow::onNewMapCreated);
|
|
||||||
this->newMapPrompt->setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_action_NewMap_triggered() {
|
void MainWindow::on_action_NewMap_triggered() {
|
||||||
|
@ -1751,11 +1740,6 @@ void MainWindow::on_mapViewTab_tabBarClicked(int index)
|
||||||
editor->setCursorRectVisible(false);
|
editor->setCursorRectVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_action_Exit_triggered()
|
|
||||||
{
|
|
||||||
QApplication::quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_mainTabBar_tabBarClicked(int index)
|
void MainWindow::on_mainTabBar_tabBarClicked(int index)
|
||||||
{
|
{
|
||||||
int oldIndex = ui->mainTabBar->currentIndex();
|
int oldIndex = ui->mainTabBar->currentIndex();
|
||||||
|
@ -2486,11 +2470,8 @@ void MainWindow::importMapFromAdvanceMap1_92()
|
||||||
void MainWindow::showExportMapImageWindow(ImageExporterMode mode) {
|
void MainWindow::showExportMapImageWindow(ImageExporterMode mode) {
|
||||||
if (!editor->project) return;
|
if (!editor->project) return;
|
||||||
|
|
||||||
if (this->mapImageExporter)
|
if (!this->mapImageExporter)
|
||||||
delete this->mapImageExporter;
|
this->mapImageExporter = new MapImageExporter(this, this->editor, mode);
|
||||||
|
|
||||||
this->mapImageExporter = new MapImageExporter(this, this->editor, mode);
|
|
||||||
this->mapImageExporter->setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
|
|
||||||
openSubWindow(this->mapImageExporter);
|
openSubWindow(this->mapImageExporter);
|
||||||
}
|
}
|
||||||
|
@ -2923,36 +2904,59 @@ bool MainWindow::initRegionMapEditor(bool silent) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::closeSupplementaryWindows() {
|
// Attempt to close any open sub-windows of the main window, giving each a chance to abort the process.
|
||||||
delete this->tilesetEditor;
|
// Each of these are expected to be a QPointer to a widget with WA_DeleteOnClose set, so manually deleting
|
||||||
delete this->regionMapEditor;
|
// and nullifying the pointer members is not necessary here.
|
||||||
delete this->mapImageExporter;
|
// TODO: Testing
|
||||||
delete this->newMapPrompt;
|
bool MainWindow::closeSupplementaryWindows() {
|
||||||
delete this->shortcutsEditor;
|
if (this->tilesetEditor && !this->tilesetEditor->close())
|
||||||
delete this->customScriptsEditor;
|
return false;
|
||||||
|
if (this->regionMapEditor && !this->regionMapEditor->close())
|
||||||
|
return false;
|
||||||
|
if (this->mapImageExporter && !this->mapImageExporter->close())
|
||||||
|
return false;
|
||||||
|
if (this->newMapPrompt && !this->newMapPrompt->close())
|
||||||
|
return false;
|
||||||
|
if (this->shortcutsEditor && !this->shortcutsEditor->close())
|
||||||
|
return false;
|
||||||
|
if (this->preferenceEditor && !this->preferenceEditor->close())
|
||||||
|
return false;
|
||||||
|
if (this->customScriptsEditor && !this->customScriptsEditor->close())
|
||||||
|
return false;
|
||||||
if (this->projectSettingsEditor) this->projectSettingsEditor->closeQuietly();
|
if (this->projectSettingsEditor) this->projectSettingsEditor->closeQuietly();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::closeEvent(QCloseEvent *event) {
|
bool MainWindow::closeProject() {
|
||||||
if (isProjectOpen()) {
|
if (!closeSupplementaryWindows())
|
||||||
if (projectHasUnsavedChanges || (editor->map && editor->map->hasUnsavedChanges())) {
|
return false;
|
||||||
QMessageBox::StandardButton result = QMessageBox::question(
|
|
||||||
this, "porymap", "The project has been modified, save changes?",
|
|
||||||
QMessageBox::No | QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
|
|
||||||
|
|
||||||
if (result == QMessageBox::Yes) {
|
if (!isProjectOpen())
|
||||||
editor->saveProject();
|
return true;
|
||||||
} else if (result == QMessageBox::No) {
|
|
||||||
logWarn("Closing porymap with unsaved changes.");
|
if (projectHasUnsavedChanges || (editor->map && editor->map->hasUnsavedChanges())) {
|
||||||
} else if (result == QMessageBox::Cancel) {
|
QMessageBox::StandardButton result = QMessageBox::question(
|
||||||
event->ignore();
|
this, "porymap", "The project has been modified, save changes?",
|
||||||
return;
|
QMessageBox::No | QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
|
||||||
}
|
|
||||||
|
if (result == QMessageBox::Yes) {
|
||||||
|
editor->saveProject();
|
||||||
|
} else if (result == QMessageBox::No) {
|
||||||
|
logWarn("Closing project with unsaved changes.");
|
||||||
|
} else if (result == QMessageBox::Cancel) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
projectConfig.save();
|
|
||||||
userConfig.save();
|
|
||||||
}
|
}
|
||||||
|
projectConfig.save();
|
||||||
|
userConfig.save();
|
||||||
|
|
||||||
|
editor->closeProject();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::saveGlobalConfigs() {
|
||||||
porymapConfig.setMainGeometry(
|
porymapConfig.setMainGeometry(
|
||||||
this->saveGeometry(),
|
this->saveGeometry(),
|
||||||
this->saveState(),
|
this->saveState(),
|
||||||
|
@ -2962,6 +2966,24 @@ void MainWindow::closeEvent(QCloseEvent *event) {
|
||||||
);
|
);
|
||||||
porymapConfig.save();
|
porymapConfig.save();
|
||||||
shortcutsConfig.save();
|
shortcutsConfig.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_action_Exit_triggered() {
|
||||||
|
if (!closeProject())
|
||||||
|
return;
|
||||||
|
|
||||||
|
saveGlobalConfigs();
|
||||||
|
|
||||||
|
QApplication::quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::closeEvent(QCloseEvent *event) {
|
||||||
|
if (!closeProject()) {
|
||||||
|
event->ignore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
saveGlobalConfigs();
|
||||||
|
|
||||||
QMainWindow::closeEvent(event);
|
QMainWindow::closeEvent(event);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ MapImageExporter::MapImageExporter(QWidget *parent_, Editor *editor_, ImageExpor
|
||||||
QDialog(parent_),
|
QDialog(parent_),
|
||||||
ui(new Ui::MapImageExporter)
|
ui(new Ui::MapImageExporter)
|
||||||
{
|
{
|
||||||
|
this->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
this->map = editor_->map;
|
this->map = editor_->map;
|
||||||
this->editor = editor_;
|
this->editor = editor_;
|
||||||
|
|
|
@ -14,6 +14,7 @@ NewMapPopup::NewMapPopup(QWidget *parent, Project *project) :
|
||||||
QMainWindow(parent),
|
QMainWindow(parent),
|
||||||
ui(new Ui::NewMapPopup)
|
ui(new Ui::NewMapPopup)
|
||||||
{
|
{
|
||||||
|
this->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
this->project = project;
|
this->project = project;
|
||||||
this->existingLayout = false;
|
this->existingLayout = false;
|
||||||
|
|
|
@ -26,6 +26,7 @@ RegionMapEditor::RegionMapEditor(QWidget *parent, Project *project) :
|
||||||
QMainWindow(parent),
|
QMainWindow(parent),
|
||||||
ui(new Ui::RegionMapEditor)
|
ui(new Ui::RegionMapEditor)
|
||||||
{
|
{
|
||||||
|
this->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
this->ui->setupUi(this);
|
this->ui->setupUi(this);
|
||||||
this->project = project;
|
this->project = project;
|
||||||
this->initShortcuts();
|
this->initShortcuts();
|
||||||
|
|
|
@ -20,6 +20,7 @@ TilesetEditor::TilesetEditor(Project *project, Map *map, QWidget *parent) :
|
||||||
map(map),
|
map(map),
|
||||||
hasUnsavedChanges(false)
|
hasUnsavedChanges(false)
|
||||||
{
|
{
|
||||||
|
this->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
this->setTilesets(this->map->layout->tileset_primary_label, this->map->layout->tileset_secondary_label);
|
this->setTilesets(this->map->layout->tileset_primary_label, this->map->layout->tileset_secondary_label);
|
||||||
this->initUi();
|
this->initUi();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue