QGIS API Documentation  2.17.0-Master (0497e4a)
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  emit symbolModified();
605 }
606 
608 {
609  QModelIndex idx = layersTree->currentIndex();
610  if ( !idx.isValid() )
611  return;
612 
613  SymbolLayerItem *item = static_cast<SymbolLayerItem*>( model->itemFromIndex( idx ) );
614  if ( !item->isLayer() )
615  return;
616 
617  QgsSymbolLayerV2* source = item->layer();
618 
619  int insertIdx = item->row();
620  item = static_cast<SymbolLayerItem*>( item->parent() );
621 
622  QgsSymbolV2* parentSymbol = item->symbol();
623 
624  QgsSymbolLayerV2* newLayer = source->clone();
625  if ( insertIdx == -1 )
626  parentSymbol->appendSymbolLayer( newLayer );
627  else
628  parentSymbol->insertSymbolLayer( item->rowCount() - insertIdx, newLayer );
629 
630  SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer );
631  item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
632  if ( newLayer->subSymbol() )
633  {
634  loadSymbol( newLayer->subSymbol(), newLayerItem );
635  layersTree->setExpanded( newLayerItem->index(), true );
636  }
637  item->updatePreview();
638 
639  layersTree->setCurrentIndex( model->indexFromItem( newLayerItem ) );
640  updateUi();
641  updatePreview();
642 }
643 
645 {
646  bool ok;
647  QString name = QInputDialog::getText( this, tr( "Symbol name" ),
648  tr( "Please enter name for the symbol:" ), QLineEdit::Normal, tr( "New symbol" ), &ok );
649  if ( !ok || name.isEmpty() )
650  return;
651 
652  // check if there is no symbol with same name
653  if ( mStyle->symbolNames().contains( name ) )
654  {
655  int res = QMessageBox::warning( this, tr( "Save symbol" ),
656  tr( "Symbol with name '%1' already exists. Overwrite?" )
657  .arg( name ),
658  QMessageBox::Yes | QMessageBox::No );
659  if ( res != QMessageBox::Yes )
660  {
661  return;
662  }
663  }
664 
665  // add new symbol to style and re-populate the list
666  mStyle->addSymbol( name, mSymbol->clone() );
667 
668  // make sure the symbol is stored
669  mStyle->saveSymbol( name, mSymbol->clone(), 0, QStringList() );
670 }
671 
673 {
674  SymbolLayerItem* item = currentLayerItem();
675  QgsSymbolLayerV2* layer = item->layer();
676 
677  if ( layer->subSymbol() )
678  {
679  item->removeRow( 0 );
680  }
681  // update symbol layer item
682  item->setLayer( newLayer );
683  // When it is a marker symbol
684  if ( newLayer->subSymbol() )
685  {
686  loadSymbol( newLayer->subSymbol(), item );
687  layersTree->setExpanded( item->index(), true );
688  }
689 
690  // Change the symbol at last to avoid deleting item's layer
691  QgsSymbolV2* symbol = static_cast<SymbolLayerItem*>( item->parent() )->symbol();
692  int layerIdx = item->parent()->rowCount() - item->row() - 1;
693  symbol->changeSymbolLayer( layerIdx, newLayer );
694 
695  item->updatePreview();
696  updatePreview();
697  // Important: This lets the layer have its own layer properties widget
698  layerChanged();
699 }
700 
702  : QDialog( parent )
703 {
704  setLayout( new QVBoxLayout() );
705  mSelectorWidget = new QgsSymbolV2SelectorWidget( symbol, style, vl, this );
706  mButtonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
707 
708  connect( mButtonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
709  connect( mButtonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
710 
711  layout()->addWidget( mSelectorWidget );
712  layout()->addWidget( mButtonBox );
713 
714  QSettings settings;
715  restoreGeometry( settings.value( "/Windows/SymbolSelectorWidget/geometry" ).toByteArray() );
716 
717  // can be embedded in renderer properties dialog
718  if ( embedded )
719  {
720  mButtonBox->hide();
721  layout()->setContentsMargins( 0, 0, 0, 0 );
722  }
723  mSelectorWidget->setDockMode( embedded );
724 }
725 
727 {
728  QSettings settings;
729  settings.setValue( "/Windows/SymbolSelectorWidget/geometry", saveGeometry() );
730 }
731 
733 {
734  return mSelectorWidget->advancedMenu();
735 }
736 
738 {
739  mSelectorWidget->setExpressionContext( context );
740 }
741 
743 {
744  return mSelectorWidget->expressionContext();
745 }
746 
748 {
749  mSelectorWidget->setMapCanvas( canvas );
750 }
751 
753 {
754  return mSelectorWidget->symbol();
755 }
756 
758 {
759  // Ignore the ESC key to avoid close the dialog without the properties window
760  if ( !isWindow() && e->key() == Qt::Key_Escape )
761  {
762  e->ignore();
763  }
764  else
765  {
767  }
768 }
769 
771 {
772  mSelectorWidget->loadSymbol();
773 }
774 
776 {
777  mSelectorWidget->loadSymbol( symbol, parent );
778 }
779 
781 {
782  mSelectorWidget->updateUi();
783 }
784 
786 {
787  mSelectorWidget->updateLockButton();
788 }
789 
791 {
792  return mSelectorWidget->currentLayerItem();
793 }
794 
796 {
797  return mSelectorWidget->currentLayer();
798 }
799 
801 {
802  mSelectorWidget->moveLayerByOffset( offset );
803 }
804 
806 {
807  mSelectorWidget->setWidget( widget );
808 }
809 
811 {
812  mSelectorWidget->moveLayerDown();
813 }
814 
816 {
817  mSelectorWidget->moveLayerUp();
818 }
819 
821 {
822  mSelectorWidget->addLayer();
823 }
824 
826 {
827  mSelectorWidget->removeLayer();
828 }
829 
831 {
832  mSelectorWidget->lockLayer();
833 }
834 
836 {
838  mSelectorWidget->saveSymbol();
840 }
841 
843 {
844  mSelectorWidget->duplicateLayer();
845 }
846 
848 {
849  mSelectorWidget->layerChanged();
850 }
851 
853 {
854  mSelectorWidget->updateLayerPreview();
855 }
856 
858 {
859  mSelectorWidget->updatePreview();
860 }
861 
863 {
864  mSelectorWidget->symbolChanged();
865 }
866 
868 {
869  mSelectorWidget->changeLayer( layer );
870 }
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
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