Merge pull request #3755 from nirvn/style_manager_upgrade

[FEATURE] Style management re-work and upgrade
This commit is contained in:
Nyall Dawson 2016-11-17 12:40:52 +10:00 committed by GitHub
commit e624518e00
30 changed files with 1190 additions and 933 deletions

View File

@ -1371,6 +1371,11 @@ QgsSvgCache {#qgis_api_break_3_0_QgsSvgCache}
- containsParamsV2() was removed. Use containsParamsV3() instead. - containsParamsV2() was removed. Use containsParamsV3() instead.
QgsStyle (renamed from QgsStyleV2) {#qgis_api_break_3_0_QgsStyle}
----------------------------------
- All group functions have been removed: group(), addGroup(), groupId(), groupName(), groupNames(), groupIds(), symbolsOfGroup(), getGroupRemoveQuery()
- The StyleEntity::GroupEntity has been removed
- The SymgroupTable enum has been removed
QgsSymbol (renamed from QgsSymbolV2) {#qgis_api_break_3_0_QgsSymbol} QgsSymbol (renamed from QgsSymbolV2) {#qgis_api_break_3_0_QgsSymbol}
------------------------------------ ------------------------------------

View File

@ -8,15 +8,16 @@ class QgsStyle : QObject
QgsStyle(); QgsStyle();
~QgsStyle(); ~QgsStyle();
//! Enum for Entities involved in a style /** Enum for Entities involved in a style
/*! /*
The enumerator is used for identifying the entity being operated on when generic * The enumerator is used for identifying the entity being operated on when generic
database functions are being run. * database functions are being run.
\sa group(), rename(), remove(), symbolsOfGroup(), symbolsWithTag(), symbolsOfSmartgroup() * \sa group(), rename(), remove(), symbolsOfGroup(), symbolsWithTag(), symbolsOfSmartgroup()
*/ */
enum StyleEntity { SymbolEntity, GroupEntity, TagEntity, ColorrampEntity, SmartgroupEntity }; enum StyleEntity { SymbolEntity, TagEntity, ColorrampEntity, SmartgroupEntity };
/** Adds a color ramp to the style. Calling this method takes the ramp's ownership. /** Adds a color ramp to the style. Calling this method takes the ramp's ownership.
*
* \note Adding a color ramp with the name of existing one replaces it. * \note Adding a color ramp with the name of existing one replaces it.
* \param name is the name of the color ramp being added or updated * \param name is the name of the color ramp being added or updated
* \param colorRamp is the color ramp. Ownership is transferred. * \param colorRamp is the color ramp. Ownership is transferred.
@ -25,24 +26,16 @@ class QgsStyle : QObject
*/ */
bool addColorRamp( const QString& name, QgsColorRamp* colorRamp /Transfer/, bool update = false ); bool addColorRamp( const QString& name, QgsColorRamp* colorRamp /Transfer/, bool update = false );
//! adds a new group and returns the group's id /** Adds new smartgroup to the database and returns the id
/*! *
* \param groupName the name of the new group as QString
* \param parent is the id of the parent group when a subgrouo is to be created. By default it is 0 indicating it is not a sub-group
* \return returns an int, which is the DB id of the new group created, 0 if the group couldn't be created
*/
int addGroup( const QString& groupName, int parent = 0 );
//! adds new smartgroup to the database and returns the id
/*!
* \param name is the name of the new Smart Group to be added * \param name is the name of the new Smart Group to be added
* \param op is the operator between the conditions; AND/OR as QString * \param op is the operator between the conditions; AND/OR as QString
* \param conditions are the smart group conditions * \param conditions are the smart group conditions
*/ */
int addSmartgroup( const QString& name, const QString& op, QMultiMap<QString, QString> conditions ); int addSmartgroup( const QString& name, const QString& op, QMultiMap<QString, QString> conditions );
//! add symbol to style. takes symbol's ownership /** Adds symbol to style and takes symbol's ownership
/*! *
* \note Adding a symbol with the name of existing one replaces it. * \note Adding a symbol with the name of existing one replaces it.
* \param name is the name of the symbol being added or updated * \param name is the name of the symbol being added or updated
* \param symbol is the Vector symbol * \param symbol is the Vector symbol
@ -51,22 +44,19 @@ class QgsStyle : QObject
*/ */
bool addSymbol( const QString& name, QgsSymbol* symbol /Transfer/, bool update = false ); bool addSymbol( const QString& name, QgsSymbol* symbol /Transfer/, bool update = false );
//! adds a new tag and returns the tag's id /** Adds a new tag and returns the tag's id
/*! *
* \param tagName the name of the new tag to be created * \param tagName the name of the new tag to be created
* \return returns an int, which is the DB id of the new tag created, 0 if the tag couldn't be created * \return returns an int, which is the DB id of the new tag created, 0 if the tag couldn't be created
*/ */
int addTag( const QString& tagName ); int addTag( const QString& tagName );
/** Returns a list of all tags in the style database /** Returns a list of all tags in the style database
* @note added in QGIS 2.16 * @note added in QGIS 2.16
* @see addTag() * @see addTag()
*/ */
QStringList tags() const; QStringList tags() const;
//! return a map of groupid and names for the given parent group
QMap<int, QString> childGroupNames( const QString& parent = "" );
//! remove all contents of the style //! remove all contents of the style
void clear(); void clear();
@ -75,24 +65,25 @@ class QgsStyle : QObject
*/ */
QgsColorRamp* colorRamp( const QString& name ) const /Factory/; QgsColorRamp* colorRamp( const QString& name ) const /Factory/;
//! return count of color ramps //! Returns count of color ramps
int colorRampCount(); int colorRampCount();
//! return a list of names of color ramps //! Returns a list of names of color ramps
QStringList colorRampNames(); QStringList colorRampNames();
//! return a const pointer to a symbol (doesn't create new instance) //! Returns a const pointer to a symbol (doesn't create new instance)
const QgsColorRamp* colorRampRef( const QString& name ) const; const QgsColorRamp* colorRampRef( const QString& name ) const;
//! return the id in the style database for the given colorramp name /** Returns the id in the style database for the given colorramp name
//! returns 0 if not found * returns 0 if not found
*/
int colorrampId( const QString& name ); int colorrampId( const QString& name );
//! return default application-wide style //! Returns default application-wide style
static QgsStyle* defaultStyle(); static QgsStyle* defaultStyle();
//! tags the symbol with the tags in the list /** Tags the symbol with the tags in the list
/*! *
* Applies the given tags to the given symbol or colorramp * Applies the given tags to the given symbol or colorramp
* \param type is either SymbolEntity or ColorrampEntity * \param type is either SymbolEntity or ColorrampEntity
* \param symbol is the name of the symbol or colorramp as QString * \param symbol is the name of the symbol or colorramp as QString
@ -101,8 +92,8 @@ class QgsStyle : QObject
*/ */
bool tagSymbol( StyleEntity type, const QString& symbol, const QStringList& tags ); bool tagSymbol( StyleEntity type, const QString& symbol, const QStringList& tags );
//! detags the symbol with the given list /** Detags the symbol with the given list
/*! *
* Removes the given tags for the specified symbol or colorramp * Removes the given tags for the specified symbol or colorramp
* \param type is either SymbolEntity or ColorrampEntity * \param type is either SymbolEntity or ColorrampEntity
* \param symbol is the name of the symbol or colorramp * \param symbol is the name of the symbol or colorramp
@ -110,85 +101,89 @@ class QgsStyle : QObject
* \return returns the success state of the operation * \return returns the success state of the operation
*/ */
bool detagSymbol( StyleEntity type, QString symbol, QStringList tags ); bool detagSymbol( StyleEntity type, QString symbol, QStringList tags );
/** Clears the symbol from all attached tags
*
* Removes all tags for the specified symbol or colorramp
* \param type is either SymbolEntity or ColorrampEntity
* \param symbol is the name of the symbol or colorramp
* \return returns the success state of the operation
*/
bool detagSymbol( StyleEntity type, QString symbol );
//! remove symbol from style (and delete it) //! Removes symbol from style (and delete it)
bool removeSymbol( const QString& name ); bool removeSymbol( const QString& name );
//! change symbol's name //! Changes symbol's name
bool renameSymbol( const QString& oldName, const QString& newName ); bool renameSymbol( const QString& oldName, const QString& newName );
//! return a NEW copy of symbol //! Returns a NEW copy of symbol
QgsSymbol* symbol( const QString& name ) /Factory/; QgsSymbol* symbol( const QString& name ) /Factory/;
//! return a const pointer to a symbol (doesn't create new instance) //! Returns a const pointer to a symbol (doesn't create new instance)
const QgsSymbol* symbolRef( const QString& name ) const; const QgsSymbol* symbolRef( const QString& name ) const;
//! return count of symbols in style //! Returns count of symbols in style
int symbolCount(); int symbolCount();
//! return a list of names of symbols //! Returns a list of names of symbols
QStringList symbolNames(); QStringList symbolNames();
//! return the id in the style database for the given symbol name /** Returns the id in the style database for the given symbol name
//! returns 0 if not found * returns 0 if not found
*/
int symbolId( const QString& name ); int symbolId( const QString& name );
//! return the DB id for the given group name //! Returns the DB id for the given tag name
int groupId( const QString& group );
//! return the group name for the given DB id
QString groupName( int groupId ) const;
//! return the DB id for the given tag name
int tagId( const QString& tag ); int tagId( const QString& tag );
//! return the DB id for the given smartgroup name //! Returns the DB id for the given smartgroup name
int smartgroupId( const QString& smartgroup ); int smartgroupId( const QString& smartgroup );
//! return the all the groups in the style /** Returns the symbol names which are flagged as favorite
QStringList groupNames(); *
//! return the ids of all the groups in the style
QList<int> groupIds() const;
//! returns the symbolnames of a given groupid
/*!
* \param type is either SymbolEntity or ColorampEntity * \param type is either SymbolEntity or ColorampEntity
* \param groupid is id of the group to which the symbols belong to, as int * \return A QStringList of the symbol or colorramp names flagged as favorite
* \return A QStringList of the symbol or colorramp names for the given group id
*/ */
QStringList symbolsOfGroup( StyleEntity type, int groupid ); QStringList symbolsOfFavorite( StyleEntity type );
//! returns the symbol names with which have the given tag /** Returns the symbol names with which have the given tag
/*! *
* \param type is either SymbolEntity or ColorampEntity * \param type is either SymbolEntity or ColorampEntity
* \param tagid is id of the tag which has been applied over the symbol as int * \param tagid is id of the tag which has been applied over the symbol as int
* \return A QStringList of the symbol or colorramp names for the given tag id * \return A QStringList of the symbol or colorramp names for the given tag id
*/ */
QStringList symbolsWithTag( StyleEntity type, int tagid ); QStringList symbolsWithTag( StyleEntity type, int tagid );
//! applies the specified group to the symbol or colorramp specified by StyleEntity /** Adds the specified symbol to favorites
/*! *
* \param type is either SymbolEntity of ColorrampEntity * \param type is either SymbolEntity of ColorrampEntity
* \param name is the name of the symbol or coloramp whose group is to be set * \param name is the name of the symbol or coloramp whose is to be added to favorites
* \param groupid is the id of the group to which the entity is assigned
* \return returns the success state as bool * \return returns the success state as bool
*/ */
bool group( StyleEntity type, const QString& name, int groupid ); bool addFavorite( StyleEntity type, const QString& name );
/** Removes the specified symbol from favorites
*
* \param type is either SymbolEntity of ColorrampEntity
* \param name is the name of the symbol or coloramp whose is to be removed from favorites
* \return returns the success state as bool
*/
bool removeFavorite( StyleEntity type, const QString& name );
//! rename the given entity with the specified id /** Renames the given entity with the specified id
/*! *
* \param type is any of the style entites. Refer enum StyleEntity. * \param type is any of the style entites. Refer enum StyleEntity.
* \param id is the DB id of the entity which is to be renamed * \param id is the DB id of the entity which is to be renamed
* \param newName is the new name of the entity * \param newName is the new name of the entity
*/ */
void rename( StyleEntity type, int id, const QString& newName ); void rename( StyleEntity type, int id, const QString& newName );
//! remove the specified entity from the db /** Removes the specified entity from the db
/*! *
* \param type is any of the style entites. Refer enum StyleEntity. * \param type is any of the style entites. Refer enum StyleEntity.
* \param id is the DB id of the entity to be removed * \param id is the DB id of the entity to be removed
*/ */
void remove( StyleEntity type, int id ); void remove( StyleEntity type, int id );
//! add the symbol to the DB with the tags /** Adds the symbol to the DB with the tags
/*! *
* \param name is the name of the symbol as QString * \param name is the name of the symbol as QString
* \param symbol is the pointer to the new QgsSymbol being saved * \param symbol is the pointer to the new QgsSymbol being saved
* \param groupid is the id of the group to which the symbol belongs. Pass 0 if it doesn't belong to any group or not known. * \param groupid is the id of the group to which the symbol belongs. Pass 0 if it doesn't belong to any group or not known.
@ -197,8 +192,8 @@ class QgsStyle : QObject
*/ */
bool saveSymbol( const QString& name, QgsSymbol* symbol /Transfer/, int groupid, const QStringList& tags ); bool saveSymbol( const QString& name, QgsSymbol* symbol /Transfer/, int groupid, const QStringList& tags );
//! add the colorramp to the DB /** Adds the colorramp to the DB
/*! *
* \param name is the name of the colorramp as QString * \param name is the name of the colorramp as QString
* \param ramp is the pointer to the new QgsColorRamp being saved * \param ramp is the pointer to the new QgsColorRamp being saved
* \param groupid is the id of the group to which the Color Ramp belongs. Pass 0 if it doesn't belong to any group or not known. * \param groupid is the id of the group to which the Color Ramp belongs. Pass 0 if it doesn't belong to any group or not known.
@ -207,54 +202,54 @@ class QgsStyle : QObject
*/ */
bool saveColorRamp( const QString& name, QgsColorRamp* ramp, int groupid, const QStringList& tags ); bool saveColorRamp( const QString& name, QgsColorRamp* ramp, int groupid, const QStringList& tags );
//! remove color ramp from style (and delete it) //! Removes color ramp from style (and delete it)
bool removeColorRamp( const QString& name ); bool removeColorRamp( const QString& name );
//! change ramp's name //! Changes ramp's name
bool renameColorRamp( const QString& oldName, const QString& newName ); bool renameColorRamp( const QString& oldName, const QString& newName );
//! load a file into the style //! Loads a file into the style
bool load( const QString& filename ); bool load( const QString& filename );
//! save style into a file (will use current filename if empty string is passed) //! Saves style into a file (will use current filename if empty string is passed)
bool save( QString filename = QString() ); bool save( QString filename = QString() );
//! return last error from load/save operation //! Returns last error from load/save operation
QString errorString(); QString errorString();
//! return current file name of the style //! Returns current file name of the style
QString fileName(); QString fileName();
//! return the names of the symbols which have a matching 'substring' in its defintion /** Returns the names of the symbols which have a matching 'substring' in its defintion
/*! *
* \param type is either SymbolEntity or ColorrampEntity * \param type is either SymbolEntity or ColorrampEntity
* \param qword is the query string to search the symbols or colorramps. * \param qword is the query string to search the symbols or colorramps.
* \return A QStringList of the matched symbols or colorramps * \return A QStringList of the matched symbols or colorramps
* */ * */
QStringList findSymbols( StyleEntity type, const QString& qword ); QStringList findSymbols( StyleEntity type, const QString& qword );
//! return the tags associated with the symbol /** Returns the tags associated with the symbol
/*! *
* \param type is either SymbolEntity or ColorrampEntity * \param type is either SymbolEntity or ColorrampEntity
* \param symbol is the name of the symbol or color ramp * \param symbol is the name of the symbol or color ramp
* \return A QStringList of the tags that have been applied to that symbol/colorramp * \return A QStringList of the tags that have been applied to that symbol/colorramp
*/ */
QStringList tagsOfSymbol( StyleEntity type, const QString& symbol ); QStringList tagsOfSymbol( StyleEntity type, const QString& symbol );
//! returns the smart groups map with id as key and name as value //! Returns the smart groups map with id as key and name as value
QMap<int, QString> smartgroupsListMap(); QMap<int, QString> smartgroupsListMap();
//! returns the smart groups list //! Returns the smart groups list
QStringList smartgroupNames(); QStringList smartgroupNames();
//! returns the QgsSmartConditionMap for the given id //! Returns the QgsSmartConditionMap for the given id
QMultiMap<QString, QString> smartgroup( int id ); QMultiMap<QString, QString> smartgroup( int id );
//! returns the operator for the smartgroup //! Returns the operator for the smartgroup
//clumsy implementation TODO create a class for smartgroups //clumsy implementation TODO create a class for smartgroups
QString smartgroupOperator( int id ); QString smartgroupOperator( int id );
//! returns the symbols for the smartgroup //! Returns the symbols for the smartgroup
QStringList symbolsOfSmartgroup( StyleEntity type, int id ); QStringList symbolsOfSmartgroup( StyleEntity type, int id );
//! Exports the style as a XML file //! Exports the style as a XML file
@ -264,29 +259,30 @@ class QgsStyle : QObject
bool importXml( const QString& filename ); bool importXml( const QString& filename );
signals: signals:
//! Is emitted every time a new symbol has been added to the database
void symbolSaved( const QString& name, QgsSymbol* symbol ); void symbolSaved( const QString& name, QgsSymbol* symbol );
//! Is emitted every time a tag or smartgroup has been added, removed, or renamed
void groupsModified();
protected: protected:
//! convenience function to open the DB and return a sqlite3 object //! Convenience function to open the DB and return a sqlite3 object
bool openDB( const QString& filename ); bool openDB( const QString& filename );
//! convenience function that would run queries which don't generate return values /** Convenience function that would run queries which don't generate return values
//! \param query query to run * \param query query to run
//! \param freeQuery release query memory * \param freeQuery release query memory
//! \return success true on success * \return success true on success
*/
bool runEmptyQuery( char* query, bool freeQuery = true ); bool runEmptyQuery( char* query, bool freeQuery = true );
//! prepares the complex query for removing a group, so that the children are not abandoned //! Gets the id from the table for the given name from the database, 0 if not found
char* getGroupRemoveQuery( int id );
//! gets the id from the table for the given name from the database, 0 if not found
int getId( const QString& table, const QString& name ); int getId( const QString& table, const QString& name );
//! gets the name from the table for the given id from the database, empty if not found //! Gets the name from the table for the given id from the database, empty if not found
QString getName( const QString& table, int id ) const; QString getName( const QString& table, int id ) const;
//! updates the properties of an existing symbol/colorramp /** Updates the properties of an existing symbol/colorramp
/*! *
* \note This should not be called separately, only called through addSymbol or addColorRamp * \note This should not be called separately, only called through addSymbol or addColorRamp
* \param type is either SymbolEntity or ColorrampEntity * \param type is either SymbolEntity or ColorrampEntity
* \param name is the name of an existing symbol or a color ramp * \param name is the name of an existing symbol or a color ramp

View File

@ -247,6 +247,7 @@
%Include symbology-ng/qgsstyleexportimportdialog.sip %Include symbology-ng/qgsstyleexportimportdialog.sip
%Include symbology-ng/qgsstylegroupselectiondialog.sip %Include symbology-ng/qgsstylegroupselectiondialog.sip
%Include symbology-ng/qgsstylemanagerdialog.sip %Include symbology-ng/qgsstylemanagerdialog.sip
%Include symbology-ng/qgsstylesavedialog.sip
%Include symbology-ng/qgssvgselectorwidget.sip %Include symbology-ng/qgssvgselectorwidget.sip
%Include symbology-ng/qgssymbollayerwidget.sip %Include symbology-ng/qgssymbollayerwidget.sip
%Include symbology-ng/qgssymbollevelsdialog.sip %Include symbology-ng/qgssymbollevelsdialog.sip

View File

@ -41,15 +41,15 @@ class QgsStyleExportImportDialog : QDialog
*/ */
void clearSelection(); void clearSelection();
/** /**
* Select the symbols belonging to the given group * Select the symbols belonging to the given tag
* @param groupName the name of the group to be selected * @param tagName the name of the tag to be selected
*/ */
void selectGroup( const QString& groupName ); void selectTag( const QString& tagName );
/** /**
* Deselect the symbols belonging to the given group * Deselect the symbols belonging to the given tag
* @param groupName the name of the group to be deselected * @param tagName the name of the tag to be deselected
*/ */
void deselectGroup( const QString& groupName ); void deselectTag( const QString& tagName );
/** /**
* @brief selectSmartgroup selects all symbols from a smart group * @brief selectSmartgroup selects all symbols from a smart group
* @param groupName * @param groupName

View File

@ -28,10 +28,10 @@ class QgsStyleGroupSelectionDialog : public QDialog, private Ui::SymbolsGroupSel
void setBold( QStandardItem *item ); void setBold( QStandardItem *item );
signals: signals:
//! group with groupName has been selected //! tag with tagName has been selected
void groupSelected( const QString& groupName ); void tagSelected( const QString& tagName );
//! group with groupName has been deselected //! tag with tagName has been deselected
void groupDeselected( const QString& groupName ); void tagDeselected( const QString& tagName );
//! smartgroup with groupName has been selected //! smartgroup with groupName has been selected
void smartgroupSelected( const QString& groupName ); void smartgroupSelected( const QString& groupName );
//! smart group with groupName has been deselected //! smart group with groupName has been deselected

View File

@ -37,8 +37,8 @@ class QgsStyleManagerDialog : QDialog
void addGroup(); void addGroup();
void removeGroup(); void removeGroup();
//! carryout symbol grouping using check boxes //! carry out symbol tagging using check boxes
void groupSymbolsAction(); void tagSymbolsAction();
//! edit the selected smart group //! edit the selected smart group
void editSmartgroupAction(); void editSmartgroupAction();
@ -49,9 +49,6 @@ class QgsStyleManagerDialog : QDialog
//! filter the symbols based on input search term //! filter the symbols based on input search term
void filterSymbols( const QString& ); void filterSymbols( const QString& );
//! Listen to tag changes
void tagsChanged();
//! Perform symbol specific tasks when selected //! Perform symbol specific tasks when selected
void symbolSelected( const QModelIndex& ); void symbolSelected( const QModelIndex& );
@ -66,7 +63,14 @@ class QgsStyleManagerDialog : QDialog
protected slots: protected slots:
bool addColorRamp( QAction* action ); bool addColorRamp( QAction* action );
void groupSelectedSymbols(); //! Add selected symbols to favorites
void addFavoriteSelectedSymbols();
//! Remove selected symbols from favorites
void removeFavoriteSelectedSymbols();
//! Tag selected symbols using menu item selection
void tagSelectedSymbols();
//! Remove all tags from selected symbols
void detagSelectedSymbols();
protected: protected:
@ -75,8 +79,6 @@ class QgsStyleManagerDialog : QDialog
//! populate the groups //! populate the groups
void populateGroups(); void populateGroups();
//! build the groups tree
void buildGroupTree( QStandardItem* &parent );
//! to set symbols checked when in editing mode //! to set symbols checked when in editing mode
void setSymbolsChecked( const QStringList& ); void setSymbolsChecked( const QStringList& );
@ -107,9 +109,6 @@ class QgsStyleManagerDialog : QDialog
//! Enables or diables the groupTree items for grouping mode //! Enables or diables the groupTree items for grouping mode
void enableItemsForGroupingMode( bool ); void enableItemsForGroupingMode( bool );
//! Event filter to capture tagsLineEdit out of focus
bool eventFilter( QObject*, QEvent* );
//! sets the text of the item with bold font //! sets the text of the item with bold font
void setBold( QStandardItem* ); void setBold( QStandardItem* );
}; };

View File

@ -0,0 +1,22 @@
class QgsStyleSaveDialog : QDialog
{
%TypeHeaderCode
#include <qgsstylesavedialog.h>
%End
public:
/** Constructor for QgsSymbolSaveDialog
* @param parent parent widget
* @param type the QgsStyle entity type being saved
*/
QgsStyleSaveDialog( QWidget* parent /TransferThis/ = NULL, QgsStyle::StyleEntity type = QgsStyle::SymbolEntity );
//! returns the text value of the name element
QString name() const;
//! returns the text value of the tags element
QString tags() const;
//! returns whether the favorite element is checked
bool isFavorite() const;
};

View File

@ -37,8 +37,9 @@ class QgsSymbolsListWidget : QWidget
void on_mSymbolUnitWidget_changed(); void on_mSymbolUnitWidget_changed();
void on_mTransparencySlider_valueChanged( int value ); void on_mTransparencySlider_valueChanged( int value );
//! Pupulates the groups combo box with available tags and smartgroups
void populateGroups();
void on_groupsCombo_currentIndexChanged( int index ); void on_groupsCombo_currentIndexChanged( int index );
void on_groupsCombo_editTextChanged( const QString &text );
void openStyleManager(); void openStyleManager();
void clipFeaturesToggled( bool checked ); void clipFeaturesToggled( bool checked );

Binary file not shown.

View File

@ -838,7 +838,7 @@
<prop k="width_unit" v="MM"/> <prop k="width_unit" v="MM"/>
</layer> </layer>
</symbol> </symbol>
<symbol alpha="1" type="marker" name="airport"> <symbol alpha="1" type="marker" name="airport" favorite="1">
<layer pass="0" class="SvgMarker" locked="0"> <layer pass="0" class="SvgMarker" locked="0">
<prop k="angle" v="0"/> <prop k="angle" v="0"/>
<prop k="fill" v="#000000"/> <prop k="fill" v="#000000"/>

View File

@ -32,13 +32,13 @@ _symbol = "CREATE TABLE symbol("\
"id INTEGER PRIMARY KEY,"\ "id INTEGER PRIMARY KEY,"\
"name TEXT UNIQUE,"\ "name TEXT UNIQUE,"\
"xml TEXT,"\ "xml TEXT,"\
"groupid INTEGER)" "favorite INTEGER)"
_colorramp = "CREATE TABLE colorramp("\ _colorramp = "CREATE TABLE colorramp("\
"id INTEGER PRIMARY KEY,"\ "id INTEGER PRIMARY KEY,"\
"name TEXT UNIQUE,"\ "name TEXT UNIQUE,"\
"xml TEXT,"\ "xml TEXT,"\
"groupid INTEGER)" "favorite INTEGER)"
_tag = "CREATE TABLE tag("\ _tag = "CREATE TABLE tag("\
"id INTEGER PRIMARY KEY,"\ "id INTEGER PRIMARY KEY,"\
@ -48,57 +48,60 @@ _tagmap = "CREATE TABLE tagmap("\
"tag_id INTEGER NOT NULL,"\ "tag_id INTEGER NOT NULL,"\
"symbol_id INTEGER)" "symbol_id INTEGER)"
_symgroup = "CREATE TABLE symgroup("\ _ctagmap = "CREATE TABLE ctagmap("\
"id INTEGER PRIMARY KEY,"\ "tag_id INTEGER NOT NULL,"\
"name TEXT,"\ "colorramp_id INTEGER)"
"parent INTEGER)"
_smartgroup = "CREATE TABLE smartgroup("\ _smartgroup = "CREATE TABLE smartgroup("\
"id INTEGER PRIMARY KEY,"\ "id INTEGER PRIMARY KEY,"\
"name TEXT,"\ "name TEXT,"\
"xml TEXT)" "xml TEXT)"
_ctagmap = "CREATE TABLE ctagmap("\ create_tables = [_symbol, _colorramp, _tag, _tagmap, _ctagmap, _smartgroup]
"tag_id INTEGER NOT NULL,"\
"colorramp_id INTEGER)"
create_tables = [ _symbol, _colorramp, _tag, _tagmap, _ctagmap, _symgroup, _smartgroup ]
# Create the DB with required Schema # Create the DB with required Schema
conn = sqlite3.connect( dbfile ) conn = sqlite3.connect(dbfile)
c = conn.cursor() c = conn.cursor()
print "Creating tables in the Database\n" print "Creating tables in the Database\n"
for table in create_tables: for table in create_tables:
try: try:
c.execute( table ) c.execute(table)
print table print table
except sqlite3.OperationalError as e: except sqlite3.OperationalError as e:
pass pass
conn.commit() conn.commit()
# parse the XML file & write symbol into DB # parse the XML file & write symbol into DB
dom = parse( xmlfile ) dom = parse(xmlfile)
symbols = dom.getElementsByTagName( "symbol" ) symbols = dom.getElementsByTagName("symbol")
for symbol in symbols: for symbol in symbols:
symbol_name = symbol.getAttribute( "name" ) symbol_name = symbol.getAttribute("name")
symbol_favorite = symbol.getAttribute("favorite")
if not symbol_favorite:
symbol_favorite = 0
if '@' in symbol_name: if '@' in symbol_name:
parts = symbol_name.split('@') parts = symbol_name.split('@')
parent_name = parts[1] parent_name = parts[1]
layerno = int(parts[2]) layerno = int(parts[2])
c.execute( "SELECT xml FROM symbol WHERE name=(?)", (parent_name,) ) c.execute("SELECT xml FROM symbol WHERE name=(?)", (parent_name,))
symdom = parseString( c.fetchone()[0] ).getElementsByTagName( 'symbol' )[0] symdom = parseString(c.fetchone()[0]).getElementsByTagName('symbol')[0]
symdom.getElementsByTagName( "layer" )[ layerno ].appendChild( symbol ) symdom.getElementsByTagName("layer")[layerno].appendChild(symbol)
c.execute( "UPDATE symbol SET xml=? WHERE name=?", ( symdom.toxml(), parent_name )) c.execute("UPDATE symbol SET xml=? WHERE name=?", (symdom.toxml(), parent_name))
else: else:
c.execute( "INSERT INTO symbol VALUES (?,?,?,?)", ( None, symbol_name, symbol.toxml(), 0 ) ) c.execute("INSERT INTO symbol VALUES (?,?,?,?)", (None, symbol_name, symbol.toxml(), symbol_favorite))
conn.commit() conn.commit()
# ColorRamps # ColorRamps
colorramps = dom.getElementsByTagName( "colorramp" ) colorramps = dom.getElementsByTagName("colorramp")
for ramp in colorramps: for ramp in colorramps:
ramp_name = ramp.getAttribute( "name" ) ramp_name = ramp.getAttribute("name")
c.execute( "INSERT INTO colorramp VALUES (?,?,?,?)", ( None, ramp_name, ramp.toxml(), 0 ) ) symbol_favorite = symbol.getAttribute("favorite")
if not symbol_favorite:
symbol_favorite = 0
c.execute("INSERT INTO colorramp VALUES (?,?,?,?)", (None, ramp_name, ramp.toxml(), symbol_favorite))
conn.commit() conn.commit()
# Finally close the sqlite cursor # Finally close the sqlite cursor

View File

@ -28,6 +28,7 @@
#include <QDomNode> #include <QDomNode>
#include <QDomNodeList> #include <QDomNodeList>
#include <QFile> #include <QFile>
#include <QSettings>
#include <QTextStream> #include <QTextStream>
#include <QByteArray> #include <QByteArray>
@ -96,13 +97,13 @@ bool QgsStyle::addSymbol( const QString& name, QgsSymbol* symbol, bool update )
{ {
mSymbols.insert( name, symbol ); mSymbols.insert( name, symbol );
if ( update ) if ( update )
saveSymbol( name, symbol, 0, QStringList() ); saveSymbol( name, symbol, false, QStringList() );
} }
return true; return true;
} }
bool QgsStyle::saveSymbol( const QString& name, QgsSymbol* symbol, int groupid, const QStringList& tags ) bool QgsStyle::saveSymbol( const QString& name, QgsSymbol* symbol, bool favorite, const QStringList& tags )
{ {
// TODO add support for groups // TODO add support for groups
QDomDocument doc( QStringLiteral( "dummy" ) ); QDomDocument doc( QStringLiteral( "dummy" ) );
@ -118,7 +119,7 @@ bool QgsStyle::saveSymbol( const QString& name, QgsSymbol* symbol, int groupid,
stream.setCodec( "UTF-8" ); stream.setCodec( "UTF-8" );
symEl.save( stream, 4 ); symEl.save( stream, 4 );
char *query = sqlite3_mprintf( "INSERT INTO symbol VALUES (NULL, '%q', '%q', %d);", char *query = sqlite3_mprintf( "INSERT INTO symbol VALUES (NULL, '%q', '%q', %d);",
name.toUtf8().constData(), xmlArray.constData(), groupid ); name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
if ( !runEmptyQuery( query ) ) if ( !runEmptyQuery( query ) )
{ {
@ -207,11 +208,12 @@ bool QgsStyle::addColorRamp( const QString& name, QgsColorRamp* colorRamp, bool
return true; return true;
} }
bool QgsStyle::saveColorRamp( const QString& name, QgsColorRamp* ramp, int groupid, const QStringList& tags ) bool QgsStyle::saveColorRamp( const QString& name, QgsColorRamp* ramp, bool favorite, const QStringList& tags )
{ {
// insert it into the database // insert it into the database
QDomDocument doc( QStringLiteral( "dummy" ) ); QDomDocument doc( QStringLiteral( "dummy" ) );
QDomElement rampEl = QgsSymbolLayerUtils::saveColorRamp( name, ramp, doc ); QDomElement rampEl = QgsSymbolLayerUtils::saveColorRamp( name, ramp, doc );
if ( rampEl.isNull() ) if ( rampEl.isNull() )
{ {
QgsDebugMsg( "Couldn't convert color ramp to valid XML!" ); QgsDebugMsg( "Couldn't convert color ramp to valid XML!" );
@ -223,8 +225,7 @@ bool QgsStyle::saveColorRamp( const QString& name, QgsColorRamp* ramp, int group
stream.setCodec( "UTF-8" ); stream.setCodec( "UTF-8" );
rampEl.save( stream, 4 ); rampEl.save( stream, 4 );
char *query = sqlite3_mprintf( "INSERT INTO colorramp VALUES (NULL, '%q', '%q', %d);", char *query = sqlite3_mprintf( "INSERT INTO colorramp VALUES (NULL, '%q', '%q', %d);",
name.toUtf8().constData(), xmlArray.constData(), groupid ); name.toUtf8().constData(), xmlArray.constData(), ( favorite ? 1 : 0 ) );
if ( !runEmptyQuery( query ) ) if ( !runEmptyQuery( query ) )
{ {
QgsDebugMsg( "Couldn't insert colorramp into the database!" ); QgsDebugMsg( "Couldn't insert colorramp into the database!" );
@ -301,8 +302,8 @@ bool QgsStyle::load( const QString& filename )
} }
// Make sure there are no Null fields in parenting symbols ang groups // Make sure there are no Null fields in parenting symbols ang groups
char *query = sqlite3_mprintf( "UPDATE symbol SET groupid=0 WHERE groupid IS NULL;" char *query = sqlite3_mprintf( "UPDATE symbol SET favorite=0 WHERE favorite IS NULL;"
"UPDATE colorramp SET groupid=0 WHERE groupid IS NULL;" "UPDATE colorramp SET favorite=0 WHERE favorite IS NULL;"
"UPDATE symgroup SET parent=0 WHERE parent IS NULL;" ); "UPDATE symgroup SET parent=0 WHERE parent IS NULL;" );
runEmptyQuery( query ); runEmptyQuery( query );
@ -460,97 +461,22 @@ bool QgsStyle::renameColorRamp( const QString& oldName, const QString& newName )
return true; return true;
} }
QStringList QgsStyle::groupNames() QStringList QgsStyle::symbolsOfFavorite( StyleEntity type ) const
{
QStringList groupNames;
sqlite3_stmt *ppStmt;
const char *query = "SELECT * FROM symgroup";
int nError = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, nullptr );
while ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
{
groupNames << QString::fromUtf8( reinterpret_cast< const char * >( sqlite3_column_text( ppStmt, SymgroupName ) ) );
}
sqlite3_finalize( ppStmt );
return groupNames;
}
QList<int> QgsStyle::groupIds() const
{
QList<int> groupIds;
sqlite3_stmt *ppStmt;
const char *query = "SELECT * FROM symgroup";
int nError = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, nullptr );
while ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
{
groupIds << QString::fromUtf8( reinterpret_cast< const char * >( sqlite3_column_text( ppStmt, SymgroupId ) ) ).toInt();
}
sqlite3_finalize( ppStmt );
return groupIds;
}
QgsSymbolGroupMap QgsStyle::childGroupNames( const QString& parent )
{
// get the name list from the sqlite database and return as a QStringList
if ( !mCurrentDB )
{
QgsDebugMsg( "Cannot open database for listing groups" );
return QgsSymbolGroupMap();
}
char *query = nullptr;
int nError;
sqlite3_stmt *ppStmt;
// decide the query to be run based on parent group
if ( parent == QLatin1String( "" ) || parent == QString() )
{
query = sqlite3_mprintf( "SELECT * FROM symgroup WHERE parent=0" );
}
else
{
char *subquery = sqlite3_mprintf( "SELECT * FROM symgroup WHERE name='%q'", parent.toUtf8().constData() );
nError = sqlite3_prepare_v2( mCurrentDB, subquery, -1, &ppStmt, nullptr );
if ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
{
query = sqlite3_mprintf( "SELECT * FROM symgroup WHERE parent=%d", sqlite3_column_int( ppStmt, SymgroupId ) );
}
sqlite3_finalize( ppStmt );
}
if ( !query )
return QgsSymbolGroupMap();
QgsSymbolGroupMap groupNames;
// Now run the query and retrieve the group names
nError = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, nullptr );
while ( nError == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
{
QString group = QString::fromUtf8( reinterpret_cast< const char * >( sqlite3_column_text( ppStmt, SymgroupName ) ) );
groupNames.insert( sqlite3_column_int( ppStmt, SymgroupId ), group );
}
sqlite3_finalize( ppStmt );
return groupNames;
}
QStringList QgsStyle::symbolsOfGroup( StyleEntity type, int groupid )
{ {
if ( !mCurrentDB ) if ( !mCurrentDB )
{ {
QgsDebugMsg( QString( "Cannot Open database for getting group symbols of groupid: %1" ).arg( groupid ) ); QgsDebugMsg( QString( "Cannot Open database for getting favorite symbols" ) );
return QStringList(); return QStringList();
} }
char *query; char *query;
if ( type == SymbolEntity ) if ( type == SymbolEntity )
{ {
query = sqlite3_mprintf( "SELECT name FROM symbol WHERE groupid=%d", groupid ); query = sqlite3_mprintf( "SELECT name FROM symbol WHERE favorite=1" );
} }
else if ( type == ColorrampEntity ) else if ( type == ColorrampEntity )
{ {
query = sqlite3_mprintf( "SELECT name FROM colorramp WHERE groupid=%d", groupid ); query = sqlite3_mprintf( "SELECT name FROM colorramp WHERE favorite=1" );
} }
else else
{ {
@ -572,7 +498,7 @@ QStringList QgsStyle::symbolsOfGroup( StyleEntity type, int groupid )
return symbols; return symbols;
} }
QStringList QgsStyle::symbolsWithTag( StyleEntity type, int tagid ) QStringList QgsStyle::symbolsWithTag( StyleEntity type, int tagid ) const
{ {
if ( !mCurrentDB ) if ( !mCurrentDB )
{ {
@ -587,7 +513,7 @@ QStringList QgsStyle::symbolsWithTag( StyleEntity type, int tagid )
} }
else if ( type == ColorrampEntity ) else if ( type == ColorrampEntity )
{ {
subquery = sqlite3_mprintf( "SELECT symbol_id FROM ctagmap WHERE tag_id=%d", tagid ); subquery = sqlite3_mprintf( "SELECT colorramp_id FROM ctagmap WHERE tag_id=%d", tagid );
} }
else else
{ {
@ -598,15 +524,15 @@ QStringList QgsStyle::symbolsWithTag( StyleEntity type, int tagid )
sqlite3_stmt *ppStmt; sqlite3_stmt *ppStmt;
int nErr = sqlite3_prepare_v2( mCurrentDB, subquery, -1, &ppStmt, nullptr ); int nErr = sqlite3_prepare_v2( mCurrentDB, subquery, -1, &ppStmt, nullptr );
// get the symbol <-> tag connection from table 'tagmap' // get the symbol <-> tag connection from table 'tagmap'/'ctagmap'
QStringList symbols; QStringList symbols;
while ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW ) while ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
{ {
int symbolId = sqlite3_column_int( ppStmt, 0 ); int id = sqlite3_column_int( ppStmt, 0 );
char *query = type == SymbolEntity char *query = type == SymbolEntity
? sqlite3_mprintf( "SELECT name FROM symbol WHERE id=%d", symbolId ) ? sqlite3_mprintf( "SELECT name FROM symbol WHERE id=%d", id )
: sqlite3_mprintf( "SELECT name FROM colorramp WHERE id=%d", symbolId ); : sqlite3_mprintf( "SELECT name FROM colorramp WHERE id=%d", id );
sqlite3_stmt *ppStmt2; sqlite3_stmt *ppStmt2;
int sErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt2, nullptr ); int sErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt2, nullptr );
@ -621,23 +547,6 @@ QStringList QgsStyle::symbolsWithTag( StyleEntity type, int tagid )
return symbols; return symbols;
} }
int QgsStyle::addGroup( const QString& groupName, int parentid )
{
if ( !mCurrentDB )
return 0;
char *query = sqlite3_mprintf( "INSERT INTO symgroup VALUES (NULL, '%q', %d)", groupName.toUtf8().constData(), parentid );
sqlite3_stmt *ppStmt;
int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, nullptr );
if ( nErr == SQLITE_OK )
( void )sqlite3_step( ppStmt );
sqlite3_finalize( ppStmt );
return static_cast< int >( sqlite3_last_insert_rowid( mCurrentDB ) );
}
int QgsStyle::addTag( const QString& tagname ) int QgsStyle::addTag( const QString& tagname )
{ {
if ( !mCurrentDB ) if ( !mCurrentDB )
@ -650,6 +559,11 @@ int QgsStyle::addTag( const QString& tagname )
( void )sqlite3_step( ppStmt ); ( void )sqlite3_step( ppStmt );
sqlite3_finalize( ppStmt ); sqlite3_finalize( ppStmt );
QSettings settings;
settings.setValue( QStringLiteral( "qgis/symbolsListGroupsIndex" ), 0 );
emit groupsModified();
return static_cast< int >( sqlite3_last_insert_rowid( mCurrentDB ) ); return static_cast< int >( sqlite3_last_insert_rowid( mCurrentDB ) );
} }
@ -676,69 +590,60 @@ QStringList QgsStyle::tags() const
void QgsStyle::rename( StyleEntity type, int id, const QString& newName ) void QgsStyle::rename( StyleEntity type, int id, const QString& newName )
{ {
bool groupRenamed = false;
char *query; char *query;
switch ( type ) switch ( type )
{ {
case SymbolEntity: case SymbolEntity:
query = sqlite3_mprintf( "UPDATE symbol SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id ); query = sqlite3_mprintf( "UPDATE symbol SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id );
break; break;
case GroupEntity:
query = sqlite3_mprintf( "UPDATE symgroup SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id );
break;
case TagEntity:
query = sqlite3_mprintf( "UPDATE tag SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id );
break;
case ColorrampEntity: case ColorrampEntity:
query = sqlite3_mprintf( "UPDATE colorramp SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id ); query = sqlite3_mprintf( "UPDATE colorramp SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id );
break; break;
case TagEntity:
query = sqlite3_mprintf( "UPDATE tag SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id );
groupRenamed = true;
break;
case SmartgroupEntity: case SmartgroupEntity:
query = sqlite3_mprintf( "UPDATE smartgroup SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id ); query = sqlite3_mprintf( "UPDATE smartgroup SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id );
groupRenamed = true;
break; break;
default: default:
QgsDebugMsg( "Invalid Style Entity indicated" ); QgsDebugMsg( "Invalid Style Entity indicated" );
return; return;
} }
if ( !runEmptyQuery( query ) ) if ( !runEmptyQuery( query ) )
{
mErrorString = QStringLiteral( "Could not rename!" ); mErrorString = QStringLiteral( "Could not rename!" );
} }
else
char* QgsStyle::getGroupRemoveQuery( int id ) {
{ if ( groupRenamed )
char *query = sqlite3_mprintf( "SELECT parent FROM symgroup WHERE id=%d", id ); {
emit groupsModified();
sqlite3_stmt *ppStmt; }
int err = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, nullptr ); }
int parentid = 0;
if ( err == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
parentid = sqlite3_column_int( ppStmt, 0 );
sqlite3_finalize( ppStmt );
return sqlite3_mprintf( "UPDATE symbol SET groupid=%d WHERE groupid=%d;"
"UPDATE symgroup SET parent=%d WHERE parent=%d;"
"DELETE FROM symgroup WHERE id=%d", parentid, id, parentid, id, id );
} }
void QgsStyle::remove( StyleEntity type, int id ) void QgsStyle::remove( StyleEntity type, int id )
{ {
bool groupRemoved = false;
char *query; char *query;
switch ( type ) switch ( type )
{ {
case SymbolEntity: case SymbolEntity:
query = sqlite3_mprintf( "DELETE FROM symbol WHERE id=%d; DELETE FROM tagmap WHERE symbol_id=%d", id, id ); query = sqlite3_mprintf( "DELETE FROM symbol WHERE id=%d; DELETE FROM tagmap WHERE symbol_id=%d", id, id );
break; break;
case GroupEntity:
query = getGroupRemoveQuery( id );
break;
case TagEntity:
query = sqlite3_mprintf( "DELETE FROM tag WHERE id=%d; DELETE FROM tagmap WHERE tag_id=%d", id, id );
break;
case ColorrampEntity: case ColorrampEntity:
query = sqlite3_mprintf( "DELETE FROM colorramp WHERE id=%d", id ); query = sqlite3_mprintf( "DELETE FROM colorramp WHERE id=%d", id );
break; break;
case TagEntity:
query = sqlite3_mprintf( "DELETE FROM tag WHERE id=%d; DELETE FROM tagmap WHERE tag_id=%d", id, id );
groupRemoved = true;
break;
case SmartgroupEntity: case SmartgroupEntity:
query = sqlite3_mprintf( "DELETE FROM smartgroup WHERE id=%d", id ); query = sqlite3_mprintf( "DELETE FROM smartgroup WHERE id=%d", id );
groupRemoved = true;
break; break;
default: default:
QgsDebugMsg( "Invalid Style Entity indicated" ); QgsDebugMsg( "Invalid Style Entity indicated" );
@ -749,6 +654,16 @@ void QgsStyle::remove( StyleEntity type, int id )
{ {
QgsDebugMsg( "Could not delete entity!" ); QgsDebugMsg( "Could not delete entity!" );
} }
else
{
if ( groupRemoved )
{
QSettings settings;
settings.setValue( QStringLiteral( "qgis/symbolsListGroupsIndex" ), 0 );
emit groupsModified();
}
}
} }
bool QgsStyle::runEmptyQuery( char *query, bool freeQuery ) bool QgsStyle::runEmptyQuery( char *query, bool freeQuery )
@ -772,17 +687,38 @@ bool QgsStyle::runEmptyQuery( char *query, bool freeQuery )
return zErr == SQLITE_OK; return zErr == SQLITE_OK;
} }
bool QgsStyle::group( StyleEntity type, const QString& name, int groupid ) bool QgsStyle::addFavorite( StyleEntity type, const QString& name )
{ {
char *query; char *query;
switch ( type ) switch ( type )
{ {
case SymbolEntity: case SymbolEntity:
query = sqlite3_mprintf( "UPDATE symbol SET groupid=%d WHERE name='%q'", groupid, name.toUtf8().constData() ); query = sqlite3_mprintf( "UPDATE symbol SET favorite=1 WHERE name='%q'", name.toUtf8().constData() );
break; break;
case ColorrampEntity: case ColorrampEntity:
query = sqlite3_mprintf( "UPDATE colorramp SET groupid=%d WHERE name='%q'", groupid, name.toUtf8().constData() ); query = sqlite3_mprintf( "UPDATE colorramp SET favorite=1 WHERE name='%q'", name.toUtf8().constData() );
break;
default:
QgsDebugMsg( "Wrong entity value. cannot apply group" );
return false;
}
return runEmptyQuery( query );
}
bool QgsStyle::removeFavorite( StyleEntity type, const QString& name )
{
char *query;
switch ( type )
{
case SymbolEntity:
query = sqlite3_mprintf( "UPDATE symbol SET favorite=0 WHERE name='%q'", name.toUtf8().constData() );
break;
case ColorrampEntity:
query = sqlite3_mprintf( "UPDATE colorramp SET favorite=0 WHERE name='%q'", name.toUtf8().constData() );
break; break;
default: default:
@ -882,37 +818,41 @@ bool QgsStyle::tagSymbol( StyleEntity type, const QString& symbol, const QString
return false; return false;
} }
QString tag;
Q_FOREACH ( const QString &tag, tags ) Q_FOREACH ( const QString &t, tags )
{ {
// sql: gets the id of the tag if present or insert the tag and get the id of the tag tag = t.trimmed();
char *query = sqlite3_mprintf( "SELECT id FROM tag WHERE name='%q'", tag.toUtf8().constData() ); if ( tag != "" )
sqlite3_stmt *ppStmt;
int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, nullptr );
int tagid;
if ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
{ {
tagid = sqlite3_column_int( ppStmt, 0 ); // sql: gets the id of the tag if present or insert the tag and get the id of the tag
} char *query = sqlite3_mprintf( "SELECT id FROM tag WHERE LOWER(name)='%q'", tag.toUtf8().toLower().constData() );
else
{
tagid = addTag( tag );
}
sqlite3_finalize( ppStmt ); sqlite3_stmt *ppStmt;
int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, nullptr );
// Now map the tag to the symbol int tagid;
query = type == SymbolEntity if ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
? sqlite3_mprintf( "INSERT INTO tagmap VALUES (%d,%d)", tagid, symbolid ) {
: sqlite3_mprintf( "INSERT INTO ctagmap VALUES (%d,%d)", tagid, symbolid ); tagid = sqlite3_column_int( ppStmt, 0 );
}
else
{
tagid = addTag( tag );
}
char *zErr = nullptr; sqlite3_finalize( ppStmt );
nErr = sqlite3_exec( mCurrentDB, query, nullptr, nullptr, &zErr );
if ( nErr ) // Now map the tag to the symbol
{ query = type == SymbolEntity
QgsDebugMsg( zErr ); ? sqlite3_mprintf( "INSERT INTO tagmap VALUES (%d,%d)", tagid, symbolid )
: sqlite3_mprintf( "INSERT INTO ctagmap VALUES (%d,%d)", tagid, symbolid );
char *zErr = nullptr;
nErr = sqlite3_exec( mCurrentDB, query, nullptr, nullptr, &zErr );
if ( nErr )
{
QgsDebugMsg( zErr );
}
} }
} }
@ -977,6 +917,45 @@ bool QgsStyle::detagSymbol( StyleEntity type, const QString& symbol, const QStri
return true; return true;
} }
bool QgsStyle::detagSymbol( StyleEntity type, const QString& symbol )
{
if ( !mCurrentDB )
{
QgsDebugMsg( "Sorry! Cannot open database for detgging." );
return false;
}
char *query = type == SymbolEntity
? sqlite3_mprintf( "SELECT id FROM symbol WHERE name='%q'", symbol.toUtf8().constData() )
: sqlite3_mprintf( "SELECT id FROM colorramp WHERE name='%q'", symbol.toUtf8().constData() );
sqlite3_stmt *ppStmt;
int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, nullptr );
int symbolid = 0;
if ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
{
symbolid = sqlite3_column_int( ppStmt, 0 );
}
else
{
sqlite3_finalize( ppStmt );
return false;
}
sqlite3_finalize( ppStmt );
// remove all tags
query = type == SymbolEntity
? sqlite3_mprintf( "DELETE FROM tagmap WHERE symbol_id=%d", symbolid )
: sqlite3_mprintf( "DELETE FROM ctagmap WHERE colorramp_id=%d", symbolid );
runEmptyQuery( query );
// TODO Perform tag cleanup
// check the number of entries for a given tag in the tagmap
// if the count is 0, then remove( TagEntity, tagid )
return true;
}
QStringList QgsStyle::tagsOfSymbol( StyleEntity type, const QString& symbol ) QStringList QgsStyle::tagsOfSymbol( StyleEntity type, const QString& symbol )
{ {
if ( !mCurrentDB ) if ( !mCurrentDB )
@ -1018,7 +997,7 @@ QStringList QgsStyle::tagsOfSymbol( StyleEntity type, const QString& symbol )
int QgsStyle::getId( const QString& table, const QString& name ) int QgsStyle::getId( const QString& table, const QString& name )
{ {
char *query = sqlite3_mprintf( "SELECT id FROM %q WHERE name='%q'", table.toUtf8().constData(), name.toUtf8().constData() ); char *query = sqlite3_mprintf( "SELECT id FROM %q WHERE LOWER(name)='%q'", table.toUtf8().constData(), name.toUtf8().toLower().constData() );
sqlite3_stmt *ppStmt; sqlite3_stmt *ppStmt;
int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, nullptr ); int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, nullptr );
@ -1062,16 +1041,6 @@ int QgsStyle::colorrampId( const QString& name )
return getId( QStringLiteral( "colorramp" ), name ); return getId( QStringLiteral( "colorramp" ), name );
} }
int QgsStyle::groupId( const QString& name )
{
return getId( QStringLiteral( "symgroup" ), name );
}
QString QgsStyle::groupName( int groupId ) const
{
return getName( QStringLiteral( "symgroup" ), groupId );
}
int QgsStyle::tagId( const QString& name ) int QgsStyle::tagId( const QString& name )
{ {
return getId( QStringLiteral( "tag" ), name ); return getId( QStringLiteral( "tag" ), name );
@ -1113,6 +1082,10 @@ int QgsStyle::addSmartgroup( const QString& name, const QString& op, const QgsSm
if ( runEmptyQuery( query ) ) if ( runEmptyQuery( query ) )
{ {
QSettings settings;
settings.setValue( QStringLiteral( "qgis/symbolsListGroupsIndex" ), 0 );
emit groupsModified();
return static_cast< int >( sqlite3_last_insert_rowid( mCurrentDB ) ); return static_cast< int >( sqlite3_last_insert_rowid( mCurrentDB ) );
} }
else else
@ -1211,12 +1184,6 @@ QStringList QgsStyle::symbolsOfSmartgroup( StyleEntity type, int id )
{ {
resultNames = symbolsWithTag( type, tagId( param ) ); resultNames = symbolsWithTag( type, tagId( param ) );
} }
else if ( constraint == QLatin1String( "group" ) )
{
// XXX Validating group id might be a good idea here
resultNames = symbolsOfGroup( type, groupId( param ) );
}
else if ( constraint == QLatin1String( "name" ) ) else if ( constraint == QLatin1String( "name" ) )
{ {
if ( type == SymbolEntity ) if ( type == SymbolEntity )
@ -1237,15 +1204,6 @@ QStringList QgsStyle::symbolsOfSmartgroup( StyleEntity type, int id )
resultNames.removeAll( name ); resultNames.removeAll( name );
} }
} }
else if ( constraint == QLatin1String( "!group" ) )
{
resultNames = type == SymbolEntity ? symbolNames() : colorRampNames();
QStringList unwanted = symbolsOfGroup( type, groupId( param ) );
Q_FOREACH ( const QString& name, unwanted )
{
resultNames.removeAll( name );
}
}
else if ( constraint == QLatin1String( "!name" ) ) else if ( constraint == QLatin1String( "!name" ) )
{ {
QStringList all = type == SymbolEntity ? symbolNames() : colorRampNames(); QStringList all = type == SymbolEntity ? symbolNames() : colorRampNames();

View File

@ -41,8 +41,6 @@ typedef QMap<int, QString> QgsSymbolGroupMap;
* The supported constraints are: * The supported constraints are:
* tag -> symbol has the tag matching the parameter * tag -> symbol has the tag matching the parameter
* !tag -> symbol doesnot have the tag matching the parameter * !tag -> symbol doesnot have the tag matching the parameter
* group -> symbol belongs to group specified by the parameter
* !group -> symbol doesn't belong to the group specified by the parameter
* name -> symbol has a part of its name matching the parameter * name -> symbol has a part of its name matching the parameter
* !name -> symbol doesn't have any part of the name matching the parameter * !name -> symbol doesn't have any part of the name matching the parameter
* *
@ -56,11 +54,10 @@ typedef QMap<int, QString> QgsSymbolGroupMap;
typedef QMultiMap<QString, QString> QgsSmartConditionMap; typedef QMultiMap<QString, QString> QgsSmartConditionMap;
// enumerators representing sqlite DB columns // enumerators representing sqlite DB columns
enum SymbolTable { SymbolId, SymbolName, SymbolXML, SymbolGroupId }; enum SymbolTable { SymbolId, SymbolName, SymbolXML, SymbolFavoriteId };
enum SymgroupTable { SymgroupId, SymgroupName, SymgroupParent };
enum TagTable { TagId, TagName }; enum TagTable { TagId, TagName };
enum TagmapTable { TagmapTagId, TagmapSymbolId }; enum TagmapTable { TagmapTagId, TagmapSymbolId };
enum ColorrampTable { ColorrampId, ColorrampName, ColorrampXML, ColorrampGroupId }; enum ColorrampTable { ColorrampId, ColorrampName, ColorrampXML, ColorrampFavoriteId };
enum SmartgroupTable { SmartgroupId, SmartgroupName, SmartgroupXML }; enum SmartgroupTable { SmartgroupId, SmartgroupName, SmartgroupXML };
/** \ingroup core /** \ingroup core
@ -74,13 +71,23 @@ class CORE_EXPORT QgsStyle : public QObject
QgsStyle(); QgsStyle();
~QgsStyle(); ~QgsStyle();
//! Enum for Entities involved in a style /** Enum for Entities involved in a style
/*! *
The enumerator is used for identifying the entity being operated on when generic * The enumerator is used for identifying the entity being operated on when generic
database functions are being run. * database functions are being run.
\sa group(), rename(), remove(), symbolsOfGroup(), symbolsWithTag(), symbolsOfSmartgroup() * \sa rename(), remove(), symbolsOfFavorite(), symbolsWithTag(), symbolsOfSmartgroup()
*/ */
enum StyleEntity { SymbolEntity, GroupEntity, TagEntity, ColorrampEntity, SmartgroupEntity }; enum StyleEntity { SymbolEntity, TagEntity, ColorrampEntity, SmartgroupEntity };
/** Adds a symbol to style and takes symbol's ownership
*
* \note Adding a symbol with the name of existing one replaces it.
* \param name is the name of the symbol being added or updated
* \param symbol is the Vector symbol
* \param update set to true when the style DB has to be updated, by default it is false
* \return success status of the operation
*/
bool addSymbol( const QString& name, QgsSymbol* symbol, bool update = false );
/** Adds a color ramp to the style. Calling this method takes the ramp's ownership. /** Adds a color ramp to the style. Calling this method takes the ramp's ownership.
* \note Adding a color ramp with the name of existing one replaces it. * \note Adding a color ramp with the name of existing one replaces it.
@ -91,49 +98,29 @@ class CORE_EXPORT QgsStyle : public QObject
*/ */
bool addColorRamp( const QString& name, QgsColorRamp* colorRamp, bool update = false ); bool addColorRamp( const QString& name, QgsColorRamp* colorRamp, bool update = false );
//! adds a new group and returns the group's id /** Adds a new tag and returns the tag's id
/*! *
* \param groupName the name of the new group as QString * \param tagName the name of the new tag to be created
* \param parent is the id of the parent group when a subgrouo is to be created. By default it is 0 indicating it is not a sub-group * \return returns an int, which is the DB id of the new tag created, 0 if the tag couldn't be created
* \return returns an int, which is the DB id of the new group created, 0 if the group couldn't be created
*/ */
int addGroup( const QString& groupName, int parent = 0 ); int addTag( const QString& tagName );
//! adds new smartgroup to the database and returns the id /** Adds a new smartgroup to the database and returns the id
/*! *
* \param name is the name of the new Smart Group to be added * \param name is the name of the new Smart Group to be added
* \param op is the operator between the conditions; AND/OR as QString * \param op is the operator between the conditions; AND/OR as QString
* \param conditions are the smart group conditions * \param conditions are the smart group conditions
*/ */
int addSmartgroup( const QString& name, const QString& op, const QgsSmartConditionMap& conditions ); int addSmartgroup( const QString& name, const QString& op, const QgsSmartConditionMap& conditions );
//! add symbol to style. takes symbol's ownership
/*!
* \note Adding a symbol with the name of existing one replaces it.
* \param name is the name of the symbol being added or updated
* \param symbol is the Vector symbol
* \param update set to true when the style DB has to be updated, by default it is false
* \return success status of the operation
*/
bool addSymbol( const QString& name, QgsSymbol* symbol, bool update = false );
//! adds a new tag and returns the tag's id
/*!
* \param tagName the name of the new tag to be created
* \return returns an int, which is the DB id of the new tag created, 0 if the tag couldn't be created
*/
int addTag( const QString& tagName );
/** Returns a list of all tags in the style database /** Returns a list of all tags in the style database
*
* @note added in QGIS 2.16 * @note added in QGIS 2.16
* @see addTag() * @see addTag()
*/ */
QStringList tags() const; QStringList tags() const;
//! return a map of groupid and names for the given parent group //! Removes all contents of the style
QgsSymbolGroupMap childGroupNames( const QString& parent = "" );
//! remove all contents of the style
void clear(); void clear();
/** Returns a new copy of the specified color ramp. The caller /** Returns a new copy of the specified color ramp. The caller
@ -141,24 +128,25 @@ class CORE_EXPORT QgsStyle : public QObject
*/ */
QgsColorRamp* colorRamp( const QString& name ) const; QgsColorRamp* colorRamp( const QString& name ) const;
//! return count of color ramps //! Returns count of color ramps
int colorRampCount(); int colorRampCount();
//! return a list of names of color ramps //! Returns a list of names of color ramps
QStringList colorRampNames(); QStringList colorRampNames();
//! return a const pointer to a symbol (doesn't create new instance) //! Returns a const pointer to a symbol (doesn't create new instance)
const QgsColorRamp* colorRampRef( const QString& name ) const; const QgsColorRamp* colorRampRef( const QString& name ) const;
//! return the id in the style database for the given colorramp name /** Returns the id in the style database for the given colorramp name
//! returns 0 if not found * returns 0 if not found
*/
int colorrampId( const QString& name ); int colorrampId( const QString& name );
//! return default application-wide style //! Returns default application-wide style
static QgsStyle* defaultStyle(); static QgsStyle* defaultStyle();
//! tags the symbol with the tags in the list /** Tags the symbol with the tags in the list
/*! *
* Applies the given tags to the given symbol or colorramp * Applies the given tags to the given symbol or colorramp
* \param type is either SymbolEntity or ColorrampEntity * \param type is either SymbolEntity or ColorrampEntity
* \param symbol is the name of the symbol or colorramp as QString * \param symbol is the name of the symbol or colorramp as QString
@ -167,8 +155,8 @@ class CORE_EXPORT QgsStyle : public QObject
*/ */
bool tagSymbol( StyleEntity type, const QString& symbol, const QStringList& tags ); bool tagSymbol( StyleEntity type, const QString& symbol, const QStringList& tags );
//! detags the symbol with the given list /** Detags the symbol with the given list
/*! *
* Removes the given tags for the specified symbol or colorramp * Removes the given tags for the specified symbol or colorramp
* \param type is either SymbolEntity or ColorrampEntity * \param type is either SymbolEntity or ColorrampEntity
* \param symbol is the name of the symbol or colorramp * \param symbol is the name of the symbol or colorramp
@ -177,150 +165,157 @@ class CORE_EXPORT QgsStyle : public QObject
*/ */
bool detagSymbol( StyleEntity type, const QString& symbol, const QStringList& tags ); bool detagSymbol( StyleEntity type, const QString& symbol, const QStringList& tags );
//! remove symbol from style (and delete it) /** Clears the symbol from all attached tags
*
* Removes all tags for the specified symbol or colorramp
* \param type is either SymbolEntity or ColorrampEntity
* \param symbol is the name of the symbol or colorramp
* \return returns the success state of the operation
*/
bool detagSymbol( StyleEntity type, const QString& symbol );
//! Removes symbol from style (and delete it)
bool removeSymbol( const QString& name ); bool removeSymbol( const QString& name );
//! change symbol's name //! Changessymbol's name
bool renameSymbol( const QString& oldName, const QString& newName ); bool renameSymbol( const QString& oldName, const QString& newName );
//! return a NEW copy of symbol //! Returns a NEW copy of symbol
QgsSymbol* symbol( const QString& name ); QgsSymbol* symbol( const QString& name );
//! return a const pointer to a symbol (doesn't create new instance) //! Returns a const pointer to a symbol (doesn't create new instance)
const QgsSymbol* symbolRef( const QString& name ) const; const QgsSymbol* symbolRef( const QString& name ) const;
//! return count of symbols in style //! Returns count of symbols in style
int symbolCount(); int symbolCount();
//! return a list of names of symbols //! Returns a list of names of symbols
QStringList symbolNames(); QStringList symbolNames();
//! return the id in the style database for the given symbol name /** Returns the id in the style database for the given symbol name
//! returns 0 if not found * returns 0 if not found
*/
int symbolId( const QString& name ); int symbolId( const QString& name );
//! return the DB id for the given group name //! Returns the DB id for the given tag name
int groupId( const QString& group );
//! return the group name for the given DB id
QString groupName( int groupId ) const;
//! return the DB id for the given tag name
int tagId( const QString& tag ); int tagId( const QString& tag );
//! return the DB id for the given smartgroup name //! Returns the DB id for the given smartgroup name
int smartgroupId( const QString& smartgroup ); int smartgroupId( const QString& smartgroup );
//! return the all the groups in the style /** Returns the symbol names which are flagged as favorite
QStringList groupNames(); *
//! return the ids of all the groups in the style
QList<int> groupIds() const;
//! returns the symbolnames of a given groupid
/*!
* \param type is either SymbolEntity or ColorampEntity * \param type is either SymbolEntity or ColorampEntity
* \param groupid is id of the group to which the symbols belong to, as int * \return A QStringList of the symbol or colorramp names flagged as favorite
* \return A QStringList of the symbol or colorramp names for the given group id
*/ */
QStringList symbolsOfGroup( StyleEntity type, int groupid ); QStringList symbolsOfFavorite( StyleEntity type ) const;
//! returns the symbol names with which have the given tag /** Returns the symbol names with which have the given tag
/*! *
* \param type is either SymbolEntity or ColorampEntity * \param type is either SymbolEntity or ColorampEntity
* \param tagid is id of the tag which has been applied over the symbol as int * \param tagid is id of the tag which has been applied over the symbol as int
* \return A QStringList of the symbol or colorramp names for the given tag id * \return A QStringList of the symbol or colorramp names for the given tag id
*/ */
QStringList symbolsWithTag( StyleEntity type, int tagid ); QStringList symbolsWithTag( StyleEntity type, int tagid ) const;
//! applies the specified group to the symbol or colorramp specified by StyleEntity /** Adds the specified symbol to favorites
/*! *
* \param type is either SymbolEntity of ColorrampEntity * \param type is either SymbolEntity of ColorrampEntity
* \param name is the name of the symbol or coloramp whose group is to be set * \param name is the name of the symbol or coloramp whose is to be added to favorites
* \param groupid is the id of the group to which the entity is assigned
* \return returns the success state as bool * \return returns the success state as bool
*/ */
bool group( StyleEntity type, const QString& name, int groupid ); bool addFavorite( StyleEntity type, const QString& name );
//! rename the given entity with the specified id /** Removes the specified symbol from favorites
/*! *
* \param type is either SymbolEntity of ColorrampEntity
* \param name is the name of the symbol or coloramp whose is to be removed from favorites
* \return returns the success state as bool
*/
bool removeFavorite( StyleEntity type, const QString& name );
/** Renames the given entity with the specified id
*
* \param type is any of the style entites. Refer enum StyleEntity. * \param type is any of the style entites. Refer enum StyleEntity.
* \param id is the DB id of the entity which is to be renamed * \param id is the DB id of the entity which is to be renamed
* \param newName is the new name of the entity * \param newName is the new name of the entity
*/ */
void rename( StyleEntity type, int id, const QString& newName ); void rename( StyleEntity type, int id, const QString& newName );
//! remove the specified entity from the db /** Removes the specified entity from the db
/*! *
* \param type is any of the style entites. Refer enum StyleEntity. * \param type is any of the style entites. Refer enum StyleEntity.
* \param id is the DB id of the entity to be removed * \param id is the DB id of the entity to be removed
*/ */
void remove( StyleEntity type, int id ); void remove( StyleEntity type, int id );
//! add the symbol to the DB with the tags /** Adds the symbol to the DB with the tags
/*! *
* \param name is the name of the symbol as QString * \param name is the name of the symbol as QString
* \param symbol is the pointer to the new QgsSymbol being saved * \param symbol is the pointer to the new QgsSymbol being saved
* \param groupid is the id of the group to which the symbol belongs. Pass 0 if it doesn't belong to any group or not known. * \param favorite is a boolean value to specify whether the symbol should be added to favorites
* \param tags is a list of tags that are associated with the symbol as a QStringList. * \param tags is a list of tags that are associated with the symbol as a QStringList.
* \return returns the success state of the save operation * \return returns the success state of the save operation
*/ */
bool saveSymbol( const QString& name, QgsSymbol* symbol, int groupid, const QStringList& tags ); bool saveSymbol( const QString& name, QgsSymbol* symbol, bool favorite, const QStringList& tags );
//! add the colorramp to the DB /** Adds the colorramp to the DB
/*! *
* \param name is the name of the colorramp as QString * \param name is the name of the colorramp as QString
* \param ramp is the pointer to the new QgsColorRamp being saved * \param ramp is the pointer to the new QgsColorRamp being saved
* \param groupid is the id of the group to which the Color Ramp belongs. Pass 0 if it doesn't belong to any group or not known. * \param favorite is a boolean value to specify whether the colorramp should be added to favorites
* \param tags is a list of tags that are associated with the color ramp as a QStringList. * \param tags is a list of tags that are associated with the color ramp as a QStringList.
* \return returns the success state of the save operation * \return returns the success state of the save operation
*/ */
bool saveColorRamp( const QString& name, QgsColorRamp* ramp, int groupid, const QStringList& tags ); bool saveColorRamp( const QString& name, QgsColorRamp* ramp, bool favorite, const QStringList& tags );
//! remove color ramp from style (and delete it) //! Removes color ramp from style (and delete it)
bool removeColorRamp( const QString& name ); bool removeColorRamp( const QString& name );
//! change ramp's name //! Changes ramp's name
bool renameColorRamp( const QString& oldName, const QString& newName ); bool renameColorRamp( const QString& oldName, const QString& newName );
//! load a file into the style //! Loads a file into the style
bool load( const QString& filename ); bool load( const QString& filename );
//! save style into a file (will use current filename if empty string is passed) //! Saves style into a file (will use current filename if empty string is passed)
bool save( QString filename = QString() ); bool save( QString filename = QString() );
//! return last error from load/save operation //! Returns last error from load/save operation
QString errorString() { return mErrorString; } QString errorString() { return mErrorString; }
//! return current file name of the style //! Returns current file name of the style
QString fileName() { return mFileName; } QString fileName() { return mFileName; }
//! return the names of the symbols which have a matching 'substring' in its defintion /** Returns the names of the symbols which have a matching 'substring' in its defintion
/*! *
* \param type is either SymbolEntity or ColorrampEntity * \param type is either SymbolEntity or ColorrampEntity
* \param qword is the query string to search the symbols or colorramps. * \param qword is the query string to search the symbols or colorramps.
* \return A QStringList of the matched symbols or colorramps * \return A QStringList of the matched symbols or colorramps
* */ * */
QStringList findSymbols( StyleEntity type, const QString& qword ); QStringList findSymbols( StyleEntity type, const QString& qword );
//! return the tags associated with the symbol /** Returns the tags associated with the symbol
/*! *
* \param type is either SymbolEntity or ColorrampEntity * \param type is either SymbolEntity or ColorrampEntity
* \param symbol is the name of the symbol or color ramp * \param symbol is the name of the symbol or color ramp
* \return A QStringList of the tags that have been applied to that symbol/colorramp * \return A QStringList of the tags that have been applied to that symbol/colorramp
*/ */
QStringList tagsOfSymbol( StyleEntity type, const QString& symbol ); QStringList tagsOfSymbol( StyleEntity type, const QString& symbol );
//! returns the smart groups map with id as key and name as value //! Returns the smart groups map with id as key and name as value
QgsSymbolGroupMap smartgroupsListMap(); QgsSymbolGroupMap smartgroupsListMap();
//! returns the smart groups list //! Returns the smart groups list
QStringList smartgroupNames(); QStringList smartgroupNames();
//! returns the QgsSmartConditionMap for the given id //! Returns the QgsSmartConditionMap for the given id
QgsSmartConditionMap smartgroup( int id ); QgsSmartConditionMap smartgroup( int id );
//! returns the operator for the smartgroup /** Returns the operator for the smartgroup
//clumsy implementation TODO create a class for smartgroups * clumsy implementation TODO create a class for smartgroups
*/
QString smartgroupOperator( int id ); QString smartgroupOperator( int id );
//! returns the symbols for the smartgroup //! Returns the symbols for the smartgroup
QStringList symbolsOfSmartgroup( StyleEntity type, int id ); QStringList symbolsOfSmartgroup( StyleEntity type, int id );
//! Exports the style as a XML file //! Exports the style as a XML file
@ -330,7 +325,10 @@ class CORE_EXPORT QgsStyle : public QObject
bool importXml( const QString& filename ); bool importXml( const QString& filename );
signals: signals:
//! Is emitted every time a new symbol has been added to the database
void symbolSaved( const QString& name, QgsSymbol* symbol ); void symbolSaved( const QString& name, QgsSymbol* symbol );
//! Is emitted every time a tag or smartgroup has been added, removed, or renamed
void groupsModified();
protected: protected:
@ -344,26 +342,25 @@ class CORE_EXPORT QgsStyle : public QObject
static QgsStyle* mDefaultStyle; static QgsStyle* mDefaultStyle;
//! convenience function to open the DB and return a sqlite3 object //! Convenience function to open the DB and return a sqlite3 object
bool openDB( const QString& filename ); bool openDB( const QString& filename );
//! convenience function that would run queries which don't generate return values /** Convenience function that would run queries which don't generate return values
//! \param query query to run *
//! \param freeQuery release query memory * \param query query to run
//! \return success true on success * \param freeQuery release query memory
* \return success true on success
*/
bool runEmptyQuery( char* query, bool freeQuery = true ); bool runEmptyQuery( char* query, bool freeQuery = true );
//! prepares the complex query for removing a group, so that the children are not abandoned //! Gets the id from the table for the given name from the database, 0 if not found
char* getGroupRemoveQuery( int id );
//! gets the id from the table for the given name from the database, 0 if not found
int getId( const QString& table, const QString& name ); int getId( const QString& table, const QString& name );
//! gets the name from the table for the given id from the database, empty if not found //! Gets the name from the table for the given id from the database, empty if not found
QString getName( const QString& table, int id ) const; QString getName( const QString& table, int id ) const;
//! updates the properties of an existing symbol/colorramp /** Updates the properties of an existing symbol/colorramp
/*! *
* \note This should not be called separately, only called through addSymbol or addColorRamp * \note This should not be called separately, only called through addSymbol or addColorRamp
* \param type is either SymbolEntity or ColorrampEntity * \param type is either SymbolEntity or ColorrampEntity
* \param name is the name of an existing symbol or a color ramp * \param name is the name of an existing symbol or a color ramp

View File

@ -38,6 +38,7 @@ SET(QGIS_GUI_SRCS
symbology-ng/qgsstyleexportimportdialog.cpp symbology-ng/qgsstyleexportimportdialog.cpp
symbology-ng/qgsstylegroupselectiondialog.cpp symbology-ng/qgsstylegroupselectiondialog.cpp
symbology-ng/qgsstylemanagerdialog.cpp symbology-ng/qgsstylemanagerdialog.cpp
symbology-ng/qgsstylesavedialog.cpp
symbology-ng/qgssvgselectorwidget.cpp symbology-ng/qgssvgselectorwidget.cpp
symbology-ng/qgssymbollayerwidget.cpp symbology-ng/qgssymbollayerwidget.cpp
symbology-ng/qgssymbollevelsdialog.cpp symbology-ng/qgssymbollevelsdialog.cpp
@ -511,6 +512,7 @@ SET(QGIS_GUI_MOC_HDRS
symbology-ng/qgsstyleexportimportdialog.h symbology-ng/qgsstyleexportimportdialog.h
symbology-ng/qgsstylegroupselectiondialog.h symbology-ng/qgsstylegroupselectiondialog.h
symbology-ng/qgsstylemanagerdialog.h symbology-ng/qgsstylemanagerdialog.h
symbology-ng/qgsstylesavedialog.h
symbology-ng/qgssvgselectorwidget.h symbology-ng/qgssvgselectorwidget.h
symbology-ng/qgssymbollayerwidget.h symbology-ng/qgssymbollayerwidget.h
symbology-ng/qgssymbollevelsdialog.h symbology-ng/qgssymbollevelsdialog.h

View File

@ -31,10 +31,8 @@ QgsSmartGroupCondition::QgsSmartGroupCondition( int id, QWidget* parent ) : QWid
mConditionId = id; mConditionId = id;
mCondCombo->addItem( tr( "has the tag" ), QVariant( "tag" ) ); mCondCombo->addItem( tr( "has the tag" ), QVariant( "tag" ) );
mCondCombo->addItem( tr( "is a member of group" ), QVariant( "group" ) );
mCondCombo->addItem( tr( "has a part of name matching" ), QVariant( "name" ) ); mCondCombo->addItem( tr( "has a part of name matching" ), QVariant( "name" ) );
mCondCombo->addItem( tr( "does NOT have the tag" ), QVariant( "!tag" ) ); mCondCombo->addItem( tr( "does NOT have the tag" ), QVariant( "!tag" ) );
mCondCombo->addItem( tr( "is NOT a member of group" ), QVariant( "!group" ) );
mCondCombo->addItem( tr( "has NO part of name matching" ), QVariant( "!name" ) ); mCondCombo->addItem( tr( "has NO part of name matching" ), QVariant( "!name" ) );
mRemoveBtn->setIcon( QIcon( QgsApplication::iconPath( "symbologyRemove.svg" ) ) ); mRemoveBtn->setIcon( QIcon( QgsApplication::iconPath( "symbologyRemove.svg" ) ) );
@ -159,7 +157,7 @@ QString QgsSmartGroupEditorDialog::conditionOperator()
void QgsSmartGroupEditorDialog::setConditionMap( const QgsSmartConditionMap& map ) void QgsSmartGroupEditorDialog::setConditionMap( const QgsSmartConditionMap& map )
{ {
QStringList constraints; QStringList constraints;
constraints << QStringLiteral( "tag" ) << QStringLiteral( "group" ) << QStringLiteral( "name" ) << QStringLiteral( "!tag" ) << QStringLiteral( "!group" ) << QStringLiteral( "!name" ); constraints << QStringLiteral( "tag" ) << QStringLiteral( "name" ) << QStringLiteral( "!tag" ) << QStringLiteral( "!name" );
// clear any defaults // clear any defaults
Q_FOREACH ( int id, mConditionMap.keys() ) Q_FOREACH ( int id, mConditionMap.keys() )

View File

@ -35,7 +35,7 @@
QgsStyleExportImportDialog::QgsStyleExportImportDialog( QgsStyle* style, QWidget *parent, Mode mode ) QgsStyleExportImportDialog::QgsStyleExportImportDialog( QgsStyle* style, QWidget *parent, Mode mode )
: QDialog( parent ) : QDialog( parent )
, mDialogMode( mode ) , mDialogMode( mode )
, mQgisStyle( style ) , mStyle( style )
{ {
setupUi( this ); setupUi( this );
@ -73,12 +73,7 @@ QgsStyleExportImportDialog::QgsStyleExportImportDialog( QgsStyle* style, QWidget
importTypeCombo->addItem( tr( "URL specified below" ), QVariant( "url" ) ); importTypeCombo->addItem( tr( "URL specified below" ), QVariant( "url" ) );
connect( importTypeCombo, SIGNAL( currentIndexChanged( int ) ), this, SLOT( importTypeChanged( int ) ) ); connect( importTypeCombo, SIGNAL( currentIndexChanged( int ) ), this, SLOT( importTypeChanged( int ) ) );
QStringList groups = mQgisStyle->groupNames(); mSymbolTags->setText( "imported" );
groupCombo->addItem( QStringLiteral( "imported" ), QVariant( "new" ) );
Q_FOREACH ( const QString& gName, groups )
{
groupCombo->addItem( gName );
}
btnBrowse->setText( QStringLiteral( "Browse" ) ); btnBrowse->setText( QStringLiteral( "Browse" ) );
connect( btnBrowse, SIGNAL( clicked() ), this, SLOT( browse() ) ); connect( btnBrowse, SIGNAL( clicked() ), this, SLOT( browse() ) );
@ -96,14 +91,17 @@ QgsStyleExportImportDialog::QgsStyleExportImportDialog( QgsStyle* style, QWidget
locationLabel->setHidden( true ); locationLabel->setHidden( true );
locationLineEdit->setHidden( true ); locationLineEdit->setHidden( true );
mFavorite->setHidden( true );
pb = new QPushButton( tr( "Select by group" ) ); pb = new QPushButton( tr( "Select by group" ) );
buttonBox->addButton( pb, QDialogButtonBox::ActionRole ); buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
connect( pb, SIGNAL( clicked() ), this, SLOT( selectByGroup() ) ); connect( pb, SIGNAL( clicked() ), this, SLOT( selectByGroup() ) );
groupLabel->setHidden( true ); tagLabel->setHidden( true );
groupCombo->setHidden( true ); mSymbolTags->setHidden( true );
tagHintLabel->setHidden( true );
buttonBox->button( QDialogButtonBox::Ok )->setText( tr( "Export" ) ); buttonBox->button( QDialogButtonBox::Ok )->setText( tr( "Export" ) );
if ( !populateStyles( mQgisStyle ) ) if ( !populateStyles( mStyle ) )
{ {
QApplication::postEvent( this, new QCloseEvent() ); QApplication::postEvent( this, new QCloseEvent() );
} }
@ -142,7 +140,7 @@ void QgsStyleExportImportDialog::doExportImport()
mFileName = fileName; mFileName = fileName;
moveStyles( &selection, mQgisStyle, mTempStyle ); moveStyles( &selection, mStyle, mTempStyle );
if ( !mTempStyle->exportXml( mFileName ) ) if ( !mTempStyle->exportXml( mFileName ) )
{ {
QMessageBox::warning( this, tr( "Export/import error" ), QMessageBox::warning( this, tr( "Export/import error" ),
@ -153,7 +151,7 @@ void QgsStyleExportImportDialog::doExportImport()
} }
else // import else // import
{ {
moveStyles( &selection, mTempStyle, mQgisStyle ); moveStyles( &selection, mTempStyle, mStyle );
// clear model // clear model
QStandardItemModel* model = qobject_cast<QStandardItemModel*>( listItems->model() ); QStandardItemModel* model = qobject_cast<QStandardItemModel*>( listItems->model() );
@ -222,26 +220,13 @@ void QgsStyleExportImportDialog::moveStyles( QModelIndexList* selection, QgsStyl
bool isSymbol = true; bool isSymbol = true;
bool prompt = true; bool prompt = true;
bool overwrite = true; bool overwrite = true;
int groupid = 0; QStringList tags;
// get the groupid when going for import // get the groupid when going for import
if ( mDialogMode == Import ) if ( mDialogMode == Import )
{ {
// get the name the user entered // get the name the user entered
QString name = groupCombo->currentText(); tags = mSymbolTags->text().split( ',' );
if ( name.isEmpty() )
{
// import to "ungrouped"
groupid = 0;
}
else if ( dst->groupNames().contains( name ) )
{
groupid = dst->groupId( name );
}
else
{
groupid = dst->addGroup( name );
}
} }
for ( int i = 0; i < selection->size(); ++i ) for ( int i = 0; i < selection->size(); ++i )
@ -272,7 +257,7 @@ void QgsStyleExportImportDialog::moveStyles( QModelIndexList* selection, QgsStyl
case QMessageBox::Yes: case QMessageBox::Yes:
dst->addSymbol( symbolName, symbol ); dst->addSymbol( symbolName, symbol );
if ( mDialogMode == Import ) if ( mDialogMode == Import )
dst->saveSymbol( symbolName, symbol, groupid, QStringList() ); dst->saveSymbol( symbolName, symbol, mFavorite->isChecked(), tags );
continue; continue;
case QMessageBox::YesToAll: case QMessageBox::YesToAll:
prompt = false; prompt = false;
@ -289,7 +274,7 @@ void QgsStyleExportImportDialog::moveStyles( QModelIndexList* selection, QgsStyl
{ {
dst->addSymbol( symbolName, symbol ); dst->addSymbol( symbolName, symbol );
if ( mDialogMode == Import ) if ( mDialogMode == Import )
dst->saveSymbol( symbolName, symbol, groupid, QStringList() ); dst->saveSymbol( symbolName, symbol, mFavorite->isChecked(), tags );
} }
else if ( dst->symbolNames().contains( symbolName ) && !overwrite ) else if ( dst->symbolNames().contains( symbolName ) && !overwrite )
{ {
@ -299,7 +284,7 @@ void QgsStyleExportImportDialog::moveStyles( QModelIndexList* selection, QgsStyl
{ {
dst->addSymbol( symbolName, symbol ); dst->addSymbol( symbolName, symbol );
if ( mDialogMode == Import ) if ( mDialogMode == Import )
dst->saveSymbol( symbolName, symbol, groupid, QStringList() ); dst->saveSymbol( symbolName, symbol, mFavorite->isChecked(), tags );
} }
} }
else else
@ -319,7 +304,7 @@ void QgsStyleExportImportDialog::moveStyles( QModelIndexList* selection, QgsStyl
case QMessageBox::Yes: case QMessageBox::Yes:
dst->addColorRamp( symbolName, ramp ); dst->addColorRamp( symbolName, ramp );
if ( mDialogMode == Import ) if ( mDialogMode == Import )
dst->saveColorRamp( symbolName, ramp, groupid, QStringList() ); dst->saveColorRamp( symbolName, ramp, mFavorite->isChecked(), tags );
continue; continue;
case QMessageBox::YesToAll: case QMessageBox::YesToAll:
prompt = false; prompt = false;
@ -336,7 +321,7 @@ void QgsStyleExportImportDialog::moveStyles( QModelIndexList* selection, QgsStyl
{ {
dst->addColorRamp( symbolName, ramp ); dst->addColorRamp( symbolName, ramp );
if ( mDialogMode == Import ) if ( mDialogMode == Import )
dst->saveColorRamp( symbolName, ramp, groupid, QStringList() ); dst->saveColorRamp( symbolName, ramp, mFavorite->isChecked(), tags );
} }
else if ( dst->colorRampNames().contains( symbolName ) && !overwrite ) else if ( dst->colorRampNames().contains( symbolName ) && !overwrite )
{ {
@ -346,7 +331,7 @@ void QgsStyleExportImportDialog::moveStyles( QModelIndexList* selection, QgsStyl
{ {
dst->addColorRamp( symbolName, ramp ); dst->addColorRamp( symbolName, ramp );
if ( mDialogMode == Import ) if ( mDialogMode == Import )
dst->saveColorRamp( symbolName, ramp, groupid, QStringList() ); dst->saveColorRamp( symbolName, ramp, mFavorite->isChecked() , tags );
} }
} }
} }
@ -394,36 +379,31 @@ void QgsStyleExportImportDialog::deselectSymbols( const QStringList& symbolNames
} }
} }
void QgsStyleExportImportDialog::selectGroup( const QString& groupName ) void QgsStyleExportImportDialog::selectTag( const QString& tagName )
{ {
QStringList symbolNames = mQgisStyle->symbolsOfGroup( QgsStyle::SymbolEntity, mQgisStyle->groupId( groupName ) ); QStringList symbolNames = mStyle->symbolsWithTag( QgsStyle::SymbolEntity, mStyle->tagId( tagName ) );
selectSymbols( symbolNames );
symbolNames = mQgisStyle->symbolsOfGroup( QgsStyle::ColorrampEntity, mQgisStyle->groupId( groupName ) );
selectSymbols( symbolNames ); selectSymbols( symbolNames );
} }
void QgsStyleExportImportDialog::deselectTag( const QString& tagName )
void QgsStyleExportImportDialog::deselectGroup( const QString& groupName )
{ {
QStringList symbolNames = mQgisStyle->symbolsOfGroup( QgsStyle::SymbolEntity, mQgisStyle->groupId( groupName ) ); QStringList symbolNames = mStyle->symbolsWithTag( QgsStyle::SymbolEntity, mStyle->tagId( tagName ) );
deselectSymbols( symbolNames );
symbolNames = mQgisStyle->symbolsOfGroup( QgsStyle::ColorrampEntity, mQgisStyle->groupId( groupName ) );
deselectSymbols( symbolNames ); deselectSymbols( symbolNames );
} }
void QgsStyleExportImportDialog::selectSmartgroup( const QString& groupName ) void QgsStyleExportImportDialog::selectSmartgroup( const QString& groupName )
{ {
QStringList symbolNames = mQgisStyle->symbolsOfSmartgroup( QgsStyle::SymbolEntity, mQgisStyle->smartgroupId( groupName ) ); QStringList symbolNames = mStyle->symbolsOfSmartgroup( QgsStyle::SymbolEntity, mStyle->smartgroupId( groupName ) );
selectSymbols( symbolNames ); selectSymbols( symbolNames );
symbolNames = mQgisStyle->symbolsOfSmartgroup( QgsStyle::ColorrampEntity, mQgisStyle->smartgroupId( groupName ) ); symbolNames = mStyle->symbolsOfSmartgroup( QgsStyle::ColorrampEntity, mStyle->smartgroupId( groupName ) );
selectSymbols( symbolNames ); selectSymbols( symbolNames );
} }
void QgsStyleExportImportDialog::deselectSmartgroup( const QString& groupName ) void QgsStyleExportImportDialog::deselectSmartgroup( const QString& groupName )
{ {
QStringList symbolNames = mQgisStyle->symbolsOfSmartgroup( QgsStyle::SymbolEntity, mQgisStyle->smartgroupId( groupName ) ); QStringList symbolNames = mStyle->symbolsOfSmartgroup( QgsStyle::SymbolEntity, mStyle->smartgroupId( groupName ) );
deselectSymbols( symbolNames ); deselectSymbols( symbolNames );
symbolNames = mQgisStyle->symbolsOfSmartgroup( QgsStyle::ColorrampEntity, mQgisStyle->smartgroupId( groupName ) ); symbolNames = mStyle->symbolsOfSmartgroup( QgsStyle::ColorrampEntity, mStyle->smartgroupId( groupName ) );
deselectSymbols( symbolNames ); deselectSymbols( symbolNames );
} }
@ -431,10 +411,10 @@ void QgsStyleExportImportDialog::selectByGroup()
{ {
if ( ! mGroupSelectionDlg ) if ( ! mGroupSelectionDlg )
{ {
mGroupSelectionDlg = new QgsStyleGroupSelectionDialog( mQgisStyle, this ); mGroupSelectionDlg = new QgsStyleGroupSelectionDialog( mStyle, this );
mGroupSelectionDlg->setWindowTitle( tr( "Select symbols by group" ) ); mGroupSelectionDlg->setWindowTitle( tr( "Select symbols by group" ) );
connect( mGroupSelectionDlg, SIGNAL( groupSelected( const QString ) ), this, SLOT( selectGroup( const QString ) ) ); connect( mGroupSelectionDlg, SIGNAL( tagSelected( const QString ) ), this, SLOT( selectTag( const QString ) ) );
connect( mGroupSelectionDlg, SIGNAL( groupDeselected( const QString ) ), this, SLOT( deselectGroup( const QString ) ) ); connect( mGroupSelectionDlg, SIGNAL( tagDeselected( const QString ) ), this, SLOT( deselectTag( const QString ) ) );
connect( mGroupSelectionDlg, SIGNAL( allSelected() ), this, SLOT( selectAll() ) ); connect( mGroupSelectionDlg, SIGNAL( allSelected() ), this, SLOT( selectAll() ) );
connect( mGroupSelectionDlg, SIGNAL( allDeselected() ), this, SLOT( clearSelection() ) ); connect( mGroupSelectionDlg, SIGNAL( allDeselected() ), this, SLOT( clearSelection() ) );
connect( mGroupSelectionDlg, SIGNAL( smartgroupSelected( const QString ) ), this, SLOT( selectSmartgroup( const QString ) ) ); connect( mGroupSelectionDlg, SIGNAL( smartgroupSelected( const QString ) ), this, SLOT( selectSmartgroup( const QString ) ) );
@ -481,8 +461,8 @@ void QgsStyleExportImportDialog::browse()
return; return;
} }
QFileInfo pathInfo( mFileName ); QFileInfo pathInfo( mFileName );
QString groupName = pathInfo.fileName().remove( QStringLiteral( ".xml" ) ); QString tag = pathInfo.fileName().remove( QStringLiteral( ".xml" ) );
groupCombo->setItemText( 0, groupName ); mSymbolTags->setText( tag );
locationLineEdit->setText( mFileName ); locationLineEdit->setText( mFileName );
populateStyles( mTempStyle ); populateStyles( mTempStyle );
} }

View File

@ -80,16 +80,16 @@ class GUI_EXPORT QgsStyleExportImportDialog : public QDialog, private Ui::QgsSty
void clearSelection(); void clearSelection();
/** /**
* Select the symbols belonging to the given group * Select the symbols belonging to the given tag
* @param groupName the name of the group to be selected * @param tagName the name of the group to be selected
*/ */
void selectGroup( const QString& groupName ); void selectTag( const QString& tagName );
/** /**
* Deselect the symbols belonging to the given group * Deselect the symbols belonging to the given tag
* @param groupName the name of the group to be deselected * @param tagName the name of the group to be deselected
*/ */
void deselectGroup( const QString& groupName ); void deselectTag( const QString& tagName );
/** /**
* @brief selectSmartgroup selects all symbols from a smart group * @brief selectSmartgroup selects all symbols from a smart group
@ -127,7 +127,7 @@ class GUI_EXPORT QgsStyleExportImportDialog : public QDialog, private Ui::QgsSty
QString mFileName; QString mFileName;
Mode mDialogMode; Mode mDialogMode;
QgsStyle* mQgisStyle; QgsStyle* mStyle;
QgsStyle* mTempStyle; QgsStyle* mTempStyle;
}; };

View File

@ -37,24 +37,19 @@ QgsStyleGroupSelectionDialog::QgsStyleGroupSelectionDialog( QgsStyle *style, QWi
setBold( allSymbols ); setBold( allSymbols );
model->appendRow( allSymbols ); model->appendRow( allSymbols );
QStandardItem *group = new QStandardItem( QLatin1String( "" ) ); //require empty name to get first order groups QStandardItem *tags = new QStandardItem( QLatin1String( "" ) ); //require empty name to get first order groups
group->setData( "groupsheader", Qt::UserRole + 2 ); tags->setData( "tagsheader", Qt::UserRole + 2 );
group->setEditable( false ); tags->setEditable( false );
group->setFlags( group->flags() & ~Qt::ItemIsSelectable ); tags->setFlags( tags->flags() & ~Qt::ItemIsSelectable );
buildGroupTree( group ); buildTagTree( tags );
group->setText( tr( "Groups" ) );//set title later tags->setText( tr( "Tags" ) );//set title later
QStandardItem *ungrouped = new QStandardItem( tr( "Ungrouped" ) ); setBold( tags );
ungrouped->setData( 0 ); model->appendRow( tags );
ungrouped->setData( "group", Qt::UserRole + 2 );
setBold( ungrouped );
setBold( group );
group->appendRow( ungrouped );
model->appendRow( group );
QStandardItem *tag = new QStandardItem( tr( "Smart Groups" ) ); QStandardItem *tag = new QStandardItem( tr( "Smart Groups" ) );
tag->setData( "smartgroupsheader" , Qt::UserRole + 2 ); tag->setData( "smartgroupsheader" , Qt::UserRole + 2 );
tag->setEditable( false ); tag->setEditable( false );
tag->setFlags( group->flags() & ~Qt::ItemIsSelectable ); tag->setFlags( tag->flags() & ~Qt::ItemIsSelectable );
setBold( tag ); setBold( tag );
QgsSymbolGroupMap sgMap = mStyle->smartgroupsListMap(); QgsSymbolGroupMap sgMap = mStyle->smartgroupsListMap();
QgsSymbolGroupMap::const_iterator i = sgMap.constBegin(); QgsSymbolGroupMap::const_iterator i = sgMap.constBegin();
@ -100,7 +95,7 @@ void QgsStyleGroupSelectionDialog::groupTreeSelectionChanged( const QItemSelecti
Q_FOREACH ( index, deselectedItems ) Q_FOREACH ( index, deselectedItems )
{ {
if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "groupsheader" ) ) if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "tagssheader" ) )
{ {
// Ignore: it's the group header // Ignore: it's the group header
} }
@ -116,14 +111,14 @@ void QgsStyleGroupSelectionDialog::groupTreeSelectionChanged( const QItemSelecti
{ {
emit smartgroupDeselected( index.data().toString() ); emit smartgroupDeselected( index.data().toString() );
} }
else if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "group" ) ) else if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "tag" ) )
{ // It's a group { // It's a tag
emit groupDeselected( index.data().toString() ); emit tagDeselected( index.data().toString() );
} }
} }
Q_FOREACH ( index, selectedItems ) Q_FOREACH ( index, selectedItems )
{ {
if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "groupsheader" ) ) if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "tagssheader" ) )
{ {
// Ignore: it's the group header // Ignore: it's the group header
} }
@ -139,27 +134,25 @@ void QgsStyleGroupSelectionDialog::groupTreeSelectionChanged( const QItemSelecti
{ {
emit smartgroupSelected( index.data().toString() ); emit smartgroupSelected( index.data().toString() );
} }
else if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "group" ) ) else if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "tag" ) )
{ // It's a group { // It's a tag
emit groupSelected( index.data().toString() ); emit tagSelected( index.data().toString() );
} }
} }
} }
void QgsStyleGroupSelectionDialog::buildGroupTree( QStandardItem* &parent ) void QgsStyleGroupSelectionDialog::buildTagTree( QStandardItem* &parent )
{ {
QgsSymbolGroupMap groups = mStyle->childGroupNames( parent->text() ); QStringList tags = mStyle->tags();
QgsSymbolGroupMap::const_iterator i = groups.constBegin(); tags.sort();
while ( i != groups.constEnd() ) Q_FOREACH ( const QString& tag, tags )
{ {
QStandardItem *item = new QStandardItem( i.value() ); QStandardItem *item = new QStandardItem( tag );
item->setData( i.key() ); item->setData( mStyle->tagId( tag ) );
item->setData( "group" , Qt::UserRole + 2 ); item->setData( "tag" , Qt::UserRole + 2 );
item->setEditable( false ); item->setEditable( false );
parent->appendRow( item ); parent->appendRow( item );
buildGroupTree( item );
++i;
} }
} }

View File

@ -38,10 +38,10 @@ class GUI_EXPORT QgsStyleGroupSelectionDialog : public QDialog, private Ui::Symb
void setBold( QStandardItem *item ); void setBold( QStandardItem *item );
signals: signals:
//! group with groupName has been selected //! tag with tagName has been selected
void groupSelected( const QString& groupName ); void tagSelected( const QString& tagName );
//! group with groupName has been deselected //! tag with tagName has been deselected
void groupDeselected( const QString& groupName ); void tagDeselected( const QString& tagName );
//! smartgroup with groupName has been selected //! smartgroup with groupName has been selected
void smartgroupSelected( const QString& groupName ); void smartgroupSelected( const QString& groupName );
//! smart group with groupName has been deselected //! smart group with groupName has been deselected
@ -60,7 +60,7 @@ class GUI_EXPORT QgsStyleGroupSelectionDialog : public QDialog, private Ui::Symb
* @brief build group tree * @brief build group tree
* @param parent * @param parent
*/ */
void buildGroupTree( QStandardItem *&parent ); void buildTagTree( QStandardItem *&parent );
QgsStyle* mStyle; QgsStyle* mStyle;
}; };

View File

@ -14,6 +14,7 @@
***************************************************************************/ ***************************************************************************/
#include "qgsstylemanagerdialog.h" #include "qgsstylemanagerdialog.h"
#include "qgsstylesavedialog.h"
#include "qgsstyle.h" #include "qgsstyle.h"
#include "qgssymbol.h" #include "qgssymbol.h"
@ -111,16 +112,15 @@ QgsStyleManagerDialog::QgsStyleManagerDialog( QgsStyle* style, QWidget* parent )
this, SLOT( groupRenamed( QStandardItem* ) ) ); this, SLOT( groupRenamed( QStandardItem* ) ) );
QMenu *groupMenu = new QMenu( tr( "Group actions" ), this ); QMenu *groupMenu = new QMenu( tr( "Group actions" ), this );
connect( actnGroupSymbols, SIGNAL( triggered() ), this, SLOT( groupSymbolsAction() ) ); connect( actnTagSymbols, SIGNAL( triggered() ), this, SLOT( tagSymbolsAction() ) );
groupMenu->addAction( actnGroupSymbols ); groupMenu->addAction( actnTagSymbols );
connect( actnFinishGrouping, SIGNAL( triggered() ), this, SLOT( groupSymbolsAction() ) ); connect( actnFinishTagging, SIGNAL( triggered() ), this, SLOT( tagSymbolsAction() ) );
actnFinishGrouping->setVisible( false ); actnFinishTagging->setVisible( false );
groupMenu->addAction( actnFinishGrouping ); groupMenu->addAction( actnFinishTagging );
groupMenu->addAction( actnEditSmartGroup ); groupMenu->addAction( actnEditSmartGroup );
btnManageGroups->setMenu( groupMenu ); btnManageGroups->setMenu( groupMenu );
connect( searchBox, SIGNAL( textChanged( QString ) ), this, SLOT( filterSymbols( QString ) ) ); connect( searchBox, SIGNAL( textChanged( QString ) ), this, SLOT( filterSymbols( QString ) ) );
tagsLineEdit->installEventFilter( this );
// Context menu for groupTree // Context menu for groupTree
groupTree->setContextMenuPolicy( Qt::CustomContextMenu ); groupTree->setContextMenuPolicy( Qt::CustomContextMenu );
@ -144,13 +144,18 @@ QgsStyleManagerDialog::QgsStyleManagerDialog( QgsStyle* style, QWidget* parent )
// Context menu for symbols/colorramps. The menu entries for every group are created when displaying the menu. // Context menu for symbols/colorramps. The menu entries for every group are created when displaying the menu.
mGroupMenu = new QMenu( this ); mGroupMenu = new QMenu( this );
connect( actnAddFavorite, SIGNAL( triggered( bool ) ), this, SLOT( addFavoriteSelectedSymbols() ) );
mGroupMenu->addAction( actnAddFavorite );
connect( actnRemoveFavorite, SIGNAL( triggered( bool ) ), this, SLOT( removeFavoriteSelectedSymbols() ) );
mGroupMenu->addAction( actnRemoveFavorite );
mGroupMenu->addSeparator()->setParent( this );
mGroupListMenu = new QMenu( mGroupMenu ); mGroupListMenu = new QMenu( mGroupMenu );
mGroupListMenu->setTitle( tr( "Add to group" ) ); mGroupListMenu->setTitle( tr( "Add to tag" ) );
mGroupListMenu->setEnabled( false ); mGroupListMenu->setEnabled( false );
mGroupMenu->addMenu( mGroupListMenu ); mGroupMenu->addMenu( mGroupListMenu );
actnUngroup->setData( 0 ); actnDetag->setData( 0 );
connect( actnUngroup, SIGNAL( triggered( bool ) ), this, SLOT( groupSelectedSymbols() ) ); connect( actnDetag, SIGNAL( triggered( bool ) ), this, SLOT( detagSelectedSymbols() ) );
mGroupMenu->addAction( actnUngroup ); mGroupMenu->addAction( actnDetag );
mGroupMenu->addSeparator()->setParent( this ); mGroupMenu->addSeparator()->setParent( this );
mGroupMenu->addAction( actnRemoveItem ); mGroupMenu->addAction( actnRemoveItem );
mGroupMenu->addAction( actnEditItem ); mGroupMenu->addAction( actnEditItem );
@ -391,20 +396,19 @@ bool QgsStyleManagerDialog::addSymbol()
return false; return false;
} }
// get unique name QgsStyleSaveDialog saveDlg( this );
bool nameInvalid = true; if ( !saveDlg.exec() )
{
delete symbol;
return false;
}
name = saveDlg.name();
// request valid/unique name
bool nameInvalid = true;
while ( nameInvalid ) while ( nameInvalid )
{ {
bool ok;
name = QInputDialog::getText( this, tr( "Symbol Name" ),
tr( "Please enter a name for new symbol:" ),
QLineEdit::Normal, name, &ok );
if ( !ok )
{
delete symbol;
return false;
}
// validate name // validate name
if ( name.isEmpty() ) if ( name.isEmpty() )
{ {
@ -419,6 +423,7 @@ bool QgsStyleManagerDialog::addSymbol()
QMessageBox::Yes | QMessageBox::No ); QMessageBox::Yes | QMessageBox::No );
if ( res == QMessageBox::Yes ) if ( res == QMessageBox::Yes )
{ {
mStyle->removeSymbol( name );
nameInvalid = false; nameInvalid = false;
} }
} }
@ -427,11 +432,26 @@ bool QgsStyleManagerDialog::addSymbol()
// valid name // valid name
nameInvalid = false; nameInvalid = false;
} }
if ( nameInvalid )
{
bool ok;
name = QInputDialog::getText( this, tr( "Symbol Name" ),
tr( "Please enter a name for new symbol:" ),
QLineEdit::Normal, name, &ok );
if ( !ok )
{
delete symbol;
return false;
}
}
} }
QStringList symbolTags = saveDlg.tags().split( ',' );
// add new symbol to style and re-populate the list // add new symbol to style and re-populate the list
mStyle->addSymbol( name, symbol, true ); mStyle->addSymbol( name, symbol );
// TODO groups and tags mStyle->saveSymbol( name, symbol, saveDlg.isFavorite(), symbolTags );
mModified = true; mModified = true;
return true; return true;
} }
@ -521,19 +541,18 @@ QString QgsStyleManagerDialog::addColorRampStatic( QWidget* parent, QgsStyle* st
return QString(); return QString();
} }
// get unique name QgsStyleSaveDialog saveDlg( parent, QgsStyle::ColorrampEntity );
bool nameInvalid = true; if ( !saveDlg.exec() )
{
return QString();
}
name = saveDlg.name();
// get valid/unique name
bool nameInvalid = true;
while ( nameInvalid ) while ( nameInvalid )
{ {
bool ok;
name = QInputDialog::getText( parent, tr( "Color Ramp Name" ),
tr( "Please enter a name for new color ramp:" ),
QLineEdit::Normal, name, &ok );
if ( !ok )
{
return QString();
}
// validate name // validate name
if ( name.isEmpty() ) if ( name.isEmpty() )
{ {
@ -556,11 +575,26 @@ QString QgsStyleManagerDialog::addColorRampStatic( QWidget* parent, QgsStyle* st
// valid name // valid name
nameInvalid = false; nameInvalid = false;
} }
if ( nameInvalid )
{
bool ok;
name = QInputDialog::getText( parent, tr( "Color Ramp Name" ),
tr( "Please enter a name for new color ramp:" ),
QLineEdit::Normal, name, &ok );
if ( !ok )
{
return QString();
}
}
} }
QStringList colorRampTags = saveDlg.tags().split( ',' );
QgsColorRamp* r = ramp.take();
// add new symbol to style and re-populate the list // add new symbol to style and re-populate the list
style->addColorRamp( name, ramp.take(), true ); style->addColorRamp( name, r );
// TODO groups and tags, using saveColorRamp style->saveColorRamp( name, r, saveDlg.isFavorite(), colorRampTags );
return name; return name;
} }
@ -854,40 +888,49 @@ void QgsStyleManagerDialog::populateGroups()
QStandardItemModel *model = qobject_cast<QStandardItemModel*>( groupTree->model() ); QStandardItemModel *model = qobject_cast<QStandardItemModel*>( groupTree->model() );
model->clear(); model->clear();
QStandardItem *favoriteSymbols = new QStandardItem( tr( "Favorites" ) );
favoriteSymbols->setData( "favorite" );
favoriteSymbols->setEditable( false );
setBold( favoriteSymbols );
model->appendRow( favoriteSymbols );
QStandardItem *allSymbols = new QStandardItem( tr( "All Symbols" ) ); QStandardItem *allSymbols = new QStandardItem( tr( "All Symbols" ) );
allSymbols->setData( "all" ); allSymbols->setData( "all" );
allSymbols->setEditable( false ); allSymbols->setEditable( false );
setBold( allSymbols ); setBold( allSymbols );
model->appendRow( allSymbols ); model->appendRow( allSymbols );
QStandardItem *group = new QStandardItem( QLatin1String( "" ) ); //require empty name to get first order groups QStandardItem *taggroup = new QStandardItem( QLatin1String( "" ) ); //require empty name to get first order groups
group->setData( "groups" ); taggroup->setData( "tags" );
group->setEditable( false ); taggroup->setEditable( false );
buildGroupTree( group ); QStringList tags = mStyle->tags();
group->setText( tr( "Groups" ) );//set title later tags.sort();
QStandardItem *ungrouped = new QStandardItem( tr( "Ungrouped" ) ); Q_FOREACH ( const QString& tag, tags )
ungrouped->setData( 0 ); {
setBold( ungrouped ); QStandardItem *item = new QStandardItem( tag );
setBold( group ); item->setData( mStyle->tagId( tag ) );
group->appendRow( ungrouped ); taggroup->appendRow( item );
model->appendRow( group ); }
taggroup->setText( tr( "Tags" ) );//set title later
setBold( taggroup );
model->appendRow( taggroup );
QStandardItem *tag = new QStandardItem( tr( "Smart Groups" ) ); QStandardItem *smart = new QStandardItem( tr( "Smart Groups" ) );
tag->setData( "smartgroups" ); smart->setData( "smartgroups" );
tag->setEditable( false ); smart->setEditable( false );
setBold( tag ); setBold( smart );
QgsSymbolGroupMap sgMap = mStyle->smartgroupsListMap(); QgsSymbolGroupMap sgMap = mStyle->smartgroupsListMap();
QgsSymbolGroupMap::const_iterator i = sgMap.constBegin(); QgsSymbolGroupMap::const_iterator i = sgMap.constBegin();
while ( i != sgMap.constEnd() ) while ( i != sgMap.constEnd() )
{ {
QStandardItem *item = new QStandardItem( i.value() ); QStandardItem *item = new QStandardItem( i.value() );
item->setData( i.key() ); item->setData( i.key() );
tag->appendRow( item ); smart->appendRow( item );
++i; ++i;
} }
model->appendRow( tag ); model->appendRow( smart );
// expand things in the grouo tree // expand things in the group tree
int rows = model->rowCount( model->indexFromItem( model->invisibleRootItem() ) ); int rows = model->rowCount( model->indexFromItem( model->invisibleRootItem() ) );
for ( int i = 0; i < rows; i++ ) for ( int i = 0; i < rows; i++ )
{ {
@ -895,20 +938,6 @@ void QgsStyleManagerDialog::populateGroups()
} }
} }
void QgsStyleManagerDialog::buildGroupTree( QStandardItem* &parent )
{
QgsSymbolGroupMap groups = mStyle->childGroupNames( parent->text() );
QgsSymbolGroupMap::const_iterator i = groups.constBegin();
while ( i != groups.constEnd() )
{
QStandardItem *item = new QStandardItem( i.value() );
item->setData( i.key() );
parent->appendRow( item );
buildGroupTree( item );
++i;
}
}
void QgsStyleManagerDialog::groupChanged( const QModelIndex& index ) void QgsStyleManagerDialog::groupChanged( const QModelIndex& index )
{ {
QStringList symbolNames; QStringList symbolNames;
@ -922,42 +951,41 @@ void QgsStyleManagerDialog::groupChanged( const QModelIndex& index )
} }
QString category = index.data( Qt::UserRole + 1 ).toString(); QString category = index.data( Qt::UserRole + 1 ).toString();
if ( category == QLatin1String( "all" ) || category == QLatin1String( "groups" ) || category == QLatin1String( "smartgroups" ) ) if ( category == QLatin1String( "all" ) || category == QLatin1String( "tags" ) || category == QLatin1String( "smartgroups" ) )
{ {
enableGroupInputs( false ); enableGroupInputs( false );
if ( category == QLatin1String( "groups" ) || category == QLatin1String( "smartgroups" ) ) if ( category == QLatin1String( "tags" ) || category == QLatin1String( "smartgroups" ) )
{ {
btnAddGroup->setEnabled( true ); btnAddGroup->setEnabled( true );
actnAddGroup->setEnabled( true ); actnAddGroup->setEnabled( true );
} }
symbolNames = currentItemType() < 3 ? mStyle->symbolNames() : mStyle->colorRampNames(); symbolNames = currentItemType() < 3 ? mStyle->symbolNames() : mStyle->colorRampNames();
} }
else else if ( category == QLatin1String( "favorite" ) )
{ {
//determine groups and tags btnAddGroup->setEnabled( true );
if ( index.parent().data( Qt::UserRole + 1 ) == "smartgroups" ) actnAddGroup->setEnabled( true );
enableGroupInputs( false );
symbolNames = mStyle->symbolsOfFavorite( type );
}
else if ( index.parent().data( Qt::UserRole + 1 ) == "smartgroups" )
{
btnRemoveGroup->setEnabled( true );
actnRemoveGroup->setEnabled( true );
btnManageGroups->setEnabled( true );
int groupId = index.data( Qt::UserRole + 1 ).toInt();
symbolNames = mStyle->symbolsOfSmartgroup( type, groupId );
}
else // tags
{
enableGroupInputs( true );
int tagId = index.data( Qt::UserRole + 1 ).toInt();
symbolNames = mStyle->symbolsWithTag( type, tagId );
if ( mGrouppingMode && tagId )
{ {
btnAddGroup->setEnabled( false ); groupSymbols = symbolNames;
actnAddGroup->setEnabled( false ); symbolNames = type == QgsStyle::SymbolEntity ? mStyle->symbolNames() : mStyle->colorRampNames();
btnRemoveGroup->setEnabled( true );
actnRemoveGroup->setEnabled( true );
btnManageGroups->setEnabled( true );
int groupId = index.data( Qt::UserRole + 1 ).toInt();
symbolNames = mStyle->symbolsOfSmartgroup( type, groupId );
}
else // then it must be a group
{
if (( !index.data( Qt::UserRole + 1 ).toInt() && ( index.data() == "Ungrouped" ) ) || mGrouppingMode )
enableGroupInputs( false );
else
enableGroupInputs( true );
int groupId = index.data( Qt::UserRole + 1 ).toInt();
symbolNames = mStyle->symbolsOfGroup( type, groupId );
if ( mGrouppingMode && groupId )
{
groupSymbols = symbolNames;
symbolNames += mStyle->symbolsOfGroup( type, 0 );
}
} }
} }
@ -969,16 +997,19 @@ void QgsStyleManagerDialog::groupChanged( const QModelIndex& index )
{ {
populateColorRamps( symbolNames, mGrouppingMode ); populateColorRamps( symbolNames, mGrouppingMode );
} }
if ( mGrouppingMode ) if ( mGrouppingMode )
{
setSymbolsChecked( groupSymbols ); setSymbolsChecked( groupSymbols );
}
actnEditSmartGroup->setVisible( false ); actnEditSmartGroup->setVisible( false );
actnAddGroup->setVisible( false ); actnAddGroup->setVisible( false );
actnRemoveGroup->setVisible( false ); actnRemoveGroup->setVisible( false );
actnGroupSymbols->setVisible( false ); actnTagSymbols->setVisible( false );
actnFinishGrouping->setVisible( false ); actnFinishTagging->setVisible( false );
if ( index.parent().isValid() && ( index.data().toString() != QLatin1String( "Ungrouped" ) ) ) if ( index.parent().isValid() )
{ {
if ( index.parent().data( Qt::UserRole + 1 ).toString() == QLatin1String( "smartgroups" ) ) if ( index.parent().data( Qt::UserRole + 1 ).toString() == QLatin1String( "smartgroups" ) )
{ {
@ -987,12 +1018,12 @@ void QgsStyleManagerDialog::groupChanged( const QModelIndex& index )
else else
{ {
actnAddGroup->setVisible( !mGrouppingMode ); actnAddGroup->setVisible( !mGrouppingMode );
actnGroupSymbols->setVisible( !mGrouppingMode ); actnTagSymbols->setVisible( !mGrouppingMode );
actnFinishGrouping->setVisible( mGrouppingMode ); actnFinishTagging->setVisible( mGrouppingMode );
} }
actnRemoveGroup->setVisible( true ); actnRemoveGroup->setVisible( true );
} }
else if ( index.data( Qt::UserRole + 1 ) == "groups" || index.data( Qt::UserRole + 1 ) == "smartgroups" ) else if ( index.data( Qt::UserRole + 1 ) == "tags" || index.data( Qt::UserRole + 1 ) == "smartgroups" )
{ {
actnAddGroup->setVisible( !mGrouppingMode ); actnAddGroup->setVisible( !mGrouppingMode );
} }
@ -1001,11 +1032,11 @@ void QgsStyleManagerDialog::groupChanged( const QModelIndex& index )
void QgsStyleManagerDialog::addGroup() void QgsStyleManagerDialog::addGroup()
{ {
QStandardItemModel *model = qobject_cast<QStandardItemModel*>( groupTree->model() ); QStandardItemModel *model = qobject_cast<QStandardItemModel*>( groupTree->model() );
QModelIndex parentIndex = groupTree->currentIndex(); QModelIndex index = groupTree->currentIndex();
// Violation 1: Creating sub-groups of system defined groups // don't allow creation of tag/smartgroup against system-defined groupings
QString parentData = parentIndex.data( Qt::UserRole + 1 ).toString(); QString data = index.data( Qt::UserRole + 1 ).toString();
if ( parentData == QLatin1String( "all" ) || ( parentIndex.data() == "Ungrouped" && parentData == QLatin1String( "0" ) ) ) if ( data == QLatin1String( "all" ) || data == "favorite" )
{ {
int err = QMessageBox::critical( this, tr( "Invalid Selection" ), int err = QMessageBox::critical( this, tr( "Invalid Selection" ),
tr( "The parent group you have selected is not user editable.\n" tr( "The parent group you have selected is not user editable.\n"
@ -1014,24 +1045,19 @@ void QgsStyleManagerDialog::addGroup()
return; return;
} }
// Violation 2: Creating a nested tag QString itemName;
if ( parentIndex.parent().data( Qt::UserRole + 1 ).toString() == QLatin1String( "smartgroups" ) ) int id;
//
if ( index.parent() != QModelIndex() )
{ {
int err = QMessageBox::critical( this, tr( "Operation Not Allowed" ), index = index.parent();
tr( "Creation of nested smart groups are not allowed\n" data = index.data( Qt::UserRole + 1 ).toString();
"Select the 'Smart Group' to create a new group." ) );
if ( err )
return;
} }
QString itemName; if ( data == QLatin1String( "smartgroups" ) )
bool isGroup = true;
int id;
if ( parentData == QLatin1String( "smartgroups" ) )
{ {
// create a smart group // create a smartgroup
QgsSmartGroupEditorDialog dlg( mStyle, this ); QgsSmartGroupEditorDialog dlg( mStyle, this );
if ( dlg.exec() == QDialog::Rejected ) if ( dlg.exec() == QDialog::Rejected )
return; return;
@ -1039,34 +1065,39 @@ void QgsStyleManagerDialog::addGroup()
if ( !id ) if ( !id )
return; return;
itemName = dlg.smartgroupName(); itemName = dlg.smartgroupName();
isGroup = false;
} }
else else
{ {
// create a simple child-group to the selected // create a tag
bool ok;
itemName = QInputDialog::getText( this, tr( "Tag name" ),
tr( "Please enter name for the new tag:" ), QLineEdit::Normal, tr( "New tag" ), &ok ).trimmed();
if ( !ok || itemName.isEmpty() )
return;
itemName = QString( tr( "New Group" ) ); int check = mStyle->tagId( itemName );
int parentid = ( parentData == QLatin1String( "groups" ) ) ? 0 : parentData.toInt(); // parentid is 0 for top-level groups if ( check > 0 )
id = mStyle->addGroup( itemName, parentid ); {
QMessageBox::critical( this, tr( "Error!" ),
tr( "Tag name already exists in your symbol database." ) );
return;
}
id = mStyle->addTag( itemName );
if ( !id ) if ( !id )
{ {
QMessageBox::critical( this, tr( "Error!" ), QMessageBox::critical( this, tr( "Error!" ),
tr( "New group could not be created.\n" tr( "New tag could not be created.\n"
"There was a problem with your symbol database." ) ); "There was a problem with your symbol database." ) );
return; return;
} }
} }
QStandardItem *parentItem = model->itemFromIndex( parentIndex ); QStandardItem *parentItem = model->itemFromIndex( index );
QStandardItem *childItem = new QStandardItem( itemName ); QStandardItem *childItem = new QStandardItem( itemName );
childItem->setData( id ); childItem->setData( id );
parentItem->appendRow( childItem ); parentItem->appendRow( childItem );
groupTree->setCurrentIndex( childItem->index() ); groupTree->setCurrentIndex( childItem->index() );
if ( isGroup )
{
groupTree->edit( childItem->index() );
}
} }
void QgsStyleManagerDialog::removeGroup() void QgsStyleManagerDialog::removeGroup()
@ -1074,9 +1105,9 @@ void QgsStyleManagerDialog::removeGroup()
QStandardItemModel *model = qobject_cast<QStandardItemModel*>( groupTree->model() ); QStandardItemModel *model = qobject_cast<QStandardItemModel*>( groupTree->model() );
QModelIndex index = groupTree->currentIndex(); QModelIndex index = groupTree->currentIndex();
// Violation: removing system groups // do not allow removal of system-defined groupings
QString data = index.data( Qt::UserRole + 1 ).toString(); QString data = index.data( Qt::UserRole + 1 ).toString();
if ( data == QLatin1String( "all" ) || data == QLatin1String( "groups" ) || data == QLatin1String( "smartgroups" ) || index.data() == "Ungrouped" ) if ( data == QLatin1String( "all" ) || data == QLatin1String( "favorite" ) || data == QLatin1String( "tags" ) || index.data() == "smartgroups" )
{ {
int err = QMessageBox::critical( this, tr( "Invalid selection" ), int err = QMessageBox::critical( this, tr( "Invalid selection" ),
tr( "Cannot delete system defined categories.\n" tr( "Cannot delete system defined categories.\n"
@ -1092,16 +1123,7 @@ void QgsStyleManagerDialog::removeGroup()
} }
else else
{ {
mStyle->remove( QgsStyle::GroupEntity, index.data( Qt::UserRole + 1 ).toInt() ); mStyle->remove( QgsStyle::TagEntity, index.data( Qt::UserRole + 1 ).toInt() );
QStandardItem *item = model->itemFromIndex( index );
if ( item->hasChildren() )
{
QStandardItem *parent = item->parent();
for ( int i = 0; i < item->rowCount(); i++ )
{
parent->appendRow( item->takeChild( i ) );
}
}
} }
parentItem->removeRow( index.row() ); parentItem->removeRow( index.row() );
} }
@ -1117,11 +1139,11 @@ void QgsStyleManagerDialog::groupRenamed( QStandardItem * item )
} }
else else
{ {
mStyle->rename( QgsStyle::GroupEntity, id, name ); mStyle->rename( QgsStyle::TagEntity, id, name );
} }
} }
void QgsStyleManagerDialog::groupSymbolsAction() void QgsStyleManagerDialog::tagSymbolsAction()
{ {
QStandardItemModel *treeModel = qobject_cast<QStandardItemModel*>( groupTree->model() ); QStandardItemModel *treeModel = qobject_cast<QStandardItemModel*>( groupTree->model() );
@ -1130,8 +1152,8 @@ void QgsStyleManagerDialog::groupSymbolsAction()
if ( mGrouppingMode ) if ( mGrouppingMode )
{ {
mGrouppingMode = false; mGrouppingMode = false;
actnGroupSymbols->setVisible( true ); actnTagSymbols->setVisible( true );
actnFinishGrouping->setVisible( false ); actnFinishTagging->setVisible( false );
// disconnect slot which handles regrouping // disconnect slot which handles regrouping
disconnect( model, SIGNAL( itemChanged( QStandardItem* ) ), disconnect( model, SIGNAL( itemChanged( QStandardItem* ) ),
this, SLOT( regrouped( QStandardItem* ) ) ); this, SLOT( regrouped( QStandardItem* ) ) );
@ -1155,21 +1177,20 @@ void QgsStyleManagerDialog::groupSymbolsAction()
QModelIndex present = groupTree->currentIndex(); QModelIndex present = groupTree->currentIndex();
while ( present.parent().isValid() ) while ( present.parent().isValid() )
{ {
if ( present.parent().data() == "Groups" ) if ( present.parent().data() == "Tags" )
{ {
validGroup = true; validGroup = true;
break; break;
} }
else present = present.parent();
present = present.parent();
} }
if ( !validGroup ) if ( !validGroup )
return; return;
mGrouppingMode = true; mGrouppingMode = true;
// Change visibility of actions // Change visibility of actions
actnGroupSymbols->setVisible( false ); actnTagSymbols->setVisible( false );
actnFinishGrouping->setVisible( true ); actnFinishTagging->setVisible( true );
// Remove all Symbol editing functionalities // Remove all Symbol editing functionalities
disconnect( treeModel, SIGNAL( itemChanged( QStandardItem* ) ), disconnect( treeModel, SIGNAL( itemChanged( QStandardItem* ) ),
this, SLOT( groupRenamed( QStandardItem* ) ) ); this, SLOT( groupRenamed( QStandardItem* ) ) );
@ -1199,20 +1220,23 @@ void QgsStyleManagerDialog::regrouped( QStandardItem *item )
QgsDebugMsg( "Unknown style entity" ); QgsDebugMsg( "Unknown style entity" );
return; return;
} }
int groupid = groupTree->currentIndex().data( Qt::UserRole + 1 ).toInt();
QStandardItemModel *treeModel = qobject_cast<QStandardItemModel*>( groupTree->model() );
QString tag = treeModel->itemFromIndex( groupTree->currentIndex() )->text();
QString symbolName = item->text(); QString symbolName = item->text();
bool regrouped; bool regrouped;
if ( item->checkState() == Qt::Checked ) if ( item->checkState() == Qt::Checked )
regrouped = mStyle->group( type, symbolName, groupid ); regrouped = mStyle->tagSymbol( type, symbolName, QStringList( tag ) );
else else
regrouped = mStyle->group( type, symbolName, 0 ); regrouped = mStyle->detagSymbol( type, symbolName, QStringList( tag ) );
if ( !regrouped ) if ( !regrouped )
{ {
int er = QMessageBox::critical( this, tr( "Database Error" ), int er = QMessageBox::critical( this, tr( "Database Error" ),
tr( "There was a problem with the Symbols database while regrouping." ) ); tr( "There was a problem with the Symbols database while regrouping." ) );
// call the slot again to get back to normal // call the slot again to get back to normal
if ( er ) if ( er )
groupSymbolsAction(); tagSymbolsAction();
} }
} }
@ -1242,69 +1266,8 @@ void QgsStyleManagerDialog::filterSymbols( const QString& qword )
} }
} }
void QgsStyleManagerDialog::tagsChanged()
{
QModelIndexList indexes = listItems->selectionModel()->selection().indexes();
QStringList addtags;
QStringList removetags;
QStringList oldtags = mTagList;
QStringList newtags = tagsLineEdit->text().split( ',', QString::SkipEmptyParts );
QgsStyle::StyleEntity type;
if ( currentItemType() < 3 )
{
type = QgsStyle::SymbolEntity;
}
else if ( currentItemType() == 3 )
{
type = QgsStyle::ColorrampEntity;
}
else
{
QgsDebugMsg( "Unknown Style Entity!" );
return;
}
// compare old with new to find removed tags
Q_FOREACH ( const QString &tag, oldtags )
{
if ( !newtags.contains( tag ) )
removetags.append( tag );
}
if ( !removetags.isEmpty() )
{
Q_FOREACH ( const QModelIndex& index, indexes )
{
mStyle->detagSymbol( type, index.data().toString(), removetags );
}
}
// compare new with old to find added tags
Q_FOREACH ( const QString &tag, newtags )
{
if ( !oldtags.contains( tag ) )
addtags.append( tag );
}
if ( !addtags.isEmpty() )
{
Q_FOREACH ( const QModelIndex& index, indexes )
{
mStyle->tagSymbol( type, index.data().toString(), addtags );
}
}
}
void QgsStyleManagerDialog::symbolSelected( const QModelIndex& index ) void QgsStyleManagerDialog::symbolSelected( const QModelIndex& index )
{ {
// Populate the tags for the symbol
tagsLineEdit->clear();
if ( index.isValid() )
{
QStandardItem *item = static_cast<QStandardItemModel*>( listItems->model() )->itemFromIndex( index );
QgsStyle::StyleEntity type = ( currentItemType() < 3 ) ? QgsStyle::SymbolEntity : QgsStyle::ColorrampEntity;
mTagList = mStyle->tagsOfSymbol( type, item->data().toString() );
tagsLineEdit->setText( mTagList.join( QStringLiteral( "," ) ) );
}
actnEditItem->setEnabled( index.isValid() && !mGrouppingMode ); actnEditItem->setEnabled( index.isValid() && !mGrouppingMode );
} }
@ -1314,8 +1277,10 @@ void QgsStyleManagerDialog::selectedSymbolsChanged( const QItemSelection& select
Q_UNUSED( deselected ); Q_UNUSED( deselected );
bool nothingSelected = listItems->selectionModel()->selectedIndexes().empty(); bool nothingSelected = listItems->selectionModel()->selectedIndexes().empty();
actnRemoveItem->setDisabled( nothingSelected ); actnRemoveItem->setDisabled( nothingSelected );
actnAddFavorite->setDisabled( nothingSelected );
actnRemoveFavorite->setDisabled( nothingSelected );
mGroupListMenu->setDisabled( nothingSelected ); mGroupListMenu->setDisabled( nothingSelected );
actnUngroup->setDisabled( nothingSelected ); actnDetag->setDisabled( nothingSelected );
actnExportAsPNG->setDisabled( nothingSelected ); actnExportAsPNG->setDisabled( nothingSelected );
actnExportAsSVG->setDisabled( nothingSelected ); actnExportAsSVG->setDisabled( nothingSelected );
actnEditItem->setDisabled( nothingSelected ); actnEditItem->setDisabled( nothingSelected );
@ -1330,7 +1295,6 @@ void QgsStyleManagerDialog::enableSymbolInputs( bool enable )
actnRemoveGroup->setEnabled( enable ); actnRemoveGroup->setEnabled( enable );
btnManageGroups->setEnabled( enable || mGrouppingMode ); // always enabled in grouping mode, as it is the only way to leave grouping mode btnManageGroups->setEnabled( enable || mGrouppingMode ); // always enabled in grouping mode, as it is the only way to leave grouping mode
searchBox->setEnabled( enable ); searchBox->setEnabled( enable );
tagsLineEdit->setEnabled( enable );
} }
void QgsStyleManagerDialog::enableGroupInputs( bool enable ) void QgsStyleManagerDialog::enableGroupInputs( bool enable )
@ -1346,19 +1310,8 @@ void QgsStyleManagerDialog::enableItemsForGroupingMode( bool enable )
QStandardItemModel *treeModel = qobject_cast<QStandardItemModel*>( groupTree->model() ); QStandardItemModel *treeModel = qobject_cast<QStandardItemModel*>( groupTree->model() );
for ( int i = 0; i < treeModel->rowCount(); i++ ) for ( int i = 0; i < treeModel->rowCount(); i++ )
{ {
if ( treeModel->item( i )->data() != "groups" ) treeModel->item( i )->setEnabled( enable );
{
treeModel->item( i )->setEnabled( enable );
}
if ( treeModel->item( i )->data() == "groups" )
{
treeModel->item( i )->setEnabled( enable );
for ( int k = 0; k < treeModel->item( i )->rowCount(); k++ )
{
if ( !treeModel->item( i )->child( k )->data().toInt() )
treeModel->item( i )->child( k )->setEnabled( enable );
}
}
if ( treeModel->item( i )->data() == "smartgroups" ) if ( treeModel->item( i )->data() == "smartgroups" )
{ {
for ( int j = 0; j < treeModel->item( i )->rowCount(); j++ ) for ( int j = 0; j < treeModel->item( i )->rowCount(); j++ )
@ -1401,19 +1354,54 @@ void QgsStyleManagerDialog::listitemsContextMenu( QPoint point )
mGroupListMenu->clear(); mGroupListMenu->clear();
QAction* a; QAction* a;
QList<int> groupIds = mStyle->groupIds(); QStringList tags = mStyle->tags();
Q_FOREACH ( int groupId, groupIds ) tags.sort();
Q_FOREACH ( const QString& tag, tags )
{ {
a = new QAction( mStyle->groupName( groupId ), mGroupListMenu ); a = new QAction( tag, mGroupListMenu );
a->setData( groupId ); a->setData( tag );
connect( a, SIGNAL( triggered( bool ) ), this, SLOT( groupSelectedSymbols() ) ); connect( a, SIGNAL( triggered( bool ) ), this, SLOT( tagSelectedSymbols() ) );
mGroupListMenu->addAction( a ); mGroupListMenu->addAction( a );
} }
mGroupMenu->popup( globalPos ); mGroupMenu->popup( globalPos );
} }
void QgsStyleManagerDialog::groupSelectedSymbols() void QgsStyleManagerDialog::addFavoriteSelectedSymbols()
{
QgsStyle::StyleEntity type = ( currentItemType() < 3 ) ? QgsStyle::SymbolEntity : QgsStyle::ColorrampEntity;
if ( currentItemType() > 3 )
{
QgsDebugMsg( "unknown entity type" );
return;
}
QModelIndexList indexes = listItems->selectionModel()->selectedIndexes();
Q_FOREACH ( const QModelIndex& index, indexes )
{
mStyle->addFavorite( type, index.data().toString() );
}
populateList();
}
void QgsStyleManagerDialog::removeFavoriteSelectedSymbols()
{
QgsStyle::StyleEntity type = ( currentItemType() < 3 ) ? QgsStyle::SymbolEntity : QgsStyle::ColorrampEntity;
if ( currentItemType() > 3 )
{
QgsDebugMsg( "unknown entity type" );
return;
}
QModelIndexList indexes = listItems->selectionModel()->selectedIndexes();
Q_FOREACH ( const QModelIndex& index, indexes )
{
mStyle->removeFavorite( type, index.data().toString() );
}
populateList();
}
void QgsStyleManagerDialog::tagSelectedSymbols()
{ {
QAction* selectedItem = qobject_cast<QAction*>( sender() ); QAction* selectedItem = qobject_cast<QAction*>( sender() );
@ -1425,11 +1413,34 @@ void QgsStyleManagerDialog::groupSelectedSymbols()
QgsDebugMsg( "unknown entity type" ); QgsDebugMsg( "unknown entity type" );
return; return;
} }
int groupId = selectedItem->data().toInt(); QString tag = selectedItem->data().toString();
QModelIndexList indexes = listItems->selectionModel()->selectedIndexes(); QModelIndexList indexes = listItems->selectionModel()->selectedIndexes();
Q_FOREACH ( const QModelIndex& index, indexes ) Q_FOREACH ( const QModelIndex& index, indexes )
{ {
mStyle->group( type, index.data().toString(), groupId ); mStyle->tagSymbol( type, index.data().toString(), QStringList( tag ) );
}
populateList();
QgsDebugMsg( "Selected Action: " + selectedItem->text() );
}
}
void QgsStyleManagerDialog::detagSelectedSymbols()
{
QAction* selectedItem = qobject_cast<QAction*>( sender() );
if ( selectedItem )
{
QgsStyle::StyleEntity type = ( currentItemType() < 3 ) ? QgsStyle::SymbolEntity : QgsStyle::ColorrampEntity;
if ( currentItemType() > 3 )
{
QgsDebugMsg( "unknown entity type" );
return;
}
QModelIndexList indexes = listItems->selectionModel()->selectedIndexes();
Q_FOREACH ( const QModelIndex& index, indexes )
{
mStyle->detagSymbol( type, index.data().toString() );
} }
populateList(); populateList();
@ -1474,14 +1485,4 @@ void QgsStyleManagerDialog::editSmartgroupAction()
groupChanged( present ); groupChanged( present );
} }
bool QgsStyleManagerDialog::eventFilter( QObject *obj, QEvent *event )
{
if (( obj == tagsLineEdit ) && ( event->type() == QEvent::FocusOut ) )
{
tagsChanged();
return true;
}
return false;
}

