Skip to content

Commit 5df5c37

Browse files
authored
Merge pull request #8507 from signedav/basicfix
Delete selected tables as DataItem action
2 parents dada301 + 37eec19 commit 5df5c37

16 files changed

+168
-76
lines changed

python/core/auto_generated/qgsbrowsermodel.sip.in

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,19 @@ items, i.e. it does not fetch children.
117117
%End
118118

119119

120+
QModelIndex findUri( const QString &uri, QModelIndex index = QModelIndex() );
121+
%Docstring
122+
Returns index of layer item with given uri. It only searches in currently fetched
123+
items, i.e. it does not fetch children.
124+
125+
:param uri: item uri
126+
:param index: the current index of the parent (to search for children)
127+
128+
:return: model index, invalid if item not found
129+
130+
.. versionadded:: 3.6
131+
%End
132+
120133
void connectItem( QgsDataItem *item ) /Deprecated/;
121134
%Docstring
122135

python/core/auto_generated/qgsdataitem.sip.in

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ Items that return valid URI will be returned in mime data when dragging a select
201201
Fast,
202202
Collapse,
203203
Rename,
204+
Delete,
204205
};
205206
typedef QFlags<QgsDataItem::Capability> Capabilities;
206207

@@ -485,6 +486,11 @@ Returns the string representation of the given ``layerType``
485486
Returns the icon name of the given ``layerType``
486487

487488
.. versionadded:: 3
489+
%End
490+
491+
virtual bool deleteLayer();
492+
%Docstring
493+
Delete this layer item
488494
%End
489495

490496
protected:

src/app/browser/qgsinbuiltdataitemproviders.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "qgsnative.h"
2424
#include "qgisapp.h"
2525
#include "qgsmessagebar.h"
26+
#include "qgsmessagelog.h"
2627
#include "qgsnewnamedialog.h"
2728
#include "qgsbrowsermodel.h"
2829
#include "qgsbrowserdockwidget_p.h"
@@ -390,6 +391,25 @@ void QgsLayerItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *men
390391
} );
391392
menu->addAction( addAction );
392393

