QGIS API Documentation 3.34.0-Prizren (ffbdd678812)
Loading...
Searching...
No Matches
qgsmaplayerloadstyledialog.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmaplayerloadstyledialog.cpp
3 ---------------------
4 begin : April 2013
5 copyright : (C) 2013 by Emilio Loi
6 email : loi at faunalia dot it
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include <QMessageBox>
17#include <QVector>
18
20#include "qgslogger.h"
21#include "qgssettings.h"
24#include "qgshelp.h"
25#include "qgsapplication.h"
26#include "qgsgui.h"
27
28
30 : QDialog( parent )
31 , mLayer( layer )
32{
33 setupUi( this );
35 setWindowTitle( tr( "Database Styles Manager" ) );
36
37 mDeleteButton = mButtonBox->button( QDialogButtonBox::StandardButton::Close );
38 mDeleteButton->setText( tr( "Delete Style" ) );
39 mDeleteButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mActionDeleteSelected.svg" ) ) );
40 mLoadButton = mButtonBox->button( QDialogButtonBox::StandardButton::Open );
41 mLoadButton->setText( tr( "Load Style" ) );
42 mCancelButton = mButtonBox->button( QDialogButtonBox::StandardButton::Cancel );
43
44 QgsSettings settings;
45
46 const QString myLastUsedDir = settings.value( QStringLiteral( "style/lastStyleDir" ), QDir::homePath() ).toString();
47
48 // load style type combobox
49 connect( mStyleTypeComboBox, qOverload<int>( &QComboBox::currentIndexChanged ), this, [ = ]( int )
50 {
54 mFromDbWidget->setVisible( type == QgsLayerPropertiesDialog::StyleType::DatasourceDatabase );
56
57 mStyleCategoriesListView->setEnabled( currentStyleType() != QgsLayerPropertiesDialog::StyleType::SLD );
58 updateLoadButtonState();
59 } );
60 mStyleTypeComboBox->addItem( tr( "From file" ), QgsLayerPropertiesDialog::QML ); // QML is used as entry, but works for SLD too, see currentStyleType()
61 mStyleTypeComboBox->addItem( tr( "Default from local database" ), QgsLayerPropertiesDialog::UserDatabase );
62
64 {
65 mStyleTypeComboBox->addItem( tr( "From datasource database" ), QgsLayerPropertiesDialog::StyleType::DatasourceDatabase );
66 if ( settings.value( QStringLiteral( "style/lastLoadStyleTypeSelection" ) ) == QgsLayerPropertiesDialog::StyleType::DatasourceDatabase )
67 {
68 mStyleTypeComboBox->setCurrentIndex( mStyleTypeComboBox->findData( QgsLayerPropertiesDialog::StyleType::DatasourceDatabase ) );
69 }
70 }
71
72 // fill style categories
73 mModel = new QgsMapLayerStyleCategoriesModel( mLayer->type(), this );
74 const QgsMapLayer::StyleCategories lastStyleCategories = settings.flagValue( QStringLiteral( "style/lastStyleCategories" ), QgsMapLayer::AllStyleCategories );
75 mModel->setCategories( lastStyleCategories );
76 mStyleCategoriesListView->setModel( mModel );
77
78 // load from file setup
79 switch ( mLayer->type() )
80 {
82 mFileWidget->setFilter( tr( "QGIS Layer Style File, SLD File" ) + QStringLiteral( " (*.qml *.sld)" ) );
83 break;
84
86 mFileWidget->setFilter( tr( "All Styles" ) + QStringLiteral( " (*.qml *.json);;" )
87 + tr( "QGIS Layer Style File" ) + QStringLiteral( " (*.qml);;" )
88 + tr( "MapBox GL Style JSON File" ) + QStringLiteral( " (*.json)" ) );
89 break;
90
98 break;
99
100 }
101
102 mFileWidget->setStorageMode( QgsFileWidget::GetFile );
103 mFileWidget->setDefaultRoot( myLastUsedDir );
104 connect( mFileWidget, &QgsFileWidget::fileChanged, this, [ = ]( const QString & path )
105 {
106 mStyleCategoriesListView->setEnabled( currentStyleType() != QgsLayerPropertiesDialog::SLD );
107 QgsSettings settings;
108 const QFileInfo tmplFileInfo( path );
109 settings.setValue( QStringLiteral( "style/lastStyleDir" ), tmplFileInfo.absolutePath() );
110
111 updateLoadButtonState();
112 } );
113
114 // load from DB
115 mLoadButton->setDisabled( true );
116 mDeleteButton->setDisabled( true );
117 mRelatedTable->setEditTriggers( QTableWidget::NoEditTriggers );
118 mRelatedTable->horizontalHeader()->setStretchLastSection( true );
119 mRelatedTable->setSelectionBehavior( QTableWidget::SelectRows );
120 mRelatedTable->verticalHeader()->setVisible( false );
121 mOthersTable->setEditTriggers( QTableWidget::NoEditTriggers );
122 mOthersTable->horizontalHeader()->setStretchLastSection( true );
123 mOthersTable->setSelectionBehavior( QTableWidget::SelectRows );
124 mOthersTable->verticalHeader()->setVisible( false );
125 connect( mRelatedTable->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsMapLayerLoadStyleDialog::onRelatedTableSelectionChanged );
126 connect( mOthersTable->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsMapLayerLoadStyleDialog::onOthersTableSelectionChanged );
127 connect( mRelatedTable, &QTableWidget::doubleClicked, this, &QDialog::accept );
128 connect( mOthersTable, &QTableWidget::doubleClicked, this, &QDialog::accept );
129 connect( mCancelButton, &QPushButton::clicked, this, &QDialog::reject );
130 connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsMapLayerLoadStyleDialog::showHelp );
131 connect( mLoadButton, &QPushButton::clicked, this, &QDialog::accept );
132 connect( mDeleteButton, &QPushButton::clicked, this, &QgsMapLayerLoadStyleDialog::deleteStyleFromDB );
133 connect( this, &QgsMapLayerLoadStyleDialog::rejected, [ = ]
134 {
135 QgsSettings().setValue( QStringLiteral( "style/lastLoadStyleTypeSelection" ), currentStyleType() );
136 } );
137
138 setTabOrder( mRelatedTable, mOthersTable );
139
140 mStyleCategoriesListView->adjustSize();
141}
142
143QgsMapLayer::StyleCategories QgsMapLayerLoadStyleDialog::styleCategories() const
144{
145 return mModel->categories();
146}
147
149{
150 QgsLayerPropertiesDialog::StyleType type = mStyleTypeComboBox->currentData().value<QgsLayerPropertiesDialog::StyleType>();
151 if ( type == QgsLayerPropertiesDialog::QML )
152 {
153 const QFileInfo fi( mFileWidget->filePath() );
154 if ( fi.exists() && fi.suffix().compare( QStringLiteral( "sld" ), Qt::CaseInsensitive ) == 0 )
156 }
157 return type;
158}
159
161{
162 return QFileInfo( mFileWidget->filePath() ).suffix();
163}
164
166{
167 return mFileWidget->filePath();
168}
169
170void QgsMapLayerLoadStyleDialog::initializeLists( const QStringList &ids, const QStringList &names, const QStringList &descriptions, int sectionLimit )
171{
172 // -1 means no ids
173 mSectionLimit = sectionLimit;
174 const int relatedTableNOfCols = sectionLimit > 0 ? 2 : 1;
175 const int othersTableNOfCols = ( sectionLimit >= 0 && ids.count() - sectionLimit > 0 ) ? 2 : 1;
176 const QString twoColsHeader( QStringLiteral( "Name;Description" ) );
177 const QString oneColsHeader( QStringLiteral( "No styles found in the database" ) );
178 const QString relatedTableHeader = relatedTableNOfCols == 1 ? oneColsHeader : twoColsHeader;
179 const QString othersTableHeader = othersTableNOfCols == 1 ? oneColsHeader : twoColsHeader;
180
181 mRelatedTable->setColumnCount( relatedTableNOfCols );
182 mOthersTable->setColumnCount( othersTableNOfCols );
183 mRelatedTable->setHorizontalHeaderLabels( relatedTableHeader.split( ';' ) );
184 mOthersTable->setHorizontalHeaderLabels( othersTableHeader.split( ';' ) );
185 mRelatedTable->setRowCount( sectionLimit );
186 mOthersTable->setRowCount( sectionLimit >= 0 ? ( ids.count() - sectionLimit ) : 0 );
187 mRelatedTable->setDisabled( relatedTableNOfCols == 1 );
188 mOthersTable->setDisabled( othersTableNOfCols == 1 );
189
190 if ( sectionLimit >= 0 )
191 {
192 for ( int i = 0; i < sectionLimit; i++ )
193 {
194 QTableWidgetItem *item = new QTableWidgetItem( names.value( i, QString() ) );
195 item->setData( Qt::UserRole, ids[i] );
196 mRelatedTable->setItem( i, 0, item );
197 mRelatedTable->setItem( i, 1, new QTableWidgetItem( descriptions.value( i, QString() ) ) );
198 }
199 for ( int i = sectionLimit; i < ids.count(); i++ )
200 {
201 const int j = i - sectionLimit;
202 QTableWidgetItem *item = new QTableWidgetItem( names.value( i, QString() ) );
203 item->setData( Qt::UserRole, ids[i] );
204 mOthersTable->setItem( j, 0, item );
205 mOthersTable->setItem( j, 1, new QTableWidgetItem( descriptions.value( i, QString() ) ) );
206 }
207 }
208}
209
211{
212 return mSelectedStyleId;
213}
214
215void QgsMapLayerLoadStyleDialog::onRelatedTableSelectionChanged()
216{
217 selectionChanged( mRelatedTable );
218 if ( mRelatedTable->selectionModel()->hasSelection() )
219 {
220 if ( mOthersTable->selectionModel()->hasSelection() )
221 {
222 disconnect( mOthersTable->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsMapLayerLoadStyleDialog::onOthersTableSelectionChanged );
223 const QTableWidgetSelectionRange range( 0, 0, mOthersTable->rowCount() - 1, mOthersTable->columnCount() - 1 );
224 mOthersTable->setRangeSelected( range, false );
225 connect( mOthersTable->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsMapLayerLoadStyleDialog::onOthersTableSelectionChanged );
226 }
227 }
228}
229
230void QgsMapLayerLoadStyleDialog::onOthersTableSelectionChanged()
231{
232 selectionChanged( mOthersTable );
233 if ( mOthersTable->selectionModel()->hasSelection() )
234 {
235 if ( mRelatedTable->selectionModel()->hasSelection() )
236 {
237 disconnect( mRelatedTable->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsMapLayerLoadStyleDialog::onRelatedTableSelectionChanged );
238 const QTableWidgetSelectionRange range( 0, 0, mRelatedTable->rowCount() - 1, mRelatedTable->columnCount() - 1 );
239 mRelatedTable->setRangeSelected( range, false );
240 connect( mRelatedTable->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsMapLayerLoadStyleDialog::onRelatedTableSelectionChanged );
241 }
242 }
243}
244
245void QgsMapLayerLoadStyleDialog::selectionChanged( QTableWidget *styleTable )
246{
247 QTableWidgetItem *item = nullptr;
248 const QList<QTableWidgetItem *> selected = styleTable->selectedItems();
249
250 if ( !selected.isEmpty() )
251 {
252 item = selected.at( 0 );
253 mSelectedStyleName = item->text();
254 mSelectedStyleId = item->data( Qt::UserRole ).toString();
255 mLoadButton->setEnabled( true );
256 mDeleteButton->setEnabled( true );
257 }
258 else
259 {
260 mSelectedStyleName.clear();
261 mSelectedStyleId.clear();
262 mLoadButton->setEnabled( false );
263 mDeleteButton->setEnabled( false );
264 }
265
266 updateLoadButtonState();
267}
268
270{
271 QgsSettings settings;
272 settings.setFlagValue( QStringLiteral( "style/lastStyleCategories" ), styleCategories() );
273 settings.setValue( QStringLiteral( "style/lastLoadStyleTypeSelection" ), currentStyleType() );
274 QDialog::accept();
275}
276
277void QgsMapLayerLoadStyleDialog::deleteStyleFromDB()
278{
279 QString msgError;
280 const QString opInfo = QObject::tr( "Delete style %1 from %2" ).arg( mSelectedStyleName, mLayer->providerType() );
281
282 if ( QMessageBox::question( nullptr, QObject::tr( "Delete Style" ),
283 QObject::tr( "Are you sure you want to delete the style %1?" ).arg( mSelectedStyleName ),
284 QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes )
285 return;
286
287 mLayer->deleteStyleFromDatabase( mSelectedStyleId, msgError );
288 if ( !msgError.isNull() )
289 {
290 QgsDebugError( opInfo + " failed." );
291 QMessageBox::warning( this, opInfo, tr( "%1: fail. %2" ).arg( opInfo, msgError ) );
292 }
293 else
294 {
295// QgisApp::instance()->messageBar()->pushMessage( opInfo, tr( "%1: success" ).arg( opInfo ), Qgis::MessageLevel::Info, QgisApp::instance()->messageTimeout() );
296
297 //Delete all rows from the UI table widgets
298 mRelatedTable->setRowCount( 0 );
299 mOthersTable->setRowCount( 0 );
300
301 //Fill UI widgets again from DB. Other users might have changed the styles meanwhile.
302 QString errorMsg;
303 QStringList ids, names, descriptions;
304 //get the list of styles in the db
305 const int sectionLimit = mLayer->listStylesInDatabase( ids, names, descriptions, errorMsg );
306 if ( !errorMsg.isNull() )
307 {
308 QMessageBox::warning( this, tr( "Error occurred while retrieving styles from database" ), errorMsg );
309 }
310 else
311 {
312 initializeLists( ids, names, descriptions, sectionLimit );
313 }
314 }
315}
316
317void QgsMapLayerLoadStyleDialog::updateLoadButtonState()
318{
320 mLoadButton->setEnabled( ( type == QgsLayerPropertiesDialog::DatasourceDatabase
321 && ( mRelatedTable->selectionModel()->hasSelection() || mOthersTable->selectionModel()->hasSelection()
322 ) ) ||
323 ( type != QgsLayerPropertiesDialog::DatasourceDatabase && !mFileWidget->filePath().isEmpty() ) ||
325}
326
327void QgsMapLayerLoadStyleDialog::showHelp()
328{
329 QgsHelp::openHelp( QStringLiteral( "introduction/general_tools.html#save-and-share-layer-properties" ) );
330}
@ Group
Composite group layer. Added in QGIS 3.24.
@ Plugin
Plugin based layer.
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ Vector
Vector layer.
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ Raster
Raster layer.
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
virtual Qgis::ProviderStyleStorageCapabilities styleStorageCapabilities() const
Returns the style storage capabilities.
@ GetFile
Select a single file.
void fileChanged(const QString &path)
Emitted whenever the current file or directory path is changed.
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition qgsgui.cpp:194
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition qgshelp.cpp:38
QgsMapLayer::StyleCategories styleCategories() const
Returns the list of selected style categories the user has opted to load.
void initializeLists(const QStringList &ids, const QStringList &names, const QStringList &descriptions, int sectionLimit)
Initialize list of database stored styles.
QString selectedStyleId()
Returns the ID of the selected database stored style.
QgsMapLayerLoadStyleDialog(QgsMapLayer *layer, QWidget *parent=nullptr)
Constructor for QgsMapLayerLoadStyleDialog, associated with the specified map layer.
QString filePath() const
Returns the full path to the selected layer style source file.
QString fileExtension() const
Returns the file extension for the selected layer style source file.
QgsLayerPropertiesDialog::StyleType currentStyleType() const
Returns the selected style type.
void setCategories(QgsMapLayer::StyleCategories categories)
Reset the model data.
QgsMapLayer::StyleCategories categories() const
Returns the categories as defined in the model.
Base class for all map layer types.
Definition qgsmaplayer.h:74
virtual bool deleteStyleFromDatabase(const QString &styleId, QString &msgError)
Deletes a style from the database.
QString providerType() const
Returns the provider type (provider key) for this layer.
virtual int listStylesInDatabase(QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError)
Lists all the style in db split into related to the layer and not related to.
Qgis::LayerType type
Definition qgsmaplayer.h:81
virtual Q_INVOKABLE QgsDataProvider * dataProvider()
Returns the layer's data provider, it may be nullptr.
This class is a composition of two QSettings instances:
Definition qgssettings.h:63
T flagValue(const QString &key, const T &defaultValue, const Section section=NoSection)
Returns the setting value for a setting based on a flag.
void setFlagValue(const QString &key, const T &value, const Section section=NoSection)
Set the value of a setting based on a flag.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
#define QgsDebugError(str)
Definition qgslogger.h:38