View File

@ -66,8 +66,8 @@ class GUI_EXPORT QgsStyleManagerDialog : public QDialog, private Ui::QgsStyleMan
void addGroup(); void addGroup();
void removeGroup(); void removeGroup();
//! carryout symbol grouping using check boxes //! carry out symbol tagging using check boxes
void groupSymbolsAction(); void tagSymbolsAction();
//! edit the selected smart group //! edit the selected smart group
void editSmartgroupAction(); void editSmartgroupAction();
@ -78,9 +78,6 @@ class GUI_EXPORT QgsStyleManagerDialog : public QDialog, private Ui::QgsStyleMan
//! filter the symbols based on input search term //! filter the symbols based on input search term
void filterSymbols( const QString& ); void filterSymbols( const QString& );
//! Listen to tag changes
void tagsChanged();
//! Perform symbol specific tasks when selected //! Perform symbol specific tasks when selected
void symbolSelected( const QModelIndex& ); void symbolSelected( const QModelIndex& );
@ -95,7 +92,14 @@ class GUI_EXPORT QgsStyleManagerDialog : public QDialog, private Ui::QgsStyleMan
protected slots: protected slots:
bool addColorRamp( QAction* action ); bool addColorRamp( QAction* action );
void groupSelectedSymbols(); //! Add selected symbols to favorites
void addFavoriteSelectedSymbols();
//! Remove selected symbols from favorites
void removeFavoriteSelectedSymbols();
//! Tag selected symbols using menu item selection
void tagSelectedSymbols();
//! Remove all tags from selected symbols
void detagSelectedSymbols();
protected: protected:
@ -104,8 +108,6 @@ class GUI_EXPORT QgsStyleManagerDialog : public QDialog, private Ui::QgsStyleMan
//! populate the groups //! populate the groups
void populateGroups(); void populateGroups();
//! build the groups tree
void buildGroupTree( QStandardItem* &parent );
//! to set symbols checked when in editing mode //! to set symbols checked when in editing mode
void setSymbolsChecked( const QStringList& ); void setSymbolsChecked( const QStringList& );
@ -136,9 +138,6 @@ class GUI_EXPORT QgsStyleManagerDialog : public QDialog, private Ui::QgsStyleMan
//! Enables or diables the groupTree items for grouping mode //! Enables or diables the groupTree items for grouping mode
void enableItemsForGroupingMode( bool ); void enableItemsForGroupingMode( bool );
//! Event filter to capture tagsLineEdit out of focus
bool eventFilter( QObject*, QEvent* ) override;
//! sets the text of the item with bold font //! sets the text of the item with bold font
void setBold( QStandardItem* ); void setBold( QStandardItem* );

