QGIS API Documentation 4.3.0-Master (8c22baaae17)
Loading...
Searching...
No Matches
qgsmaplayerstylemanagerwidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmaplayerstylemanagerwidget.cpp
3 ---------------------
4 begin : June 2016
5 copyright : (C) 2016 by Nathan Woodrow
6 email : woodrow dot nathan at gmail dot com
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 ***************************************************************************/
16
17#include "qgsapplication.h"
18#include "qgslogger.h"
19#include "qgsmapcanvas.h"
20#include "qgsmaplayer.h"
24#include "qgspointcloudlayer.h"
27#include "qgstiledscenelayer.h"
29#include "qgsvectorlayer.h"
31#include "qgsvectortilelayer.h"
33
34#include <QAction>
35#include <QFileDialog>
36#include <QInputDialog>
37#include <QMessageBox>
38#include <QString>
39#include <QToolBar>
40#include <QVBoxLayout>
41
42#include "moc_qgsmaplayerstylemanagerwidget.cpp"
43
44using namespace Qt::StringLiterals;
45
46//
47// QgsMapLayerStyleModel
48//
50 : QAbstractListModel( parent )
51 , mManager( manager )
52{
53 if ( mManager )
54 {
55 connect( mManager, &QgsMapLayerStyleManager::styleAdded, this, &QgsMapLayerStyleModel::styleAdded );
56 connect( mManager, &QgsMapLayerStyleManager::styleRemoved, this, &QgsMapLayerStyleModel::styleRemoved );
57 connect( mManager, &QgsMapLayerStyleManager::styleRenamed, this, &QgsMapLayerStyleModel::styleRenamed );
58
59 mStyleNames = mManager->styles();
60 }
61}
62
63int QgsMapLayerStyleModel::rowCount( const QModelIndex &parent ) const
64{
65 if ( parent.isValid() )
66 return 0;
67
68 return static_cast< int >( mStyleNames.size() );
69}
70
71QVariant QgsMapLayerStyleModel::data( const QModelIndex &index, int role ) const
72{
73 if ( index.row() < 0 || index.row() >= rowCount( QModelIndex() ) )
74 return QVariant();
75
76 switch ( role )
77 {
78 case Qt::DisplayRole:
79 case Qt::ToolTipRole:
80 case Qt::EditRole:
81 return mStyleNames.at( index.row() );
82
83 default:
84 break;
85 }
86 return QVariant();
87}
88
89bool QgsMapLayerStyleModel::setData( const QModelIndex &index, const QVariant &value, int role )
90{
91 if ( !mManager || !index.isValid() || role != Qt::EditRole )
92 {
93 return false;
94 }
95 if ( index.row() >= mStyleNames.size() )
96 {
97 return false;
98 }
99
100 if ( value.toString().isEmpty() )
101 return false;
102
103 //has name changed?
104 const bool changed = mStyleNames.at( index.row() ) != value.toString();
105 if ( !changed )
106 return true;
107
108 //check if name already exists
109 if ( mStyleNames.contains( value.toString() ) )
110 return false;
111
112 mManager->renameStyle( mStyleNames[index.row()], value.toString() );
113 mStyleNames[index.row()] = value.toString();
114 return true;
115}
116
117Qt::ItemFlags QgsMapLayerStyleModel::flags( const QModelIndex &index ) const
118{
119 Qt::ItemFlags flags = QAbstractListModel::flags( index );
120 if ( index.isValid() )
121 {
122 return flags | Qt::ItemIsEditable;
123 }
124 else
125 {
126 return flags;
127 }
128}
129
130QModelIndex QgsMapLayerStyleModel::indexForName( const QString &name ) const
131{
132 const int row = static_cast< int >( mStyleNames.indexOf( name ) );
133 if ( row >= 0 )
134 {
135 return index( row, 0, QModelIndex() );
136 }
137 return QModelIndex();
138}
139
140void QgsMapLayerStyleModel::styleAdded( const QString &name )
141{
142 beginInsertRows( QModelIndex(), static_cast< int >( mStyleNames.size() ), static_cast< int >( mStyleNames.size() ) );
143 mStyleNames << name;
144 endInsertRows();
145}
146
147void QgsMapLayerStyleModel::styleRemoved( const QString &name )
148{
149 const int row = static_cast< int >( mStyleNames.indexOf( name ) );
150 if ( row >= 0 )
151 {
152 beginRemoveRows( QModelIndex(), row, row );
153 mStyleNames.remove( row );
154 endRemoveRows();
155 }
156}
157
158void QgsMapLayerStyleModel::styleRenamed( const QString &oldname, const QString &newname )
159{
160 const QModelIndex styleIndex = indexForName( oldname );
161 mStyleNames[styleIndex.row()] = newname;
162 emit dataChanged( styleIndex, styleIndex );
163}
164
165//
166// QgsMapLayerStyleManagerWidget
167//
168
170 : QgsMapLayerConfigWidget( layer, canvas, parent )
171{
172 mStyleList = new QListView( this );
173 if ( layer )
174 {
175 mModel = new QgsMapLayerStyleModel( layer->styleManager(), this );
176 mStyleList->setModel( mModel );
177 }
178 mStyleList->setObjectName( "mStyleList" );
179 mStyleList->setViewMode( QListView::ListMode );
180 mStyleList->setResizeMode( QListView::Adjust );
181
182 QToolBar *toolbar = new QToolBar( this );
183 QAction *addAction = toolbar->addAction( tr( "Add" ) );
184 addAction->setIcon( QgsApplication::getThemeIcon( u"symbologyAdd.svg"_s ) );
185 connect( addAction, &QAction::triggered, this, &QgsMapLayerStyleManagerWidget::addStyle );
186 QAction *removeAction = toolbar->addAction( tr( "Remove Current" ) );
187 removeAction->setIcon( QgsApplication::getThemeIcon( u"symbologyRemove.svg"_s ) );
188 connect( removeAction, &QAction::triggered, this, &QgsMapLayerStyleManagerWidget::removeStyle );
189 QAction *loadFromFileAction = toolbar->addAction( tr( "Load Style" ) );
190 loadFromFileAction->setIcon( QgsApplication::getThemeIcon( u"/mActionFileOpen.svg"_s ) );
191 connect( loadFromFileAction, &QAction::triggered, this, &QgsMapLayerStyleManagerWidget::loadStyle );
192 QAction *saveAction = toolbar->addAction( tr( "Save Style" ) );
193 saveAction->setIcon( QgsApplication::getThemeIcon( u"mActionFileSave.svg"_s ) );
194 connect( saveAction, &QAction::triggered, this, &QgsMapLayerStyleManagerWidget::saveStyle );
195 QAction *saveAsDefaultAction = toolbar->addAction( tr( "Save as Default" ) );
196 connect( saveAsDefaultAction, &QAction::triggered, this, &QgsMapLayerStyleManagerWidget::saveAsDefault );
197 QAction *loadDefaultAction = toolbar->addAction( tr( "Restore Default" ) );
198 connect( loadDefaultAction, &QAction::triggered, this, &QgsMapLayerStyleManagerWidget::loadDefault );
199
200 setLayout( new QVBoxLayout() );
201 layout()->setContentsMargins( 0, 0, 0, 0 );
202 layout()->addWidget( toolbar );
203 layout()->addWidget( mStyleList );
204
205 if ( mLayer )
206 {
207 connect( mLayer->styleManager(), &QgsMapLayerStyleManager::currentStyleChanged, this, &QgsMapLayerStyleManagerWidget::currentStyleChanged );
208 connect( mStyleList->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsMapLayerStyleManagerWidget::selectionChanged );
209
210 const QString active = mLayer->styleManager()->currentStyle();
211 currentStyleChanged( active );
212 }
213}
214
216{
217 if ( layer == mLayer )
218 {
219 return;
220 }
221 if ( mLayer )
222 {
223 disconnect( mLayer->styleManager(), &QgsMapLayerStyleManager::currentStyleChanged, this, &QgsMapLayerStyleManagerWidget::currentStyleChanged );
224 }
225
226 if ( mModel )
227 {
228 mStyleList->setModel( nullptr );
229 mModel->deleteLater();
230 mModel = nullptr;
231 }
232 mLayer = layer;
233 if ( mLayer )
234 {
235 connect( mLayer->styleManager(), &QgsMapLayerStyleManager::currentStyleChanged, this, &QgsMapLayerStyleManagerWidget::currentStyleChanged );
236 mModel = new QgsMapLayerStyleModel( layer->styleManager(), this );
237 mStyleList->setModel( mModel );
238 currentStyleChanged( mLayer->styleManager()->currentStyle() );
239 connect( mStyleList->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsMapLayerStyleManagerWidget::selectionChanged );
240 }
241}
242
243void QgsMapLayerStyleManagerWidget::selectionChanged( const QItemSelection &selected, const QItemSelection & )
244{
245 if ( !mLayer || selected.empty() )
246 return;
247
248 const QModelIndex index = selected.indexes().first();
249 if ( !index.isValid() )
250 return;
251
252 const QString name = index.data().toString();
253 mLayer->styleManager()->setCurrentStyle( name );
254}
255
256void QgsMapLayerStyleManagerWidget::currentStyleChanged( const QString &name )
257{
258 const QModelIndex listIndex = mModel->indexForName( name );
259 if ( listIndex.isValid() )
260 {
261 mStyleList->selectionModel()->select( listIndex, QItemSelectionModel::SelectionFlag::ClearAndSelect );
262 }
263}
264
265void QgsMapLayerStyleManagerWidget::addStyle()
266{
267 bool ok;
268 const QString text = QInputDialog::getText( nullptr, tr( "New Style" ), tr( "Style name:" ), QLineEdit::Normal, u"new style"_s, &ok );
269 if ( !ok || text.isEmpty() )
270 return;
271
272 const bool res = mLayer->styleManager()->addStyleFromLayer( text );
273 if ( res ) // make it active!
274 {
275 mLayer->styleManager()->setCurrentStyle( text );
276 }
277 else
278 {
279 QgsDebugError( "Failed to add style: " + text );
280 }
281}
282
283void QgsMapLayerStyleManagerWidget::removeStyle()
284{
285 const QString current = mLayer->styleManager()->currentStyle();
286 const bool res = mLayer->styleManager()->removeStyle( current );
287 if ( !res )
288 QgsDebugError( u"Failed to remove current style"_s );
289}
290
291void QgsMapLayerStyleManagerWidget::saveAsDefault()
292{
293 if ( !mLayer )
294 return;
295
296 switch ( mLayer->type() )
297 {
299 QgsVectorLayerProperties( mMapCanvas, mMapLayerConfigWidgetContext.messageBar(), qobject_cast<QgsVectorLayer *>( mLayer ) ).saveDefaultStyle();
300 break;
301
303 QgsRasterLayerProperties( mLayer, mMapCanvas ).saveStyleAsDefault();
304 break;
305
307 QgsMeshLayerProperties( mLayer, mMapCanvas ).saveStyleAsDefault();
308 break;
309
311 QgsVectorTileLayerProperties( qobject_cast<QgsVectorTileLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).saveStyleAsDefault();
312 break;
313
315 QgsPointCloudLayerProperties( qobject_cast<QgsPointCloudLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).saveStyleAsDefault();
316 break;
317
319 QgsTiledSceneLayerProperties( qobject_cast<QgsTiledSceneLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).saveStyleAsDefault();
320 break;
321
322 // Not available for these
326 break;
327 }
328}
329
330void QgsMapLayerStyleManagerWidget::loadDefault()
331{
332 if ( !mLayer )
333 return;
334
335 switch ( mLayer->type() )
336 {
338 QgsVectorLayerProperties( mMapCanvas, mMapLayerConfigWidgetContext.messageBar(), qobject_cast<QgsVectorLayer *>( mLayer ) ).loadDefaultStyle();
339 break;
340
342 QgsRasterLayerProperties( mLayer, mMapCanvas ).loadDefaultStyle();
343 break;
344
346 QgsMeshLayerProperties( mLayer, mMapCanvas ).loadDefaultStyle();
347 break;
348
350 QgsVectorTileLayerProperties( qobject_cast<QgsVectorTileLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).loadDefaultStyle();
351 break;
352
354 QgsPointCloudLayerProperties( qobject_cast<QgsPointCloudLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).loadDefaultStyle();
355 break;
356
358 QgsTiledSceneLayerProperties( qobject_cast<QgsTiledSceneLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).loadDefaultStyle();
359 break;
360
361 // Not available for these
365 break;
366 }
367}
368
369void QgsMapLayerStyleManagerWidget::saveStyle()
370{
371 if ( !mLayer )
372 return;
373
374 switch ( mLayer->type() )
375 {
377 QgsVectorLayerProperties( mMapCanvas, mMapLayerConfigWidgetContext.messageBar(), qobject_cast<QgsVectorLayer *>( mLayer ) ).saveStyleAs();
378 break;
379
381 QgsRasterLayerProperties( mLayer, mMapCanvas ).saveStyleAs();
382 break;
383
385 QgsMeshLayerProperties( mLayer, mMapCanvas ).saveStyleToFile();
386 break;
387
389 QgsVectorTileLayerProperties( qobject_cast<QgsVectorTileLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).saveStyleToFile();
390 break;
391
393 QgsPointCloudLayerProperties( qobject_cast<QgsPointCloudLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).saveStyleToFile();
394 break;
395
397 QgsTiledSceneLayerProperties( qobject_cast<QgsTiledSceneLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).saveStyleToFile();
398 break;
399
400 // Not available for these
404 break;
405 }
406}
407
408void QgsMapLayerStyleManagerWidget::loadStyle()
409{
410 if ( !mLayer )
411 return;
412
413 switch ( mLayer->type() )
414 {
416 QgsVectorLayerProperties( mMapCanvas, mMapLayerConfigWidgetContext.messageBar(), qobject_cast<QgsVectorLayer *>( mLayer ) ).loadStyle();
417 break;
418
420 QgsRasterLayerProperties( mLayer, mMapCanvas ).loadStyleFromFile();
421 break;
422
424 QgsMeshLayerProperties( mLayer, mMapCanvas ).loadStyleFromFile();
425 break;
426
428 QgsVectorTileLayerProperties( qobject_cast<QgsVectorTileLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).loadStyle();
429 break;
430
432 QgsPointCloudLayerProperties( qobject_cast<QgsPointCloudLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).loadStyleFromFile();
433 break;
434
436 QgsTiledSceneLayerProperties( qobject_cast<QgsTiledSceneLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).loadStyleFromFile();
437 break;
438
439 // Not available for these
443 break;
444 }
445}
@ Group
Composite group layer. Added in QGIS 3.24.
Definition qgis.h:214
@ Plugin
Plugin based layer.
Definition qgis.h:209
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
Definition qgis.h:215
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
Definition qgis.h:212
@ Vector
Vector layer.
Definition qgis.h:207
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
Definition qgis.h:211
@ Mesh
Mesh layer. Added in QGIS 3.2.
Definition qgis.h:210
@ Raster
Raster layer.
Definition qgis.h:208
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
Definition qgis.h:213
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Map canvas is a class for displaying all GIS data types on a canvas.
QgsMapLayerConfigWidget(QgsMapLayer *layer, QgsMapCanvas *canvas, QWidget *parent=nullptr)
A panel widget that can be shown in the map style dock.
QPointer< QgsMapLayer > mLayer
QgsMapLayerConfigWidgetContext mMapLayerConfigWidgetContext
QgsMapLayer * layer()
Returns the layer the widget is associated with.
void syncToLayer(QgsMapLayer *layer) final
Reset to original (vector layer) values.
QgsMapLayerStyleManagerWidget(QgsMapLayer *layer, QgsMapCanvas *canvas, QWidget *parent=nullptr)
Style manager widget to manage the layers styles.
Management of styles for use with one map layer.
void styleAdded(const QString &name)
Emitted when a new style has been added.
void styleRenamed(const QString &oldName, const QString &newName)
Emitted when a style has been renamed.
void currentStyleChanged(const QString &currentName)
Emitted when the current style has been changed.
void styleRemoved(const QString &name)
Emitted when a style has been removed.
A model for display of styles from a QgsMapLayerStyleManager.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QModelIndex indexForName(const QString &name) const
Returns the model index corresponding to the specified style name.
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
Qt::ItemFlags flags(const QModelIndex &index) const override
QgsMapLayerStyleModel(QgsMapLayerStyleManager *manager, QObject *parent=nullptr)
Constructor for QgsMapLayerStyleModel, showing styles from the specified manager.
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
Base class for all map layer types.
Definition qgsmaplayer.h:83
#define QgsDebugError(str)
Definition qgslogger.h:71