QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgspropertyoverridebutton.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspropertyoverridebutton.cpp
3  -----------------------------
4  Date : January 2017
5  Copyright : (C) 2017 by Nyall Dawson
6  Email : nyall dot dawson 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 "qgsapplication.h"
20 #include "qgsexpression.h"
21 #include "qgsmessageviewer.h"
22 #include "qgsvectorlayer.h"
23 #include "qgspanelwidget.h"
25 #include "qgsauxiliarystorage.h"
26 #include "qgscolorschemeregistry.h"
27 #include "qgscolorbutton.h"
28 #include "qgsguiutils.h"
29 
30 #include <QClipboard>
31 #include <QMenu>
32 #include <QMouseEvent>
33 #include <QPointer>
34 #include <QGroupBox>
35 #include <QRegularExpression>
36 
38  const QgsVectorLayer *layer )
39  : QToolButton( parent )
40  , mVectorLayer( layer )
41 
42 {
43  setFocusPolicy( Qt::StrongFocus );
44 
46 
47  // button width is 1.25 * icon size, height 1.1 * icon size. But we round to ensure even pixel sizes for equal margins
48  setFixedSize( 2 * static_cast< int >( 1.25 * iconSize / 2.0 ), 2 * static_cast< int >( iconSize * 1.1 / 2.0 ) );
49 
50  setIconSize( QSize( iconSize, iconSize ) );
51  setPopupMode( QToolButton::InstantPopup );
52 
53  connect( this, &QgsPropertyOverrideButton::activated, this, &QgsPropertyOverrideButton::updateSiblingWidgets );
54 
55  mDefineMenu = new QMenu( this );
56  connect( mDefineMenu, &QMenu::aboutToShow, this, &QgsPropertyOverrideButton::aboutToShowMenu );
57  connect( mDefineMenu, &QMenu::triggered, this, &QgsPropertyOverrideButton::menuActionTriggered );
58  setMenu( mDefineMenu );
59 
60  mFieldsMenu = new QMenu( this );
61  mActionDataTypes = new QAction( this );
62  // list fields and types in submenu, since there may be many
63  mActionDataTypes->setMenu( mFieldsMenu );
64 
65  mActionVariables = new QAction( tr( "Variable" ), this );
66  mVariablesMenu = new QMenu( this );
67  mActionVariables->setMenu( mVariablesMenu );
68 
69  mActionColors = new QAction( tr( "Color" ), this );
70  mColorsMenu = new QMenu( this );
71  mActionColors->setMenu( mColorsMenu );
72 
73  mActionActive = new QAction( this );
74  QFont f = mActionActive->font();
75  f.setBold( true );
76  mActionActive->setFont( f );
77 
78  mActionDescription = new QAction( tr( "Description…" ), this );
79 
80  mActionCreateAuxiliaryField = new QAction( tr( "Store Data in the Project" ), this );
81  mActionCreateAuxiliaryField->setCheckable( true );
82 
83  mActionExpDialog = new QAction( tr( "Edit…" ), this );
84  mActionExpression = nullptr;
85  mActionPasteExpr = new QAction( tr( "Paste" ), this );
86  mActionCopyExpr = new QAction( tr( "Copy" ), this );
87  mActionClearExpr = new QAction( tr( "Clear" ), this );
88  mActionAssistant = new QAction( tr( "Assistant…" ), this );
89  QFont assistantFont = mActionAssistant->font();
90  assistantFont.setBold( true );
91  mActionAssistant->setFont( assistantFont );
92  mDefineMenu->addAction( mActionAssistant );
93 }
94 
95 
96 void QgsPropertyOverrideButton::init( int propertyKey, const QgsProperty &property, const QgsPropertiesDefinition &definitions, const QgsVectorLayer *layer, bool auxiliaryStorageEnabled )
97 {
98  init( propertyKey, property, definitions.value( propertyKey ), layer, auxiliaryStorageEnabled );
99 }
100 
101 void QgsPropertyOverrideButton::init( int propertyKey, const QgsProperty &property, const QgsPropertyDefinition &definition, const QgsVectorLayer *layer, bool auxiliaryStorageEnabled )
102 {
103  mVectorLayer = layer;
104  mAuxiliaryStorageEnabled = auxiliaryStorageEnabled;
105  setToProperty( property );
106  mPropertyKey = propertyKey;
107 
108  mDefinition = definition;
109  mDataTypes = mDefinition.dataType();
110 
111  mInputDescription = mDefinition.helpText();
112  mFullDescription.clear();
113  mUsageInfo.clear();
114 
115  // set up data types string
116  mDataTypesString.clear();
117 
118  QStringList ts;
119  switch ( mDataTypes )
120  {
122  ts << tr( "boolean" );
124 
126  ts << tr( "int" );
127  ts << tr( "double" );
129 
131  ts << tr( "string" );
132  break;
133  }
134 
135  if ( !ts.isEmpty() )
136  {
137  mDataTypesString = ts.join( QLatin1String( ", " ) );
138  mActionDataTypes->setText( tr( "Field type: " ) + mDataTypesString );
139  }
140 
142  updateGui();
143  updateSiblingWidgets( isActive() );
144 }
145 
146 void QgsPropertyOverrideButton::init( int propertyKey, const QgsAbstractPropertyCollection &collection, const QgsPropertiesDefinition &definitions, const QgsVectorLayer *layer, bool auxiliaryStorageEnabled )
147 {
148  init( propertyKey, collection.property( propertyKey ), definitions, layer, auxiliaryStorageEnabled );
149 }
150 
151 
153 {
154  mFieldNameList.clear();
155  mFieldTypeList.clear();
156 
157  if ( mVectorLayer )
158  {
159  // store just a list of fields of unknown type or those that match the expected type
160  const QgsFields fields = mVectorLayer->fields();
161  for ( const QgsField &f : fields )
162  {
163  bool fieldMatch = false;
164  QString fieldType;
165 
166  switch ( mDataTypes )
167  {
169  fieldMatch = true;
170  break;
171 
173  fieldMatch = f.isNumeric() || f.type() == QVariant::String;
174  break;
175 
177  fieldMatch = f.type() == QVariant::String;
178  break;
179  }
180 
181  switch ( f.type() )
182  {
183  case QVariant::String:
184  fieldType = tr( "string" );
185  break;
186  case QVariant::Int:
187  fieldType = tr( "integer" );
188  break;
189  case QVariant::LongLong:
190  fieldType = tr( "integer64" );
191  break;
192  case QVariant::Double:
193  fieldType = tr( "double" );
194  break;
195  case QVariant::Bool:
196  fieldType = tr( "boolean" );
197  break;
198  default:
199  fieldType = tr( "unknown type" );
200  }
201  if ( fieldMatch )
202  {
203  mFieldNameList << f.name();
204  mFieldTypeList << fieldType;
205  }
206  }
207  }
208 }
209 
211 {
212  return mProperty;
213 }
214 
216 {
217  mVectorLayer = layer;
218 }
219 
220 void QgsPropertyOverrideButton::registerCheckedWidget( QWidget *widget, bool natural )
221 {
222  const auto constMSiblingWidgets = mSiblingWidgets;
223  for ( const SiblingWidget &sw : constMSiblingWidgets )
224  {
225  if ( widget == sw.mWidgetPointer.data() && sw.mSiblingType == SiblingCheckState )
226  return;
227  }
228  mSiblingWidgets.append( SiblingWidget( QPointer<QWidget>( widget ), SiblingCheckState, natural ) );
229  updateSiblingWidgets( isActive() );
230 }
231 
232 void QgsPropertyOverrideButton::registerEnabledWidget( QWidget *widget, bool natural )
233 {
234  const auto constMSiblingWidgets = mSiblingWidgets;
235  for ( const SiblingWidget &sw : constMSiblingWidgets )
236  {
237  if ( widget == sw.mWidgetPointer.data() && sw.mSiblingType == SiblingEnableState )
238  return;
239  }
240  mSiblingWidgets.append( SiblingWidget( QPointer<QWidget>( widget ), SiblingEnableState, natural ) );
241  updateSiblingWidgets( isActive() );
242 }
243 
244 void QgsPropertyOverrideButton::registerVisibleWidget( QWidget *widget, bool natural )
245 {
246  const auto constMSiblingWidgets = mSiblingWidgets;
247  for ( const SiblingWidget &sw : constMSiblingWidgets )
248  {
249  if ( widget == sw.mWidgetPointer.data() && sw.mSiblingType == SiblingVisibility )
250  return;
251  }
252  mSiblingWidgets.append( SiblingWidget( QPointer<QWidget>( widget ), SiblingVisibility, natural ) );
253  updateSiblingWidgets( isActive() );
254 }
255 
257 {
258  const auto constMSiblingWidgets = mSiblingWidgets;
259  for ( const SiblingWidget &sw : constMSiblingWidgets )
260  {
261  if ( widget == sw.mWidgetPointer.data() && sw.mSiblingType == SiblingExpressionText )
262  return;
263  }
264  mSiblingWidgets.append( SiblingWidget( QPointer<QWidget>( widget ), SiblingExpressionText ) );
265  updateSiblingWidgets( isActive() );
266 }
267 
268 
270 {
271  // Ctrl-click to toggle activated state
272  if ( ( event->modifiers() & ( Qt::ControlModifier ) )
273  || event->button() == Qt::RightButton )
274  {
275  setActivePrivate( !mProperty.isActive() );
276  updateGui();
277  emit changed();
278  event->ignore();
279  return;
280  }
281 
282  // pass to default behavior
283  QToolButton::mousePressEvent( event );
284 }
285 
287 {
288  if ( property )
289  {
290  switch ( property.propertyType() )
291  {
294  break;
296  {
297  mFieldName = property.field();
298  break;
299  }
301  {
302  mExpressionString = property.expressionString();
303  break;
304  }
305  }
306  }
307  else
308  {
309  mFieldName.clear();
310  mExpressionString.clear();
311  }
312  mProperty = property;
313  setActive( mProperty && mProperty.isActive() );
314  updateSiblingWidgets( isActive() );
315  updateGui();
316 }
317 
319 void QgsPropertyOverrideButton::aboutToShowMenu()
320 {
321  mDefineMenu->clear();
322  // update fields so that changes made to layer's fields are reflected
324 
325  bool hasExp = !mExpressionString.isEmpty();
326  QString ddTitle = tr( "Data defined override" );
327 
328  QAction *ddTitleAct = mDefineMenu->addAction( ddTitle );
329  QFont titlefont = ddTitleAct->font();
330  titlefont.setItalic( true );
331  ddTitleAct->setFont( titlefont );
332  ddTitleAct->setEnabled( false );
333 
334  bool addActiveAction = false;
335  if ( mProperty.propertyType() == QgsProperty::ExpressionBasedProperty && hasExp )
336  {
337  QgsExpression exp( mExpressionString );
338  // whether expression is parse-able
339  addActiveAction = !exp.hasParserError();
340  }
341  else if ( mProperty.propertyType() == QgsProperty::FieldBasedProperty )
342  {
343  // whether field exists
344  addActiveAction = mFieldNameList.contains( mFieldName );
345  }
346 
347  if ( addActiveAction )
348  {
349  ddTitleAct->setText( ddTitle + " (" + ( mProperty.propertyType() == QgsProperty::ExpressionBasedProperty ? tr( "expression" ) : tr( "field" ) ) + ')' );
350  mDefineMenu->addAction( mActionActive );
351  mActionActive->setText( mProperty.isActive() ? tr( "Deactivate" ) : tr( "Activate" ) );
352  mActionActive->setData( QVariant( !mProperty.isActive() ) );
353  }
354 
355  if ( !mFullDescription.isEmpty() )
356  {
357  mDefineMenu->addAction( mActionDescription );
358  }
359 
360  mDefineMenu->addSeparator();
361 
362  // deactivate button if field already exists
363  if ( mAuxiliaryStorageEnabled && mVectorLayer )
364  {
365  mDefineMenu->addAction( mActionCreateAuxiliaryField );
366 
367  const QgsAuxiliaryLayer *alayer = mVectorLayer->auxiliaryLayer();
368 
369  mActionCreateAuxiliaryField->setEnabled( true );
370  mActionCreateAuxiliaryField->setChecked( false );
371 
372  int index = mVectorLayer->fields().indexFromName( mFieldName );
373  int srcIndex;
374  if ( index >= 0 && alayer && mVectorLayer->isAuxiliaryField( index, srcIndex ) )
375  {
376  mActionCreateAuxiliaryField->setEnabled( false );
377  mActionCreateAuxiliaryField->setChecked( true );
378  }
379  }
380 
381  bool fieldActive = false;
382  if ( !mDataTypesString.isEmpty() )
383  {
384  QAction *fieldTitleAct = mDefineMenu->addAction( tr( "Attribute Field" ) );
385  fieldTitleAct->setFont( titlefont );
386  fieldTitleAct->setEnabled( false );
387 
388  mDefineMenu->addAction( mActionDataTypes );
389 
390  mFieldsMenu->clear();
391 
392  if ( !mFieldNameList.isEmpty() )
393  {
394 
395  for ( int j = 0; j < mFieldNameList.count(); ++j )
396  {
397  QString fldname = mFieldNameList.at( j );
398  QAction *act = mFieldsMenu->addAction( fldname + " (" + mFieldTypeList.at( j ) + ')' );
399  act->setData( QVariant( fldname ) );
400  if ( mFieldName == fldname )
401  {
402  act->setCheckable( true );
403  act->setChecked( mProperty.propertyType() == QgsProperty::FieldBasedProperty );
404  fieldActive = mProperty.propertyType() == QgsProperty::FieldBasedProperty;
405  }
406  }
407  }
408  else
409  {
410  QAction *act = mFieldsMenu->addAction( tr( "No matching field types found" ) );
411  act->setEnabled( false );
412  }
413 
414  mDefineMenu->addSeparator();
415  }
416 
417  mFieldsMenu->menuAction()->setCheckable( true );
418  mFieldsMenu->menuAction()->setChecked( fieldActive && mProperty.propertyType() == QgsProperty::FieldBasedProperty && !mProperty.transformer() );
419 
420  bool colorActive = false;
421  mColorsMenu->clear();
424  {
425  // project colors menu
426  QAction *colorTitleAct = mDefineMenu->addAction( tr( "Project Color" ) );
427  colorTitleAct->setFont( titlefont );
428  colorTitleAct->setEnabled( false );
429 
430  QList<QgsProjectColorScheme *> projectSchemes;
431  QgsApplication::colorSchemeRegistry()->schemes( projectSchemes );
432  if ( projectSchemes.length() > 0 )
433  {
434  QgsProjectColorScheme *scheme = projectSchemes.at( 0 );
435  const QgsNamedColorList colors = scheme->fetchColors();
436  for ( const auto &color : colors )
437  {
438  if ( color.second.isEmpty() )
439  continue;
440 
441  QPixmap icon = QgsColorButton::createMenuIcon( color.first, mDefinition.standardTemplate() == QgsPropertyDefinition::ColorWithAlpha );
442  QAction *act = mColorsMenu->addAction( color.second );
443  act->setIcon( icon );
444  if ( mProperty.propertyType() == QgsProperty::ExpressionBasedProperty && hasExp && mExpressionString == QStringLiteral( "project_color('%1')" ).arg( color.second ) )
445  {
446  act->setCheckable( true );
447  act->setChecked( true );
448  colorActive = true;
449  }
450  }
451  }
452 
453  if ( mColorsMenu->actions().isEmpty() )
454  {
455  QAction *act = mColorsMenu->addAction( tr( "No colors set" ) );
456  act->setEnabled( false );
457  }
458 
459  mDefineMenu->addAction( mActionColors );
460  mColorsMenu->menuAction()->setCheckable( true );
461  mColorsMenu->menuAction()->setChecked( colorActive && !mProperty.transformer() );
462 
463  mDefineMenu->addSeparator();
464  }
465 
466  QAction *exprTitleAct = mDefineMenu->addAction( tr( "Expression" ) );
467  exprTitleAct->setFont( titlefont );
468  exprTitleAct->setEnabled( false );
469 
470  mVariablesMenu->clear();
471  bool variableActive = false;
472  if ( mExpressionContextGenerator )
473  {
474  QgsExpressionContext context = mExpressionContextGenerator->createExpressionContext();
475  QStringList variables = context.variableNames();
476  const auto constVariables = variables;
477  for ( const QString &variable : constVariables )
478  {
479  if ( context.isReadOnly( variable ) ) //only want to show user-set variables
480  continue;
481  if ( variable.startsWith( '_' ) ) //no hidden variables
482  continue;
483 
484  QAction *act = mVariablesMenu->addAction( variable );
485  act->setData( QVariant( variable ) );
486 
487  if ( mProperty.propertyType() == QgsProperty::ExpressionBasedProperty && hasExp && mExpressionString == '@' + variable )
488  {
489  act->setCheckable( true );
490  act->setChecked( true );
491  variableActive = true;
492  }
493  }
494  }
495 
496  if ( mVariablesMenu->actions().isEmpty() )
497  {
498  QAction *act = mVariablesMenu->addAction( tr( "No variables set" ) );
499  act->setEnabled( false );
500  }
501 
502  mDefineMenu->addAction( mActionVariables );
503  mVariablesMenu->menuAction()->setCheckable( true );
504  mVariablesMenu->menuAction()->setChecked( variableActive && !mProperty.transformer() );
505 
506  if ( hasExp )
507  {
508  QString expString = mExpressionString;
509  if ( expString.length() > 35 )
510  {
511  expString.truncate( 35 );
512  expString.append( QChar( 0x2026 ) );
513  }
514 
515  expString.prepend( tr( "Current: " ) );
516 
517  if ( !mActionExpression )
518  {
519  mActionExpression = new QAction( expString, this );
520  mActionExpression->setCheckable( true );
521  }
522  else
523  {
524  mActionExpression->setText( expString );
525  }
526  mDefineMenu->addAction( mActionExpression );
527  mActionExpression->setChecked( mProperty.propertyType() == QgsProperty::ExpressionBasedProperty && !variableActive && !colorActive && !mProperty.transformer() );
528 
529  mDefineMenu->addAction( mActionExpDialog );
530  mDefineMenu->addAction( mActionCopyExpr );
531  mDefineMenu->addAction( mActionPasteExpr );
532  }
533  else
534  {
535  mDefineMenu->addAction( mActionExpDialog );
536  mDefineMenu->addAction( mActionPasteExpr );
537  }
538 
539  if ( hasExp || !mFieldName.isEmpty() )
540  {
541  mDefineMenu->addSeparator();
542  mDefineMenu->addAction( mActionClearExpr );
543  }
544 
545  if ( !mDefinition.name().isEmpty() && mDefinition.supportsAssistant() )
546  {
547  mDefineMenu->addSeparator();
548  mActionAssistant->setCheckable( mProperty.transformer() );
549  mActionAssistant->setChecked( mProperty.transformer() );
550  mDefineMenu->addAction( mActionAssistant );
551  }
552 }
553 
554 void QgsPropertyOverrideButton::menuActionTriggered( QAction *action )
555 {
556  if ( action == mActionActive )
557  {
558  setActivePrivate( mActionActive->data().toBool() );
559  updateGui();
560  emit changed();
561  }
562  else if ( action == mActionDescription )
563  {
564  showDescriptionDialog();
565  }
566  else if ( action == mActionExpDialog )
567  {
568  showExpressionDialog();
569  }
570  else if ( action == mActionExpression )
571  {
572  mProperty.setExpressionString( mExpressionString );
573  mProperty.setTransformer( nullptr );
574  setActivePrivate( true );
575  updateSiblingWidgets( isActive() );
576  updateGui();
577  emit changed();
578  }
579  else if ( action == mActionCopyExpr )
580  {
581  QApplication::clipboard()->setText( mExpressionString );
582  }
583  else if ( action == mActionPasteExpr )
584  {
585  QString exprString = QApplication::clipboard()->text();
586  if ( !exprString.isEmpty() )
587  {
588  mExpressionString = exprString;
589  mProperty.setExpressionString( mExpressionString );
590  mProperty.setTransformer( nullptr );
591  setActivePrivate( true );
592  updateSiblingWidgets( isActive() );
593  updateGui();
594  emit changed();
595  }
596  }
597  else if ( action == mActionClearExpr )
598  {
599  setActivePrivate( false );
600  mProperty.setStaticValue( QVariant() );
601  mProperty.setTransformer( nullptr );
602  mExpressionString.clear();
603  updateSiblingWidgets( isActive() );
604  updateGui();
605  emit changed();
606  }
607  else if ( action == mActionAssistant )
608  {
609  showAssistant();
610  }
611  else if ( action == mActionCreateAuxiliaryField )
612  {
613  emit createAuxiliaryField();
614  }
615  else if ( mFieldsMenu->actions().contains( action ) ) // a field name clicked
616  {
617  if ( action->isEnabled() )
618  {
619  if ( mFieldName != action->text() )
620  {
621  mFieldName = action->data().toString();
622  }
623  mProperty.setField( mFieldName );
624  mProperty.setTransformer( nullptr );
625  setActivePrivate( true );
626  updateSiblingWidgets( isActive() );
627  updateGui();
628  emit changed();
629  }
630  }
631  else if ( mVariablesMenu->actions().contains( action ) ) // a variable name clicked
632  {
633  if ( mExpressionString != action->text().prepend( "@" ) )
634  {
635  mExpressionString = action->data().toString().prepend( "@" );
636  }
637  mProperty.setExpressionString( mExpressionString );
638  mProperty.setTransformer( nullptr );
639  setActivePrivate( true );
640  updateSiblingWidgets( isActive() );
641  updateGui();
642  emit changed();
643  }
644  else if ( mColorsMenu->actions().contains( action ) ) // a color name clicked
645  {
646  if ( mExpressionString != QStringLiteral( "project_color('%1')" ).arg( action->text() ) )
647  {
648  mExpressionString = QStringLiteral( "project_color('%1')" ).arg( action->text() );
649  }
650  mProperty.setExpressionString( mExpressionString );
651  mProperty.setTransformer( nullptr );
652  setActivePrivate( true );
653  updateSiblingWidgets( isActive() );
654  updateGui();
655  emit changed();
656  }
657 }
659 
660 void QgsPropertyOverrideButton::showDescriptionDialog()
661 {
662  QgsMessageViewer *mv = new QgsMessageViewer( this );
663  mv->setWindowTitle( tr( "Data Definition Description" ) );
664  mv->setMessageAsHtml( mFullDescription );
665  mv->exec();
666 }
667 
668 
669 void QgsPropertyOverrideButton::showExpressionDialog()
670 {
671  QgsExpressionContext context = mExpressionContextGenerator ? mExpressionContextGenerator->createExpressionContext() : QgsExpressionContext();
672 
673  // build sensible initial expression text - see https://github.com/qgis/QGIS/issues/26526
674  QString currentExpression = ( mProperty.propertyType() == QgsProperty::StaticProperty && !mProperty.staticValue().isValid() ) ? QString()
675  : mProperty.asExpression();
676 
677  QgsExpressionBuilderDialog d( const_cast<QgsVectorLayer *>( mVectorLayer ), currentExpression, this, QStringLiteral( "generic" ), context );
678  d.setExpectedOutputFormat( mInputDescription );
679  if ( d.exec() == QDialog::Accepted )
680  {
681  mExpressionString = d.expressionText().trimmed();
682  mProperty.setExpressionString( mExpressionString );
683  mProperty.setTransformer( nullptr );
684  setActivePrivate( !mExpressionString.isEmpty() );
685  updateSiblingWidgets( isActive() );
686  updateGui();
687  emit changed();
688  }
689  activateWindow(); // reset focus to parent window
690 }
691 
692 void QgsPropertyOverrideButton::showAssistant()
693 {
694  //first step - try to convert any existing expression to a transformer if one doesn't
695  //already exist
696  if ( !mProperty.transformer() )
697  {
698  ( void )mProperty.convertToTransformer();
699  }
700 
702  QgsPropertyAssistantWidget *widget = new QgsPropertyAssistantWidget( panel, mDefinition, mProperty, mVectorLayer );
703  widget->registerExpressionContextGenerator( mExpressionContextGenerator );
704  widget->setSymbol( mSymbol ); // we only show legend preview in dialog version
705 
706  if ( panel && panel->dockMode() )
707  {
708  connect( widget, &QgsPropertyAssistantWidget::widgetChanged, this, [this, widget]
709  {
710  widget->updateProperty( this->mProperty );
711  mExpressionString = this->mProperty.asExpression();
712  mFieldName = this->mProperty.field();
713  updateSiblingWidgets( isActive() );
714  this->emit changed();
715  } );
716 
717  // if the source layer is removed, we need to dismiss the assistant immediately
718  connect( mVectorLayer, &QObject::destroyed, widget, &QgsPanelWidget::acceptPanel );
719 
720  connect( widget, &QgsPropertyAssistantWidget::panelAccepted, this, [ = ] { updateGui(); } );
721 
722  panel->openPanel( widget );
723  return;
724  }
725  else
726  {
727  // Show the dialog version if not in a panel
728  QDialog *dlg = new QDialog( this );
729  QString key = QStringLiteral( "/UI/paneldialog/%1" ).arg( widget->panelTitle() );
730  QgsSettings settings;
731  dlg->restoreGeometry( settings.value( key ).toByteArray() );
732  dlg->setWindowTitle( widget->panelTitle() );
733  dlg->setLayout( new QVBoxLayout() );
734  dlg->layout()->addWidget( widget );
735  QDialogButtonBox *buttonBox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
736  connect( buttonBox, &QDialogButtonBox::accepted, dlg, &QDialog::accept );
737  connect( buttonBox, &QDialogButtonBox::rejected, dlg, &QDialog::reject );
738  connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsPropertyOverrideButton::showHelp );
739  dlg->layout()->addWidget( buttonBox );
740 
741  if ( dlg->exec() == QDialog::Accepted )
742  {
743  widget->updateProperty( mProperty );
744  mExpressionString = mProperty.asExpression();
745  mFieldName = mProperty.field();
746  widget->acceptPanel();
747  updateSiblingWidgets( isActive() );
748  updateGui();
749 
750  emit changed();
751  }
752  settings.setValue( key, dlg->saveGeometry() );
753  }
754 }
755 
756 void QgsPropertyOverrideButton::updateGui()
757 {
758  bool hasExp = !mExpressionString.isEmpty();
759  bool hasField = !mFieldName.isEmpty();
760 
761  QIcon icon = QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefine.svg" ) );
762  QString deftip = tr( "undefined" );
763  QString deftype;
764  if ( mProperty.propertyType() == QgsProperty::ExpressionBasedProperty && hasExp )
765  {
766  icon = mProperty.isActive() ? QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineExpressionOn.svg" ) ) : QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineExpression.svg" ) );
767 
768  QRegularExpression rx( QStringLiteral( "^project_color\\('(.*)'\\)$" ) );
769  QRegularExpressionMatch match = rx.match( mExpressionString );
770  if ( match.hasMatch() )
771  {
772  icon = mProperty.isActive() ? QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineColorOn.svg" ) ) : QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineColor.svg" ) );
773  deftip = match.captured( 1 );
774  deftype = tr( "project color" );
775  }
776  else
777  {
778  QgsExpression exp( mExpressionString );
779  if ( exp.hasParserError() )
780  {
781  icon = QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineExpressionError.svg" ) );
782  deftip = tr( "Parse error: %1" ).arg( exp.parserErrorString() );
783  }
784  else
785  {
786  deftip = mExpressionString;
787  }
788  }
789  }
790  else if ( mProperty.propertyType() != QgsProperty::ExpressionBasedProperty && hasField )
791  {
792  icon = mProperty.isActive() ? QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineOn.svg" ) ) : QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefine.svg" ) );
793 
794  if ( !mFieldNameList.contains( mFieldName ) && !mProperty.transformer() )
795  {
796  icon = QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineError.svg" ) );
797  deftip = tr( "'%1' field missing" ).arg( mFieldName );
798  }
799  else
800  {
801  deftip = mFieldName;
802  }
803  }
804 
805  setIcon( icon );
806 
807  // build full description for tool tip and popup dialog
808  mFullDescription = tr( "<b><u>Data defined override</u></b><br>" );
809 
810  mFullDescription += tr( "<b>Active: </b>%1&nbsp;&nbsp;&nbsp;<i>(ctrl|right-click toggles)</i><br>" ).arg( mProperty.isActive() ? tr( "yes" ) : tr( "no" ) );
811 
812  if ( !mUsageInfo.isEmpty() )
813  {
814  mFullDescription += tr( "<b>Usage:</b><br>%1<br>" ).arg( mUsageInfo );
815  }
816 
817  if ( !mInputDescription.isEmpty() )
818  {
819  mFullDescription += tr( "<b>Expected input:</b><br>%1<br>" ).arg( mInputDescription );
820  }
821 
822  if ( !mDataTypesString.isEmpty() )
823  {
824  mFullDescription += tr( "<b>Valid input types:</b><br>%1<br>" ).arg( mDataTypesString );
825  }
826 
827  if ( deftype.isEmpty() && deftip != tr( "undefined" ) )
828  {
829  deftype = mProperty.propertyType() == QgsProperty::ExpressionBasedProperty ? tr( "expression" ) : tr( "field" );
830  }
831 
832  // truncate long expressions, or tool tip may be too wide for screen
833  if ( deftip.length() > 75 )
834  {
835  deftip.truncate( 75 );
836  deftip.append( QChar( 0x2026 ) );
837  }
838 
839  mFullDescription += tr( "<b>Current definition (%1):</b><br>%2" ).arg( deftype, deftip );
840 
841  setToolTip( mFullDescription );
842 
843 }
844 
845 void QgsPropertyOverrideButton::setActivePrivate( bool active )
846 {
847  if ( mProperty.isActive() != active )
848  {
849  mProperty.setActive( active );
850  emit activated( mProperty.isActive() );
851  }
852 }
853 
854 void QgsPropertyOverrideButton::updateSiblingWidgets( bool state )
855 {
856  const auto constMSiblingWidgets = mSiblingWidgets;
857  for ( const SiblingWidget &sw : constMSiblingWidgets )
858  {
859  switch ( sw.mSiblingType )
860  {
861 
862  case SiblingCheckState:
863  {
864  // don't uncheck, only set to checked
865  if ( state )
866  {
867  QAbstractButton *btn = qobject_cast< QAbstractButton * >( sw.mWidgetPointer.data() );
868  if ( btn && btn->isCheckable() )
869  {
870  btn->setChecked( sw.mNatural ? state : !state );
871  }
872  else
873  {
874  QGroupBox *grpbx = qobject_cast< QGroupBox * >( sw.mWidgetPointer.data() );
875  if ( grpbx && grpbx->isCheckable() )
876  {
877  grpbx->setChecked( sw.mNatural ? state : !state );
878  }
879  }
880  }
881  break;
882  }
883 
884  case SiblingEnableState:
885  {
886  QLineEdit *le = qobject_cast< QLineEdit * >( sw.mWidgetPointer.data() );
887  if ( le )
888  le->setReadOnly( sw.mNatural ? !state : state );
889  else
890  sw.mWidgetPointer.data()->setEnabled( sw.mNatural ? state : !state );
891  break;
892  }
893 
894  case SiblingVisibility:
895  {
896  sw.mWidgetPointer.data()->setVisible( sw.mNatural ? state : !state );
897  break;
898  }
899 
900  case SiblingExpressionText:
901  {
902  QLineEdit *le = qobject_cast<QLineEdit *>( sw.mWidgetPointer.data() );
903  if ( le )
904  {
905  le->setText( mProperty.asExpression() );
906  }
907  else
908  {
909  QTextEdit *te = qobject_cast<QTextEdit *>( sw.mWidgetPointer.data() );
910  if ( te )
911  {
912  te->setText( mProperty.asExpression() );
913  }
914  }
915  break;
916  }
917 
918  case SiblingLinkedWidget:
919  {
920  if ( QgsColorButton *cb = qobject_cast< QgsColorButton * >( sw.mWidgetPointer.data() ) )
921  {
922  if ( state && mProperty.isProjectColor() )
923  {
924  QRegularExpression rx( QStringLiteral( "^project_color\\('(.*)'\\)$" ) );
925  QRegularExpressionMatch match = rx.match( mExpressionString );
926  if ( match.hasMatch() )
927  {
928  cb->linkToProjectColor( match.captured( 1 ) );
929  }
930  }
931  else
932  {
933  cb->linkToProjectColor( QString() );
934  }
935  }
936  break;
937  }
938  }
939  }
940 }
941 
942 
943 
945 {
946  if ( mProperty.isActive() != active )
947  {
948  mProperty.setActive( active );
949  emit changed();
950  emit activated( mProperty.isActive() );
951  }
952 }
953 
955 {
956  mExpressionContextGenerator = generator;
957 }
958 
960 {
961  for ( const SiblingWidget &sw : qgis::as_const( mSiblingWidgets ) )
962  {
963  if ( widget == sw.mWidgetPointer.data() && sw.mSiblingType == SiblingLinkedWidget )
964  return;
965  }
966  mSiblingWidgets.append( SiblingWidget( QPointer<QWidget>( widget ), SiblingLinkedWidget ) );
967 
968  if ( QgsColorButton *cb = qobject_cast< QgsColorButton * >( widget ) )
969  {
970  connect( cb, &QgsColorButton::unlinked, this, [ = ]
971  {
972  setActive( false );
973  updateGui();
974  } );
975  }
976 
977  updateSiblingWidgets( isActive() );
978 }
979 
980 void QgsPropertyOverrideButton::showHelp()
981 {
982  QgsHelp::openHelp( QStringLiteral( "introduction/general_tools.html#data-defined" ) );
983 }
QgsPropertyAssistantWidget::registerExpressionContextGenerator
void registerExpressionContextGenerator(QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
Definition: qgspropertyassistantwidget.cpp:140
QgsPropertyAssistantWidget
Shows a user-friendly assistant guiding users through the creation of QgsProperty overrides.
Definition: qgspropertyassistantwidget.h:116
QgsProperty::setTransformer
void setTransformer(QgsPropertyTransformer *transformer)
Sets an optional transformer to use for manipulating the calculated values for the property.
Definition: qgsproperty.cpp:795
qgscolorbutton.h
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:370
QgsProperty::isActive
bool isActive() const
Returns whether the property is currently active.
Definition: qgsproperty.cpp:266
QgsPropertyOverrideButton::registerExpressionWidget
void registerExpressionWidget(QWidget *widget)
Register a sibling widget (line edit, text edit) that will receive the property as an expression.
Definition: qgspropertyoverridebutton.cpp:256
QgsProperty
A store for object properties.
Definition: qgsproperty.h:232
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:626
QgsSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Definition: qgssettings.cpp:174
QgsAuxiliaryLayer
Class allowing to manage the auxiliary storage for a vector layer.
Definition: qgsauxiliarystorage.h:61
QgsPropertyOverrideButton::changed
void changed()
Emitted when property definition changes.
QgsPanelWidget::findParentPanel
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
Definition: qgspanelwidget.cpp:49
qgsexpression.h
QgsPropertyDefinition::DataTypeString
@ DataTypeString
Property requires a string value.
Definition: qgsproperty.h:93
QgsProperty::FieldBasedProperty
@ FieldBasedProperty
Field based property (QgsFieldBasedProperty)
Definition: qgsproperty.h:240
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:45
QgsNamedColorList
QList< QPair< QColor, QString > > QgsNamedColorList
List of colors paired with a friendly display name identifying the color.
Definition: qgscolorscheme.h:34
QgsVectorLayer::isAuxiliaryField
bool isAuxiliaryField(int index, int &srcIndex) const
Returns true if the field comes from the auxiliary layer, false otherwise.
Definition: qgsvectorlayer.cpp:3627
QgsAbstractPropertyCollection
Abstract base class for QgsPropertyCollection like objects.
Definition: qgspropertycollection.h:42
QgsPanelWidget::openPanel
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
Definition: qgspanelwidget.cpp:79
QgsProperty::asExpression
QString asExpression() const
Returns an expression string representing the state of the property, or an empty string if the proper...
Definition: qgsproperty.cpp:332
QgsPropertyDefinition::DataTypeBoolean
@ DataTypeBoolean
Property requires a boolean value.
Definition: qgsproperty.h:107
QgsApplication::colorSchemeRegistry
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application's color scheme registry, used for managing color schemes.
Definition: qgsapplication.cpp:2138
QgsPropertyDefinition::DataTypeNumeric
@ DataTypeNumeric
Property requires a numeric value.
Definition: qgsproperty.h:100
QgsProjectColorScheme
A color scheme which contains project specific colors set through project properties dialog.
Definition: qgscolorscheme.h:300
QgsColorButton::unlinked
void unlinked()
Emitted when the color is unlinked, e.g.
QgsVectorLayer::auxiliaryLayer
QgsAuxiliaryLayer * auxiliaryLayer()
Returns the current auxiliary layer.
Definition: qgsvectorlayer.cpp:5293
QgsPropertyOverrideButton::createAuxiliaryField
void createAuxiliaryField()
Emitted when creating a new auxiliary field.
QgsPropertyOverrideButton::propertyKey
int propertyKey() const
Returns the property key linked to the button.
Definition: qgspropertyoverridebutton.h:123
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QgsProperty::isProjectColor
bool isProjectColor() const
Returns true if the property is set to a linked project color.
Definition: qgsproperty.cpp:443
QgsPropertyOverrideButton::registerEnabledWidget
void registerEnabledWidget(QWidget *widget, bool natural=true)
Register a sibling widget that gets enabled when the property is active, and disabled when the proper...
Definition: qgspropertyoverridebutton.cpp:232
QgsPropertyOverrideButton::setActive
void setActive(bool active)
Set whether the current property override definition is to be used.
Definition: qgspropertyoverridebutton.cpp:944
QgsPropertyOverrideButton::active
bool active
Definition: qgspropertyoverridebutton.h:54
FALLTHROUGH
#define FALLTHROUGH
Definition: qgis.h:828
QgsProperty::propertyType
Type propertyType() const
Returns the property type.
Definition: qgsproperty.cpp:261
QgsProperty::transformer
const QgsPropertyTransformer * transformer() const
Returns the existing transformer used for manipulating the calculated values for the property,...
Definition: qgsproperty.cpp:801
QgsPropertyOverrideButton::mouseReleaseEvent
void mouseReleaseEvent(QMouseEvent *event) override
Definition: qgspropertyoverridebutton.cpp:269
QgsPanelWidget::dockMode
bool dockMode()
Returns the dock mode state.
Definition: qgspanelwidget.h:83
QgsProperty::value
QVariant value(const QgsExpressionContext &context, const QVariant &defaultValue=QVariant(), bool *ok=nullptr) const
Calculates the current value of the property, including any transforms which are set for the property...
Definition: qgsproperty.cpp:519
QgsPropertyOverrideButton::setToProperty
void setToProperty(const QgsProperty &property)
Sets the widget to reflect the current state of a QgsProperty.
Definition: qgspropertyoverridebutton.cpp:286
QgsProperty::setActive
void setActive(bool active)
Sets whether the property is currently active.
Definition: qgsproperty.cpp:271
QgsGuiUtils::iconSize
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
Definition: qgsguiutils.cpp:250
QgsPropertyOverrideButton::registerLinkedWidget
void registerLinkedWidget(QWidget *widget)
Registers a widget which is linked to this button.
Definition: qgspropertyoverridebutton.cpp:959
QgsExpressionContext::isReadOnly
bool isReadOnly(const QString &name) const
Returns whether a variable is read only, and should not be modifiable by users.
Definition: qgsexpressioncontext.cpp:431
QgsPropertyAssistantWidget::setSymbol
void setSymbol(std::shared_ptr< QgsSymbol > symbol)
Sets a symbol which can be used for previews inside the widget.
Definition: qgspropertyassistantwidget.h:150
qgsauxiliarystorage.h
qgsapplication.h
QgsPropertyDefinition::dataType
DataType dataType() const
Returns the allowable field/value data type for the property.
Definition: qgsproperty.h:189
QgsVectorLayer::fields
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Definition: qgsvectorlayer.cpp:3283
QgsProperty::convertToTransformer
bool convertToTransformer()
Attempts to convert an existing expression based property to a base expression with corresponding tra...
Definition: qgsproperty.cpp:806
QgsPropertyOverrideButton::activated
void activated(bool isActive)
Emitted when the activated status of the widget changes.
QgsProperty::ExpressionBasedProperty
@ ExpressionBasedProperty
Expression based property (QgsExpressionBasedProperty)
Definition: qgsproperty.h:241
QgsPropertiesDefinition
QMap< int, QgsPropertyDefinition > QgsPropertiesDefinition
Definition of available properties.
Definition: qgspropertycollection.h:29
QgsPropertyDefinition::helpText
QString helpText() const
Helper text for using the property, including a description of the valid values for the property.
Definition: qgsproperty.h:179
QgsPanelWidget
Base class for any widget that can be shown as a inline panel.
Definition: qgspanelwidget.h:30
QgsProperty::setField
void setField(const QString &field)
Sets the field name the property references.
Definition: qgsproperty.cpp:292
QgsPropertyOverrideButton::updateFieldLists
void updateFieldLists()
Updates list of fields.
Definition: qgspropertyoverridebutton.cpp:152
QgsPropertyDefinition::ColorWithAlpha
@ ColorWithAlpha
Color with alpha channel.
Definition: qgsproperty.h:65
QgsPanelWidget::panelAccepted
void panelAccepted(QgsPanelWidget *panel)
Emitted when the panel is accepted by the user.
QgsAbstractPropertyCollection::property
virtual QgsProperty property(int key) const =0
Returns a matching property from the collection, if one exists.
QgsPropertyOverrideButton::setVectorLayer
void setVectorLayer(const QgsVectorLayer *layer)
Sets the vector layer associated with the button.
Definition: qgspropertyoverridebutton.cpp:215
QgsExpressionBuilderDialog
A generic dialog for building expression strings.
Definition: qgsexpressionbuilderdialog.h:31
QgsColorButton::createMenuIcon
static QPixmap createMenuIcon(const QColor &color, bool showChecks=true)
Creates an icon for displaying a color in a drop-down menu.
Definition: qgscolorbutton.cpp:447
QgsPanelWidget::acceptPanel
void acceptPanel()
Accept the panel.
Definition: qgspanelwidget.cpp:107
qgsmessageviewer.h
QgsExpressionContext::variableNames
QStringList variableNames() const
Returns a list of variables names set by all scopes in the context.
Definition: qgsexpressioncontext.cpp:403
QgsPanelWidget::widgetChanged
void widgetChanged()
Emitted when the widget state changes.
QgsPropertyOverrideButton::toProperty
QgsProperty toProperty() const
Returns a QgsProperty object encapsulating the current state of the widget.
Definition: qgspropertyoverridebutton.cpp:210
QgsPropertyDefinition
Definition for a property.
Definition: qgsproperty.h:48
QgsProperty::setExpressionString
void setExpressionString(const QString &expression)
Sets the expression to use for the property value.
Definition: qgsproperty.cpp:313
QgsExpressionContextGenerator::createExpressionContext
virtual QgsExpressionContext createExpressionContext() const =0
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QgsPanelWidget::panelTitle
QString panelTitle()
The title of the panel.
Definition: qgspanelwidget.h:50
QgsPropertyDefinition::standardTemplate
StandardPropertyTemplate standardTemplate() const
Returns the property's standard template, if applicable.
Definition: qgsproperty.h:195
QgsSettings::setValue
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Definition: qgssettings.cpp:289
QgsPropertyOverrideButton::init
void init(int propertyKey, const QgsProperty &property, const QgsPropertiesDefinition &definitions, const QgsVectorLayer *layer=nullptr, bool auxiliaryStorageEnabled=false)
Initialize a newly constructed property button (useful if button was included in a UI layout).
Definition: qgspropertyoverridebutton.cpp:96
QgsApplication
Extends QApplication to provide access to QGIS specific resources such as theme paths,...
Definition: qgsapplication.h:83
QgsPropertyAssistantWidget::updateProperty
void updateProperty(QgsProperty &property)
Updates a property in place to corresponding to the current settings shown in the widget.
Definition: qgspropertyassistantwidget.cpp:146
qgsvectorlayer.h
QgsPropertyOverrideButton::QgsPropertyOverrideButton
QgsPropertyOverrideButton(QWidget *parent=nullptr, const QgsVectorLayer *layer=nullptr)
Constructor for QgsPropertyOverrideButton.
Definition: qgspropertyoverridebutton.cpp:37
QgsPropertyOverrideButton::isActive
bool isActive() const
Returns true if the button has an active property.
Definition: qgspropertyoverridebutton.h:128
QgsHelp::openHelp
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:36
QgsColorSchemeRegistry::schemes
QList< QgsColorScheme * > schemes() const
Returns all color schemes in the registry.
Definition: qgscolorschemeregistry.cpp:88
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
QgsPropertyOverrideButton::registerExpressionContextGenerator
void registerExpressionContextGenerator(QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
Definition: qgspropertyoverridebutton.cpp:954
QgsPropertyDefinition::name
QString name() const
Returns the name of the property.
Definition: qgsproperty.h:140
QgsProperty::field
QString field() const
Returns the current field name the property references.
Definition: qgsproperty.cpp:300
QgsColorButton
A cross platform button subclass for selecting colors.
Definition: qgscolorbutton.h:36
qgscolorschemeregistry.h
QgsProperty::setStaticValue
void setStaticValue(const QVariant &value)
Sets the static value for the property.
Definition: qgsproperty.cpp:277
QgsProjectColorScheme::fetchColors
QgsNamedColorList fetchColors(const QString &context=QString(), const QColor &baseColor=QColor()) override
Gets a list of colors from the scheme.
Definition: qgscolorscheme.cpp:192
QgsPropertyOverrideButton::registerCheckedWidget
void registerCheckedWidget(QWidget *widget, bool natural=true)
Register a sibling widget that gets checked when the property is active.
Definition: qgspropertyoverridebutton.cpp:220
qgspropertyassistantwidget.h
QgsPropertyDefinition::supportsAssistant
bool supportsAssistant() const
Returns true if the property is of a type which is compatible with property override assistants.
Definition: qgsproperty.cpp:189
QgsProperty::staticValue
QVariant staticValue() const
Returns the current static value for the property.
Definition: qgsproperty.cpp:284
qgsguiutils.h
QgsGuiUtils::scaleIconSize
int scaleIconSize(int standardSize)
Scales an icon size to compensate for display pixel density, making the icon size hi-dpi friendly,...
Definition: qgsguiutils.cpp:245
qgspanelwidget.h
QgsExpression
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:105
QgsProperty::StaticProperty
@ StaticProperty
Static property (QgsStaticProperty)
Definition: qgsproperty.h:239
QgsExpressionContextGenerator
Abstract interface for generating an expression context.
Definition: qgsexpressioncontextgenerator.h:37
qgspropertyoverridebutton.h
QgsPropertyDefinition::ColorNoAlpha
@ ColorNoAlpha
Color with no alpha channel.
Definition: qgsproperty.h:66
QgsFields::indexFromName
int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:202
QgsProperty::InvalidProperty
@ InvalidProperty
Invalid (not set) property.
Definition: qgsproperty.h:238
QgsPropertyOverrideButton::registerVisibleWidget
void registerVisibleWidget(QWidget *widget, bool natural=true)
Register a sibling widget that gets visible when the property is active, and hidden when the property...
Definition: qgspropertyoverridebutton.cpp:244
qgsexpressionbuilderdialog.h
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50