View File

@ -0,0 +1,56 @@
/***************************************************************************
qgssymbolsavedialog.cpp
---------------------------------------
begin : November 2016
copyright : (C) 2016 by Mathieu Pellerin
email : nirvn dot asia at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsstylesavedialog.h"
#include "qgis.h"
#include "qgsstyle.h"
#include <QLineEdit>
#include <QCheckBox>
QgsStyleSaveDialog::QgsStyleSaveDialog( QWidget* parent, QgsStyle::StyleEntity type )
: QDialog( parent )
{
setupUi( this );
if ( type == QgsStyle::SymbolEntity )
{
this->setWindowTitle( tr( "Save new symbol" ) );
}
else if ( type == QgsStyle::ColorrampEntity )
{
this->setWindowTitle( tr( "Save new color ramp" ) );
}
}
QgsStyleSaveDialog::~QgsStyleSaveDialog() { }
QString QgsStyleSaveDialog::name() const
{
return mName->text();
}
QString QgsStyleSaveDialog::tags() const
{
return mTags->text();
}
bool QgsStyleSaveDialog::isFavorite() const
{
return mFavorite->isChecked();
}

View File

@ -0,0 +1,57 @@
/***************************************************************************
qgssymbolsavedialog.h
-------------------------------------
begin : November 2016
copyright : (C) 2016 by Mathieu Pellerin
email : nirvn dot asia at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSSTYLESAVEDIALOG_H
#define QGSSTYLESAVEDIALOG_H
#include <QDialog>
#include "ui_qgsstylesavedialog.h"
#include "qgsstyle.h"
/** \ingroup gui
* \brief a dialog for setting properties of a newly saved style.
* \note added in QGIS 3.0
*/
class GUI_EXPORT QgsStyleSaveDialog: public QDialog, private Ui::QgsStyleSaveDialog
{
Q_OBJECT
public:
/** Constructor for QgsSymbolSaveDialog
* @param parent parent widget
* @param type the QgsStyle entity type being saved
*/
QgsStyleSaveDialog( QWidget* parent = nullptr, QgsStyle::StyleEntity type = QgsStyle::SymbolEntity );
~QgsStyleSaveDialog();
//! returns the text value of the name element
QString name() const;
//! returns the text value of the tags element
QString tags() const;
//! returns whether the favorite element is checked
bool isFavorite() const;
};
#endif // QGSSTYLESAVEDIALOG_H

