QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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  delete mSymbol;
306  mSymbol = nullptr;
307 }
308 
310 {
311  SymbolLayerItem* symbolItem = new SymbolLayerItem( symbol );
312  QFont boldFont = symbolItem->font();
313  boldFont.setBold( true );
314  symbolItem->setFont( boldFont );
315  parent->appendRow( symbolItem );
316 
317  int count = symbol->symbolLayerCount();
318  for ( int i = count - 1; i >= 0; i-- )
319  {
320  SymbolLayerItem *layerItem = new SymbolLayerItem( symbol->symbolLayer( i ) );
321  layerItem->setEditable( false );
322  symbolItem->appendRow( layerItem );
323  if ( symbol->symbolLayer( i )->subSymbol() )
324  {
325  loadSymbol( symbol->symbolLayer( i )->subSymbol(), layerItem );
326  }
327  layersTree->setExpanded( layerItem->index(), true );
328  }
329  layersTree->setExpanded( symbolItem->index(), true );
330 }
331 
332 
334 {
335  model->clear();
336  loadSymbol( mSymbol, static_cast<SymbolLayerItem*>( model->invisibleRootItem() ) );
337 }
338 
340 {
341  QModelIndex currentIdx = layersTree->currentIndex();
342  if ( !currentIdx.isValid() )
343  return;
344 
345  SymbolLayerItem *item = static_cast<SymbolLayerItem*>( model->itemFromIndex( currentIdx ) );
346  if ( !item->isLayer() )
347  {
348  btnUp->setEnabled( false );
349  btnDown->setEnabled( false );
350  btnRemoveLayer->setEnabled( false );
351  btnLock->setEnabled( false );
352  btnDuplicate->setEnabled( false );
353  return;
354  }
355 
356  int rowCount = item->parent()->rowCount();
357  int currentRow = item->row();
358 
359  btnUp->setEnabled( currentRow > 0 );
360  btnDown->setEnabled( currentRow < rowCount - 1 );
361  btnRemoveLayer->setEnabled( rowCount > 1 );
362  btnLock->setEnabled( true );
363  btnDuplicate->setEnabled( true );
364 }
365 
367 {
368  QImage preview = mSymbol->bigSymbolPreviewImage( mPresetExpressionContext.data() );
369  lblPreview->setPixmap( QPixmap::fromImage( preview ) );
370  // Hope this is a appropriate place
371  emit symbolModified();
372 }
373 
375 {
376  // get current layer item and update its icon
377  SymbolLayerItem* item = currentLayerItem();
378  if ( item )
379  item->updatePreview();
380  // update also preview of the whole symbol
381  updatePreview();
382 }
383 
385 {
386  QModelIndex idx = layersTree->currentIndex();
387  if ( !idx.isValid() )
388  return nullptr;
389 
390  SymbolLayerItem *item = static_cast<SymbolLayerItem*>( model->itemFromIndex( idx ) );
391  if ( !item->isLayer() )
392  return nullptr;
393 
394  return item;
395 }
396 
398 {
399  QModelIndex idx = layersTree->currentIndex();
400  if ( !idx.isValid() )
401  return nullptr;
402 
403  SymbolLayerItem *item = static_cast<SymbolLayerItem*>( model->itemFromIndex( idx ) );
404  if ( item->isLayer() )
405  return item->layer();
406 
407  return nullptr;
408 }
409 
411 {
412  updateUi();
413 
414  SymbolLayerItem *currentItem = static_cast<SymbolLayerItem*>( model->itemFromIndex( layersTree->currentIndex() ) );
415  if ( !currentItem )
416  return;
417 
418  if ( currentItem->isLayer() )
419  {
420  SymbolLayerItem *parent = static_cast<SymbolLayerItem*>( currentItem->parent() );
421  mDataDefineRestorer.reset( new DataDefinedRestorer( parent->symbol(), currentItem->layer() ) );
422  QgsLayerPropertiesWidget *layerProp = new QgsLayerPropertiesWidget( currentItem->layer(), parent->symbol(), mVectorLayer );
423  layerProp->setDockMode( this->dockMode() );
424  layerProp->setExpressionContext( mPresetExpressionContext.data() );
425  layerProp->setMapCanvas( mMapCanvas );
426  setWidget( layerProp );
427  connect( layerProp, SIGNAL( changed() ), mDataDefineRestorer.data(), SLOT( restore() ) );
428  connect( layerProp, SIGNAL( changed() ), this, SLOT( updateLayerPreview() ) );
429  // This connection when layer type is changed
430  connect( layerProp, SIGNAL( changeLayer( QgsSymbolLayerV2* ) ), this, SLOT( changeLayer( QgsSymbolLayerV2* ) ) );
431 
432  connectChildPanel( layerProp );
433  }
434  else
435  {
436  mDataDefineRestorer.reset();
437  // then it must be a symbol
438  currentItem->symbol()->setLayer( mVectorLayer );
439  // Now populate symbols of that type using the symbols list widget:
440  QgsSymbolsListWidget *symbolsList = new QgsSymbolsListWidget( currentItem->symbol(), mStyle, mAdvancedMenu, this, mVectorLayer );
441  symbolsList->setExpressionContext( mPresetExpressionContext.data() );
442  symbolsList->setMapCanvas( mMapCanvas );
443 
444  setWidget( symbolsList );
445  connect( symbolsList, SIGNAL( changed() ), this, SLOT( symbolChanged() ) );
446  }
448 }
449 
451 {
452  SymbolLayerItem *currentItem = static_cast<SymbolLayerItem*>( model->itemFromIndex( layersTree->currentIndex() ) );
453  if ( !currentItem || currentItem->isLayer() )
454  return;
455  // disconnect to avoid recreating widget
456  disconnect( layersTree->selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ), this, SLOT( layerChanged() ) );
457  if ( currentItem->parent() )
458  {
459  // it is a sub-symbol
460  QgsSymbolV2* symbol = currentItem->symbol();
461  SymbolLayerItem *parent = static_cast<SymbolLayerItem*>( currentItem->parent() );
462  parent->removeRow( 0 );
463  loadSymbol( symbol, parent );
464  layersTree->setCurrentIndex( parent->child( 0 )->index() );
465  parent->updatePreview();
466  }
467  else
468  {
469  //it is the symbol itself
470  loadSymbol();
471  QModelIndex newIndex = layersTree->model()->index( 0, 0 );
472  layersTree->setCurrentIndex( newIndex );
473  }
474  updatePreview();
475  // connect it back once things are set
476  connect( layersTree->selectionModel(), SIGNAL( currentChanged( const QModelIndex&, const QModelIndex& ) ), this, SLOT( layerChanged() ) );
477 }
478 
480 {
481  int index = stackedWidget->addWidget( widget );
482  stackedWidget->setCurrentIndex( index );
483  if ( mPresentWidget )
485  mPresentWidget = widget;
486 }
487 
489 {
490  QgsSymbolLayerV2* layer = currentLayer();
491  if ( !layer )
492  return;
493  btnLock->setChecked( layer->isLocked() );
494 }
495 
497 {
498  QModelIndex idx = layersTree->currentIndex();
499  if ( !idx.isValid() )
500  return;
501 
502  int insertIdx = -1;
503  SymbolLayerItem *item = static_cast<SymbolLayerItem*>( model->itemFromIndex( idx ) );
504  if ( item->isLayer() )
505  {
506  insertIdx = item->row();
507  item = static_cast<SymbolLayerItem*>( item->parent() );
508  }
509 
510  QgsSymbolV2* parentSymbol = item->symbol();
511 
512  // save data-defined values at marker level
513  QgsDataDefined ddSize = parentSymbol->type() == QgsSymbolV2::Marker
514  ? static_cast<QgsMarkerSymbolV2 *>( parentSymbol )->dataDefinedSize()
515  : QgsDataDefined();
516  QgsDataDefined ddAngle = parentSymbol->type() == QgsSymbolV2::Marker
517  ? static_cast<QgsMarkerSymbolV2 *>( parentSymbol )->dataDefinedAngle()
518  : QgsDataDefined();
519  QgsDataDefined ddWidth = parentSymbol->type() == QgsSymbolV2::Line
520  ? static_cast<QgsLineSymbolV2 *>( parentSymbol )->dataDefinedWidth()
521  : QgsDataDefined() ;
522 
524  if ( insertIdx == -1 )
525  parentSymbol->appendSymbolLayer( newLayer );
526  else
527  parentSymbol->insertSymbolLayer( item->rowCount() - insertIdx, newLayer );
528 
529  // restore data-defined values at marker level
530  if ( ddSize != QgsDataDefined() )
531  static_cast<QgsMarkerSymbolV2 *>( parentSymbol )->setDataDefinedSize( ddSize );
532  if ( ddAngle != QgsDataDefined() )
533  static_cast<QgsMarkerSymbolV2 *>( parentSymbol )->setDataDefinedAngle( ddAngle );
534  if ( ddWidth != QgsDataDefined() )
535  static_cast<QgsLineSymbolV2 *>( parentSymbol )->setDataDefinedWidth( ddWidth );
536 
537  SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer );
538  item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
539  item->updatePreview();
540 
541  layersTree->setCurrentIndex( model->indexFromItem( newLayerItem ) );
542  updateUi();
543  updatePreview();
544 }
545 
547 {
548  SymbolLayerItem *item = currentLayerItem();
549  int row = item->row();
550  SymbolLayerItem *parent = static_cast<SymbolLayerItem*>( item->parent() );
551 
552  int layerIdx = parent->rowCount() - row - 1; // IMPORTANT
553  QgsSymbolV2* parentSymbol = parent->symbol();
554  QgsSymbolLayerV2 *tmpLayer = parentSymbol->takeSymbolLayer( layerIdx );
555 
556  parent->removeRow( row );
557  parent->updatePreview();
558 
559  QModelIndex newIdx = parent->child( 0 )->index();
560  layersTree->setCurrentIndex( newIdx );
561 
562  updateUi();
563  updatePreview();
564  //finally delete the removed layer pointer
565  delete tmpLayer;
566 }
567 
569 {
570  moveLayerByOffset( + 1 );
571 }
572 
574 {
575  moveLayerByOffset( -1 );
576 }
577 
579 {
580  SymbolLayerItem *item = currentLayerItem();
581  if ( !item )
582  return;
583  int row = item->row();
584 
585  SymbolLayerItem *parent = static_cast<SymbolLayerItem*>( item->parent() );
586  QgsSymbolV2* parentSymbol = parent->symbol();
587 
588  int layerIdx = parent->rowCount() - row - 1;
589  // switch layers
590  QgsSymbolLayerV2* tmpLayer = parentSymbol->takeSymbolLayer( layerIdx );
591  parentSymbol->insertSymbolLayer( layerIdx - offset, tmpLayer );
592 
593  QList<QStandardItem*> rowItems = parent->takeRow( row );
594  parent->insertRows( row + offset, rowItems );
595  parent->updatePreview();
596 
597  QModelIndex newIdx = rowItems[ 0 ]->index();
598  layersTree->setCurrentIndex( newIdx );
599 
600  updatePreview();
601  updateUi();
602 }
603 
605 {
606  QgsSymbolLayerV2* layer = currentLayer();
607  if ( !layer )
608  return;
609  layer->setLocked( btnLock->isChecked() );
610  emit symbolModified();
611 }
612 
614 {
615  QModelIndex idx = layersTree->currentIndex();
616  if ( !idx.isValid() )
617  return;
618 
619  SymbolLayerItem *item = static_cast<SymbolLayerItem*>( model->itemFromIndex( idx ) );
620  if ( !item->isLayer() )
621  return;
622 
623  QgsSymbolLayerV2* source = item->layer();
624 
625  int insertIdx = item->row();
626  item = static_cast<SymbolLayerItem*>( item->parent() );
627 
628  QgsSymbolV2* parentSymbol = item->symbol();
629 
630  QgsSymbolLayerV2* newLayer = source->clone();
631  if ( insertIdx == -1 )
632  parentSymbol->appendSymbolLayer( newLayer );
633  else
634  parentSymbol->insertSymbolLayer( item->rowCount() - insertIdx, newLayer );
635 
636  SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer );
637  item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
638  if ( newLayer->subSymbol() )
639  {
640  loadSymbol( newLayer->subSymbol(), newLayerItem );
641  layersTree->setExpanded( newLayerItem->index(), true );
642  }
643  item->updatePreview();
644 
645  layersTree->setCurrentIndex( model->indexFromItem( newLayerItem ) );
646  updateUi();
647  updatePreview();
648 }
649 
651 {
652  bool ok;
653  QString name = QInputDialog::getText( this, tr( "Symbol name" ),
654  tr( "Please enter name for the symbol:" ), QLineEdit::Normal, tr( "New symbol" ), &ok );
655  if ( !ok || name.isEmpty() )
656  return;
657 
658  // check if there is no symbol with same name
659  if ( mStyle->symbolNames().contains( name ) )
660  {
661  int res = QMessageBox::warning( this, tr( "Save symbol" ),
662  tr( "Symbol with name '%1' already exists. Overwrite?" )
663  .arg( name ),
664  QMessageBox::Yes | QMessageBox::No );
665  if ( res != QMessageBox::Yes )
666  {
667  return;
668  }
669  }
670 
671  // add new symbol to style and re-populate the list
672  mStyle->addSymbol( name, mSymbol->clone() );
673 
674  // make sure the symbol is stored
675  mStyle->saveSymbol( name, mSymbol->clone(), 0, QStringList() );
676 }
677 
679 {
680  SymbolLayerItem* item = currentLayerItem();
681  QgsSymbolLayerV2* layer = item->layer();
682 
683  if ( layer->subSymbol() )
684  {
685  item->removeRow( 0 );
686  }
687  // update symbol layer item
688  item->setLayer( newLayer );
689  // When it is a marker symbol
690  if ( newLayer->subSymbol() )
691  {
692  loadSymbol( newLayer->subSymbol(), item );
693  layersTree->setExpanded( item->index(), true );
694  }
695 
696  // Change the symbol at last to avoid deleting item's layer
697  QgsSymbolV2* symbol = static_cast<SymbolLayerItem*>( item->parent() )->symbol();
698  int layerIdx = item->parent()->rowCount() - item->row() - 1;
699  symbol->changeSymbolLayer( layerIdx, newLayer );
700 
701  item->updatePreview();
702  updatePreview();
703  // Important: This lets the layer have its own layer properties widget
704  layerChanged();
705 }
706 
708  : QDialog( parent )
709 {
710  setLayout( new QVBoxLayout() );
711  mSelectorWidget = new QgsSymbolV2SelectorWidget( symbol, style, vl, this );
712  mButtonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
713 
714  connect( mButtonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
715  connect( mButtonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
716 
717  layout()->addWidget( mSelectorWidget );
718  layout()->addWidget( mButtonBox );
719 
720  QSettings settings;
721  restoreGeometry( settings.value( "/Windows/SymbolSelectorWidget/geometry" ).toByteArray() );
722 
723  // can be embedded in renderer properties dialog
724  if ( embedded )
725  {
726  mButtonBox->hide();
727  layout()->setContentsMargins( 0, 0, 0, 0 );
728  }
729  mSelectorWidget->setDockMode( embedded );
730 }
731 
733 {
734  QSettings settings;
735  settings.setValue( "/Windows/SymbolSelectorWidget/geometry", saveGeometry() );
736 }
737 
739 {
740  return mSelectorWidget->advancedMenu();
741 }
742 
744 {
745  mSelectorWidget->setExpressionContext( context );
746 }
747 
749 {
750  return mSelectorWidget->expressionContext();
751 }
752 
754 {
755  mSelectorWidget->setMapCanvas( canvas );
756 }
757 
759 {
760  return mSelectorWidget->symbol();
761 }
762 
764 {
765  // Ignore the ESC key to avoid close the dialog without the properties window
766  if ( !isWindow() && e->key() == Qt::Key_Escape )
767  {
768  e->ignore();
769  }
770  else
771  {
773  }
774 }
775 
777 {
778  mSelectorWidget->loadSymbol();
779 }
780 
782 {
783  mSelectorWidget->loadSymbol( symbol, parent );
784 }
785 
787 {
788  mSelectorWidget->updateUi();
789 }
790 
792 {
793  mSelectorWidget->updateLockButton();
794 }
795 
797 {
798  return mSelectorWidget->currentLayerItem();
799 }
800 
802 {
803  return mSelectorWidget->currentLayer();
804 }
805 
807 {
808  mSelectorWidget->moveLayerByOffset( offset );
809 }
810 
812 {
813  mSelectorWidget->setWidget( widget );
814 }
815 
817 {
818  mSelectorWidget->moveLayerDown();
819 }
820 
822 {
823  mSelectorWidget->moveLayerUp();
824 }
825 
827 {
828  mSelectorWidget->addLayer();
829 }
830 
832 {
833  mSelectorWidget->removeLayer();
834 }
835 
837 {
838  mSelectorWidget->lockLayer();
839 }
840 
842 {
844  mSelectorWidget->saveSymbol();
846 }
847 
849 {
850  mSelectorWidget->duplicateLayer();
851 }
852 
854 {
855  mSelectorWidget->layerChanged();
856 }
857 
859 {
860  mSelectorWidget->updateLayerPreview();
861 }
862 
864 {
865  mSelectorWidget->updatePreview();
866 }
867 
869 {
870  mSelectorWidget->symbolChanged();
871 }
872 
874 {
875  mSelectorWidget->changeLayer( layer );
876 }
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 ...
QgsSymbolLayerV2AbstractMetadata * symbolLayerMetadata(const QString &name) const
return metadata for specified symbol layer. Returns NULL if not found
QStandardItem * invisibleRootItem() const
void releaseSymbol()
Delete the symbol.
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:515
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)
SymbolType type() const
Definition: qgssymbolv2.h:107
Line symbol.
Definition: qgssymbolv2.h:82
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:81
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)
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:67
static QIcon symbolPreviewIcon(QgsSymbolV2 *symbol, QSize size)
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
QgsExpressionContext * expressionContext() const
Returns the expression context used for the dialog, if set.
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:134
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)
virtual void accept()
bool isWindow() const
QgsExpressionContext * expressionContext() const
Returns the expression context used for the dialog, if set.
void widgetChanged()
Emitted 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)
const QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.
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:516
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
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:83
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.
QgsSymbolV2::SymbolType type() const
virtual QVariant data(int role) const
QgsSymbolV2 * symbol()
Return the symbol that is currently active in the widget.
Q_DECL_DEPRECATED void saveSymbol()
void duplicateLayer()
Duplicates the current symbol layer and places the duplicated layer above the current symbol layer...
bool isLocked() const
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