Skip to content

Commit

Permalink
Don't exit after a save done after a quit request
Browse files Browse the repository at this point in the history
Performing the following pathological sequence of actions used to cause
Drawpile to exit unexpectedly:

* Having a dirty, yet unsaved canvas.
* Initiating quitting the application.
* Saying that you want to save.
* Cancelling that save dialog.
* Performing a save or save as.

This is fixed by not setting the "exit after save" flag if the save
dialog is cancelled.
  • Loading branch information
askmeaboutlo0m committed Dec 19, 2023
1 parent 11b05e2 commit 3ff7589
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 29 deletions.
3 changes: 2 additions & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ Unreleased Version 2.2.0-pre
* Server Feature: Allow setting web admin auth through DRAWPILESRV_WEB_ADMIN_AUTH environment variable. The --web-admin-auth parameter takes precedence.
* Fix: Show the fill tool size limit rectangle even when the outline width is set to zero pixels. Thanks Blozzom for reporting.
* Server Fix: Show an error message if listing on a certain server is not allowed.
* Fix: Unlist sessions more reliably when terminating sessions hosted "on this computer".
* Fix: Unlist sessions more reliably when terminating sessions hosted "on this computer". Thanks to Buch for helping figure this out.
* Fix: Don't select a newly created layer when there's a default layer.
* Fix: Give the timeline dock a sensible minimum height. Thanks Kink for reporting.
* Fix: Make notification sounds work in the AppImage release. Thanks anonymous for reporting.
* Fix: Don't exit the program in the pathological case of initiating a quit, being prompted to save, cancelling the save dialog and then saving again.

2023-12-08 Version 2.2.0-beta.11
* Server Fix: No longer show "cannot look up one session and then join another" when joining a session with an ID alias. Thanks Kink and Fabian for finding this.
Expand Down
53 changes: 27 additions & 26 deletions src/desktop/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ MainWindow::MainWindow(bool restoreWindowPosition)
m_notificationsMuted(false),
m_initialCatchup(false),
m_doc(nullptr),
m_exitAfterSave(false)
m_exitAction(RUNNING)
{
// Avoid flickering of intermediate states.
setUpdatesEnabled(false);
Expand Down Expand Up @@ -1158,12 +1158,11 @@ void MainWindow::closeEvent(QCloseEvent *event)

if(m_doc->isSaveInProgress()) {
// Don't quit while save is in progress
m_exitAfterSave = true;
m_exitAction = SAVING;
event->ignore();
return;
}

QElapsedTimer disconnectTimer;
if(canReplace() == false) {

// First confirm disconnection
Expand All @@ -1182,12 +1181,16 @@ void MainWindow::closeEvent(QCloseEvent *event)

box.exec();
if(box.clickedButton() == exitbtn) {
disconnectTimer.start();
// Disconnect and wait a moment for things to settle so that
// e.g. the builtin server gets a chance to shut down properly
// and any pending drawing commands get executed.
m_exitAction = DISCONNECTING;
m_doc->client()->disconnectFromServer();
} else {
event->ignore();
return;
setEnabled(false);
QApplication::setOverrideCursor(Qt::WaitCursor);
}
event->ignore();
return;
}

// Then confirm unsaved changes
Expand All @@ -1208,8 +1211,9 @@ void MainWindow::closeEvent(QCloseEvent *event)
// Save and exit, or cancel exit if couldn't save.
if(box.clickedButton() == savebtn) {
cancel = true;
m_exitAfterSave = true;
save();
if(save()) {
m_exitAction = SAVING;
}
}

// Cancel exit
Expand All @@ -1219,19 +1223,8 @@ void MainWindow::closeEvent(QCloseEvent *event)
}
}
}
// If we just disconnected, give things another moment to settle so that
// e.g. the builtin server gets a chance to shut down gracefully and delete
// any session announcements that may have been made.
qint64 delay = disconnectTimer.isValid() && !m_exitAfterSave
? 1000 - disconnectTimer.elapsed() : 0;
if(delay > 0) {
event->ignore();
setEnabled(false);
QApplication::setOverrideCursor(Qt::WaitCursor);
QTimer::singleShot(delay, this, &QMainWindow::close);
} else {
exit();
}

exit();
}

bool MainWindow::event(QEvent *event)
Expand Down Expand Up @@ -1532,11 +1525,14 @@ void MainWindow::open()
/**
* If no file name has been selected, \a saveas is called.
*/
void MainWindow::save()
bool MainWindow::save()
{
QString result = FileWrangler{this}.saveImage(m_doc);
if(!result.isEmpty()) {
if(result.isEmpty()) {
return false;
} else {
addRecentFile(result);
return true;
}
}

Expand Down Expand Up @@ -1613,9 +1609,9 @@ void MainWindow::onCanvasSaved(const QString &errorMessage)

// Cancel exit if canvas is modified while it was being saved
if(m_doc->isDirty())
m_exitAfterSave = false;
m_exitAction = RUNNING;

if(m_exitAfterSave)
if(m_exitAction == SAVING)
close();
}

Expand Down Expand Up @@ -2304,6 +2300,11 @@ void MainWindow::onServerDisconnected(const QString &message, const QString &err
dpApp().notifications()->trigger(
this, notification::Event::Disconnect, notif);
}

if(m_exitAction != RUNNING) {
m_exitAction = RUNNING;
QTimer::singleShot(100, this, &QMainWindow::close);
}
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/desktop/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public slots:
void showNew();
void open();
void open(const QUrl &url);
void save();
bool save();
void saveas();
void saveSelection();
void exportImage();
Expand Down Expand Up @@ -361,7 +361,7 @@ private slots:

Document *m_doc;
MainActions *m_ma;
bool m_exitAfterSave;
enum { RUNNING, DISCONNECTING, SAVING } m_exitAction;

drawdance::CanvasState m_preResetCanvasState;

Expand Down

0 comments on commit 3ff7589

Please sign in to comment.