View File

@ -19,6 +19,7 @@
#include "qgssizescalewidget.h" #include "qgssizescalewidget.h"
#include "qgsstylemanagerdialog.h" #include "qgsstylemanagerdialog.h"
#include "qgsstylesavedialog.h"
#include "qgsdatadefined.h" #include "qgsdatadefined.h"
#include "qgssymbol.h" #include "qgssymbol.h"
@ -29,6 +30,8 @@
#include "qgsapplication.h" #include "qgsapplication.h"
#include "qgsvectorlayer.h" #include "qgsvectorlayer.h"
#include <QAction>
#include <QSettings>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <QPainter> #include <QPainter>
@ -38,6 +41,7 @@
#include <QInputDialog> #include <QInputDialog>
#include <QMessageBox> #include <QMessageBox>
#include <QMenu> #include <QMenu>
#include <QPushButton>
#include <QScopedPointer> #include <QScopedPointer>
@ -67,26 +71,20 @@ QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbol* symbol, QgsStyle* style,
} }
mClipFeaturesAction = new QAction( tr( "Clip features to canvas extent" ), this ); mClipFeaturesAction = new QAction( tr( "Clip features to canvas extent" ), this );
mClipFeaturesAction->setCheckable( true ); mClipFeaturesAction->setCheckable( true );
connect( mClipFeaturesAction, SIGNAL( toggled( bool ) ), this, SLOT( clipFeaturesToggled( bool ) ) ); connect( mClipFeaturesAction, &QAction::toggled, this, &QgsSymbolsListWidget::clipFeaturesToggled );
// populate the groups
groupsCombo->addItem( QLatin1String( "" ) );
populateGroups();
QStringList groups = style->smartgroupNames();
Q_FOREACH ( const QString& group, groups )
{
groupsCombo->addItem( group, QVariant( "smart" ) );
}
QStandardItemModel* model = new QStandardItemModel( viewSymbols ); QStandardItemModel* model = new QStandardItemModel( viewSymbols );
viewSymbols->setModel( model ); viewSymbols->setModel( model );
connect( viewSymbols->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), this, SLOT( setSymbolFromStyle( const QModelIndex & ) ) ); connect( viewSymbols->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), this, SLOT( setSymbolFromStyle( const QModelIndex & ) ) );
connect( mStyle, SIGNAL( symbolSaved( QString, QgsSymbol* ) ), this, SLOT( symbolAddedToStyle( QString, QgsSymbol* ) ) ); connect( mStyle, &QgsStyle::symbolSaved , this, &QgsSymbolsListWidget::symbolAddedToStyle );
connect( openStyleManagerButton, SIGNAL( pressed() ), this, SLOT( openStyleManager() ) ); connect( mStyle, &QgsStyle::groupsModified , this, &QgsSymbolsListWidget::populateGroups );
connect( openStyleManagerButton, &QPushButton::pressed, this, &QgsSymbolsListWidget::openStyleManager );
lblSymbolName->setText( QLatin1String( "" ) ); lblSymbolName->setText( QLatin1String( "" ) );
populateSymbolView();
populateGroups();
if ( mSymbol ) if ( mSymbol )
{ {
@ -119,7 +117,7 @@ QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbol* symbol, QgsStyle* style,
btnColor->setColorDialogTitle( tr( "Select color" ) ); btnColor->setColorDialogTitle( tr( "Select color" ) );
btnColor->setContext( QStringLiteral( "symbology" ) ); btnColor->setContext( QStringLiteral( "symbology" ) );
connect( btnSaveSymbol, SIGNAL( clicked() ), this, SLOT( saveSymbol() ) ); connect( btnSaveSymbol, &QPushButton::clicked, this, &QgsSymbolsListWidget::saveSymbol );
} }
QgsSymbolsListWidget::~QgsSymbolsListWidget() QgsSymbolsListWidget::~QgsSymbolsListWidget()
@ -148,30 +146,72 @@ QgsSymbolWidgetContext QgsSymbolsListWidget::context() const
return mContext; return mContext;
} }
void QgsSymbolsListWidget::populateGroups( const QString& parent, const QString& prepend ) void QgsSymbolsListWidget::populateGroups()
{ {
QgsSymbolGroupMap groups = mStyle->childGroupNames( parent ); groupsCombo->blockSignals( true );
QgsSymbolGroupMap::const_iterator i = groups.constBegin(); groupsCombo->clear();
while ( i != groups.constEnd() )
groupsCombo->addItem( tr( "Favorites" ), QVariant( "favorite" ) );
groupsCombo->addItem( tr( "All Symbols" ), QVariant( "all" ) );
int index = 2;
QStringList tags = mStyle->tags();
if ( tags.count() > 0 )
{ {
QString text; tags.sort();
if ( !prepend.isEmpty() ) groupsCombo->insertSeparator( index );
Q_FOREACH ( const QString& tag, tags )
{ {
text = prepend + '/' + i.value(); groupsCombo->addItem( tag, QVariant( "tag" ) );
index++;
} }
else
{
text = i.value();
}
groupsCombo->addItem( text, QVariant( i.key() ) );
populateGroups( i.value(), text );
++i;
} }
QStringList groups = mStyle->smartgroupNames();
if ( groups.count() > 0 )
{
groups.sort();
groupsCombo->insertSeparator( index + 1 );
Q_FOREACH ( const QString& group, groups )
{
groupsCombo->addItem( group, QVariant( "smartgroup" ) );
}
}
groupsCombo->blockSignals( false );
QSettings settings;
index = settings.value( "qgis/symbolsListGroupsIndex", 0 ).toInt();
groupsCombo->setCurrentIndex( index );
populateSymbolView();
} }
void QgsSymbolsListWidget::populateSymbolView() void QgsSymbolsListWidget::populateSymbolView()
{ {
populateSymbols( mStyle->symbolNames() ); QStringList symbols;
QString text = groupsCombo->currentText();
int id;
if ( groupsCombo->currentData().toString() == QLatin1String( "favorite" ) )
{
symbols = mStyle->symbolsOfFavorite( QgsStyle::SymbolEntity );
}
else if ( groupsCombo->currentData().toString() == QLatin1String( "all" ) )
{
symbols = mStyle->symbolNames();
}
else if ( groupsCombo->currentData().toString() == QLatin1String( "smartgroup" ) )
{
id = mStyle->smartgroupId( text );
symbols = mStyle->symbolsOfSmartgroup( QgsStyle::SymbolEntity, id );
}
else
{
id = mStyle->tagId( text );
symbols = mStyle->symbolsWithTag( QgsStyle::SymbolEntity, id );
}
populateSymbols( symbols );
} }
void QgsSymbolsListWidget::populateSymbols( const QStringList& names ) void QgsSymbolsListWidget::populateSymbols( const QStringList& names )
@ -357,30 +397,34 @@ void QgsSymbolsListWidget::addSymbolToStyle()
void QgsSymbolsListWidget::saveSymbol() void QgsSymbolsListWidget::saveSymbol()
{ {
bool ok; QgsStyleSaveDialog saveDlg( this );
QString name = QInputDialog::getText( this, tr( "Symbol name" ), if ( !saveDlg.exec() )
tr( "Please enter name for the symbol:" ), QLineEdit::Normal, tr( "New symbol" ), &ok ); return;
if ( !ok || name.isEmpty() )
if ( saveDlg.name().isEmpty() )
return; return;
// check if there is no symbol with same name // check if there is no symbol with same name
if ( mStyle->symbolNames().contains( name ) ) if ( mStyle->symbolNames().contains( saveDlg.name() ) )
{ {
int res = QMessageBox::warning( this, tr( "Save symbol" ), int res = QMessageBox::warning( this, tr( "Save symbol" ),
tr( "Symbol with name '%1' already exists. Overwrite?" ) tr( "Symbol with name '%1' already exists. Overwrite?" )
.arg( name ), .arg( saveDlg.name() ),
QMessageBox::Yes | QMessageBox::No ); QMessageBox::Yes | QMessageBox::No );
if ( res != QMessageBox::Yes ) if ( res != QMessageBox::Yes )
{ {
return; return;
} }
mStyle->removeSymbol( saveDlg.name() );
} }
QStringList symbolTags = saveDlg.tags().split( ',' );
// add new symbol to style and re-populate the list // add new symbol to style and re-populate the list
mStyle->addSymbol( name, mSymbol->clone() ); mStyle->addSymbol( saveDlg.name(), mSymbol->clone() );
// make sure the symbol is stored // make sure the symbol is stored
mStyle->saveSymbol( name, mSymbol->clone(), 0, QStringList() ); mStyle->saveSymbol( saveDlg.name(), mSymbol->clone(), saveDlg.isFavorite(), symbolTags );
} }
void QgsSymbolsListWidget::on_mSymbolUnitWidget_changed() void QgsSymbolsListWidget::on_mSymbolUnitWidget_changed()
@ -537,7 +581,7 @@ void QgsSymbolsListWidget::setSymbolFromStyle( const QModelIndex & index )
// get new instance of symbol from style // get new instance of symbol from style
QgsSymbol* s = mStyle->symbol( symbolName ); QgsSymbol* s = mStyle->symbol( symbolName );
QgsUnitTypes::RenderUnit unit = s->outputUnit(); QgsUnitTypes::RenderUnit unit = s->outputUnit();
// remove all symbol layers from original symbol // remove all symbol layers from original symbolgroupsCombo
while ( mSymbol->symbolLayerCount() ) while ( mSymbol->symbolLayerCount() )
mSymbol->deleteSymbolLayer( 0 ); mSymbol->deleteSymbolLayer( 0 );
// move all symbol layers to our symbol // move all symbol layers to our symbol
@ -557,32 +601,8 @@ void QgsSymbolsListWidget::setSymbolFromStyle( const QModelIndex & index )
void QgsSymbolsListWidget::on_groupsCombo_currentIndexChanged( int index ) void QgsSymbolsListWidget::on_groupsCombo_currentIndexChanged( int index )
{ {
QStringList symbols; QSettings settings;
QString text = groupsCombo->itemText( index ); settings.setValue( QStringLiteral( "qgis/symbolsListGroupsIndex" ), index );
// List all symbols when empty list item is selected
if ( text.isEmpty() )
{
symbols = mStyle->symbolNames();
}
else
{
int groupid;
if ( groupsCombo->itemData( index ).toString() == QLatin1String( "smart" ) )
{
groupid = mStyle->smartgroupId( text );
symbols = mStyle->symbolsOfSmartgroup( QgsStyle::SymbolEntity, groupid );
}
else
{
groupid = groupsCombo->itemData( index ).toInt();
symbols = mStyle->symbolsOfGroup( QgsStyle::SymbolEntity, groupid );
}
}
populateSymbols( symbols );
}
void QgsSymbolsListWidget::on_groupsCombo_editTextChanged( const QString &text ) populateSymbolView();
{
QStringList symbols = mStyle->findSymbols( QgsStyle::SymbolEntity, text );
populateSymbols( symbols );
} }

