QGIS API Documentation  3.6.0-Noosa (5873452)
qgssymbolslistwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssymbolslist.cpp
3  ---------------------
4  begin : June 2012
5  copyright : (C) 2012 by Arunmozhi
6  email : aruntheguy at gmail.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 
16 
17 #include "qgssymbolslistwidget.h"
18 
19 #include "qgsstylemanagerdialog.h"
20 #include "qgsstylesavedialog.h"
21 
22 #include "qgssymbol.h"
23 #include "qgsstyle.h"
24 #include "qgssymbollayerutils.h"
25 #include "qgsmarkersymbollayer.h"
26 #include "qgsmapcanvas.h"
27 #include "qgsapplication.h"
28 #include "qgsvectorlayer.h"
29 #include "qgssettings.h"
31 #include "qgsauxiliarystorage.h"
32 #include "qgsstylemodel.h"
33 #include "qgsgui.h"
35 
36 #include <QAction>
37 #include <QString>
38 #include <QStringList>
39 #include <QPainter>
40 #include <QIcon>
41 #include <QStandardItemModel>
42 #include <QColorDialog>
43 #include <QInputDialog>
44 #include <QMessageBox>
45 #include <QMenu>
46 #include <QPushButton>
47 
48 
49 //
50 // QgsReadOnlyStyleModel
51 //
52 
54 QgsReadOnlyStyleModel::QgsReadOnlyStyleModel( QgsStyle *style, QObject *parent )
55  : QgsStyleProxyModel( style, parent )
56 {
57 
58 }
59 
60 Qt::ItemFlags QgsReadOnlyStyleModel::flags( const QModelIndex &index ) const
61 {
62  return QgsStyleProxyModel::flags( index ) & ~Qt::ItemIsEditable;
63 }
64 
65 QVariant QgsReadOnlyStyleModel::data( const QModelIndex &index, int role ) const
66 {
67  if ( role == Qt::FontRole )
68  {
69  // drop font size to get reasonable amount of item name shown
70  QFont f = QgsStyleProxyModel::data( index, role ).value< QFont >();
71  f.setPointSize( 9 );
72  return f;
73  }
74  return QgsStyleProxyModel::data( index, role );
75 }
76 
78 
79 
80 //
81 // QgsSymbolsListWidget
82 //
83 
84 QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbol *symbol, QgsStyle *style, QMenu *menu, QWidget *parent, QgsVectorLayer *layer )
85  : QWidget( parent )
86  , mSymbol( symbol )
87  , mStyle( style )
88  , mLayer( layer )
89 {
90  setupUi( this );
91  connect( mSymbolUnitWidget, &QgsUnitSelectionWidget::changed, this, &QgsSymbolsListWidget::mSymbolUnitWidget_changed );
92  spinAngle->setClearValue( 0 );
93 
96 
97  mModel = new QgsReadOnlyStyleModel( mStyle, this );
98  mModel->setEntityFilterEnabled( true );
100  if ( mSymbol )
101  {
102  mModel->setSymbolTypeFilterEnabled( true );
103  mModel->setSymbolType( mSymbol->type() );
104  }
105 
106  btnAdvanced->hide(); // advanced button is hidden by default
107  if ( menu ) // show it if there is a menu pointer
108  {
109  mAdvancedMenu = menu;
110  btnAdvanced->show();
111  btnAdvanced->setMenu( mAdvancedMenu );
112  }
113  else
114  {
115  btnAdvanced->setMenu( new QMenu( this ) );
116  }
117  mClipFeaturesAction = new QAction( tr( "Clip Features to Canvas Extent" ), this );
118  mClipFeaturesAction->setCheckable( true );
119  connect( mClipFeaturesAction, &QAction::toggled, this, &QgsSymbolsListWidget::clipFeaturesToggled );
120  mStandardizeRingsAction = new QAction( tr( "Force Right-Hand-Rule Orientation" ), this );
121  mStandardizeRingsAction->setCheckable( true );
122  connect( mStandardizeRingsAction, &QAction::toggled, this, &QgsSymbolsListWidget::forceRHRToggled );
123 
124  double iconSize = Qgis::UI_SCALE_FACTOR * fontMetrics().width( 'X' ) * 10;
125  viewSymbols->setIconSize( QSize( static_cast< int >( iconSize ), static_cast< int >( iconSize * 0.9 ) ) ); // ~100, 90 on low dpi
126  double treeIconSize = Qgis::UI_SCALE_FACTOR * fontMetrics().width( 'X' ) * 2;
127  mSymbolTreeView->setIconSize( QSize( static_cast< int >( treeIconSize ), static_cast< int >( treeIconSize ) ) );
128 
129  mModel->addDesiredIconSize( viewSymbols->iconSize() );
130  mModel->addDesiredIconSize( mSymbolTreeView->iconSize() );
131  viewSymbols->setModel( mModel );
132  mSymbolTreeView->setModel( mModel );
133 
134  viewSymbols->setSelectionBehavior( QAbstractItemView::SelectRows );
135  mSymbolTreeView->setSelectionModel( viewSymbols->selectionModel() );
136  mSymbolTreeView->setSelectionMode( viewSymbols->selectionMode() );
137 
138  connect( viewSymbols->selectionModel(), &QItemSelectionModel::currentChanged, this, &QgsSymbolsListWidget::setSymbolFromStyle );
139 
141 
142  connect( openStyleManagerButton, &QToolButton::clicked, this, &QgsSymbolsListWidget::openStyleManager );
143 
144  lblSymbolName->clear();
145 
146  connect( mButtonIconView, &QToolButton::toggled, this, [ = ]( bool active )
147  {
148  if ( active )
149  {
150  mSymbolViewStackedWidget->setCurrentIndex( 0 );
151  // note -- we have to save state here and not in destructor, as new symbol list widgets are created before the previous ones are destroyed
152  QgsSettings().setValue( QStringLiteral( "UI/symbolsList/lastIconView" ), 0, QgsSettings::Gui );
153  }
154  } );
155  connect( mButtonListView, &QToolButton::toggled, this, [ = ]( bool active )
156  {
157  if ( active )
158  {
159  QgsSettings().setValue( QStringLiteral( "UI/symbolsList/lastIconView" ), 1, QgsSettings::Gui );
160  mSymbolViewStackedWidget->setCurrentIndex( 1 );
161  }
162  } );
163 
164  // restore previous view
165  QgsSettings settings;
166  const int currentView = settings.value( QStringLiteral( "UI/symbolsList/lastIconView" ), 0, QgsSettings::Gui ).toInt();
167  if ( currentView == 0 )
168  mButtonIconView->setChecked( true );
169  else
170  mButtonListView->setChecked( true );
171 
172  mSymbolTreeView->header()->restoreState( settings.value( QStringLiteral( "UI/symbolsList/treeState" ), QByteArray(), QgsSettings::Gui ).toByteArray() );
173  connect( mSymbolTreeView->header(), &QHeaderView::sectionResized, this, [this]
174  {
175  // note -- we have to save state here and not in destructor, as new symbol list widgets are created before the previous ones are destroyed
176  QgsSettings().setValue( QStringLiteral( "UI/symbolsList/treeState" ), mSymbolTreeView->header()->saveState(), QgsSettings::Gui );
177  } );
178 
179  QgsFilterLineEdit *groupEdit = new QgsFilterLineEdit();
180  groupEdit->setShowSearchIcon( true );
181  groupEdit->setShowClearButton( true );
182  groupEdit->setPlaceholderText( tr( "Filter symbols…" ) );
183  groupsCombo->setLineEdit( groupEdit );
184  populateGroups();
185  connect( groupsCombo, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsSymbolsListWidget::groupsCombo_currentIndexChanged );
186  connect( groupsCombo, &QComboBox::currentTextChanged, this, &QgsSymbolsListWidget::updateModelFilters );
187 
188  if ( mSymbol )
189  {
190  updateSymbolInfo();
191  }
192 
193  // select correct page in stacked widget
194  // there's a correspondence between symbol type number and page numbering => exploit it!
195  stackedWidget->setCurrentIndex( symbol->type() );
197  connect( spinAngle, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSymbolsListWidget::setMarkerAngle );
198  connect( spinSize, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSymbolsListWidget::setMarkerSize );
199  connect( spinWidth, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsSymbolsListWidget::setLineWidth );
200 
201  registerDataDefinedButton( mRotationDDBtn, QgsSymbolLayer::PropertyAngle );
203  registerDataDefinedButton( mSizeDDBtn, QgsSymbolLayer::PropertySize );
205  registerDataDefinedButton( mWidthDDBtn, QgsSymbolLayer::PropertyStrokeWidth );
207 
208  connect( this, &QgsSymbolsListWidget::changed, this, &QgsSymbolsListWidget::updateAssistantSymbol );
209  updateAssistantSymbol();
210 
211  btnColor->setAllowOpacity( true );
212  btnColor->setColorDialogTitle( tr( "Select Color" ) );
213  btnColor->setContext( QStringLiteral( "symbology" ) );
214  connect( btnSaveSymbol, &QPushButton::clicked, this, &QgsSymbolsListWidget::saveSymbol );
215 
216  connect( mOpacityWidget, &QgsOpacityWidget::opacityChanged, this, &QgsSymbolsListWidget::opacityChanged );
217 }
218 
220 {
221  // This action was added to the menu by this widget, clean it up
222  // The menu can be passed in the constructor, so may live longer than this widget
223  btnAdvanced->menu()->removeAction( mClipFeaturesAction );
224  btnAdvanced->menu()->removeAction( mStandardizeRingsAction );
225 }
226 
227 void QgsSymbolsListWidget::registerDataDefinedButton( QgsPropertyOverrideButton *button, QgsSymbolLayer::Property key )
228 {
229  button->setProperty( "propertyKey", key );
230  button->registerExpressionContextGenerator( this );
231 
232  connect( button, &QgsPropertyOverrideButton::createAuxiliaryField, this, &QgsSymbolsListWidget::createAuxiliaryField );
233 }
234 
235 void QgsSymbolsListWidget::createAuxiliaryField()
236 {
237  // try to create an auxiliary layer if not yet created
238  if ( !mLayer->auxiliaryLayer() )
239  {
240  QgsNewAuxiliaryLayerDialog dlg( mLayer, this );
241  dlg.exec();
242  }
243 
244  // return if still not exists
245  if ( !mLayer->auxiliaryLayer() )
246  return;
247 
248  QgsPropertyOverrideButton *button = qobject_cast<QgsPropertyOverrideButton *>( sender() );
249  QgsSymbolLayer::Property key = static_cast< QgsSymbolLayer::Property >( button->propertyKey() );
251 
252  // create property in auxiliary storage if necessary
253  if ( !mLayer->auxiliaryLayer()->exists( def ) )
254  mLayer->auxiliaryLayer()->addAuxiliaryField( def );
255 
256  // update property with join field name from auxiliary storage
257  QgsProperty property = button->toProperty();
258  property.setField( QgsAuxiliaryLayer::nameFromProperty( def, true ) );
259  property.setActive( true );
260  button->updateFieldLists();
261  button->setToProperty( property );
262 
263  QgsMarkerSymbol *markerSymbol = static_cast<QgsMarkerSymbol *>( mSymbol );
264  QgsLineSymbol *lineSymbol = static_cast<QgsLineSymbol *>( mSymbol );
265  switch ( key )
266  {
268  if ( markerSymbol )
269  markerSymbol->setDataDefinedAngle( button->toProperty() );
270  break;
271 
273  if ( markerSymbol )
274  {
275  markerSymbol->setDataDefinedSize( button->toProperty() );
276  markerSymbol->setScaleMethod( QgsSymbol::ScaleDiameter );
277  }
278  break;
279 
281  if ( lineSymbol )
282  lineSymbol->setDataDefinedWidth( button->toProperty() );
283  break;
284 
285  default:
286  break;
287  }
288 
289  emit changed();
290 }
291 
293 {
294  mContext = context;
295  Q_FOREACH ( QgsUnitSelectionWidget *unitWidget, findChildren<QgsUnitSelectionWidget *>() )
296  {
297  unitWidget->setMapCanvas( mContext.mapCanvas() );
298  }
299 #if 0
300  Q_FOREACH ( QgsPropertyOverrideButton *ddButton, findChildren<QgsPropertyOverrideButton *>() )
301  {
302  if ( ddButton->assistant() )
303  ddButton->assistant()->setMapCanvas( mContext.mapCanvas() );
304  }
305 #endif
306 }
307 
309 {
310  return mContext;
311 }
312 
314 {
315  mUpdatingGroups = true;
316  groupsCombo->blockSignals( true );
317  groupsCombo->clear();
318 
319  groupsCombo->addItem( tr( "Favorites" ), QVariant( "favorite" ) );
320  groupsCombo->addItem( tr( "All Symbols" ), QVariant( "all" ) );
321 
322  int index = 2;
323  QStringList tags = mStyle->tags();
324  if ( tags.count() > 0 )
325  {
326  tags.sort();
327  groupsCombo->insertSeparator( index );
328  Q_FOREACH ( const QString &tag, tags )
329  {
330  groupsCombo->addItem( tag, QVariant( "tag" ) );
331  index++;
332  }
333  }
334 
335  QStringList groups = mStyle->smartgroupNames();
336  if ( groups.count() > 0 )
337  {
338  groups.sort();
339  groupsCombo->insertSeparator( index + 1 );
340  Q_FOREACH ( const QString &group, groups )
341  {
342  groupsCombo->addItem( group, QVariant( "smartgroup" ) );
343  }
344  }
345  groupsCombo->blockSignals( false );
346 
347  QgsSettings settings;
348  index = settings.value( QStringLiteral( "qgis/symbolsListGroupsIndex" ), 0 ).toInt();
349  groupsCombo->setCurrentIndex( index );
350 
351  mUpdatingGroups = false;
352 
353  updateModelFilters();
354 }
355 
356 void QgsSymbolsListWidget::updateModelFilters()
357 {
358  if ( mUpdatingGroups )
359  return;
360 
361  const QString text = groupsCombo->currentText();
362  const bool isFreeText = text != groupsCombo->itemText( groupsCombo->currentIndex() );
363 
364  if ( isFreeText )
365  {
366  mModel->setFavoritesOnly( false );
367  mModel->setTagId( -1 );
368  mModel->setSmartGroupId( -1 );
369  mModel->setFilterString( groupsCombo->currentText() );
370  }
371  else if ( groupsCombo->currentData().toString() == QLatin1String( "favorite" ) )
372  {
373  mModel->setFavoritesOnly( true );
374  mModel->setTagId( -1 );
375  mModel->setSmartGroupId( -1 );
376  mModel->setFilterString( QString() );
377  }
378  else if ( groupsCombo->currentData().toString() == QLatin1String( "all" ) )
379  {
380  mModel->setFavoritesOnly( false );
381  mModel->setTagId( -1 );
382  mModel->setSmartGroupId( -1 );
383  mModel->setFilterString( QString() );
384  }
385  else if ( groupsCombo->currentData().toString() == QLatin1String( "smartgroup" ) )
386  {
387  mModel->setFavoritesOnly( false );
388  mModel->setTagId( -1 );
389  mModel->setSmartGroupId( mStyle->smartgroupId( text ) );
390  mModel->setFilterString( QString() );
391  }
392  else
393  {
394  mModel->setFavoritesOnly( false );
395  mModel->setTagId( mStyle->tagId( text ) );
396  mModel->setSmartGroupId( -1 );
397  mModel->setFilterString( QString() );
398  }
399 }
400 
401 void QgsSymbolsListWidget::forceRHRToggled( bool checked )
402 {
403  if ( !mSymbol )
404  return;
405 
406  mSymbol->setForceRHR( checked );
407  emit changed();
408 }
409 
411 {
412  // prefer to use global window manager to open the style manager, if possible!
413  // this allows reuse of an existing non-modal window instead of opening a new modal window.
414  // Note that we only use the non-modal dialog if we're open in the panel -- if we're already
415  // open as part of a modal dialog, then we MUST use another modal dialog or the result will
416  // not be focusable!
418  if ( !panel || !panel->dockMode()
420  || !QgsGui::windowManager()->openStandardDialog( QgsWindowManagerInterface::DialogStyleManager ) )
421  {
422  // fallback to modal dialog
423  QgsStyleManagerDialog dlg( mStyle, this );
424  dlg.exec();
425 
426  updateModelFilters(); // probably not needed -- the model should automatically update if any changes were made
427  }
428 }
429 
431 {
432  if ( !mSymbol )
433  return;
434 
435  mSymbol->setClipFeaturesToExtent( checked );
436  emit changed();
437 }
438 
439 void QgsSymbolsListWidget::setSymbolColor( const QColor &color )
440 {
441  mSymbol->setColor( color );
442  emit changed();
443 }
444 
446 {
447  QgsMarkerSymbol *markerSymbol = static_cast<QgsMarkerSymbol *>( mSymbol );
448  if ( markerSymbol->angle() == angle )
449  return;
450  markerSymbol->setAngle( angle );
451  emit changed();
452 }
453 
455 {
456  QgsMarkerSymbol *markerSymbol = static_cast<QgsMarkerSymbol *>( mSymbol );
457  QgsProperty dd( mRotationDDBtn->toProperty() );
458 
459  spinAngle->setEnabled( !mRotationDDBtn->isActive() );
460 
461  QgsProperty symbolDD( markerSymbol->dataDefinedAngle() );
462 
463  if ( // shall we remove datadefined expressions for layers ?
464  ( !symbolDD && !dd )
465  // shall we set the "en masse" expression for properties ?
466  || dd )
467  {
468  markerSymbol->setDataDefinedAngle( dd );
469  emit changed();
470  }
471 }
472 
474 {
475  QgsMarkerSymbol *markerSymbol = static_cast<QgsMarkerSymbol *>( mSymbol );
476  if ( markerSymbol->size() == size )
477  return;
478  markerSymbol->setSize( size );
479  emit changed();
480 }
481 
483 {
484  QgsMarkerSymbol *markerSymbol = static_cast<QgsMarkerSymbol *>( mSymbol );
485  QgsProperty dd( mSizeDDBtn->toProperty() );
486 
487  spinSize->setEnabled( !mSizeDDBtn->isActive() );
488 
489  QgsProperty symbolDD( markerSymbol->dataDefinedSize() );
490 
491  if ( // shall we remove datadefined expressions for layers ?
492  ( !symbolDD && !dd )
493  // shall we set the "en masse" expression for properties ?
494  || dd )
495  {
496  markerSymbol->setDataDefinedSize( dd );
497  markerSymbol->setScaleMethod( QgsSymbol::ScaleDiameter );
498  emit changed();
499  }
500 }
501 
503 {
504  QgsLineSymbol *lineSymbol = static_cast<QgsLineSymbol *>( mSymbol );
505  if ( lineSymbol->width() == width )
506  return;
507  lineSymbol->setWidth( width );
508  emit changed();
509 }
510 
512 {
513  QgsLineSymbol *lineSymbol = static_cast<QgsLineSymbol *>( mSymbol );
514  QgsProperty dd( mWidthDDBtn->toProperty() );
515 
516  spinWidth->setEnabled( !mWidthDDBtn->isActive() );
517 
518  QgsProperty symbolDD( lineSymbol->dataDefinedWidth() );
519 
520  if ( // shall we remove datadefined expressions for layers ?
521  ( !symbolDD && !dd )
522  // shall we set the "en masse" expression for properties ?
523  || dd )
524  {
525  lineSymbol->setDataDefinedWidth( dd );
526  emit changed();
527  }
528 }
529 
530 void QgsSymbolsListWidget::updateAssistantSymbol()
531 {
532  mAssistantSymbol.reset( mSymbol->clone() );
533  if ( mSymbol->type() == QgsSymbol::Marker )
534  mSizeDDBtn->setSymbol( mAssistantSymbol );
535  else if ( mSymbol->type() == QgsSymbol::Line && mLayer )
536  mWidthDDBtn->setSymbol( mAssistantSymbol );
537 }
538 
540 {
541  bool ok;
542  QString name = QInputDialog::getText( this, tr( "Save Symbol" ),
543  tr( "Please enter name for the symbol:" ), QLineEdit::Normal, tr( "New symbol" ), &ok );
544  if ( !ok || name.isEmpty() )
545  return;
546 
547  // check if there is no symbol with same name
548  if ( mStyle->symbolNames().contains( name ) )
549  {
550  int res = QMessageBox::warning( this, tr( "Save Symbol" ),
551  tr( "Symbol with name '%1' already exists. Overwrite?" )
552  .arg( name ),
553  QMessageBox::Yes | QMessageBox::No );
554  if ( res != QMessageBox::Yes )
555  {
556  return;
557  }
558  }
559 
560  // add new symbol to style and re-populate the list
561  mStyle->addSymbol( name, mSymbol->clone() );
562 
563  // make sure the symbol is stored
564  mStyle->saveSymbol( name, mSymbol->clone(), false, QStringList() );
565 }
566 
568 {
569  QgsStyleSaveDialog saveDlg( this );
570  if ( !saveDlg.exec() )
571  return;
572 
573  if ( saveDlg.name().isEmpty() )
574  return;
575 
576  // check if there is no symbol with same name
577  if ( mStyle->symbolNames().contains( saveDlg.name() ) )
578  {
579  int res = QMessageBox::warning( this, tr( "Save Symbol" ),
580  tr( "Symbol with name '%1' already exists. Overwrite?" )
581  .arg( saveDlg.name() ),
582  QMessageBox::Yes | QMessageBox::No );
583  if ( res != QMessageBox::Yes )
584  {
585  return;
586  }
587  mStyle->removeSymbol( saveDlg.name() );
588  }
589 
590  QStringList symbolTags = saveDlg.tags().split( ',' );
591 
592  // add new symbol to style and re-populate the list
593  mStyle->addSymbol( saveDlg.name(), mSymbol->clone() );
594 
595  // make sure the symbol is stored
596  mStyle->saveSymbol( saveDlg.name(), mSymbol->clone(), saveDlg.isFavorite(), symbolTags );
597 }
598 
599 void QgsSymbolsListWidget::mSymbolUnitWidget_changed()
600 {
601  if ( mSymbol )
602  {
603 
604  mSymbol->setOutputUnit( mSymbolUnitWidget->unit() );
605  mSymbol->setMapUnitScale( mSymbolUnitWidget->getMapUnitScale() );
606 
607  emit changed();
608  }
609 }
610 
611 void QgsSymbolsListWidget::opacityChanged( double opacity )
612 {
613  if ( mSymbol )
614  {
615  mSymbol->setOpacity( opacity );
616  emit changed();
617  }
618 }
619 
620 void QgsSymbolsListWidget::updateSymbolColor()
621 {
622  btnColor->blockSignals( true );
623  btnColor->setColor( mSymbol->color() );
624  btnColor->blockSignals( false );
625 }
626 
627 QgsExpressionContext QgsSymbolsListWidget::createExpressionContext() const
628 {
629  if ( mContext.expressionContext() )
630  return QgsExpressionContext( *mContext.expressionContext() );
631 
632  //otherwise create a default symbol context
633  QgsExpressionContext expContext( mContext.globalProjectAtlasMapLayerScopes( layer() ) );
634 
635  // additional scopes
636  Q_FOREACH ( const QgsExpressionContextScope &scope, mContext.additionalExpressionContextScopes() )
637  {
638  expContext.appendScope( new QgsExpressionContextScope( scope ) );
639  }
640 
641  expContext.setHighlightedVariables( QStringList() << QgsExpressionContext::EXPR_ORIGINAL_VALUE << QgsExpressionContext::EXPR_SYMBOL_COLOR
645 
646  return expContext;
647 }
648 
649 void QgsSymbolsListWidget::updateSymbolInfo()
650 {
651  updateSymbolColor();
652 
653  Q_FOREACH ( QgsPropertyOverrideButton *button, findChildren< QgsPropertyOverrideButton * >() )
654  {
655  button->registerExpressionContextGenerator( this );
656  }
657 
658  if ( mSymbol->type() == QgsSymbol::Marker )
659  {
660  QgsMarkerSymbol *markerSymbol = static_cast<QgsMarkerSymbol *>( mSymbol );
661  spinSize->setValue( markerSymbol->size() );
662  spinAngle->setValue( markerSymbol->angle() );
663 
664  if ( mLayer )
665  {
666  QgsProperty ddSize( markerSymbol->dataDefinedSize() );
667  mSizeDDBtn->init( QgsSymbolLayer::PropertySize, ddSize, QgsSymbolLayer::propertyDefinitions(), mLayer, true );
668  spinSize->setEnabled( !mSizeDDBtn->isActive() );
669  QgsProperty ddAngle( markerSymbol->dataDefinedAngle() );
670  mRotationDDBtn->init( QgsSymbolLayer::PropertyAngle, ddAngle, QgsSymbolLayer::propertyDefinitions(), mLayer, true );
671  spinAngle->setEnabled( !mRotationDDBtn->isActive() );
672  }
673  else
674  {
675  mSizeDDBtn->setEnabled( false );
676  mRotationDDBtn->setEnabled( false );
677  }
678  }
679  else if ( mSymbol->type() == QgsSymbol::Line )
680  {
681  QgsLineSymbol *lineSymbol = static_cast<QgsLineSymbol *>( mSymbol );
682  spinWidth->setValue( lineSymbol->width() );
683 
684  if ( mLayer )
685  {
686  QgsProperty dd( lineSymbol->dataDefinedWidth() );
687  mWidthDDBtn->init( QgsSymbolLayer::PropertyStrokeWidth, dd, QgsSymbolLayer::propertyDefinitions(), mLayer, true );
688  spinWidth->setEnabled( !mWidthDDBtn->isActive() );
689  }
690  else
691  {
692  mWidthDDBtn->setEnabled( false );
693  }
694  }
695 
696  mSymbolUnitWidget->blockSignals( true );
697  mSymbolUnitWidget->setUnit( mSymbol->outputUnit() );
698  mSymbolUnitWidget->setMapUnitScale( mSymbol->mapUnitScale() );
699  mSymbolUnitWidget->blockSignals( false );
700 
701  mOpacityWidget->setOpacity( mSymbol->opacity() );
702 
703  // Clean up previous advanced symbol actions
704  const QList<QAction *> actionList( btnAdvanced->menu()->actions() );
705  for ( const auto &action : actionList )
706  {
707  if ( mClipFeaturesAction->text() == action->text() )
708  {
709  btnAdvanced->menu()->removeAction( action );
710  }
711  else if ( mStandardizeRingsAction->text() == action->text() )
712  {
713  btnAdvanced->menu()->removeAction( action );
714  }
715  }
716 
717  if ( mSymbol->type() == QgsSymbol::Line || mSymbol->type() == QgsSymbol::Fill )
718  {
719  //add clip features option for line or fill symbols
720  btnAdvanced->menu()->addAction( mClipFeaturesAction );
721  }
722  if ( mSymbol->type() == QgsSymbol::Fill )
723  {
724  btnAdvanced->menu()->addAction( mStandardizeRingsAction );
725  }
726 
727  btnAdvanced->setVisible( mAdvancedMenu || !btnAdvanced->menu()->isEmpty() );
728 
729  whileBlocking( mClipFeaturesAction )->setChecked( mSymbol->clipFeaturesToExtent() );
730  whileBlocking( mStandardizeRingsAction )->setChecked( mSymbol->forceRHR() );
731 }
732 
733 void QgsSymbolsListWidget::setSymbolFromStyle( const QModelIndex &index )
734 {
735  QString symbolName = mModel->data( mModel->index( index.row(), QgsStyleModel::Name ) ).toString();
736  lblSymbolName->setText( symbolName );
737  // get new instance of symbol from style
738  std::unique_ptr< QgsSymbol > s( mStyle->symbol( symbolName ) );
739  if ( !s )
740  return;
741 
742  // remove all symbol layers from original symbolgroupsCombo
743  while ( mSymbol->symbolLayerCount() )
744  mSymbol->deleteSymbolLayer( 0 );
745  // move all symbol layers to our symbol
746  while ( s->symbolLayerCount() )
747  {
748  QgsSymbolLayer *sl = s->takeSymbolLayer( 0 );
749  mSymbol->appendSymbolLayer( sl );
750  }
751  mSymbol->setOpacity( s->opacity() );
752 
753  updateSymbolInfo();
754  emit changed();
755 }
756 
757 void QgsSymbolsListWidget::groupsCombo_currentIndexChanged( int index )
758 {
759  QgsSettings settings;
760  settings.setValue( QStringLiteral( "qgis/symbolsListGroupsIndex" ), index );
761 }
static const QString EXPR_ORIGINAL_VALUE
Inbuilt variable name for value original value variable.
static const QString EXPR_CLUSTER_COLOR
Inbuilt variable name for cluster color variable.
Meters value as Map units.
Definition: qgsunittypes.h:120
QList< QgsExpressionContextScope * > globalProjectAtlasMapLayerScopes(const QgsMapLayer *layer) const
Returns list of scopes: global, project, atlas, map, layer.
void setFilterString(const QString &filter)
Sets a filter string, such that only symbol entities with names matching the specified string will be...
void setLineWidth(double width)
static QgsWindowManagerInterface * windowManager()
Returns the global window manager, if set.
Definition: qgsgui.cpp:113
QString tags() const
returns the text value of the tags element
bool dockMode()
Returns the dock mode state.
static const QString EXPR_GEOMETRY_POINT_COUNT
Inbuilt variable name for point count variable.
void setSymbolFromStyle(const QModelIndex &index)
A dialog allowing users to customize and populate a QgsStyle.
void setSmartGroupId(int id)
Sets a smart group id to filter style entities by.
void setMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol.
Definition: qgssymbol.cpp:269
Calculate scale by the diameter.
Definition: qgssymbol.h:97
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:61
a dialog for setting properties of a newly saved style.
static const double UI_SCALE_FACTOR
UI scaling factor.
Definition: qgis.h:139
bool exists(const QgsPropertyDefinition &definition) const
Returns true if the property is stored in the layer already, false otherwise.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
bool appendSymbolLayer(QgsSymbolLayer *layer)
Appends a symbol layer at the end of the current symbol layer list.
Definition: qgssymbol.cpp:360
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setTagId(int id)
Sets a tag id to filter style entities by.
QgsMapUnitScale mapUnitScale() const
Returns the map unit scale for the symbol.
Definition: qgssymbol.cpp:237
QString name() const
returns the text value of the name element
void setSize(double size)
Sets the size for the whole symbol.
Definition: qgssymbol.cpp:1277
bool clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context&#39;s extent...
Definition: qgssymbol.h:380
void setSymbolType(QgsSymbol::SymbolType type)
Sets the symbol type filter.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Definition: qgssymbol.h:150
Base class for any widget that can be shown as a inline panel.
void setMarkerSize(double size)
bool deleteSymbolLayer(int index)
Removes and deletes the symbol layer at the specified index.
Definition: qgssymbol.cpp:370
void setDataDefinedAngle(const QgsProperty &property)
Set data defined angle for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1203
Line symbol.
Definition: qgssymbol.h:86
void setAngle(double symbolAngle)
Sets the angle for the whole symbol.
Definition: qgssymbol.cpp:1168
void setFavoritesOnly(bool favoritesOnly)
Sets whether the model should show only favorited entities.
QList< QgsUnitTypes::RenderUnit > RenderUnitList
List of render units.
Definition: qgsunittypes.h:184
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:786
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:732
void populateGroups()
Pupulates the groups combo box with available tags and smartgroups.
A line symbol type, for rendering LineString and MultiLineString geometries.
Definition: qgssymbol.h:920
QgsUnitTypes::RenderUnit outputUnit() const
Returns the units to use for sizes and widths within the symbol.
Definition: qgssymbol.cpp:216
void setOutputUnit(QgsUnitTypes::RenderUnit unit)
Sets the units to use for sizes and widths within the symbol.
Definition: qgssymbol.cpp:261
void setSymbolTypeFilterEnabled(bool enabled)
Sets whether filtering by symbol type is enabled.
void createAuxiliaryField()
Emitted when creating a new auxiliary field.
QgsProperty dataDefinedAngle() const
Returns data defined angle for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1231
A dialog to create a new auxiliary layer.
void setField(const QString &field)
Sets the field name the property references.
void setEntityFilterEnabled(bool enabled)
Sets whether filtering by entity type is enabled.
void addDesiredIconSize(QSize size)
Adds an additional icon size to generate for Qt::DecorationRole data.
A button for controlling property overrides which may apply to a widget.
QStringList symbolNames()
Returns a list of names of symbols.
Definition: qgsstyle.cpp:191
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget...
bool forceRHR() const
Returns true if polygon features drawn by the symbol will be reoriented to follow the standard right-...
Definition: qgssymbol.h:402
Contains settings which reflect the context in which a symbol (or renderer) widget is shown...
void setToProperty(const QgsProperty &property)
Sets the widget to reflect the current state of a QgsProperty.
QgsProperty toProperty() const
Returns a QgsProperty object encapsulating the current state of the widget.
void setOpacity(qreal opacity)
Sets the opacity for the symbol.
Definition: qgssymbol.h:346
void setWidth(double width)
Sets the width for the whole line symbol.
Definition: qgssymbol.cpp:1608
double width() const
Returns the estimated width for the whole symbol, which is the maximum width of all marker symbol lay...
Definition: qgssymbol.cpp:1634
void registerExpressionContextGenerator(QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
void opacityChanged(double opacity)
Emitted when the opacity is changed in the widget, where opacity ranges from 0.0 (transparent) to 1...
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void groupsModified()
Is emitted every time a tag or smartgroup has been added, removed, or renamed.
points (e.g., for font sizes)
Definition: qgsunittypes.h:118
void setSymbolColor(const QColor &color)
static const QString EXPR_SYMBOL_COLOR
Inbuilt variable name for symbol color variable.
QLineEdit subclass with built in support for clearing the widget&#39;s value and handling custom null val...
QColor color() const
Returns the symbol&#39;s color.
Definition: qgssymbol.cpp:461
void setMarkerAngle(double angle)
void setScaleMethod(QgsSymbol::ScaleMethod scaleMethod)
Definition: qgssymbol.cpp:1483
Single scope for storing variables and functions for use within a QgsExpressionContext.
A store for object properties.
Definition: qgsproperty.h:229
QgsAuxiliaryLayer * auxiliaryLayer()
Returns the current auxiliary layer.
A QSortFilterProxyModel subclass for showing filtered symbol and color ramps entries from a QgsStyle ...
void setDataDefinedWidth(const QgsProperty &property)
Set data defined width for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1668
const QgsVectorLayer * layer() const
Returns the vector layer associated with the widget.
Definition for a property.
Definition: qgsproperty.h:46
int smartgroupId(const QString &smartgroup)
Returns the DB id for the given smartgroup name.
Definition: qgsstyle.cpp:1221
QgsProperty dataDefinedSize() const
Returns data defined size for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1428
QStringList smartgroupNames()
Returns the smart groups list.
Definition: qgsstyle.cpp:1303
int tagId(const QString &tag)
Returns the DB id for the given tag name.
Definition: qgsstyle.cpp:1216
void colorChanged(const QColor &color)
Is emitted whenever a new color is set for the button.
void changed()
Emitted when property definition changes.
QgsMapCanvas * mapCanvas() const
Returns the map canvas associated with the widget.
void clipFeaturesToggled(bool checked)
void setContext(const QgsSymbolWidgetContext &context)
Sets the context in which the symbol widget is shown, e.g., the associated map canvas and expression ...
Marker symbol.
Definition: qgssymbol.h:85
bool addSymbol(const QString &name, QgsSymbol *symbol, bool update=false)
Adds a symbol to style and takes symbol&#39;s ownership.
Definition: qgsstyle.cpp:88
QgsExpressionContext * expressionContext() const
Returns the expression context used for the widget, if set.
QStringList tags() const
Returns a list of all tags in the style database.
Definition: qgsstyle.cpp:647
Fill symbol.
Definition: qgssymbol.h:87
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:212
Name column.
Definition: qgsstylemodel.h:50
SymbolType type() const
Returns the symbol&#39;s type.
Definition: qgssymbol.h:120
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
Definition: qgssymbol.cpp:1300
static QString nameFromProperty(const QgsPropertyDefinition &def, bool joined=false)
Returns the name of the auxiliary field for a property definition.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
int propertyKey() const
Returns the property key linked to the button.
static const QString EXPR_CLUSTER_SIZE
Inbuilt variable name for cluster size variable.
QgsSymbolWidgetContext context() const
Returns the context in which the symbol widget is shown, e.g., the associated map canvas and expressi...
bool isFavorite() const
returns whether the favorite element is checked
static const QString EXPR_GEOMETRY_POINT_NUM
Inbuilt variable name for point number variable.
QgsSymbol * symbol(const QString &name)
Returns a NEW copy of symbol.
Definition: qgsstyle.cpp:175
QgsSymbol * symbol()
Returns the symbol that is currently active in the widget.
void setMapCanvas(QgsMapCanvas *canvas)
Sets the map canvas associated with the widget.
void setDataDefinedSize(const QgsProperty &property)
Set data defined size for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1392
bool saveSymbol(const QString &name, QgsSymbol *symbol, bool favorite, const QStringList &tags)
Adds the symbol to the DB with the tags.
Definition: qgsstyle.cpp:112
void setClipFeaturesToExtent(bool clipFeaturesToExtent)
Sets whether features drawn by the symbol should be clipped to the render context&#39;s extent...
Definition: qgssymbol.h:369
qreal opacity() const
Returns the opacity for the symbol.
Definition: qgssymbol.h:339
bool removeSymbol(const QString &name)
Removes symbol from style (and delete it)
Definition: qgsstyle.cpp:143
void setEntityFilter(QgsStyle::StyleEntity filter)
Sets the style entity type filter.
static const QgsPropertiesDefinition & propertyDefinitions()
Returns the symbol layer property definitions.
void setForceRHR(bool force)
Sets whether polygon features drawn by the symbol should be reoriented to follow the standard right-h...
Definition: qgssymbol.h:391
A widget displaying a combobox allowing the user to choose between various display units...
bool addAuxiliaryField(const QgsPropertyDefinition &definition)
Adds an auxiliary field for the given property.
static const QString EXPR_GEOMETRY_PART_NUM
Inbuilt variable name for geometry part number variable.
Represents a vector layer which manages a vector based data sets.
void updateFieldLists()
Updates list of fields.
static const QString EXPR_GEOMETRY_PART_COUNT
Inbuilt variable name for geometry part count variable.
QgsProperty dataDefinedWidth() const
Returns data defined width for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1703
double angle() const
Returns the marker angle for the whole symbol.
Definition: qgssymbol.cpp:1180
QgsSymbolsListWidget(QgsSymbol *symbol, QgsStyle *style, QMenu *menu, QWidget *parent, QgsVectorLayer *layer=nullptr)
Constructor for QgsSymbolsListWidget.
Property
Data definable properties.
QList< QgsExpressionContextScope > additionalExpressionContextScopes() const
Returns the list of additional expression context scopes to show as available within the layer...
void setColor(const QColor &color)
Sets the color for the symbol.
Definition: qgssymbol.cpp:452