Skip to content
Permalink
Browse files

Merge pull request #8657 from elpaso/bugfix-20743-badlayers-dirty

Decent workaround to dirty a project after bad layer handling
  • Loading branch information
elpaso committed Dec 13, 2018
2 parents a395aff + 0042cc0 commit 8c07c994fc328c14482696be5d2b60bd86fc7e58
Showing with 111 additions and 76 deletions.
  1. +94 −75 src/app/qgisapp.cpp
  2. +2 −0 src/app/qgisapp.h
  3. +6 −1 src/app/qgshandlebadlayers.cpp
  4. +9 −0 src/app/qgshandlebadlayers.h
@@ -1240,7 +1240,8 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
mRasterFileFilter = QgsProviderRegistry::instance()->fileRasterFilters();

// set handler for missing layers (will be owned by QgsProject)
QgsProject::instance()->setBadLayerHandler( new QgsHandleBadLayersHandler() );
mAppBadLayersHandler = new QgsHandleBadLayersHandler();
QgsProject::instance()->setBadLayerHandler( mAppBadLayersHandler );

#if 0
// Set the background color for toolbox and overview as they default to
@@ -5806,7 +5807,12 @@ void QgisApp::enableProjectMacros()

bool QgisApp::addProject( const QString &projectFile )
{
MAYBE_UNUSED QgsProjectDirtyBlocker dirtyBlocker( QgsProject::instance() );

bool returnCode = false;
std::unique_ptr< QgsProjectDirtyBlocker > dirtyBlocker = qgis::make_unique< QgsProjectDirtyBlocker >( QgsProject::instance() );
QObject connectionScope; // manually control scope of layersChanged lambda connection - we need the connection automatically destroyed when this function finishes
bool badLayersHandled = false;
connect( mAppBadLayersHandler, &QgsHandleBadLayersHandler::layersChanged, &connectionScope, [&badLayersHandled] { badLayersHandled = true; } );

// close the previous opened project if any
closeProject();
@@ -5849,107 +5855,120 @@ bool QgisApp::addProject( const QString &projectFile )
QgsProject::instance()->setFileName( projectFile );
QgsProject::instance()->setDirty( true );
mProjectLastModified = QgsProject::instance()->lastModified();
return true;
returnCode = true;
}
else
{
mMapCanvas->freeze( false );
mMapCanvas->refresh();
returnCode = false;
}

mMapCanvas->freeze( false );
mMapCanvas->refresh();
return false;
}
else
{

mProjectLastModified = QgsProject::instance()->lastModified();
mProjectLastModified = QgsProject::instance()->lastModified();

setTitleBarText_( *this );
int myRedInt = QgsProject::instance()->readNumEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorRedPart" ), 255 );
int myGreenInt = QgsProject::instance()->readNumEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorGreenPart" ), 255 );
int myBlueInt = QgsProject::instance()->readNumEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorBluePart" ), 255 );
QColor myColor = QColor( myRedInt, myGreenInt, myBlueInt );
mOverviewCanvas->setBackgroundColor( myColor );
setTitleBarText_( *this );
int myRedInt = QgsProject::instance()->readNumEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorRedPart" ), 255 );
int myGreenInt = QgsProject::instance()->readNumEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorGreenPart" ), 255 );
int myBlueInt = QgsProject::instance()->readNumEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorBluePart" ), 255 );
QColor myColor = QColor( myRedInt, myGreenInt, myBlueInt );
mOverviewCanvas->setBackgroundColor( myColor );

applyProjectSettingsToCanvas( mMapCanvas );
applyProjectSettingsToCanvas( mMapCanvas );

//load project scales
bool projectScales = QgsProject::instance()->readBoolEntry( QStringLiteral( "Scales" ), QStringLiteral( "/useProjectScales" ) );
if ( projectScales )
{
mScaleWidget->updateScales( QgsProject::instance()->readListEntry( QStringLiteral( "Scales" ), QStringLiteral( "/ScalesList" ) ) );
}
//load project scales
bool projectScales = QgsProject::instance()->readBoolEntry( QStringLiteral( "Scales" ), QStringLiteral( "/useProjectScales" ) );
if ( projectScales )
{
mScaleWidget->updateScales( QgsProject::instance()->readListEntry( QStringLiteral( "Scales" ), QStringLiteral( "/ScalesList" ) ) );
}

mMapCanvas->updateScale();
QgsDebugMsg( QStringLiteral( "Scale restored..." ) );
mMapCanvas->updateScale();
QgsDebugMsg( QStringLiteral( "Scale restored..." ) );

mActionFilterLegend->setChecked( QgsProject::instance()->readBoolEntry( QStringLiteral( "Legend" ), QStringLiteral( "filterByMap" ) ) );
mActionFilterLegend->setChecked( QgsProject::instance()->readBoolEntry( QStringLiteral( "Legend" ), QStringLiteral( "filterByMap" ) ) );

// Select the first layer
if ( mLayerTreeView->layerTreeModel()->rootGroup()->findLayers().count() > 0 )
{
mLayerTreeView->setCurrentLayer( mLayerTreeView->layerTreeModel()->rootGroup()->findLayers().at( 0 )->layer() );
}
// Select the first layer
if ( mLayerTreeView->layerTreeModel()->rootGroup()->findLayers().count() > 0 )
{
mLayerTreeView->setCurrentLayer( mLayerTreeView->layerTreeModel()->rootGroup()->findLayers().at( 0 )->layer() );
}

QgsSettings settings;
QgsSettings settings;

#ifdef WITH_BINDINGS
// does the project have any macros?
if ( mPythonUtils && mPythonUtils->isEnabled() )
{
if ( !QgsProject::instance()->readEntry( QStringLiteral( "Macros" ), QStringLiteral( "/pythonCode" ), QString() ).isEmpty() )
// does the project have any macros?
if ( mPythonUtils && mPythonUtils->isEnabled() )
{
int enableMacros = settings.value( QStringLiteral( "qgis/enableMacros" ), 1 ).toInt();
// 0 = never, 1 = ask, 2 = just for this session, 3 = always

if ( enableMacros == 3 || enableMacros == 2 )
if ( !QgsProject::instance()->readEntry( QStringLiteral( "Macros" ), QStringLiteral( "/pythonCode" ), QString() ).isEmpty() )
{
enableProjectMacros();
}
else if ( enableMacros == 1 ) // ask
{
// create the notification widget for macros
int enableMacros = settings.value( QStringLiteral( "qgis/enableMacros" ), 1 ).toInt();
// 0 = never, 1 = ask, 2 = just for this session, 3 = always

if ( enableMacros == 3 || enableMacros == 2 )
{
enableProjectMacros();
}
else if ( enableMacros == 1 ) // ask
{
// create the notification widget for macros

QToolButton *btnEnableMacros = new QToolButton();
btnEnableMacros->setText( tr( "Enable Macros" ) );
btnEnableMacros->setStyleSheet( QStringLiteral( "background-color: rgba(255, 255, 255, 0); color: black; text-decoration: underline;" ) );
btnEnableMacros->setCursor( Qt::PointingHandCursor );
btnEnableMacros->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );

QgsMessageBarItem *macroMsg = new QgsMessageBarItem(
tr( "Security warning" ),
tr( "project macros have been disabled." ),
btnEnableMacros,
Qgis::Warning,
0,
mInfoBar );
QToolButton *btnEnableMacros = new QToolButton();
btnEnableMacros->setText( tr( "Enable Macros" ) );
btnEnableMacros->setStyleSheet( QStringLiteral( "background-color: rgba(255, 255, 255, 0); color: black; text-decoration: underline;" ) );
btnEnableMacros->setCursor( Qt::PointingHandCursor );
btnEnableMacros->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Preferred );

connect( btnEnableMacros, &QToolButton::clicked, this, [this, macroMsg]
{
enableProjectMacros();
mInfoBar->popWidget( macroMsg );
} );
QgsMessageBarItem *macroMsg = new QgsMessageBarItem(
tr( "Security warning" ),
tr( "project macros have been disabled." ),
btnEnableMacros,
Qgis::Warning,
0,
mInfoBar );

connect( btnEnableMacros, &QToolButton::clicked, this, [this, macroMsg]
{
enableProjectMacros();
mInfoBar->popWidget( macroMsg );
} );

// display the macros notification widget
mInfoBar->pushItem( macroMsg );
// display the macros notification widget
mInfoBar->pushItem( macroMsg );
}
}
}
}
#endif