View File

@ -67,12 +67,15 @@ class GUI_EXPORT QgsSymbolsListWidget : public QWidget, private Ui::SymbolsListW
void setLineWidth( double width ); void setLineWidth( double width );
void addSymbolToStyle(); void addSymbolToStyle();
void saveSymbol(); void saveSymbol();
void symbolAddedToStyle( const QString& name, QgsSymbol* symbol ); void symbolAddedToStyle( const QString& name, QgsSymbol* symbol );
void on_mSymbolUnitWidget_changed(); void on_mSymbolUnitWidget_changed();
void on_mTransparencySlider_valueChanged( int value ); void on_mTransparencySlider_valueChanged( int value );
//! Pupulates the groups combo box with available tags and smartgroups
void populateGroups();
void on_groupsCombo_currentIndexChanged( int index ); void on_groupsCombo_currentIndexChanged( int index );
void on_groupsCombo_editTextChanged( const QString &text );
void openStyleManager(); void openStyleManager();
void clipFeaturesToggled( bool checked ); void clipFeaturesToggled( bool checked );
@ -99,8 +102,6 @@ class GUI_EXPORT QgsSymbolsListWidget : public QWidget, private Ui::SymbolsListW
//! Displays alpha value as transparency in mTransparencyLabel //! Displays alpha value as transparency in mTransparencyLabel
void displayTransparency( double alpha ); void displayTransparency( double alpha );
//! Recursive function to create the group tree in the widget
void populateGroups( const QString& parent = "", const QString& prepend = "" );
QgsSymbolWidgetContext mContext; QgsSymbolWidgetContext mContext;