394+
if ( item->capabilities2() & QgsDataItem::Delete )
395+
{
396+
QStringList selectedDeletableItemPaths;
397+
for ( QgsDataItem *selectedItem : selectedItems )
398+
{
399+
if ( qobject_cast<QgsLayerItem *>( selectedItem ) && ( selectedItem->capabilities2() & QgsDataItem::Delete ) )
400+
selectedDeletableItemPaths.append( qobject_cast<QgsLayerItem *>( selectedItem )->uri() );
401+
}
402+
403+
const QString deleteText = selectedDeletableItemPaths.count() == 1 ? tr( "Delete Layer" )
404+
: tr( "Delete Selected Layers" );
405+
QAction *deleteAction = new QAction( deleteText, menu );
406+
connect( deleteAction, &QAction::triggered, this, [ = ]
407+
{
408+
deleteLayers( selectedDeletableItemPaths );
409+
} );
410+
menu->addAction( deleteAction );
411+
}
412+
393413
QAction *propertiesAction = new QAction( tr( "Layer Properties…" ), menu );
394414
connect( propertiesAction, &QAction::triggered, this, [ = ]
395415
{
@@ -457,6 +477,22 @@ void QgsLayerItemGuiProvider::addLayersFromItems( const QList<QgsDataItem *> &it
457477
QgisApp::instance()->handleDropUriList( layerUriList );
458478
}
459479

480+
void QgsLayerItemGuiProvider::deleteLayers( const QStringList &itemPaths )
481+
{
482+
for ( const QString &itemPath : itemPaths )
483+
{
484+
//get the item from browserModel by its path
485+
QgsLayerItem *item = qobject_cast<QgsLayerItem *>( QgisApp::instance()->browserModel()->dataItem( QgisApp::instance()->browserModel()->findUri( itemPath ) ) );
486+
if ( !item )
487+
{
488+
QgsMessageLog::logMessage( tr( "Item with path %1 no longer exists." ).arg( itemPath ) );
489+
return;
490+
}
491+
if ( !item->deleteLayer() )
492+
QMessageBox::information( QgisApp::instance(), tr( "Delete Layer" ), tr( "Item Layer %1 cannot be deleted." ).arg( item->name() ) );
493+
}
494+
}
495+
460496
void QgsLayerItemGuiProvider::showPropertiesForItem( QgsLayerItem *item )
461497
{
462498
if ( ! item )

src/app/browser/qgsinbuiltdataitemproviders.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ class QgsLayerItemGuiProvider : public QObject, public QgsDataItemGuiProvider
100100

101101
void addLayersFromItems( const QList<QgsDataItem *> &items );
102102
void showPropertiesForItem( QgsLayerItem *item );
103+
void deleteLayers( const QStringList &itemPath );
103104

104105
};
105106

src/core/qgsbrowsermodel.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,30 @@ QModelIndex QgsBrowserModel::findPath( QAbstractItemModel *model, const QString
371371
return QModelIndex(); // not found
372372
}
373373

374+
QModelIndex QgsBrowserModel::findUri( const QString &uri, QModelIndex index )
375+
{
376+
for ( int i = 0; i < this->rowCount( index ); i++ )
377+
{
378+
QModelIndex idx = this->index( i, 0, index );
379+
380+
if ( qobject_cast<QgsLayerItem *>( dataItem( idx ) ) )
381+
{
382+
QString itemUri = qobject_cast<QgsLayerItem *>( dataItem( idx ) )->uri();
383+
384+
if ( itemUri == uri )
385+
{
386+
QgsDebugMsgLevel( "Arrived " + itemUri, 4 );
387+
return idx; // we have found the item we have been looking for
388+
}
389+
}
390+
391+
QModelIndex childIdx = findUri( uri, idx );
392+
if ( childIdx.isValid() )
393+
return childIdx;
394+
}
395+
return QModelIndex();
396+
}
397+
374398
void QgsBrowserModel::connectItem( QgsDataItem * )
375399
{
376400
// deprecated, no use

src/core/qgsbrowsermodel.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,17 @@ class CORE_EXPORT QgsBrowserModel : public QAbstractItemModel
136136
//! \note not available in Python bindings
137137
static QModelIndex findPath( QAbstractItemModel *model, const QString &path, Qt::MatchFlag matchFlag = Qt::MatchExactly ) SIP_SKIP;
138138

139+
/**
140+
* Returns index of layer item with given uri. It only searches in currently fetched
141+
* items, i.e. it does not fetch children.
142+
* \param uri item uri
143+
* \param index the current index of the parent (to search for children)
144+
* \returns model index, invalid if item not found
145+
*
146+
* \since QGIS 3.6
147+
*/
148+
QModelIndex findUri( const QString &uri, QModelIndex index = QModelIndex() );
149+
139150
/**
140151
* \deprecated Deprecated since QGIS 3.4 -- this method has no effect, and is dangerous to call in earlier QGIS versions. Any usage should be removed (and will have no harmful side-effects!).
141152
*/

src/core/qgsdataitem.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,11 @@ QString QgsLayerItem::iconName( QgsLayerItem::LayerType layerType )
701701
}
702702
}
703703

704+
bool QgsLayerItem::deleteLayer()
705+
{
706+
return false;
707+
}
708+
704709
bool QgsLayerItem::equal( const QgsDataItem *other )
705710
{
706711
//QgsDebugMsg ( mPath + " x " + other->mPath );

src/core/qgsdataitem.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,9 @@ class CORE_EXPORT QgsDataItem : public QObject
210210
SetCrs = 1 << 0, //!< Can set CRS on layer or group of layers
211211
Fertile = 1 << 1, //!< Can create children. Even items without this capability may have children, but cannot create them, it means that children are created by item ancestors.
212212
Fast = 1 << 2, //!< CreateChildren() is fast enough to be run in main thread when refreshing items, most root items (wms,wfs,wcs,postgres...) are considered fast because they are reading data only from QgsSettings
213-
Collapse = 1 << 3, //!< The collapse/expand status for this items children should be ignored in order to avoid undesired network connections (wms etc.)
213+
Collapse = 1 << 3, //!< The collapse/expand status for this items children should be ignored in order to avoid undesired network connections (wms etc.)
214214
Rename = 1 << 4, //!< Item can be renamed
215+
Delete = 1 << 5, //!< Item can be deleted
215216
};
216217
Q_DECLARE_FLAGS( Capabilities, Capability )
217218

@@ -505,6 +506,9 @@ class CORE_EXPORT QgsLayerItem : public QgsDataItem
505506
*/
506507
static QString iconName( LayerType layerType );
507508

509+
//! Delete this layer item
510+
virtual bool deleteLayer();
511+
508512
protected:
509513

510514
//! The provider key

src/providers/mssql/qgsmssqldataitems.cpp

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -561,64 +561,68 @@ QgsMssqlLayerItem::QgsMssqlLayerItem( QgsDataItem *parent, const QString &name,
561561
: QgsLayerItem( parent, name, path, QString(), layerType, QStringLiteral( "mssql" ) )
562562
, mLayerProperty( layerProperty )
563563
{
564+
mCapabilities |= Delete;
564565
mUri = createUri();
565566
setState( Populated );
566567
}
567568

568569
#ifdef HAVE_GUI
569570
QList<QAction *> QgsMssqlLayerItem::actions( QWidget *actionParent )
570571
{
571-
QgsMssqlConnectionItem *connItem = qobject_cast<QgsMssqlConnectionItem *>( parent() ? parent()->parent() : nullptr );
572-
573572
QList<QAction *> lst;
574573

575-
// delete
576-
QAction *actionDeleteLayer = new QAction( tr( "Delete Table" ), actionParent );
577-
connect( actionDeleteLayer, &QAction::triggered, this, [ = ]
578-
{
579-
if ( QMessageBox::question( nullptr, QObject::tr( "Delete Table" ),
580-
QObject::tr( "Are you sure you want to delete [%1].[%2]?" ).arg( mLayerProperty.schemaName, mLayerProperty.tableName ),
581-
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
582-
return;
583-
584-
QString errCause;
585-
bool res = QgsMssqlConnection::dropTable( mUri, &errCause );
586-
if ( !res )
587-
{
588-
QMessageBox::warning( nullptr, tr( "Delete Table" ), errCause );
589-
}
590-
else
591-
{
592-
QMessageBox::information( nullptr, tr( "Delete Table" ), tr( "Table deleted successfully." ) );
593-
if ( connItem )
594-
connItem->refresh();
595-
}
596-
} );
597-
lst.append( actionDeleteLayer );
598-
599574
// truncate
600575
QAction *actionTruncateLayer = new QAction( tr( "Truncate Table" ), actionParent );
601576
connect( actionTruncateLayer, &QAction::triggered, this, [ = ]
602577
{
603-
if ( QMessageBox::question( nullptr, QObject::tr( "Truncate Table" ),
604-
QObject::tr( "Are you sure you want to truncate [%1].[%2]?\n\nThis will delete all data within the table." ).arg( mLayerProperty.schemaName, mLayerProperty.tableName ),
605-
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
606-
return;
607-
608-
QString errCause;
609-
bool res = QgsMssqlConnection::truncateTable( mUri, &errCause );
610-
if ( !res )
611-
{
612-
QMessageBox::warning( nullptr, tr( "Truncate Table" ), errCause );
613-
}
614-
else
615-
{
616-
QMessageBox::information( nullptr, tr( "Truncate Table" ), tr( "Table truncated successfully." ) );
617-
}
578+
truncateTable();
618579
} );
619580
lst.append( actionTruncateLayer );
620581
return lst;
621582
}
583+
584+
bool QgsMssqlLayerItem::deleteLayer()
585+
{
586+
QgsMssqlConnectionItem *connItem = qobject_cast<QgsMssqlConnectionItem *>( parent() ? parent()->parent() : nullptr );
587+
588+
if ( QMessageBox::question( nullptr, QObject::tr( "Delete Table" ),
589+
QObject::tr( "Are you sure you want to delete [%1].[%2]?" ).arg( mLayerProperty.schemaName, mLayerProperty.tableName ),
590+
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
591+
return true;
592+
593+
QString errCause;
594+
bool res = QgsMssqlConnection::dropTable( mUri, &errCause );
595+
if ( !res )
596+
{
597+
QMessageBox::warning( nullptr, tr( "Delete Table" ), errCause );
598+
}
599+
else
600+
{
601+
QMessageBox::information( nullptr, tr( "Delete Table" ), tr( "Table deleted successfully." ) );
602+
if ( connItem )
603+
connItem->refresh();
604+
}
605+
return true;
606+
}
607+
608+
void QgsMssqlLayerItem::truncateTable()
609+
{
610+
if ( QMessageBox::question( nullptr, QObject::tr( "Truncate Table" ),
611+
QObject::tr( "Are you sure you want to truncate [%1].[%2]?\n\nThis will delete all data within the table." ).arg( mLayerProperty.schemaName, mLayerProperty.tableName ),
612+
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
613+
return;
614+
615+
QString errCause;
616+
bool res = QgsMssqlConnection::truncateTable( mUri, &errCause );
617+
if ( !res )
618+
{
619+
QMessageBox::warning( nullptr, tr( "Truncate Table" ), errCause );
620+
}
621+
else
622+
{
623+
QMessageBox::information( nullptr, tr( "Truncate Table" ), tr( "Table truncated successfully." ) );
624+
}
625+
}
622626
#endif
623627

624628
QgsMssqlLayerItem *QgsMssqlLayerItem::createClone()

src/providers/mssql/qgsmssqldataitems.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,12 @@ class QgsMssqlLayerItem : public QgsLayerItem
140140

141141
bool disableInvalidGeometryHandling() const;
142142

143+
public slots:
144+
#ifdef HAVE_GUI
145+
bool deleteLayer() override;
146+
void truncateTable();
147+
#endif
148+
143149
private:
144150
QgsMssqlLayerProperty mLayerProperty;
145151
bool mDisableInvalidGeometryHandling = false;

0 commit comments

Comments
 (0)