emit projectRead(); // let plug-ins know that we've read in a new
// project so that they can check any project
// specific plug-in state
emit projectRead(); // let plug-ins know that we've read in a new
// project so that they can check any project
// specific plug-in state

// add this to the list of recently used project files
saveRecentProjectPath( false );
// add this to the list of recently used project files
saveRecentProjectPath( false );

QApplication::restoreOverrideCursor();
QApplication::restoreOverrideCursor();

if ( autoSetupOnFirstLayer )
mLayerTreeCanvasBridge->setAutoSetupOnFirstLayer( true );
if ( autoSetupOnFirstLayer )
mLayerTreeCanvasBridge->setAutoSetupOnFirstLayer( true );

mMapCanvas->freeze( false );
mMapCanvas->refresh();
mMapCanvas->freeze( false );
mMapCanvas->refresh();

mStatusBar->showMessage( tr( "Project loaded" ), 3000 );
return true;
mStatusBar->showMessage( tr( "Project loaded" ), 3000 );
returnCode = true;
}

if ( badLayersHandled )
{
dirtyBlocker.reset(); // allow project dirtying again
QgsProject::instance()->setDirty( true );
}

return returnCode;
} // QgisApp::addProject(QString projectFile)


@@ -105,6 +105,7 @@ class QgsGeometryValidationDock;
class QgsGeometryValidationModel;
class QgsUserProfileManagerWidgetFactory;
class Qgs3DMapCanvasDockWidget;
class QgsHandleBadLayersHandler;

class QDomDocument;
class QNetworkReply;
@@ -2310,6 +2311,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
std::unique_ptr<QgsGeometryValidationService> mGeometryValidationService;
QgsGeometryValidationModel *mGeometryValidationModel = nullptr;
QgsGeometryValidationDock *mGeometryValidationDock = nullptr;
QgsHandleBadLayersHandler *mAppBadLayersHandler = nullptr;

friend class TestQgisAppPython;
friend class QgisAppInterface;
@@ -57,7 +57,12 @@ void QgsHandleBadLayersHandler::handleBadLayers( const QList<QDomNode> &layers )
Qgis::Warning, QgisApp::instance()->messageTimeout() );

if ( dialog->layerCount() > 0 )
dialog->exec();
{
if ( dialog->exec() == dialog->Accepted )
{
emit layersChanged();
}
}

delete dialog;
QApplication::restoreOverrideCursor();
@@ -32,6 +32,15 @@ class APP_EXPORT QgsHandleBadLayersHandler

//! Implementation of the handler
void handleBadLayers( const QList<QDomNode> &layers ) override;

signals:

/**
* Emitted when layers have changed
* \since QGIS 3.6
*/
void layersChanged();

};


0 comments on commit 8c07c99

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