View File

@ -43,17 +43,33 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="3" column="0">
<widget class="QLabel" name="groupLabel"> <widget class="QLabel" name="tagLabel">
<property name="text"> <property name="text">
<string>Save to group</string> <string>Tag(s)</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1" colspan="2"> <item row="2" column="0" colspan="3">
<widget class="QComboBox" name="groupCombo"> <widget class="QCheckBox" name="mFavorite">
<property name="editable"> <property name="sizePolicy">
<bool>true</bool> <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Add to favorites</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QLineEdit" name="mSymbolTags"/>
</item>
<item row="4" column="1" colspan="2">
<widget class="QLabel" name="tagHintLabel">
<property name="text">
<string>Tip: separate multiple tags with commas</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -380,26 +380,6 @@ QMenu::item:selected { background-color: gray; } */
</property> </property>
</widget> </widget>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Tags</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="tagsLineEdit"/>
</item>
</layout>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>
@ -450,15 +430,37 @@ QMenu::item:selected { background-color: gray; } */
<string>Edit item</string> <string>Edit item</string>
</property> </property>
</action> </action>
<action name="actnUngroup"> <action name="actnAddFavorite">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="text"> <property name="text">
<string>Ungroup</string> <string>Add to favorites</string>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Ungroup</string> <string>Add to favorites</string>
</property>
</action>
<action name="actnRemoveFavorite">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Remove from favorites</string>
</property>
<property name="toolTip">
<string>Remove from favorites</string>
</property>
</action>
<action name="actnDetag">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Clear tags</string>
</property>
<property name="toolTip">
<string>Clear tags</string>
</property> </property>
</action> </action>
<action name="actnEditSmartGroup"> <action name="actnEditSmartGroup">
@ -484,17 +486,17 @@ QMenu::item:selected { background-color: gray; } */
<string>Remove group</string> <string>Remove group</string>
</property> </property>
</action> </action>
<action name="actnGroupSymbols"> <action name="actnTagSymbols">
<property name="text"> <property name="text">
<string>Group symbols</string> <string>Attach selected tag to symbols</string>
</property> </property>
</action> </action>
<action name="actnFinishGrouping"> <action name="actnFinishTagging">
<property name="enabled"> <property name="enabled">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="text"> <property name="text">
<string>Finish grouping</string> <string>Finish tagging</string>
</property> </property>
<property name="visible"> <property name="visible">
<bool>true</bool> <bool>true</bool>

