QGIS API Documentation
qgssymbolv2selectordialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssymbolv2selectordialog.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 "qgssymbollayerv2.h"
21 #include "qgssymbollayerv2utils.h"
23 #include "qgsdatadefined.h"
24 
25 // the widgets
26 #include "qgssymbolslistwidget.h"
28 #include "qgssymbollayerv2widget.h"
31 
32 #include "qgslogger.h"
33 #include "qgsapplication.h"
34 
35 #include <QColorDialog>
36 #include <QPainter>
37 #include <QStandardItemModel>
38 #include <QInputDialog>
39 #include <QMessageBox>
40 #include <QKeyEvent>
41 #include <QMenu>
42 
43 #include <QWidget>
44 #include <QFile>
45 #include <QStandardItem>
46 
48 
49 static const int SymbolLayerItemType = QStandardItem::UserType + 1;
50 
51 DataDefinedRestorer::DataDefinedRestorer( QgsSymbolV2* symbol, const QgsSymbolLayerV2* symbolLayer )
52  : mMarker( nullptr )
53  , mMarkerSymbolLayer( nullptr )
54  , mLine( nullptr )
55  , mLineSymbolLayer( nullptr )
56 {
57  if ( symbolLayer->type() == QgsSymbolV2::Marker && symbol->type() == QgsSymbolV2::Marker )
58  {
59  Q_ASSERT( symbol->type() == QgsSymbolV2::Marker );
60  mMarker = static_cast<QgsMarkerSymbolV2*>( symbol );
61  mMarkerSymbolLayer = static_cast<const QgsMarkerSymbolLayerV2*>( symbolLayer );
62  mDDSize = mMarker->dataDefinedSize();
63  mDDAngle = mMarker->dataDefinedAngle();
64  // check if restore is actually needed
65  if ( mDDSize == QgsDataDefined() && mDDAngle == QgsDataDefined() )
66  mMarker = nullptr;
67  }
68  else if ( symbolLayer->type() == QgsSymbolV2::Line && symbol->type() == QgsSymbolV2::Line )
69  {
70  mLine = static_cast<QgsLineSymbolV2*>( symbol );
71  mLineSymbolLayer = static_cast<const QgsLineSymbolLayerV2*>( symbolLayer );
72  mDDWidth = mLine->dataDefinedWidth();
73  // check if restore is actually needed
74  if ( mDDWidth == QgsDataDefined() )
75  mLine = nullptr;
76  }
77  save();
78 }
79 
80 void DataDefinedRestorer::save()
81 {
82  if ( mMarker )
83  {
84  mSize = mMarkerSymbolLayer->size();
85  mAngle = mMarkerSymbolLayer->angle();
86  mMarkerOffset = mMarkerSymbolLayer->offset();
87  }
88  else if ( mLine )
89  {
90  mWidth = mLineSymbolLayer->width();
91  mLineOffset = mLineSymbolLayer->offset();
92  }
93 }
94 
95 void DataDefinedRestorer::restore()
96 {
97  if ( mMarker )
98  {
99  if ( mDDSize != QgsDataDefined() &&
100  ( mSize != mMarkerSymbolLayer->size() || mMarkerOffset != mMarkerSymbolLayer->offset() ) )
101  mMarker->setDataDefinedSize( mDDSize );
102  if ( mDDAngle != QgsDataDefined() &&
103  mAngle != mMarkerSymbolLayer->angle() )
104  mMarker->setDataDefinedAngle( mDDAngle );
105  }
106  else if ( mLine )
107  {
108  if ( mDDWidth != QgsDataDefined() &&
109  ( mWidth != mLineSymbolLayer->width() || mLineOffset != mLineSymbolLayer->offset() ) )
110  mLine->setDataDefinedWidth( mDDWidth );
111  }
112  save();
113 }
114 
115 // Hybrid item which may represent a symbol or a layer
116 // Check using item->isLayer()
117 class SymbolLayerItem : public QStandardItem
118 {
119  public:
120  explicit SymbolLayerItem( QgsSymbolLayerV2* layer )
121  {
122  setLayer( layer );
123  }
124 
125  explicit SymbolLayerItem( QgsSymbolV2* symbol )
126  {
127  setSymbol( symbol );
128  }
129 
130  void setLayer( QgsSymbolLayerV2* layer )
131  {
132  mLayer = layer;
133  mIsLayer = true;
134  mSymbol = nullptr;
135  updatePreview();
136  }
137 
138  void setSymbol( QgsSymbolV2* symbol )
139  {
140  mSymbol = symbol;
141  mIsLayer = false;
142  mLayer = nullptr;
143  updatePreview();
144  }
145 
146  void updatePreview()
147  {
148  QIcon icon;
149  if ( mIsLayer )
150  icon = QgsSymbolLayerV2Utils::symbolLayerPreviewIcon( mLayer, QgsSymbolV2::MM, QSize( 16, 16 ) ); //todo: make unit a parameter
151  else
153  setIcon( icon );
154 
155  if ( parent() )
156  static_cast<SymbolLayerItem*>( parent() )->updatePreview();
157  }
158 
159  int type() const override { return SymbolLayerItemType; }
160  bool isLayer() { return mIsLayer; }
161 
162  // returns the symbol pointer; helpful in determining a layer's parent symbol
163  QgsSymbolV2* symbol()
164  {
165  return mSymbol;
166  }
167 
169  {
170  return mLayer;
171  }
172 
173  QVariant data( int role ) const override
174  {
175  if ( role == Qt::DisplayRole || role == Qt::EditRole )
176  {
177  if ( mIsLayer )
178  return QgsSymbolLayerV2Registry::instance()->symbolLayerMetadata( mLayer->layerType() )->visibleName();
179  else
180  {
181  switch ( mSymbol->type() )
182  {
183  case QgsSymbolV2::Marker :
184  return QCoreApplication::translate( "SymbolLayerItem", "Marker", nullptr, QCoreApplication::UnicodeUTF8 );
185  case QgsSymbolV2::Fill :
186  return QCoreApplication::translate( "SymbolLayerItem", "Fill", nullptr, QCoreApplication::UnicodeUTF8 );
187  case QgsSymbolV2::Line :
188  return QCoreApplication::translate( "SymbolLayerItem", "Line", nullptr, QCoreApplication::UnicodeUTF8 );
189  default:
190  return "Symbol";
191  }
192  }
193  }
194  if ( role == Qt::SizeHintRole )
195  return QVariant( QSize( 32, 32 ) );
196  if ( role == Qt::CheckStateRole )
197  return QVariant(); // could be true/false
198  return QStandardItem::data( role );
199  }
200 
201  protected:
204  bool mIsLayer;
205 };
206 
208 
210 
212  : QDialog( parent )
213  , mAdvancedMenu( nullptr )
214  , mVectorLayer( vl )
215  , mMapCanvas( nullptr )
216 {
217 #ifdef Q_OS_MAC
218  setWindowModality( Qt::WindowModal );
219 #endif
220  mStyle = style;
221  mSymbol = symbol;
222  mPresentWidget = nullptr;
223 
224  setupUi( this );
225 
226  QSettings settings;
227  restoreGeometry( settings.value( "/Windows/SymbolSelectorDialog/geometry" ).toByteArray() );
228 
229  // can be embedded in renderer properties dialog
230  if ( embedded )
231  {
232  buttonBox->hide();
233  layout()->setContentsMargins( 0, 0, 0, 0 );
234  }
235  // setup icons
236  btnAddLayer->setIcon( QIcon( QgsApplication::iconPath( "symbologyAdd.svg" ) ) );
237  btnRemoveLayer->setIcon( QIcon( QgsApplication::iconPath( "symbologyRemove.svg" ) ) );
238  QIcon iconLock;
239  iconLock.addFile( QgsApplication::iconPath( "locked.svg" ), QSize(), QIcon::Normal, QIcon::On );
240  iconLock.addFile( QgsApplication::iconPath( "locked.svg" ), QSize(), QIcon::Active, QIcon::On );
241  iconLock.addFile( QgsApplication::iconPath( "unlocked.svg" ), QSize(), QIcon::Normal, QIcon::Off );
242  iconLock.addFile( QgsApplication::iconPath( "unlocked.svg" ), QSize(), QIcon::Active, QIcon::Off );
243  btnLock->setIcon( iconLock );
244  btnDuplicate->setIcon( QIcon( QgsApplication::iconPath( "mActionDuplicateLayer.svg" ) ) );
245  btnUp->setIcon( QIcon( QgsApplication::iconPath( "symbologyUp.svg" ) ) );
246  btnDown->setIcon( QIcon( QgsApplication::iconPath( "symbologyDown.svg" ) ) );
247 
248  model = new QStandardItemModel( layersTree );
249  // Set the symbol
250  layersTree->setModel( model );
251  layersTree->setHeaderHidden( true );
252 
253  QItemSelectionModel* selModel = layersTree->selectionModel();
254  connect( selModel, SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ), this, SLOT( layerChanged() ) );
255 
256  loadSymbol( symbol, static_cast<SymbolLayerItem*>( model->invisibleRootItem() ) );
257  updatePreview();
258 
259  connect( btnUp, SIGNAL( clicked() ), this, SLOT( moveLayerUp() ) );
260  connect( btnDown, SIGNAL( clicked() ), this, SLOT( moveLayerDown() ) );
261  connect( btnAddLayer, SIGNAL( clicked() ), this, SLOT( addLayer() ) );
262  connect( btnRemoveLayer, SIGNAL( clicked() ), this, SLOT( removeLayer() ) );
263  connect( btnLock, SIGNAL( clicked() ), this, SLOT( lockLayer() ) );
264  connect( btnDuplicate, SIGNAL( clicked() ), this, SLOT( duplicateLayer() ) );
265 
266  updateUi();
267 
268  // set symbol as active item in the tree
269  QModelIndex newIndex = layersTree->model()->index( 0, 0 );
270  layersTree->setCurrentIndex( newIndex );
271 }
272 
274 {
275  QSettings settings;
276  settings.setValue( "/Windows/SymbolSelectorDialog/geometry", saveGeometry() );
277 }
278 
280 {
281  // Ignore the ESC key to avoid close the dialog without the properties window
282  if ( !isWindow() && e->key() == Qt::Key_Escape )
283  {
284  e->ignore();
285  }
286  else
287  {
289  }
290 }
291 
293 {
294  if ( !mAdvancedMenu )
295  {
296  mAdvancedMenu = new QMenu( this );
297  // Brute force method to activate the Advanced menu
298  layerChanged();
299  }
300  return mAdvancedMenu;
301 }
302 
304 {
305  mPresetExpressionContext.reset( context );
306  layerChanged();
307  updatePreview();
308 }
309 
311 {
312  mMapCanvas = canvas;
313 
314  QWidget* widget = stackedWidget->currentWidget();
315  QgsLayerPropertiesWidget* layerProp = dynamic_cast< QgsLayerPropertiesWidget* >( widget );
316  QgsSymbolsListWidget* listWidget = dynamic_cast< QgsSymbolsListWidget* >( widget );
317 
318  if ( layerProp )
319  layerProp->setMapCanvas( canvas );
320  if ( listWidget )
321  listWidget->setMapCanvas( canvas );
322 }
323 
325 {
326  SymbolLayerItem* symbolItem = new SymbolLayerItem( symbol );
327  QFont boldFont = symbolItem->font();
328  boldFont.setBold( true );
329  symbolItem->setFont( boldFont );
330  parent->appendRow( symbolItem );
331 
332  int count = symbol->symbolLayerCount();
333  for ( int i = count - 1; i >= 0; i-- )
334  {
335  SymbolLayerItem *layerItem = new SymbolLayerItem( symbol->symbolLayer( i ) );
336  layerItem->setEditable( false );
337  symbolItem->appendRow( layerItem );
338  if ( symbol->symbolLayer( i )->subSymbol() )
339  {
340  loadSymbol( symbol->symbolLayer( i )->subSymbol(), layerItem );
341  }
342  layersTree->setExpanded( layerItem->index(), true );
343  }
344  layersTree->setExpanded( symbolItem->index(), true );
345 }
346 
347 
349 {
350  model->clear();
351  loadSymbol( mSymbol, static_cast<SymbolLayerItem*>( model->invisibleRootItem() ) );
352 }
353 
355 {
356  QModelIndex currentIdx = layersTree->currentIndex();
357  if ( !currentIdx.isValid() )
358  return;
359 
360  SymbolLayerItem *item = static_cast<SymbolLayerItem*>( model->itemFromIndex( currentIdx ) );
361  if ( !item->isLayer() )
362  {
363  btnUp->setEnabled( false );
364  btnDown->setEnabled( false );
365  btnRemoveLayer->setEnabled( false );
366  btnLock->setEnabled( false );
367  btnDuplicate->setEnabled( false );
368  return;
369  }
370 
371  int rowCount = item->parent()->rowCount();
372  int currentRow = item->row();
373 
374  btnUp->setEnabled( currentRow > 0 );
375  btnDown->setEnabled( currentRow < rowCount - 1 );
376  btnRemoveLayer->setEnabled( rowCount > 1 );
377  btnLock->setEnabled( true );
378  btnDuplicate->setEnabled( true );
379 }
380 
382 {
383  QImage preview = mSymbol->bigSymbolPreviewImage( mPresetExpressionContext.data() );
384  lblPreview->setPixmap( QPixmap::fromImage( preview ) );
385  // Hope this is a appropriate place
386  emit symbolModified();
387 }
388 
390 {
391  // get current layer item and update its icon
392  SymbolLayerItem* item = currentLayerItem();
393  if ( item )
394  item->updatePreview();
395  // update also preview of the whole symbol
396  updatePreview();
397 }
398 
400 {
401  QModelIndex idx = layersTree->currentIndex();
402  if ( !idx.isValid() )
403  return nullptr;
404 
405  SymbolLayerItem *item = static_cast<SymbolLayerItem*>( model->itemFromIndex( idx ) );
406  if ( !item->isLayer() )
407  return nullptr;
408 
409  return item;
410 }
411 
413 {
414  QModelIndex idx = layersTree->currentIndex();
415  if ( !idx.isValid() )
416  return nullptr;
417 
418  SymbolLayerItem *item = static_cast<SymbolLayerItem*>( model->itemFromIndex( idx ) );
419  if ( item->isLayer() )
420  return item->layer();
421 
422  return nullptr;
423 }
424 
426 {
427  updateUi();
428 
429  SymbolLayerItem *currentItem = static_cast<SymbolLayerItem*>( model->itemFromIndex( layersTree->currentIndex() ) );
430  if ( !currentItem )
431  return;
432 
433  if ( currentItem->isLayer() )
434  {
435  SymbolLayerItem *parent = static_cast<SymbolLayerItem*>( currentItem->parent() );
436  mDataDefineRestorer.reset( new DataDefinedRestorer( parent->symbol(), currentItem->layer() ) );
437  QgsLayerPropertiesWidget *layerProp = new QgsLayerPropertiesWidget( currentItem->layer(), parent->symbol(), mVectorLayer );
438  layerProp->setExpressionContext( mPresetExpressionContext.data() );
439  layerProp->setMapCanvas( mMapCanvas );
440  setWidget( layerProp );
441  connect( layerProp, SIGNAL( changed() ), mDataDefineRestorer.data(), SLOT( restore() ) );
442  connect( layerProp, SIGNAL( changed() ), this, SLOT( updateLayerPreview() ) );
443  // This connection when layer type is changed
444  connect( layerProp, SIGNAL( changeLayer( QgsSymbolLayerV2* ) ), this, SLOT( changeLayer( QgsSymbolLayerV2* ) ) );
445  }
446  else
447  {
448  mDataDefineRestorer.reset();
449  // then it must be a symbol
450  currentItem->symbol()->setLayer( mVectorLayer );
451  // Now populate symbols of that type using the symbols list widget:
452  QgsSymbolsListWidget *symbolsList = new QgsSymbolsListWidget( currentItem->symbol(), mStyle, mAdvancedMenu, this, mVectorLayer );
453  symbolsList->setExpressionContext( mPresetExpressionContext.data() );
454  symbolsList->setMapCanvas( mMapCanvas );
455 
456  setWidget( symbolsList );
457  connect( symbolsList, SIGNAL( changed() ), this, SLOT( symbolChanged() ) );
458  }
460 }
461 
463 {
464  SymbolLayerItem *currentItem = static_cast<SymbolLayerItem*>( model->itemFromIndex( layersTree->currentIndex() ) );
465  if ( !currentItem || currentItem->isLayer() )
466  return;
467  // disconnect to avoid recreating widget
468  disconnect( layersTree->selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ), this, SLOT( layerChanged() ) );
469  if ( currentItem->parent() )
470  {
471  // it is a sub-symbol
472  QgsSymbolV2* symbol = currentItem->symbol();
473  SymbolLayerItem *parent = static_cast<SymbolLayerItem*>( currentItem->parent() );
474  parent->removeRow( 0 );
475  loadSymbol( symbol, parent );
476  layersTree->setCurrentIndex( parent->child( 0 )->index() );
477  parent->updatePreview();
478  }
479  else
480  {
481  //it is the symbol itself
482  loadSymbol();
483  QModelIndex newIndex = layersTree->model()->index( 0, 0 );
484  layersTree->setCurrentIndex( newIndex );
485  }
486  updatePreview();
487  // connect it back once things are set
488  connect( layersTree->selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ), this, SLOT( layerChanged() ) );
489 }
490 
492 {
493  int index = stackedWidget->addWidget( widget );
494  stackedWidget->setCurrentIndex( index );
495  if ( mPresentWidget )
497  mPresentWidget = widget;
498 }
499 
501 {
502  QgsSymbolLayerV2* layer = currentLayer();
503  if ( !layer )
504  return;
505  btnLock->setChecked( layer->isLocked() );
506 }
507 
509 {
510  QModelIndex idx = layersTree->currentIndex();
511  if ( !idx.isValid() )
512  return;
513 
514  int insertIdx = -1;
515  SymbolLayerItem *item = static_cast<SymbolLayerItem*>( model->itemFromIndex( idx ) );
516  if ( item->isLayer() )
517  {
518  insertIdx = item->row();
519  item = static_cast<SymbolLayerItem*>( item->parent() );
520  }
521 
522  QgsSymbolV2* parentSymbol = item->symbol();
523 
524  // save data-defined values at marker level
525  QgsDataDefined ddSize = parentSymbol->type() == QgsSymbolV2::Marker
526  ? static_cast<QgsMarkerSymbolV2 *>( parentSymbol )->dataDefinedSize()
527  : QgsDataDefined();
528  QgsDataDefined ddAngle = parentSymbol->type() == QgsSymbolV2::Marker
529  ? static_cast<QgsMarkerSymbolV2 *>( parentSymbol )->dataDefinedAngle()
530  : QgsDataDefined();
531  QgsDataDefined ddWidth = parentSymbol->type() == QgsSymbolV2::Line
532  ? static_cast<QgsLineSymbolV2 *>( parentSymbol )->dataDefinedWidth()
533  : QgsDataDefined() ;
534 
536  if ( insertIdx == -1 )
537  parentSymbol->appendSymbolLayer( newLayer );
538  else
539  parentSymbol->insertSymbolLayer( item->rowCount() - insertIdx, newLayer );
540 
541  // restore data-defined values at marker level
542  if ( ddSize != QgsDataDefined() )
543  static_cast<QgsMarkerSymbolV2 *>( parentSymbol )->setDataDefinedSize( ddSize );
544  if ( ddAngle != QgsDataDefined() )
545  static_cast<QgsMarkerSymbolV2 *>( parentSymbol )->setDataDefinedAngle( ddAngle );
546  if ( ddWidth != QgsDataDefined() )
547  static_cast<QgsLineSymbolV2 *>( parentSymbol )->setDataDefinedWidth( ddWidth );
548 
549  SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer );
550  item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
551  item->updatePreview();
552 
553  layersTree->setCurrentIndex( model->indexFromItem( newLayerItem ) );
554  updateUi();
555  updatePreview();
556 }
557 
559 {
560  SymbolLayerItem *item = currentLayerItem();
561  int row = item->row();
562  SymbolLayerItem *parent = static_cast<SymbolLayerItem*>( item->parent() );
563 
564  int layerIdx = parent->rowCount() - row - 1; // IMPORTANT
565  QgsSymbolV2* parentSymbol = parent->symbol();
566  QgsSymbolLayerV2 *tmpLayer = parentSymbol->takeSymbolLayer( layerIdx );
567 
568  parent->removeRow( row );
569  parent->updatePreview();
570 
571  QModelIndex newIdx = parent->child( 0 )->index();
572  layersTree->setCurrentIndex( newIdx );
573 
574  updateUi();
575  updatePreview();
576  //finally delete the removed layer pointer
577  delete tmpLayer;
578 }
579 
581 {
582  moveLayerByOffset( + 1 );
583 }
584 
586 {
587  moveLayerByOffset( -1 );
588 }
589 
591 {
592  SymbolLayerItem *item = currentLayerItem();
593  if ( !item )
594  return;
595  int row = item->row();
596 
597  SymbolLayerItem *parent = static_cast<SymbolLayerItem*>( item->parent() );
598  QgsSymbolV2* parentSymbol = parent->symbol();
599 
600  int layerIdx = parent->rowCount() - row - 1;
601  // switch layers
602  QgsSymbolLayerV2* tmpLayer = parentSymbol->takeSymbolLayer( layerIdx );
603  parentSymbol->insertSymbolLayer( layerIdx - offset, tmpLayer );
604 
605  QList<QStandardItem*> rowItems = parent->takeRow( row );
606  parent->insertRows( row + offset, rowItems );
607  parent->updatePreview();
608 
609  QModelIndex newIdx = rowItems[ 0 ]->index();
610  layersTree->setCurrentIndex( newIdx );
611 
612  updatePreview();
613  updateUi();
614 }
615 
617 {
618  QgsSymbolLayerV2* layer = currentLayer();
619  if ( !layer )
620  return;
621  layer->setLocked( btnLock->isChecked() );
622 }
623 
625 {
626  QModelIndex idx = layersTree->currentIndex();
627  if ( !idx.isValid() )
628  return;
629 
630  SymbolLayerItem *item = static_cast<SymbolLayerItem*>( model->itemFromIndex( idx ) );
631  if ( !item->isLayer() )
632  return;
633 
634  QgsSymbolLayerV2* source = item->layer();
635 
636  int insertIdx = item->row();
637  item = static_cast<SymbolLayerItem*>( item->parent() );
638 
639  QgsSymbolV2* parentSymbol = item->symbol();
640 
641  QgsSymbolLayerV2* newLayer = source->clone();
642  if ( insertIdx == -1 )
643  parentSymbol->appendSymbolLayer( newLayer );
644  else
645  parentSymbol->insertSymbolLayer( item->rowCount() - insertIdx, newLayer );
646 
647  SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer );
648  item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
649  if ( newLayer->subSymbol() )
650  {
651  loadSymbol( newLayer->subSymbol(), newLayerItem );
652  layersTree->setExpanded( newLayerItem->index(), true );
653  }
654  item->updatePreview();
655 
656  layersTree->setCurrentIndex( model->indexFromItem( newLayerItem ) );
657  updateUi();
658  updatePreview();
659 }
660 
662 {
663  bool ok;
664  QString name = QInputDialog::getText( this, tr( "Symbol name" ),
665  tr( "Please enter name for the symbol:" ), QLineEdit::Normal, tr( "New symbol" ), &ok );
666  if ( !ok || name.isEmpty() )
667  return;
668 
669  // check if there is no symbol with same name
670  if ( mStyle->symbolNames().contains( name ) )
671  {
672  int res = QMessageBox::warning( this, tr( "Save symbol" ),
673  tr( "Symbol with name '%1' already exists. Overwrite?" )
674  .arg( name ),
675  QMessageBox::Yes | QMessageBox::No );
676  if ( res != QMessageBox::Yes )
677  {
678  return;
679  }
680  }
681 
682  // add new symbol to style and re-populate the list
683  mStyle->addSymbol( name, mSymbol->clone() );
684 
685  // make sure the symbol is stored
686  mStyle->saveSymbol( name, mSymbol->clone(), 0, QStringList() );
687 }
688 
690 {
691  SymbolLayerItem* item = currentLayerItem();
692  QgsSymbolLayerV2* layer = item->layer();
693 
694  if ( layer->subSymbol() )
695  {
696  item->removeRow( 0 );
697  }
698  // update symbol layer item
699  item->setLayer( newLayer );
700  // When it is a marker symbol
701  if ( newLayer->subSymbol() )
702  {
703  loadSymbol( newLayer->subSymbol(), item );
704  layersTree->setExpanded( item->index(), true );
705  }
706 
707  // Change the symbol at last to avoid deleting item's layer
708  QgsSymbolV2* symbol = static_cast<SymbolLayerItem*>( item->parent() )->symbol();
709  int layerIdx = item->parent()->rowCount() - item->row() - 1;
710  symbol->changeSymbolLayer( layerIdx, newLayer );
711 
712  item->updatePreview();
713  updatePreview();
714  // Important: This lets the layer have its own layer properties widget
715  layerChanged();
716 }
QLayout * layout() const
void setLocked(bool locked)
QByteArray toByteArray() const
static unsigned index
void setExpressionContext(QgsExpressionContext *context)
Sets the optional expression context used for the widget.
void setContentsMargins(int left, int top, int right, int bottom)
void setupUi(QWidget *widget)
static QgsSymbolLayerV2 * defaultSymbolLayer(QgsSymbolV2::SymbolType type)
create a new instance of symbol layer for specified symbol type with default settings ...
void setIcon(const QPixmap &i)
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const =0
virtual QgsSymbolLayerV2 * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
A container class for data source field mapping or expression.
static QIcon symbolLayerPreviewIcon(QgsSymbolLayerV2 *layer, QgsSymbolV2::OutputUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale())
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
void setWindowModality(Qt::WindowModality windowModality)
virtual QgsSymbolV2 * clone() const =0
QStyle * style() const
void symbolChanged()
Slot to update tree when a new symbol from style.
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
bool contains(const QString &str, Qt::CaseSensitivity cs) const
bool changeSymbolLayer(int index, QgsSymbolLayerV2 *layer)
delete layer at specified index and set a new one
QPixmap fromImage(const QImage &image, QFlags< Qt::ImageConversionFlag > flags)
Line symbol.
Definition: qgssymbolv2.h:79
static QgsSymbolLayerV2Registry * instance()
return the single instance of this class (instantiate it if not exists)
const QPixmap * icon() const
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
const QgsVectorLayer * mVectorLayer
QString tr(const char *sourceText, const char *disambiguation, int n)
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:105
const QgsVectorLayer * mLayer
Marker symbol.
Definition: qgssymbolv2.h:78
void reset(T *other)
void setBold(bool enable)
void setValue(const QString &key, const QVariant &value)
const char * name() const
bool isValid() const
The output shall be in millimeters.
Definition: qgssymbolv2.h:64
static QIcon symbolPreviewIcon(QgsSymbolV2 *symbol, QSize size)
const QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.
void ignore()
bool appendSymbolLayer(QgsSymbolLayerV2 *layer)
Append symbol layer at the end of the list Ownership will be transferred.
bool saveSymbol(const QString &name, QgsSymbolV2 *symbol, int groupid, const QStringList &tags)
add the symbol to the DB with the tags
Definition: qgsstylev2.cpp:105
void keyPressEvent(QKeyEvent *event) override
Reimplements dialog keyPress event so we can ignore it.
QModelIndex indexFromItem(const QStandardItem *item) const
QMenu * advancedMenu()
return menu for "advanced" button - create it if doesn&#39;t exist and show the advanced button ...
void setExpressionContext(QgsExpressionContext *context)
Sets the optional expression context used for the widget.
bool restoreGeometry(const QByteArray &geometry)
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
bool isEmpty() const
int symbolLayerCount()
Returns total number of symbol layers contained in the symbol.
Definition: qgssymbolv2.h:131
virtual void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
void deleteLater()
bool isLayer(QgsLayerTreeNode *node)
Check whether the node is a valid layer node.
Definition: qgslayertree.h:40
QStringList symbolNames()
return a list of names of symbols
Definition: qgsstylev2.cpp:180
QgsSymbolLayerV2AbstractMetadata * symbolLayerMetadata(const QString &name) const
return metadata for specified symbol layer. Returns NULL if not found
bool isWindow() const
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)
QgsSymbolV2::SymbolType type() const
T * data() const
int key() const
QImage bigSymbolPreviewImage(QgsExpressionContext *expressionContext=nullptr)
Returns a large (roughly 100x100 pixel) preview image for the symbol.
virtual QgsSymbolV2 * subSymbol()
void addFile(const QString &fileName, const QSize &size, Mode mode, State state)
virtual void keyPressEvent(QKeyEvent *e)
QVariant value(const QString &key, const QVariant &defaultValue) const
const QAbstractItemModel * model() const
void duplicateLayer()
Duplicates the current symbol layer and places the duplicated layer above the current symbol layer...
bool insertSymbolLayer(int index, QgsSymbolLayerV2 *layer)
Insert symbol layer to specified index Ownership will be transferred.
QByteArray saveGeometry() const
bool isLocked() const
QStandardItem * itemFromIndex(const QModelIndex &index) const
QgsSymbolV2SelectorDialog(QgsSymbolV2 *symbol, QgsStyleV2 *style, const QgsVectorLayer *vl, QWidget *parent=nullptr, bool embedded=false)
void setExpressionContext(QgsExpressionContext *context)
Sets the optional expression context used for the widget.
QString translate(const char *context, const char *sourceText, const char *disambiguation, Encoding encoding)
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the dialog.
Fill symbol.
Definition: qgssymbolv2.h:80
void changeLayer(QgsSymbolLayerV2 *layer)
alters tree and sets proper widget when Layer Type is changed
StandardButton warning(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
QgsSymbolLayerV2 * takeSymbolLayer(int index)
Remove symbol layer from the list and return pointer to it.
QgsSymbolLayerV2 * symbolLayer(int layer)
Returns a specific symbol layers contained in the symbol.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const
Represents a vector layer which manages a vector based data sets.
virtual void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
virtual QVariant data(int role) const
Q_DECL_DEPRECATED void saveSymbol()