QGIS API Documentation 4.3.0-Master (0cfde48c85b)
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 mModel = new QgsMapLayerStyleModel( layer->styleManager(), this );
173 mStyleList = new QListView( this );
174 mStyleList->setModel( mModel );
175 mStyleList->setViewMode( QListView::ListMode );
176 mStyleList->setResizeMode( QListView::Adjust );
177
178 QToolBar *toolbar = new QToolBar( this );
179 QAction *addAction = toolbar->addAction( tr( "Add" ) );
180 addAction->setIcon( QgsApplication::getThemeIcon( u"symbologyAdd.svg"_s ) );
181 connect( addAction, &QAction::triggered, this, &QgsMapLayerStyleManagerWidget::addStyle );
182 QAction *removeAction = toolbar->addAction( tr( "Remove Current" ) );
183 removeAction->setIcon( QgsApplication::getThemeIcon( u"symbologyRemove.svg"_s ) );
184 connect( removeAction, &QAction::triggered, this, &QgsMapLayerStyleManagerWidget::removeStyle );
185 QAction *loadFromFileAction = toolbar->addAction( tr( "Load Style" ) );
186 loadFromFileAction->setIcon( QgsApplication::getThemeIcon( u"/mActionFileOpen.svg"_s ) );
187 connect( loadFromFileAction, &QAction::triggered, this, &QgsMapLayerStyleManagerWidget::loadStyle );
188 QAction *saveAction = toolbar->addAction( tr( "Save Style" ) );
189 saveAction->setIcon( QgsApplication::getThemeIcon( u"mActionFileSave.svg"_s ) );
190 connect( saveAction, &QAction::triggered, this, &QgsMapLayerStyleManagerWidget::saveStyle );
191 QAction *saveAsDefaultAction = toolbar->addAction( tr( "Save as Default" ) );
192 connect( saveAsDefaultAction, &QAction::triggered, this, &QgsMapLayerStyleManagerWidget::saveAsDefault );
193 QAction *loadDefaultAction = toolbar->addAction( tr( "Restore Default" ) );
194 connect( loadDefaultAction, &QAction::triggered, this, &QgsMapLayerStyleManagerWidget::loadDefault );
195
196 connect( mStyleList->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsMapLayerStyleManagerWidget::selectionChanged );
197
198 setLayout( new QVBoxLayout() );
199 layout()->setContentsMargins( 0, 0, 0, 0 );
200 layout()->addWidget( toolbar );
201 layout()->addWidget( mStyleList );
202
203 connect( mLayer->styleManager(), &QgsMapLayerStyleManager::currentStyleChanged, this, &QgsMapLayerStyleManagerWidget::currentStyleChanged );
204
205 const QString active = mLayer->styleManager()->currentStyle();
206 currentStyleChanged( active );
207}
208
209void QgsMapLayerStyleManagerWidget::selectionChanged( const QItemSelection &selected, const QItemSelection & )
210{
211 if ( !mLayer || selected.empty() )
212 return;
213
214 const QModelIndex index = selected.indexes().first();
215 if ( !index.isValid() )
216 return;
217
218 const QString name = index.data().toString();
220}
221
222void QgsMapLayerStyleManagerWidget::currentStyleChanged( const QString &name )
223{
224 const QModelIndex listIndex = mModel->indexForName( name );
225 if ( listIndex.isValid() )
226 {
227 mStyleList->selectionModel()->select( listIndex, QItemSelectionModel::SelectionFlag::ClearAndSelect );
228 }
229}
230
231void QgsMapLayerStyleManagerWidget::addStyle()
232{
233 bool ok;
234 const QString text = QInputDialog::getText( nullptr, tr( "New Style" ), tr( "Style name:" ), QLineEdit::Normal, u"new style"_s, &ok );
235 if ( !ok || text.isEmpty() )
236 return;
237
238 const bool res = mLayer->styleManager()->addStyleFromLayer( text );
239 if ( res ) // make it active!
240 {
241 mLayer->styleManager()->setCurrentStyle( text );
242 }
243 else
244 {
245 QgsDebugError( "Failed to add style: " + text );
246 }
247}
248
249void QgsMapLayerStyleManagerWidget::removeStyle()
250{
251 const QString current = mLayer->styleManager()->currentStyle();
252 const bool res = mLayer->styleManager()->removeStyle( current );
253 if ( !res )
254 QgsDebugError( u"Failed to remove current style"_s );
255}
256
257void QgsMapLayerStyleManagerWidget::saveAsDefault()
258{
259 if ( !mLayer )
260 return;
261
262 switch ( mLayer->type() )
263 {
265 QgsVectorLayerProperties( mMapCanvas, mMapLayerConfigWidgetContext.messageBar(), qobject_cast<QgsVectorLayer *>( mLayer ) ).saveDefaultStyle();
266 break;
267
269 QgsRasterLayerProperties( mLayer, mMapCanvas ).saveStyleAsDefault();
270 break;
271
273 QgsMeshLayerProperties( mLayer, mMapCanvas ).saveStyleAsDefault();
274 break;
275
277 QgsVectorTileLayerProperties( qobject_cast<QgsVectorTileLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).saveStyleAsDefault();
278 break;
279
281 QgsPointCloudLayerProperties( qobject_cast<QgsPointCloudLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).saveStyleAsDefault();
282 break;
283
285 QgsTiledSceneLayerProperties( qobject_cast<QgsTiledSceneLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).saveStyleAsDefault();
286 break;
287
288 // Not available for these
292 break;
293 }
294}
295
296void QgsMapLayerStyleManagerWidget::loadDefault()
297{
298 if ( !mLayer )
299 return;
300
301 switch ( mLayer->type() )
302 {
304 QgsVectorLayerProperties( mMapCanvas, mMapLayerConfigWidgetContext.messageBar(), qobject_cast<QgsVectorLayer *>( mLayer ) ).loadDefaultStyle();
305 break;
306
308 QgsRasterLayerProperties( mLayer, mMapCanvas ).loadDefaultStyle();
309 break;
310
312 QgsMeshLayerProperties( mLayer, mMapCanvas ).loadDefaultStyle();
313 break;
314
316 QgsVectorTileLayerProperties( qobject_cast<QgsVectorTileLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).loadDefaultStyle();
317 break;
318
320 QgsPointCloudLayerProperties( qobject_cast<QgsPointCloudLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).loadDefaultStyle();
321 break;
322
324 QgsTiledSceneLayerProperties( qobject_cast<QgsTiledSceneLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).loadDefaultStyle();
325 break;
326
327 // Not available for these
331 break;
332 }
333}
334
335void QgsMapLayerStyleManagerWidget::saveStyle()
336{
337 if ( !mLayer )
338 return;
339
340 switch ( mLayer->type() )
341 {
343 QgsVectorLayerProperties( mMapCanvas, mMapLayerConfigWidgetContext.messageBar(), qobject_cast<QgsVectorLayer *>( mLayer ) ).saveStyleAs();
344 break;
345
347 QgsRasterLayerProperties( mLayer, mMapCanvas ).saveStyleAs();
348 break;
349
351 QgsMeshLayerProperties( mLayer, mMapCanvas ).saveStyleToFile();
352 break;
353
355 QgsVectorTileLayerProperties( qobject_cast<QgsVectorTileLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).saveStyleToFile();
356 break;
357
359 QgsPointCloudLayerProperties( qobject_cast<QgsPointCloudLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).saveStyleToFile();
360 break;
361
363 QgsTiledSceneLayerProperties( qobject_cast<QgsTiledSceneLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).saveStyleToFile();
364 break;
365
366 // Not available for these
370 break;
371 }
372}
373
374void QgsMapLayerStyleManagerWidget::loadStyle()
375{
376 if ( !mLayer )
377 return;
378
379 switch ( mLayer->type() )
380 {
382 QgsVectorLayerProperties( mMapCanvas, mMapLayerConfigWidgetContext.messageBar(), qobject_cast<QgsVectorLayer *>( mLayer ) ).loadStyle();
383 break;
384
386 QgsRasterLayerProperties( mLayer, mMapCanvas ).loadStyleFromFile();
387 break;
388
390 QgsMeshLayerProperties( mLayer, mMapCanvas ).loadStyleFromFile();
391 break;
392
394 QgsVectorTileLayerProperties( qobject_cast<QgsVectorTileLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).loadStyle();
395 break;
396
398 QgsPointCloudLayerProperties( qobject_cast<QgsPointCloudLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).loadStyleFromFile();
399 break;
400
402 QgsTiledSceneLayerProperties( qobject_cast<QgsTiledSceneLayer *>( mLayer ), mMapCanvas, mMapLayerConfigWidgetContext.messageBar() ).loadStyleFromFile();
403 break;
404
405 // Not available for these
409 break;
410 }
411}
@ 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.
QgsMapLayerConfigWidgetContext mMapLayerConfigWidgetContext
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.
bool setCurrentStyle(const QString &name)
Set a different style as the current style - will apply it to the 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
QgsMapLayerStyleManager * styleManager() const
Gets access to the layer's style manager.
#define QgsDebugError(str)
Definition qgslogger.h:71