View File

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsStyleSaveDialog</class>
<widget class="QDialog" name="QgsStyleSaveDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>489</width>
<height>225</height>
</rect>
</property>
<property name="windowTitle">
<string>Save new style</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_1">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="mName"/>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="mFavorite">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Add to favorites</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Tag(s)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="mTags"/>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Tip: separate multiple tags with commas</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>mName</tabstop>
<tabstop>mTags</tabstop>
<tabstop>mFavorite</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>QgsStyleSaveDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>QgsStyleSaveDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -72,7 +72,7 @@
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="text"> <property name="text">
<string>Symbols in group</string> <string>Symbols in</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -131,17 +131,11 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="btnSaveSymbol"> <widget class="QPushButton" name="btnSaveSymbol">
<property name="maximumSize">
<size>
<width>70</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>Save symbol</string> <string>Save symbol</string>
</property> </property>
<property name="text"> <property name="text">
<string>Save</string> <string>Save symbol</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -65,6 +65,7 @@ class TestStyle : public QObject
void testCreateColorRamps(); void testCreateColorRamps();
void testLoadColorRamps(); void testLoadColorRamps();
void testSaveLoad(); void testSaveLoad();
void testFavorites();
void testTags(); void testTags();
}; };
@ -258,6 +259,35 @@ void TestStyle::testSaveLoad()
testLoadColorRamps(); testLoadColorRamps();
} }
void TestStyle::testFavorites()
{
mStyle->clear();
// save initial number of favorites to compare against additions / substractions
QStringList favorites;
favorites = mStyle->symbolsOfFavorite( QgsStyle::SymbolEntity );
int count = favorites.count();
// add some symbols to favorites
mStyle->saveSymbol( "symbolA", QgsMarkerSymbol::createSimple( QgsStringMap() ), true, QStringList() );
mStyle->saveSymbol( "symbolB", QgsMarkerSymbol::createSimple( QgsStringMap() ), false, QStringList() );
mStyle->saveSymbol( "symbolC", QgsMarkerSymbol::createSimple( QgsStringMap() ), true, QStringList() );
// check for added symbols to favorites
favorites = mStyle->symbolsOfFavorite( QgsStyle::SymbolEntity );
QCOMPARE( favorites.count(), count + 2 );
QVERIFY( favorites.contains( "symbolA" ) );
QVERIFY( favorites.contains( "symbolC" ) );
// remove one symbol from favorites
mStyle->removeFavorite( QgsStyle::SymbolEntity, "symbolA" );
// insure favorites updated after removal
favorites = mStyle->symbolsOfFavorite( QgsStyle::SymbolEntity );
QCOMPARE( favorites.count(), count + 1 );
QVERIFY( favorites.contains( "symbolC" ) );
}
void TestStyle::testTags() void TestStyle::testTags()
{ {
mStyle->clear(); mStyle->clear();
@ -289,7 +319,7 @@ void TestStyle::testTags()
QVERIFY( !tags.contains( "purple" ) ); QVERIFY( !tags.contains( "purple" ) );
//add some symbols //add some symbols
QVERIFY( mStyle->saveSymbol( "symbol1", QgsMarkerSymbol::createSimple( QgsStringMap() ), 0, QStringList() << "red" << "starry" ) ); QVERIFY( mStyle->saveSymbol( "symbol1", QgsMarkerSymbol::createSimple( QgsStringMap() ), false, QStringList() << "red" << "starry" ) );
mStyle->addSymbol( QStringLiteral( "blue starry" ), QgsMarkerSymbol::createSimple( QgsStringMap() ), true ); mStyle->addSymbol( QStringLiteral( "blue starry" ), QgsMarkerSymbol::createSimple( QgsStringMap() ), true );
mStyle->addSymbol( QStringLiteral( "red circle" ), QgsMarkerSymbol::createSimple( QgsStringMap() ), true ); mStyle->addSymbol( QStringLiteral( "red circle" ), QgsMarkerSymbol::createSimple( QgsStringMap() ), true );