diff --git a/app/activeproject.cpp b/app/activeproject.cpp index 77060f0f6..f9b60fe65 100644 --- a/app/activeproject.cpp +++ b/app/activeproject.cpp @@ -300,7 +300,19 @@ bool ActiveProject::validateProject() if ( !layer->isValid() ) { errorsFound = true; - CoreUtils::log( QStringLiteral( "Project load" ), QStringLiteral( "Invalid layer %1" ).arg( layer->name() ) ); + QgsError layerError = layer->error(); + QString reason; + + if ( !layerError.isEmpty() ) + { + reason = layerError.summary(); + } + else if ( layer->dataProvider() ) + { + reason = layer->dataProvider()->error().summary(); + } + + CoreUtils::log( QStringLiteral( "Project load" ), QStringLiteral( "Invalid layer %1: %2" ).arg( layer->name(), reason ) ); emit reportIssue( tr( "Layer" ) + ": " + layer->name(), tr( "Unable to load source " ) + ": " + layer->publicSource() ); } else diff --git a/app/layer/layerdetaildata.cpp b/app/layer/layerdetaildata.cpp index cdd49a0a5..675716904 100644 --- a/app/layer/layerdetaildata.cpp +++ b/app/layer/layerdetaildata.cpp @@ -14,6 +14,7 @@ #include "qgslegendsettings.h" #include "qgslayertreemodel.h" +#include "coreutils.h" #include "mmstyle.h" LayerDetailData::LayerDetailData( QObject *parent ) @@ -39,6 +40,7 @@ void LayerDetailData::setLayerTreeNode( QgsLayerTreeNode *newLayerTreeNode ) mName = QString(); mLayerId = QString(); mIsVisible = false; + mIsValid = false; mIsSpatial = false; mIsVectorLayer = false; @@ -50,6 +52,7 @@ void LayerDetailData::setLayerTreeNode( QgsLayerTreeNode *newLayerTreeNode ) emit nameChanged( mName ); emit layerIdChanged( mLayerId ); emit isVisibleChanged( mIsVisible ); + emit isValidChanged( mIsValid ); emit isSpatialChanged( mIsSpatial ); emit isVectorLayerChanged( mIsVectorLayer ); emit vectorLayerChanged( nullptr ); @@ -64,6 +67,7 @@ void LayerDetailData::setLayerTreeNode( QgsLayerTreeNode *newLayerTreeNode ) emit nameChanged( mName ); emit layerIdChanged( mLayerId ); emit isVisibleChanged( mIsVisible ); + emit isValidChanged( mIsValid ); emit isSpatialChanged( mIsSpatial ); emit isVectorLayerChanged( mIsVectorLayer ); emit vectorLayerChanged( nullptr ); @@ -80,6 +84,18 @@ void LayerDetailData::setLayerTreeNode( QgsLayerTreeNode *newLayerTreeNode ) mLayerId = nodeLayer->layerId(); emit layerIdChanged( mLayerId ); + mIsValid = nodeLayer->layer()->isValid(); + emit isValidChanged( mIsValid ); + + // Log invalid layers + if ( !mIsValid ) + { + QgsError layerError = nodeLayer->layer()->error(); + const QString reason = !layerError.isEmpty() ? layerError.summary() + : ( nodeLayer->layer()->dataProvider() ? nodeLayer->layer()->dataProvider()->error().summary() : QString() ); + CoreUtils::log( QStringLiteral( "Layer detail" ), QStringLiteral( "Opened invalid layer %1: %2" ).arg( mName, reason ) ); + } + mIsSpatial = nodeLayer->layer()->isSpatial(); emit isSpatialChanged( mIsSpatial ); @@ -192,6 +208,11 @@ bool LayerDetailData::isVisible() const return mIsVisible; } +bool LayerDetailData::isValid() const +{ + return mIsValid; +} + QgsLegendRenderer *LayerDetailData::legendRenderer() const { return mLegendRenderer.get(); diff --git a/app/layer/layerdetaildata.h b/app/layer/layerdetaildata.h index 2b878c1de..3a2faaf3f 100644 --- a/app/layer/layerdetaildata.h +++ b/app/layer/layerdetaildata.h @@ -27,6 +27,7 @@ class LayerDetailData : public QObject Q_PROPERTY( QString name READ name NOTIFY nameChanged ) Q_PROPERTY( QString layerId READ layerId NOTIFY layerIdChanged ) Q_PROPERTY( bool isVisible READ isVisible NOTIFY isVisibleChanged ) + Q_PROPERTY( bool isValid READ isValid NOTIFY isValidChanged ) Q_PROPERTY( bool isSpatial READ isSpatial NOTIFY isSpatialChanged ) Q_PROPERTY( bool isVectorLayer READ isVectorLayer NOTIFY isVectorLayerChanged ) Q_PROPERTY( QgsVectorLayer *vectorLayer READ vectorLayer NOTIFY vectorLayerChanged ) @@ -40,6 +41,7 @@ class LayerDetailData : public QObject void setLayerTreeNode( QgsLayerTreeNode *newLayerTreeNode ); bool isVisible() const; + bool isValid() const; bool isSpatial() const; bool isVectorLayer() const; const QString &name() const; @@ -54,6 +56,7 @@ class LayerDetailData : public QObject signals: void isSpatialChanged( bool showLegned ); void isVisibleChanged( bool isVisible ); + void isValidChanged( bool isValid ); void isVectorLayerChanged( bool isVectorLayer ); void nameChanged( const QString &name ); void layerIdChanged( const QString &layerId ); @@ -69,6 +72,7 @@ class LayerDetailData : public QObject QString mLayerId; bool mIsSpatial = false; bool mIsVisible = false; + bool mIsValid = false; bool mIsVectorLayer = false; }; diff --git a/app/layerfeaturesmodel.cpp b/app/layerfeaturesmodel.cpp index b7f39cf55..f4ca75b5b 100644 --- a/app/layerfeaturesmodel.cpp +++ b/app/layerfeaturesmodel.cpp @@ -91,7 +91,7 @@ void LayerFeaturesModel::populate() { cancelPendingRequests(); - if ( mLayer && mLayer->dataProvider() ) + if ( mLayer && mLayer->isValid() && mLayer->dataProvider() ) { mFetchingResults = true; emit fetchingResultsChanged( mFetchingResults ); diff --git a/app/qml/layers/MMLayerDetailPage.qml b/app/qml/layers/MMLayerDetailPage.qml index 9f29d5dc8..5a91efcef 100644 --- a/app/qml/layers/MMLayerDetailPage.qml +++ b/app/qml/layers/MMLayerDetailPage.qml @@ -56,6 +56,31 @@ Page { interactive: layerDetailData.isVectorLayer } + Component { + id: layerUnavailablePageComponent + + MMComponents.MMPage { + id: layerUnavailablePage + + pageHeader.title: layerDetailData.name + onBackClicked: root.closePage() + + pageContent: Item { + width: parent.width + height: parent.height + + MMComponents.MMMessage { + anchors.centerIn: parent + width: parent.width - 2 * __style.margin20 + + image: __style.negativeMMSymbolImage + title: qsTr( "Layer unavailable" ) + description: qsTr( "This layer couldn't be loaded. Check your connection or contact your administrator." ) + } + } + } + } + Component { id: layerDetailPageComponent @@ -283,6 +308,11 @@ Page { // * there is an exception, we do not want to show features of the map sketches layer // + if ( !layerDetailData.isValid ) { + content.addItem( layerUnavailablePageComponent.createObject( content ) ) + return + } + const isSketchingLayer = layerDetailData.layerId === __activeProject.mapSketchesLayerId() if ( layerDetailData.isVectorLayer && !isSketchingLayer ) {