QGIS API Documentation 3.41.0-Master (cea29feecf2)
Loading...
Searching...
No Matches
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 "moc_qgsmaplayerstylemanager.cpp"
18#include "qgsmaplayerstyle.h"
19#include "qgsmaplayer.h"
20
21#include "qgslogger.h"
22
23#include <QDomElement>
24#include <QTextStream>
25
27 : mLayer( layer )
28
29{
30 reset();
31}
32
33QString QgsMapLayerStyleManager::defaultStyleName()
34{
35 return tr( "default" );
36}
37
38
40{
41 mStyles.insert( defaultStyleName(), QgsMapLayerStyle() ); // insert entry for the default current style
42 mCurrentStyle = defaultStyleName();
43}
44
45void QgsMapLayerStyleManager::readXml( const QDomElement &mgrElement )
46{
47 mCurrentStyle = mgrElement.attribute( QStringLiteral( "current" ) );
48 if ( mCurrentStyle.isEmpty() )
49 {
50 // For old project made with QGIS 2, we migrate to "default".
51 mCurrentStyle = defaultStyleName();
52 }
53
54 mStyles.clear();
55 QDomElement ch = mgrElement.firstChildElement( QStringLiteral( "map-layer-style" ) );
56 while ( !ch.isNull() )
57 {
58 QString name = ch.attribute( QStringLiteral( "name" ) );
59 if ( name.isEmpty() )
60 {
61 // For old project made with QGIS 2, we migrate to "default".
62 name = defaultStyleName();
63 }
65 style.readXml( ch );
66 mStyles.insert( name, style );
67
68 ch = ch.nextSiblingElement( QStringLiteral( "map-layer-style" ) );
69 }
70}
71
72void QgsMapLayerStyleManager::writeXml( QDomElement &mgrElement ) const
73{
74 QDomDocument doc = mgrElement.ownerDocument();
75 mgrElement.setAttribute( QStringLiteral( "current" ), mCurrentStyle );
76
77 const auto constStyles = styles();
78 for ( const QString &name : constStyles )
79 {
80 QDomElement ch = doc.createElement( QStringLiteral( "map-layer-style" ) );
81 ch.setAttribute( QStringLiteral( "name" ), name );
82 mStyles[name].writeXml( ch );
83 mgrElement.appendChild( ch );
84 }
85}
86
88{
89 return mStyles.keys();
90}
91
92QMap<QString, QgsMapLayerStyle> QgsMapLayerStyleManager::mapLayerStyles() const
93{
94 return mStyles;
95}
96
98{
99 if ( name == mCurrentStyle )
100 {
101 // current style's entry is always kept invalid - get the style data from layer's properties
102 QgsMapLayerStyle curr;
103 curr.readFromLayer( mLayer );
104 return curr;
105 }
106
107 return mStyles.value( name );
108}
109
110bool QgsMapLayerStyleManager::addStyle( const QString &name, const QgsMapLayerStyle &style )
111{
112 if ( mStyles.contains( name ) )
113 return false;
114 if ( !style.isValid() )
115 return false;
116
117 mStyles.insert( name, style );
118 emit styleAdded( name );
119 return true;
120}
121
123{
125 style.readFromLayer( mLayer );
126 return addStyle( name, style );
127}
128
129bool QgsMapLayerStyleManager::removeStyle( const QString &name )
130{
131 if ( !mStyles.contains( name ) )
132 return false;
133 if ( mStyles.count() == 1 )
134 return false; // cannot remove the last one
135
136 // change to a different style if this one is the current
137 if ( mCurrentStyle == name )
138 {
139 QStringList keys = mStyles.keys();
140 QString newCurrent = keys[0];
141 if ( newCurrent == name )
142 newCurrent = keys[1]; // there must be at least one more
143 setCurrentStyle( newCurrent );
144 }
145
146 mStyles.remove( name );
147 emit styleRemoved( name );
148 return true;
149}
150
151bool QgsMapLayerStyleManager::renameStyle( const QString &name, const QString &newName )
152{
153 if ( !mStyles.contains( name ) || mStyles.contains( newName ) )
154 return false;
155
156 if ( name == mCurrentStyle )
157 mCurrentStyle = newName;
158
159 mStyles[newName] = mStyles[name];
160 mStyles.remove( name );
161 emit styleRenamed( name, newName );
162 return true;
163}
164
166{
167 return mCurrentStyle;
168}
169
171{
172 if ( !mStyles.contains( name ) )
173 return false;
174
175 if ( mCurrentStyle == name )
176 return true; // nothing to do
177
178 mStyles[mCurrentStyle].readFromLayer( mLayer ); // sync before unloading it
179 mCurrentStyle = name;
180 mStyles[mCurrentStyle].writeToLayer( mLayer );
181 mStyles[mCurrentStyle].clear(); // current style does not keep any stored data
182 emit currentStyleChanged( mCurrentStyle );
183
184 mLayer->triggerRepaint();
185 return true;
186}
187
188bool QgsMapLayerStyleManager::setOverrideStyle( const QString &styleDef )
189{
190 if ( mOverriddenOriginalStyle )
191 return false; // cannot override the style more than once!
192
193 mLayer->blockSignals( true );
194 if ( mStyles.contains( styleDef ) )
195 {
196 mOverriddenOriginalStyle = new QgsMapLayerStyle;
197 mOverriddenOriginalStyle->readFromLayer( mLayer );
198
199 // apply style name
200 mStyles[styleDef].writeToLayer( mLayer );
201 }
202 else if ( styleDef.startsWith( '<' ) )
203 {
204 mOverriddenOriginalStyle = new QgsMapLayerStyle;
205 mOverriddenOriginalStyle->readFromLayer( mLayer );
206
207 // apply style XML
208 const QgsMapLayerStyle overrideStyle( styleDef );
209 overrideStyle.writeToLayer( mLayer );
210 }
211 mLayer->blockSignals( false );
212
213 return true;
214}
215
217{
218 if ( !mOverriddenOriginalStyle )
219 return false;
220
221 mLayer->blockSignals( true );
222 mOverriddenOriginalStyle->writeToLayer( mLayer );
223 mLayer->blockSignals( false );
224
225 delete mOverriddenOriginalStyle;
226 mOverriddenOriginalStyle = nullptr;
227 return true;
228}
229
230bool QgsMapLayerStyleManager::isDefault( const QString &styleName )
231{
232 return styleName == defaultStyleName();
233}
234
236{
237 const QStringList styleNames = other->mStyles.keys();
238
239 for ( const QString &styleName : styleNames )
240 {
241 mStyles.remove( styleName );
242 addStyle( styleName, other->style( styleName ) );
243 }
244}
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:76
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.