mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-09 00:08:52 -04:00
A few UX enhancements for error reporting on GPKGs
This fixes #36574 by showing an error in the data items when the layer cannot be opened. In the same way, similar errors now bubble up to the message bar from data source select dialog.
This commit is contained in:
parent
62bd026743
commit
cd4785de9e
@ -138,6 +138,13 @@ Emitted when a progress dialog is shown by the provider dialog
|
|||||||
Emitted when the ok/add buttons should be enabled/disabled
|
Emitted when the ok/add buttons should be enabled/disabled
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
void pushMessage( const QString &title, const QString &message, const Qgis::MessageLevel level = Qgis::MessageLevel::Info );
|
||||||
|
%Docstring
|
||||||
|
Emitted when a ``message`` with ``title`` and ``level`` must be shown to the user using the parent visible message bar
|
||||||
|
|
||||||
|
.. versionadded:: 3.14
|
||||||
|
%End
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -15865,7 +15865,7 @@ void QgisApp::onLayerError( const QString &msg )
|
|||||||
|
|
||||||
Q_ASSERT( layer );
|
Q_ASSERT( layer );
|
||||||
|
|
||||||
mInfoBar->pushCritical( tr( "Layer %1" ).arg( layer->name() ), msg );
|
visibleMessageBar()->pushCritical( tr( "Layer %1" ).arg( layer->name() ), msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QgisApp::gestureEvent( QGestureEvent *event )
|
bool QgisApp::gestureEvent( QGestureEvent *event )
|
||||||
|
@ -112,6 +112,8 @@ QgsGeoPackageCollectionItem::QgsGeoPackageCollectionItem( QgsDataItem *parent, c
|
|||||||
QVector<QgsDataItem *> QgsGeoPackageCollectionItem::createChildren()
|
QVector<QgsDataItem *> QgsGeoPackageCollectionItem::createChildren()
|
||||||
{
|
{
|
||||||
QVector<QgsDataItem *> children;
|
QVector<QgsDataItem *> children;
|
||||||
|
try
|
||||||
|
{
|
||||||
const auto layers = QgsOgrLayerItem::subLayers( mPath.remove( QLatin1String( "gpkg:/" ) ), QStringLiteral( "GPKG" ) );
|
const auto layers = QgsOgrLayerItem::subLayers( mPath.remove( QLatin1String( "gpkg:/" ) ), QStringLiteral( "GPKG" ) );
|
||||||
for ( const QgsOgrDbLayerInfo *info : layers )
|
for ( const QgsOgrDbLayerInfo *info : layers )
|
||||||
{
|
{
|
||||||
@ -135,6 +137,11 @@ QVector<QgsDataItem *> QgsGeoPackageCollectionItem::createChildren()
|
|||||||
children.append( new QgsProjectItem( this, projectName, QgsGeoPackageProjectStorage::encodeUri( projectUri ) ) );
|
children.append( new QgsProjectItem( this, projectName, QgsGeoPackageProjectStorage::encodeUri( projectUri ) ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch ( QgsOgrLayerNotValidException &ex )
|
||||||
|
{
|
||||||
|
children.append( new QgsErrorItem( this, ex.what(), mPath + "/error" ) );
|
||||||
|
}
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,11 +107,7 @@ QList<QgsOgrDbLayerInfo *> QgsOgrLayerItem::subLayers( const QString &path, cons
|
|||||||
// Vector layers
|
// Vector layers
|
||||||
const QgsVectorLayer::LayerOptions layerOptions { QgsProject::instance()->transformContext() };
|
const QgsVectorLayer::LayerOptions layerOptions { QgsProject::instance()->transformContext() };
|
||||||
QgsVectorLayer layer( path, QStringLiteral( "ogr_tmp" ), QStringLiteral( "ogr" ), layerOptions );
|
QgsVectorLayer layer( path, QStringLiteral( "ogr_tmp" ), QStringLiteral( "ogr" ), layerOptions );
|
||||||
if ( ! layer.isValid( ) )
|
if ( layer.isValid( ) )
|
||||||
{
|
|
||||||
QgsDebugMsgLevel( QStringLiteral( "Layer is not a valid %1 Vector layer %2" ).arg( path ), 3 );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// Collect mixed-geom layers
|
// Collect mixed-geom layers
|
||||||
QMultiMap<int, QStringList> subLayersMap;
|
QMultiMap<int, QStringList> subLayersMap;
|
||||||
@ -188,6 +184,7 @@ QList<QgsOgrDbLayerInfo *> QgsOgrLayerItem::subLayers( const QString &path, cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Raster layers
|
// Raster layers
|
||||||
QgsRasterLayer::LayerOptions options;
|
QgsRasterLayer::LayerOptions options;
|
||||||
options.loadDefaultStyle = false;
|
options.loadDefaultStyle = false;
|
||||||
@ -200,7 +197,7 @@ QList<QgsOgrDbLayerInfo *> QgsOgrLayerItem::subLayers( const QString &path, cons
|
|||||||
// Split on ':' since this is what comes out from the provider
|
// Split on ':' since this is what comes out from the provider
|
||||||
QStringList pieces = uri.split( ':' );
|
QStringList pieces = uri.split( ':' );
|
||||||
QString name = pieces.value( pieces.length() - 1 );
|
QString name = pieces.value( pieces.length() - 1 );
|
||||||
QgsDebugMsgLevel( QStringLiteral( "Adding GeoPackage Raster item %1 %2 %3" ).arg( name, uri ), 3 );
|
QgsDebugMsgLevel( QStringLiteral( "Adding GeoPackage Raster item %1 %2" ).arg( name, uri ), 3 );
|
||||||
children.append( new QgsOgrDbLayerInfo( path, uri, name, QString(), QStringLiteral( "Raster" ), QgsLayerItem::LayerType::Raster ) );
|
children.append( new QgsOgrDbLayerInfo( path, uri, name, QString(), QStringLiteral( "Raster" ), QgsLayerItem::LayerType::Raster ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,6 +235,24 @@ QList<QgsOgrDbLayerInfo *> QgsOgrLayerItem::subLayers( const QString &path, cons
|
|||||||
children.append( new QgsOgrDbLayerInfo( path, uri, name, QString(), QStringLiteral( "Raster" ), QgsLayerItem::LayerType::Raster ) );
|
children.append( new QgsOgrDbLayerInfo( path, uri, name, QString(), QStringLiteral( "Raster" ), QgsLayerItem::LayerType::Raster ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// There were problems in reading the file: throw
|
||||||
|
if ( ! layer.isValid() && ! rlayer.isValid() )
|
||||||
|
{
|
||||||
|
QString errorMessage;
|
||||||
|
// If it is file based and the file exists, there might be a permission error, let's change
|
||||||
|
// the message to give the user a hint about this possiblity.
|
||||||
|
if ( QFile::exists( path ) )
|
||||||
|
{
|
||||||
|
errorMessage = tr( "Error opening file, check file and directory permissions on\n%1" ).arg( path );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errorMessage = tr( "Layer is not valid (%1)" ).arg( path );
|
||||||
|
}
|
||||||
|
throw QgsOgrLayerNotValidException( errorMessage );
|
||||||
|
}
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +55,20 @@ class CORE_EXPORT QgsOgrDbLayerInfo
|
|||||||
QgsLayerItem::LayerType mLayerType = QgsLayerItem::LayerType::NoType;
|
QgsLayerItem::LayerType mLayerType = QgsLayerItem::LayerType::NoType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The QgsOgrLayerException class is thrown by QgsOgrLayerItem when the layer is not valid
|
||||||
|
*/
|
||||||
|
class CORE_EXPORT QgsOgrLayerNotValidException: public QgsException
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for QgsOgrLayerNotValidException, with the specified error \a message.
|
||||||
|
*/
|
||||||
|
QgsOgrLayerNotValidException( const QString &message )
|
||||||
|
: QgsException( message )
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
class CORE_EXPORT QgsOgrLayerItem final: public QgsLayerItem
|
class CORE_EXPORT QgsOgrLayerItem final: public QgsLayerItem
|
||||||
{
|
{
|
||||||
@ -63,7 +77,11 @@ class CORE_EXPORT QgsOgrLayerItem final: public QgsLayerItem
|
|||||||
QgsOgrLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri, LayerType layerType, bool isSubLayer = false );
|
QgsOgrLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri, LayerType layerType, bool isSubLayer = false );
|
||||||
|
|
||||||
QString layerName() const override;
|
QString layerName() const override;
|
||||||
//! Retrieve sub layers from a DB ogr layer \a path with the specified \a driver
|
|
||||||
|
/**
|
||||||
|
* Retrieve sub layers from a DB ogr layer \a path with the specified \a driver
|
||||||
|
* If the layer is not valid, throw a std::exception
|
||||||
|
*/
|
||||||
static QList<QgsOgrDbLayerInfo *> subLayers( const QString &path, const QString &driver );
|
static QList<QgsOgrDbLayerInfo *> subLayers( const QString &path, const QString &driver );
|
||||||
//! Returns a LayerType from a geometry type string
|
//! Returns a LayerType from a geometry type string
|
||||||
static QgsLayerItem::LayerType layerTypeFromDb( const QString &geometryType );
|
static QgsLayerItem::LayerType layerTypeFromDb( const QString &geometryType );
|
||||||
|
@ -358,6 +358,8 @@ void QgsVectorLayerSaveAsDialog::accept()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( mActionOnExistingFile == QgsVectorFileWriter::CreateOrOverwriteFile )
|
else if ( mActionOnExistingFile == QgsVectorFileWriter::CreateOrOverwriteFile )
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
const QList<QgsOgrDbLayerInfo *> subLayers = QgsOgrLayerItem::subLayers( filename(), format() );
|
const QList<QgsOgrDbLayerInfo *> subLayers = QgsOgrLayerItem::subLayers( filename(), format() );
|
||||||
QStringList layerList;
|
QStringList layerList;
|
||||||
@ -379,6 +381,14 @@ void QgsVectorLayerSaveAsDialog::accept()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch ( QgsOgrLayerNotValidException &ex )
|
||||||
|
{
|
||||||
|
QMessageBox::critical( this,
|
||||||
|
tr( "Save Vector Layer As" ),
|
||||||
|
tr( "Error opening destination file: %1" ).arg( ex.what() ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QgsSettings settings;
|
QgsSettings settings;
|
||||||
settings.setValue( QStringLiteral( "UI/lastVectorFileFilterDir" ), QFileInfo( filename() ).absolutePath() );
|
settings.setValue( QStringLiteral( "UI/lastVectorFileFilterDir" ), QFileInfo( filename() ).absolutePath() );
|
||||||
|
@ -332,6 +332,9 @@ void QgsOgrDbSourceSelect::btnConnect_clicked()
|
|||||||
QgsOgrDbConnection conn( subKey, ogrDriverName() );
|
QgsOgrDbConnection conn( subKey, ogrDriverName() );
|
||||||
|
|
||||||
mPath = conn.path();
|
mPath = conn.path();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
const QList<QgsOgrDbLayerInfo *> layers = QgsOgrLayerItem::subLayers( mPath, ogrDriverName() );
|
const QList<QgsOgrDbLayerInfo *> layers = QgsOgrLayerItem::subLayers( mPath, ogrDriverName() );
|
||||||
|
|
||||||
QModelIndex rootItemIndex = mTableModel.indexFromItem( mTableModel.invisibleRootItem() );
|
QModelIndex rootItemIndex = mTableModel.indexFromItem( mTableModel.invisibleRootItem() );
|
||||||
@ -368,6 +371,11 @@ void QgsOgrDbSourceSelect::btnConnect_clicked()
|
|||||||
QgsOgrDbConnection::setSelectedConnection( subKey, ogrDriverName() );
|
QgsOgrDbConnection::setSelectedConnection( subKey, ogrDriverName() );
|
||||||
qDeleteAll( layers );
|
qDeleteAll( layers );
|
||||||
}
|
}
|
||||||
|
catch ( QgsOgrLayerNotValidException &ex )
|
||||||
|
{
|
||||||
|
pushMessage( tr( "Error opening layer" ), ex.what(), Qgis::MessageLevel::Critical );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void QgsOgrDbSourceSelect::setSql( const QModelIndex &index )
|
void QgsOgrDbSourceSelect::setSql( const QModelIndex &index )
|
||||||
|
@ -142,6 +142,12 @@ class GUI_EXPORT QgsAbstractDataSourceWidget : public QDialog
|
|||||||
//! Emitted when the ok/add buttons should be enabled/disabled
|
//! Emitted when the ok/add buttons should be enabled/disabled
|
||||||
void enableButtons( bool enable );
|
void enableButtons( bool enable );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when a \a message with \a title and \a level must be shown to the user using the parent visible message bar
|
||||||
|
* \since QGIS 3.14
|
||||||
|
*/
|
||||||
|
void pushMessage( const QString &title, const QString &message, const Qgis::MessageLevel level = Qgis::MessageLevel::Info );
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -166,10 +166,10 @@ void QgsDataSourceManagerDialog::addProviderDialog( QgsAbstractDataSourceWidget
|
|||||||
void QgsDataSourceManagerDialog::makeConnections( QgsAbstractDataSourceWidget *dlg, const QString &providerKey )
|
void QgsDataSourceManagerDialog::makeConnections( QgsAbstractDataSourceWidget *dlg, const QString &providerKey )
|
||||||
{
|
{
|
||||||
// DB
|
// DB
|
||||||
connect( dlg, SIGNAL( addDatabaseLayers( QStringList const &, QString const & ) ),
|
connect( dlg, &QgsAbstractDataSourceWidget::addDatabaseLayers,
|
||||||
this, SIGNAL( addDatabaseLayers( QStringList const &, QString const & ) ) );
|
this, &QgsDataSourceManagerDialog::addDatabaseLayers );
|
||||||
connect( dlg, SIGNAL( progressMessage( QString ) ),
|
connect( dlg, &QgsAbstractDataSourceWidget::progressMessage,
|
||||||
this, SIGNAL( showStatusMessage( QString ) ) );
|
this, &QgsDataSourceManagerDialog::showStatusMessage );
|
||||||
// Vector
|
// Vector
|
||||||
connect( dlg, &QgsAbstractDataSourceWidget::addVectorLayer, this, [ = ]( const QString & vectorLayerPath, const QString & baseName, const QString & specifiedProvider )
|
connect( dlg, &QgsAbstractDataSourceWidget::addVectorLayer, this, [ = ]( const QString & vectorLayerPath, const QString & baseName, const QString & specifiedProvider )
|
||||||
{
|
{
|
||||||
@ -179,20 +179,29 @@ void QgsDataSourceManagerDialog::makeConnections( QgsAbstractDataSourceWidget *d
|
|||||||
);
|
);
|
||||||
connect( dlg, &QgsAbstractDataSourceWidget::addVectorLayers,
|
connect( dlg, &QgsAbstractDataSourceWidget::addVectorLayers,
|
||||||
this, &QgsDataSourceManagerDialog::vectorLayersAdded );
|
this, &QgsDataSourceManagerDialog::vectorLayersAdded );
|
||||||
connect( dlg, SIGNAL( connectionsChanged() ), this, SIGNAL( connectionsChanged() ) );
|
connect( dlg, &QgsAbstractDataSourceWidget::connectionsChanged, this, &QgsDataSourceManagerDialog::connectionsChanged );
|
||||||
// Raster
|
// Raster
|
||||||
connect( dlg, SIGNAL( addRasterLayer( QString const &, QString const &, QString const & ) ),
|
connect( dlg, &QgsAbstractDataSourceWidget::addRasterLayer,
|
||||||
this, SIGNAL( addRasterLayer( QString const &, QString const &, QString const & ) ) );
|
this, [ = ]( const QString & uri, const QString & baseName, const QString & providerKey )
|
||||||
|
{
|
||||||
|
addRasterLayer( uri, baseName, providerKey );
|
||||||
|
} );
|
||||||
// Mesh
|
// Mesh
|
||||||
connect( dlg, &QgsAbstractDataSourceWidget::addMeshLayer, this, &QgsDataSourceManagerDialog::addMeshLayer );
|
connect( dlg, &QgsAbstractDataSourceWidget::addMeshLayer, this, &QgsDataSourceManagerDialog::addMeshLayer );
|
||||||
// Vector tile
|
// Vector tile
|
||||||
connect( dlg, &QgsAbstractDataSourceWidget::addVectorTileLayer, this, &QgsDataSourceManagerDialog::addVectorTileLayer );
|
connect( dlg, &QgsAbstractDataSourceWidget::addVectorTileLayer, this, &QgsDataSourceManagerDialog::addVectorTileLayer );
|
||||||
// Virtual
|
// Virtual
|
||||||
connect( dlg, SIGNAL( replaceVectorLayer( QString, QString, QString, QString ) ),
|
connect( dlg, &QgsAbstractDataSourceWidget::replaceVectorLayer,
|
||||||
this, SIGNAL( replaceSelectedVectorLayer( QString, QString, QString, QString ) ) );
|
this, &QgsDataSourceManagerDialog::replaceSelectedVectorLayer );
|
||||||
// Common
|
// Common
|
||||||
connect( dlg, SIGNAL( connectionsChanged() ), this, SIGNAL( connectionsChanged() ) );
|
connect( dlg, &QgsAbstractDataSourceWidget::connectionsChanged, this, &QgsDataSourceManagerDialog::connectionsChanged );
|
||||||
connect( this, SIGNAL( providerDialogsRefreshRequested() ), dlg, SLOT( refresh() ) );
|
connect( this, &QgsDataSourceManagerDialog::providerDialogsRefreshRequested, dlg, &QgsAbstractDataSourceWidget::refresh );
|
||||||
|
|
||||||
|
// Message
|
||||||
|
connect( dlg, &QgsAbstractDataSourceWidget::pushMessage, this, [ = ]( const QString & title, const QString & message, const Qgis::MessageLevel level )
|
||||||
|
{
|
||||||
|
mMessageBar->pushMessage( title, message, level );
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsDataSourceManagerDialog::showEvent( QShowEvent *e )
|
void QgsDataSourceManagerDialog::showEvent( QShowEvent *e )
|
||||||
|
Loading…
x
Reference in New Issue
Block a user