QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 = QString( 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 = std::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::ReadFlag::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 
Contains information about the context in which a processing algorithm is executed.
QgsProject * project() const
Returns the project in which the algorithm is being executed.
Custom exception class for processing related exceptions.
Definition: qgsexception.h:83
Base class for providing feedback from a processing algorithm.
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...
An input file or folder parameter for processing algorithms.
@ File
Parameter is a single file.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:99
bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified style entity visitor, causing it to visit all style entities associated with th...
bool read(const QString &filename, QgsProject::ReadFlags flags=QgsProject::ReadFlags())
Reads given project file from the given file.
@ FlagDontResolveLayers
Don't resolve layer paths (i.e. don't load any layer content). Dramatically improves project read tim...
virtual QgsStyle::StyleEntity type() const =0
Returns the type of style entity.
@ ReportFooter
Report footer section.
@ Annotation
An individual annotation.
@ Annotations
Annotations collection.
@ LayoutItem
Individual item in a print layout.
@ SymbolRule
Rule based symbology or label child rule.
@ ReportHeader
Report header section.
@ PrintLayout
An individual print layout.
@ 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
Contains information relating to a node (i.e.
QString description
A string describing the node.
QgsStyleEntityVisitorInterface::NodeType type
Node type.
Contains information relating to the style entity currently being visited.
QString description
A string describing the style entity.
const QgsStyleEntityInterface * entity
Reference to style entity being visited.