QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
qgsstylealgorithms.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsstylealgorithms.cpp
3  ---------------------
4  begin : July 2019
5  copyright : (C) 2019 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgsstylealgorithms.h"
19 #include "qgsstyle.h"
20 
22 
23 QgsCombineStylesAlgorithm::QgsCombineStylesAlgorithm() = default;
24 
25 QgsCombineStylesAlgorithm::~QgsCombineStylesAlgorithm() = default;
26 
27 void QgsCombineStylesAlgorithm::initAlgorithm( const QVariantMap & )
28 {
29  addParameter( new QgsProcessingParameterMultipleLayers( QStringLiteral( "INPUT" ), QObject::tr( "Input databases" ), QgsProcessing::TypeFile ) );
30 
31  addParameter( new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT" ), QObject::tr( "Output style database" ),
32  QObject::tr( "Style files (*.xml)" ) ) );
33 
34  const QStringList options = QStringList()
35  << QObject::tr( "Symbols" )
36  << QObject::tr( "Color ramps" )
37  << QObject::tr( "Text formats" )
38  << QObject::tr( "Label settings" );
39  addParameter( new QgsProcessingParameterEnum( QStringLiteral( "OBJECTS" ), QObject::tr( "Objects to combine" ), options, true, QVariantList() << 0 << 1 << 2 << 3 ) );
40  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "SYMBOLS" ), QObject::tr( "Symbol count" ) ) );
41  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "COLORRAMPS" ), QObject::tr( "Color ramp count" ) ) );
42  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "TEXTFORMATS" ), QObject::tr( "Text format count" ) ) );
43  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "LABELSETTINGS" ), QObject::tr( "Label settings count" ) ) );
44 }
45 
46 QString QgsCombineStylesAlgorithm::name() const
47 {
48  return QStringLiteral( "combinestyles" );
49 }
50 
51 QString QgsCombineStylesAlgorithm::displayName() const
52 {
53  return QObject::tr( "Combine style databases" );
54 }
55 
56 QStringList QgsCombineStylesAlgorithm::tags() const
57 {
58  return QObject::tr( "symbols,colors,ramps,formats,labels,text,fonts,merge" ).split( ',' );
59 }
60 
61 QString QgsCombineStylesAlgorithm::group() const
62 {
63  return QObject::tr( "Cartography" );
64 }
65 
66 QString QgsCombineStylesAlgorithm::groupId() const
67 {
68  return QStringLiteral( "cartography" );
69 }
70 
71 QString QgsCombineStylesAlgorithm::shortHelpString() const
72 {
73  return QObject::tr( "This algorithm combines multiple QGIS style databases into a single style database. If any symbols exist with duplicate names between the different "
74  "source databases these will be renamed to have unique names in the output combined database." );
75 }
76 
77 QString QgsCombineStylesAlgorithm::shortDescription() const
78 {
79  return QObject::tr( "Combines multiple style databases into a single database." );
80 }
81 
82 QgsCombineStylesAlgorithm *QgsCombineStylesAlgorithm::createInstance() const
83 {
84  return new QgsCombineStylesAlgorithm();
85 }
86 
87 QVariantMap QgsCombineStylesAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
88 {
89  const QStringList inputs = parameterAsFileList( parameters, QStringLiteral( "INPUT" ), context );
90 
91  QList< QgsStyle::StyleEntity > objects;
92  const QList< int > selectedObjects = parameterAsEnums( parameters, QStringLiteral( "OBJECTS" ), context );
93  if ( selectedObjects.contains( 0 ) )
94  objects << QgsStyle::SymbolEntity;
95  if ( selectedObjects.contains( 1 ) )
96  objects << QgsStyle::ColorrampEntity;
97  if ( selectedObjects.contains( 2 ) )
98  objects << QgsStyle::TextFormatEntity;
99  if ( selectedObjects.contains( 3 ) )
101 
102  QgsStyle style;
103  style.createMemoryDatabase();
104 
105  int i = 0;
106  QMap< QgsStyle::StyleEntity, QSet< QString> > usedNames;
107  auto makeUniqueName = [&usedNames]( const QString & sourceName, QgsStyle::StyleEntity type )->QString
108  {
109  QString candidate = sourceName;
110  int i = 1;
111  bool exists = true;
112  while ( exists )
113  {
114  exists = usedNames[ type ].contains( candidate );
115  if ( !exists )
116  break;
117 
118  i++;
119  candidate = sourceName + QStringLiteral( " (%1)" ).arg( i );
120  }
121 
122  usedNames[ type ].insert( candidate );
123  return candidate;
124  };
125 
126  for ( const QString &source : inputs )
127  {
128  if ( feedback )
129  {
130  feedback->setProgress( 100 * i / static_cast< double >( inputs.count() ) );
131  feedback->pushInfo( QObject::tr( "Importing %1" ).arg( source ) );
132  }
133 
134  QgsStyle sourceStyle;
135  sourceStyle.createMemoryDatabase();
136  if ( !sourceStyle.importXml( source ) )
137  {
138  feedback->reportError( QObject::tr( "Could not read %1" ).arg( source ) );
139  i++;
140  continue;
141  }
142 
143  if ( objects.contains( QgsStyle::SymbolEntity ) )
144  {
145  const QStringList symbolNames = sourceStyle.symbolNames();
146  for ( const QString &name : symbolNames )
147  {
148  const QString newName = makeUniqueName( name, QgsStyle::SymbolEntity );
149  style.addSymbol( newName, sourceStyle.symbol( name ), true );
150  style.tagSymbol( QgsStyle::SymbolEntity, newName, sourceStyle.tagsOfSymbol( QgsStyle::SymbolEntity, name ) );
151  }
152  }
153  if ( objects.contains( QgsStyle::ColorrampEntity ) )
154  {
155  const QStringList colorRampNames = sourceStyle.colorRampNames();
156  for ( const QString &name : colorRampNames )
157  {
158  const QString newName = makeUniqueName( name, QgsStyle::ColorrampEntity );
159  style.addColorRamp( newName, sourceStyle.colorRamp( name ), true );
160  style.tagSymbol( QgsStyle::ColorrampEntity, newName, sourceStyle.tagsOfSymbol( QgsStyle::ColorrampEntity, name ) );
161  }
162  }
163  if ( objects.contains( QgsStyle::TextFormatEntity ) )
164  {
165  const QStringList formatNames = sourceStyle.textFormatNames();
166  for ( const QString &name : formatNames )
167  {
168  const QString newName = makeUniqueName( name, QgsStyle::TextFormatEntity );
169  style.addTextFormat( newName, sourceStyle.textFormat( name ), true );
170  style.tagSymbol( QgsStyle::TextFormatEntity, newName, sourceStyle.tagsOfSymbol( QgsStyle::TextFormatEntity, name ) );
171  }
172  }
173  if ( objects.contains( QgsStyle::LabelSettingsEntity ) )
174  {
175  const QStringList formatNames = sourceStyle.labelSettingsNames();
176  for ( const QString &name : formatNames )
177  {
178  const QString newName = makeUniqueName( name, QgsStyle::LabelSettingsEntity );
179  style.addLabelSettings( newName, sourceStyle.labelSettings( name ), true );
181  }
182  }
183 
184  i++;
185  }
186  if ( feedback )
187  {
188  feedback->setProgress( 100 );
189  feedback->pushInfo( QObject::tr( "Writing output file" ) );
190  }
191 
192  const QString file = parameterAsString( parameters, QStringLiteral( "OUTPUT" ), context );
193  if ( !style.exportXml( file ) )
194  {
195  throw QgsProcessingException( QObject::tr( "Error saving style database as %1" ).arg( file ) );
196  }
197 
198  QVariantMap results;
199  results.insert( QStringLiteral( "OUTPUT" ), file );
200  results.insert( QStringLiteral( "SYMBOLS" ), style.symbolCount() );
201  results.insert( QStringLiteral( "COLORRAMPS" ), style.colorRampCount() );
202  results.insert( QStringLiteral( "TEXTFORMATS" ), style.textFormatCount() );
203  results.insert( QStringLiteral( "LABELSETTINGS" ), style.labelSettingsCount() );
204  return results;
205 }
206 
208 
209 
210 
211 
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:63
Contains information about the context in which a processing algorithm is executed.
Custom exception class for processing related exceptions.
Definition: qgsexception.h:83
Base class for providing feedback from a processing algorithm.
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
A numeric output for processing algorithms.
An enum based parameter for processing algorithms, allowing for selection from predefined values.
A generic file based destination parameter, for specifying the destination path for a file (non-map l...
A parameter for processing algorithms which accepts multiple map layers.
@ TypeFile
Files (i.e. non map layer sources, such as text files)
Definition: qgsprocessing.h:53
int colorRampCount()
Returns count of color ramps.
Definition: qgsstyle.cpp:457
QgsTextFormat textFormat(const QString &name) const
Returns the text format with the specified name.
Definition: qgsstyle.cpp:2122
bool tagSymbol(StyleEntity type, const QString &symbol, const QStringList &tags)
Tags the symbol with the tags in the list.
Definition: qgsstyle.cpp:1757
QStringList textFormatNames() const
Returns a list of names of text formats in the style.
Definition: qgsstyle.cpp:2132
bool addColorRamp(const QString &name, QgsColorRamp *colorRamp, bool update=false)
Adds a color ramp to the style.
Definition: qgsstyle.cpp:297
QgsSymbol * symbol(const QString &name)
Returns a NEW copy of symbol.
Definition: qgsstyle.cpp:275
int labelSettingsCount() const
Returns count of label settings in the style.
Definition: qgsstyle.cpp:2191
StyleEntity
Enum for Entities involved in a style.
Definition: qgsstyle.h:179
@ LabelSettingsEntity
Label settings.
Definition: qgsstyle.h:185
@ TextFormatEntity
Text formats.
Definition: qgsstyle.h:184
@ SymbolEntity
Symbols.
Definition: qgsstyle.h:180
@ ColorrampEntity
Color ramps.
Definition: qgsstyle.h:182
QStringList tagsOfSymbol(StyleEntity type, const QString &symbol)
Returns the tags associated with the symbol.
Definition: qgsstyle.cpp:1913
QStringList colorRampNames() const
Returns a list of names of color ramps.
Definition: qgsstyle.cpp:462
int textFormatCount() const
Returns count of text formats in the style.
Definition: qgsstyle.cpp:2127
bool exportXml(const QString &filename)
Exports the style as a XML file.
Definition: qgsstyle.cpp:2536
QgsColorRamp * colorRamp(const QString &name) const
Returns a new copy of the specified color ramp.
Definition: qgsstyle.cpp:446
int symbolCount()
Returns count of symbols in style.
Definition: qgsstyle.cpp:286
bool createMemoryDatabase()
Creates a temporary memory database.
Definition: qgsstyle.cpp:515
QStringList labelSettingsNames() const
Returns a list of names of label settings in the style.
Definition: qgsstyle.cpp:2196
bool addTextFormat(const QString &name, const QgsTextFormat &format, bool update=false)
Adds a text format with the specified name to the style.
Definition: qgsstyle.cpp:321
QgsPalLayerSettings labelSettings(const QString &name) const
Returns the label settings with the specified name.
Definition: qgsstyle.cpp:2142
bool addSymbol(const QString &name, QgsSymbol *symbol, bool update=false)
Adds a symbol to style and takes symbol's ownership.
Definition: qgsstyle.cpp:181
QStringList symbolNames() const
Returns a list of names of symbols.
Definition: qgsstyle.cpp:291
bool importXml(const QString &filename)
Imports the symbols and colorramps into the default style database from the given XML file.
Definition: qgsstyle.cpp:2700
bool addLabelSettings(const QString &name, const QgsPalLayerSettings &settings, bool update=false)
Adds label settings with the specified name to the style.
Definition: qgsstyle.cpp:342