QGIS API Documentation  2.14.0-Essen
qgsstylev2managerdialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsstylev2managerdialog.cpp
3  ---------------------
4  begin : November 2009
5  copyright : (C) 2009 by Martin Dobias
6  email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
17 
18 #include "qgsstylev2.h"
19 #include "qgssymbolv2.h"
20 #include "qgssymbollayerv2utils.h"
21 #include "qgsvectorcolorrampv2.h"
22 
30 
31 #include <QFile>
32 #include <QFileDialog>
33 #include <QInputDialog>
34 #include <QMessageBox>
35 #include <QSettings>
36 #include <QStandardItemModel>
37 #include <QAction>
38 #include <QMenu>
39 
40 #include "qgsapplication.h"
41 #include "qgslogger.h"
42 
44  : QDialog( parent ), mStyle( style ), mModified( false )
45 {
46  setupUi( this );
47 #ifdef Q_OS_MAC
48  setWindowModality( Qt::WindowModal );
49 #endif
50 
51  QSettings settings;
52 
53  restoreGeometry( settings.value( "/Windows/StyleV2Manager/geometry" ).toByteArray() );
54  mSplitter->setSizes( QList<int>() << 170 << 540 );
55  mSplitter->restoreState( settings.value( "/Windows/StyleV2Manager/splitter" ).toByteArray() );
56 
57  tabItemType->setDocumentMode( true );
58  searchBox->setPlaceholderText( tr( "Type here to filter symbols..." ) );
59 
60  connect( this, SIGNAL( finished( int ) ), this, SLOT( onFinished() ) );
61 
62  connect( listItems, SIGNAL( doubleClicked( const QModelIndex & ) ), this, SLOT( editItem() ) );
63 
64  connect( btnAddItem, SIGNAL( clicked() ), this, SLOT( addItem() ) );
65  connect( actnEditItem, SIGNAL( triggered( bool ) ), this, SLOT( editItem() ) );
66  connect( actnRemoveItem, SIGNAL( triggered( bool ) ), this, SLOT( removeItem() ) );
67 
68  btnRemoveItem->setDefaultAction( actnRemoveItem );
69  btnEditItem->setDefaultAction( actnEditItem );
70 
71  QMenu *shareMenu = new QMenu( tr( "Share menu" ), this );
72  shareMenu->addAction( actnExportAsPNG );
73  shareMenu->addAction( actnExportAsSVG );
74  QAction *exportAction = new QAction( tr( "Export..." ), this );
75  shareMenu->addAction( exportAction );
76  QAction *importAction = new QAction( tr( "Import..." ), this );
77  shareMenu->addAction( importAction );
78  exportAction->setIcon( QIcon( QgsApplication::iconPath( "mActionSharingExport.svg" ) ) );
79  importAction->setIcon( QIcon( QgsApplication::iconPath( "mActionSharingImport.svg" ) ) );
80  connect( actnExportAsPNG, SIGNAL( triggered() ), this, SLOT( exportItemsPNG() ) );
81  connect( actnExportAsSVG, SIGNAL( triggered() ), this, SLOT( exportItemsSVG() ) );
82  connect( exportAction, SIGNAL( triggered() ), this, SLOT( exportItems() ) );
83  connect( importAction, SIGNAL( triggered() ), this, SLOT( importItems() ) );
84  btnShare->setMenu( shareMenu );
85 
86  // Set editing mode off by default
87  mGrouppingMode = false;
88 
89  QStandardItemModel* model = new QStandardItemModel( listItems );
90  listItems->setModel( model );
91  listItems->setSelectionMode( QAbstractItemView::ExtendedSelection );
92 
93  connect( model, SIGNAL( itemChanged( QStandardItem* ) ), this, SLOT( itemChanged( QStandardItem* ) ) );
94  connect( listItems->selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ),
95  this, SLOT( symbolSelected( const QModelIndex& ) ) );
96  connect( listItems->selectionModel(), SIGNAL( selectionChanged( const QItemSelection, const QItemSelection ) ),
97  this, SLOT( selectedSymbolsChanged( const QItemSelection&, const QItemSelection& ) ) );
98 
99  populateTypes();
100 
101  QStandardItemModel* groupModel = new QStandardItemModel( groupTree );
102  groupTree->setModel( groupModel );
103  groupTree->setHeaderHidden( true );
104  populateGroups();
105  connect( groupTree->selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ),
106  this, SLOT( groupChanged( const QModelIndex& ) ) );
107  connect( groupModel, SIGNAL( itemChanged( QStandardItem* ) ),
108  this, SLOT( groupRenamed( QStandardItem* ) ) );
109 
110  QMenu *groupMenu = new QMenu( tr( "Group actions" ), this );
111  connect( actnGroupSymbols, SIGNAL( triggered() ), this, SLOT( groupSymbolsAction() ) );
112  groupMenu->addAction( actnGroupSymbols );
113  connect( actnFinishGrouping, SIGNAL( triggered() ), this, SLOT( groupSymbolsAction() ) );
114  actnFinishGrouping->setVisible( false );
115  groupMenu->addAction( actnFinishGrouping );
116  groupMenu->addAction( actnEditSmartGroup );
117  btnManageGroups->setMenu( groupMenu );
118 
119  connect( searchBox, SIGNAL( textChanged( QString ) ), this, SLOT( filterSymbols( QString ) ) );
120  tagsLineEdit->installEventFilter( this );
121 
122  // Context menu for groupTree
123  groupTree->setContextMenuPolicy( Qt::CustomContextMenu );
124  connect( groupTree, SIGNAL( customContextMenuRequested( const QPoint& ) ),
125  this, SLOT( grouptreeContextMenu( const QPoint& ) ) );
126 
127  // Context menu for listItems
128  listItems->setContextMenuPolicy( Qt::CustomContextMenu );
129  connect( listItems, SIGNAL( customContextMenuRequested( const QPoint& ) ),
130  this, SLOT( listitemsContextMenu( const QPoint& ) ) );
131 
132  // Menu for the "Add item" toolbutton when in colorramp mode
133  QStringList rampTypes;
134  rampTypes << tr( "Gradient" ) << tr( "Random" ) << tr( "ColorBrewer" );
135  rampTypes << tr( "cpt-city" ); // todo, only for rasters?
136  mMenuBtnAddItemColorRamp = new QMenu( this );
137  Q_FOREACH ( const QString& rampType, rampTypes )
138  mMenuBtnAddItemColorRamp->addAction( new QAction( rampType, this ) );
139  connect( mMenuBtnAddItemColorRamp, SIGNAL( triggered( QAction* ) ),
140  this, SLOT( addColorRamp( QAction* ) ) );
141 
142  // Context menu for symbols/colorramps. The menu entries for every group are created when displaying the menu.
143  mGroupMenu = new QMenu( this );
145  mGroupListMenu->setTitle( tr( "Add to group" ) );
146  mGroupListMenu->setEnabled( false );
148  actnUngroup->setData( 0 );
149  connect( actnUngroup, SIGNAL( triggered( bool ) ), this, SLOT( groupSelectedSymbols() ) );
150  mGroupMenu->addAction( actnUngroup );
151  mGroupMenu->addSeparator()->setParent( this );
152  mGroupMenu->addAction( actnRemoveItem );
153  mGroupMenu->addAction( actnEditItem );
154  mGroupMenu->addSeparator()->setParent( this );
155  mGroupMenu->addAction( actnExportAsPNG );
156  mGroupMenu->addAction( actnExportAsSVG );
157 
158  // Context menu for the group tree
159  mGroupTreeContextMenu = new QMenu( this );
160  connect( actnEditSmartGroup, SIGNAL( triggered( bool ) ), this, SLOT( editSmartgroupAction() ) );
161  mGroupTreeContextMenu->addAction( actnEditSmartGroup );
162  connect( actnAddGroup, SIGNAL( triggered( bool ) ), this, SLOT( addGroup() ) );
163  mGroupTreeContextMenu->addAction( actnAddGroup );
164  connect( actnRemoveGroup, SIGNAL( triggered( bool ) ), this, SLOT( removeGroup() ) );
165  mGroupTreeContextMenu->addAction( actnRemoveGroup );
166 
168 }
169 
171 {
172  if ( mModified )
173  {
174  mStyle->save();
175  }
176 
177  QSettings settings;
178  settings.setValue( "/Windows/StyleV2Manager/geometry", saveGeometry() );
179  settings.setValue( "/Windows/StyleV2Manager/splitter", mSplitter->saveState() );
180 }
181 
183 {
184 #if 0
185  // save current selection index in types combo
186  int current = ( tabItemType->count() > 0 ? tabItemType->currentIndex() : 0 );
187 
188 // no counting of style items
189  int markerCount = 0, lineCount = 0, fillCount = 0;
190 
191  QStringList symbolNames = mStyle->symbolNames();
192  for ( int i = 0; i < symbolNames.count(); ++i )
193  {
194  switch ( mStyle->symbolRef( symbolNames[i] )->type() )
195  {
196  case QgsSymbolV2::Marker:
197  markerCount++;
198  break;
199  case QgsSymbolV2::Line:
200  lineCount++;
201  break;
202  case QgsSymbolV2::Fill:
203  fillCount++;
204  break;
205  default:
206  Q_ASSERT( 0 && "unknown symbol type" );
207  break;
208  }
209  }
210 
211  cboItemType->clear();
212  cboItemType->addItem( tr( "Marker symbol (%1)" ).arg( markerCount ), QVariant( QgsSymbolV2::Marker ) );
213  cboItemType->addItem( tr( "Line symbol (%1)" ).arg( lineCount ), QVariant( QgsSymbolV2::Line ) );
214  cboItemType->addItem( tr( "Fill symbol (%1)" ).arg( fillCount ), QVariant( QgsSymbolV2::Fill ) );
215 
216  cboItemType->addItem( tr( "Color ramp (%1)" ).arg( mStyle->colorRampCount() ), QVariant( 3 ) );
217 
218  // update current index to previous selection
219  cboItemType->setCurrentIndex( current );
220 #endif
221 }
222 
224 {
225  // when in Color Ramp tab, add menu to add item button and hide "Export symbols as PNG/SVG"
226  bool flag = currentItemType() != 3;
227  btnAddItem->setMenu( flag ? nullptr : mMenuBtnAddItemColorRamp );
228  actnExportAsPNG->setVisible( flag );
229  actnExportAsSVG->setVisible( flag );
230 
231  // set icon and grid size, depending on type
232  if ( currentItemType() == 1 || currentItemType() == 3 )
233  {
234  listItems->setIconSize( QSize( 75, 50 ) );
235  listItems->setGridSize( QSize( 100, 80 ) );
236  }
237  else
238  {
239  listItems->setIconSize( QSize( 50, 50 ) );
240  listItems->setGridSize( QSize( 75, 80 ) );
241  }
242 
243  populateList();
244 }
245 
247 {
248  if ( currentItemType() > 3 )
249  {
250  Q_ASSERT( 0 && "not implemented" );
251  return;
252  }
253  groupChanged( groupTree->selectionModel()->currentIndex() );
254 }
255 
256 void QgsStyleV2ManagerDialog::populateSymbols( const QStringList& symbolNames, bool check )
257 {
258  QStandardItemModel* model = qobject_cast<QStandardItemModel*>( listItems->model() );
259  model->clear();
260 
261  int type = currentItemType();
262 
263  for ( int i = 0; i < symbolNames.count(); ++i )
264  {
265  QString name = symbolNames[i];
266  QgsSymbolV2* symbol = mStyle->symbol( name );
267  if ( symbol && symbol->type() == type )
268  {
269  QStandardItem* item = new QStandardItem( name );
270  QIcon icon = QgsSymbolLayerV2Utils::symbolPreviewIcon( symbol, listItems->iconSize() );
271  item->setIcon( icon );
272  item->setData( name ); // used to find out original name when user edited the name
273  item->setCheckable( check );
274  item->setToolTip( name );
275  // add to model
276  model->appendRow( item );
277  }
278  delete symbol;
279  }
281  symbolSelected( listItems->currentIndex() );
282 }
283 
284 
285 void QgsStyleV2ManagerDialog::populateColorRamps( const QStringList& colorRamps, bool check )
286 {
287  QStandardItemModel* model = qobject_cast<QStandardItemModel*>( listItems->model() );
288  model->clear();
289 
290  for ( int i = 0; i < colorRamps.count(); ++i )
291  {
292  QString name = colorRamps[i];
293  QgsVectorColorRampV2* ramp = mStyle->colorRamp( name );
294 
295  QStandardItem* item = new QStandardItem( name );
296  QIcon icon = QgsSymbolLayerV2Utils::colorRampPreviewIcon( ramp, listItems->iconSize() );
297  item->setIcon( icon );
298  item->setData( name ); // used to find out original name when user edited the name
299  item->setCheckable( check );
300  item->setToolTip( name );
301  model->appendRow( item );
302  delete ramp;
303  }
305  symbolSelected( listItems->currentIndex() );
306 }
307 
309 {
310  switch ( tabItemType->currentIndex() )
311  {
312  case 0:
313  return QgsSymbolV2::Marker;
314  case 1:
315  return QgsSymbolV2::Line;
316  case 2:
317  return QgsSymbolV2::Fill;
318  case 3:
319  return 3;
320  default:
321  return 0;
322  }
323 }
324 
326 {
327  QModelIndex index = listItems->selectionModel()->currentIndex();
328  if ( !index.isValid() )
329  return QString();
330  return index.model()->data( index, 0 ).toString();
331 }
332 
334 {
335  bool changed = false;
336  if ( currentItemType() < 3 )
337  {
338  changed = addSymbol();
339  }
340  else if ( currentItemType() == 3 )
341  {
342  changed = addColorRamp();
343  }
344  else
345  {
346  Q_ASSERT( 0 && "not implemented" );
347  }
348 
349  if ( changed )
350  {
351  populateList();
352  populateTypes();
353  }
354 }
355 
357 {
358  // create new symbol with current type
359  QgsSymbolV2* symbol;
360  QString name = tr( "new symbol" );
361  switch ( currentItemType() )
362  {
363  case QgsSymbolV2::Marker:
364  symbol = new QgsMarkerSymbolV2();
365  name = tr( "new marker" );
366  break;
367  case QgsSymbolV2::Line:
368  symbol = new QgsLineSymbolV2();
369  name = tr( "new line" );
370  break;
371  case QgsSymbolV2::Fill:
372  symbol = new QgsFillSymbolV2();
373  name = tr( "new fill symbol" );
374  break;
375  default:
376  Q_ASSERT( 0 && "unknown symbol type" );
377  return false;
378  }
379 
380  // get symbol design
381  // NOTE : Set the parent widget as "this" to notify the Symbol selector
382  // that, it is being called by Style Manager, so recursive calling
383  // of style manager and symbol selector can be arrested
384  // See also: editSymbol()
385  QgsSymbolV2SelectorDialog dlg( symbol, mStyle, nullptr, this );
386  if ( dlg.exec() == 0 )
387  {
388  delete symbol;
389  return false;
390  }
391 
392  // get unique name
393  bool nameInvalid = true;
394 
395  while ( nameInvalid )
396  {
397  bool ok;
398  name = QInputDialog::getText( this, tr( "Symbol Name" ),
399  tr( "Please enter a name for new symbol:" ),
400  QLineEdit::Normal, name, &ok );
401  if ( !ok )
402  {
403  delete symbol;
404  return false;
405  }
406  // validate name
407  if ( name.isEmpty() )
408  {
409  QMessageBox::warning( this, tr( "Save symbol" ),
410  tr( "Cannot save symbol without name. Enter a name." ) );
411  }
412  else if ( mStyle->symbolNames().contains( name ) )
413  {
414  int res = QMessageBox::warning( this, tr( "Save symbol" ),
415  tr( "Symbol with name '%1' already exists. Overwrite?" )
416  .arg( name ),
417  QMessageBox::Yes | QMessageBox::No );
418  if ( res == QMessageBox::Yes )
419  {
420  nameInvalid = false;
421  }
422  }
423  else
424  {
425  // valid name
426  nameInvalid = false;
427  }
428  }
429 
430  // add new symbol to style and re-populate the list
431  mStyle->addSymbol( name, symbol, true );
432  // TODO groups and tags
433  mModified = true;
434  return true;
435 }
436 
437 
439 {
440  // let the user choose the color ramp type if rampType is not given
441  bool ok = true;
442  if ( rampType.isEmpty() )
443  {
444  QStringList rampTypes;
445  rampTypes << tr( "Gradient" ) << tr( "Random" ) << tr( "ColorBrewer" );
446  rampTypes << tr( "cpt-city" ); // todo, only for rasters?
447  rampType = QInputDialog::getItem( parent, tr( "Color ramp type" ),
448  tr( "Please select color ramp type:" ), rampTypes, 0, false, &ok );
449  }
450  if ( !ok || rampType.isEmpty() )
451  return QString();
452 
453  QString name = tr( "new ramp" );
454 
455  QgsVectorColorRampV2 *ramp = nullptr;
456  if ( rampType == tr( "Gradient" ) )
457  {
459  QgsVectorGradientColorRampV2Dialog dlg( gradRamp, parent );
460  if ( !dlg.exec() )
461  {
462  delete gradRamp;
463  return QString();
464  }
465  ramp = gradRamp;
466  name = tr( "new gradient ramp" );
467  }
468  else if ( rampType == tr( "Random" ) )
469  {
471  QgsVectorRandomColorRampV2Dialog dlg( randRamp, parent );
472  if ( !dlg.exec() )
473  {
474  delete randRamp;
475  return QString();
476  }
477  ramp = randRamp;
478  name = tr( "new random ramp" );
479  }
480  else if ( rampType == tr( "ColorBrewer" ) )
481  {
483  QgsVectorColorBrewerColorRampV2Dialog dlg( brewerRamp, parent );
484  if ( !dlg.exec() )
485  {
486  delete brewerRamp;
487  return QString();
488  }
489  ramp = brewerRamp;
490  name = brewerRamp->schemeName() + QString::number( brewerRamp->colors() );
491  }
492  else if ( rampType == tr( "cpt-city" ) )
493  {
494  QgsCptCityColorRampV2* cptCityRamp = new QgsCptCityColorRampV2( "", "" );
495  QgsCptCityColorRampV2Dialog dlg( cptCityRamp, parent );
496  if ( !dlg.exec() )
497  {
498  delete cptCityRamp;
499  return QString();
500  }
501  // name = dlg.selectedName();
502  name = QFileInfo( cptCityRamp->schemeName() ).baseName() + cptCityRamp->variantName();
503  if ( dlg.saveAsGradientRamp() )
504  {
505  ramp = cptCityRamp->cloneGradientRamp();
506  delete cptCityRamp;
507  }
508  else
509  {
510  ramp = cptCityRamp;
511  }
512  }
513  else
514  {
515  // Q_ASSERT( 0 && "invalid ramp type" );
516  // bailing out is rather harsh!
517  QgsDebugMsg( "invalid ramp type " + rampType );
518  return QString();
519  }
520 
521  // get unique name
522  bool nameInvalid = true;
523 
524  while ( nameInvalid )
525  {
526  bool ok;
527  name = QInputDialog::getText( parent, tr( "Color Ramp Name" ),
528  tr( "Please enter a name for new color ramp:" ),
529  QLineEdit::Normal, name, &ok );
530  if ( !ok )
531  {
532  delete ramp;
533  return QString();
534  }
535  // validate name
536  if ( name.isEmpty() )
537  {
538  QMessageBox::warning( parent, tr( "Save Color Ramp" ),
539  tr( "Cannot save color ramp without name. Enter a name." ) );
540  }
541  else if ( style->colorRampNames().contains( name ) )
542  {
543  int res = QMessageBox::warning( parent, tr( "Save color ramp" ),
544  tr( "Color ramp with name '%1' already exists. Overwrite?" )
545  .arg( name ),
546  QMessageBox::Yes | QMessageBox::No );
547  if ( res == QMessageBox::Yes )
548  {
549  nameInvalid = false;
550  }
551  }
552  else
553  {
554  // valid name
555  nameInvalid = false;
556  }
557  }
558 
559  // add new symbol to style and re-populate the list
560  style->addColorRamp( name, ramp, true );
561  // TODO groups and tags, using saveColorRamp
562  return name;
563 }
564 
565 
567 {
568  return addColorRamp( nullptr );
569 }
570 
572 {
573  // pass the action text, which is the color ramp type
574  QString rampName = addColorRampStatic( this, mStyle,
575  action ? action->text() : QString() );
576  if ( !rampName.isEmpty() )
577  {
578  mModified = true;
579  populateList();
580  return true;
581  }
582 
583  return false;
584 }
585 
587 {
588  bool changed = false;
589  if ( currentItemType() < 3 )
590  {
591  changed = editSymbol();
592  }
593  else if ( currentItemType() == 3 )
594  {
595  changed = editColorRamp();
596  }
597  else
598  {
599  Q_ASSERT( 0 && "not implemented" );
600  }
601 
602  if ( changed )
603  populateList();
604 }
605 
607 {
608  QString symbolName = currentItemName();
609  if ( symbolName.isEmpty() )
610  return false;
611 
612  QgsSymbolV2* symbol = mStyle->symbol( symbolName );
613 
614  // let the user edit the symbol and update list when done
615  QgsSymbolV2SelectorDialog dlg( symbol, mStyle, nullptr, this );
616  if ( dlg.exec() == 0 )
617  {
618  delete symbol;
619  return false;
620  }
621 
622  // by adding symbol to style with the same name the old effectively gets overwritten
623  mStyle->addSymbol( symbolName, symbol, true );
624  mModified = true;
625  return true;
626 }
627 
629 {
631  if ( name.isEmpty() )
632  return false;
633 
634  QgsVectorColorRampV2* ramp = mStyle->colorRamp( name );
635 
636  if ( ramp->type() == "gradient" )
637  {
638  QgsVectorGradientColorRampV2* gradRamp = static_cast<QgsVectorGradientColorRampV2*>( ramp );
639  QgsVectorGradientColorRampV2Dialog dlg( gradRamp, this );
640  if ( !dlg.exec() )
641  {
642  delete ramp;
643  return false;
644  }
645  }
646  else if ( ramp->type() == "random" )
647  {
648  QgsVectorRandomColorRampV2* randRamp = static_cast<QgsVectorRandomColorRampV2*>( ramp );
649  QgsVectorRandomColorRampV2Dialog dlg( randRamp, this );
650  if ( !dlg.exec() )
651  {
652  delete ramp;
653  return false;
654  }
655  }
656  else if ( ramp->type() == "colorbrewer" )
657  {
658  QgsVectorColorBrewerColorRampV2* brewerRamp = static_cast<QgsVectorColorBrewerColorRampV2*>( ramp );
659  QgsVectorColorBrewerColorRampV2Dialog dlg( brewerRamp, this );
660  if ( !dlg.exec() )
661  {
662  delete ramp;
663  return false;
664  }
665  }
666  else if ( ramp->type() == "cpt-city" )
667  {
668  QgsCptCityColorRampV2* cptCityRamp = static_cast<QgsCptCityColorRampV2*>( ramp );
669  QgsCptCityColorRampV2Dialog dlg( cptCityRamp, this );
670  if ( !dlg.exec() )
671  {
672  delete ramp;
673  return false;
674  }
675  if ( dlg.saveAsGradientRamp() )
676  {
677  ramp = cptCityRamp->cloneGradientRamp();
678  delete cptCityRamp;
679  }
680  }
681  else
682  {
683  Q_ASSERT( 0 && "invalid ramp type" );
684  }
685 
686  mStyle->addColorRamp( name, ramp, true );
687  mModified = true;
688  return true;
689 }
690 
691 
693 {
694  bool changed = false;
695  if ( currentItemType() < 3 )
696  {
697  changed = removeSymbol();
698  }
699  else if ( currentItemType() == 3 )
700  {
701  changed = removeColorRamp();
702  }
703  else
704  {
705  Q_ASSERT( 0 && "not implemented" );
706  }
707 
708  if ( changed )
709  {
710  populateList();
711  populateTypes();
712  }
713 }
714 
716 {
717  QModelIndexList indexes = listItems->selectionModel()->selectedIndexes();
718  if ( QMessageBox::Yes != QMessageBox::question( this, tr( "Confirm removal" ),
719  QString( tr( "Do you really want to remove %n symbol(s)?", nullptr, indexes.count() ) ),
720  QMessageBox::Yes,
721  QMessageBox::No ) )
722  return false;
723 
724  Q_FOREACH ( const QModelIndex& index, indexes )
725  {
726  QString symbolName = index.data().toString();
727  // delete from style and update list
728  if ( !symbolName.isEmpty() )
729  mStyle->removeSymbol( symbolName );
730  }
731  mModified = true;
732  return true;
733 }
734 
736 {
737  QModelIndexList indexes = listItems->selectionModel()->selectedIndexes();
738  if ( QMessageBox::Yes != QMessageBox::question( this, tr( "Confirm removal" ),
739  QString( tr( "Do you really want to remove %n ramps(s)?", nullptr, indexes.count() ) ),
740  QMessageBox::Yes,
741  QMessageBox::No ) )
742  return false;
743 
744  Q_FOREACH ( const QModelIndex& index, indexes )
745  {
746  QString rampName = index.data().toString();
747  // delete from style and update list
748  if ( !rampName.isEmpty() )
749  mStyle->removeColorRamp( rampName );
750  }
751  mModified = true;
752  return true;
753 }
754 
756 {
757  // an item has been edited
758  QString oldName = item->data().toString();
759 
760  bool changed = false;
761  if ( currentItemType() < 3 )
762  {
763  changed = mStyle->renameSymbol( oldName, item->text() );
764  }
765  else if ( currentItemType() == 3 )
766  {
767  changed = mStyle->renameColorRamp( oldName, item->text() );
768  }
769 
770  if ( changed )
771  {
772  populateList();
773  mModified = true;
774  }
775  else
776  {
777  QMessageBox::critical( this, tr( "Cannot rename item" ),
778  tr( "Name is already taken by another item. Choose a different name." ) );
779  item->setText( oldName );
780  }
781 }
782 
784 {
785  QString dir = QFileDialog::getExistingDirectory( this, tr( "Exported selected symbols as PNG" ),
786  QDir::home().absolutePath(),
787  QFileDialog::ShowDirsOnly
788  | QFileDialog::DontResolveSymlinks );
789  exportSelectedItemsImages( dir, "png", QSize( 32, 32 ) );
790 }
791 
793 {
794  QString dir = QFileDialog::getExistingDirectory( this, tr( "Exported selected symbols as SVG" ),
795  QDir::home().absolutePath(),
796  QFileDialog::ShowDirsOnly
797  | QFileDialog::DontResolveSymlinks );
798  exportSelectedItemsImages( dir, "svg", QSize( 32, 32 ) );
799 }
800 
801 
803 {
804  if ( dir.isEmpty() )
805  return;
806 
807  QModelIndexList indexes = listItems->selectionModel()->selection().indexes();
808  Q_FOREACH ( const QModelIndex& index, indexes )
809  {
810  QString name = index.data().toString();
811  QString path = dir + '/' + name + '.' + format;
812  QgsSymbolV2 *sym = mStyle->symbol( name );
813  sym->exportImage( path, format, size );
814  }
815 }
816 
818 {
820  dlg.exec();
821 }
822 
824 {
826  dlg.exec();
827  populateList();
828  populateGroups();
829 }
830 
832 {
833  QFont font = item->font();
834  font.setBold( true );
835  item->setFont( font );
836 }
837 
839 {
840  QStandardItemModel *model = qobject_cast<QStandardItemModel*>( groupTree->model() );
841  model->clear();
842 
843  QStandardItem *allSymbols = new QStandardItem( tr( "All Symbols" ) );
844  allSymbols->setData( "all" );
845  allSymbols->setEditable( false );
846  setBold( allSymbols );
847  model->appendRow( allSymbols );
848 
849  QStandardItem *group = new QStandardItem( "" ); //require empty name to get first order groups
850  group->setData( "groups" );
851  group->setEditable( false );
852  buildGroupTree( group );
853  group->setText( tr( "Groups" ) );//set title later
854  QStandardItem *ungrouped = new QStandardItem( tr( "Ungrouped" ) );
855  ungrouped->setData( 0 );
856  setBold( ungrouped );
857  setBold( group );
858  group->appendRow( ungrouped );
859  model->appendRow( group );
860 
861  QStandardItem *tag = new QStandardItem( tr( "Smart Groups" ) );
862  tag->setData( "smartgroups" );
863  tag->setEditable( false );
864  setBold( tag );
867  while ( i != sgMap.constEnd() )
868  {
869  QStandardItem *item = new QStandardItem( i.value() );
870  item->setData( i.key() );
871  tag->appendRow( item );
872  ++i;
873  }
874  model->appendRow( tag );
875 
876  // expand things in the grouo tree
877  int rows = model->rowCount( model->indexFromItem( model->invisibleRootItem() ) );
878  for ( int i = 0; i < rows; i++ )
879  {
880  groupTree->setExpanded( model->indexFromItem( model->item( i ) ), true );
881  }
882 }
883 
885 {
886  QgsSymbolGroupMap groups = mStyle->childGroupNames( parent->text() );
888  while ( i != groups.constEnd() )
889  {
890  QStandardItem *item = new QStandardItem( i.value() );
891  item->setData( i.key() );
892  parent->appendRow( item );
893  buildGroupTree( item );
894  ++i;
895  }
896 }
897 
899 {
900  QStringList symbolNames;
901  QStringList groupSymbols;
902 
904  if ( currentItemType() > 3 )
905  {
906  QgsDebugMsg( "Entity not implemented" );
907  return;
908  }
909 
910  QString category = index.data( Qt::UserRole + 1 ).toString();
911  if ( category == "all" || category == "groups" || category == "smartgroups" )
912  {
913  enableGroupInputs( false );
914  if ( category == "groups" || category == "smartgroups" )
915  {
916  btnAddGroup->setEnabled( true );
917  actnAddGroup->setEnabled( true );
918  }
919  symbolNames = currentItemType() < 3 ? mStyle->symbolNames() : mStyle->colorRampNames();
920  }
921  else
922  {
923  //determine groups and tags
924  if ( index.parent().data( Qt::UserRole + 1 ) == "smartgroups" )
925  {
926  btnAddGroup->setEnabled( false );
927  actnAddGroup->setEnabled( false );
928  btnRemoveGroup->setEnabled( true );
929  actnRemoveGroup->setEnabled( true );
930  btnManageGroups->setEnabled( true );
931  int groupId = index.data( Qt::UserRole + 1 ).toInt();
932  symbolNames = mStyle->symbolsOfSmartgroup( type, groupId );
933  }
934  else // then it must be a group
935  {
936  if (( !index.data( Qt::UserRole + 1 ).toInt() && ( index.data() == "Ungrouped" ) ) || mGrouppingMode )
937  enableGroupInputs( false );
938  else
939  enableGroupInputs( true );
940  int groupId = index.data( Qt::UserRole + 1 ).toInt();
941  symbolNames = mStyle->symbolsOfGroup( type, groupId );
942  if ( mGrouppingMode && groupId )
943  {
944  groupSymbols = symbolNames;
945  symbolNames += mStyle->symbolsOfGroup( type, 0 );
946  }
947  }
948  }
949 
950  if ( currentItemType() < 3 )
951  {
952  populateSymbols( symbolNames, mGrouppingMode );
953  }
954  else if ( currentItemType() == 3 )
955  {
956  populateColorRamps( symbolNames, mGrouppingMode );
957  }
958  if ( mGrouppingMode )
959  setSymbolsChecked( groupSymbols );
960 
961  actnEditSmartGroup->setVisible( false );
962  actnAddGroup->setVisible( false );
963  actnRemoveGroup->setVisible( false );
964  actnGroupSymbols->setVisible( false );
965  actnFinishGrouping->setVisible( false );
966 
967  if ( index.parent().isValid() && ( index.data().toString() != "Ungrouped" ) )
968  {
969  if ( index.parent().data( Qt::UserRole + 1 ).toString() == "smartgroups" )
970  {
971  actnEditSmartGroup->setVisible( !mGrouppingMode );
972  }
973  else
974  {
975  actnAddGroup->setVisible( !mGrouppingMode );
976  actnGroupSymbols->setVisible( !mGrouppingMode );
977  actnFinishGrouping->setVisible( mGrouppingMode );
978  }
979  actnRemoveGroup->setVisible( true );
980  }
981  else if ( index.data( Qt::UserRole + 1 ) == "groups" || index.data( Qt::UserRole + 1 ) == "smartgroups" )
982  {
983  actnAddGroup->setVisible( !mGrouppingMode );
984  }
985 }
986 
988 {
989  QStandardItemModel *model = qobject_cast<QStandardItemModel*>( groupTree->model() );
990  QModelIndex parentIndex = groupTree->currentIndex();
991 
992  // Violation 1: Creating sub-groups of system defined groups
993  QString parentData = parentIndex.data( Qt::UserRole + 1 ).toString();
994  if ( parentData == "all" || ( parentIndex.data() == "Ungrouped" && parentData == "0" ) )
995  {
996  int err = QMessageBox::critical( this, tr( "Invalid Selection" ),
997  tr( "The parent group you have selected is not user editable.\n"
998  "Kindly select a user defined group." ) );
999  if ( err )
1000  return;
1001  }
1002 
1003  // Violation 2: Creating a nested tag
1004  if ( parentIndex.parent().data( Qt::UserRole + 1 ).toString() == "smartgroups" )
1005  {
1006  int err = QMessageBox::critical( this, tr( "Operation Not Allowed" ),
1007  tr( "Creation of nested smart groups are not allowed\n"
1008  "Select the 'Smart Group' to create a new group." ) );
1009  if ( err )
1010  return;
1011  }
1012 
1013  QString itemName;
1014  bool isGroup = true;
1015 
1016  int id;
1017  if ( parentData == "smartgroups" )
1018  {
1019  // create a smart group
1020 
1021  QgsSmartGroupEditorDialog dlg( mStyle, this );
1022  if ( dlg.exec() == QDialog::Rejected )
1023  return;
1024  id = mStyle->addSmartgroup( dlg.smartgroupName(), dlg.conditionOperator(), dlg.conditionMap() );
1025  if ( !id )
1026  return;
1027  itemName = dlg.smartgroupName();
1028  isGroup = false;
1029  }
1030  else
1031  {
1032  // create a simple child-group to the selected
1033 
1034  itemName = QString( tr( "New Group" ) );
1035  int parentid = ( parentData == "groups" ) ? 0 : parentData.toInt(); // parentid is 0 for top-level groups
1036  id = mStyle->addGroup( itemName, parentid );
1037  if ( !id )
1038  {
1039  QMessageBox::critical( this, tr( "Error!" ),
1040  tr( "New group could not be created.\n"
1041  "There was a problem with your symbol database." ) );
1042  return;
1043  }
1044  }
1045 
1046  QStandardItem *parentItem = model->itemFromIndex( parentIndex );
1047  QStandardItem *childItem = new QStandardItem( itemName );
1048  childItem->setData( id );
1049  parentItem->appendRow( childItem );
1050 
1051  groupTree->setCurrentIndex( childItem->index() );
1052  if ( isGroup )
1053  {
1054  groupTree->edit( childItem->index() );
1055  }
1056 }
1057 
1059 {
1060  QStandardItemModel *model = qobject_cast<QStandardItemModel*>( groupTree->model() );
1061  QModelIndex index = groupTree->currentIndex();
1062 
1063  // Violation: removing system groups
1064  QString data = index.data( Qt::UserRole + 1 ).toString();
1065  if ( data == "all" || data == "groups" || data == "smartgroups" || index.data() == "Ungrouped" )
1066  {
1067  int err = QMessageBox::critical( this, tr( "Invalid selection" ),
1068  tr( "Cannot delete system defined categories.\n"
1069  "Kindly select a group or smart group you might want to delete." ) );
1070  if ( err )
1071  return;
1072  }
1073 
1074  QStandardItem *parentItem = model->itemFromIndex( index.parent() );
1075  if ( parentItem->data( Qt::UserRole + 1 ).toString() == "smartgroups" )
1076  {
1077  mStyle->remove( QgsStyleV2::SmartgroupEntity, index.data( Qt::UserRole + 1 ).toInt() );
1078  }
1079  else
1080  {
1081  mStyle->remove( QgsStyleV2::GroupEntity, index.data( Qt::UserRole + 1 ).toInt() );
1082  QStandardItem *item = model->itemFromIndex( index );
1083  if ( item->hasChildren() )
1084  {
1085  QStandardItem *parent = item->parent();
1086  for ( int i = 0; i < item->rowCount(); i++ )
1087  {
1088  parent->appendRow( item->takeChild( i ) );
1089  }
1090  }
1091  }
1092  parentItem->removeRow( index.row() );
1093 }
1094 
1096 {
1097  QString data = item->data( Qt::UserRole + 1 ).toString();
1098  QgsDebugMsg( "Symbol group edited: data=" + data + " text=" + item->text() );
1099  int id = item->data( Qt::UserRole + 1 ).toInt();
1100  QString name = item->text();
1101  if ( item->parent()->data( Qt::UserRole + 1 ) == "smartgroups" )
1102  {
1104  }
1105  else
1106  {
1107  mStyle->rename( QgsStyleV2::GroupEntity, id, name );
1108  }
1109 }
1110 
1112 {
1113 
1114  QStandardItemModel *treeModel = qobject_cast<QStandardItemModel*>( groupTree->model() );
1115  QStandardItemModel *model = qobject_cast<QStandardItemModel*>( listItems->model() );
1116 
1117  if ( mGrouppingMode )
1118  {
1119  mGrouppingMode = false;
1120  actnGroupSymbols->setVisible( true );
1121  actnFinishGrouping->setVisible( false );
1122  // disconnect slot which handles regrouping
1123  disconnect( model, SIGNAL( itemChanged( QStandardItem* ) ),
1124  this, SLOT( regrouped( QStandardItem* ) ) );
1125 
1126  // disabel all items except groups in groupTree
1128  groupChanged( groupTree->currentIndex() );
1129 
1130  // Finally: Reconnect all Symbol editing functionalities
1131  connect( treeModel, SIGNAL( itemChanged( QStandardItem* ) ),
1132  this, SLOT( groupRenamed( QStandardItem* ) ) );
1133  connect( model, SIGNAL( itemChanged( QStandardItem* ) ),
1134  this, SLOT( itemChanged( QStandardItem* ) ) );
1135  // Reset the selection mode
1136  listItems->setSelectionMode( QAbstractItemView::ExtendedSelection );
1137  }
1138  else
1139  {
1140  bool validGroup = false;
1141  // determine whether it is a valid group
1142  QModelIndex present = groupTree->currentIndex();
1143  while ( present.parent().isValid() )
1144  {
1145  if ( present.parent().data() == "Groups" )
1146  {
1147  validGroup = true;
1148  break;
1149  }
1150  else
1151  present = present.parent();
1152  }
1153  if ( !validGroup )
1154  return;
1155 
1156  mGrouppingMode = true;
1157  // Change visibility of actions
1158  actnGroupSymbols->setVisible( false );
1159  actnFinishGrouping->setVisible( true );
1160  // Remove all Symbol editing functionalities
1161  disconnect( treeModel, SIGNAL( itemChanged( QStandardItem* ) ),
1162  this, SLOT( groupRenamed( QStandardItem* ) ) );
1163  disconnect( model, SIGNAL( itemChanged( QStandardItem* ) ),
1164  this, SLOT( itemChanged( QStandardItem* ) ) );
1165 
1166  // disabel all items except groups in groupTree
1167  enableItemsForGroupingMode( false );
1168  groupChanged( groupTree->currentIndex() );
1169  btnManageGroups->setEnabled( true );
1170 
1171 
1172  // Connect to slot which handles regrouping
1173  connect( model, SIGNAL( itemChanged( QStandardItem* ) ),
1174  this, SLOT( regrouped( QStandardItem* ) ) );
1175 
1176  // No selection should be possible
1177  listItems->setSelectionMode( QAbstractItemView::NoSelection );
1178  }
1179 }
1180 
1182 {
1184  if ( currentItemType() > 3 )
1185  {
1186  QgsDebugMsg( "Unknown style entity" );
1187  return;
1188  }
1189  int groupid = groupTree->currentIndex().data( Qt::UserRole + 1 ).toInt();
1190  QString symbolName = item->text();
1191  bool regrouped;
1192  if ( item->checkState() == Qt::Checked )
1193  regrouped = mStyle->group( type, symbolName, groupid );
1194  else
1195  regrouped = mStyle->group( type, symbolName, 0 );
1196  if ( !regrouped )
1197  {
1198  int er = QMessageBox::critical( this, tr( "Database Error" ),
1199  tr( "There was a problem with the Symbols database while regrouping." ) );
1200  // call the slot again to get back to normal
1201  if ( er )
1203  }
1204 }
1205 
1207 {
1208  QStandardItemModel *model = qobject_cast<QStandardItemModel*>( listItems->model() );
1209  Q_FOREACH ( const QString& symbol, symbols )
1210  {
1211  QList<QStandardItem*> items = model->findItems( symbol );
1212  Q_FOREACH ( QStandardItem* item, items )
1213  item->setCheckState( Qt::Checked );
1214  }
1215 }
1216 
1218 {
1219  QStringList items;
1220  if ( currentItemType() == 3 )
1221  {
1222  items = mStyle->findSymbols( QgsStyleV2::ColorrampEntity, qword );
1223  populateColorRamps( items );
1224  }
1225  else
1226  {
1227  items = mStyle->findSymbols( QgsStyleV2::SymbolEntity, qword );
1228  populateSymbols( items );
1229  }
1230 }
1231 
1233 {
1234  QModelIndexList indexes = listItems->selectionModel()->selection().indexes();
1235  QStringList addtags;
1236  QStringList removetags;
1237 
1238  QStringList oldtags = mTagList;
1239  QStringList newtags = tagsLineEdit->text().split( ',', QString::SkipEmptyParts );
1240 
1242  if ( currentItemType() < 3 )
1243  {
1244  type = QgsStyleV2::SymbolEntity;
1245  }
1246  else if ( currentItemType() == 3 )
1247  {
1249  }
1250  else
1251  {
1252  QgsDebugMsg( "Unknown Style Entity!" );
1253  return;
1254  }
1255  // compare old with new to find removed tags
1256  Q_FOREACH ( const QString &tag, oldtags )
1257  {
1258  if ( !newtags.contains( tag ) )
1259  removetags.append( tag );
1260  }
1261  if ( !removetags.isEmpty() )
1262  {
1263  Q_FOREACH ( const QModelIndex& index, indexes )
1264  {
1265  mStyle->detagSymbol( type, index.data().toString(), removetags );
1266  }
1267  }
1268  // compare new with old to find added tags
1269  Q_FOREACH ( const QString &tag, newtags )
1270  {
1271  if ( !oldtags.contains( tag ) )
1272  addtags.append( tag );
1273  }
1274  if ( !addtags.isEmpty() )
1275  {
1276  Q_FOREACH ( const QModelIndex& index, indexes )
1277  {
1278  mStyle->tagSymbol( type, index.data().toString(), addtags );
1279  }
1280  }
1281 }
1282 
1284 {
1285  // Populate the tags for the symbol
1286  tagsLineEdit->clear();
1287  if ( index.isValid() )
1288  {
1289  QStandardItem *item = static_cast<QStandardItemModel*>( listItems->model() )->itemFromIndex( index );
1291  mTagList = mStyle->tagsOfSymbol( type, item->data().toString() );
1292  tagsLineEdit->setText( mTagList.join( "," ) );
1293  }
1294 
1295  actnEditItem->setEnabled( index.isValid() && !mGrouppingMode );
1296 }
1297 
1299 {
1300  Q_UNUSED( selected );
1301  Q_UNUSED( deselected );
1302  bool nothingSelected = listItems->selectionModel()->selectedIndexes().empty();
1303  actnRemoveItem->setDisabled( nothingSelected );
1304  mGroupListMenu->setDisabled( nothingSelected );
1305  actnUngroup->setDisabled( nothingSelected );
1306  actnExportAsPNG->setDisabled( nothingSelected );
1307  actnExportAsSVG->setDisabled( nothingSelected );
1308  actnEditItem->setDisabled( nothingSelected );
1309 }
1310 
1312 {
1313  groupTree->setEnabled( enable );
1314  btnAddGroup->setEnabled( enable );
1315  actnAddGroup->setEnabled( enable );
1316  btnRemoveGroup->setEnabled( enable );
1317  actnRemoveGroup->setEnabled( enable );
1318  btnManageGroups->setEnabled( enable || mGrouppingMode ); // always enabled in grouping mode, as it is the only way to leave grouping mode
1319  searchBox->setEnabled( enable );
1320  tagsLineEdit->setEnabled( enable );
1321 }
1322 
1324 {
1325  btnAddGroup->setEnabled( enable );
1326  btnRemoveGroup->setEnabled( enable );
1327  actnRemoveGroup->setEnabled( enable );
1328  btnManageGroups->setEnabled( enable || mGrouppingMode ); // always enabled in grouping mode, as it is the only way to leave grouping mode
1329 }
1330 
1332 {
1333  QStandardItemModel *treeModel = qobject_cast<QStandardItemModel*>( groupTree->model() );
1334  for ( int i = 0; i < treeModel->rowCount(); i++ )
1335  {
1336  if ( treeModel->item( i )->data() != "groups" )
1337  {
1338  treeModel->item( i )->setEnabled( enable );
1339  }
1340  if ( treeModel->item( i )->data() == "groups" )
1341  {
1342  treeModel->item( i )->setEnabled( enable );
1343  for ( int k = 0; k < treeModel->item( i )->rowCount(); k++ )
1344  {
1345  if ( !treeModel->item( i )->child( k )->data().toInt() )
1346  treeModel->item( i )->child( k )->setEnabled( enable );
1347  }
1348  }
1349  if ( treeModel->item( i )->data() == "smartgroups" )
1350  {
1351  for ( int j = 0; j < treeModel->item( i )->rowCount(); j++ )
1352  {
1353  treeModel->item( i )->child( j )->setEnabled( enable );
1354  }
1355  }
1356  }
1357 
1358  // The buttons
1359  // NOTE: if you ever change the layout name in the .ui file edit here too
1360  for ( int i = 0; i < symbolBtnsLayout->count(); i++ )
1361  {
1362  QWidget *w = qobject_cast<QWidget*>( symbolBtnsLayout->itemAt( i )->widget() );
1363  if ( w )
1364  w->setEnabled( enable );
1365  }
1366 
1367  // The actions
1368  actnRemoveItem->setEnabled( enable );
1369  actnEditItem->setEnabled( enable );
1370 }
1371 
1373 {
1374  QPoint globalPos = groupTree->viewport()->mapToGlobal( point );
1375 
1376  QModelIndex index = groupTree->indexAt( point );
1377  QgsDebugMsg( "Now you clicked: " + index.data().toString() );
1378 
1379  if ( index.isValid() && !mGrouppingMode )
1380  mGroupTreeContextMenu->popup( globalPos );
1381 }
1382 
1384 {
1385  QPoint globalPos = listItems->viewport()->mapToGlobal( point );
1386 
1387  // Clear all actions and create new actions for every group
1388  mGroupListMenu->clear();
1389 
1390  QAction* a;
1391  QList<int> groupIds = mStyle->groupIds();
1392  Q_FOREACH ( int groupId, groupIds )
1393  {
1394  a = new QAction( mStyle->groupName( groupId ), mGroupListMenu );
1395  a->setData( groupId );
1396  connect( a, SIGNAL( triggered( bool ) ), this, SLOT( groupSelectedSymbols() ) );
1397  mGroupListMenu->addAction( a );
1398  }
1399 
1400  mGroupMenu->popup( globalPos );
1401 }
1402 
1404 {
1405  QAction* selectedItem = qobject_cast<QAction*>( sender() );
1406 
1407  if ( selectedItem )
1408  {
1410  if ( currentItemType() > 3 )
1411  {
1412  QgsDebugMsg( "unknow entity type" );
1413  return;
1414  }
1415  int groupId = selectedItem->data().toInt();
1416  QModelIndexList indexes = listItems->selectionModel()->selectedIndexes();
1417  Q_FOREACH ( const QModelIndex& index, indexes )
1418  {
1419  mStyle->group( type, index.data().toString(), groupId );
1420  }
1421  populateList();
1422 
1423  QgsDebugMsg( "Selected Action: " + selectedItem->text() );
1424  }
1425 }
1426 
1428 {
1429  QStandardItemModel *treeModel = qobject_cast<QStandardItemModel*>( groupTree->model() );
1430 
1431  // determine whether it is a valid group
1432  QModelIndex present = groupTree->currentIndex();
1433  if ( present.parent().data( Qt::UserRole + 1 ) != "smartgroups" )
1434  {
1435  QMessageBox::critical( this, tr( "Invalid Selection" ),
1436  tr( "You have not selected a Smart Group. Kindly select a Smart Group to edit." ) );
1437  return;
1438  }
1439  QStandardItem* item = treeModel->itemFromIndex( present );
1440 
1441  QgsSmartGroupEditorDialog dlg( mStyle, this );
1442  QgsSmartConditionMap map = mStyle->smartgroup( present.data( Qt::UserRole + 1 ).toInt() );
1443  dlg.setSmartgroupName( item->text() );
1444  dlg.setOperator( mStyle->smartgroupOperator( item->data().toInt() ) );
1445  dlg.setConditionMap( map );
1446 
1447  if ( dlg.exec() == QDialog::Rejected )
1448  return;
1449 
1451  int id = mStyle->addSmartgroup( dlg.smartgroupName(), dlg.conditionOperator(), dlg.conditionMap() );
1452  if ( !id )
1453  {
1454  QMessageBox::critical( this, tr( "Database Error!" ),
1455  tr( "There was some error while editing the smart group." ) );
1456  return;
1457  }
1458  item->setText( dlg.smartgroupName() );
1459  item->setData( id );
1460 
1461  groupChanged( present );
1462 }
1463 
1465 {
1466 
1467  if (( obj == tagsLineEdit ) && ( event->type() == QEvent::FocusOut ) )
1468  {
1469  tagsChanged();
1470  return true;
1471  }
1472  return false;
1473 }
1474 
void customContextMenuRequested(const QPoint &pos)
QStringList tagsOfSymbol(StyleEntity type, const QString &symbol)
return the tags associated with the symbol
Definition: qgsstylev2.cpp:907
QString smartgroupOperator(int id)
returns the operator for the smartgroup
QList< int > groupIds() const
return the ids of all the groups in the style
Definition: qgsstylev2.cpp:478
void setToolTip(const QString &toolTip)
QByteArray toByteArray() const
static unsigned index
virtual bool event(QEvent *e)
void remove(StyleEntity type, int id)
remove the specified entity from the db
Definition: qgsstylev2.cpp:703
QgsVectorColorRampV2 * colorRamp(const QString &name)
return a NEW copy of color ramp
Definition: qgsstylev2.cpp:258
QString getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir, QFlags< QFileDialog::Option > options)
Type type() const
void setupUi(QWidget *widget)
QMenu * mMenuBtnAddItemColorRamp
Menu for the "Add item" toolbutton when in colorramp mode.
void setIcon(const QIcon &icon)
static QIcon colorRampPreviewIcon(QgsVectorColorRampV2 *ramp, QSize size)
virtual QString type() const =0
QString getItem(QWidget *parent, const QString &title, const QString &label, const QStringList &items, int current, bool editable, bool *ok, QFlags< Qt::WindowType > flags, QFlags< Qt::InputMethodHint > inputMethodHints)
bool tagSymbol(StyleEntity type, const QString &symbol, const QStringList &tags)
tags the symbol with the tags in the list
Definition: qgsstylev2.cpp:802
bool group(StyleEntity type, const QString &name, int groupid)
applies the specified group to the symbol or colorramp specified by StyleEntity
Definition: qgsstylev2.cpp:755
void selectedSymbolsChanged(const QItemSelection &selected, const QItemSelection &deselected)
Perform tasks when the selected symbols change.
QStandardItem * invisibleRootItem() const
SymbolType type() const
Definition: qgssymbolv2.h:104
bool addSymbol(const QString &name, QgsSymbolV2 *symbol, bool update=false)
add symbol to style. takes symbol&#39;s ownership
Definition: qgsstylev2.cpp:81
QgsSmartConditionMap conditionMap()
returns the condition map
void setWindowModality(Qt::WindowModality windowModality)
void itemChanged(QStandardItem *item)
void groupChanged(const QModelIndex &)
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
void enableItemsForGroupingMode(bool)
Enables or diables the groupTree items for grouping mode.
QObject * sender() const
QVariant data() const
QStyle * style() const
void tagsChanged()
Listen to tag changes.
const_iterator constBegin() const
void setIcon(const QIcon &icon)
QStringList symbolsOfGroup(StyleEntity type, int groupid)
returns the symbolnames of a given groupid
Definition: qgsstylev2.cpp:539
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
void addAction(QAction *action)
bool contains(const QString &str, Qt::CaseSensitivity cs) const
void removeRow(int row)
QString groupName(int groupId) const
return the group name for the given DB id
Definition: qgsstylev2.cpp:997
int exec()
Line symbol.
Definition: qgssymbolv2.h:79
bool addColorRamp(const QString &name, QgsVectorColorRampV2 *colorRamp, bool update=false)
add color ramp to style. takes ramp&#39;s ownership
Definition: qgsstylev2.cpp:186
const QPixmap * icon() const
bool detagSymbol(StyleEntity type, const QString &symbol, const QStringList &tags)
detags the symbol with the given list
Definition: qgsstylev2.cpp:854
QString join(const QString &separator) const
QString smartgroupName()
returns the value from mNameLineEdit
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QStringList colorRampNames()
return a list of names of color ramps
Definition: qgsstylev2.cpp:274
QString tr(const char *sourceText, const char *disambiguation, int n)
QString text() const
Qt::CheckState checkState() const
Marker symbol.
Definition: qgssymbolv2.h:78
virtual void setData(const QVariant &value, int role)
void finished(int result)
bool save(QString filename=QString())
save style into a file (will use current filename if empty string is passed)
Definition: qgsstylev2.cpp:358
void setBold(bool enable)
void setValue(const QString &key, const QVariant &value)
QSize size() const
void clear()
const char * name() const
bool isValid() const
QString variantName() const
void setEnabled(bool)
QString number(int n, int base)
static QIcon symbolPreviewIcon(QgsSymbolV2 *symbol, QSize size)
QgsSymbolGroupMap childGroupNames(const QString &parent="")
return a map of groupid and names for the given parent group
Definition: qgsstylev2.cpp:492
int count(const T &value) const
bool addSymbol()
add a new symbol to style
void append(const T &value)
bool renameColorRamp(const QString &oldName, const QString &newName)
change ramp&#39;s name
Definition: qgsstylev2.cpp:436
void popup(const QPoint &p, QAction *atAction)
int toInt(bool *ok) const
int colorRampCount()
return count of color ramps
Definition: qgsstylev2.cpp:269
QModelIndex indexFromItem(const QStandardItem *item) const
const Key & key() const
void filterSymbols(const QString &)
filter the symbols based on input search term
StandardButton question(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
void populateSymbols(const QStringList &symbolNames, bool checkable=false)
populate list view with symbols of the current type with the given names
bool restoreGeometry(const QByteArray &geometry)
void populateGroups()
populate the groups
void appendRow(const QList< QStandardItem * > &items)
bool hasChildren() const
int toInt(bool *ok, int base) const
bool isEmpty() const
QStringList mTagList
space to store symbol tags
const QgsSymbolV2 * symbolRef(const QString &name) const
return a const pointer to a symbol (doesn&#39;t create new instance)
Definition: qgsstylev2.cpp:170
bool isEmpty() const
QStandardItem * parent() const
const_iterator constEnd() const
QMenu * mGroupMenu
Context menu for the symbols/colorramps.
void groupRenamed(QStandardItem *)
void rename(StyleEntity type, int id, const QString &newName)
rename the given entity with the specified id
Definition: qgsstylev2.cpp:657
void populateColorRamps(const QStringList &colorRamps, bool checkable=false)
populate list view with color ramps
QList< QStandardItem * > findItems(const QString &text, QFlags< Qt::MatchFlag > flags, int column) const
const T & value() const
void buildGroupTree(QStandardItem *&parent)
build the groups tree
QStringList symbolsOfSmartgroup(StyleEntity type, int id)
returns the symbols for the smartgroup
void exportSelectedItemsImages(const QString &dir, const QString &format, QSize size)
virtual QVariant data(const QModelIndex &index, int role) const =0
void setTitle(const QString &title)
QAction * addSeparator()
void setSymbolsChecked(const QStringList &)
to set symbols checked when in editing mode
QMenu * mGroupTreeContextMenu
Context menu for the group tree.
void populateTypes()
populate combo box with known style items (symbols, color ramps)
QModelIndex parent() const
QgsStyleV2ManagerDialog(QgsStyleV2 *style, QWidget *parent=nullptr)
QStringList symbolNames()
return a list of names of symbols
Definition: qgsstylev2.cpp:180
QgsSymbolGroupMap smartgroupsListMap()
returns the smart groups map with id as key and name as value
QStandardItem * child(int row, int column) const
void setFont(const QFont &font)
QString getText(QWidget *parent, const QString &title, const QString &label, QLineEdit::EchoMode mode, const QString &text, bool *ok, QFlags< Qt::WindowType > flags, QFlags< Qt::InputMethodHint > inputMethodHints)
void setData(const QVariant &userData)
void setEnabled(bool enabled)
QgsSymbolV2 * symbol(const QString &name)
return a NEW copy of symbol
Definition: qgsstylev2.cpp:164
QStandardItem * item(int row, int column) const
void setParent(QObject *parent)
const QFont & font() const
void exportImage(const QString &path, const QString &format, QSize size)
export symbol as image format. PNG and SVG supported
bool eventFilter(QObject *, QEvent *) override
Event filter to capture tagsLineEdit out of focus.
bool mGrouppingMode
Mode to display the symbol list.
void setBold(QStandardItem *)
sets the text of the item with bold font
QgsVectorGradientColorRampV2 * cloneGradientRamp() const
void setText(const QString &text)
QFont font() const
QVariant value(const QString &key, const QVariant &defaultValue) const
void symbolSelected(const QModelIndex &)
Perform symbol specific tasks when selected.
const QAbstractItemModel * model() const
void listitemsContextMenu(QPoint)
Context menu for the listItems ( symbols list )
void groupSymbolsAction()
carryout symbol grouping using check boxes
bool renameSymbol(const QString &oldName, const QString &newName)
change symbol&#39;s name
Definition: qgsstylev2.cpp:404
QVariant data(int role) const
QByteArray saveGeometry() const
void setOperator(const QString &)
sets the operator AND/OR
QStandardItem * itemFromIndex(const QModelIndex &index) const
QAction * addMenu(QMenu *menu)
void grouptreeContextMenu(QPoint)
Context menu for the groupTree.
Fill symbol.
Definition: qgssymbolv2.h:80
StandardButton critical(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
virtual int rowCount(const QModelIndex &parent) const
QStringList split(const QString &sep, const QString &str, bool allowEmptyEntries)
QModelIndex index() const
int rowCount() const
void setSmartgroupName(const QString &)
sets the smart group Name
StandardButton warning(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
void editSmartgroupAction()
edit the selected smart group
bool removeColorRamp(const QString &name)
remove color ramp from style (and delete it)
Definition: qgsstylev2.cpp:240
static QString addColorRampStatic(QWidget *parent, QgsStyleV2 *style, QString RampType=QString())
open add color ramp dialog, return color ramp&#39;s name if the ramp has been added
void setCheckState(Qt::CheckState state)
void enableGroupInputs(bool)
Enables or disables the groupTree specific inputs.
void enableSymbolInputs(bool)
Enables or disbables the symbol specific inputs.
void onFinished()
called when the dialog is going to be closed
QStandardItem * takeChild(int row, int column)
void setDisabled(bool disable)
StyleEntity
Enum for Entities involved in a style.
Definition: qgsstylev2.h:80
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const
QChar * data()
bool isGroup(QgsLayerTreeNode *node)
Check whether the node is a valid group node.
Definition: qgslayertree.h:34
QString toString() const
QDir home()
void setCheckable(bool checkable)
void setConditionMap(const QgsSmartConditionMap &)
sets up the GUI for the given conditionmap
void appendRow(const QList< QStandardItem * > &items)
virtual QVariant data(int role) const
QStringList findSymbols(StyleEntity type, const QString &qword)
return the names of the symbols which have a matching &#39;substring&#39; in its defintion ...
Definition: qgsstylev2.cpp:776
void setEditable(bool editable)
void regrouped(QStandardItem *)
symbol changed from one group
int addGroup(const QString &groupName, int parent=0)
adds a new group and returns the group&#39;s id
Definition: qgsstylev2.cpp:625
QgsSmartConditionMap smartgroup(int id)
returns the QgsSmartConditionMap for the given id
bool removeSymbol(const QString &name)
remove symbol from style (and delete it)
Definition: qgsstylev2.cpp:136
int addSmartgroup(const QString &name, const QString &op, const QgsSmartConditionMap &conditions)
adds new smartgroup to the database and returns the id
QMenu * mGroupListMenu
Sub-menu of mGroupMenu, dynamically filled to show one entry for every group.
QString conditionOperator()
returns the AND/OR condition
bool addColorRamp()
add a new color ramp to style
void populateList()
adds symbols of some type to list