Skip to content

Commit 4f7d9cd

Browse files
authoredFeb 5, 2017
Merge pull request #4064 from jgrocha/delete-style-from-db-provider-postgis
Delete style from db provider postgis
2 parents 6ca2cc1 + 20eea32 commit 4f7d9cd

13 files changed

+293
-34
lines changed
 

‎python/core/qgsvectordataprovider.sip

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,14 @@ class QgsVectorDataProvider : QgsDataProvider
407407
*/
408408
virtual bool isSaveAndLoadStyleToDBSupported() const;
409409

410+
/**
411+
* Checks if the provider supports style removal
412+
* Must be implemented by providers that support delete styles from db returning true
413+
* @note added in QGIS 3.0
414+
* @return true if delete operation is supported by the provider
415+
*/
416+
virtual bool isDeleteStyleFromDbSupported() const;
417+
410418
static QVariant convertValue( QVariant::Type type, const QString& value );
411419

412420
/**

‎python/core/qgsvectorlayer.sip

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,15 @@ class QgsVectorLayer : QgsMapLayer, QgsExpressionContextGenerator
649649
*/
650650
virtual QString getStyleFromDatabase( const QString& styleId, QString &msgError /Out/ );
651651

652+
/**
653+
* Delete a style from the database
654+
* @note added in QGIS 3.0
655+
* @param styleId the provider's layer_styles table id of the style to delete
656+
* @param msgError reference to string that will be updated with any error messages
657+
* @return true in case of success
658+
*/
659+
virtual bool deleteStyleFromDatabase( const QString& styleId, QString &msgError /Out/ );
660+
652661
/**
653662
* Load a named style from file/local db/datasource db
654663
* @param theURI the URI of the style or the URI of the layer

‎src/app/qgsloadstylefromdbdialog.cpp

Lines changed: 104 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "qgsloadstylefromdbdialog.h"
1717
#include "qgslogger.h"
18+
#include "qgisapp.h"
1819

1920
#include <QSettings>
2021
#include <QMessageBox>
@@ -25,10 +26,10 @@ QgsLoadStyleFromDBDialog::QgsLoadStyleFromDBDialog( QWidget *parent )
2526
, mSectionLimit( 0 )
2627
{
2728
setupUi( this );
28-
setWindowTitle( QStringLiteral( "Load style from database" ) );
29-
mSelectedStyleId = QLatin1String( "" );
29+
setWindowTitle( QStringLiteral( "Database styles manager" ) );
3030

3131
mLoadButton->setDisabled( true );
32+
mDeleteButton->setDisabled( true );
3233
mRelatedTable->setEditTriggers( QTableWidget::NoEditTriggers );
3334
mRelatedTable->horizontalHeader()->setStretchLastSection( true );
3435
mRelatedTable->setSelectionBehavior( QTableWidget::SelectRows );
@@ -39,20 +40,21 @@ QgsLoadStyleFromDBDialog::QgsLoadStyleFromDBDialog( QWidget *parent )
3940
mOthersTable->setSelectionBehavior( QTableWidget::SelectRows );
4041
mOthersTable->verticalHeader()->setVisible( false );
4142

42-
connect( mRelatedTable, SIGNAL( cellClicked( int, int ) ), this, SLOT( cellSelectedRelatedTable( int ) ) );
43-
connect( mOthersTable, SIGNAL( cellClicked( int, int ) ), this, SLOT( cellSelectedOthersTable( int ) ) );
44-
connect( mRelatedTable, SIGNAL( doubleClicked( QModelIndex ) ), this, SLOT( accept() ) );
45-
connect( mOthersTable, SIGNAL( doubleClicked( QModelIndex ) ), this, SLOT( accept() ) );
46-
connect( mCancelButton, SIGNAL( clicked() ), this, SLOT( reject() ) );
47-
connect( mLoadButton, SIGNAL( clicked() ), this, SLOT( accept() ) );
43+
connect( mRelatedTable->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsLoadStyleFromDBDialog::onRelatedTableSelectionChanged );
44+
connect( mOthersTable->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsLoadStyleFromDBDialog::onOthersTableSelectionChanged );
45+
connect( mRelatedTable, &QTableWidget::doubleClicked, this, &QDialog::accept );
46+
connect( mOthersTable, &QTableWidget::doubleClicked, this, &QDialog::accept );
47+
connect( mCancelButton, &QPushButton::clicked, this, &QDialog::reject );
48+
connect( mLoadButton, &QPushButton::clicked, this, &QDialog::accept );
49+
connect( mDeleteButton, &QPushButton::clicked, this, &QgsLoadStyleFromDBDialog::deleteStyleFromDB );
4850

4951
setTabOrder( mRelatedTable, mOthersTable );
5052
setTabOrder( mOthersTable, mCancelButton );
51-
setTabOrder( mCancelButton, mLoadButton );
53+
setTabOrder( mCancelButton, mDeleteButton );
54+
setTabOrder( mDeleteButton, mLoadButton );
5255

5356
QSettings settings;
5457
restoreGeometry( settings.value( QStringLiteral( "/Windows/loadStyleFromDb/geometry" ) ).toByteArray() );
55-
5658
}
5759

5860
QgsLoadStyleFromDBDialog::~QgsLoadStyleFromDBDialog()
@@ -102,14 +104,100 @@ QString QgsLoadStyleFromDBDialog::getSelectedStyleId()
102104
return mSelectedStyleId;
103105
}
104106

105-
void QgsLoadStyleFromDBDialog::cellSelectedRelatedTable( int r )
107+
void QgsLoadStyleFromDBDialog::setLayer( QgsVectorLayer *l )
106108
{
107-
mLoadButton->setEnabled( true );
108-
mSelectedStyleId = mRelatedTable->item( r, 0 )->data( Qt::UserRole ).toString();
109+
mLayer = l;
110+
mDeleteButton->setVisible( mLayer->dataProvider()->isDeleteStyleFromDbSupported() );
109111
}
110112

111-
void QgsLoadStyleFromDBDialog::cellSelectedOthersTable( int r )
113+
void QgsLoadStyleFromDBDialog::onRelatedTableSelectionChanged()
112114
{
113-
mLoadButton->setEnabled( true );
114-
mSelectedStyleId = mOthersTable->item( r, 0 )->data( Qt::UserRole ).toString();
115+
selectionChanged( mRelatedTable );
116+
if ( mRelatedTable->selectionModel()->hasSelection() )
117+
{
118+
if ( mOthersTable->selectionModel()->hasSelection() )
119+
{
120+
disconnect( mOthersTable->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsLoadStyleFromDBDialog::onOthersTableSelectionChanged );
121+
QTableWidgetSelectionRange range( 0, 0, mOthersTable->rowCount() - 1, mOthersTable->columnCount() - 1 );
122+
mOthersTable->setRangeSelected( range, false );
123+
connect( mOthersTable->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsLoadStyleFromDBDialog::onOthersTableSelectionChanged );
124+
}
125+
}
126+
}
127+
128+
void QgsLoadStyleFromDBDialog::onOthersTableSelectionChanged()
129+
{
130+
selectionChanged( mOthersTable );
131+
if ( mOthersTable->selectionModel()->hasSelection() )
132+
{
133+
if ( mRelatedTable->selectionModel()->hasSelection() )
134+
{
135+
disconnect( mRelatedTable->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsLoadStyleFromDBDialog::onRelatedTableSelectionChanged );
136+
QTableWidgetSelectionRange range( 0, 0, mRelatedTable->rowCount() - 1, mRelatedTable->columnCount() - 1 );
137+
mRelatedTable->setRangeSelected( range, false );
138+
connect( mRelatedTable->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsLoadStyleFromDBDialog::onRelatedTableSelectionChanged );
139+
}
140+
}
141+
}
142+
143+
void QgsLoadStyleFromDBDialog::selectionChanged( QTableWidget *styleTable )
144+
{
145+
QTableWidgetItem *item;
146+
QList<QTableWidgetItem *> selected = styleTable->selectedItems();
147+
148+
if ( !selected.isEmpty() )
149+
{
150+
item = selected.at( 0 );
151+
mSelectedStyleName = item->text();
152+
mSelectedStyleId = item->data( Qt::UserRole ).toString();
153+
mLoadButton->setEnabled( true );
154+
mDeleteButton->setEnabled( true );
155+
}
156+
else
157+
{
158+
mSelectedStyleName.clear();
159+
mSelectedStyleId.clear();
160+
mLoadButton->setEnabled( false );
161+
mDeleteButton->setEnabled( false );
162+
}
163+
}
164+
165+
void QgsLoadStyleFromDBDialog::deleteStyleFromDB()
166+
{
167+
QString msgError;
168+
QString opInfo = QObject::tr( "Delete style %1 from %2" ).arg( mSelectedStyleName, mLayer->providerType() );
169+
170+
if ( QMessageBox::question( nullptr, QObject::tr( "Delete style" ),
171+
QObject::tr( "Are you sure you want to delete the style %1?" ).arg( mSelectedStyleName ),
172+
QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
173+
return;
174+
175+
mLayer->deleteStyleFromDatabase( mSelectedStyleId, msgError );
176+
if ( !msgError.isNull() )
177+
{
178+
QgsDebugMsg( opInfo + " failed." );
179+
QgisApp::instance()->messageBar()->pushMessage( opInfo , tr( "%1: fail. %2" ).arg( opInfo, msgError ), QgsMessageBar::WARNING, QgisApp::instance()->messageTimeout() );
180+
}
181+
else
182+
{
183+
QgisApp::instance()->messageBar()->pushMessage( opInfo , tr( "%1: success" ).arg( opInfo ), QgsMessageBar::INFO, QgisApp::instance()->messageTimeout() );
184+
185+
//Delete all rows from the UI table widgets
186+
mRelatedTable->setRowCount( 0 );
187+
mOthersTable->setRowCount( 0 );
188+
189+
//Fill UI widgets again from DB. Other users might have change the styles meanwhile.
190+
QString errorMsg;
191+
QStringList ids, names, descriptions;
192+
//get the list of styles in the db
193+
int sectionLimit = mLayer->listStylesInDatabase( ids, names, descriptions, errorMsg );
194+
if ( !errorMsg.isNull() )
195+
{
196+
QgisApp::instance()->messageBar()->pushMessage( tr( "Error occurred retrieving styles from database" ), errorMsg, QgsMessageBar::WARNING, QgisApp::instance()->messageTimeout() );
197+
}
198+
else
199+
{
200+
initializeLists( ids, names, descriptions, sectionLimit );
201+
}
202+
}
115203
}

‎src/app/qgsloadstylefromdbdialog.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919
#include "ui_qgsloadstylefromdbdialog.h"
2020
#include "qgisgui.h"
2121
#include "qgis_app.h"
22+
#include "qgsvectorlayer.h"
23+
#include "qgsvectordataprovider.h"
2224

2325
class APP_EXPORT QgsLoadStyleFromDBDialog : public QDialog, private Ui::QgsLoadStyleFromDBDialogLayout
2426
{
2527
QString mSelectedStyleId;
28+
QString mSelectedStyleName;
2629
int mSectionLimit;
27-
QString qmlStyle;
2830
Q_OBJECT
2931
public:
3032
explicit QgsLoadStyleFromDBDialog( QWidget *parent = nullptr );
@@ -33,12 +35,16 @@ class APP_EXPORT QgsLoadStyleFromDBDialog : public QDialog, private Ui::QgsLoadS
3335

3436
void initializeLists( const QStringList& ids, const QStringList& names, const QStringList& descriptions, int sectionLimit );
3537
QString getSelectedStyleId();
38+
void selectionChanged( QTableWidget *styleTable );
39+
void setLayer( QgsVectorLayer *l );
3640

3741
public slots:
38-
void cellSelectedRelatedTable( int r );
39-
void cellSelectedOthersTable( int r );
42+
void onRelatedTableSelectionChanged();
43+
void onOthersTableSelectionChanged();
44+
void deleteStyleFromDB();
4045

4146
private:
47+
QgsVectorLayer *mLayer = nullptr;
4248

4349
};
4450

‎src/app/qgsvectorlayerproperties.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
163163
//for loading
164164
mLoadStyleMenu = new QMenu( this );
165165
mLoadStyleMenu->addAction( tr( "Load from file..." ) );
166-
mLoadStyleMenu->addAction( tr( "Load from database" ) );
166+
mLoadStyleMenu->addAction( tr( "Database styles manager" ) );
167167
//mActionLoadStyle->setContextMenuPolicy( Qt::PreventContextMenu );
168168
mActionLoadStyle->setMenu( mLoadStyleMenu );
169169

@@ -883,11 +883,11 @@ void QgsVectorLayerProperties::saveStyleAs( StyleType styleType )
883883

884884
if ( !msgError.isNull() )
885885
{
886-
QMessageBox::warning( this, infoWindowTitle, msgError );
886+
QgisApp::instance()->messageBar()->pushMessage( infoWindowTitle , msgError, QgsMessageBar::WARNING, QgisApp::instance()->messageTimeout() );
887887
}
888888
else
889889
{
890-
QMessageBox::information( this, infoWindowTitle, tr( "Style saved" ) );
890+
QgisApp::instance()->messageBar()->pushMessage( infoWindowTitle , tr( "Style saved" ), QgsMessageBar::INFO, QgisApp::instance()->messageTimeout() );
891891
}
892892

893893
}
@@ -1022,6 +1022,7 @@ void QgsVectorLayerProperties::showListOfStylesFromDatabase()
10221022
}
10231023

10241024
QgsLoadStyleFromDBDialog dialog;
1025+
dialog.setLayer( mLayer );
10251026
dialog.initializeLists( ids, names, descriptions, sectionLimit );
10261027

10271028
if ( dialog.exec() == QDialog::Accepted )

‎src/core/qgsvectordataprovider.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,11 @@ bool QgsVectorDataProvider::isSaveAndLoadStyleToDBSupported() const
695695
return false;
696696
}
697697

698+
bool QgsVectorDataProvider::isDeleteStyleFromDbSupported() const
699+
{
700+
return false;
701+
}
702+
698703
void QgsVectorDataProvider::pushError( const QString& msg ) const
699704
{
700705
QgsDebugMsg( msg );

‎src/core/qgsvectordataprovider.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,12 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
470470
*/
471471
virtual bool isSaveAndLoadStyleToDBSupported() const;
472472

