Skip to content

Commit 66f5f54

Browse files
committed
[browser] Add missing delete actions for more file types
1 parent e4b52a4 commit 66f5f54

File tree

4 files changed

+158
-7
lines changed

4 files changed

+158
-7
lines changed

src/providers/ogr/qgsgeopackagedataitems.cpp

+60-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ QWidget *QgsGeoPackageRootItem::paramWidget()
172172

173173
QList<QAction *> QgsGeoPackageCollectionItem::actions( QWidget *parent )
174174
{
175-
QList<QAction *> lst;
175+
QList<QAction *> lst = QgsDataCollectionItem::actions( parent );
176176

177177
if ( QgsOgrDbConnection::connectionList( QStringLiteral( "GPKG" ) ).contains( mName ) )
178178
{
@@ -193,6 +193,24 @@ QList<QAction *> QgsGeoPackageCollectionItem::actions( QWidget *parent )
193193
connect( actionAddTable, &QAction::triggered, this, &QgsGeoPackageCollectionItem::addTable );
194194
lst.append( actionAddTable );
195195

196+
QAction *sep = new QAction( parent );
197+
sep->setSeparator( true );
198+
lst.append( sep );
199+
200+
QString message = QObject::tr( "Delete %1…" ).arg( mName );
201+
QAction *actionDelete = new QAction( message, parent );
202+
203+
// IMPORTANT - we need to capture the stuff we need, and then hand the slot
204+
// off to a static method. This is because it's possible for this item
205+
// to be deleted in the background on us (e.g. by a parent directory refresh)
206+
const QString path = mPath;
207+
QPointer< QgsDataItem > parentItem( mParent );
208+
connect( actionDelete, &QAction::triggered, this, [ path, parentItem ]
209+
{
210+
deleteGpkg( path, parentItem );
211+
} );
212+
lst.append( actionDelete );
213+
196214
// Run VACUUM
197215
QAction *actionVacuumDb = new QAction( tr( "Compact Database (VACUUM)" ), parent );
198216
connect( actionVacuumDb, &QAction::triggered, this, &QgsGeoPackageConnectionItem::vacuumGeoPackageDbAction );
@@ -202,6 +220,47 @@ QList<QAction *> QgsGeoPackageCollectionItem::actions( QWidget *parent )
202220
return lst;
203221
}
204222

223+
void QgsGeoPackageCollectionItem::deleteGpkg( const QString &path, QPointer<QgsDataItem> parent )
224+
{
225+
const QString title = QObject::tr( "Delete GeoPackage" );
226+
// Check if the layer is in the project
227+
const QgsMapLayer *projectLayer = nullptr;
228+
const auto mapLayers = QgsProject::instance()->mapLayers();
229+
for ( auto it = mapLayers.constBegin(); it != mapLayers.constEnd(); ++it )
230+
{
231+
const QVariantMap parts = QgsProviderRegistry::instance()->decodeUri( it.value()->dataProvider()->name(), it.value()->source() );
232+
if ( parts.value( QStringLiteral( "path" ) ).toString() == path )
233+
{
234+
projectLayer = it.value();
235+
}
236+
}
237+
if ( ! projectLayer )
238+
{
239+
const QString confirmMessage = QObject::tr( "Are you sure you want to delete '%1'?" ).arg( path );
240+
241+
if ( QMessageBox::question( nullptr, title,
242+
confirmMessage,
243+
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
244+
return;
245+
246+
if ( !QFile::remove( path ) )
247+
{
248+
QMessageBox::warning( nullptr, title, tr( "Could not delete GeoPackage." ) );
249+
}
250+
else
251+
{
252+
QMessageBox::information( nullptr, title, tr( "GeoPackage deleted successfully." ) );
253+
if ( parent )
254+
parent->refresh();
255+
}
256+
}
257+
else
258+
{
259+
QMessageBox::warning( nullptr, title, QObject::tr( "The GeoPackage '%1' cannot be deleted because it is in the current project as '%2',"
260+
" remove it from the project and retry." ).arg( path, projectLayer->name() ) );
261+
}
262+
}
263+
205264
bool QgsGeoPackageCollectionItem::handleDrop( const QMimeData *data, Qt::DropAction )
206265
{
207266

src/providers/ogr/qgsgeopackagedataitems.h

+2
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ class QgsGeoPackageCollectionItem : public QgsDataCollectionItem
8383
bool acceptDrop() override { return true; }
8484
bool handleDrop( const QMimeData *data, Qt::DropAction action ) override;
8585
QList<QAction *> actions( QWidget *parent ) override;
86+
static void deleteGpkg( const QString &path, QPointer< QgsDataItem > parent );
87+
8688
#endif
8789

8890
//! Returns the layer type from \a geometryType

src/providers/ogr/qgsogrdataitems.cpp

+90-6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "qgsrasterlayer.h"
2525
#include "qgsgeopackagedataitems.h"
2626
#include "qgsogrutils.h"
27+
#include "qgsproviderregistry.h"
2728

2829
#include <QFileInfo>
2930
#include <QTextStream>
@@ -510,6 +511,85 @@ bool QgsOgrDataCollectionItem::createConnection( const QString &name, const QStr
510511
return storeConnection( path, ogrDriverName );
511512
}
512513

514+
#ifdef HAVE_GUI
515+
QList<QAction *> QgsOgrDataCollectionItem::actions( QWidget *parent )
516+
{
517+
QList<QAction *> lst = QgsDataCollectionItem::actions( parent );
518+
519+
const bool isFolder = QFileInfo( mPath ).isDir();
520+
// Messages are different for files and tables
521+
QString message = QObject::tr( "Delete %1 “%2”…" ).arg( isFolder ? tr( "Folder" ) : tr( "File" ), mName );
522+
QAction *actionDeleteLayer = new QAction( message, parent );
523+
524+
// IMPORTANT - we need to capture the stuff we need, and then hand the slot
525+
// off to a static method. This is because it's possible for this item
526+
// to be deleted in the background on us (e.g. by a parent directory refresh)
527+
const QString path = mPath;
528+
QPointer< QgsDataItem > parentItem( mParent );
529+
connect( actionDeleteLayer, &QAction::triggered, this, [ path, parentItem ]
530+
{
531+
deleteCollection( path, parentItem );
532+
} );
533+
lst.append( actionDeleteLayer );
534+
535+
return lst;
536+
}
537+
538+
void QgsOgrDataCollectionItem::deleteCollection( const QString &path, QPointer<QgsDataItem> parent )
539+
{
540+
const bool isFolder = QFileInfo( path ).isDir();
541+
const QString type = isFolder ? tr( "folder" ) : tr( "file" );
542+
const QString typeCaps = isFolder ? tr( "Folder" ) : tr( "File" );
543+
const QString title = QObject::tr( "Delete %1" ).arg( type );
544+
// Check if the layer is in the project
545+
const QgsMapLayer *projectLayer = nullptr;
546+
const auto mapLayers = QgsProject::instance()->mapLayers();
547+
for ( auto it = mapLayers.constBegin(); it != mapLayers.constEnd(); ++it )
548+
{
549+
const QVariantMap parts = QgsProviderRegistry::instance()->decodeUri( it.value()->dataProvider()->name(), it.value()->source() );
550+
if ( parts.value( QStringLiteral( "path" ) ).toString() == path )
551+
{
552+
projectLayer = it.value();
553+
}
554+
}
555+
if ( ! projectLayer )
556+
{
557+
const QString confirmMessage = QObject::tr( "Are you sure you want to delete '%1'?" ).arg( path );
558+
559+
if ( QMessageBox::question( nullptr, title,
560+
confirmMessage,
561+
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
562+
return;
563+
564+
bool res = false;
565+
if ( isFolder )
566+
{
567+
// e.g. the abomination which is gdb
568+
QDir dir( path );
569+
res = dir.removeRecursively();
570+
}
571+
else
572+
{
573+
res = QFile::remove( path );
574+
}
575+
if ( !res )
576+
{
577+
QMessageBox::warning( nullptr, title, tr( "Could not delete %1." ).arg( type ) );
578+
}
579+
else
580+
{
581+
QMessageBox::information( nullptr, title, tr( "%1 deleted successfully." ).arg( typeCaps ) );
582+
if ( parent )
583+
parent->refresh();
584+
}
585+
}
586+
else
587+
{
588+
QMessageBox::warning( nullptr, title, QObject::tr( "The %1 '%2' cannot be deleted because it is in the current project as '%3',"
589+
" remove it from the project and retry." ).arg( type, path, projectLayer->name() ) );
590+
}
591+
}
592+
#endif
513593

514594
// ---------------------------------------------------------------------------
515595

@@ -638,10 +718,14 @@ QgsDataItem *QgsOgrDataItemProvider::createDataItem( const QString &pathIn, QgsD
638718
// with the companion variable (same name) in the gdal provider
639719
// class
640720
// TODO: add more OGR supported multiple layers formats here!
641-
QStringList ogrSupportedDbLayersExtensions;
642-
ogrSupportedDbLayersExtensions << QStringLiteral( "gpkg" ) << QStringLiteral( "sqlite" ) << QStringLiteral( "db" ) << QStringLiteral( "gdb" ) << QStringLiteral( "kml" );
643-
QStringList ogrSupportedDbDriverNames;
644-
ogrSupportedDbDriverNames << QStringLiteral( "GPKG" ) << QStringLiteral( "db" ) << QStringLiteral( "gdb" );
721+
static QStringList sOgrSupportedDbLayersExtensions { QStringLiteral( "gpkg" ),
722+
QStringLiteral( "sqlite" ),
723+
QStringLiteral( "db" ),
724+
QStringLiteral( "gdb" ),
725+
QStringLiteral( "kml" ) };
726+
static QStringList sOgrSupportedDbDriverNames { QStringLiteral( "GPKG" ),
727+
QStringLiteral( "db" ),
728+
QStringLiteral( "gdb" ) };
645729

646730
// Fast track: return item without testing if:
647731
// scanExtSetting or zipfile and scan zip == "Basic scan"
@@ -666,7 +750,7 @@ QgsDataItem *QgsOgrDataItemProvider::createDataItem( const QString &pathIn, QgsD
666750
// Handle collections
667751
// Check if the layer has sublayers by comparing the extension
668752
QgsDataItem *item = nullptr;
669-
if ( ! ogrSupportedDbLayersExtensions.contains( suffix ) )
753+
if ( ! sOgrSupportedDbLayersExtensions.contains( suffix ) )
670754
{
671755
item = new QgsOgrLayerItem( parentItem, name, path, path, QgsLayerItem::Vector );
672756
}
@@ -714,7 +798,7 @@ QgsDataItem *QgsOgrDataItemProvider::createDataItem( const QString &pathIn, QgsD
714798
{
715799
item = new QgsGeoPackageCollectionItem( parentItem, name, path );
716800
}
717-
else if ( numLayers > 1 || ogrSupportedDbDriverNames.contains( driverName ) )
801+
else if ( numLayers > 1 || sOgrSupportedDbDriverNames.contains( driverName ) )
718802
{
719803
item = new QgsOgrDataCollectionItem( parentItem, name, path );
720804
}

src/providers/ogr/qgsogrdataitems.h

+6
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ class QgsOgrDataCollectionItem : public QgsDataCollectionItem
100100
*/
101101
static bool createConnection( const QString &name, const QString &extensions, const QString &ogrDriverName );
102102

103+
#ifdef HAVE_GUI
104+
QList<QAction *> actions( QWidget *parent ) override;
105+
106+
static void deleteCollection( const QString &path, QPointer< QgsDataItem > parent );
107+
#endif
108+
103109
};
104110

105111
//! Provider for OGR root data item

0 commit comments

Comments
 (0)