Skip to content

Commit

Permalink
Improved UX when closing projects with layers with unsaved changes
Browse files Browse the repository at this point in the history
Previously, the unsaved layer warnings would come AFTER the
unsaved project warning. The unsaved layer warnings had no
cancel option, which meant that there was no way to cancel
a project close when unsaved layer edits exist, and you
were forced to either save these edits or discard them.

Now, the unsaved layer edits checks occur before the unsaved
project check, and you have the option now to 'Cancel' the
project close from the unsaved layer edits messagebox. This
allows users to cancel the project close operation if they
want to e.g. inspect manually unsaved layers to decide
what action is appropriate to take on these.

Also fixes the unsaved layer edits prompt sometimes didn't
appear, even though unsaved changes were present...

(cherry-picked from 02bd1cc)
  • Loading branch information
nyalldawson committed Aug 3, 2018
1 parent dd5ed68 commit 7d67897
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 6 deletions.
39 changes: 33 additions & 6 deletions src/app/qgisapp.cpp
Expand Up @@ -5142,7 +5142,7 @@ void QgisApp::fileExit()
return;
}

if ( saveDirty() )
if ( checkUnsavedLayerEdits() && saveDirty() )
{
closeProject();
userProfileManager()->setDefaultFromActive();
Expand Down Expand Up @@ -5177,7 +5177,7 @@ bool QgisApp::fileNew( bool promptToSaveFlag, bool forceBlank )

if ( promptToSaveFlag )
{
if ( !saveDirty() )
if ( !checkUnsavedLayerEdits() || !saveDirty() )
{
return false; //cancel pressed
}
Expand Down Expand Up @@ -5271,7 +5271,7 @@ bool QgisApp::fileNewFromTemplate( const QString &fileName )
if ( checkTasksDependOnProject() )
return false;

if ( !saveDirty() )
if ( !checkUnsavedLayerEdits() || !saveDirty() )
{
return false; //cancel pressed
}
Expand Down Expand Up @@ -5570,7 +5570,7 @@ void QgisApp::fileOpen()
return;

// possibly save any pending work before opening a new project
if ( saveDirty() )
if ( checkUnsavedLayerEdits() && saveDirty() )
{
// Retrieve last used project dir from persistent settings
QgsSettings settings;
Expand Down Expand Up @@ -5604,6 +5604,9 @@ void QgisApp::fileRevert()
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) == QMessageBox::No )
return;

if ( !checkUnsavedLayerEdits() )
return;

// re-open the current project
addProject( QgsProject::instance()->fileName() );
}
Expand Down Expand Up @@ -6031,7 +6034,7 @@ void QgisApp::openProject( QAction *action )
return;

QString debugme = action->data().toString();
if ( saveDirty() )
if ( checkUnsavedLayerEdits() && saveDirty() )
addProject( debugme );
}

Expand All @@ -6057,7 +6060,7 @@ void QgisApp::openProject( const QString &fileName )
return;

// possibly save any pending work before opening a different project
if ( saveDirty() )
if ( checkUnsavedLayerEdits() && saveDirty() )
{
// error handling and reporting is in addProject() function
addProject( fileName );
Expand Down Expand Up @@ -10831,6 +10834,30 @@ bool QgisApp::saveDirty()
return answer != QMessageBox::Cancel;
}

bool QgisApp::checkUnsavedLayerEdits()
{
// check to see if there are any vector layers with unsaved provider edits
// to ensure user has opportunity to save any editing
if ( QgsProject::instance()->count() > 0 )
{
const QMap<QString, QgsMapLayer *> layers = QgsProject::instance()->mapLayers();
for ( auto it = layers.begin(); it != layers.end(); ++it )
{
if ( QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( it.value() ) )
{
const bool hasUnsavedEdits = ( vl->isEditable() && vl->isModified() );
if ( !hasUnsavedEdits )
continue;

if ( !toggleEditing( vl, true ) )
return false;
}
}
}

return true;
}

bool QgisApp::checkTasksDependOnProject()
{
QSet< QString > activeTaskDescriptions;
Expand Down
11 changes: 11 additions & 0 deletions src/app/qgisapp.h
Expand Up @@ -1779,6 +1779,17 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
* \returns true if saved or discarded, false if canceled
*/
bool saveDirty();

/**
* Checks for unsaved changes in open layers and prompts the user to save
* or discard these changes for each layer.
*
* Returns true if there are no unsaved layer edits remaining, or the user
* opted to discard them all. Returns false if the user opted to cancel
* on any layer.
*/
bool checkUnsavedLayerEdits();

//! Checks for running tasks dependent on the open project
bool checkTasksDependOnProject();

Expand Down

0 comments on commit 7d67897

Please sign in to comment.