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.
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}
------------------------------------

View File

@ -8,15 +8,16 @@ class QgsStyle : QObject
QgsStyle();
~QgsStyle();
//! Enum for Entities involved in a style
/*!
The enumerator is used for identifying the entity being operated on when generic
database functions are being run.
\sa group(), rename(), remove(), symbolsOfGroup(), symbolsWithTag(), symbolsOfSmartgroup()
/** Enum for Entities involved in a style
/*
* The enumerator is used for identifying the entity being operated on when generic
* database functions are being run.
* \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.
*
* \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 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 );
//! adds a new group and returns the group's 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
/*!
/** Adds new smartgroup to the database and returns the id
*
* \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 conditions are the smart group 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.
* \param name is the name of the symbol being added or updated
* \param symbol is the Vector symbol
@ -51,22 +44,19 @@ class QgsStyle : QObject
*/
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
* \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
* @note added in QGIS 2.16
* @see addTag()
* @note added in QGIS 2.16
* @see addTag()
*/
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
void clear();
@ -75,24 +65,25 @@ class QgsStyle : QObject
*/
QgsColorRamp* colorRamp( const QString& name ) const /Factory/;
//! return count of color ramps
//! Returns count of color ramps
int colorRampCount();
//! return a list of names of color ramps
//! Returns a list of names of color ramps
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;
//! return the id in the style database for the given colorramp name
//! returns 0 if not found
/** Returns the id in the style database for the given colorramp name
* returns 0 if not found
*/
int colorrampId( const QString& name );
//! return default application-wide style
//! Returns default application-wide style
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
* \param type is either SymbolEntity or ColorrampEntity
* \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 );
//! detags the symbol with the given list
/*!
/** Detags the symbol with the given list
*
* Removes the given tags for the specified symbol or colorramp
* \param type is either SymbolEntity or ColorrampEntity
* \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
*/
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 );
//! change symbol's name
//! Changes symbol's name
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/;
//! 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;
//! return count of symbols in style
//! Returns count of symbols in style
int symbolCount();
//! return a list of names of symbols
//! Returns a list of names of symbols
QStringList symbolNames();
//! return the id in the style database for the given symbol name
//! returns 0 if not found
/** Returns the id in the style database for the given symbol name
* returns 0 if not found
*/
int symbolId( const QString& name );
//! return the DB id for the given group 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
//! Returns the DB id for the given tag name
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 );
//! return the all the groups in the style
QStringList groupNames();
//! return the ids of all the groups in the style
QList<int> groupIds() const;
//! returns the symbolnames of a given groupid
/*!
/** Returns the symbol names which are flagged as favorite
*
* \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 for the given group id
* \return A QStringList of the symbol or colorramp names flagged as favorite
*/
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 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
*/
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 name is the name of the symbol or coloramp whose group is to be set
* \param groupid is the id of the group to which the entity is assigned
* \param name is the name of the symbol or coloramp whose is to be added to favorites
* \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 id is the DB id of the entity which is to be renamed
* \param newName is the new name of the entity
*/
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 id is the DB id of the entity to be removed
*/
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 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.
@ -197,8 +192,8 @@ class QgsStyle : QObject
*/
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 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.
@ -207,54 +202,54 @@ class QgsStyle : QObject
*/
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 );
//! change ramp's name
//! Changes ramp's name
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 );
//! 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() );
//! return last error from load/save operation
//! Returns last error from load/save operation
QString errorString();
//! return current file name of the style
//! Returns current file name of the style
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 qword is the query string to search the symbols or colorramps.
* \return A QStringList of the matched symbols or colorramps
* */
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 symbol is the name of the symbol or color ramp
* \return A QStringList of the tags that have been applied to that symbol/colorramp
*/
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();
//! returns the smart groups list
//! Returns the smart groups list
QStringList smartgroupNames();
//! returns the QgsSmartConditionMap for the given id
//! Returns the QgsSmartConditionMap for the given 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
QString smartgroupOperator( int id );
//! returns the symbols for the smartgroup
//! Returns the symbols for the smartgroup
QStringList symbolsOfSmartgroup( StyleEntity type, int id );
//! Exports the style as a XML file
@ -264,29 +259,30 @@ class QgsStyle : QObject
bool importXml( const QString& filename );
signals:
//! Is emitted every time a new symbol has been added to the database
void symbolSaved( const QString& name, QgsSymbol* symbol );
//! Is emitted every time a tag or smartgroup has been added, removed, or renamed
void groupsModified();
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 );
//! convenience function that would run queries which don't generate return values
//! \param query query to run
//! \param freeQuery release query memory
//! \return success true on success
/** Convenience function that would run queries which don't generate return values
* \param query query to run
* \param freeQuery release query memory
* \return success true on success
*/
bool runEmptyQuery( char* query, bool freeQuery = true );
//! prepares the complex query for removing a group, so that the children are not abandoned
char* getGroupRemoveQuery( int id );
//! gets the id from the table for the given name from the database, 0 if not found
//! 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 );
//! 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;
//! 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
* \param type is either SymbolEntity or ColorrampEntity
* \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/qgsstylegroupselectiondialog.sip
%Include symbology-ng/qgsstylemanagerdialog.sip
%Include symbology-ng/qgsstylesavedialog.sip
%Include symbology-ng/qgssvgselectorwidget.sip
%Include symbology-ng/qgssymbollayerwidget.sip
%Include symbology-ng/qgssymbollevelsdialog.sip

View File

