Skip to content
Permalink
Browse files

Improved UX when closing projects with layers with unsaved changes

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...
  • Loading branch information
nyalldawson committed Aug 3, 2018
1 parent e5604f9 commit 02bd1ccc14d11cca00f01382791232387a4656cd
Showing with 44 additions and 6 deletions.
  1. +33 −6 src/app/qgisapp.cpp
  2. +11 −0 src/app/qgisapp.h
@@ -5218,7 +5218,7 @@ void QgisApp::fileExit()
return;
}

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

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

if ( !saveDirty() )
if ( !checkUnsavedLayerEdits() || !saveDirty() )
{
return false; //cancel pressed
}
@@ -5646,7 +5646,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;
@@ -5680,6 +5680,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() );
}
@@ -6107,7 +6110,7 @@ void QgisApp::openProject( QAction *action )
return;

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

@@ -6133,7 +6136,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 );
@@ -10917,6 +10920,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;
@@ -1787,6 +1787,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();

0 comments on commit 02bd1cc

Please sign in to comment.
You can’t perform that action at this time.