Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #8507 from signedav/basicfix
Delete selected tables as DataItem action
  • Loading branch information
m-kuhn committed Jan 8, 2019
2 parents dada301 + 37eec19 commit 5df5c37
Show file tree
Hide file tree
Showing 16 changed files with 168 additions and 76 deletions.
13 changes: 13 additions & 0 deletions python/core/auto_generated/qgsbrowsermodel.sip.in
Expand Up @@ -117,6 +117,19 @@ items, i.e. it does not fetch children.
%End


QModelIndex findUri( const QString &uri, QModelIndex index = QModelIndex() );
%Docstring
Returns index of layer item with given uri. It only searches in currently fetched
items, i.e. it does not fetch children.

:param uri: item uri
:param index: the current index of the parent (to search for children)

:return: model index, invalid if item not found

.. versionadded:: 3.6
%End

void connectItem( QgsDataItem *item ) /Deprecated/;
%Docstring

Expand Down
6 changes: 6 additions & 0 deletions python/core/auto_generated/qgsdataitem.sip.in
Expand Up @@ -201,6 +201,7 @@ Items that return valid URI will be returned in mime data when dragging a select
Fast,
Collapse,
Rename,
Delete,
};
typedef QFlags<QgsDataItem::Capability> Capabilities;

Expand Down Expand Up @@ -485,6 +486,11 @@ Returns the string representation of the given ``layerType``
Returns the icon name of the given ``layerType``

.. versionadded:: 3
%End

virtual bool deleteLayer();
%Docstring
Delete this layer item
%End

protected:
Expand Down
36 changes: 36 additions & 0 deletions src/app/browser/qgsinbuiltdataitemproviders.cpp
Expand Up @@ -23,6 +23,7 @@
#include "qgsnative.h"
#include "qgisapp.h"
#include "qgsmessagebar.h"
#include "qgsmessagelog.h"
#include "qgsnewnamedialog.h"
#include "qgsbrowsermodel.h"
#include "qgsbrowserdockwidget_p.h"
Expand Down Expand Up @@ -390,6 +391,25 @@ void QgsLayerItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *men
} );
menu->addAction( addAction );

if ( item->capabilities2() & QgsDataItem::Delete )
{
QStringList selectedDeletableItemPaths;
for ( QgsDataItem *selectedItem : selectedItems )
{
if ( qobject_cast<QgsLayerItem *>( selectedItem ) && ( selectedItem->capabilities2() & QgsDataItem::Delete ) )
selectedDeletableItemPaths.append( qobject_cast<QgsLayerItem *>( selectedItem )->uri() );
}

const QString deleteText = selectedDeletableItemPaths.count() == 1 ? tr( "Delete Layer" )
: tr( "Delete Selected Layers" );
QAction *deleteAction = new QAction( deleteText, menu );
connect( deleteAction, &QAction::triggered, this, [ = ]
{
deleteLayers( selectedDeletableItemPaths );
} );
menu->addAction( deleteAction );
}