@ -41,15 +41,15 @@ class QgsStyleExportImportDialog : QDialog
*/
void clearSelection();
/**
* Select the symbols belonging to the given group
* @param groupName the name of the group to be selected
* Select the symbols belonging to the given tag
* @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
* @param groupName the name of the group to be deselected
* Deselect the symbols belonging to the given tag
* @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
* @param groupName

View File

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

View File

@ -37,8 +37,8 @@ class QgsStyleManagerDialog : QDialog
void addGroup();
void removeGroup();
//! carryout symbol grouping using check boxes
void groupSymbolsAction();
//! carry out symbol tagging using check boxes
void tagSymbolsAction();
//! edit the selected smart group
void editSmartgroupAction();
@ -49,9 +49,6 @@ class QgsStyleManagerDialog : QDialog
//! filter the symbols based on input search term
void filterSymbols( const QString& );
//! Listen to tag changes
void tagsChanged();
//! Perform symbol specific tasks when selected
void symbolSelected( const QModelIndex& );
@ -66,7 +63,14 @@ class QgsStyleManagerDialog : QDialog
protected slots:
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:
@ -75,8 +79,6 @@ class QgsStyleManagerDialog : QDialog
//! populate the groups
void populateGroups();
//! build the groups tree
void buildGroupTree( QStandardItem* &parent );
//! to set symbols checked when in editing mode
void setSymbolsChecked( const QStringList& );
@ -107,9 +109,6 @@ class QgsStyleManagerDialog : QDialog
//! Enables or diables the groupTree items for grouping mode
void enableItemsForGroupingMode( bool );
//! Event filter to capture tagsLineEdit out of focus
bool eventFilter( QObject*, QEvent* );
//! sets the text of the item with bold font
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_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_editTextChanged( const QString &text );
void openStyleManager();
void clipFeaturesToggled( bool checked );

Binary file not shown.

View File

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

View File

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

View File

@ -28,6 +28,7 @@
#include <QDomNode>
#include <QDomNodeList>
#include <QFile>
#include <QSettings>
#include <QTextStream>
#include <QByteArray>
@ -96,13 +97,13 @@ bool QgsStyle::addSymbol( const QString& name, QgsSymbol* symbol, bool update )
{
mSymbols.insert( name, symbol );
if ( update )
saveSymbol( name, symbol, 0, QStringList() );
saveSymbol( name, symbol, false, QStringList() );
}
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
QDomDocument doc( QStringLiteral( "dummy" ) );
@ -118,7 +119,7 @@ bool QgsStyle::saveSymbol( const QString& name, QgsSymbol* symbol, int groupid,
stream.setCodec( "UTF-8" );
symEl.save( stream, 4 );
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 ) )
{
@ -207,11 +208,12 @@ bool QgsStyle::addColorRamp( const QString& name, QgsColorRamp* colorRamp, bool
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
QDomDocument doc( QStringLiteral( "dummy" ) );
QDomElement rampEl = QgsSymbolLayerUtils::saveColorRamp( name, ramp, doc );
if ( rampEl.isNull() )
{
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" );
rampEl.save( stream, 4 );
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 ) )
{
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
char *query = sqlite3_mprintf( "UPDATE symbol SET groupid=0 WHERE groupid IS NULL;"
"UPDATE colorramp SET groupid=0 WHERE groupid IS NULL;"
char *query = sqlite3_mprintf( "UPDATE symbol SET favorite=0 WHERE favorite IS NULL;"
"UPDATE colorramp SET favorite=0 WHERE favorite IS NULL;"
"UPDATE symgroup SET parent=0 WHERE parent IS NULL;" );
runEmptyQuery( query );
@ -460,97 +461,22 @@ bool QgsStyle::renameColorRamp( const QString& oldName, const QString& newName )
return true;
}
QStringList QgsStyle::groupNames()
{
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 )
QStringList QgsStyle::symbolsOfFavorite( StyleEntity type ) const
{
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();
}
char *query;
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 )
{
query = sqlite3_mprintf( "SELECT name FROM colorramp WHERE groupid=%d", groupid );
query = sqlite3_mprintf( "SELECT name FROM colorramp WHERE favorite=1" );
}
else
{
@ -572,7 +498,7 @@ QStringList QgsStyle::symbolsOfGroup( StyleEntity type, int groupid )
return symbols;
}
QStringList QgsStyle::symbolsWithTag( StyleEntity type, int tagid )
QStringList QgsStyle::symbolsWithTag( StyleEntity type, int tagid ) const
{
if ( !mCurrentDB )
{
@ -587,7 +513,7 @@ QStringList QgsStyle::symbolsWithTag( StyleEntity type, int tagid )
}
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
{
@ -598,15 +524,15 @@ QStringList QgsStyle::symbolsWithTag( StyleEntity type, int tagid )
sqlite3_stmt *ppStmt;
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;
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
? sqlite3_mprintf( "SELECT name FROM symbol WHERE id=%d", symbolId )
: sqlite3_mprintf( "SELECT name FROM colorramp WHERE id=%d", symbolId );
? sqlite3_mprintf( "SELECT name FROM symbol WHERE id=%d", id )
: sqlite3_mprintf( "SELECT name FROM colorramp WHERE id=%d", id );
sqlite3_stmt *ppStmt2;
int sErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt2, nullptr );
@ -621,23 +547,6 @@ QStringList QgsStyle::symbolsWithTag( StyleEntity type, int tagid )
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 )
{
if ( !mCurrentDB )
@ -650,6 +559,11 @@ int QgsStyle::addTag( const QString& tagname )
( void )sqlite3_step( ppStmt );
sqlite3_finalize( ppStmt );
QSettings settings;
settings.setValue( QStringLiteral( "qgis/symbolsListGroupsIndex" ), 0 );
emit groupsModified();
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 )
{
bool groupRenamed = false;
char *query;
switch ( type )
{
case SymbolEntity:
query = sqlite3_mprintf( "UPDATE symbol SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id );
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:
query = sqlite3_mprintf( "UPDATE colorramp 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 );
groupRenamed = true;
break;
case SmartgroupEntity:
query = sqlite3_mprintf( "UPDATE smartgroup SET name='%q' WHERE id=%d", newName.toUtf8().constData(), id );
groupRenamed = true;
break;
default:
QgsDebugMsg( "Invalid Style Entity indicated" );
return;
}
if ( !runEmptyQuery( query ) )
{
mErrorString = QStringLiteral( "Could not rename!" );
}
char* QgsStyle::getGroupRemoveQuery( int id )
{
char *query = sqlite3_mprintf( "SELECT parent FROM symgroup WHERE id=%d", id );
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 );
}
else
{
if ( groupRenamed )
{
emit groupsModified();
}
}
}
void QgsStyle::remove( StyleEntity type, int id )
{
bool groupRemoved = false;
char *query;
switch ( type )
{
case SymbolEntity:
query = sqlite3_mprintf( "DELETE FROM symbol WHERE id=%d; DELETE FROM tagmap WHERE symbol_id=%d", id, id );
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:
query = sqlite3_mprintf( "DELETE FROM colorramp WHERE id=%d", id );
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:
query = sqlite3_mprintf( "DELETE FROM smartgroup WHERE id=%d", id );
groupRemoved = true;
break;
default:
QgsDebugMsg( "Invalid Style Entity indicated" );
@ -749,6 +654,16 @@ void QgsStyle::remove( StyleEntity type, int id )
{
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 )
@ -772,17 +687,38 @@ bool QgsStyle::runEmptyQuery( char *query, bool freeQuery )
return zErr == SQLITE_OK;
}
bool QgsStyle::group( StyleEntity type, const QString& name, int groupid )
bool QgsStyle::addFavorite( StyleEntity type, const QString& name )
{
char *query;
switch ( type )
{
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;
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;
default:
@ -882,37 +818,41 @@ bool QgsStyle::tagSymbol( StyleEntity type, const QString& symbol, const QString
return false;
}
Q_FOREACH ( const QString &tag, tags )
QString tag;
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
char *query = sqlite3_mprintf( "SELECT id FROM tag WHERE name='%q'", tag.toUtf8().constData() );
sqlite3_stmt *ppStmt;
int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, nullptr );
int tagid;
if ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
tag = t.trimmed();
if ( tag != "" )
{
tagid = sqlite3_column_int( ppStmt, 0 );
}
else
{
tagid = addTag( tag );
}
// 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() );
sqlite3_finalize( ppStmt );
sqlite3_stmt *ppStmt;
int nErr = sqlite3_prepare_v2( mCurrentDB, query, -1, &ppStmt, nullptr );
// Now map the tag to the symbol
query = type == SymbolEntity
? sqlite3_mprintf( "INSERT INTO tagmap VALUES (%d,%d)", tagid, symbolid )
: sqlite3_mprintf( "INSERT INTO ctagmap VALUES (%d,%d)", tagid, symbolid );
int tagid;
if ( nErr == SQLITE_OK && sqlite3_step( ppStmt ) == SQLITE_ROW )
{
tagid = sqlite3_column_int( ppStmt, 0 );
}
else
{
tagid = addTag( tag );
}
char *zErr = nullptr;
nErr = sqlite3_exec( mCurrentDB, query, nullptr, nullptr, &zErr );
if ( nErr )
{
QgsDebugMsg( zErr );
sqlite3_finalize( ppStmt );
// Now map the tag to the symbol
query = type == SymbolEntity
? 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;
}
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 )
{
if ( !mCurrentDB )
@ -1018,7 +997,7 @@ QStringList QgsStyle::tagsOfSymbol( StyleEntity type, const QString& symbol )
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;
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 );
}
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 )
{
return getId( QStringLiteral( "tag" ), name );
@ -1113,6 +1082,10 @@ int QgsStyle::addSmartgroup( const QString& name, const QString& op, const QgsSm
if ( runEmptyQuery( query ) )
{
QSettings settings;
settings.setValue( QStringLiteral( "qgis/symbolsListGroupsIndex" ), 0 );
emit groupsModified();
return static_cast< int >( sqlite3_last_insert_rowid( mCurrentDB ) );
}
else
@ -1211,12 +1184,6 @@ QStringList QgsStyle::symbolsOfSmartgroup( StyleEntity type, int id )
{
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" ) )
{
if ( type == SymbolEntity )
@ -1237,15 +1204,6 @@ QStringList QgsStyle::symbolsOfSmartgroup( StyleEntity type, int id )
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" ) )
{
QStringList all = type == SymbolEntity ? symbolNames() : colorRampNames();

View File

@ -41,8 +41,6 @@ typedef QMap<int, QString> QgsSymbolGroupMap;
* The supported constraints are:
* tag -> symbol has 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 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;
// enumerators representing sqlite DB columns
enum SymbolTable { SymbolId, SymbolName, SymbolXML, SymbolGroupId };
enum SymgroupTable { SymgroupId, SymgroupName, SymgroupParent };
enum SymbolTable { SymbolId, SymbolName, SymbolXML, SymbolFavoriteId };
enum TagTable { TagId, TagName };
enum TagmapTable { TagmapTagId, TagmapSymbolId };
enum ColorrampTable { ColorrampId, ColorrampName, ColorrampXML, ColorrampGroupId };
enum ColorrampTable { ColorrampId, ColorrampName, ColorrampXML, ColorrampFavoriteId };
enum SmartgroupTable { SmartgroupId, SmartgroupName, SmartgroupXML };
/** \ingroup core
@ -74,13 +71,23 @@ class CORE_EXPORT QgsStyle : public QObject
QgsStyle();
~QgsStyle();
//! Enum for Entities involved in a style
/*!
The enumerator is used for identifying the entity being operated on when generic
database functions are being run.
\sa group(), rename(), remove(), symbolsOfGroup(), symbolsWithTag(), symbolsOfSmartgroup()
/** Enum for Entities involved in a style
*
* The enumerator is used for identifying the entity being operated on when generic
* database functions are being run.
* \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.
* \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 );
//! adds a new group and returns the group's 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
/** 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 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 op is the operator between the conditions; AND/OR as QString
* \param conditions are the smart group 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
*
* @note added in QGIS 2.16
* @see addTag()
*/
QStringList tags() const;
//! return a map of groupid and names for the given parent group
QgsSymbolGroupMap childGroupNames( const QString& parent = "" );
//! remove all contents of the style
//! Removes all contents of the style
void clear();
/** 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;
//! return count of color ramps
//! Returns count of color ramps
int colorRampCount();
//! return a list of names of color ramps
//! Returns a list of names of color ramps
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;
//! return the id in the style database for the given colorramp name
//! returns 0 if not found
/** Returns the id in the style database for the given colorramp name
* returns 0 if not found
*/
int colorrampId( const QString& name );
//! return default application-wide style
//! Returns default application-wide style
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
* \param type is either SymbolEntity or ColorrampEntity
* \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 );
//! detags the symbol with the given list
/*!
/** Detags the symbol with the given list
*
* Removes the given tags for the specified symbol or colorramp
* \param type is either SymbolEntity or ColorrampEntity
* \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 );
//! 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 );
//! change symbol's name
//! Changessymbol's name
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 );
//! 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;
//! return count of symbols in style
//! Returns count of symbols in style
int symbolCount();
//! return a list of names of symbols
//! Returns a list of names of symbols
QStringList symbolNames();
//! return the id in the style database for the given symbol name
//! returns 0 if not found
/** Returns the id in the style database for the given symbol name
* returns 0 if not found
*/
int symbolId( const QString& name );
//! return the DB id for the given group 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
//! Returns the DB id for the given tag name
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 );
//! return the all the groups in the style
QStringList groupNames();
//! return the ids of all the groups in the style
QList<int> groupIds() const;
//! returns the symbolnames of a given groupid
/*!
/** Returns the symbol names which are flagged as favorite
*
* \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 for the given group id
* \return A QStringList of the symbol or colorramp names flagged as favorite
*/
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 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
*/
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 name is the name of the symbol or coloramp whose group is to be set
* \param groupid is the id of the group to which the entity is assigned
* \param name is the name of the symbol or coloramp whose is to be added to favorites
* \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 id is the DB id of the entity which is to be renamed
* \param newName is the new name of the entity
*/
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 id is the DB id of the entity to be removed
*/
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 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.
* \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 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.
* \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 );
//! change ramp's name
//! Changes ramp's name
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 );
//! 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() );
//! return last error from load/save operation
//! Returns last error from load/save operation
QString errorString() { return mErrorString; }
//! return current file name of the style
//! Returns current file name of the style
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 qword is the query string to search the symbols or colorramps.
* \return A QStringList of the matched symbols or colorramps
* */
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 symbol is the name of the symbol or color ramp
* \return A QStringList of the tags that have been applied to that symbol/colorramp
*/
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();
//! returns the smart groups list
//! Returns the smart groups list
QStringList smartgroupNames();
//! returns the QgsSmartConditionMap for the given id
//! Returns the QgsSmartConditionMap for the given id
QgsSmartConditionMap smartgroup( int id );
//! returns the operator for the smartgroup
//clumsy implementation TODO create a class for smartgroups
/** Returns the operator for the smartgroup
* clumsy implementation TODO create a class for smartgroups
*/
QString smartgroupOperator( int id );
//! returns the symbols for the smartgroup
//! Returns the symbols for the smartgroup
QStringList symbolsOfSmartgroup( StyleEntity type, int id );
//! Exports the style as a XML file
@ -330,7 +325,10 @@ class CORE_EXPORT QgsStyle : public QObject
bool importXml( const QString& filename );
signals:
//! Is emitted every time a new symbol has been added to the database
void symbolSaved( const QString& name, QgsSymbol* symbol );
//! Is emitted every time a tag or smartgroup has been added, removed, or renamed
void groupsModified();
protected:
@ -344,26 +342,25 @@ class CORE_EXPORT QgsStyle : public QObject
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 );
//! convenience function that would run queries which don't generate return values
//! \param query query to run
//! \param freeQuery release query memory
//! \return success true on success
/** Convenience function that would run queries which don't generate return values
*
* \param query query to run
* \param freeQuery release query memory
* \return success true on success
*/
bool runEmptyQuery( char* query, bool freeQuery = true );
//! prepares the complex query for removing a group, so that the children are not abandoned
char* getGroupRemoveQuery( int id );
//! gets the id from the table for the given name from the database, 0 if not found
//! 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 );
//! 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;
//! 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
* \param type is either SymbolEntity or ColorrampEntity
* \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/qgsstylegroupselectiondialog.cpp
symbology-ng/qgsstylemanagerdialog.cpp
symbology-ng/qgsstylesavedialog.cpp
symbology-ng/qgssvgselectorwidget.cpp
symbology-ng/qgssymbollayerwidget.cpp
symbology-ng/qgssymbollevelsdialog.cpp
@ -511,6 +512,7 @@ SET(QGIS_GUI_MOC_HDRS
symbology-ng/qgsstyleexportimportdialog.h
symbology-ng/qgsstylegroupselectiondialog.h
symbology-ng/qgsstylemanagerdialog.h
symbology-ng/qgsstylesavedialog.h
symbology-ng/qgssvgselectorwidget.h
symbology-ng/qgssymbollayerwidget.h
symbology-ng/qgssymbollevelsdialog.h

View File

@ -31,10 +31,8 @@ QgsSmartGroupCondition::QgsSmartGroupCondition( int id, QWidget* parent ) : QWid
mConditionId = id;
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( "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" ) );
mRemoveBtn->setIcon( QIcon( QgsApplication::iconPath( "symbologyRemove.svg" ) ) );
@ -159,7 +157,7 @@ QString QgsSmartGroupEditorDialog::conditionOperator()
void QgsSmartGroupEditorDialog::setConditionMap( const QgsSmartConditionMap& map )
{
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
Q_FOREACH ( int id, mConditionMap.keys() )

View File

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

View File

@ -80,16 +80,16 @@ class GUI_EXPORT QgsStyleExportImportDialog : public QDialog, private Ui::QgsSty
void clearSelection();
/**
* Select the symbols belonging to the given group
* @param groupName the name of the group to be selected
* Select the symbols belonging to the given tag
* @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
* @param groupName the name of the group to be deselected
* Deselect the symbols belonging to the given tag
* @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
@ -127,7 +127,7 @@ class GUI_EXPORT QgsStyleExportImportDialog : public QDialog, private Ui::QgsSty
QString mFileName;
Mode mDialogMode;
QgsStyle* mQgisStyle;
QgsStyle* mStyle;
QgsStyle* mTempStyle;
};

View File

@ -37,24 +37,19 @@ QgsStyleGroupSelectionDialog::QgsStyleGroupSelectionDialog( QgsStyle *style, QWi
setBold( allSymbols );
model->appendRow( allSymbols );
QStandardItem *group = new QStandardItem( QLatin1String( "" ) ); //require empty name to get first order groups
group->setData( "groupsheader", Qt::UserRole + 2 );
group->setEditable( false );
group->setFlags( group->flags() & ~Qt::ItemIsSelectable );
buildGroupTree( group );
group->setText( tr( "Groups" ) );//set title later
QStandardItem *ungrouped = new QStandardItem( tr( "Ungrouped" ) );
ungrouped->setData( 0 );
ungrouped->setData( "group", Qt::UserRole + 2 );
setBold( ungrouped );
setBold( group );
group->appendRow( ungrouped );
model->appendRow( group );
QStandardItem *tags = new QStandardItem( QLatin1String( "" ) ); //require empty name to get first order groups
tags->setData( "tagsheader", Qt::UserRole + 2 );
tags->setEditable( false );
tags->setFlags( tags->flags() & ~Qt::ItemIsSelectable );
buildTagTree( tags );
tags->setText( tr( "Tags" ) );//set title later
setBold( tags );
model->appendRow( tags );
QStandardItem *tag = new QStandardItem( tr( "Smart Groups" ) );
tag->setData( "smartgroupsheader" , Qt::UserRole + 2 );
tag->setEditable( false );
tag->setFlags( group->flags() & ~Qt::ItemIsSelectable );
tag->setFlags( tag->flags() & ~Qt::ItemIsSelectable );
setBold( tag );
QgsSymbolGroupMap sgMap = mStyle->smartgroupsListMap();
QgsSymbolGroupMap::const_iterator i = sgMap.constBegin();
@ -100,7 +95,7 @@ void QgsStyleGroupSelectionDialog::groupTreeSelectionChanged( const QItemSelecti
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
}
@ -116,14 +111,14 @@ void QgsStyleGroupSelectionDialog::groupTreeSelectionChanged( const QItemSelecti
{
emit smartgroupDeselected( index.data().toString() );
}
else if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "group" ) )
{ // It's a group
emit groupDeselected( index.data().toString() );
else if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "tag" ) )
{ // It's a tag
emit tagDeselected( index.data().toString() );
}
}
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
}
@ -139,27 +134,25 @@ void QgsStyleGroupSelectionDialog::groupTreeSelectionChanged( const QItemSelecti
{
emit smartgroupSelected( index.data().toString() );
}
else if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "group" ) )
{ // It's a group
emit groupSelected( index.data().toString() );
else if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "tag" ) )
{ // It's a tag
emit tagSelected( index.data().toString() );
}
}
}
void QgsStyleGroupSelectionDialog::buildGroupTree( QStandardItem* &parent )
void QgsStyleGroupSelectionDialog::buildTagTree( QStandardItem* &parent )
{
QgsSymbolGroupMap groups = mStyle->childGroupNames( parent->text() );
QgsSymbolGroupMap::const_iterator i = groups.constBegin();
while ( i != groups.constEnd() )
QStringList tags = mStyle->tags();
tags.sort();
Q_FOREACH ( const QString& tag, tags )
{
QStandardItem *item = new QStandardItem( i.value() );
item->setData( i.key() );
item->setData( "group" , Qt::UserRole + 2 );
QStandardItem *item = new QStandardItem( tag );
item->setData( mStyle->tagId( tag ) );
item->setData( "tag" , Qt::UserRole + 2 );
item->setEditable( false );
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 );
signals:
//! group with groupName has been selected
void groupSelected( const QString& groupName );
//! group with groupName has been deselected
void groupDeselected( const QString& groupName );
//! tag with tagName has been selected
void tagSelected( const QString& tagName );
//! tag with tagName has been deselected
void tagDeselected( const QString& tagName );
//! smartgroup with groupName has been selected
void smartgroupSelected( const QString& groupName );
//! smart group with groupName has been deselected
@ -60,7 +60,7 @@ class GUI_EXPORT QgsStyleGroupSelectionDialog : public QDialog, private Ui::Symb
* @brief build group tree
* @param parent
*/
void buildGroupTree( QStandardItem *&parent );
void buildTagTree( QStandardItem *&parent );
QgsStyle* mStyle;
};

