1 /***************************************************************************
2     qgsstyle.h
3     ---------------------
4     begin                : November 2009
5     copyright            : (C) 2009 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 
16 #ifndef QGSSTYLE_H
17 #define QGSSTYLE_H
18 
19 #include "qgis_core.h"
20 #include "qgis.h"
21 #include <QMap>
22 #include <QMultiMap>
23 #include <QString>
24 
25 #include <sqlite3.h>
26 
27 #include "qgssqliteutils.h"
28 #include "qgssymbollayerutils.h" // QgsStringMap
29 #include "qgstextformat.h"
30 #include "qgspallabeling.h"
31 #include "qgslegendpatchshape.h"
32 
33 class QgsSymbol;
34 class QgsSymbolLayer;
35 class QgsColorRamp;
36 class QgsStyleEntityInterface;
37 class QgsAbstract3DSymbol;
38 class QDomDocument;
39 class QDomElement;
40 
41 typedef QMap<QString, QgsColorRamp * > QgsVectorColorRampMap;
42 typedef QMap<int, QString> QgsSymbolGroupMap;
43 
44 /**
45  * Map of name to text format.
46  * \since QGIS 3.10
47  */
48 typedef QMap<QString, QgsTextFormat > QgsTextFormatMap;
49 
50 /**
51  * Map of name to label settings.
52  * \since QGIS 3.10
53  */
54 typedef QMap<QString, QgsPalLayerSettings > QgsLabelSettingsMap;
55 
56 /*
57  * Constants used to describe copy-paste MIME types
58  */
59 #define QGSCLIPBOARD_STYLE_MIME "application/qgis.style"
60 
61 /**
62  * \ingroup core
63  *  A multimap to hold the smart group conditions as constraint and parameter pairs.
64  *  Both the key and the value of the map are QString. The key is the constraint of the condition and the value is the parameter which is applied for the constraint.
65  *
66  *  The supported constraints are:
67  *  tag -> symbol has the tag matching the parameter
68  *  !tag -> symbol doesn't have the tag matching the parameter
69  *  name -> symbol has a part of its name matching the parameter
70  *  !name -> symbol doesn't have any part of the name matching the parameter
71  *
72  *  Example Usage:
73  *  QgsSmartConditionMap conditions;
74  *  conditions.insert( "tag", "red" ); // adds the condition: Symbol has the tag red
75  *  conditions.insert( "!name", "way" ); // add the condition: Symbol doesn't have any part of its name matching `way`
76  *
77  *  \note This is a Multimap, which means it will contain multiple values for the same key.
78  */
79 typedef QMultiMap<QString, QString> QgsSmartConditionMap;
80 
81 // enumerators representing sqlite DB columns
82 
83 /**
84  * Columns available in the Symbols table.
85  */
86 enum SymbolTable
87 {
88   SymbolId, //!< Symbol ID
89   SymbolName, //!< Symbol Name
90   SymbolXML, //!< Symbol definition (as XML)
91   SymbolFavoriteId, //!< Symbol is favorite flag
92 };
93 
94 /**
95  * Columns available in the Tags table.
96  */
97 enum TagTable
98 {
99   TagId, //!< Tag ID
100   TagName, //!< Tag name
101 };
102 
103 /**
104  * Columns available in the tag to symbol table.
105  */
106 enum TagmapTable
107 {
108   TagmapTagId, //!< Tag ID
109   TagmapSymbolId, //!< Symbol ID
110 };
111 
112 /**
113  * Columns available in the color ramp table.
114  */
115 enum ColorrampTable
116 {
117   ColorrampId, //!< Color ramp ID
118   ColorrampName, //!< Color ramp name
119   ColorrampXML, //!< Color ramp definition (as XML)
120   ColorrampFavoriteId, //!< Color ramp is favorite flag
121 };
122 
123 /**
124  * Columns available in the text format table.
125  */
126 enum TextFormatTable
127 {
128   TextFormatId, //!< Text format ID
129   TextFormatName, //!< Text format name
130   TextFormatXML, //!< Text format definition (as XML)
131   TextFormatFavoriteId, //!< Text format is favorite flag
132 };
133 
134 /**
135  * Columns available in the label settings table.
136  */
137 enum LabelSettingsTable
138 {
139   LabelSettingsId, //!< Label settings ID
140   LabelSettingsName, //!< Label settings name
141   LabelSettingsXML, //!< Label settings definition (as XML)
142   LabelSettingsFavoriteId, //!< Label settings is favorite flag
143 };
144 
145 /**
146  * Columns available in the smart group table.
147  */
148 enum SmartgroupTable
149 {
150   SmartgroupId, //!< Smart group ID
151   SmartgroupName, //!< Smart group name
152   SmartgroupXML, //!< Smart group definition (as XML)
153 };
154 
155 /**
156  * \ingroup core
157  * \class QgsStyle
158  */
159 class CORE_EXPORT QgsStyle : public QObject
160 {
161     Q_OBJECT
162 
163   public:
164 
165     /**
166      * Constructor for QgsStyle.
167      */
168     QgsStyle();
169     ~QgsStyle() override;
170 
171     /**
172      * Enum for Entities involved in a style
173      *
174      *  The enumerator is used for identifying the entity being operated on when generic
175      *  database functions are being run.
176      *  \sa rename(), remove(), symbolsOfFavorite(), symbolsWithTag(), symbolsOfSmartgroup()
177      */
178     enum StyleEntity
179     {
180       SymbolEntity, //!< Symbols
181       TagEntity, //!< Tags
182       ColorrampEntity, //!< Color ramps
183       SmartgroupEntity, //!< Smart groups
184       TextFormatEntity, //!< Text formats
185       LabelSettingsEntity, //!< Label settings
186       LegendPatchShapeEntity, //!< Legend patch shape (since QGIS 3.14)
187       Symbol3DEntity, //!< 3D symbol entity (since QGIS 3.14)
188     };
189 
190     /**
191      * Adds an \a entity to the style, with the specified \a name. Ownership is not transferred.
192      *
193      * If \a update is TRUE then the style database is updated automatically as a result.
194      *
195      * Returns TRUE if the add operation was successful.
196      *
197      * \note Adding an entity with the name of existing one replaces the existing one automatically.
198      *
199      * \since QGIS 3.10
200      */
201     bool addEntity( const QString &name, const QgsStyleEntityInterface *entity, bool update = false );
202 
203     /**
204      * Adds a symbol to style and takes symbol's ownership
205      *
206      *  \note Adding a symbol with the name of existing one replaces it.
207      *  \param name is the name of the symbol being added or updated
208      *  \param symbol is the Vector symbol
209      *  \param update set to TRUE when the style database has to be updated, by default it is FALSE
210      *  \returns success status of the operation
211      */
212     bool addSymbol( const QString &name, QgsSymbol *symbol SIP_TRANSFER, bool update = false );
213 
214     /**
215      * Adds a color ramp to the style. Calling this method takes the ramp's ownership.
216      *  \note Adding a color ramp with the name of existing one replaces it.
217      *  \param name is the name of the color ramp being added or updated
218      *  \param colorRamp is the color ramp. Ownership is transferred.
219      *  \param update set to TRUE when the style database has to be updated, by default it is FALSE
220      *  \returns success status of the operation
221      */
222     bool addColorRamp( const QString &name, QgsColorRamp *colorRamp SIP_TRANSFER, bool update = false );
223 
224     /**
225      * Adds a text \a format with the specified \a name to the style.
226      *
227      * If \a update is set to TRUE, the style database will be automatically updated with the new text format.
228      *
229      * Returns TRUE if the operation was successful.
230      *
231      * \note Adding a text format with the name of existing one replaces it.
232      * \since QGIS 3.10
233      */
234     bool addTextFormat( const QString &name, const QgsTextFormat &format, bool update = false );
235 
236     /**
237      * Adds label \a settings with the specified \a name to the style.
238      *
239      * If \a update is set to TRUE, the style database will be automatically updated with the new text format.
240      *
241      * Returns TRUE if the operation was successful.
242      *
243      * \note Adding label settings with the name of existing ones replaces them.
244      * \since QGIS 3.10
245      */
246     bool addLabelSettings( const QString &name, const QgsPalLayerSettings &settings, bool update = false );
247 
248     /**
249      * Adds a legend patch \a shape with the specified \a name to the style.
250      *
251      * If \a update is set to TRUE, the style database will be automatically updated with the new legend patch shape.
252      *
253      * Returns TRUE if the operation was successful.
254      *
255      * \note Adding legend patch shapes with the name of existing ones replaces them.
256      * \since QGIS 3.14
257      */
258     bool addLegendPatchShape( const QString &name, const QgsLegendPatchShape &shape, bool update = false );
259 
260     /**
261      * Adds a 3d \a symbol with the specified \a name to the style. Ownership of \a symbol is transferred.
262      *
263      * If \a update is set to TRUE, the style database will be automatically updated with the new legend patch shape.
264      *
265      * Returns TRUE if the operation was successful.
266      *
267      * \note Adding 3d symbols with the name of existing ones replaces them.
268      * \since QGIS 3.16
269      */
270     bool addSymbol3D( const QString &name, QgsAbstract3DSymbol *symbol SIP_TRANSFER, bool update = false );
271 
272     /**
273      * Adds a new tag and returns the tag's id
274      *
275      *  \param tagName the name of the new tag to be created
276      *  \returns returns an int, which is the database id of the new tag created, 0 if the tag couldn't be created
277      */
278     int addTag( const QString &tagName );
279 
280     /**
281      * Adds a new smartgroup to the database and returns the id
282      *
283      *  \param name is the name of the new Smart Group to be added
284      *  \param op is the operator between the conditions; AND/OR as QString
285      *  \param conditions are the smart group conditions
286      *
287      * \note Not available from Python bindings
288      */
289     int addSmartgroup( const QString &name, const QString &op, const QgsSmartConditionMap &conditions ) SIP_SKIP;
290 
291     /**
292      * Adds a new smartgroup to the database and returns the id.
293      *
294      * \param name is the name of the new Smart Group to be added
295      * \param op is the operator between the conditions; AND/OR as QString
296      * \param matchTag list of strings to match within tags
297      * \param noMatchTag list of strings to exclude matches from tags
298      * \param matchName list of string to match within names
299      * \param noMatchName list of strings to exclude matches from names
300      *
301      * \since QGIS 3.4
302      */
303     int addSmartgroup( const QString &name, const QString &op, const QStringList &matchTag, const QStringList &noMatchTag,
304                        const QStringList &matchName, const QStringList &noMatchName );
305 
306     /**
307      * Returns a list of all tags in the style database
308      *
309      * \see addTag()
310      * \since QGIS 2.16
311      */
312     QStringList tags() const;
313 
314     //! Removes all contents of the style
315     void clear();
316 
317     /**
318      * Returns a new copy of the specified color ramp. The caller
319      * takes responsibility for deleting the returned object.
320      */
321     QgsColorRamp *colorRamp( const QString &name ) const SIP_FACTORY;
322 
323     //! Returns count of color ramps
324     int colorRampCount();
325 
326     //! Returns a list of names of color ramps
327     QStringList colorRampNames() const;
328 
329     //! Returns a const pointer to a symbol (doesn't create new instance)
330     const QgsColorRamp *colorRampRef( const QString &name ) const;
331 
332     /**
333      * Returns the id in the style database for the given colorramp name
334      * returns 0 if not found
335      */
336     int colorrampId( const QString &name );
337 
338     /**
339      * Returns the text format with the specified \a name.
340      *
341      * \since QGIS 3.10
342      */
343     QgsTextFormat textFormat( const QString &name ) const;
344 
345     /**
346      * Returns count of text formats in the style.
347      * \since QGIS 3.10
348      */
349     int textFormatCount() const;
350 
351     /**
352      * Returns a list of names of text formats in the style.
353      * \since QGIS 3.10
354      */
355     QStringList textFormatNames() const;
356 
357     /**
358      * Returns the ID in the style database for the given text format by \a name.
359      * Returns 0 if the text format was not found.
360      *
361      * \since QGIS 3.10
362      */
363     int textFormatId( const QString &name );
364 
365     /**
366      * Returns the label settings with the specified \a name.
367      *
368      * \since QGIS 3.10
369      */
370     QgsPalLayerSettings labelSettings( const QString &name ) const;
371 
372     /**
373      * Returns the legend patch shape with the specified \a name.
374      *
375      * \since QGIS 3.14
376      */
377     QgsLegendPatchShape legendPatchShape( const QString &name ) const;
378 
379     /**
380      * Returns count of legend patch shapes in the style.
381      * \since QGIS 3.14
382      */
383     int legendPatchShapesCount() const;
384 
385     /**
386      * Returns the symbol type corresponding to the legend patch shape
387      * with the specified \a name, or QgsSymbol::Hybrid
388      * if a matching legend patch shape is not present.
389      *
390      * \since QGIS 3.14
391      */
392     Qgis::SymbolType legendPatchShapeSymbolType( const QString &name ) const;
393 
394     /**
395      * Returns a new copy of the 3D symbol with the specified \a name.
396      *
397      * \since QGIS 3.16
398      */
399     QgsAbstract3DSymbol *symbol3D( const QString &name ) const SIP_FACTORY;
400 
401     /**
402      * Returns count of 3D symbols in the style.
403      * \since QGIS 3.16
404      */
405     int symbol3DCount() const;
406 
407     /**
408      * Returns the list of the vector layer geometry types which are compatible with the 3D symbol
409      * with the specified \a name, or an empty list if a matching 3d symbol is not present.
410      *
411      * \since QGIS 3.16
412      */
413     QList< QgsWkbTypes::GeometryType > symbol3DCompatibleGeometryTypes( const QString &name ) const;
414 
415     /**
416      * Returns the layer geometry type corresponding to the label settings
417      * with the specified \a name, or QgsWkbTypes::UnknownGeometry
418      * if matching label settings are not present.
419      *
420      * \since QGIS 3.10
421      */
422     QgsWkbTypes::GeometryType labelSettingsLayerType( const QString &name ) const;
423 
424     /**
425      * Returns count of label settings in the style.
426      * \since QGIS 3.10
427      */
428     int labelSettingsCount() const;
429 
430     /**
431      * Returns a list of names of label settings in the style.
432      * \since QGIS 3.10
433      */
434     QStringList labelSettingsNames() const;
435 
436     /**
437      * Returns the ID in the style database for the given label settings by \a name.
438      * Returns 0 if the label settings were not found.
439      *
440      * \since QGIS 3.10
441      */
442     int labelSettingsId( const QString &name );
443 
444     //! Returns default application-wide style
445     static QgsStyle *defaultStyle();
446 
447     //! Deletes the default style. Only to be used by QgsApplication::exitQgis()
448     static void cleanDefaultStyle() SIP_SKIP;
449 
450     /**
451      * Tags the symbol with the tags in the list
452      *
453      *  Applies the given tags to the given symbol or colorramp
454      *  \param type is either SymbolEntity or ColorrampEntity
455      *  \param symbol is the name of the symbol or colorramp as QString
456      *  \param tags is the list of the tags that are to be applied as QStringList
457      *  \returns returns the success state of the operation
458      */
459     bool tagSymbol( StyleEntity type, const QString &symbol, const QStringList &tags );
460 
461     /**
462      * Detags the symbol with the given list
463      *
464      *  Removes the given tags for the specified symbol or colorramp
465      *  \param type is either SymbolEntity or ColorrampEntity
466      *  \param symbol is the name of the symbol or colorramp
467      *  \param tags is the list of tags that are to be removed as QStringList
468      *  \returns returns the success state of the operation
469      */
470     bool detagSymbol( StyleEntity type, const QString &symbol, const QStringList &tags );
471 
472     /**
473      * Clears the symbol from all attached tags
474      *
475      *  Removes all tags for the specified symbol or colorramp
476      *  \param type is either SymbolEntity or ColorrampEntity
477      *  \param symbol is the name of the symbol or colorramp
478      *  \returns returns the success state of the operation
479      */
480     bool detagSymbol( StyleEntity type, const QString &symbol );
481 
482     //! Removes symbol from style (and delete it)
483     bool removeSymbol( const QString &name );
484 
485     /**
486      * Renames an entity of the specified \a type from \a oldName to \a newName.
487      *
488      * Returns TRUE if the entity was successfully renamed.
489      *
490      * \since QGIS 3.14
491      */
492     bool renameEntity( StyleEntity type, const QString &oldName, const QString &newName );
493 
494     /**
495      * Renames a symbol from \a oldName to \a newName.
496      *
497      * Returns TRUE if symbol was successfully renamed.
498      */
499     bool renameSymbol( const QString &oldName, const QString &newName );
500 
501     //! Returns a NEW copy of symbol
502     QgsSymbol *symbol( const QString &name ) SIP_FACTORY;
503 
504     //! Returns a const pointer to a symbol (doesn't create new instance)
505     const QgsSymbol *symbolRef( const QString &name ) const;
506 
507     //! Returns count of symbols in style
508     int symbolCount();
509 
510     //! Returns a list of names of symbols
511     QStringList symbolNames() const;
512 
513     /**
514      * Returns the id in the style database for the given symbol name
515      * returns 0 if not found
516      */
517     int symbolId( const QString &name );
518 
519     /**
520      * Returns the id in the style database for the given \a name of the specified entity \a type.
521      * Returns 0 if not found.
522      */
523     int entityId( StyleEntity type, const QString &name );
524 
525     //! Returns the database id for the given tag name
526     int tagId( const QString &tag );
527     //! Returns the database id for the given smartgroup name
528     int smartgroupId( const QString &smartgroup );
529 
530     /**
531      * Returns a list of the names of all existing entities of the specified \a type.
532      * \since QGIS 3.10
533      */
534     QStringList allNames( StyleEntity type ) const;
535 
536     /**
537      * Returns the symbol names which are flagged as favorite
538      *
539      *  \param type is either SymbolEntity or ColorampEntity
540      *  \returns A QStringList of the symbol or colorramp names flagged as favorite
541      */
542     QStringList symbolsOfFavorite( StyleEntity type ) const;
543 
544     /**
545      * Returns the symbol names with which have the given tag
546      *
547      *  \param type is either SymbolEntity or ColorampEntity
548      *  \param tagid is id of the tag which has been applied over the symbol as int
549      *  \returns A QStringList of the symbol or colorramp names for the given tag id
550      */
551     QStringList symbolsWithTag( StyleEntity type, int tagid ) const;
552 
553     /**
554      * Adds the specified symbol to favorites
555      *
556      *  \param type is either SymbolEntity of ColorrampEntity
557      *  \param name is the name of the symbol or coloramp whose is to be added to favorites
558      *  \returns returns the success state as bool
559      */
560     bool addFavorite( StyleEntity type, const QString &name );
561 
562     /**
563      * Removes the specified symbol from favorites
564      *
565      *  \param type is either SymbolEntity of ColorrampEntity
566      *  \param name is the name of the symbol or coloramp whose is to be removed from favorites
567      *  \returns returns the success state as bool
568      */
569     bool removeFavorite( StyleEntity type, const QString &name );
570 
571     /**
572      * Renames the given entity with the specified id
573      *
574      *  \param type is any of the style entities. Refer enum StyleEntity.
575      *  \param id is the database id of the entity which is to be renamed
576      *  \param newName is the new name of the entity
577      */
578     bool rename( StyleEntity type, int id, const QString &newName );
579 
580     /**
581      * Removes the specified entity from the database.
582      *
583      *  \param type is any of the style entities. Refer enum StyleEntity.
584      *  \param id is the database id of the entity to be removed
585      *
586      * \see removeEntityByName()
587      */
588     bool remove( StyleEntity type, int id );
589 
590     /**
591      * Removes the entry of the specified \a type with matching \a name from the database.
592      *
593      * \see remove()
594      * \since QGIS 3.14
595      */
596     bool removeEntityByName( StyleEntity type, const QString &name );
597 
598     /**
599      * Adds the symbol to the database with tags.
600      *
601      *  \param name is the name of the symbol as QString
602      *  \param symbol is the pointer to the new QgsSymbol being saved
603      *  \param favorite is a boolean value to specify whether the symbol should be added to favorites
604      *  \param tags is a list of tags that are associated with the symbol as a QStringList.
605      *  \returns returns the success state of the save operation
606      */
607     bool saveSymbol( const QString &name, QgsSymbol *symbol, bool favorite, const QStringList &tags );
608 
609     /**
610      * Adds the colorramp to the database.
611      *
612      *  \param name is the name of the colorramp as QString
613      *  \param ramp is the pointer to the new QgsColorRamp being saved
614      *  \param favorite is a boolean value to specify whether the colorramp should be added to favorites
615      *  \param tags is a list of tags that are associated with the color ramp as a QStringList.
616      *  \returns returns the success state of the save operation
617      */
618     bool saveColorRamp( const QString &name, QgsColorRamp *ramp, bool favorite, const QStringList &tags );
619 
620     //! Removes color ramp from style (and delete it)
621     bool removeColorRamp( const QString &name );
622 
623     //! Changes ramp's name
624     bool renameColorRamp( const QString &oldName, const QString &newName );
625 
626     /**
627      * Adds a text \a format to the database.
628      *
629      *  \param name is the name of the text format
630      *  \param format text format to save
631      *  \param favorite is a boolean value to specify whether the text format should be added to favorites
632      *  \param tags is a list of tags that are associated with the text format
633      *  \returns returns the success state of the save operation
634      */
635     bool saveTextFormat( const QString &name, const QgsTextFormat &format, bool favorite, const QStringList &tags );
636 
637     /**
638      * Removes a text format from the style.
639      * \since QGIS 3.10
640      */
641     bool removeTextFormat( const QString &name );
642 
643     /**
644      * Changes a text format's name.
645      *
646      * \since QGIS 3.10
647      */
648     bool renameTextFormat( const QString &oldName, const QString &newName );
649 
650     /**
651      * Adds label \a settings to the database.
652      *
653      *  \param name is the name of the label settings
654      *  \param settings label settings to save
655      *  \param favorite is a boolean value to specify whether the label settings should be added to favorites
656      *  \param tags is a list of tags that are associated with the label settings
657      *  \returns returns the success state of the save operation
658      */
659     bool saveLabelSettings( const QString &name, const QgsPalLayerSettings &settings, bool favorite, const QStringList &tags );
660 
661     /**
662      * Removes label settings from the style.
663      * \since QGIS 3.10
664      */
665     bool removeLabelSettings( const QString &name );
666 
667     /**
668      * Changes a label setting's name.
669      *
670      * \since QGIS 3.10
671      */
672     bool renameLabelSettings( const QString &oldName, const QString &newName );
673 
674     /**
675      * Adds a legend patch \a shape to the database.
676      *
677      * \param name is the name of the legend patch shape
678      * \param shape legend patch shape to save
679      * \param favorite is a boolean value to specify whether the legend patch shape should be added to favorites
680      * \param tags is a list of tags that are associated with the legend patch shape
681      * \returns returns the success state of the save operation
682      *
683      * \since QGIS 3.14
684      */
685     bool saveLegendPatchShape( const QString &name, const QgsLegendPatchShape &shape, bool favorite, const QStringList &tags );
686 
687     /**
688      * Changes a legend patch shape's name.
689      *
690      * \since QGIS 3.14
691      */
692     bool renameLegendPatchShape( const QString &oldName, const QString &newName );
693 
694     /**
695      * Returns a list of names of legend patch shapes in the style.
696      * \since QGIS 3.14
697      */
698     QStringList legendPatchShapeNames() const;
699 
700     /**
701      * Returns a symbol to use for rendering preview icons for a patch \a shape.
702      *
703      * Ownership of the symbol is not transferred.
704      *
705      * \since QGIS 3.14
706      */
707     const QgsSymbol *previewSymbolForPatchShape( const QgsLegendPatchShape &shape ) const;
708 
709     /**
710      * Returns the default legend patch shape for the given symbol \a type.
711      *
712      * \see defaultPatchAsQPolygonF()
713      * \since QGIS 3.14
714      */
715     QgsLegendPatchShape defaultPatch( Qgis::SymbolType type, QSizeF size ) const;
716 
717     /**
718      * Returns the default patch geometry for the given symbol \a type and \a size as a set of QPolygonF objects (parts and rings).
719      *
720      * \see defaultPatch()
721      * \since QGIS 3.14
722      */
723     QList< QList< QPolygonF > > defaultPatchAsQPolygonF( Qgis::SymbolType type, QSizeF size ) const;
724 
725     /**
726      * Text format context.
727      *
728      * \since QGIS 3.20
729      */
730     enum class TextFormatContext : int
731     {
732       Labeling, //!< Text format used in labeling
733     };
734 
735     /**
736      * Returns the default text format to use for new text based objects in the specified \a context.
737      *
738      * \since QGIS 3.20
739      */
740     QgsTextFormat defaultTextFormat( QgsStyle::TextFormatContext context = QgsStyle::TextFormatContext::Labeling ) const;
741 
742     /**
743      * Adds a 3d \a symbol to the database.
744      *
745      * \param name is the name of the 3d symbol
746      * \param symbol 3d symbol to save. Ownership is transferred.
747      * \param favorite is a boolean value to specify whether the 3d symbol should be added to favorites
748      * \param tags is a list of tags that are associated with the 3d symbol
749      * \returns returns the success state of the save operation
750      *
751      * \since QGIS 3.16
752      */
753     bool saveSymbol3D( const QString &name, QgsAbstract3DSymbol *symbol SIP_TRANSFER, bool favorite, const QStringList &tags );
754 
755     /**
756      * Changes a 3d symbol's name.
757      *
758      * \since QGIS 3.16
759      */
760     bool renameSymbol3D( const QString &oldName, const QString &newName );
761 
762     /**
763      * Returns a list of names of 3d symbols in the style.
764      * \since QGIS 3.16
765      */
766     QStringList symbol3DNames() const;
767 
768     /**
769      * Creates an on-disk database
770      *
771      *  This function creates a new on-disk permanent style database.
772      *  \returns returns the success state of the database creation
773      *  \see createMemoryDatabase()
774      *  \since QGIS 3.0
775      */
776     bool createDatabase( const QString &filename );
777 
778     /**
779      * Creates a temporary memory database
780      *
781      *  This function is used to create a temporary style database in case a permanent on-disk database is not needed.
782      *  \returns returns the success state of the temporary memory database creation
783      *  \see createDatabase()
784      *  \since QGIS 3.0
785      */
786     bool createMemoryDatabase();
787 
788     /**
789      * Creates tables structure for new database
790      *
791      *  This function is used to create the tables structure in a newly-created database.
792      *  \returns returns the success state of the temporary memory database creation
793      *  \see createDatabase()
794      *  \see createMemoryDatabase()
795      *  \since QGIS 3.0
796      */
797     void createTables();
798 
799     /**
800      * Loads a file into the style
801      *
802      *  This function will load an on-disk database and populate styles.
803      *  \param filename location of the database to load styles from
804      *  \returns returns the success state of the database being loaded
805      */
806     bool load( const QString &filename );
807 
808     //! Saves style into a file (will use current filename if empty string is passed)
809     bool save( QString filename = QString() );
810 
811     //! Returns last error from load/save operation
errorString()812     QString errorString() { return mErrorString; }
813 
814     //! Returns current file name of the style
fileName()815     QString fileName() { return mFileName; }
816 
817     /**
818      * Returns the names of the symbols which have a matching 'substring' in its definition
819      *
820      *  \param type is either SymbolEntity or ColorrampEntity
821      *  \param qword is the query string to search the symbols or colorramps.
822      *  \returns A QStringList of the matched symbols or colorramps
823      */
824     QStringList findSymbols( StyleEntity type, const QString &qword );
825 
826     /**
827      * Returns the tags associated with the symbol
828      *
829      *  \param type is either SymbolEntity or ColorrampEntity
830      *  \param symbol is the name of the symbol or color ramp
831      *  \returns A QStringList of the tags that have been applied to that symbol/colorramp
832      */
833     QStringList tagsOfSymbol( StyleEntity type, const QString &symbol );
834 
835     /**
836      * Returns TRUE if the symbol with matching \a type and \a name is
837      * marked as a favorite.
838      *
839      * \since QGIS 3.10
840      */
841     bool isFavorite( StyleEntity type, const QString &name );
842 
843     /**
844      * Returns whether a given tag is associated with the symbol
845      *
846      *  \param type is either SymbolEntity or ColorrampEntity
847      *  \param symbol is the name of the symbol or color ramp
848      *  \param tag the name of the tag to look for
849      *  \returns A boolean value identicating whether a tag was found attached to the symbol
850      */
851     bool symbolHasTag( StyleEntity type, const QString &symbol, const QString &tag );
852 
853     //! Returns the tag name for the given id
854     QString tag( int id ) const;
855 
856     //! Returns the smart groups map with id as key and name as value
857     QgsSymbolGroupMap smartgroupsListMap();
858 
859     //! Returns the smart groups list
860     QStringList smartgroupNames() const;
861 
862     //! Returns the QgsSmartConditionMap for the given id
863     QgsSmartConditionMap smartgroup( int id );
864 
865     /**
866      * Returns the operator for the smartgroup.
867      */
868     QString smartgroupOperator( int id );
869 
870     //! Returns the symbols for the smartgroup
871     QStringList symbolsOfSmartgroup( StyleEntity type, int id );
872 
873     //! Exports the style as a XML file
874     bool exportXml( const QString &filename );
875 
876     //! Imports the symbols and colorramps into the default style database from the given XML file
877     bool importXml( const QString &filename );
878 
879     /**
880      * Tests if the file at \a path is a QGIS style XML file.
881      *
882      * This method samples only the first line in the file, so is safe to call on
883      * large xml files.
884      *
885      * \since QGIS 3.6
886      */
887     static bool isXmlStyleFile( const QString &path );
888 
889   signals:
890 
891     /**
892      * Emitted every time a new symbol has been added to the database.
893      * Emitted whenever a symbol has been added to the style and the database
894      * has been updated as a result.
895      * \see symbolRemoved()
896      * \see rampAdded()
897      * \see symbolChanged()
898      */
899     void symbolSaved( const QString &name, QgsSymbol *symbol );
900 
901     /**
902      * Emitted whenever a symbol's definition is changed. This does not include
903      * name or tag changes.
904      *
905      * \see symbolSaved()
906      *
907      * \since QGIS 3.4
908      */
909     void symbolChanged( const QString &name );
910 
911     //! Emitted every time a tag or smartgroup has been added, removed, or renamed
912     void groupsModified();
913 
914     /**
915      * Emitted whenever an \a entity's tags are changed.
916      *
917      * \since QGIS 3.4
918      */
919     void entityTagsChanged( QgsStyle::StyleEntity entity, const QString &name, const QStringList &newTags );
920 
921     /**
922      * Emitted whenever an \a entity is either favorited or un-favorited.
923      *
924      * \since QGIS 3.4
925      */
926     void favoritedChanged( QgsStyle::StyleEntity entity, const QString &name, bool isFavorite );
927 
928     /**
929      * Emitted every time a new entity has been added to the database.
930      *
931      * \since QGIS 3.14
932      */
933     void entityAdded( QgsStyle::StyleEntity entity, const QString &name );
934 
935     /**
936      * Emitted whenever an entity of the specified type is removed from the style and the database
937      * has been updated as a result.
938      *
939      * \since QGIS 3.14
940      */
941     void entityRemoved( QgsStyle::StyleEntity entity, const QString &name );
942 
943     /**
944      * Emitted whenever a entity of the specified type has been renamed from \a oldName to \a newName
945      * \since QGIS 3.14
946      */
947     void entityRenamed( QgsStyle::StyleEntity entity, const QString &oldName, const QString &newName );
948 
949     /**
950      * Emitted whenever an entity's definition is changed. This does not include
951      * name or tag changes.
952      *
953      * \since QGIS 3.14
954      */
955     void entityChanged( QgsStyle::StyleEntity entity, const QString &name );
956 
957     /**
958      * Emitted whenever a symbol has been removed from the style and the database
959      * has been updated as a result.
960      * \see symbolSaved()
961      * \see rampRemoved()
962      * \since QGIS 3.4
963      */
964     void symbolRemoved( const QString &name );
965 
966     /**
967      * Emitted whenever a symbol has been renamed from \a oldName to \a newName
968      * \see rampRenamed()
969      * \since QGIS 3.4
970      */
971     void symbolRenamed( const QString &oldName, const QString &newName );
972 
973     /**
974      * Emitted whenever a color ramp has been renamed from \a oldName to \a newName
975      * \see symbolRenamed()
976      * \since QGIS 3.4
977      */
978     void rampRenamed( const QString &oldName, const QString &newName );
979 
980     /**
981      * Emitted whenever a color ramp has been added to the style and the database
982      * has been updated as a result.
983      * \see rampRemoved()
984      * \see symbolSaved()
985      * \since QGIS 3.4
986      */
987     void rampAdded( const QString &name );
988 
989     /**
990      * Emitted whenever a color ramp has been removed from the style and the database
991      * has been updated as a result.
992      * \see rampAdded()
993      * \see symbolRemoved()
994      * \since QGIS 3.4
995      */
996     void rampRemoved( const QString &name );
997 
998     /**
999      * Emitted whenever a color ramp's definition is changed. This does not include
1000      * name or tag changes.
1001      *
1002      * \see rampAdded()
1003      *
1004      * \since QGIS 3.4
1005      */
1006     void rampChanged( const QString &name );
1007 
1008 
1009     /**
1010      * Emitted whenever a text format has been renamed from \a oldName to \a newName
1011      * \see symbolRenamed()
1012      * \since QGIS 3.10
1013      */
1014     void textFormatRenamed( const QString &oldName, const QString &newName );
1015 
1016     /**
1017      * Emitted whenever a text format has been added to the style and the database
1018      * has been updated as a result.
1019      * \see textFormatRemoved()
1020      * \see symbolSaved()
1021      * \since QGIS 3.10
1022      */
1023     void textFormatAdded( const QString &name );
1024 
1025     /**
1026      * Emitted whenever a text format has been removed from the style and the database
1027      * has been updated as a result.
1028      * \see textFormatAdded()
1029      * \see symbolRemoved()
1030      * \since QGIS 3.10
1031      */
1032     void textFormatRemoved( const QString &name );
1033 
1034     /**
1035      * Emitted whenever a text format's definition is changed. This does not include
1036      * name or tag changes.
1037      *
1038      * \see textFormatAdded()
1039      *
1040      * \since QGIS 3.10
1041      */
1042     void textFormatChanged( const QString &name );
1043 
1044     /**
1045      * Emitted whenever label settings have been renamed from \a oldName to \a newName
1046      * \see symbolRenamed()
1047      * \since QGIS 3.10
1048      */
1049     void labelSettingsRenamed( const QString &oldName, const QString &newName );
1050 
1051     /**
1052      * Emitted whenever label settings have been added to the style and the database
1053      * has been updated as a result.
1054      * \see labelSettingsRemoved()
1055      * \see symbolSaved()
1056      * \since QGIS 3.10
1057      */
1058     void labelSettingsAdded( const QString &name );
1059 
1060     /**
1061      * Emitted whenever label settings have been removed from the style and the database
1062      * has been updated as a result.
1063      * \see labelSettingsAdded()
1064      * \see symbolRemoved()
1065      * \since QGIS 3.10
1066      */
1067     void labelSettingsRemoved( const QString &name );
1068 
1069     /**
1070      * Emitted whenever a label setting's definition is changed. This does not include
1071      * name or tag changes.
1072      *
1073      * \see labelSettingsAdded()
1074      *
1075      * \since QGIS 3.10
1076      */
1077     void labelSettingsChanged( const QString &name );
1078 
1079   private:
1080 
1081     QgsSymbolMap mSymbols;
1082     QgsVectorColorRampMap mColorRamps;
1083     QgsTextFormatMap mTextFormats;
1084     QgsLabelSettingsMap mLabelSettings;
1085     QMap<QString, QgsLegendPatchShape > mLegendPatchShapes;
1086     QMap<QString, QgsAbstract3DSymbol * > m3dSymbols;
1087 
1088     QHash< QgsStyle::StyleEntity, QHash< QString, QStringList > > mCachedTags;
1089     QHash< QgsStyle::StyleEntity, QHash< QString, bool > > mCachedFavorites;
1090 
1091     QString mErrorString;
1092     QString mFileName;
1093 
1094     sqlite3_database_unique_ptr mCurrentDB;
1095 
1096     std::unique_ptr< QgsSymbol > mPatchMarkerSymbol;
1097     std::unique_ptr< QgsSymbol > mPatchLineSymbol;
1098     std::unique_ptr< QgsSymbol > mPatchFillSymbol;
1099 
1100     mutable QHash< int, QHash< QSizeF, QgsLegendPatchShape > > mDefaultPatchCache;
1101     mutable QHash< int, QHash< QSizeF, QList< QList< QPolygonF > > > > mDefaultPatchQPolygonFCache;
1102 
1103     QMap< QString, QDomElement > mDeferred3DsymbolElements;
1104     void handleDeferred3DSymbolCreation();
1105 
1106     static QgsStyle *sDefaultStyle;
1107 
1108     //! Convenience function to open the DB and return a sqlite3 object
1109     bool openDatabase( const QString &filename );
1110 
1111     //! Imports the symbols and colorramps into the default style database from the given XML file
1112     bool importXml( const QString &filename, int sinceVersion );
1113 
1114     /**
1115      * Convenience function that would run queries which don't generate return values
1116      *
1117      *  \param query query to run
1118      *  \returns success TRUE on success
1119      */
1120     bool runEmptyQuery( const QString &query );
1121 
1122     //! Gets the id from the table for the given name from the database, 0 if not found
1123     int getId( const QString &table, const QString &name );
1124 
1125     //! Gets the name from the table for the given id from the database, empty if not found
1126     QString getName( const QString &table, int id ) const;
1127 
1128     /**
1129      * Updates the properties of an existing symbol/colorramp
1130      *
1131      *  \note This should not be called separately, only called through addSymbol or addColorRamp
1132      *  \param type is either SymbolEntity or ColorrampEntity
1133      *  \param name is the name of an existing symbol or a color ramp
1134      *  \returns Success state of the update operation
1135      */
1136     bool updateSymbol( StyleEntity type, const QString &name );
1137 
1138     void clearCachedTags( StyleEntity type, const QString &name );
1139 
1140 
1141     void upgradeIfRequired();
1142 
1143     /**
1144      * Returns the table name for the specified entity \a type.
1145      */
1146     static QString entityTableName( StyleEntity type );
1147 
1148     /**
1149      * Returns the tag map table name for the specified entity \a type.
1150      */
1151     static QString tagmapTableName( StyleEntity type );
1152 
1153     /**
1154      * Returns the entity ID field name for for the tag map table for the specified entity \a type.
1155      */
1156     static QString tagmapEntityIdFieldName( StyleEntity type );
1157 
1158     friend class Qgs3D;
1159     friend class TestStyle;
1160 
1161     Q_DISABLE_COPY( QgsStyle )
1162 };
1163 
1164 /**
1165  * \class QgsStyleEntityInterface
1166  * \ingroup core
1167  * \brief An interface for entities which can be placed in a QgsStyle database.
1168  * \since QGIS 3.10
1169  */
1170 class CORE_EXPORT QgsStyleEntityInterface
1171 {
1172 
1173 #ifdef SIP_RUN
1174     SIP_CONVERT_TO_SUBCLASS_CODE
1175     switch ( sipCpp->type() )
1176     {
1177       case QgsStyle::SymbolEntity:
1178         sipType = sipType_QgsStyleSymbolEntity;
1179         break;
1180 
1181       case QgsStyle::ColorrampEntity:
1182         sipType = sipType_QgsStyleColorRampEntity;
1183         break;
1184 
1185       case QgsStyle::TextFormatEntity:
1186         sipType = sipType_QgsStyleTextFormatEntity;
1187         break;
1188 
1189       case QgsStyle::LabelSettingsEntity:
1190         sipType = sipType_QgsStyleLabelSettingsEntity;
1191         break;
1192 
1193       case QgsStyle::SmartgroupEntity:
1194       case QgsStyle::TagEntity:
1195         sipType = 0;
1196         break;
1197     }
1198     SIP_END
1199 #endif
1200 
1201   public:
1202 
1203     virtual ~QgsStyleEntityInterface() = default;
1204 
1205     /**
1206      * Returns the type of style entity.
1207      */
1208     virtual QgsStyle::StyleEntity type() const = 0;
1209 
1210 };
1211 
1212 /**
1213  * \class QgsStyleSymbolEntity
1214  * \ingroup core
1215  * \brief A symbol entity for QgsStyle databases.
1216  * \since QGIS 3.10
1217  */
1218 class CORE_EXPORT QgsStyleSymbolEntity : public QgsStyleEntityInterface
1219 {
1220   public:
1221 
1222     /**
1223      * Constructor for QgsStyleSymbolEntity, with the specified \a symbol.
1224      *
1225      * Ownership of \a symbol is NOT transferred.
1226      */
QgsStyleSymbolEntity(QgsSymbol * symbol)1227     QgsStyleSymbolEntity( QgsSymbol *symbol )
1228       : mSymbol( symbol )
1229     {}
1230 
1231     QgsStyle::StyleEntity type() const override;
1232 
1233     /**
1234      * Returns the entity's symbol.
1235      */
symbol()1236     QgsSymbol *symbol() const { return mSymbol; }
1237 
1238   private:
1239 
1240     QgsSymbol *mSymbol = nullptr;
1241 
1242 };
1243 
1244 /**
1245  * \class QgsStyleColorRampEntity
1246  * \ingroup core
1247  * \brief A color ramp entity for QgsStyle databases.
1248  * \since QGIS 3.10
1249  */
1250 class CORE_EXPORT QgsStyleColorRampEntity : public QgsStyleEntityInterface
1251 {
1252   public:
1253 
1254     /**
1255      * Constructor for QgsStyleColorRampEntity, with the specified color \a ramp.
1256      *
1257      * Ownership of \a ramp is NOT transferred.
1258      */
QgsStyleColorRampEntity(QgsColorRamp * ramp)1259     QgsStyleColorRampEntity( QgsColorRamp *ramp )
1260       : mRamp( ramp )
1261     {}
1262 
1263     QgsStyle::StyleEntity type() const override;
1264 
1265     /**
1266      * Returns the entity's color ramp.
1267      */
ramp()1268     QgsColorRamp *ramp() const { return mRamp; }
1269 
1270   private:
1271 
1272     QgsColorRamp *mRamp = nullptr;
1273 };
1274 
1275 /**
1276  * \class QgsStyleTextFormatEntity
1277  * \ingroup core
1278  * \brief A text format entity for QgsStyle databases.
1279  * \since QGIS 3.10
1280  */
1281 class CORE_EXPORT QgsStyleTextFormatEntity : public QgsStyleEntityInterface
1282 {
1283   public:
1284 
1285     /**
1286      * Constructor for QgsStyleTextFormatEntity, with the specified text \a format.
1287      */
QgsStyleTextFormatEntity(const QgsTextFormat & format)1288     QgsStyleTextFormatEntity( const QgsTextFormat &format )
1289       : mFormat( format )
1290     {}
1291 
1292     QgsStyle::StyleEntity type() const override;
1293 
1294     /**
1295      * Returns the entity's text format.
1296      */
format()1297     QgsTextFormat format() const { return mFormat; }
1298 
1299   private:
1300 
1301     QgsTextFormat mFormat;
1302 
1303 };
1304 
1305 /**
1306  * \class QgsStyleLabelSettingsEntity
1307  * \ingroup core
1308  * \brief A label settings entity for QgsStyle databases.
1309  * \since QGIS 3.10
1310  */
1311 class CORE_EXPORT QgsStyleLabelSettingsEntity : public QgsStyleEntityInterface
1312 {
1313   public:
1314 
1315     /**
1316      * Constructor for QgsStyleLabelSettingsEntity, with the specified label \a settings.
1317      */
QgsStyleLabelSettingsEntity(const QgsPalLayerSettings & settings)1318     QgsStyleLabelSettingsEntity( const QgsPalLayerSettings &settings )
1319       : mSettings( settings )
1320     {}
1321 
1322     QgsStyle::StyleEntity type() const override;
1323 
1324 
1325     /**
1326      * Returns the entity's label settings.
1327      */
settings()1328     const QgsPalLayerSettings &settings() const { return mSettings; }
1329 
1330   private:
1331 
1332     QgsPalLayerSettings mSettings;
1333 };
1334 
1335 /**
1336  * \class QgsStyleLegendPatchShapeEntity
1337  * \ingroup core
1338  * \brief A legend patch shape entity for QgsStyle databases.
1339  * \since QGIS 3.14
1340  */
1341 class CORE_EXPORT QgsStyleLegendPatchShapeEntity : public QgsStyleEntityInterface
1342 {
1343   public:
1344 
1345     /**
1346      * Constructor for QgsStyleLegendPatchShapeEntity, with the specified legend patch \a shape.
1347      */
QgsStyleLegendPatchShapeEntity(const QgsLegendPatchShape & shape)1348     QgsStyleLegendPatchShapeEntity( const QgsLegendPatchShape &shape )
1349       : mShape( shape )
1350     {}
1351 
1352     QgsStyle::StyleEntity type() const override;
1353 
1354 
1355     /**
1356      * Returns the entity's legend patch shape.
1357      */
shape()1358     const QgsLegendPatchShape &shape() const { return mShape; }
1359 
1360   private:
1361 
1362     QgsLegendPatchShape mShape;
1363 };
1364 
1365 /**
1366  * \class QgsStyleSymbol3DEntity
1367  * \ingroup core
1368  * \brief A 3d symbol entity for QgsStyle databases.
1369  * \since QGIS 3.16
1370  */
1371 class CORE_EXPORT QgsStyleSymbol3DEntity : public QgsStyleEntityInterface
1372 {
1373   public:
1374 
1375     /**
1376      * Constructor for QgsStyleSymbol3DEntity, with the specified \a symbol.
1377      *
1378      * Ownership of \a symbol is NOT transferred.
1379      */
QgsStyleSymbol3DEntity(const QgsAbstract3DSymbol * symbol)1380     QgsStyleSymbol3DEntity( const QgsAbstract3DSymbol *symbol )
1381       : mSymbol( symbol )
1382     {}
1383 
1384     QgsStyle::StyleEntity type() const override;
1385 
1386     /**
1387      * Returns the entity's symbol.
1388      */
symbol()1389     const QgsAbstract3DSymbol *symbol() const { return mSymbol; }
1390 
1391   private:
1392 
1393     const QgsAbstract3DSymbol *mSymbol = nullptr;
1394 };
1395 
1396 #endif
1397