QAction *propertiesAction = new QAction( tr( "Layer Properties…" ), menu );
connect( propertiesAction, &QAction::triggered, this, [ = ]
{
Expand Down Expand Up @@ -457,6 +477,22 @@ void QgsLayerItemGuiProvider::addLayersFromItems( const QList<QgsDataItem *> &it
QgisApp::instance()->handleDropUriList( layerUriList );
}

void QgsLayerItemGuiProvider::deleteLayers( const QStringList &itemPaths )
{
for ( const QString &itemPath : itemPaths )
{
//get the item from browserModel by its path
QgsLayerItem *item = qobject_cast<QgsLayerItem *>( QgisApp::instance()->browserModel()->dataItem( QgisApp::instance()->browserModel()->findUri( itemPath ) ) );
if ( !item )
{
QgsMessageLog::logMessage( tr( "Item with path %1 no longer exists." ).arg( itemPath ) );
return;
}
if ( !item->deleteLayer() )
QMessageBox::information( QgisApp::instance(), tr( "Delete Layer" ), tr( "Item Layer %1 cannot be deleted." ).arg( item->name() ) );
}
}

void QgsLayerItemGuiProvider::showPropertiesForItem( QgsLayerItem *item )
{
if ( ! item )
Expand Down
1 change: 1 addition & 0 deletions src/app/browser/qgsinbuiltdataitemproviders.h
Expand Up @@ -100,6 +100,7 @@ class QgsLayerItemGuiProvider : public QObject, public QgsDataItemGuiProvider

void addLayersFromItems( const QList<QgsDataItem *> &items );
void showPropertiesForItem( QgsLayerItem *item );
void deleteLayers( const QStringList &itemPath );

};

Expand Down
24 changes: 24 additions & 0 deletions src/core/qgsbrowsermodel.cpp
Expand Up @@ -371,6 +371,30 @@ QModelIndex QgsBrowserModel::findPath( QAbstractItemModel *model, const QString
return QModelIndex(); // not found
}

QModelIndex QgsBrowserModel::findUri( const QString &uri, QModelIndex index )
{
for ( int i = 0; i < this->rowCount( index ); i++ )
{
QModelIndex idx = this->index( i, 0, index );

if ( qobject_cast<QgsLayerItem *>( dataItem( idx ) ) )
{
QString itemUri = qobject_cast<QgsLayerItem *>( dataItem( idx ) )->uri();

if ( itemUri == uri )
{
QgsDebugMsgLevel( "Arrived " + itemUri, 4 );
return idx; // we have found the item we have been looking for
}
}

QModelIndex childIdx = findUri( uri, idx );
if ( childIdx.isValid() )
return childIdx;
}
return QModelIndex();
}

void QgsBrowserModel::connectItem( QgsDataItem * )
{
// deprecated, no use
Expand Down
11 changes: 11 additions & 0 deletions src/core/qgsbrowsermodel.h
Expand Up @@ -136,6 +136,17 @@ class CORE_EXPORT QgsBrowserModel : public QAbstractItemModel
//! \note not available in Python bindings
static QModelIndex findPath( QAbstractItemModel *model, const QString &path, Qt::MatchFlag matchFlag = Qt::MatchExactly ) SIP_SKIP;

/**
* Returns index of layer item with given uri. It only searches in currently fetched
* items, i.e. it does not fetch children.
* \param uri item uri
* \param index the current index of the parent (to search for children)
* \returns model index, invalid if item not found
*
* \since QGIS 3.6
*/
QModelIndex findUri( const QString &uri, QModelIndex index = QModelIndex() );

/**
* \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!).
*/
Expand Down
5 changes: 5 additions & 0 deletions src/core/qgsdataitem.cpp
Expand Up @@ -701,6 +701,11 @@ QString QgsLayerItem::iconName( QgsLayerItem::LayerType layerType )
}
}

bool QgsLayerItem::deleteLayer()
{
return false;
}

bool QgsLayerItem::equal( const QgsDataItem *other )
{
//QgsDebugMsg ( mPath + " x " + other->mPath );
Expand Down
6 changes: 5 additions & 1 deletion src/core/qgsdataitem.h
Expand Up @@ -210,8 +210,9 @@ class CORE_EXPORT QgsDataItem : public QObject
SetCrs = 1 << 0, //!< Can set CRS on layer or group of layers
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.
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
Collapse = 1 << 3, //!< The collapse/expand status for this items children should be ignored in order to avoid undesired network connections (wms etc.)
Collapse = 1 << 3, //!< The collapse/expand status for this items children should be ignored in order to avoid undesired network connections (wms etc.)
Rename = 1 << 4, //!< Item can be renamed
Delete = 1 << 5, //!< Item can be deleted
};
Q_DECLARE_FLAGS( Capabilities, Capability )

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

//! Delete this layer item
virtual bool deleteLayer();

protected:

//! The provider key
Expand Down
86 changes: 45 additions & 41 deletions src/providers/mssql/qgsmssqldataitems.cpp
Expand Up @@ -561,64 +561,68 @@ QgsMssqlLayerItem::QgsMssqlLayerItem( QgsDataItem *parent, const QString &name,
: QgsLayerItem( parent, name, path, QString(), layerType, QStringLiteral( "mssql" ) )
, mLayerProperty( layerProperty )
{
mCapabilities |= Delete;
mUri = createUri();
setState( Populated );
}

#ifdef HAVE_GUI
QList<QAction *> QgsMssqlLayerItem::actions( QWidget *actionParent )
{
QgsMssqlConnectionItem *connItem = qobject_cast<QgsMssqlConnectionItem *>( parent() ? parent()->parent() : nullptr );

QList<QAction *> lst;

// delete
QAction *actionDeleteLayer = new QAction( tr( "Delete Table" ), actionParent );
connect( actionDeleteLayer, &QAction::triggered, this, [ = ]
{
if ( QMessageBox::question( nullptr, QObject::tr( "Delete Table" ),
QObject::tr( "Are you sure you want to delete [%1].[%2]?" ).arg( mLayerProperty.schemaName, mLayerProperty.tableName ),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
return;

QString errCause;
bool res = QgsMssqlConnection::dropTable( mUri, &errCause );
if ( !res )
{
QMessageBox::warning( nullptr, tr( "Delete Table" ), errCause );
}
else
{
QMessageBox::information( nullptr, tr( "Delete Table" ), tr( "Table deleted successfully." ) );
if ( connItem )
connItem->refresh();
}
} );
lst.append( actionDeleteLayer );

// truncate
QAction *actionTruncateLayer = new QAction( tr( "Truncate Table" ), actionParent );
connect( actionTruncateLayer, &QAction::triggered, this, [ = ]
{
if ( QMessageBox::question( nullptr, QObject::tr( "Truncate Table" ),
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 ),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
return;

QString errCause;
bool res = QgsMssqlConnection::truncateTable( mUri, &errCause );
if ( !res )
{
QMessageBox::warning( nullptr, tr( "Truncate Table" ), errCause );
}
else
{
QMessageBox::information( nullptr, tr( "Truncate Table" ), tr( "Table truncated successfully." ) );
}
truncateTable();
} );
lst.append( actionTruncateLayer );
return lst;
}

bool QgsMssqlLayerItem::deleteLayer()
{
QgsMssqlConnectionItem *connItem = qobject_cast<QgsMssqlConnectionItem *>( parent() ? parent()->parent() : nullptr );

if ( QMessageBox::question( nullptr, QObject::tr( "Delete Table" ),
QObject::tr( "Are you sure you want to delete [%1].[%2]?" ).arg( mLayerProperty.schemaName, mLayerProperty.tableName ),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
return true;

QString errCause;
bool res = QgsMssqlConnection::dropTable( mUri, &errCause );
if ( !res )
{
QMessageBox::warning( nullptr, tr( "Delete Table" ), errCause );
}
else
{
QMessageBox::information( nullptr, tr( "Delete Table" ), tr( "Table deleted successfully." ) );
if ( connItem )
connItem->refresh();
}
return true;
}

void QgsMssqlLayerItem::truncateTable()
{
if ( QMessageBox::question( nullptr, QObject::tr( "Truncate Table" ),
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 ),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
return;

QString errCause;
bool res = QgsMssqlConnection::truncateTable( mUri, &errCause );
if ( !res )
{
QMessageBox::warning( nullptr, tr( "Truncate Table" ), errCause );
}
else
{
QMessageBox::information( nullptr, tr( "Truncate Table" ), tr( "Table truncated successfully." ) );
}
}
#endif

QgsMssqlLayerItem *QgsMssqlLayerItem::createClone()
Expand Down
6 changes: 6 additions & 0 deletions src/providers/mssql/qgsmssqldataitems.h
Expand Up @@ -140,6 +140,12 @@ class QgsMssqlLayerItem : public QgsLayerItem

bool disableInvalidGeometryHandling() const;

public slots:
#ifdef HAVE_GUI
bool deleteLayer() override;
void truncateTable();
#endif

private:
QgsMssqlLayerProperty mLayerProperty;
bool mDisableInvalidGeometryHandling = false;
Expand Down
12 changes: 5 additions & 7 deletions src/providers/ogr/qgsgeopackagedataitems.cpp
Expand Up @@ -80,9 +80,6 @@ QVector<QgsDataItem *> QgsGeoPackageRootItem::createChildren()
QList<QAction *> QgsGeoPackageAbstractLayerItem::actions( QWidget * )
{
QList<QAction *> lst;
QAction *actionDeleteLayer = new QAction( tr( "Delete Layer '%1'…" ).arg( mName ), this );
connect( actionDeleteLayer, &QAction::triggered, this, &QgsGeoPackageAbstractLayerItem::deleteLayer );
lst.append( actionDeleteLayer );
// Check capabilities: for now rename is only available for vectors
if ( capabilities2() & QgsDataItem::Capability::Rename )
{
Expand Down Expand Up @@ -496,7 +493,7 @@ void QgsGeoPackageCollectionItem::vacuumGeoPackageDbAction()
}
}

void QgsGeoPackageAbstractLayerItem::deleteLayer()
bool QgsGeoPackageAbstractLayerItem::deleteLayer()
{
// Check if the layer(s) are in the registry
const QList<QgsMapLayer *> layersList( layersInProject( ) );
Expand All @@ -505,14 +502,14 @@ void QgsGeoPackageAbstractLayerItem::deleteLayer()
if ( QMessageBox::question( nullptr, QObject::tr( "Delete Layer" ), QObject::tr( "The layer <b>%1</b> exists in the current project <b>%2</b>,"
" do you want to remove it from the project and delete it?" ).arg( mName, layersList.at( 0 )->name() ), QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
{
return;
return true;
}
}
else if ( QMessageBox::question( nullptr, QObject::tr( "Delete Layer" ),
QObject::tr( "Are you sure you want to delete layer <b>%1</b> from GeoPackage?" ).arg( mName ),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
{
return;
return true;
}

if ( ! layersList.isEmpty() )
Expand All @@ -532,7 +529,7 @@ void QgsGeoPackageAbstractLayerItem::deleteLayer()
if ( mParent )
mParent->refreshConnections();
}

return true;
}

void QgsGeoPackageAbstractLayerItem::renameLayer( )
Expand Down Expand Up @@ -733,6 +730,7 @@ bool QgsGeoPackageConnectionItem::equal( const QgsDataItem *other )
QgsGeoPackageAbstractLayerItem::QgsGeoPackageAbstractLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri, QgsLayerItem::LayerType layerType, const QString &providerKey )
: QgsLayerItem( parent, name, path, uri, layerType, providerKey )
{
mCapabilities |= Delete;
mToolTip = uri;
setState( Populated ); // no children are expected
}
Expand Down
2 changes: 1 addition & 1 deletion src/providers/ogr/qgsgeopackagedataitems.h
Expand Up @@ -47,10 +47,10 @@ class QgsGeoPackageAbstractLayerItem : public QgsLayerItem
QList<QgsMapLayer *> layersInProject() const;

#ifdef HAVE_GUI
bool deleteLayer() override;
QList<QAction *> actions( QWidget *menu ) override;

public slots:
virtual void deleteLayer();
//! Renames the layer: default implementation does nothing!
virtual void renameLayer();
#endif
Expand Down

0 comments on commit 5df5c37

Please sign in to comment.