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