QGIS API Documentation 3.30.0-'s-Hertogenbosch (f186b8efe0)
qgsmaplayerstylemanager.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmaplayerstylemanager.cpp
3 --------------------------------------
4 Date : January 2015
5 Copyright : (C) 2015 by Martin Dobias
6 Email : wonder dot sk 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 ***************************************************************************/
15
17#include "qgsmaplayerstyle.h"
18#include "qgsmaplayer.h"
19
20#include "qgslogger.h"
21
22#include <QDomElement>
23#include <QTextStream>
24
26 : mLayer( layer )
27
28{
29 reset();
30}
31
32QString QgsMapLayerStyleManager::defaultStyleName()
33{
34 return tr( "default" );
35}
36
37
39{
40 mStyles.insert( defaultStyleName(), QgsMapLayerStyle() ); // insert entry for the default current style
41 mCurrentStyle = defaultStyleName();
42}
43
44void QgsMapLayerStyleManager::readXml( const QDomElement &mgrElement )
45{
46 mCurrentStyle = mgrElement.attribute( QStringLiteral( "current" ) );
47 if ( mCurrentStyle.isEmpty() )
48 {
49 // For old project made with QGIS 2, we migrate to "default".
50 mCurrentStyle = defaultStyleName();
51 }
52
53 mStyles.clear();
54 QDomElement ch = mgrElement.firstChildElement( QStringLiteral( "map-layer-style" ) );
55 while ( !ch.isNull() )
56 {
57 QString name = ch.attribute( QStringLiteral( "name" ) );
58 if ( name.isEmpty() )
59 {
60 // For old project made with QGIS 2, we migrate to "default".
61 name = defaultStyleName();
62 }
64 style.readXml( ch );
65 mStyles.insert( name, style );
66
67 ch = ch.nextSiblingElement( QStringLiteral( "map-layer-style" ) );
68 }
69}
70
71void QgsMapLayerStyleManager::writeXml( QDomElement &mgrElement ) const
72{
73 QDomDocument doc = mgrElement.ownerDocument();
74 mgrElement.setAttribute( QStringLiteral( "current" ), mCurrentStyle );
75
76 const auto constStyles = styles();
77 for ( const QString &name : constStyles )
78 {
79 QDomElement ch = doc.createElement( QStringLiteral( "map-layer-style" ) );
80 ch.setAttribute( QStringLiteral( "name" ), name );
81 mStyles[name].writeXml( ch );
82 mgrElement.appendChild( ch );
83 }
84}
85
87{
88 return mStyles.keys();
89}
90
91QMap<QString, QgsMapLayerStyle> QgsMapLayerStyleManager::mapLayerStyles() const
92{
93 return mStyles;
94}
95
97{
98 if ( name == mCurrentStyle )
99 {
100 // current style's entry is always kept invalid - get the style data from layer's properties
101 QgsMapLayerStyle curr;
102 curr.readFromLayer( mLayer );
103 return curr;
104 }
105
106 return mStyles.value( name );
107}
108
109bool QgsMapLayerStyleManager::addStyle( const QString &name, const QgsMapLayerStyle &style )
110{
111 if ( mStyles.contains( name ) )
112 return false;
113 if ( !style.isValid() )
114 return false;
115
116 mStyles.insert( name, style );
117 emit styleAdded( name );
118 return true;
119}
120
122{
124 style.readFromLayer( mLayer );
125 return addStyle( name, style );
126}
127
128bool QgsMapLayerStyleManager::removeStyle( const QString &name )
129{
130 if ( !mStyles.contains( name ) )
131 return false;
132 if ( mStyles.count() == 1 )
133 return false; // cannot remove the last one
134
135 // change to a different style if this one is the current
136 if ( mCurrentStyle == name )
137 {
138 QStringList keys = mStyles.keys();
139 QString newCurrent = keys[0];
140 if ( newCurrent == name )
141 newCurrent = keys[1]; // there must be at least one more
142 setCurrentStyle( newCurrent );
143 }
144
145 mStyles.remove( name );
146 emit styleRemoved( name );
147 return true;
148}
149
150bool QgsMapLayerStyleManager::renameStyle( const QString &name, const QString &newName )
151{
152 if ( !mStyles.contains( name ) || mStyles.contains( newName ) )
153 return false;
154
155 if ( name == mCurrentStyle )
156 mCurrentStyle = newName;
157
158 mStyles[newName] = mStyles[name];
159 mStyles.remove( name );
160 emit styleRenamed( name, newName );
161 return true;
162}
163
165{
166 return mCurrentStyle;
167}
168
170{
171 if ( !mStyles.contains( name ) )
172 return false;
173
174 if ( mCurrentStyle == name )
175 return true; // nothing to do
176
177 mStyles[mCurrentStyle].readFromLayer( mLayer ); // sync before unloading it
178 mCurrentStyle = name;
179 mStyles[mCurrentStyle].writeToLayer( mLayer );
180 mStyles[mCurrentStyle].clear(); // current style does not keep any stored data
181 emit currentStyleChanged( mCurrentStyle );
182
183 mLayer->triggerRepaint();
184 return true;
185}
186
187bool QgsMapLayerStyleManager::setOverrideStyle( const QString &styleDef )
188{
189 if ( mOverriddenOriginalStyle )
190 return false; // cannot override the style more than once!
191
192 mLayer->blockSignals( true );
193 if ( mStyles.contains( styleDef ) )
194 {
195 mOverriddenOriginalStyle = new QgsMapLayerStyle;
196 mOverriddenOriginalStyle->readFromLayer( mLayer );
197
198 // apply style name
199 mStyles[styleDef].writeToLayer( mLayer );
200 }
201 else if ( styleDef.startsWith( '<' ) )
202 {
203 mOverriddenOriginalStyle = new QgsMapLayerStyle;
204 mOverriddenOriginalStyle->readFromLayer( mLayer );
205
206 // apply style XML
207 const QgsMapLayerStyle overrideStyle( styleDef );
208 overrideStyle.writeToLayer( mLayer );
209 }
210 mLayer->blockSignals( false );
211
212 return true;
213}
214
216{
217 if ( !mOverriddenOriginalStyle )
218 return false;
219
220 mLayer->blockSignals( true );
221 mOverriddenOriginalStyle->writeToLayer( mLayer );
222 mLayer->blockSignals( false );
223
224 delete mOverriddenOriginalStyle;
225 mOverriddenOriginalStyle = nullptr;
226 return true;
227}
228
229bool QgsMapLayerStyleManager::isDefault( const QString &styleName )
230{
231 return styleName == defaultStyleName();
232}
233
235{
236 const QStringList styleNames = other->mStyles.keys();
237
238 for ( const QString &styleName : styleNames )
239 {
240 mStyles.remove( styleName );
241 addStyle( styleName, other->style( styleName ) );
242 }
243}
Management of styles for use with one map layer.
bool addStyle(const QString &name, const QgsMapLayerStyle &style)
Add a style with given name and data.
QString currentStyle() const
Returns name of the current style.
bool removeStyle(const QString &name)
Remove a stored style.
void copyStylesFrom(QgsMapLayerStyleManager *other)
Copies all styles from other.
QStringList styles() const
Returns list of all defined style names.
bool setCurrentStyle(const QString &name)
Set a different style as the current style - will apply it to the layer.
static bool isDefault(const QString &styleName)
Returns true if this is the default style.
void styleAdded(const QString &name)
Emitted when a new style has been added.
void writeXml(QDomElement &mgrElement) const
Write configuration (for project saving)
void reset()
Reset the style manager to a basic state - with one default style which is set as current.
void styleRenamed(const QString &oldName, const QString &newName)
Emitted when a style has been renamed.
bool restoreOverrideStyle()
Restore the original store after a call to setOverrideStyle()
bool addStyleFromLayer(const QString &name)
Add style by cloning the current one.
bool renameStyle(const QString &name, const QString &newName)
Rename a stored style to a different name.
QgsMapLayerStyleManager(QgsMapLayer *layer)
Construct a style manager associated with a map layer (must not be nullptr).
QMap< QString, QgsMapLayerStyle > mapLayerStyles() const
Gets available styles for the associated map layer.
bool setOverrideStyle(const QString &styleDef)
Temporarily apply a different style to the layer.
QgsMapLayerStyle style(const QString &name) const
Returns data of a stored style - accessed by its unique name.
void readXml(const QDomElement &mgrElement)
Read configuration (for project loading)
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.
Stores style information (renderer, opacity, labeling, diagrams etc.) applicable to a map layer.
void readXml(const QDomElement &styleElement)
Read style configuration (for project file reading)
void readFromLayer(QgsMapLayer *layer)
Store layer's active style information in the instance.
void writeToLayer(QgsMapLayer *layer) const
Apply stored layer's style information to the layer.
bool isValid() const
Tell whether the style is valid (i.e. there is something stored in it)
Base class for all map layer types.
Definition: qgsmaplayer.h:73
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.