QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
qgsprojectstylealgorithms.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsprojectstylealgorithms.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 
19 #include "qgsstyle.h"
20 
22 
23 //
24 // QgsProjectToStyleVisitor
25 //
26 
27 QgsSaveToStyleVisitor::QgsSaveToStyleVisitor( QgsStyle *style, const QList<QgsStyle::StyleEntity> &objects )
28  : mStyle( style )
29  , mObjects( objects )
30 {
31 }
32 
33 bool QgsSaveToStyleVisitor::visit( const QgsStyleEntityVisitorInterface::StyleLeaf &entity )
34 {
35  if ( mObjects.empty() || mObjects.contains( entity.entity->type() ) )
36  {
37  const QString name = ( mParentNames.join( ' ' ) + ' ' + entity.description ).trimmed();
38  QString candidate = name;
39  int i = 1;
40  bool exists = true;
41  while ( exists )
42  {
43  exists = mStyle->allNames( entity.entity->type() ).contains( candidate );
44  if ( !exists )
45  break;
46 
47  i++;
48  candidate = name + QStringLiteral( " (%1)" ).arg( i );
49  }
50  mStyle->addEntity( candidate, entity.entity, true );
51  }
52  return true;
53 }
54 
55 bool QgsSaveToStyleVisitor::visitEnter( const QgsStyleEntityVisitorInterface::Node &node )
56 {
57  switch ( node.type )
58  {
66  break;
67 
73  mParentNames << node.description;
74  break;
75  }
76  return true;
77 }
78 
79 bool QgsSaveToStyleVisitor::visitExit( const QgsStyleEntityVisitorInterface::Node &node )
80 {
81  switch ( node.type )
82  {
90  break;
91 
97  mParentNames.pop_back();
98  break;
99  }
100  return true;
101 }
102 
103 //
104 // QgsStyleFromProjectAlgorithm
105 //
106 
107 QgsStyleFromProjectAlgorithm::QgsStyleFromProjectAlgorithm() = default;
108 
109 QgsStyleFromProjectAlgorithm::~QgsStyleFromProjectAlgorithm() = default;
110 
111 void QgsStyleFromProjectAlgorithm::initAlgorithm( const QVariantMap & )
112 {
113  addParameter( new QgsProcessingParameterFile( QStringLiteral( "INPUT" ), QObject::tr( "Input project (leave blank to use current)" ), QgsProcessingParameterFile::File,
114  QString(), QVariant(), true, QObject::tr( "QGIS files" ) + QStringLiteral( " (*.qgs *.qgz *.QGS)" ) ) );
115 
116  addParameter( new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT" ), QObject::tr( "Output style database" ),
117  QObject::tr( "Style files (*.xml)" ) ) );
118 
119  QStringList options = QStringList()
120  << QObject::tr( "Symbols" )
121  << QObject::tr( "Color ramps" )
122  << QObject::tr( "Text formats" )
123  << QObject::tr( "Label settings" );
124  addParameter( new QgsProcessingParameterEnum( QStringLiteral( "OBJECTS" ), QObject::tr( "Objects to extract" ), options, true, QVariantList() << 0 << 1 << 2 << 3 ) );
125  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "SYMBOLS" ), QObject::tr( "Symbol count" ) ) );
126  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "COLORRAMPS" ), QObject::tr( "Color ramp count" ) ) );
127  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "TEXTFORMATS" ), QObject::tr( "Text format count" ) ) );
128  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "LABELSETTINGS" ), QObject::tr( "Label settings count" ) ) );
129 }
130 
131 QString QgsStyleFromProjectAlgorithm::name() const
132 {
133  return QStringLiteral( "stylefromproject" );
134 }
135 
136 QString QgsStyleFromProjectAlgorithm::displayName() const
137 {
138  return QObject::tr( "Create style database from project" );
139 }
140 
141 QStringList QgsStyleFromProjectAlgorithm::tags() const
142 {
143  return QObject::tr( "symbols,color,ramps,colors,formats,labels,text,fonts" ).split( ',' );
144 }
145 
146 QString QgsStyleFromProjectAlgorithm::group() const
147 {
148  return QObject::tr( "Cartography" );
149 }
150 
151 QString QgsStyleFromProjectAlgorithm::groupId() const
152 {
153  return QStringLiteral( "cartography" );
154 }
155 
156 QString QgsStyleFromProjectAlgorithm::shortHelpString() const
157 {
158  return QObject::tr( "This algorithm extracts all style objects (including symbols, color ramps, text formats and label settings) from a QGIS project.\n\n"
159  "The extracted symbols are saved to a QGIS style database (XML format), which can be managed and imported via the Style Manager dialog." );
160 }
161 
162 QString QgsStyleFromProjectAlgorithm::shortDescription() const
163 {
164  return QObject::tr( "Creates a style database by extracting all symbols, color ramps, text formats and label settings from a QGIS project." );
165 }
166 
167 QgsStyleFromProjectAlgorithm *QgsStyleFromProjectAlgorithm::createInstance() const
168 {
169  return new QgsStyleFromProjectAlgorithm();
170 }
171 
172 bool QgsStyleFromProjectAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
173 {
174  mProjectPath = parameterAsFile( parameters, QStringLiteral( "INPUT" ), context );
175  if ( mProjectPath.isEmpty() && !context.project() )
176  return false;
177 
178  const QList< int > selectedObjects = parameterAsEnums( parameters, QStringLiteral( "OBJECTS" ), context );
179  if ( selectedObjects.contains( 0 ) )
180  mObjects << QgsStyle::SymbolEntity;
181  if ( selectedObjects.contains( 1 ) )
182  mObjects << QgsStyle::ColorrampEntity;
183  if ( selectedObjects.contains( 2 ) )
184  mObjects << QgsStyle::TextFormatEntity;
185  if ( selectedObjects.contains( 3 ) )
186  mObjects << QgsStyle::LabelSettingsEntity;
187 
188  mStyle = qgis::make_unique< QgsStyle >();
189  mStyle->createMemoryDatabase();
190 
191  if ( mProjectPath.isEmpty() )
192  {
193  // using current project -- not thread safe, so prepare in the main thread
194  QgsSaveToStyleVisitor visitor( mStyle.get(), mObjects );
195  context.project()->accept( &visitor );
196  }
197  return true;
198 }
199 
200 QVariantMap QgsStyleFromProjectAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
201 {
202  if ( !mProjectPath.isEmpty() )
203  {
204  // load project from path
205  QgsProject p;
206  if ( !p.read( mProjectPath, QgsProject::FlagDontResolveLayers ) )
207  {
208  throw QgsProcessingException( QObject::tr( "Could not read project %1" ).arg( mProjectPath ) );
209  }
210 
211  QgsSaveToStyleVisitor visitor( mStyle.get(), mObjects );
212  p.accept( &visitor );
213  }
214 
215  const QString file = parameterAsString( parameters, QStringLiteral( "OUTPUT" ), context );
216  if ( !mStyle->exportXml( file ) )
217  {
218  throw QgsProcessingException( QObject::tr( "Error saving style database as %1" ).arg( file ) );
219  }
220 
221  QVariantMap results;
222  results.insert( QStringLiteral( "OUTPUT" ), file );
223  results.insert( QStringLiteral( "SYMBOLS" ), mStyle->symbolCount() );
224  results.insert( QStringLiteral( "COLORRAMPS" ), mStyle->colorRampCount() );
225  results.insert( QStringLiteral( "TEXTFORMATS" ), mStyle->textFormatCount() );
226  results.insert( QStringLiteral( "LABELSETTINGS" ), mStyle->labelSettingsCount() );
227  return results;
228 }
229 
231 
232 
233 
234 
An input file or folder parameter for processing algorithms.
Base class for providing feedback from a processing algorithm.
Don&#39;t resolve layer paths (i.e. don&#39;t load any layer content). Dramatically improves project read tim...
Definition: qgsproject.h:276
A numeric output for processing algorithms.
Individual item in a print layout.
QgsProject * project() const
Returns the project in which the algorithm is being executed.
An enum based parameter for processing algorithms, allowing for selection from predefined values...
Custom exception class for processing related exceptions.
Definition: qgsexception.h:82
Contains information relating to a node (i.e.
QgsStyleEntityVisitorInterface::NodeType type
Node type.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts, annotations, canvases, etc.
Definition: qgsproject.h:89
A generic file based destination parameter, for specifying the destination path for a file (non-map l...
QString description
A string describing the node.
Rule based symbology or label child rule.
virtual QgsStyle::StyleEntity type() const =0
Returns the type of style entity.
QString description
A string describing the style entity.
bool read(const QString &filename, QgsProject::ReadFlags flags=nullptr)
Reads given project file from the given file.
bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified style entity visitor, causing it to visit all style entities associated with th...
const QgsStyleEntityInterface * entity
Reference to style entity being visited.
Contains information about the context in which a processing algorithm is executed.
Contains information relating to the style entity currently being visited.