QGIS API Documentation  2.15.0-Master (972fc9f)
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  : QgsPanelWidget( 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  // setup icons
227  btnAddLayer->setIcon( QIcon( QgsApplication::iconPath( "symbologyAdd.svg" ) ) );
228  btnRemoveLayer->setIcon( QIcon( QgsApplication::iconPath( "symbologyRemove.svg" ) ) );
229  QIcon iconLock;
230  iconLock.addFile( QgsApplication::iconPath( "locked.svg" ), QSize(), QIcon::Normal, QIcon::On );
231  iconLock.addFile( QgsApplication::iconPath( "locked.svg" ), QSize(), QIcon::Active, QIcon::On );
232  iconLock.addFile( QgsApplication::iconPath( "unlocked.svg" ), QSize(), QIcon::Normal, QIcon::Off );
233  iconLock.addFile( QgsApplication::iconPath( "unlocked.svg" ), QSize(), QIcon::Active, QIcon::Off );
234  btnLock->setIcon( iconLock );
235  btnDuplicate->setIcon( QIcon( QgsApplication::iconPath( "mActionDuplicateLayer.svg" ) ) );
236  btnUp->setIcon( QIcon( QgsApplication::iconPath( "symbologyUp.svg" ) ) );
237  btnDown->setIcon( QIcon( QgsApplication::iconPath( "symbologyDown.svg" ) ) );
238 
239  model = new QStandardItemModel( layersTree );
240  // Set the symbol
241  layersTree->setModel( model );
242  layersTree->setHeaderHidden( true );
243 
244  QItemSelectionModel* selModel = layersTree->selectionModel();
245  connect( selModel, SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ), this, SLOT( layerChanged() ) );
246 
247  loadSymbol( symbol, static_cast<SymbolLayerItem*>( model->invisibleRootItem() ) );
248  updatePreview();
249 
250  connect( btnUp, SIGNAL( clicked() ), this, SLOT( moveLayerUp() ) );
251  connect( btnDown, SIGNAL( clicked() ), this, SLOT( moveLayerDown() ) );
252  connect( btnAddLayer, SIGNAL( clicked() ), this, SLOT( addLayer() ) );
253  connect( btnRemoveLayer, SIGNAL( clicked() ), this, SLOT( removeLayer() ) );
254  connect( btnLock, SIGNAL( clicked() ), this, SLOT( lockLayer() ) );
255  connect( btnDuplicate, SIGNAL( clicked() ), this, SLOT( duplicateLayer() ) );
256  connect( this, SIGNAL( symbolModified() ), this, SIGNAL( widgetChanged() ) );
257 
258  updateUi();
259 
260  // set symbol as active item in the tree
261  QModelIndex newIndex = layersTree->model()->index( 0, 0 );
262  layersTree->setCurrentIndex( newIndex );
263 
264  setPanelTitle( tr( "Symbol selector" ) );
265 }
266 
268 {
269 }
270 
272 {
273  if ( !mAdvancedMenu )
274  {
275  mAdvancedMenu = new QMenu( this );
276  // Brute force method to activate the Advanced menu
277  layerChanged();
278  }
279  return mAdvancedMenu;
280 }
281 
283 {
284  mPresetExpressionContext.reset( context );
285  layerChanged();
286  updatePreview();
287 }
288 
290 {
291  mMapCanvas = canvas;
292 
293  QWidget* widget = stackedWidget->currentWidget();
294  QgsLayerPropertiesWidget* layerProp = dynamic_cast< QgsLayerPropertiesWidget* >( widget );
295  QgsSymbolsListWidget* listWidget = dynamic_cast< QgsSymbolsListWidget* >( widget );
296 
297  if ( layerProp )
298  layerProp->setMapCanvas( canvas );
299  if ( listWidget )
300  listWidget->setMapCanvas( canvas );
301 }
302 
304 {
305  SymbolLayerItem* symbolItem = new SymbolLayerItem( symbol );
306  QFont boldFont = symbolItem->font();
307  boldFont.setBold( true );
308  symbolItem->setFont( boldFont );
309  parent->appendRow( symbolItem );
310 
311  int count = symbol->symbolLayerCount();
312  for ( int i = count - 1; i >= 0; i-- )
313  {
314  SymbolLayerItem *layerItem = new SymbolLayerItem( symbol->symbolLayer( i ) );
315  layerItem->setEditable( false );
316  symbolItem->appendRow( layerItem );
317  if ( symbol->symbolLayer( i )->subSymbol() )
318  {
319  loadSymbol( symbol->symbolLayer( i )->subSymbol(), layerItem );
320  }
321  layersTree->setExpanded( layerItem->index(), true );
322  }
323  layersTree->setExpanded( symbolItem->index(), true );
324 }
325 
326 
328 {
329  model->clear();
330  loadSymbol( mSymbol, static_cast<SymbolLayerItem*>( model->invisibleRootItem() ) );
331 }
332 
334 {
335  QModelIndex currentIdx = layersTree->currentIndex();
336  if ( !currentIdx.isValid() )
337  return;
338 
339  SymbolLayerItem *item = static_cast<SymbolLayerItem*>( model->itemFromIndex( currentIdx ) );
340  if ( !item->isLayer() )
341  {
342  btnUp->setEnabled( false );
343  btnDown->setEnabled( false );
344  btnRemoveLayer->setEnabled( false );
345  btnLock->setEnabled( false );
346  btnDuplicate->setEnabled( false );
347  return;
348  }
349 
350  int rowCount = item->parent()->rowCount();
351  int currentRow = item->row();
352 
353  btnUp->setEnabled( currentRow > 0 );
354  btnDown->setEnabled( currentRow < rowCount - 1 );
355  btnRemoveLayer->setEnabled( rowCount > 1 );
356  btnLock->setEnabled( true );
357  btnDuplicate->setEnabled( true );
358 }
359 
361 {
362  QImage preview = mSymbol->bigSymbolPreviewImage( mPresetExpressionContext.data() );
363  lblPreview->setPixmap( QPixmap::fromImage( preview ) );
364  // Hope this is a appropriate place
365  emit symbolModified();
366 }
367 
369 {
370  // get current layer item and update its icon
371  SymbolLayerItem* item = currentLayerItem();
372  if ( item )
373  item->updatePreview();
374  // update also preview of the whole symbol
375  updatePreview();
376 }
377 
379 {
380  QModelIndex idx = layersTree->currentIndex();
381  if ( !idx.isValid() )
382  return nullptr;
383 
384  SymbolLayerItem *item = static_cast<SymbolLayerItem*>( model->itemFromIndex( idx ) );
385  if ( !item->isLayer() )
386  return nullptr;
387 
388  return item;
389 }
390 
392 {
393  QModelIndex idx = layersTree->currentIndex();
394  if ( !idx.isValid() )
395  return nullptr;
396 
397  SymbolLayerItem *item = static_cast<SymbolLayerItem*>( model->itemFromIndex( idx ) );
398  if ( item->isLayer() )
399  return item->layer();
400 
401  return nullptr;
402 }
403 
405 {
406  updateUi();
407 
408  SymbolLayerItem *currentItem = static_cast<SymbolLayerItem*>( model->itemFromIndex( layersTree->currentIndex() ) );
409  if ( !currentItem )
410  return;
411 
412  if ( currentItem->isLayer() )
413  {
414  SymbolLayerItem *parent = static_cast<SymbolLayerItem*>( currentItem->parent() );
415  mDataDefineRestorer.reset( new DataDefinedRestorer( parent->symbol(), currentItem->layer() ) );
416  QgsLayerPropertiesWidget *layerProp = new QgsLayerPropertiesWidget( currentItem->layer(), parent->symbol(), mVectorLayer );
417  layerProp->setDockMode( this->dockMode() );
418  layerProp->setExpressionContext( mPresetExpressionContext.data() );
419  layerProp->setMapCanvas( mMapCanvas );
420  setWidget( layerProp );
421  connect( layerProp, SIGNAL( changed() ), mDataDefineRestorer.data(), SLOT( restore() ) );
422  connect( layerProp, SIGNAL( changed() ), this, SLOT( updateLayerPreview() ) );
423  // This connection when layer type is changed
424  connect( layerProp, SIGNAL( changeLayer( QgsSymbolLayerV2* ) ), this, SLOT( changeLayer( QgsSymbolLayerV2* ) ) );
425 
426  connectChildPanel( layerProp );
427  }
428  else
429  {
430  mDataDefineRestorer.reset();
431  // then it must be a symbol
432  currentItem->symbol()->setLayer( mVectorLayer );
433  // Now populate symbols of that type using the symbols list widget:
434  QgsSymbolsListWidget *symbolsList = new QgsSymbolsListWidget( currentItem->symbol(), mStyle, mAdvancedMenu, this, mVectorLayer );
435  symbolsList->setExpressionContext( mPresetExpressionContext.data() );
436  symbolsList->setMapCanvas( mMapCanvas );
437 
438  setWidget( symbolsList );
439  connect( symbolsList, SIGNAL( changed() ), this, SLOT( symbolChanged() ) );
440  }
442 }
443 
445 {
446  SymbolLayerItem *currentItem = static_cast<SymbolLayerItem*>( model->itemFromIndex( layersTree->currentIndex() ) );
447  if ( !currentItem || currentItem->isLayer() )
448  return;
449  // disconnect to avoid recreating widget
450  disconnect( layersTree->selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ), this, SLOT( layerChanged() ) );
451  if ( currentItem->parent() )
452  {
453  // it is a sub-symbol
454  QgsSymbolV2* symbol = currentItem->symbol();
455  SymbolLayerItem *parent = static_cast<SymbolLayerItem*>( currentItem->parent() );
456  parent->removeRow( 0 );
457  loadSymbol( symbol, parent );
458  layersTree->setCurrentIndex( parent->child( 0 )->index() );
459  parent->updatePreview();
460  }
461  else
462  {
463  //it is the symbol itself
464  loadSymbol();
465  QModelIndex newIndex = layersTree->model()->index( 0, 0 );
466  layersTree->setCurrentIndex( newIndex );
467  }
468  updatePreview();
469  // connect it back once things are set
470  connect( layersTree->selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ), this, SLOT( layerChanged() ) );
471 }
472 
474 {
475  int index = stackedWidget->addWidget( widget );
476  stackedWidget->setCurrentIndex( index );
477  if ( mPresentWidget )
479  mPresentWidget = widget;
480 }
481 
483 {
484  QgsSymbolLayerV2* layer = currentLayer();
485  if ( !layer )
486  return;
487  btnLock->setChecked( layer->isLocked() );
488 }
489 
491 {
492  QModelIndex idx = layersTree->currentIndex();
493  if ( !idx.isValid() )
494  return;
495 
496  int insertIdx = -1;
497  SymbolLayerItem *item = static_cast<SymbolLayerItem*>( model->itemFromIndex( idx ) );
498  if ( item->isLayer() )
499  {
500  insertIdx = item->row();
501  item = static_cast<SymbolLayerItem*>( item->parent() );
502  }
503 
504  QgsSymbolV2* parentSymbol = item->symbol();
505 
506  // save data-defined values at marker level
507  QgsDataDefined ddSize = parentSymbol->type() == QgsSymbolV2::Marker
508  ? static_cast<QgsMarkerSymbolV2 *>( parentSymbol )->dataDefinedSize()
509  : QgsDataDefined();
510  QgsDataDefined ddAngle = parentSymbol->type() == QgsSymbolV2::Marker
511  ? static_cast<QgsMarkerSymbolV2 *>( parentSymbol )->dataDefinedAngle()
512  : QgsDataDefined();
513  QgsDataDefined ddWidth = parentSymbol->type() == QgsSymbolV2::Line
514  ? static_cast<QgsLineSymbolV2 *>( parentSymbol )->dataDefinedWidth()
515  : QgsDataDefined() ;
516 
518  if ( insertIdx == -1 )
519  parentSymbol->appendSymbolLayer( newLayer );
520  else
521  parentSymbol->insertSymbolLayer( item->rowCount() - insertIdx, newLayer );
522 
523  // restore data-defined values at marker level
524  if ( ddSize != QgsDataDefined() )
525  static_cast<QgsMarkerSymbolV2 *>( parentSymbol )->setDataDefinedSize( ddSize );
526  if ( ddAngle != QgsDataDefined() )
527  static_cast<QgsMarkerSymbolV2 *>( parentSymbol )->setDataDefinedAngle( ddAngle );
528  if ( ddWidth != QgsDataDefined() )
529  static_cast<QgsLineSymbolV2 *>( parentSymbol )->setDataDefinedWidth( ddWidth );
530 
531  SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer );
532  item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
533  item->updatePreview();
534 
535  layersTree->setCurrentIndex( model->indexFromItem( newLayerItem ) );
536  updateUi();
537  updatePreview();
538 }
539 
541 {
542  SymbolLayerItem *item = currentLayerItem();
543  int row = item->row();
544  SymbolLayerItem *parent = static_cast<SymbolLayerItem*>( item->parent() );
545 
546  int layerIdx = parent->rowCount() - row - 1; // IMPORTANT
547  QgsSymbolV2* parentSymbol = parent->symbol();
548  QgsSymbolLayerV2 *tmpLayer = parentSymbol->takeSymbolLayer( layerIdx );
549 
550  parent->removeRow( row );
551  parent->updatePreview();
552 
553  QModelIndex newIdx = parent->child( 0 )->index();
554  layersTree->setCurrentIndex( newIdx );
555 
556  updateUi();
557  updatePreview();
558  //finally delete the removed layer pointer
559  delete tmpLayer;
560 }
561 
563 {
564  moveLayerByOffset( + 1 );
565 }
566 
568 {
569  moveLayerByOffset( -1 );
570 }
571 
573 {
574  SymbolLayerItem *item = currentLayerItem();
575  if ( !item )
576  return;
577  int row = item->row();
578 
579  SymbolLayerItem *parent = static_cast<SymbolLayerItem*>( item->parent() );
580  QgsSymbolV2* parentSymbol = parent->symbol();
581 
582  int layerIdx = parent->rowCount() - row - 1;
583  // switch layers
584  QgsSymbolLayerV2* tmpLayer = parentSymbol->takeSymbolLayer( layerIdx );
585  parentSymbol->insertSymbolLayer( layerIdx - offset, tmpLayer );
586 
587  QList<QStandardItem*> rowItems = parent->takeRow( row );
588  parent->insertRows( row + offset, rowItems );
589  parent->updatePreview();
590 
591  QModelIndex newIdx = rowItems[ 0 ]->index();
592  layersTree->setCurrentIndex( newIdx );
593 
594  updatePreview();
595  updateUi();
596 }
597 
599 {
600  QgsSymbolLayerV2* layer = currentLayer();
601  if ( !layer )
602  return;
603  layer->setLocked( btnLock->isChecked() );
604 }
605 
607 {
608  QModelIndex idx = layersTree->currentIndex();
609  if ( !idx.isValid() )
610  return;
611 
612  SymbolLayerItem *item = static_cast<SymbolLayerItem*>( model->itemFromIndex( idx ) );
613  if ( !item->isLayer() )
614  return;
615 
616  QgsSymbolLayerV2* source = item->layer();
617 
618  int insertIdx = item->row();
619  item = static_cast<SymbolLayerItem*>( item->parent() );
620 
621  QgsSymbolV2* parentSymbol = item->symbol();
622 
623  QgsSymbolLayerV2* newLayer = source->clone();
624  if ( insertIdx == -1 )
625  parentSymbol->appendSymbolLayer( newLayer );
626  else
627  parentSymbol->insertSymbolLayer( item->rowCount() - insertIdx, newLayer );
628 
629  SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer );
630  item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
631  if ( newLayer->subSymbol() )
632  {
633  loadSymbol( newLayer->subSymbol(), newLayerItem );
634  layersTree->setExpanded( newLayerItem->index(), true );
635  }
636  item->updatePreview();
637 
638  layersTree->setCurrentIndex( model->indexFromItem( newLayerItem ) );
639  updateUi();
640  updatePreview();
641 }
642 
644 {
645  bool ok;
646  QString name = QInputDialog::getText( this, tr( "Symbol name" ),
647  tr( "Please enter name for the symbol:" ), QLineEdit::Normal, tr( "New symbol" ), &ok );
648  if ( !ok || name.isEmpty() )
649  return;
650 
651  // check if there is no symbol with same name
652  if ( mStyle->symbolNames().contains( name ) )
653  {
654  int res = QMessageBox::warning( this, tr( "Save symbol" ),
655  tr( "Symbol with name '%1' already exists. Overwrite?" )
656  .arg( name ),
657  QMessageBox::Yes | QMessageBox::No );
658  if ( res != QMessageBox::Yes )
659  {
660  return;
661  }
662  }
663 
664  // add new symbol to style and re-populate the list
665  mStyle->addSymbol( name, mSymbol->clone() );
666 
667  // make sure the symbol is stored
668  mStyle->saveSymbol( name, mSymbol->clone(), 0, QStringList() );
669 }
670 
672 {
673  SymbolLayerItem* item = currentLayerItem();
674  QgsSymbolLayerV2* layer = item->layer();
675 
676  if ( layer->subSymbol() )
677  {
678  item->removeRow( 0 );
679  }
680  // update symbol layer item
681  item->setLayer( newLayer );
682  // When it is a marker symbol
683  if ( newLayer->subSymbol() )
684  {
685  loadSymbol( newLayer->subSymbol(), item );
686  layersTree->setExpanded( item->index(), true );
687  }
688 
689  // Change the symbol at last to avoid deleting item's layer
690  QgsSymbolV2* symbol = static_cast<SymbolLayerItem*>( item->parent() )->symbol();
691  int layerIdx = item->parent()->rowCount() - item->row() - 1;
692  symbol->changeSymbolLayer( layerIdx, newLayer );
693 
694  item->updatePreview();
695  updatePreview();
696  // Important: This lets the layer have its own layer properties widget
697  layerChanged();
698 }
699 
701  : QDialog( parent )
702 {
703  setLayout( new QVBoxLayout() );
704  mSelectorWidget = new QgsSymbolV2SelectorWidget( symbol, style, vl, this );
705  mButtonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
706 
707  connect( mButtonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
708  connect( mButtonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
709 
710  layout()->addWidget( mSelectorWidget );
711  layout()->addWidget( mButtonBox );
712 
713  QSettings settings;
714  restoreGeometry( settings.value( "/Windows/SymbolSelectorWidget/geometry" ).toByteArray() );
715 
716  // can be embedded in renderer properties dialog
717  if ( embedded )
718  {
719  mButtonBox->hide();
720  layout()->setContentsMargins( 0, 0, 0, 0 );
721  }
722  mSelectorWidget->setDockMode( embedded );
723 }
724 
726 {
727  QSettings settings;
728  settings.setValue( "/Windows/SymbolSelectorWidget/geometry", saveGeometry() );
729 }
730 
732 {
733  return mSelectorWidget->advancedMenu();
734 }
735 
737 {
738  mSelectorWidget->setExpressionContext( context );
739 }
740 
742 {
743  return mSelectorWidget->expressionContext();
744 }
745 
747 {
748  mSelectorWidget->setMapCanvas( canvas );
749 }
750 
752 {
753  return mSelectorWidget->symbol();
754 }
755 
757 {
758  // Ignore the ESC key to avoid close the dialog without the properties window
759  if ( !isWindow() && e->key() == Qt::Key_Escape )
760  {
761  e->ignore();
762  }
763  else
764  {
766  }
767 }
768 
770 {
771  mSelectorWidget->loadSymbol();
772 }
773 
775 {
776  mSelectorWidget->loadSymbol( symbol, parent );
777 }
778 
780 {
781  mSelectorWidget->updateUi();
782 }
783 
785 {
786  mSelectorWidget->updateLockButton();
787 }
788 
790 {
791  return mSelectorWidget->currentLayerItem();
792 }
793 
795 {
796  return mSelectorWidget->currentLayer();
797 }
798 
800 {
801  mSelectorWidget->moveLayerByOffset( offset );
802 }
803 
805 {
806  mSelectorWidget->setWidget( widget );
807 }
808 
810 {
811  mSelectorWidget->moveLayerDown();
812 }
813 
815 {
816  mSelectorWidget->moveLayerUp();
817 }
818 
820 {
821  mSelectorWidget->addLayer();
822 }
823 
825 {
826  mSelectorWidget->removeLayer();
827 }
828 
830 {
831  mSelectorWidget->lockLayer();
832 }
833 
835 {
837  mSelectorWidget->saveSymbol();
839 }
840 
842 {
843  mSelectorWidget->duplicateLayer();
844 }
845 
847 {
848  mSelectorWidget->layerChanged();
849 }
850 
852 {
853  mSelectorWidget->updateLayerPreview();
854 }
855 
857 {
858  mSelectorWidget->updatePreview();
859 }
860 
862 {
863  mSelectorWidget->symbolChanged();
864 }
865 
867 {
868  mSelectorWidget->changeLayer( layer );
869 }
QLayout * layout() const
Q_DECL_DEPRECATED void saveSymbol()
Save the current active symbol layer into the users saved styles.
void setLocked(bool locked)
Symbol selector widget that cna be used to select and build a symbol.
QByteArray toByteArray() const
void connectChildPanel(QgsPanelWidget *panel)
Connect the given sub panel widgets showPanel signals to this current panels main showPanel event to ...
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 ...
virtual void reject()
void setIcon(const QPixmap &i)
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const =0
void loadSymbol()
Reload the current symbol in the view.
virtual QgsSymbolLayerV2 * clone() const =0
Shall be reimplemented by subclasses to create a deep copy of the instance.
bool dockMode()
Return the dock mode state.
void changeLayer(QgsSymbolLayerV2 *layer)
alters tree and sets proper widget when Layer Type is changed
A container class for data source field mapping or expression.
static QIcon symbolLayerPreviewIcon(QgsSymbolLayerV2 *layer, QgsSymbolV2::OutputUnit u, QSize size, const QgsMapUnitScale &scale=QgsMapUnitScale())
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the dialog.
QMenu * advancedMenu()
return menu for "advanced" button - create it if doesn&#39;t exist and show the advanced button ...
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
void rejected()
QStyle * style() const
QgsSymbolV2 * symbol()
Return the symbol that is currently active in the widget.
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.
virtual void setDockMode(bool dockMode) override
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs...
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:514
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
void accepted()
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)
Base class for any widget that can be shown as a inline panel.
const QPixmap * icon() const
void updateLayerPreview()
Update the single symbol layer preview in the widget.
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
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:109
const QgsVectorLayer * mLayer
Marker symbol.
Definition: qgssymbolv2.h:78
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs...
void reset(T *other)
QgsExpressionContext * expressionContext() const
Returns the expression context used for the dialog, if set.
void setBold(bool enable)
void setWidget(QWidget *widget)
Set the properties widget for the active symbol layer.
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 setLayout(QLayout *layout)
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)
QgsSymbolV2SelectorWidget(QgsSymbolV2 *symbol, QgsStyleV2 *style, const QgsVectorLayer *vl, QWidget *parent=nullptr)
Symbol selector widget that can be used to select and build a symbol.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
bool isEmpty() const
void updatePreview()
Update the preivew of the whole symbol in the iterface.
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()
void hide()
void updateLockButton()
Update the lock button states based on the current symbol layer.
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
void moveLayerDown()
Move the active symbol layer down.
void addWidget(QWidget *w)
QgsSymbolLayerV2AbstractMetadata * symbolLayerMetadata(const QString &name) const
return metadata for specified symbol layer. Returns NULL if not found
virtual void accept()
bool isWindow() const
void widgetChanged()
Emiited when the widget state changes.
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)
void symbolModified()
Emiited when a symbol is modified in the widget.
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:515
virtual void keyPressEvent(QKeyEvent *e)
void addLayer()
Add a symobl layer to the bottom of the stack.
QVariant value(const QString &key, const QVariant &defaultValue) const
QgsSymbolLayerV2 * currentLayer()
The current symbol layer that is active in the interface.
void symbolChanged()
Slot to update tree when a new symbol from style.
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.
void setExpressionContext(QgsExpressionContext *context)
Sets the optional expression context used for the widget.
void setPanelTitle(QString panelTitle)
Set the title of the panel when shown in the interface.
QByteArray saveGeometry() const
bool isLocked() const
QStandardItem * itemFromIndex(const QModelIndex &index) const
void moveLayerUp()
Move the active symbol layer up.
void layerChanged()
Called when the layer changes in the widget.
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 lockLayer()
Lock the current active symbol layer.
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)
void keyPressEvent(QKeyEvent *e) override
Reimplements dialog keyPress event so we can ignore it.
Abstract base class for marker symbol layers.
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.
void removeLayer()
Remove the current active symbol layer.
virtual void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
virtual QVariant data(int role) const
QgsSymbolV2 * symbol()
Return the symbol that is currently active in the widget.
Q_DECL_DEPRECATED void saveSymbol()
QgsExpressionContext * expressionContext() const
Returns the expression context used for the dialog, if set.
void duplicateLayer()
Duplicates the current symbol layer and places the duplicated layer above the current symbol layer...
void updateUi()
Update the state of the UI based on the currently set symbol layer.
void moveLayerByOffset(int offset)
Move the current active layer by a set offset in the list.
const QgsVectorLayer * mVectorLayer