Skip to content

Commit e624518

Browse files
authoredNov 17, 2016
Merge pull request #3755 from nirvn/style_manager_upgrade
[FEATURE] Style management re-work and upgrade
2 parents 964ecfd + 5e487cf commit e624518

30 files changed

+1186
-929
lines changed
 

‎doc/api_break.dox

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,11 @@ QgsSvgCache {#qgis_api_break_3_0_QgsSvgCache}
13711371

13721372
- containsParamsV2() was removed. Use containsParamsV3() instead.
13731373

1374+
QgsStyle (renamed from QgsStyleV2) {#qgis_api_break_3_0_QgsStyle}
1375+
----------------------------------
1376+
- All group functions have been removed: group(), addGroup(), groupId(), groupName(), groupNames(), groupIds(), symbolsOfGroup(), getGroupRemoveQuery()
1377+
- The StyleEntity::GroupEntity has been removed
1378+
- The SymgroupTable enum has been removed
13741379

13751380
QgsSymbol (renamed from QgsSymbolV2) {#qgis_api_break_3_0_QgsSymbol}
13761381
------------------------------------

‎python/core/symbology-ng/qgsstyle.sip

Lines changed: 98 additions & 102 deletions
Large diffs are not rendered by default.

‎python/gui/gui.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@
247247
%Include symbology-ng/qgsstyleexportimportdialog.sip
248248
%Include symbology-ng/qgsstylegroupselectiondialog.sip
249249
%Include symbology-ng/qgsstylemanagerdialog.sip
250+
%Include symbology-ng/qgsstylesavedialog.sip
250251
%Include symbology-ng/qgssvgselectorwidget.sip
251252
%Include symbology-ng/qgssymbollayerwidget.sip
252253
%Include symbology-ng/qgssymbollevelsdialog.sip

‎python/gui/symbology-ng/qgsstyleexportimportdialog.sip

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ class QgsStyleExportImportDialog : QDialog
4141
*/
4242
void clearSelection();
4343
/**
44-
* Select the symbols belonging to the given group
45-
* @param groupName the name of the group to be selected
44+
* Select the symbols belonging to the given tag
45+
* @param tagName the name of the tag to be selected
4646
*/
47-
void selectGroup( const QString& groupName );
47+
void selectTag( const QString& tagName );
4848
/**
49-
* Deselect the symbols belonging to the given group
50-
* @param groupName the name of the group to be deselected
49+
* Deselect the symbols belonging to the given tag
50+
* @param tagName the name of the tag to be deselected
5151
*/
52-
void deselectGroup( const QString& groupName );
52+
void deselectTag( const QString& tagName );
5353
/**
5454
* @brief selectSmartgroup selects all symbols from a smart group
5555
* @param groupName

‎python/gui/symbology-ng/qgsstylegroupselectiondialog.sip

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ class QgsStyleGroupSelectionDialog : public QDialog, private Ui::SymbolsGroupSel
2828
void setBold( QStandardItem *item );
2929

3030
signals:
31-
//! group with groupName has been selected
32-
void groupSelected( const QString& groupName );
33-
//! group with groupName has been deselected
34-
void groupDeselected( const QString& groupName );
31+
//! tag with tagName has been selected
32+
void tagSelected( const QString& tagName );
33+
//! tag with tagName has been deselected
34+
void tagDeselected( const QString& tagName );
3535
//! smartgroup with groupName has been selected
3636
void smartgroupSelected( const QString& groupName );
3737
//! smart group with groupName has been deselected

‎python/gui/symbology-ng/qgsstylemanagerdialog.sip

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ class QgsStyleManagerDialog : QDialog
3737
void addGroup();
3838
void removeGroup();
3939

40-
//! carryout symbol grouping using check boxes
41-
void groupSymbolsAction();
40+
//! carry out symbol tagging using check boxes
41+
void tagSymbolsAction();
4242

4343
//! edit the selected smart group
4444
void editSmartgroupAction();
@@ -49,9 +49,6 @@ class QgsStyleManagerDialog : QDialog
4949
//! filter the symbols based on input search term
5050
void filterSymbols( const QString& );
5151

52-
//! Listen to tag changes
53-
void tagsChanged();
54-
5552
//! Perform symbol specific tasks when selected
5653
void symbolSelected( const QModelIndex& );
5754

@@ -66,7 +63,14 @@ class QgsStyleManagerDialog : QDialog
6663

6764
protected slots:
6865
bool addColorRamp( QAction* action );
69-
void groupSelectedSymbols();
66+
//! Add selected symbols to favorites
67+
void addFavoriteSelectedSymbols();
68+
//! Remove selected symbols from favorites
69+
void removeFavoriteSelectedSymbols();
70+
//! Tag selected symbols using menu item selection
71+
void tagSelectedSymbols();
72+
//! Remove all tags from selected symbols
73+
void detagSelectedSymbols();
7074

7175
protected:
7276

@@ -75,8 +79,6 @@ class QgsStyleManagerDialog : QDialog
7579

7680
//! populate the groups
7781
void populateGroups();
78-
//! build the groups tree
79-
void buildGroupTree( QStandardItem* &parent );
8082
//! to set symbols checked when in editing mode
8183
void setSymbolsChecked( const QStringList& );
8284

@@ -107,9 +109,6 @@ class QgsStyleManagerDialog : QDialog
107109
//! Enables or diables the groupTree items for grouping mode
108110
void enableItemsForGroupingMode( bool );
109111

110-
//! Event filter to capture tagsLineEdit out of focus
111-
bool eventFilter( QObject*, QEvent* );
112-
113112
//! sets the text of the item with bold font
114113
void setBold( QStandardItem* );
115114
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
class QgsStyleSaveDialog : QDialog
2+
{
3+
%TypeHeaderCode
4+
#include <qgsstylesavedialog.h>
5+
%End
6+
7+
public:
8+
/** Constructor for QgsSymbolSaveDialog
9+
* @param parent parent widget
10+
* @param type the QgsStyle entity type being saved
11+
*/
12+
QgsStyleSaveDialog( QWidget* parent /TransferThis/ = NULL, QgsStyle::StyleEntity type = QgsStyle::SymbolEntity );
13+
14+
//! returns the text value of the name element
15+
QString name() const;
16+
17+
//! returns the text value of the tags element
18+
QString tags() const;
19+
20+
//! returns whether the favorite element is checked
21+
bool isFavorite() const;
22+
};

‎python/gui/symbology-ng/qgssymbolslistwidget.sip

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@ class QgsSymbolsListWidget : QWidget
3737
void on_mSymbolUnitWidget_changed();
3838
void on_mTransparencySlider_valueChanged( int value );
3939

40+
//! Pupulates the groups combo box with available tags and smartgroups
41+
void populateGroups();
4042
void on_groupsCombo_currentIndexChanged( int index );
41-
void on_groupsCombo_editTextChanged( const QString &text );
4243

4344
void openStyleManager();
4445
void clipFeaturesToggled( bool checked );

‎resources/symbology-ng-style.db

20 KB
Binary file not shown.

‎resources/symbology-ng-style.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,7 @@
838838
<prop k="width_unit" v="MM"/>
839839
</layer>
840840
</symbol>
841-
<symbol alpha="1" type="marker" name="airport">
841+
<symbol alpha="1" type="marker" name="airport" favorite="1">
842842
<layer pass="0" class="SvgMarker" locked="0">
843843
<prop k="angle" v="0"/>
844844
<prop k="fill" v="#000000"/>

‎scripts/symbol_xml2db.py

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@
3232
"id INTEGER PRIMARY KEY,"\
3333
"name TEXT UNIQUE,"\
3434
"xml TEXT,"\
35-
"groupid INTEGER)"
35+
"favorite INTEGER)"
3636

3737
_colorramp = "CREATE TABLE colorramp("\
3838
"id INTEGER PRIMARY KEY,"\
3939
"name TEXT UNIQUE,"\
4040
"xml TEXT,"\
41-
"groupid INTEGER)"
41+
"favorite INTEGER)"
4242

4343
_tag = "CREATE TABLE tag("\
4444
"id INTEGER PRIMARY KEY,"\
@@ -48,57 +48,60 @@
4848
"tag_id INTEGER NOT NULL,"\
4949
"symbol_id INTEGER)"
5050

51-
_symgroup = "CREATE TABLE symgroup("\
52-
"id INTEGER PRIMARY KEY,"\
53-
"name TEXT,"\
54-
"parent INTEGER)"
51+
_ctagmap = "CREATE TABLE ctagmap("\
52+
"tag_id INTEGER NOT NULL,"\
53+
"colorramp_id INTEGER)"
5554

5655
_smartgroup = "CREATE TABLE smartgroup("\
5756
"id INTEGER PRIMARY KEY,"\
5857
"name TEXT,"\
5958
"xml TEXT)"
6059

61-
_ctagmap = "CREATE TABLE ctagmap("\
62-
"tag_id INTEGER NOT NULL,"\
63-
"colorramp_id INTEGER)"
64-
65-
create_tables = [ _symbol, _colorramp, _tag, _tagmap, _ctagmap, _symgroup, _smartgroup ]
60+
create_tables = [_symbol, _colorramp, _tag, _tagmap, _ctagmap, _smartgroup]
6661

6762
# Create the DB with required Schema
68-
conn = sqlite3.connect( dbfile )
63+
conn = sqlite3.connect(dbfile)
6964
c = conn.cursor()
7065
print "Creating tables in the Database\n"
7166
for table in create_tables:
7267
try:
73-
c.execute( table )
68+
c.execute(table)
7469
print table
7570
except sqlite3.OperationalError as e:
7671
pass
7772
conn.commit()
7873

7974
# parse the XML file & write symbol into DB
80-
dom = parse( xmlfile )
81-
symbols = dom.getElementsByTagName( "symbol" )
75+
dom = parse(xmlfile)
76+
symbols = dom.getElementsByTagName("symbol")
8277
for symbol in symbols:
83-
symbol_name = symbol.getAttribute( "name" )
78+
symbol_name = symbol.getAttribute("name")
79+
symbol_favorite = symbol.getAttribute("favorite")
80+
if not symbol_favorite:
81+
symbol_favorite = 0
82+
8483
if '@' in symbol_name:
8584
parts = symbol_name.split('@')
8685
parent_name = parts[1]
8786
layerno = int(parts[2])
88-
c.execute( "SELECT xml FROM symbol WHERE name=(?)", (parent_name,) )
89-
symdom = parseString( c.fetchone()[0] ).getElementsByTagName( 'symbol' )[0]
90-
symdom.getElementsByTagName( "layer" )[ layerno ].appendChild( symbol )
91-
c.execute( "UPDATE symbol SET xml=? WHERE name=?", ( symdom.toxml(), parent_name ))
87+
c.execute("SELECT xml FROM symbol WHERE name=(?)", (parent_name,))
88+
symdom = parseString(c.fetchone()[0]).getElementsByTagName('symbol')[0]
89+
symdom.getElementsByTagName("layer")[layerno].appendChild(symbol)
90+
c.execute("UPDATE symbol SET xml=? WHERE name=?", (symdom.toxml(), parent_name))
9291
else:
93-
c.execute( "INSERT INTO symbol VALUES (?,?,?,?)", ( None, symbol_name, symbol.toxml(), 0 ) )
92+
c.execute("INSERT INTO symbol VALUES (?,?,?,?)", (None, symbol_name, symbol.toxml(), symbol_favorite))
9493
conn.commit()
9594

9695

9796
# ColorRamps
98-
colorramps = dom.getElementsByTagName( "colorramp" )
97+
colorramps = dom.getElementsByTagName("colorramp")
9998
for ramp in colorramps:
100-
ramp_name = ramp.getAttribute( "name" )
101-
c.execute( "INSERT INTO colorramp VALUES (?,?,?,?)", ( None, ramp_name, ramp.toxml(), 0 ) )
99+
ramp_name = ramp.getAttribute("name")
100+
symbol_favorite = symbol.getAttribute("favorite")
101+
if not symbol_favorite:
102+
symbol_favorite = 0
103+
104+
c.execute("INSERT INTO colorramp VALUES (?,?,?,?)", (None, ramp_name, ramp.toxml(), symbol_favorite))
102105
conn.commit()
103106

104107
# Finally close the sqlite cursor

‎src/core/symbology-ng/qgsstyle.cpp

Lines changed: 150 additions & 192 deletions
Large diffs are not rendered by default.

‎src/core/symbology-ng/qgsstyle.h

Lines changed: 120 additions & 123 deletions
Large diffs are not rendered by default.

‎src/gui/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ SET(QGIS_GUI_SRCS
3838
symbology-ng/qgsstyleexportimportdialog.cpp
3939
symbology-ng/qgsstylegroupselectiondialog.cpp
4040
symbology-ng/qgsstylemanagerdialog.cpp
41+
symbology-ng/qgsstylesavedialog.cpp
4142
symbology-ng/qgssvgselectorwidget.cpp
4243
symbology-ng/qgssymbollayerwidget.cpp
4344
symbology-ng/qgssymbollevelsdialog.cpp
@@ -511,6 +512,7 @@ SET(QGIS_GUI_MOC_HDRS
511512
symbology-ng/qgsstyleexportimportdialog.h
512513
symbology-ng/qgsstylegroupselectiondialog.h
513514
symbology-ng/qgsstylemanagerdialog.h
515+
symbology-ng/qgsstylesavedialog.h
514516
symbology-ng/qgssvgselectorwidget.h
515517
symbology-ng/qgssymbollayerwidget.h
516518
symbology-ng/qgssymbollevelsdialog.h

‎src/gui/symbology-ng/qgssmartgroupeditordialog.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,8 @@ QgsSmartGroupCondition::QgsSmartGroupCondition( int id, QWidget* parent ) : QWid
3131
mConditionId = id;
3232

3333
mCondCombo->addItem( tr( "has the tag" ), QVariant( "tag" ) );
34-
mCondCombo->addItem( tr( "is a member of group" ), QVariant( "group" ) );
3534
mCondCombo->addItem( tr( "has a part of name matching" ), QVariant( "name" ) );
3635
mCondCombo->addItem( tr( "does NOT have the tag" ), QVariant( "!tag" ) );
37-
mCondCombo->addItem( tr( "is NOT a member of group" ), QVariant( "!group" ) );
3836
mCondCombo->addItem( tr( "has NO part of name matching" ), QVariant( "!name" ) );
3937

4038
mRemoveBtn->setIcon( QIcon( QgsApplication::iconPath( "symbologyRemove.svg" ) ) );
@@ -159,7 +157,7 @@ QString QgsSmartGroupEditorDialog::conditionOperator()
159157
void QgsSmartGroupEditorDialog::setConditionMap( const QgsSmartConditionMap& map )
160158
{
161159
QStringList constraints;
162-
constraints << QStringLiteral( "tag" ) << QStringLiteral( "group" ) << QStringLiteral( "name" ) << QStringLiteral( "!tag" ) << QStringLiteral( "!group" ) << QStringLiteral( "!name" );
160+
constraints << QStringLiteral( "tag" ) << QStringLiteral( "name" ) << QStringLiteral( "!tag" ) << QStringLiteral( "!name" );
163161

164162
// clear any defaults
165163
Q_FOREACH ( int id, mConditionMap.keys() )

‎src/gui/symbology-ng/qgsstyleexportimportdialog.cpp

Lines changed: 31 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
QgsStyleExportImportDialog::QgsStyleExportImportDialog( QgsStyle* style, QWidget *parent, Mode mode )
3636
: QDialog( parent )
3737
, mDialogMode( mode )
38-
, mQgisStyle( style )
38+
, mStyle( style )
3939
{
4040
setupUi( this );
4141

@@ -73,12 +73,7 @@ QgsStyleExportImportDialog::QgsStyleExportImportDialog( QgsStyle* style, QWidget
7373
importTypeCombo->addItem( tr( "URL specified below" ), QVariant( "url" ) );
7474
connect( importTypeCombo, SIGNAL( currentIndexChanged( int ) ), this, SLOT( importTypeChanged( int ) ) );
7575

76-
QStringList groups = mQgisStyle->groupNames();
77-
groupCombo->addItem( QStringLiteral( "imported" ), QVariant( "new" ) );
78-
Q_FOREACH ( const QString& gName, groups )
79-
{
80-
groupCombo->addItem( gName );
81-
}
76+
mSymbolTags->setText( "imported" );
8277

8378
btnBrowse->setText( QStringLiteral( "Browse" ) );
8479
connect( btnBrowse, SIGNAL( clicked() ), this, SLOT( browse() ) );
@@ -96,14 +91,17 @@ QgsStyleExportImportDialog::QgsStyleExportImportDialog( QgsStyle* style, QWidget
9691
locationLabel->setHidden( true );
9792
locationLineEdit->setHidden( true );
9893

94+
mFavorite->setHidden( true );
95+
9996
pb = new QPushButton( tr( "Select by group" ) );
10097
buttonBox->addButton( pb, QDialogButtonBox::ActionRole );
10198
connect( pb, SIGNAL( clicked() ), this, SLOT( selectByGroup() ) );
102-
groupLabel->setHidden( true );
103-
groupCombo->setHidden( true );
99+
tagLabel->setHidden( true );
100+
mSymbolTags->setHidden( true );
101+
tagHintLabel->setHidden( true );
104102

105103
buttonBox->button( QDialogButtonBox::Ok )->setText( tr( "Export" ) );
106-
if ( !populateStyles( mQgisStyle ) )
104+
if ( !populateStyles( mStyle ) )
107105
{
108106
QApplication::postEvent( this, new QCloseEvent() );
109107
}
@@ -142,7 +140,7 @@ void QgsStyleExportImportDialog::doExportImport()
142140

143141
mFileName = fileName;
144142

145-
moveStyles( &selection, mQgisStyle, mTempStyle );
143+
moveStyles( &selection, mStyle, mTempStyle );
146144
if ( !mTempStyle->exportXml( mFileName ) )
147145
{
148146
QMessageBox::warning( this, tr( "Export/import error" ),
@@ -153,7 +151,7 @@ void QgsStyleExportImportDialog::doExportImport()
153151
}
154152
else // import
155153
{
156-
moveStyles( &selection, mTempStyle, mQgisStyle );
154+
moveStyles( &selection, mTempStyle, mStyle );
157155

158156
// clear model
159157
QStandardItemModel* model = qobject_cast<QStandardItemModel*>( listItems->model() );
@@ -222,26 +220,13 @@ void QgsStyleExportImportDialog::moveStyles( QModelIndexList* selection, QgsStyl
222220
bool isSymbol = true;
223221
bool prompt = true;
224222
bool overwrite = true;
225-
int groupid = 0;
223+
QStringList tags;
226224

227225
// get the groupid when going for import
228226
if ( mDialogMode == Import )
229227
{
230228
// get the name the user entered
231-
QString name = groupCombo->currentText();
232-
if ( name.isEmpty() )
233-
{
234-
// import to "ungrouped"
235-
groupid = 0;
236-
}
237-
else if ( dst->groupNames().contains( name ) )
238-
{
239-
groupid = dst->groupId( name );
240-
}
241-
else
242-
{
243-
groupid = dst->addGroup( name );
244-
}
229+
tags = mSymbolTags->text().split( ',' );
245230
}
246231

247232
for ( int i = 0; i < selection->size(); ++i )
@@ -272,7 +257,7 @@ void QgsStyleExportImportDialog::moveStyles( QModelIndexList* selection, QgsStyl
272257
case QMessageBox::Yes:
273258
dst->addSymbol( symbolName, symbol );
274259
if ( mDialogMode == Import )
275-
dst->saveSymbol( symbolName, symbol, groupid, QStringList() );
260+
dst->saveSymbol( symbolName, symbol, mFavorite->isChecked(), tags );
276261
continue;
277262
case QMessageBox::YesToAll:
278263
prompt = false;
@@ -289,7 +274,7 @@ void QgsStyleExportImportDialog::moveStyles( QModelIndexList* selection, QgsStyl
289274
{
290275
dst->addSymbol( symbolName, symbol );
291276
if ( mDialogMode == Import )
292-
dst->saveSymbol( symbolName, symbol, groupid, QStringList() );
277+
dst->saveSymbol( symbolName, symbol, mFavorite->isChecked(), tags );
293278
}
294279
else if ( dst->symbolNames().contains( symbolName ) && !overwrite )
295280
{
@@ -299,7 +284,7 @@ void QgsStyleExportImportDialog::moveStyles( QModelIndexList* selection, QgsStyl
299284
{
300285
dst->addSymbol( symbolName, symbol );
301286
if ( mDialogMode == Import )
302-
dst->saveSymbol( symbolName, symbol, groupid, QStringList() );
287+
dst->saveSymbol( symbolName, symbol, mFavorite->isChecked(), tags );
303288
}
304289
}
305290
else
@@ -319,7 +304,7 @@ void QgsStyleExportImportDialog::moveStyles( QModelIndexList* selection, QgsStyl
319304
case QMessageBox::Yes:
320305
dst->addColorRamp( symbolName, ramp );
321306
if ( mDialogMode == Import )
322-
dst->saveColorRamp( symbolName, ramp, groupid, QStringList() );
307+
dst->saveColorRamp( symbolName, ramp, mFavorite->isChecked(), tags );
323308
continue;
324309
case QMessageBox::YesToAll:
325310
prompt = false;
@@ -336,7 +321,7 @@ void QgsStyleExportImportDialog::moveStyles( QModelIndexList* selection, QgsStyl
336321
{
337322
dst->addColorRamp( symbolName, ramp );
338323
if ( mDialogMode == Import )
339-
dst->saveColorRamp( symbolName, ramp, groupid, QStringList() );
324+
dst->saveColorRamp( symbolName, ramp, mFavorite->isChecked(), tags );
340325
}
341326
else if ( dst->colorRampNames().contains( symbolName ) && !overwrite )
342327
{
@@ -346,7 +331,7 @@ void QgsStyleExportImportDialog::moveStyles( QModelIndexList* selection, QgsStyl
346331
{
347332
dst->addColorRamp( symbolName, ramp );
348333
if ( mDialogMode == Import )
349-
dst->saveColorRamp( symbolName, ramp, groupid, QStringList() );
334+
dst->saveColorRamp( symbolName, ramp, mFavorite->isChecked() , tags );
350335
}
351336
}
352337
}
@@ -394,47 +379,42 @@ void QgsStyleExportImportDialog::deselectSymbols( const QStringList& symbolNames
394379
}
395380
}
396381

397-
void QgsStyleExportImportDialog::selectGroup( const QString& groupName )
382+
void QgsStyleExportImportDialog::selectTag( const QString& tagName )
398383
{
399-
QStringList symbolNames = mQgisStyle->symbolsOfGroup( QgsStyle::SymbolEntity, mQgisStyle->groupId( groupName ) );
400-
selectSymbols( symbolNames );
401-
symbolNames = mQgisStyle->symbolsOfGroup( QgsStyle::ColorrampEntity, mQgisStyle->groupId( groupName ) );
384+
QStringList symbolNames = mStyle->symbolsWithTag( QgsStyle::SymbolEntity, mStyle->tagId( tagName ) );
402385
selectSymbols( symbolNames );
403386
}
404387

405-
406-
void QgsStyleExportImportDialog::deselectGroup( const QString& groupName )
388+
void QgsStyleExportImportDialog::deselectTag( const QString& tagName )
407389
{
408-
QStringList symbolNames = mQgisStyle->symbolsOfGroup( QgsStyle::SymbolEntity, mQgisStyle->groupId( groupName ) );
409-
deselectSymbols( symbolNames );
410-
symbolNames = mQgisStyle->symbolsOfGroup( QgsStyle::ColorrampEntity, mQgisStyle->groupId( groupName ) );
390+
QStringList symbolNames = mStyle->symbolsWithTag( QgsStyle::SymbolEntity, mStyle->tagId( tagName ) );
411391
deselectSymbols( symbolNames );
412392
}
413393

414394
void QgsStyleExportImportDialog::selectSmartgroup( const QString& groupName )
415395
{
416-
QStringList symbolNames = mQgisStyle->symbolsOfSmartgroup( QgsStyle::SymbolEntity, mQgisStyle->smartgroupId( groupName ) );
396+
QStringList symbolNames = mStyle->symbolsOfSmartgroup( QgsStyle::SymbolEntity, mStyle->smartgroupId( groupName ) );
417397
selectSymbols( symbolNames );
418-
symbolNames = mQgisStyle->symbolsOfSmartgroup( QgsStyle::ColorrampEntity, mQgisStyle->smartgroupId( groupName ) );
398+
symbolNames = mStyle->symbolsOfSmartgroup( QgsStyle::ColorrampEntity, mStyle->smartgroupId( groupName ) );
419399
selectSymbols( symbolNames );
420400
}
421401

422402
void QgsStyleExportImportDialog::deselectSmartgroup( const QString& groupName )
423403
{
424-
QStringList symbolNames = mQgisStyle->symbolsOfSmartgroup( QgsStyle::SymbolEntity, mQgisStyle->smartgroupId( groupName ) );
404+
QStringList symbolNames = mStyle->symbolsOfSmartgroup( QgsStyle::SymbolEntity, mStyle->smartgroupId( groupName ) );
425405
deselectSymbols( symbolNames );
426-
symbolNames = mQgisStyle->symbolsOfSmartgroup( QgsStyle::ColorrampEntity, mQgisStyle->smartgroupId( groupName ) );
406+
symbolNames = mStyle->symbolsOfSmartgroup( QgsStyle::ColorrampEntity, mStyle->smartgroupId( groupName ) );
427407
deselectSymbols( symbolNames );
428408
}
429409

430410
void QgsStyleExportImportDialog::selectByGroup()
431411
{
432412
if ( ! mGroupSelectionDlg )
433413
{
434-
mGroupSelectionDlg = new QgsStyleGroupSelectionDialog( mQgisStyle, this );
414+
mGroupSelectionDlg = new QgsStyleGroupSelectionDialog( mStyle, this );
435415
mGroupSelectionDlg->setWindowTitle( tr( "Select symbols by group" ) );
436-
connect( mGroupSelectionDlg, SIGNAL( groupSelected( const QString ) ), this, SLOT( selectGroup( const QString ) ) );
437-
connect( mGroupSelectionDlg, SIGNAL( groupDeselected( const QString ) ), this, SLOT( deselectGroup( const QString ) ) );
416+
connect( mGroupSelectionDlg, SIGNAL( tagSelected( const QString ) ), this, SLOT( selectTag( const QString ) ) );
417+
connect( mGroupSelectionDlg, SIGNAL( tagDeselected( const QString ) ), this, SLOT( deselectTag( const QString ) ) );
438418
connect( mGroupSelectionDlg, SIGNAL( allSelected() ), this, SLOT( selectAll() ) );
439419
connect( mGroupSelectionDlg, SIGNAL( allDeselected() ), this, SLOT( clearSelection() ) );
440420
connect( mGroupSelectionDlg, SIGNAL( smartgroupSelected( const QString ) ), this, SLOT( selectSmartgroup( const QString ) ) );
@@ -481,8 +461,8 @@ void QgsStyleExportImportDialog::browse()
481461
return;
482462
}
483463
QFileInfo pathInfo( mFileName );
484-
QString groupName = pathInfo.fileName().remove( QStringLiteral( ".xml" ) );
485-
groupCombo->setItemText( 0, groupName );
464+
QString tag = pathInfo.fileName().remove( QStringLiteral( ".xml" ) );
465+
mSymbolTags->setText( tag );
486466
locationLineEdit->setText( mFileName );
487467
populateStyles( mTempStyle );
488468
}

‎src/gui/symbology-ng/qgsstyleexportimportdialog.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,16 @@ class GUI_EXPORT QgsStyleExportImportDialog : public QDialog, private Ui::QgsSty
8080
void clearSelection();
8181

8282
/**
83-
* Select the symbols belonging to the given group
84-
* @param groupName the name of the group to be selected
83+
* Select the symbols belonging to the given tag
84+
* @param tagName the name of the group to be selected
8585
*/
86-
void selectGroup( const QString& groupName );
86+
void selectTag( const QString& tagName );
8787

8888
/**
89-
* Deselect the symbols belonging to the given group
90-
* @param groupName the name of the group to be deselected
89+
* Deselect the symbols belonging to the given tag
90+
* @param tagName the name of the group to be deselected
9191
*/
92-
void deselectGroup( const QString& groupName );
92+
void deselectTag( const QString& tagName );
9393

9494
/**
9595
* @brief selectSmartgroup selects all symbols from a smart group
@@ -127,7 +127,7 @@ class GUI_EXPORT QgsStyleExportImportDialog : public QDialog, private Ui::QgsSty
127127
QString mFileName;
128128
Mode mDialogMode;
129129

130-
QgsStyle* mQgisStyle;
130+
QgsStyle* mStyle;
131131
QgsStyle* mTempStyle;
132132
};
133133

‎src/gui/symbology-ng/qgsstylegroupselectiondialog.cpp

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -37,24 +37,19 @@ QgsStyleGroupSelectionDialog::QgsStyleGroupSelectionDialog( QgsStyle *style, QWi
3737
setBold( allSymbols );
3838
model->appendRow( allSymbols );
3939

40-
QStandardItem *group = new QStandardItem( QLatin1String( "" ) ); //require empty name to get first order groups
41-
group->setData( "groupsheader", Qt::UserRole + 2 );
42-
group->setEditable( false );
43-
group->setFlags( group->flags() & ~Qt::ItemIsSelectable );
44-
buildGroupTree( group );
45-
group->setText( tr( "Groups" ) );//set title later
46-
QStandardItem *ungrouped = new QStandardItem( tr( "Ungrouped" ) );
47-
ungrouped->setData( 0 );
48-
ungrouped->setData( "group", Qt::UserRole + 2 );
49-
setBold( ungrouped );
50-
setBold( group );
51-
group->appendRow( ungrouped );
52-
model->appendRow( group );
40+
QStandardItem *tags = new QStandardItem( QLatin1String( "" ) ); //require empty name to get first order groups
41+
tags->setData( "tagsheader", Qt::UserRole + 2 );
42+
tags->setEditable( false );
43+
tags->setFlags( tags->flags() & ~Qt::ItemIsSelectable );
44+
buildTagTree( tags );
45+
tags->setText( tr( "Tags" ) );//set title later
46+
setBold( tags );
47+
model->appendRow( tags );
5348

5449
QStandardItem *tag = new QStandardItem( tr( "Smart Groups" ) );
5550
tag->setData( "smartgroupsheader" , Qt::UserRole + 2 );
5651
tag->setEditable( false );
57-
tag->setFlags( group->flags() & ~Qt::ItemIsSelectable );
52+
tag->setFlags( tag->flags() & ~Qt::ItemIsSelectable );
5853
setBold( tag );
5954
QgsSymbolGroupMap sgMap = mStyle->smartgroupsListMap();
6055
QgsSymbolGroupMap::const_iterator i = sgMap.constBegin();
@@ -100,7 +95,7 @@ void QgsStyleGroupSelectionDialog::groupTreeSelectionChanged( const QItemSelecti
10095

10196
Q_FOREACH ( index, deselectedItems )
10297
{
103-
if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "groupsheader" ) )
98+
if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "tagssheader" ) )
10499
{
105100
// Ignore: it's the group header
106101
}
@@ -116,14 +111,14 @@ void QgsStyleGroupSelectionDialog::groupTreeSelectionChanged( const QItemSelecti
116111
{
117112
emit smartgroupDeselected( index.data().toString() );
118113
}
119-
else if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "group" ) )
120-
{ // It's a group
121-
emit groupDeselected( index.data().toString() );
114+
else if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "tag" ) )
115+
{ // It's a tag
116+
emit tagDeselected( index.data().toString() );
122117
}
123118
}
124119
Q_FOREACH ( index, selectedItems )
125120
{
126-
if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "groupsheader" ) )
121+
if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "tagssheader" ) )
127122
{
128123
// Ignore: it's the group header
129124
}
@@ -139,27 +134,25 @@ void QgsStyleGroupSelectionDialog::groupTreeSelectionChanged( const QItemSelecti
139134
{
140135
emit smartgroupSelected( index.data().toString() );
141136
}
142-
else if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "group" ) )
143-
{ // It's a group
144-
emit groupSelected( index.data().toString() );
137+
else if ( index.data( Qt::UserRole + 2 ).toString() == QLatin1String( "tag" ) )
138+
{ // It's a tag
139+
emit tagSelected( index.data().toString() );
145140
}
146141
}
147142
}
148143

149144

150-
void QgsStyleGroupSelectionDialog::buildGroupTree( QStandardItem* &parent )
145+
void QgsStyleGroupSelectionDialog::buildTagTree( QStandardItem* &parent )
151146
{
152-
QgsSymbolGroupMap groups = mStyle->childGroupNames( parent->text() );
153-
QgsSymbolGroupMap::const_iterator i = groups.constBegin();
154-
while ( i != groups.constEnd() )
147+
QStringList tags = mStyle->tags();
148+
tags.sort();
149+
Q_FOREACH ( const QString& tag, tags )
155150
{
156-
QStandardItem *item = new QStandardItem( i.value() );
157-
item->setData( i.key() );
158-
item->setData( "group" , Qt::UserRole + 2 );
151+
QStandardItem *item = new QStandardItem( tag );
152+
item->setData( mStyle->tagId( tag ) );
153+
item->setData( "tag" , Qt::UserRole + 2 );
159154
item->setEditable( false );
160155
parent->appendRow( item );
161-
buildGroupTree( item );
162-
++i;
163156
}
164157
}
165158

‎src/gui/symbology-ng/qgsstylegroupselectiondialog.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ class GUI_EXPORT QgsStyleGroupSelectionDialog : public QDialog, private Ui::Symb
3838
void setBold( QStandardItem *item );
3939

4040
signals:
41-
//! group with groupName has been selected
42-
void groupSelected( const QString& groupName );
43-
//! group with groupName has been deselected
44-
void groupDeselected( const QString& groupName );
41+
//! tag with tagName has been selected
42+
void tagSelected( const QString& tagName );
43+
//! tag with tagName has been deselected
44+
void tagDeselected( const QString& tagName );
4545
//! smartgroup with groupName has been selected
4646
void smartgroupSelected( const QString& groupName );
4747
//! smart group with groupName has been deselected
@@ -60,7 +60,7 @@ class GUI_EXPORT QgsStyleGroupSelectionDialog : public QDialog, private Ui::Symb
6060
* @brief build group tree
6161
* @param parent
6262
*/
63-
void buildGroupTree( QStandardItem *&parent );
63+
void buildTagTree( QStandardItem *&parent );
6464
QgsStyle* mStyle;
6565

6666
};

‎src/gui/symbology-ng/qgsstylemanagerdialog.cpp

Lines changed: 249 additions & 248 deletions
Large diffs are not rendered by default.

‎src/gui/symbology-ng/qgsstylemanagerdialog.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ class GUI_EXPORT QgsStyleManagerDialog : public QDialog, private Ui::QgsStyleMan
6666
void addGroup();
6767
void removeGroup();
6868

69-
//! carryout symbol grouping using check boxes
70-
void groupSymbolsAction();
69+
//! carry out symbol tagging using check boxes
70+
void tagSymbolsAction();
7171

7272
//! edit the selected smart group
7373
void editSmartgroupAction();
@@ -78,9 +78,6 @@ class GUI_EXPORT QgsStyleManagerDialog : public QDialog, private Ui::QgsStyleMan
7878
//! filter the symbols based on input search term
7979
void filterSymbols( const QString& );
8080

81-
//! Listen to tag changes
82-
void tagsChanged();
83-
8481
//! Perform symbol specific tasks when selected
8582
void symbolSelected( const QModelIndex& );
8683

@@ -95,7 +92,14 @@ class GUI_EXPORT QgsStyleManagerDialog : public QDialog, private Ui::QgsStyleMan
9592

9693
protected slots:
9794
bool addColorRamp( QAction* action );
98-
void groupSelectedSymbols();
95+
//! Add selected symbols to favorites
96+
void addFavoriteSelectedSymbols();
97+
//! Remove selected symbols from favorites
98+
void removeFavoriteSelectedSymbols();
99+
//! Tag selected symbols using menu item selection
100+
void tagSelectedSymbols();
101+
//! Remove all tags from selected symbols
102+
void detagSelectedSymbols();
99103

100104
protected:
101105

@@ -104,8 +108,6 @@ class GUI_EXPORT QgsStyleManagerDialog : public QDialog, private Ui::QgsStyleMan
104108

105109
//! populate the groups
106110
void populateGroups();
107-
//! build the groups tree
108-
void buildGroupTree( QStandardItem* &parent );
109111
//! to set symbols checked when in editing mode
110112
void setSymbolsChecked( const QStringList& );
111113

@@ -136,9 +138,6 @@ class GUI_EXPORT QgsStyleManagerDialog : public QDialog, private Ui::QgsStyleMan
136138
//! Enables or diables the groupTree items for grouping mode
137139
void enableItemsForGroupingMode( bool );
138140

139-
//! Event filter to capture tagsLineEdit out of focus
140-
bool eventFilter( QObject*, QEvent* ) override;
141-
142141
//! sets the text of the item with bold font
143142
void setBold( QStandardItem* );
144143

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/***************************************************************************
2+
qgssymbolsavedialog.cpp
3+
---------------------------------------
4+
begin : November 2016
5+
copyright : (C) 2016 by Mathieu Pellerin
6+
email : nirvn dot asia at gmail dot com
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#include "qgsstylesavedialog.h"
19+
20+
#include "qgis.h"
21+
#include "qgsstyle.h"
22+
23+
#include <QLineEdit>
24+
#include <QCheckBox>
25+
26+
QgsStyleSaveDialog::QgsStyleSaveDialog( QWidget* parent, QgsStyle::StyleEntity type )
27+
: QDialog( parent )
28+
{
29+
setupUi( this );
30+
31+
if ( type == QgsStyle::SymbolEntity )
32+
{
33+
this->setWindowTitle( tr( "Save new symbol" ) );
34+
}
35+
else if ( type == QgsStyle::ColorrampEntity )
36+
{
37+
this->setWindowTitle( tr( "Save new color ramp" ) );
38+
}
39+
}
40+
41+
QgsStyleSaveDialog::~QgsStyleSaveDialog() { }
42+
43+
QString QgsStyleSaveDialog::name() const
44+
{
45+
return mName->text();
46+
}
47+
48+
QString QgsStyleSaveDialog::tags() const
49+
{
50+
return mTags->text();
51+
}
52+
53+
bool QgsStyleSaveDialog::isFavorite() const
54+
{
55+
return mFavorite->isChecked();
56+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/***************************************************************************
2+
qgssymbolsavedialog.h
3+
-------------------------------------
4+
begin : November 2016
5+
copyright : (C) 2016 by Mathieu Pellerin
6+
email : nirvn dot asia at gmail dot com
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#ifndef QGSSTYLESAVEDIALOG_H
19+
#define QGSSTYLESAVEDIALOG_H
20+
21+
#include <QDialog>
22+
#include "ui_qgsstylesavedialog.h"
23+
24+
#include "qgsstyle.h"
25+
26+
/** \ingroup gui
27+
* \brief a dialog for setting properties of a newly saved style.
28+
* \note added in QGIS 3.0
29+
*/
30+
class GUI_EXPORT QgsStyleSaveDialog: public QDialog, private Ui::QgsStyleSaveDialog
31+
{
32+
Q_OBJECT
33+
34+
public:
35+
36+
/** Constructor for QgsSymbolSaveDialog
37+
* @param parent parent widget
38+
* @param type the QgsStyle entity type being saved
39+
*/
40+
QgsStyleSaveDialog( QWidget* parent = nullptr, QgsStyle::StyleEntity type = QgsStyle::SymbolEntity );
41+
42+
~QgsStyleSaveDialog();
43+
44+
//! returns the text value of the name element
45+
QString name() const;
46+
47+
//! returns the text value of the tags element
48+
QString tags() const;
49+
50+
//! returns whether the favorite element is checked
51+
bool isFavorite() const;
52+
53+
54+
55+
};
56+
57+
#endif // QGSSTYLESAVEDIALOG_H

‎src/gui/symbology-ng/qgssymbolslistwidget.cpp

Lines changed: 83 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "qgssizescalewidget.h"
2020

2121
#include "qgsstylemanagerdialog.h"
22+
#include "qgsstylesavedialog.h"
2223
#include "qgsdatadefined.h"
2324

2425
#include "qgssymbol.h"
@@ -29,6 +30,8 @@
2930
#include "qgsapplication.h"
3031
#include "qgsvectorlayer.h"
3132

33+
#include <QAction>
34+
#include <QSettings>
3235
#include <QString>
3336
#include <QStringList>
3437
#include <QPainter>
@@ -38,6 +41,7 @@
3841
#include <QInputDialog>
3942
#include <QMessageBox>
4043
#include <QMenu>
44+
#include <QPushButton>
4145
#include <QScopedPointer>
4246

4347

@@ -67,26 +71,20 @@ QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbol* symbol, QgsStyle* style,
6771
}
6872
mClipFeaturesAction = new QAction( tr( "Clip features to canvas extent" ), this );
6973
mClipFeaturesAction->setCheckable( true );
70-
connect( mClipFeaturesAction, SIGNAL( toggled( bool ) ), this, SLOT( clipFeaturesToggled( bool ) ) );
71-
72-
// populate the groups
73-
groupsCombo->addItem( QLatin1String( "" ) );
74-
populateGroups();
75-
QStringList groups = style->smartgroupNames();
76-
Q_FOREACH ( const QString& group, groups )
77-
{
78-
groupsCombo->addItem( group, QVariant( "smart" ) );
79-
}
74+
connect( mClipFeaturesAction, &QAction::toggled, this, &QgsSymbolsListWidget::clipFeaturesToggled );
8075

8176
QStandardItemModel* model = new QStandardItemModel( viewSymbols );
8277
viewSymbols->setModel( model );
8378
connect( viewSymbols->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), this, SLOT( setSymbolFromStyle( const QModelIndex & ) ) );
8479

85-
connect( mStyle, SIGNAL( symbolSaved( QString, QgsSymbol* ) ), this, SLOT( symbolAddedToStyle( QString, QgsSymbol* ) ) );
86-
connect( openStyleManagerButton, SIGNAL( pressed() ), this, SLOT( openStyleManager() ) );
80+
connect( mStyle, &QgsStyle::symbolSaved , this, &QgsSymbolsListWidget::symbolAddedToStyle );
81+
connect( mStyle, &QgsStyle::groupsModified , this, &QgsSymbolsListWidget::populateGroups );
82+
83+
connect( openStyleManagerButton, &QPushButton::pressed, this, &QgsSymbolsListWidget::openStyleManager );
8784

8885
lblSymbolName->setText( QLatin1String( "" ) );
89-
populateSymbolView();
86+
87+
populateGroups();
9088

9189
if ( mSymbol )
9290
{
@@ -119,7 +117,7 @@ QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbol* symbol, QgsStyle* style,
119117
btnColor->setColorDialogTitle( tr( "Select color" ) );
120118
btnColor->setContext( QStringLiteral( "symbology" ) );
121119

122-
connect( btnSaveSymbol, SIGNAL( clicked() ), this, SLOT( saveSymbol() ) );
120+
connect( btnSaveSymbol, &QPushButton::clicked, this, &QgsSymbolsListWidget::saveSymbol );
123121
}
124122

125123
QgsSymbolsListWidget::~QgsSymbolsListWidget()
@@ -148,30 +146,72 @@ QgsSymbolWidgetContext QgsSymbolsListWidget::context() const
148146
return mContext;
149147
}
150148

151-
void QgsSymbolsListWidget::populateGroups( const QString& parent, const QString& prepend )
149+
void QgsSymbolsListWidget::populateGroups()
152150
{
153-
QgsSymbolGroupMap groups = mStyle->childGroupNames( parent );
154-
QgsSymbolGroupMap::const_iterator i = groups.constBegin();
155-
while ( i != groups.constEnd() )
151+
groupsCombo->blockSignals( true );
152+
groupsCombo->clear();
153+
154+
groupsCombo->addItem( tr( "Favorites" ), QVariant( "favorite" ) );
155+
groupsCombo->addItem( tr( "All Symbols" ), QVariant( "all" ) );
156+
157+
int index = 2;
158+
QStringList tags = mStyle->tags();
159+
if ( tags.count() > 0 )
156160
{
157-
QString text;
158-
if ( !prepend.isEmpty() )
161+
tags.sort();
162+
groupsCombo->insertSeparator( index );
163+
Q_FOREACH ( const QString& tag, tags )
159164
{
160-
text = prepend + '/' + i.value();
165+
groupsCombo->addItem( tag, QVariant( "tag" ) );
166+
index++;
161167
}
162-
else
168+
}
169+
170+
QStringList groups = mStyle->smartgroupNames();
171+
if ( groups.count() > 0 )
172+
{
173+
groups.sort();
174+
groupsCombo->insertSeparator( index + 1 );
175+
Q_FOREACH ( const QString& group, groups )
163176
{
164-
text = i.value();
177+
groupsCombo->addItem( group, QVariant( "smartgroup" ) );
165178
}
166-
groupsCombo->addItem( text, QVariant( i.key() ) );
167-
populateGroups( i.value(), text );
168-
++i;
169179
}
180+
groupsCombo->blockSignals( false );
181+
182+
QSettings settings;
183+
index = settings.value( "qgis/symbolsListGroupsIndex", 0 ).toInt();
184+
groupsCombo->setCurrentIndex( index );
185+
186+
populateSymbolView();
170187
}
171188

172189
void QgsSymbolsListWidget::populateSymbolView()
173190
{
174-
populateSymbols( mStyle->symbolNames() );
191+
QStringList symbols;
192+
QString text = groupsCombo->currentText();
193+
int id;
194+
195+
if ( groupsCombo->currentData().toString() == QLatin1String( "favorite" ) )
196+
{
197+
symbols = mStyle->symbolsOfFavorite( QgsStyle::SymbolEntity );
198+
}
199+
else if ( groupsCombo->currentData().toString() == QLatin1String( "all" ) )
200+
{
201+
symbols = mStyle->symbolNames();
202+
}
203+
else if ( groupsCombo->currentData().toString() == QLatin1String( "smartgroup" ) )
204+
{
205+
id = mStyle->smartgroupId( text );
206+
symbols = mStyle->symbolsOfSmartgroup( QgsStyle::SymbolEntity, id );
207+
}
208+
else
209+
{
210+
id = mStyle->tagId( text );
211+
symbols = mStyle->symbolsWithTag( QgsStyle::SymbolEntity, id );
212+
}
213+
214+
populateSymbols( symbols );
175215
}
176216

177217
void QgsSymbolsListWidget::populateSymbols( const QStringList& names )
@@ -357,30 +397,34 @@ void QgsSymbolsListWidget::addSymbolToStyle()
357397

358398
void QgsSymbolsListWidget::saveSymbol()
359399
{
360-
bool ok;
361-
QString name = QInputDialog::getText( this, tr( "Symbol name" ),
362-
tr( "Please enter name for the symbol:" ), QLineEdit::Normal, tr( "New symbol" ), &ok );
363-
if ( !ok || name.isEmpty() )
400+
QgsStyleSaveDialog saveDlg( this );
401+
if ( !saveDlg.exec() )
402+
return;
403+
404+
if ( saveDlg.name().isEmpty() )
364405
return;
365406

366407
// check if there is no symbol with same name
367-
if ( mStyle->symbolNames().contains( name ) )
408+
if ( mStyle->symbolNames().contains( saveDlg.name() ) )
368409
{
369410
int res = QMessageBox::warning( this, tr( "Save symbol" ),
370411
tr( "Symbol with name '%1' already exists. Overwrite?" )
371-
.arg( name ),
412+
.arg( saveDlg.name() ),
372413
QMessageBox::Yes | QMessageBox::No );
373414
if ( res != QMessageBox::Yes )
374415
{
375416
return;
376417
}
418+
mStyle->removeSymbol( saveDlg.name() );
377419
}
378420

421+
QStringList symbolTags = saveDlg.tags().split( ',' );
422+
379423
// add new symbol to style and re-populate the list
380-
mStyle->addSymbol( name, mSymbol->clone() );
424+
mStyle->addSymbol( saveDlg.name(), mSymbol->clone() );
381425

382426
// make sure the symbol is stored
383-
mStyle->saveSymbol( name, mSymbol->clone(), 0, QStringList() );
427+
mStyle->saveSymbol( saveDlg.name(), mSymbol->clone(), saveDlg.isFavorite(), symbolTags );
384428
}
385429

386430
void QgsSymbolsListWidget::on_mSymbolUnitWidget_changed()
@@ -537,7 +581,7 @@ void QgsSymbolsListWidget::setSymbolFromStyle( const QModelIndex & index )
537581
// get new instance of symbol from style
538582
QgsSymbol* s = mStyle->symbol( symbolName );
539583
QgsUnitTypes::RenderUnit unit = s->outputUnit();
540-
// remove all symbol layers from original symbol
584+
// remove all symbol layers from original symbolgroupsCombo
541585
while ( mSymbol->symbolLayerCount() )
542586
mSymbol->deleteSymbolLayer( 0 );
543587
// move all symbol layers to our symbol
@@ -557,32 +601,8 @@ void QgsSymbolsListWidget::setSymbolFromStyle( const QModelIndex & index )
557601

558602
void QgsSymbolsListWidget::on_groupsCombo_currentIndexChanged( int index )
559603
{
560-
QStringList symbols;
561-
QString text = groupsCombo->itemText( index );
562-
// List all symbols when empty list item is selected
563-
if ( text.isEmpty() )
564-
{
565-
symbols = mStyle->symbolNames();
566-
}
567-
else
568-
{
569-
int groupid;
570-
if ( groupsCombo->itemData( index ).toString() == QLatin1String( "smart" ) )
571-
{
572-
groupid = mStyle->smartgroupId( text );
573-
symbols = mStyle->symbolsOfSmartgroup( QgsStyle::SymbolEntity, groupid );
574-
}
575-
else
576-
{
577-
groupid = groupsCombo->itemData( index ).toInt();
578-
symbols = mStyle->symbolsOfGroup( QgsStyle::SymbolEntity, groupid );
579-
}
580-
}
581-
populateSymbols( symbols );
582-
}
604+
QSettings settings;
605+
settings.setValue( QStringLiteral( "qgis/symbolsListGroupsIndex" ), index );
583606

584-
void QgsSymbolsListWidget::on_groupsCombo_editTextChanged( const QString &text )
585-
{
586-
QStringList symbols = mStyle->findSymbols( QgsStyle::SymbolEntity, text );
587-
populateSymbols( symbols );
607+
populateSymbolView();
588608
}

‎src/gui/symbology-ng/qgssymbolslistwidget.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,15 @@ class GUI_EXPORT QgsSymbolsListWidget : public QWidget, private Ui::SymbolsListW
6767
void setLineWidth( double width );
6868
void addSymbolToStyle();
6969
void saveSymbol();
70+
7071
void symbolAddedToStyle( const QString& name, QgsSymbol* symbol );
72+
7173
void on_mSymbolUnitWidget_changed();
7274
void on_mTransparencySlider_valueChanged( int value );
7375

76+
//! Pupulates the groups combo box with available tags and smartgroups
77+
void populateGroups();
7478
void on_groupsCombo_currentIndexChanged( int index );
75-
void on_groupsCombo_editTextChanged( const QString &text );
7679

7780
void openStyleManager();
7881
void clipFeaturesToggled( bool checked );
@@ -99,8 +102,6 @@ class GUI_EXPORT QgsSymbolsListWidget : public QWidget, private Ui::SymbolsListW
99102

100103
//! Displays alpha value as transparency in mTransparencyLabel
101104
void displayTransparency( double alpha );
102-
//! Recursive function to create the group tree in the widget
103-
void populateGroups( const QString& parent = "", const QString& prepend = "" );
104105

105106
QgsSymbolWidgetContext mContext;
106107

‎src/ui/qgsstyleexportimportdialogbase.ui

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,33 @@
4343
</property>
4444
</widget>
4545
</item>
46-
<item row="2" column="0">
47-
<widget class="QLabel" name="groupLabel">
46+
<item row="3" column="0">
47+
<widget class="QLabel" name="tagLabel">
4848
<property name="text">
49-
<string>Save to group</string>
49+
<string>Tag(s)</string>
5050
</property>
5151
</widget>
5252
</item>
53-
<item row="2" column="1" colspan="2">
54-
<widget class="QComboBox" name="groupCombo">
55-
<property name="editable">
56-
<bool>true</bool>
53+
<item row="2" column="0" colspan="3">
54+
<widget class="QCheckBox" name="mFavorite">
55+
<property name="sizePolicy">
56+
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
57+
<horstretch>0</horstretch>
58+
<verstretch>0</verstretch>
59+
</sizepolicy>
60+
</property>
61+
<property name="text">
62+
<string>Add to favorites</string>
63+
</property>
64+
</widget>
65+
</item>
66+
<item row="3" column="1" colspan="2">
67+
<widget class="QLineEdit" name="mSymbolTags"/>
68+
</item>
69+
<item row="4" column="1" colspan="2">
70+
<widget class="QLabel" name="tagHintLabel">
71+
<property name="text">
72+
<string>Tip: separate multiple tags with commas</string>
5773
</property>
5874
</widget>
5975
</item>

‎src/ui/qgsstylemanagerdialogbase.ui

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -380,26 +380,6 @@ QMenu::item:selected { background-color: gray; } */
380380
</property>
381381
</widget>
382382
</item>
383-
<item>
384-
<layout class="QHBoxLayout" name="horizontalLayout_2">
385-
<item>
386-
<widget class="QLabel" name="label">
387-
<property name="font">
388-
<font>
389-
<weight>75</weight>
390-
<bold>true</bold>
391-
</font>
392-
</property>
393-
<property name="text">
394-
<string>Tags</string>
395-
</property>
396-
</widget>
397-
</item>
398-
<item>
399-
<widget class="QLineEdit" name="tagsLineEdit"/>
400-
</item>
401-
</layout>
402-
</item>
403383
</layout>
404384
</item>
405385
</layout>
@@ -450,15 +430,37 @@ QMenu::item:selected { background-color: gray; } */
450430
<string>Edit item</string>
451431
</property>
452432
</action>
453-
<action name="actnUngroup">
433+
<action name="actnAddFavorite">
434+
<property name="enabled">
435+
<bool>false</bool>
436+
</property>
437+
<property name="text">
438+
<string>Add to favorites</string>
439+
</property>
440+
<property name="toolTip">
441+
<string>Add to favorites</string>
442+
</property>
443+
</action>
444+
<action name="actnRemoveFavorite">
445+
<property name="enabled">
446+
<bool>false</bool>
447+
</property>
448+
<property name="text">
449+
<string>Remove from favorites</string>
450+
</property>
451+
<property name="toolTip">
452+
<string>Remove from favorites</string>
453+
</property>
454+
</action>
455+
<action name="actnDetag">
454456
<property name="enabled">
455457
<bool>false</bool>
456458
</property>
457459
<property name="text">
458-
<string>Ungroup</string>
460+
<string>Clear tags</string>
459461
</property>
460462
<property name="toolTip">
461-
<string>Ungroup</string>
463+
<string>Clear tags</string>
462464
</property>
463465
</action>
464466
<action name="actnEditSmartGroup">
@@ -484,17 +486,17 @@ QMenu::item:selected { background-color: gray; } */
484486
<string>Remove group</string>
485487
</property>
486488
</action>
487-
<action name="actnGroupSymbols">
489+
<action name="actnTagSymbols">
488490
<property name="text">
489-
<string>Group symbols</string>
491+
<string>Attach selected tag to symbols</string>
490492
</property>
491493
</action>
492-
<action name="actnFinishGrouping">
494+
<action name="actnFinishTagging">
493495
<property name="enabled">
494496
<bool>true</bool>
495497
</property>
496498
<property name="text">
497-
<string>Finish grouping</string>
499+
<string>Finish tagging</string>
498500
</property>
499501
<property name="visible">
500502
<bool>true</bool>

‎src/ui/qgsstylesavedialog.ui

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>QgsStyleSaveDialog</class>
4+
<widget class="QDialog" name="QgsStyleSaveDialog">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>489</width>
10+
<height>225</height>
11+
</rect>
12+
</property>
13+
<property name="windowTitle">
14+
<string>Save new style</string>
15+
</property>
16+
<layout class="QVBoxLayout" name="verticalLayout">
17+
<item>
18+
<layout class="QGridLayout" name="gridLayout">
19+
<item row="0" column="0">
20+
<widget class="QLabel" name="label_1">
21+
<property name="text">
22+
<string>Name</string>
23+
</property>
24+
</widget>
25+
</item>
26+
<item row="0" column="1">
27+
<widget class="QLineEdit" name="mName"/>
28+
</item>
29+
<item row="3" column="0" colspan="2">
30+
<widget class="QCheckBox" name="mFavorite">
31+
<property name="sizePolicy">
32+
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
33+
<horstretch>0</horstretch>
34+
<verstretch>0</verstretch>
35+
</sizepolicy>
36+
</property>
37+
<property name="text">
38+
<string>Add to favorites</string>
39+
</property>
40+
</widget>
41+
</item>
42+
<item row="1" column="0">
43+
<widget class="QLabel" name="label_10">
44+
<property name="text">
45+
<string>Tag(s)</string>
46+
</property>
47+
</widget>
48+
</item>
49+
<item row="1" column="1">
50+
<widget class="QLineEdit" name="mTags"/>
51+
</item>
52+
<item row="2" column="1">
53+
<widget class="QLabel" name="label_10">
54+
<property name="text">
55+
<string>Tip: separate multiple tags with commas</string>
56+
</property>
57+
</widget>
58+
</item>
59+
</layout>
60+
</item>
61+
<item>
62+
<spacer name="verticalSpacer">
63+
<property name="orientation">
64+
<enum>Qt::Vertical</enum>
65+
</property>
66+
<property name="sizeHint" stdset="0">
67+
<size>
68+
<width>20</width>
69+
<height>40</height>
70+
</size>
71+
</property>
72+
</spacer>
73+
</item>
74+
<item>
75+
<widget class="QDialogButtonBox" name="buttonBox">
76+
<property name="orientation">
77+
<enum>Qt::Horizontal</enum>
78+
</property>
79+
<property name="standardButtons">
80+
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
81+
</property>
82+
</widget>
83+
</item>
84+
</layout>
85+
</widget>
86+
<tabstops>
87+
<tabstop>mName</tabstop>
88+
<tabstop>mTags</tabstop>
89+
<tabstop>mFavorite</tabstop>
90+
</tabstops>
91+
<resources/>
92+
<connections>
93+
<connection>
94+
<sender>buttonBox</sender>
95+
<signal>accepted()</signal>
96+
<receiver>QgsStyleSaveDialog</receiver>
97+
<slot>accept()</slot>
98+
<hints>
99+
<hint type="sourcelabel">
100+
<x>248</x>
101+
<y>254</y>
102+
</hint>
103+
<hint type="destinationlabel">
104+
<x>157</x>
105+
<y>274</y>
106+
</hint>
107+
</hints>
108+
</connection>
109+
<connection>
110+
<sender>buttonBox</sender>
111+
<signal>rejected()</signal>
112+
<receiver>QgsStyleSaveDialog</receiver>
113+
<slot>reject()</slot>
114+
<hints>
115+
<hint type="sourcelabel">
116+
<x>316</x>
117+
<y>260</y>
118+
</hint>
119+
<hint type="destinationlabel">
120+
<x>286</x>
121+
<y>274</y>
122+
</hint>
123+
</hints>
124+
</connection>
125+
</connections>
126+
</ui>

‎src/ui/symbollayer/widget_symbolslist.ui

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
<item>
7373
<widget class="QLabel" name="label">
7474
<property name="text">
75-
<string>Symbols in group</string>
75+
<string>Symbols in</string>
7676
</property>
7777
</widget>
7878
</item>
@@ -131,17 +131,11 @@
131131
</item>
132132
<item>
133133
<widget class="QPushButton" name="btnSaveSymbol">
134-
<property name="maximumSize">
135-
<size>
136-
<width>70</width>
137-
<height>16777215</height>
138-
</size>
139-
</property>
140134
<property name="toolTip">
141135
<string>Save symbol</string>
142136
</property>
143137
<property name="text">
144-
<string>Save</string>
138+
<string>Save symbol</string>
145139
</property>
146140
</widget>
147141
</item>

‎tests/src/core/testqgsstyle.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class TestStyle : public QObject
6565
void testCreateColorRamps();
6666
void testLoadColorRamps();
6767
void testSaveLoad();
68+
void testFavorites();
6869
void testTags();
6970

7071
};
@@ -258,6 +259,35 @@ void TestStyle::testSaveLoad()
258259
testLoadColorRamps();
259260
}
260261

262+
void TestStyle::testFavorites()
263+
{
264+
mStyle->clear();
265+
266+
// save initial number of favorites to compare against additions / substractions
267+
QStringList favorites;
268+
favorites = mStyle->symbolsOfFavorite( QgsStyle::SymbolEntity );
269+
int count = favorites.count();
270+
271+
// add some symbols to favorites
272+
mStyle->saveSymbol( "symbolA", QgsMarkerSymbol::createSimple( QgsStringMap() ), true, QStringList() );
273+
mStyle->saveSymbol( "symbolB", QgsMarkerSymbol::createSimple( QgsStringMap() ), false, QStringList() );
274+
mStyle->saveSymbol( "symbolC", QgsMarkerSymbol::createSimple( QgsStringMap() ), true, QStringList() );
275+
276+
// check for added symbols to favorites
277+
favorites = mStyle->symbolsOfFavorite( QgsStyle::SymbolEntity );
278+
QCOMPARE( favorites.count(), count + 2 );
279+
QVERIFY( favorites.contains( "symbolA" ) );
280+
QVERIFY( favorites.contains( "symbolC" ) );
281+
282+
// remove one symbol from favorites
283+
mStyle->removeFavorite( QgsStyle::SymbolEntity, "symbolA" );
284+
285+
// insure favorites updated after removal
286+
favorites = mStyle->symbolsOfFavorite( QgsStyle::SymbolEntity );
287+
QCOMPARE( favorites.count(), count + 1 );
288+
QVERIFY( favorites.contains( "symbolC" ) );
289+
}
290+
261291
void TestStyle::testTags()
262292
{
263293
mStyle->clear();
@@ -289,7 +319,7 @@ void TestStyle::testTags()
289319
QVERIFY( !tags.contains( "purple" ) );
290320

291321
//add some symbols
292-
QVERIFY( mStyle->saveSymbol( "symbol1", QgsMarkerSymbol::createSimple( QgsStringMap() ), 0, QStringList() << "red" << "starry" ) );
322+
QVERIFY( mStyle->saveSymbol( "symbol1", QgsMarkerSymbol::createSimple( QgsStringMap() ), false, QStringList() << "red" << "starry" ) );
293323
mStyle->addSymbol( QStringLiteral( "blue starry" ), QgsMarkerSymbol::createSimple( QgsStringMap() ), true );
294324
mStyle->addSymbol( QStringLiteral( "red circle" ), QgsMarkerSymbol::createSimple( QgsStringMap() ), true );
295325

0 commit comments

Comments
 (0)
Please sign in to comment.