mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-27 00:33:48 -05:00
Merge pull request #8507 from signedav/basicfix
Delete selected tables as DataItem action
This commit is contained in:
commit
5df5c3763e
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
||||
@ -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:
|
||||
|
@ -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"
|
||||
@ -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, [ = ]
|
||||
{
|
||||
@ -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 )
|
||||
|
@ -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 );
|
||||
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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!).
|
||||
*/
|
||||
|
@ -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 );
|
||||
|
@ -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 )
|
||||
|
||||
@ -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
|
||||
|
@ -561,6 +561,7 @@ QgsMssqlLayerItem::QgsMssqlLayerItem( QgsDataItem *parent, const QString &name,
|
||||
: QgsLayerItem( parent, name, path, QString(), layerType, QStringLiteral( "mssql" ) )
|
||||
, mLayerProperty( layerProperty )
|
||||
{
|
||||
mCapabilities |= Delete;
|
||||
mUri = createUri();
|
||||
setState( Populated );
|
||||
}
|
||||
@ -568,57 +569,60 @@ QgsMssqlLayerItem::QgsMssqlLayerItem( QgsDataItem *parent, const QString &name,
|
||||
#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()
|
||||
|
@ -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;
|
||||
|
@ -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 )
|
||||
{
|
||||
@ -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( ) );
|
||||
@ -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() )
|
||||
@ -532,7 +529,7 @@ void QgsGeoPackageAbstractLayerItem::deleteLayer()
|
||||
if ( mParent )
|
||||
mParent->refreshConnections();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QgsGeoPackageAbstractLayerItem::renameLayer( )
|
||||
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -296,6 +296,7 @@ QgsPGLayerItem::QgsPGLayerItem( QgsDataItem *parent, const QString &name, const
|
||||
: QgsLayerItem( parent, name, path, QString(), layerType, QStringLiteral( "postgres" ) )
|
||||
, mLayerProperty( layerProperty )
|
||||
{
|
||||
mCapabilities |= Delete;
|
||||
mUri = createUri();
|
||||
setState( Populated );
|
||||
Q_ASSERT( mLayerProperty.size() == 1 );
|
||||
@ -317,10 +318,6 @@ QList<QAction *> QgsPGLayerItem::actions( QWidget *parent )
|
||||
connect( actionRenameLayer, &QAction::triggered, this, &QgsPGLayerItem::renameLayer );
|
||||
lst.append( actionRenameLayer );
|
||||
|
||||
QAction *actionDeleteLayer = new QAction( tr( "Delete %1" ).arg( typeName ), parent );
|
||||
connect( actionDeleteLayer, &QAction::triggered, this, &QgsPGLayerItem::deleteLayer );
|
||||
lst.append( actionDeleteLayer );
|
||||
|
||||
if ( !mLayerProperty.isView )
|
||||
{
|
||||
QAction *actionTruncateLayer = new QAction( tr( "Truncate %1" ).arg( typeName ), parent );
|
||||
@ -338,12 +335,12 @@ QList<QAction *> QgsPGLayerItem::actions( QWidget *parent )
|
||||
return lst;
|
||||
}
|
||||
|
||||
void QgsPGLayerItem::deleteLayer()
|
||||
bool QgsPGLayerItem::deleteLayer()
|
||||
{
|
||||
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;
|
||||
return true;
|
||||
|
||||
QString errCause;
|
||||
bool res = ::deleteLayer( mUri, errCause );
|
||||
@ -357,6 +354,7 @@ void QgsPGLayerItem::deleteLayer()
|
||||
if ( mParent )
|
||||
mParent->refresh();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void QgsPGLayerItem::renameLayer()
|
||||
|
@ -129,7 +129,7 @@ class QgsPGLayerItem : public QgsLayerItem
|
||||
|
||||
public slots:
|
||||
#ifdef HAVE_GUI
|
||||
void deleteLayer();
|
||||
bool deleteLayer() override;
|
||||
void renameLayer();
|
||||
void truncateTable();
|
||||
void refreshMaterializedView();
|
||||
|
@ -37,27 +37,17 @@ QGISEXTERN bool deleteLayer( const QString &dbPath, const QString &tableName, QS
|
||||
QgsSLLayerItem::QgsSLLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri, LayerType layerType )
|
||||
: QgsLayerItem( parent, name, path, uri, layerType, QStringLiteral( "spatialite" ) )
|
||||
{
|
||||
mCapabilities |= Delete;
|
||||
setState( Populated ); // no children are expected
|
||||
}
|
||||
|
||||
#ifdef HAVE_GUI
|
||||
QList<QAction *> QgsSLLayerItem::actions( QWidget *parent )
|
||||
{
|
||||
QList<QAction *> lst;
|
||||
|
||||
QAction *actionDeleteLayer = new QAction( tr( "Delete Layer" ), parent );
|
||||
connect( actionDeleteLayer, &QAction::triggered, this, &QgsSLLayerItem::deleteLayer );
|
||||
lst.append( actionDeleteLayer );
|
||||
|
||||
return lst;
|
||||
}
|
||||
|
||||
void QgsSLLayerItem::deleteLayer()
|
||||
bool QgsSLLayerItem::deleteLayer()
|
||||
{
|
||||
if ( QMessageBox::question( nullptr, QObject::tr( "Delete Object" ),
|
||||
QObject::tr( "Are you sure you want to delete %1?" ).arg( mName ),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
|
||||
return;
|
||||
return true;
|
||||
|
||||
QgsDataSourceUri uri( mUri );
|
||||
QString errCause;
|
||||
@ -71,6 +61,7 @@ void QgsSLLayerItem::deleteLayer()
|
||||
QMessageBox::information( nullptr, tr( "Delete Layer" ), tr( "Layer deleted successfully." ) );
|
||||
mParent->refresh();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -24,12 +24,7 @@ class QgsSLLayerItem : public QgsLayerItem
|
||||
QgsSLLayerItem( QgsDataItem *parent, const QString &name, const QString &path, const QString &uri, LayerType layerType );
|
||||
|
||||
#ifdef HAVE_GUI
|
||||
QList<QAction *> actions( QWidget *parent ) override;
|
||||
#endif
|
||||
|
||||
public slots:
|
||||
#ifdef HAVE_GUI
|
||||
void deleteLayer();
|
||||
bool deleteLayer() override;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user