473+
/**
474+
* It returns false by default.
475+
* Must be implemented by providers that support delete styles from db returning true
476+
*/
477+
virtual bool isDeleteStyleFromDbSupported() const;
478+
473479
static QVariant convertValue( QVariant::Type type, const QString& value );
474480

475481
/**

‎src/core/qgsvectorlayer.cpp

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@ typedef QString getStyleById_t(
119119
QString& errCause
120120
);
121121

122+
typedef bool deleteStyleById_t(
123+
const QString& uri,
124+
QString styleID,
125+
QString& errCause
126+
);
127+
122128
QgsVectorLayer::QgsVectorLayer( const QString& vectorLayerPath,
123129
const QString& baseName,
124130
const QString& providerKey,
@@ -4266,8 +4272,7 @@ QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx ) const
42664272

42674273
int QgsVectorLayer::listStylesInDatabase( QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError )
42684274
{
4269-
QgsProviderRegistry * pReg = QgsProviderRegistry::instance();
4270-
QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4275+
QScopedPointer<QLibrary> myLib( QgsProviderRegistry::instance()->providerLibrary( mProviderKey ) );
42714276
if ( !myLib )
42724277
{
42734278
msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
@@ -4277,7 +4282,6 @@ int QgsVectorLayer::listStylesInDatabase( QStringList &ids, QStringList &names,
42774282

42784283
if ( !listStylesExternalMethod )
42794284
{
4280-
delete myLib;
42814285
msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, QStringLiteral( "listStyles" ) );
42824286
return -1;
42834287
}
@@ -4287,8 +4291,7 @@ int QgsVectorLayer::listStylesInDatabase( QStringList &ids, QStringList &names,
42874291

42884292
QString QgsVectorLayer::getStyleFromDatabase( const QString& styleId, QString &msgError )
42894293
{
4290-
QgsProviderRegistry * pReg = QgsProviderRegistry::instance();
4291-
QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4294+
QScopedPointer<QLibrary> myLib( QgsProviderRegistry::instance()->providerLibrary( mProviderKey ) );
42924295
if ( !myLib )
42934296
{
42944297
msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
@@ -4298,22 +4301,37 @@ QString QgsVectorLayer::getStyleFromDatabase( const QString& styleId, QString &m
42984301

42994302
if ( !getStyleByIdMethod )
43004303
{
4301-
delete myLib;
43024304
msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, QStringLiteral( "getStyleById" ) );
43034305
return QString();
43044306
}
43054307

43064308
return getStyleByIdMethod( mDataSource, styleId, msgError );
43074309
}
43084310

4311+
bool QgsVectorLayer::deleteStyleFromDatabase( const QString& styleId, QString &msgError )
4312+
{
4313+
QScopedPointer<QLibrary> myLib( QgsProviderRegistry::instance()->providerLibrary( mProviderKey ) );
4314+
if ( !myLib )
4315+
{
4316+
msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
4317+
return false;
4318+
}
4319+
deleteStyleById_t* deleteStyleByIdMethod = reinterpret_cast< deleteStyleById_t * >( cast_to_fptr( myLib->resolve( "deleteStyleById" ) ) );
4320+
if ( !deleteStyleByIdMethod )
4321+
{
4322+
msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, QStringLiteral( "deleteStyleById" ) );
4323+
return false;
4324+
}
4325+
return deleteStyleByIdMethod( mDataSource, styleId, msgError );
4326+
}
4327+
43094328

43104329
void QgsVectorLayer::saveStyleToDatabase( const QString& name, const QString& description,
43114330
bool useAsDefault, const QString& uiFileContent, QString &msgError )
43124331
{
43134332

43144333
QString sldStyle, qmlStyle;
4315-
QgsProviderRegistry * pReg = QgsProviderRegistry::instance();
4316-
QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4334+
QScopedPointer<QLibrary> myLib( QgsProviderRegistry::instance()->providerLibrary( mProviderKey ) );
43174335
if ( !myLib )
43184336
{
43194337
msgError = QObject::tr( "Unable to load %1 provider" ).arg( mProviderKey );
@@ -4323,7 +4341,6 @@ void QgsVectorLayer::saveStyleToDatabase( const QString& name, const QString& de
43234341

43244342
if ( !saveStyleExternalMethod )
43254343
{
4326-
delete myLib;
43274344
msgError = QObject::tr( "Provider %1 has no %2 method" ).arg( mProviderKey, QStringLiteral( "saveStyle" ) );
43284345
return;
43294346
}
@@ -4359,8 +4376,7 @@ QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &theResultFl
43594376
QgsDataSourceUri dsUri( theURI );
43604377
if ( !loadFromLocalDB && mDataProvider && mDataProvider->isSaveAndLoadStyleToDBSupported() )
43614378
{
4362-
QgsProviderRegistry * pReg = QgsProviderRegistry::instance();
4363-
QLibrary *myLib = pReg->providerLibrary( mProviderKey );
4379+
QScopedPointer<QLibrary> myLib( QgsProviderRegistry::instance()->providerLibrary( mProviderKey ) );
43644380
if ( myLib )
43654381
{
43664382
loadStyle_t* loadStyleExternalMethod = reinterpret_cast< loadStyle_t * >( cast_to_fptr( myLib->resolve( "loadStyle" ) ) );

‎src/core/qgsvectorlayer.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,15 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
732732
*/
733733
virtual QString getStyleFromDatabase( const QString& styleId, QString &msgError );
734734

735+
/**
736+
* Delete a style from the database
737+
* @note added in QGIS 3.0
738+
* @param styleId the provider's layer_styles table id of the style to delete
739+
* @param msgError reference to string that will be updated with any error messages
740+
* @return true in case of success
741+
*/
742+
virtual bool deleteStyleFromDatabase( const QString& styleId, QString &msgError );
743+
735744
/**
736745
* Load a named style from file/local db/datasource db
737746
* @param theURI the URI of the style or the URI of the layer

0 commit comments

Comments
 (0)
Please sign in to comment.