View File

@ -14,6 +14,7 @@
***************************************************************************/
#include "qgsstylemanagerdialog.h"
#include "qgsstylesavedialog.h"
#include "qgsstyle.h"
#include "qgssymbol.h"
@ -111,16 +112,15 @@ QgsStyleManagerDialog::QgsStyleManagerDialog( QgsStyle* style, QWidget* parent )
this, SLOT( groupRenamed( QStandardItem* ) ) );
QMenu *groupMenu = new QMenu( tr( "Group actions" ), this );
connect( actnGroupSymbols, SIGNAL( triggered() ), this, SLOT( groupSymbolsAction() ) );
groupMenu->addAction( actnGroupSymbols );
connect( actnFinishGrouping, SIGNAL( triggered() ), this, SLOT( groupSymbolsAction() ) );
actnFinishGrouping->setVisible( false );
groupMenu->addAction( actnFinishGrouping );
connect( actnTagSymbols, SIGNAL( triggered() ), this, SLOT( tagSymbolsAction() ) );
groupMenu->addAction( actnTagSymbols );
connect( actnFinishTagging, SIGNAL( triggered() ), this, SLOT( tagSymbolsAction() ) );
actnFinishTagging->setVisible( false );
groupMenu->addAction( actnFinishTagging );
groupMenu->addAction( actnEditSmartGroup );
btnManageGroups->setMenu( groupMenu );
connect( searchBox, SIGNAL( textChanged( QString ) ), this, SLOT( filterSymbols( QString ) ) );
tagsLineEdit->installEventFilter( this );
// Context menu for groupTree
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.
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->setTitle( tr( "Add to group" ) );
mGroupListMenu->setTitle( tr( "Add to tag" ) );
mGroupListMenu->setEnabled( false );
mGroupMenu->addMenu( mGroupListMenu );
actnUngroup->setData( 0 );
connect( actnUngroup, SIGNAL( triggered( bool ) ), this, SLOT( groupSelectedSymbols() ) );
mGroupMenu->addAction( actnUngroup );
actnDetag->setData( 0 );
connect( actnDetag, SIGNAL( triggered( bool ) ), this, SLOT( detagSelectedSymbols() ) );
mGroupMenu->addAction( actnDetag );
mGroupMenu->addSeparator()->setParent( this );
mGroupMenu->addAction( actnRemoveItem );
mGroupMenu->addAction( actnEditItem );
@ -391,20 +396,19 @@ bool QgsStyleManagerDialog::addSymbol()
return false;
}
// get unique name
bool nameInvalid = true;
QgsStyleSaveDialog saveDlg( this );
if ( !saveDlg.exec() )
{
delete symbol;
return false;
}
name = saveDlg.name();
// request valid/unique name
bool nameInvalid = true;
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
if ( name.isEmpty() )
{
@ -419,6 +423,7 @@ bool QgsStyleManagerDialog::addSymbol()
QMessageBox::Yes | QMessageBox::No );
if ( res == QMessageBox::Yes )
{
mStyle->removeSymbol( name );
nameInvalid = false;
}
}
@ -427,11 +432,26 @@ bool QgsStyleManagerDialog::addSymbol()
// valid name
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
mStyle->addSymbol( name, symbol, true );
// TODO groups and tags
mStyle->addSymbol( name, symbol );
mStyle->saveSymbol( name, symbol, saveDlg.isFavorite(), symbolTags );
mModified = true;
return true;
}
@ -521,19 +541,18 @@ QString QgsStyleManagerDialog::addColorRampStatic( QWidget* parent, QgsStyle* st
return QString();
}
// get unique name
bool nameInvalid = true;
QgsStyleSaveDialog saveDlg( parent, QgsStyle::ColorrampEntity );
if ( !saveDlg.exec() )
{
return QString();
}
name = saveDlg.name();
// get valid/unique name
bool nameInvalid = true;
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
if ( name.isEmpty() )
{
@ -556,11 +575,26 @@ QString QgsStyleManagerDialog::addColorRampStatic( QWidget* parent, QgsStyle* st
// valid name
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
style->addColorRamp( name, ramp.take(), true );
// TODO groups and tags, using saveColorRamp
style->addColorRamp( name, r );
style->saveColorRamp( name, r, saveDlg.isFavorite(), colorRampTags );
return name;
}
@ -854,40 +888,49 @@ void QgsStyleManagerDialog::populateGroups()
QStandardItemModel *model = qobject_cast<QStandardItemModel*>( groupTree->model() );
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" ) );
allSymbols->setData( "all" );
allSymbols->setEditable( false );
setBold( allSymbols );
model->appendRow( allSymbols );
QStandardItem *group = new QStandardItem( QLatin1String( "" ) ); //require empty name to get first order groups
group->setData( "groups" );
group->setEditable( false );
buildGroupTree( group );
group->setText( tr( "Groups" ) );//set title later
QStandardItem *ungrouped = new QStandardItem( tr( "Ungrouped" ) );
ungrouped->setData( 0 );
setBold( ungrouped );
setBold( group );
group->appendRow( ungrouped );
model->appendRow( group );
QStandardItem *taggroup = new QStandardItem( QLatin1String( "" ) ); //require empty name to get first order groups
taggroup->setData( "tags" );
taggroup->setEditable( false );
QStringList tags = mStyle->tags();
tags.sort();
Q_FOREACH ( const QString& tag, tags )
{
QStandardItem *item = new QStandardItem( tag );
item->setData( mStyle->tagId( tag ) );
taggroup->appendRow( item );
}
taggroup->setText( tr( "Tags" ) );//set title later
setBold( taggroup );
model->appendRow( taggroup );
QStandardItem *tag = new QStandardItem( tr( "Smart Groups" ) );
tag->setData( "smartgroups" );
tag->setEditable( false );
setBold( tag );
QStandardItem *smart = new QStandardItem( tr( "Smart Groups" ) );
smart->setData( "smartgroups" );
smart->setEditable( false );
setBold( smart );
QgsSymbolGroupMap sgMap = mStyle->smartgroupsListMap();
QgsSymbolGroupMap::const_iterator i = sgMap.constBegin();
while ( i != sgMap.constEnd() )
{
QStandardItem *item = new QStandardItem( i.value() );
item->setData( i.key() );
tag->appendRow( item );
smart->appendRow( item );
++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() ) );
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 )
{
QStringList symbolNames;
@ -922,42 +951,41 @@ void QgsStyleManagerDialog::groupChanged( const QModelIndex& index )
}
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 );
if ( category == QLatin1String( "groups" ) || category == QLatin1String( "smartgroups" ) )
if ( category == QLatin1String( "tags" ) || category == QLatin1String( "smartgroups" ) )
{
btnAddGroup->setEnabled( true );
actnAddGroup->setEnabled( true );
}
symbolNames = currentItemType() < 3 ? mStyle->symbolNames() : mStyle->colorRampNames();
}
else
else if ( category == QLatin1String( "favorite" ) )
{
//determine groups and tags
if ( index.parent().data( Qt::UserRole + 1 ) == "smartgroups" )
btnAddGroup->setEnabled( true );
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 );
actnAddGroup->setEnabled( false );
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 );
}
groupSymbols = symbolNames;
symbolNames = type == QgsStyle::SymbolEntity ? mStyle->symbolNames() : mStyle->colorRampNames();
}
}
@ -969,16 +997,19 @@ void QgsStyleManagerDialog::groupChanged( const QModelIndex& index )
{
populateColorRamps( symbolNames, mGrouppingMode );
}
if ( mGrouppingMode )
{
setSymbolsChecked( groupSymbols );
}
actnEditSmartGroup->setVisible( false );
actnAddGroup->setVisible( false );
actnRemoveGroup->setVisible( false );
actnGroupSymbols->setVisible( false );
actnFinishGrouping->setVisible( false );
actnTagSymbols->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" ) )
{
@ -987,12 +1018,12 @@ void QgsStyleManagerDialog::groupChanged( const QModelIndex& index )
else
{
actnAddGroup->setVisible( !mGrouppingMode );
actnGroupSymbols->setVisible( !mGrouppingMode );
actnFinishGrouping->setVisible( mGrouppingMode );
actnTagSymbols->setVisible( !mGrouppingMode );
actnFinishTagging->setVisible( mGrouppingMode );
}
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 );
}
@ -1001,11 +1032,11 @@ void QgsStyleManagerDialog::groupChanged( const QModelIndex& index )
void QgsStyleManagerDialog::addGroup()
{
QStandardItemModel *model = qobject_cast<QStandardItemModel*>( groupTree->model() );
QModelIndex parentIndex = groupTree->currentIndex();
QModelIndex index = groupTree->currentIndex();
// Violation 1: Creating sub-groups of system defined groups
QString parentData = parentIndex.data( Qt::UserRole + 1 ).toString();
if ( parentData == QLatin1String( "all" ) || ( parentIndex.data() == "Ungrouped" && parentData == QLatin1String( "0" ) ) )
// don't allow creation of tag/smartgroup against system-defined groupings
QString data = index.data( Qt::UserRole + 1 ).toString();
if ( data == QLatin1String( "all" ) || data == "favorite" )
{
int err = QMessageBox::critical( this, tr( "Invalid Selection" ),
tr( "The parent group you have selected is not user editable.\n"
@ -1014,24 +1045,19 @@ void QgsStyleManagerDialog::addGroup()
return;
}
// Violation 2: Creating a nested tag
if ( parentIndex.parent().data( Qt::UserRole + 1 ).toString() == QLatin1String( "smartgroups" ) )
QString itemName;
int id;
//
if ( index.parent() != QModelIndex() )
{
int err = QMessageBox::critical( this, tr( "Operation Not Allowed" ),
tr( "Creation of nested smart groups are not allowed\n"
"Select the 'Smart Group' to create a new group." ) );
if ( err )
return;
index = index.parent();
data = index.data( Qt::UserRole + 1 ).toString();
}
QString itemName;
bool isGroup = true;
int id;
if ( parentData == QLatin1String( "smartgroups" ) )
if ( data == QLatin1String( "smartgroups" ) )
{
// create a smart group
// create a smartgroup
QgsSmartGroupEditorDialog dlg( mStyle, this );
if ( dlg.exec() == QDialog::Rejected )
return;
@ -1039,34 +1065,39 @@ void QgsStyleManagerDialog::addGroup()
if ( !id )
return;
itemName = dlg.smartgroupName();
isGroup = false;
}
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 parentid = ( parentData == QLatin1String( "groups" ) ) ? 0 : parentData.toInt(); // parentid is 0 for top-level groups
id = mStyle->addGroup( itemName, parentid );
int check = mStyle->tagId( itemName );
if ( check > 0 )
{
QMessageBox::critical( this, tr( "Error!" ),
tr( "Tag name already exists in your symbol database." ) );
return;
}
id = mStyle->addTag( itemName );
if ( !id )
{
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." ) );
return;
}
}
QStandardItem *parentItem = model->itemFromIndex( parentIndex );
QStandardItem *parentItem = model->itemFromIndex( index );
QStandardItem *childItem = new QStandardItem( itemName );
childItem->setData( id );
parentItem->appendRow( childItem );
groupTree->setCurrentIndex( childItem->index() );
if ( isGroup )
{
groupTree->edit( childItem->index() );
}
}
void QgsStyleManagerDialog::removeGroup()
@ -1074,9 +1105,9 @@ void QgsStyleManagerDialog::removeGroup()
QStandardItemModel *model = qobject_cast<QStandardItemModel*>( groupTree->model() );
QModelIndex index = groupTree->currentIndex();
// Violation: removing system groups
// do not allow removal of system-defined groupings
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" ),
tr( "Cannot delete system defined categories.\n"
@ -1092,16 +1123,7 @@ void QgsStyleManagerDialog::removeGroup()
}
else
{
mStyle->remove( QgsStyle::GroupEntity, 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 ) );
}
}
mStyle->remove( QgsStyle::TagEntity, index.data( Qt::UserRole + 1 ).toInt() );
}
parentItem->removeRow( index.row() );
}
@ -1117,11 +1139,11 @@ void QgsStyleManagerDialog::groupRenamed( QStandardItem * item )
}
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() );
@ -1130,8 +1152,8 @@ void QgsStyleManagerDialog::groupSymbolsAction()
if ( mGrouppingMode )
{
mGrouppingMode = false;
actnGroupSymbols->setVisible( true );
actnFinishGrouping->setVisible( false );
actnTagSymbols->setVisible( true );
actnFinishTagging->setVisible( false );
// disconnect slot which handles regrouping
disconnect( model, SIGNAL( itemChanged( QStandardItem* ) ),
this, SLOT( regrouped( QStandardItem* ) ) );
@ -1155,21 +1177,20 @@ void QgsStyleManagerDialog::groupSymbolsAction()
QModelIndex present = groupTree->currentIndex();
while ( present.parent().isValid() )
{
if ( present.parent().data() == "Groups" )
if ( present.parent().data() == "Tags" )
{
validGroup = true;
break;
}
else
present = present.parent();
present = present.parent();
}
if ( !validGroup )
return;
mGrouppingMode = true;
// Change visibility of actions
actnGroupSymbols->setVisible( false );
actnFinishGrouping->setVisible( true );
actnTagSymbols->setVisible( false );
actnFinishTagging->setVisible( true );
// Remove all Symbol editing functionalities
disconnect( treeModel, SIGNAL( itemChanged( QStandardItem* ) ),
this, SLOT( groupRenamed( QStandardItem* ) ) );
@ -1199,20 +1220,23 @@ void QgsStyleManagerDialog::regrouped( QStandardItem *item )
QgsDebugMsg( "Unknown style entity" );
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();
bool regrouped;
if ( item->checkState() == Qt::Checked )
regrouped = mStyle->group( type, symbolName, groupid );
regrouped = mStyle->tagSymbol( type, symbolName, QStringList( tag ) );
else
regrouped = mStyle->group( type, symbolName, 0 );
regrouped = mStyle->detagSymbol( type, symbolName, QStringList( tag ) );
if ( !regrouped )
{
int er = QMessageBox::critical( this, tr( "Database Error" ),
tr( "There was a problem with the Symbols database while regrouping." ) );
// call the slot again to get back to normal
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 )
{
// 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 );
}
@ -1314,8 +1277,10 @@ void QgsStyleManagerDialog::selectedSymbolsChanged( const QItemSelection& select
Q_UNUSED( deselected );
bool nothingSelected = listItems->selectionModel()->selectedIndexes().empty();
actnRemoveItem->setDisabled( nothingSelected );
actnAddFavorite->setDisabled( nothingSelected );
actnRemoveFavorite->setDisabled( nothingSelected );
mGroupListMenu->setDisabled( nothingSelected );
actnUngroup->setDisabled( nothingSelected );
actnDetag->setDisabled( nothingSelected );
actnExportAsPNG->setDisabled( nothingSelected );
actnExportAsSVG->setDisabled( nothingSelected );
actnEditItem->setDisabled( nothingSelected );
@ -1330,7 +1295,6 @@ void QgsStyleManagerDialog::enableSymbolInputs( bool enable )
actnRemoveGroup->setEnabled( enable );
btnManageGroups->setEnabled( enable || mGrouppingMode ); // always enabled in grouping mode, as it is the only way to leave grouping mode
searchBox->setEnabled( enable );
tagsLineEdit->setEnabled( enable );
}
void QgsStyleManagerDialog::enableGroupInputs( bool enable )
@ -1346,19 +1310,8 @@ void QgsStyleManagerDialog::enableItemsForGroupingMode( bool enable )
QStandardItemModel *treeModel = qobject_cast<QStandardItemModel*>( groupTree->model() );
for ( int i = 0; i < treeModel->rowCount(); i++ )
{
if ( treeModel->item( i )->data() != "groups" )
{
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 );
}
}
treeModel->item( i )->setEnabled( enable );
if ( treeModel->item( i )->data() == "smartgroups" )
{
for ( int j = 0; j < treeModel->item( i )->rowCount(); j++ )
@ -1401,19 +1354,54 @@ void QgsStyleManagerDialog::listitemsContextMenu( QPoint point )
mGroupListMenu->clear();
QAction* a;
QList<int> groupIds = mStyle->groupIds();
Q_FOREACH ( int groupId, groupIds )
QStringList tags = mStyle->tags();
tags.sort();
Q_FOREACH ( const QString& tag, tags )
{
a = new QAction( mStyle->groupName( groupId ), mGroupListMenu );
a->setData( groupId );
connect( a, SIGNAL( triggered( bool ) ), this, SLOT( groupSelectedSymbols() ) );
a = new QAction( tag, mGroupListMenu );
a->setData( tag );
connect( a, SIGNAL( triggered( bool ) ), this, SLOT( tagSelectedSymbols() ) );
mGroupListMenu->addAction( a );
}
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() );
@ -1425,11 +1413,34 @@ void QgsStyleManagerDialog::groupSelectedSymbols()
QgsDebugMsg( "unknown entity type" );
return;
}
int groupId = selectedItem->data().toInt();
QString tag = selectedItem->data().toString();
QModelIndexList indexes = listItems->selectionModel()->selectedIndexes();
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();
@ -1474,14 +1485,4 @@ void QgsStyleManagerDialog::editSmartgroupAction()
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 removeGroup();
//! carryout symbol grouping using check boxes
void groupSymbolsAction();
//! carry out symbol tagging using check boxes
void tagSymbolsAction();
//! edit the selected smart group
void editSmartgroupAction();
@ -78,9 +78,6 @@ class GUI_EXPORT QgsStyleManagerDialog : public QDialog, private Ui::QgsStyleMan
//! filter the symbols based on input search term
void filterSymbols( const QString& );
//! Listen to tag changes
void tagsChanged();
//! Perform symbol specific tasks when selected
void symbolSelected( const QModelIndex& );
@ -95,7 +92,14 @@ class GUI_EXPORT QgsStyleManagerDialog : public QDialog, private Ui::QgsStyleMan
protected slots:
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:
@ -104,8 +108,6 @@ class GUI_EXPORT QgsStyleManagerDialog : public QDialog, private Ui::QgsStyleMan
//! populate the groups
void populateGroups();
//! build the groups tree
void buildGroupTree( QStandardItem* &parent );
//! to set symbols checked when in editing mode
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
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
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 "qgsstylemanagerdialog.h"
#include "qgsstylesavedialog.h"
#include "qgsdatadefined.h"
#include "qgssymbol.h"
@ -29,6 +30,8 @@
#include "qgsapplication.h"
#include "qgsvectorlayer.h"
#include <QAction>
#include <QSettings>
#include <QString>
#include <QStringList>
#include <QPainter>
@ -38,6 +41,7 @@
#include <QInputDialog>
#include <QMessageBox>
#include <QMenu>
#include <QPushButton>
#include <QScopedPointer>
@ -67,26 +71,20 @@ QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbol* symbol, QgsStyle* style,
}
mClipFeaturesAction = new QAction( tr( "Clip features to canvas extent" ), this );
mClipFeaturesAction->setCheckable( true );
connect( mClipFeaturesAction, SIGNAL( toggled( bool ) ), this, SLOT( clipFeaturesToggled( bool ) ) );
// populate the groups
groupsCombo->addItem( QLatin1String( "" ) );
populateGroups();
QStringList groups = style->smartgroupNames();
Q_FOREACH ( const QString& group, groups )
{
groupsCombo->addItem( group, QVariant( "smart" ) );
}
connect( mClipFeaturesAction, &QAction::toggled, this, &QgsSymbolsListWidget::clipFeaturesToggled );
QStandardItemModel* model = new QStandardItemModel( viewSymbols );
viewSymbols->setModel( model );
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( openStyleManagerButton, SIGNAL( pressed() ), this, SLOT( openStyleManager() ) );
connect( mStyle, &QgsStyle::symbolSaved , this, &QgsSymbolsListWidget::symbolAddedToStyle );
connect( mStyle, &QgsStyle::groupsModified , this, &QgsSymbolsListWidget::populateGroups );
connect( openStyleManagerButton, &QPushButton::pressed, this, &QgsSymbolsListWidget::openStyleManager );
lblSymbolName->setText( QLatin1String( "" ) );
populateSymbolView();
populateGroups();
if ( mSymbol )
{
@ -119,7 +117,7 @@ QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbol* symbol, QgsStyle* style,
btnColor->setColorDialogTitle( tr( "Select color" ) );
btnColor->setContext( QStringLiteral( "symbology" ) );
connect( btnSaveSymbol, SIGNAL( clicked() ), this, SLOT( saveSymbol() ) );
connect( btnSaveSymbol, &QPushButton::clicked, this, &QgsSymbolsListWidget::saveSymbol );
}
QgsSymbolsListWidget::~QgsSymbolsListWidget()
@ -148,30 +146,72 @@ QgsSymbolWidgetContext QgsSymbolsListWidget::context() const
return mContext;
}
void QgsSymbolsListWidget::populateGroups( const QString& parent, const QString& prepend )
void QgsSymbolsListWidget::populateGroups()
{
QgsSymbolGroupMap groups = mStyle->childGroupNames( parent );
QgsSymbolGroupMap::const_iterator i = groups.constBegin();
while ( i != groups.constEnd() )
groupsCombo->blockSignals( true );
groupsCombo->clear();
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;
if ( !prepend.isEmpty() )
tags.sort();
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()
{
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 )
@ -357,30 +397,34 @@ void QgsSymbolsListWidget::addSymbolToStyle()
void QgsSymbolsListWidget::saveSymbol()
{
bool ok;
QString name = QInputDialog::getText( this, tr( "Symbol name" ),
tr( "Please enter name for the symbol:" ), QLineEdit::Normal, tr( "New symbol" ), &ok );
if ( !ok || name.isEmpty() )
QgsStyleSaveDialog saveDlg( this );
if ( !saveDlg.exec() )
return;
if ( saveDlg.name().isEmpty() )
return;
// 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" ),
tr( "Symbol with name '%1' already exists. Overwrite?" )
.arg( name ),
.arg( saveDlg.name() ),
QMessageBox::Yes | QMessageBox::No );
if ( res != QMessageBox::Yes )
{
return;
}
mStyle->removeSymbol( saveDlg.name() );
}
QStringList symbolTags = saveDlg.tags().split( ',' );
// 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
mStyle->saveSymbol( name, mSymbol->clone(), 0, QStringList() );
mStyle->saveSymbol( saveDlg.name(), mSymbol->clone(), saveDlg.isFavorite(), symbolTags );
}
void QgsSymbolsListWidget::on_mSymbolUnitWidget_changed()
@ -537,7 +581,7 @@ void QgsSymbolsListWidget::setSymbolFromStyle( const QModelIndex & index )
// get new instance of symbol from style
QgsSymbol* s = mStyle->symbol( symbolName );
QgsUnitTypes::RenderUnit unit = s->outputUnit();
// remove all symbol layers from original symbol
// remove all symbol layers from original symbolgroupsCombo
while ( mSymbol->symbolLayerCount() )
mSymbol->deleteSymbolLayer( 0 );
// move all symbol layers to our symbol
@ -557,32 +601,8 @@ void QgsSymbolsListWidget::setSymbolFromStyle( const QModelIndex & index )
void QgsSymbolsListWidget::on_groupsCombo_currentIndexChanged( int index )
{
QStringList symbols;
QString text = groupsCombo->itemText( 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 );
}
QSettings settings;
settings.setValue( QStringLiteral( "qgis/symbolsListGroupsIndex" ), index );
void QgsSymbolsListWidget::on_groupsCombo_editTextChanged( const QString &text )
{
QStringList symbols = mStyle->findSymbols( QgsStyle::SymbolEntity, text );
populateSymbols( symbols );
populateSymbolView();
}

