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 }
0 commit comments