View File

@ -67,12 +67,15 @@ class GUI_EXPORT QgsSymbolsListWidget : public QWidget, private Ui::SymbolsListW
void setLineWidth( double width );
void addSymbolToStyle();
void saveSymbol();
void symbolAddedToStyle( const QString& name, QgsSymbol* symbol );
void on_mSymbolUnitWidget_changed();
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_editTextChanged( const QString &text );
void openStyleManager();
void clipFeaturesToggled( bool checked );
@ -99,8 +102,6 @@ class GUI_EXPORT QgsSymbolsListWidget : public QWidget, private Ui::SymbolsListW
//! Displays alpha value as transparency in mTransparencyLabel
void displayTransparency( double alpha );
//! Recursive function to create the group tree in the widget
void populateGroups( const QString& parent = "", const QString& prepend = "" );
QgsSymbolWidgetContext mContext;

View File

@ -43,17 +43,33 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="groupLabel">
<item row="3" column="0">
<widget class="QLabel" name="tagLabel">
<property name="text">
<string>Save to group</string>
<string>Tag(s)</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QComboBox" name="groupCombo">
<property name="editable">
<bool>true</bool>
<item row="2" column="0" colspan="3">
<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="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>
</widget>
</item>

View File

@ -380,26 +380,6 @@ QMenu::item:selected { background-color: gray; } */
</property>
</widget>
</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>
</item>
</layout>
@ -450,15 +430,37 @@ QMenu::item:selected { background-color: gray; } */
<string>Edit item</string>
</property>
</action>
<action name="actnUngroup">
<action name="actnAddFavorite">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Ungroup</string>
<string>Add to favorites</string>
</property>
<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>
</action>
<action name="actnEditSmartGroup">
@ -484,17 +486,17 @@ QMenu::item:selected { background-color: gray; } */
<string>Remove group</string>
</property>
</action>
<action name="actnGroupSymbols">
<action name="actnTagSymbols">
<property name="text">
<string>Group symbols</string>
<string>Attach selected tag to symbols</string>
</property>
</action>
<action name="actnFinishGrouping">
<action name="actnFinishTagging">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Finish grouping</string>
<string>Finish tagging</string>
</property>
<property name="visible">
<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>
<widget class="QLabel" name="label">
<property name="text">
<string>Symbols in group</string>
<string>Symbols in</string>
</property>
</widget>
</item>
@ -131,17 +131,11 @@
</item>
<item>
<widget class="QPushButton" name="btnSaveSymbol">
<property name="maximumSize">
<size>
<width>70</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Save symbol</string>
</property>
<property name="text">
<string>Save</string>
<string>Save symbol</string>
</property>
</widget>
</item>

View File

@ -65,6 +65,7 @@ class TestStyle : public QObject
void testCreateColorRamps();
void testLoadColorRamps();
void testSaveLoad();
void testFavorites();
void testTags();
};
@ -258,6 +259,35 @@ void TestStyle::testSaveLoad()
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()
{
mStyle->clear();
@ -289,7 +319,7 @@ void TestStyle::testTags()
QVERIFY( !tags.contains( "purple" ) );
//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( "red circle" ), QgsMarkerSymbol::createSimple( QgsStringMap() ), true );