QGIS API Documentation  2.99.0-Master (e077efd)
qgsdatadefinedbutton.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsdatadefinedbutton.cpp - Data defined selector button
3  --------------------------------------
4  Date : 27-April-2013
5  Copyright : (C) 2013 by Larry Shaffer
6  Email : larrys at dakcarto 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 
16 #include "qgsdatadefinedbutton.h"
17 
18 #include <qgsapplication.h>
19 #include <qgsdatadefined.h>
21 #include <qgsexpression.h>
22 #include <qgsmessageviewer.h>
23 #include <qgsvectorlayer.h>
24 
25 #include <QClipboard>
26 #include <QMenu>
27 #include <QMouseEvent>
28 #include <QPointer>
29 #include <QGroupBox>
30 
32  const QgsVectorLayer* vl,
33  const QgsDataDefined* datadefined,
34  DataTypes datatypes,
35  const QString& description )
36  : QToolButton( parent )
37  , mExpressionContextGenerator( nullptr )
38 {
39  // set up static icons
40  if ( mIconDataDefine.isNull() )
41  {
42  mIconDataDefine = QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefine.svg" ) );
43  mIconDataDefineOn = QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineOn.svg" ) );
44  mIconDataDefineError = QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineError.svg" ) );
45  mIconDataDefineExpression = QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineExpression.svg" ) );
46  mIconDataDefineExpressionOn = QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineExpressionOn.svg" ) );
47  mIconDataDefineExpressionError = QgsApplication::getThemeIcon( QStringLiteral( "/mIconDataDefineExpressionError.svg" ) );
48  }
49 
50  setFocusPolicy( Qt::StrongFocus );
51 
52  // set default tool button icon properties
53  setFixedSize( 30, 26 );
54  setStyleSheet( QStringLiteral( "QToolButton{ background: none; border: 1px solid rgba(0, 0, 0, 0%);} QToolButton:focus { border: 1px solid palette(highlight); }" ) );
55  setIconSize( QSize( 24, 24 ) );
56  setPopupMode( QToolButton::InstantPopup );
57 
58  mDefineMenu = new QMenu( this );
59  connect( mDefineMenu, SIGNAL( aboutToShow() ), this, SLOT( aboutToShowMenu() ) );
60  connect( mDefineMenu, SIGNAL( triggered( QAction* ) ), this, SLOT( menuActionTriggered( QAction* ) ) );
61  setMenu( mDefineMenu );
62 
63  mFieldsMenu = new QMenu( this );
64  mActionDataTypes = new QAction( this );
65  // list fields and types in submenu, since there may be many
66  mActionDataTypes->setMenu( mFieldsMenu );
67 
68  mActionVariables = new QAction( tr( "Variable" ), this );
69  mVariablesMenu = new QMenu( this );
70  mActionVariables->setMenu( mVariablesMenu );
71 
72  mActionActive = new QAction( this );
73  QFont f = mActionActive->font();
74  f.setBold( true );
75  mActionActive->setFont( f );
76 
77  mActionDescription = new QAction( tr( "Description..." ), this );
78 
79  mActionExpDialog = new QAction( tr( "Edit..." ), this );
80  mActionExpression = nullptr;
81  mActionPasteExpr = new QAction( tr( "Paste" ), this );
82  mActionCopyExpr = new QAction( tr( "Copy" ), this );
83  mActionClearExpr = new QAction( tr( "Clear" ), this );
84  mActionAssistant = new QAction( tr( "Assistant..." ), this );
85  QFont assistantFont = mActionAssistant->font();
86  assistantFont.setBold( true );
87  mActionAssistant->setFont( assistantFont );
88  mDefineMenu->addAction( mActionAssistant );
89 
90  // set up sibling widget connections
91  connect( this, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( disableEnabledWidgets( bool ) ) );
92  connect( this, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( checkCheckedWidgets( bool ) ) );
93 
94  init( vl, datadefined, datatypes, description );
95 }
96 
98 {
99  mEnabledWidgets.clear();
100  mCheckedWidgets.clear();
101 }
102 
103 void QgsDataDefinedButton::updateFieldLists()
104 {
105  mFieldNameList.clear();
106  mFieldTypeList.clear();
107 
108  if ( mVectorLayer )
109  {
110  // store just a list of fields of unknown type or those that match the expected type
111  Q_FOREACH ( const QgsField& f, mVectorLayer->fields() )
112  {
113  bool fieldMatch = false;
114  // NOTE: these are the only QVariant enums supported at this time (see QgsField)
115  QString fieldType;
116  switch ( f.type() )
117  {
118  case QVariant::String:
119  fieldMatch = mDataTypes.testFlag( String );
120  fieldType = tr( "string" );
121  break;
122  case QVariant::Int:
123  fieldMatch = mDataTypes.testFlag( Int ) || mDataTypes.testFlag( Double );
124  fieldType = tr( "integer" );
125  break;
126  case QVariant::Double:
127  fieldMatch = mDataTypes.testFlag( Double );
128  fieldType = tr( "double" );
129  break;
130  case QVariant::Invalid:
131  default:
132  fieldMatch = true; // field type is unknown
133  fieldType = tr( "unknown type" );
134  }
135  if ( fieldMatch || mDataTypes.testFlag( AnyType ) )
136  {
137  mFieldNameList << f.name();
138  mFieldTypeList << fieldType;
139  }
140  }
141  }
142 }
143 
145  const QgsDataDefined* datadefined,
146  DataTypes datatypes,
147  const QString& description )
148 {
149  mVectorLayer = vl;
150  // construct default property if none or incorrect passed in
151  if ( !datadefined )
152  {
153  mProperty.insert( QStringLiteral( "active" ), QStringLiteral( "0" ) );
154  mProperty.insert( QStringLiteral( "useexpr" ), QStringLiteral( "0" ) );
155  mProperty.insert( QStringLiteral( "expression" ), QString() );
156  mProperty.insert( QStringLiteral( "field" ), QString() );
157  }
158  else
159  {
160  mProperty.insert( QStringLiteral( "active" ), datadefined->isActive() ? "1" : "0" );
161  mProperty.insert( QStringLiteral( "useexpr" ), datadefined->useExpression() ? "1" : "0" );
162  mProperty.insert( QStringLiteral( "expression" ), datadefined->expressionString() );
163  mProperty.insert( QStringLiteral( "field" ), datadefined->field() );
164  }
165 
166  mDataTypes = datatypes;
167  mFieldNameList.clear();
168  mFieldTypeList.clear();
169 
170  mInputDescription = description;
171  mFullDescription.clear();
172  mUsageInfo.clear();
173  mCurrentDefinition.clear();
174 
175  // set up data types string
176  mDataTypesString.clear();
177 
178  QStringList ts;
179  if ( mDataTypes.testFlag( String ) )
180  {
181  ts << tr( "string" );
182  }
183  if ( mDataTypes.testFlag( Int ) )
184  {
185  ts << tr( "int" );
186  }
187  if ( mDataTypes.testFlag( Double ) )
188  {
189  ts << tr( "double" );
190  }
191 
192  if ( !ts.isEmpty() )
193  {
194  mDataTypesString = ts.join( QStringLiteral( ", " ) );
195  mActionDataTypes->setText( tr( "Field type: " ) + mDataTypesString );
196  }
197 
198  updateFieldLists();
199  updateGui();
200 }
201 
202 
204 {
205  if ( !dd )
206  return;
207 
208  dd->setActive( isActive() );
210  dd->setField( getField() );
212 }
213 
215 {
216  QgsDataDefined dd;
217  updateDataDefined( &dd );
218  return dd;
219 }
220 
222 {
223  mVectorLayer = layer;
224 }
225 
226 void QgsDataDefinedButton::mouseReleaseEvent( QMouseEvent *event )
227 {
228  // Ctrl-click to toggle activated state
229  if (( event->modifiers() & ( Qt::ControlModifier ) )
230  || event->button() == Qt::RightButton )
231  {
232  setActive( !isActive() );
233  updateGui();
234  event->ignore();
235  return;
236  }
237 
238  // pass to default behaviour
239  QToolButton::mousePressEvent( event );
240 }
241 
242 void QgsDataDefinedButton::aboutToShowMenu()
243 {
244  mDefineMenu->clear();
245  // update fields so that changes made to layer's fields are reflected
246  updateFieldLists();
247 
248  bool hasExp = !getExpression().isEmpty();
249  bool hasField = !getField().isEmpty();
250  QString ddTitle = tr( "Data defined override" );
251 
252  QAction* ddTitleAct = mDefineMenu->addAction( ddTitle );
253  QFont titlefont = ddTitleAct->font();
254  titlefont.setItalic( true );
255  ddTitleAct->setFont( titlefont );
256  ddTitleAct->setEnabled( false );
257 
258  bool addActiveAction = false;
259  if ( useExpression() && hasExp )
260  {
261  QgsExpression exp( getExpression() );
262  // whether expression is parse-able
263  addActiveAction = !exp.hasParserError();
264  }
265  else if ( !useExpression() && hasField )
266  {
267  // whether field exists
268  addActiveAction = mFieldNameList.contains( getField() );
269  }
270 
271  if ( addActiveAction )
272  {
273  ddTitleAct->setText( ddTitle + " (" + ( useExpression() ? tr( "expression" ) : tr( "field" ) ) + ')' );
274  mDefineMenu->addAction( mActionActive );
275  mActionActive->setText( isActive() ? tr( "Deactivate" ) : tr( "Activate" ) );
276  mActionActive->setData( QVariant( isActive() ? false : true ) );
277  }
278 
279  if ( !mFullDescription.isEmpty() )
280  {
281  mDefineMenu->addAction( mActionDescription );
282  }
283 
284  mDefineMenu->addSeparator();
285 
286  bool fieldActive = false;
287  if ( !mDataTypesString.isEmpty() )
288  {
289  QAction* fieldTitleAct = mDefineMenu->addAction( tr( "Attribute field" ) );
290  fieldTitleAct->setFont( titlefont );
291  fieldTitleAct->setEnabled( false );
292 
293  mDefineMenu->addAction( mActionDataTypes );
294 
295  mFieldsMenu->clear();
296 
297  if ( !mFieldNameList.isEmpty() )
298  {
299 
300  for ( int j = 0; j < mFieldNameList.count(); ++j )
301  {
302  QString fldname = mFieldNameList.at( j );
303  QAction* act = mFieldsMenu->addAction( fldname + " (" + mFieldTypeList.at( j ) + ')' );
304  act->setData( QVariant( fldname ) );
305  if ( getField() == fldname )
306  {
307  act->setCheckable( true );
308  act->setChecked( !useExpression() );
309  fieldActive = !useExpression();
310  }
311  }
312  }
313  else
314  {
315  QAction* act = mFieldsMenu->addAction( tr( "No matching field types found" ) );
316  act->setEnabled( false );
317  }
318 
319  mDefineMenu->addSeparator();
320  }
321 
322  mFieldsMenu->menuAction()->setCheckable( true );
323  mFieldsMenu->menuAction()->setChecked( fieldActive );
324 
325  QAction* exprTitleAct = mDefineMenu->addAction( tr( "Expression" ) );
326  exprTitleAct->setFont( titlefont );
327  exprTitleAct->setEnabled( false );
328 
329  mVariablesMenu->clear();
330  bool variableActive = false;
331  if ( mExpressionContextGenerator )
332  {
333  QgsExpressionContext context = mExpressionContextGenerator->createExpressionContext();
334  QStringList variables = context.variableNames();
335  Q_FOREACH ( const QString& variable, variables )
336  {
337  if ( context.isReadOnly( variable ) ) //only want to show user-set variables
338  continue;
339  if ( variable.startsWith( '_' ) ) //no hidden variables
340  continue;
341 
342  QAction* act = mVariablesMenu->addAction( variable );
343  act->setData( QVariant( variable ) );
344 
345  if ( useExpression() && hasExp && getExpression() == '@' + variable )
346  {
347  act->setCheckable( true );
348  act->setChecked( true );
349  variableActive = true;
350  }
351  }
352  }
353 
354  if ( mVariablesMenu->actions().isEmpty() )
355  {
356  QAction* act = mVariablesMenu->addAction( tr( "No variables set" ) );
357  act->setEnabled( false );
358  }
359 
360  mDefineMenu->addAction( mActionVariables );
361  mVariablesMenu->menuAction()->setCheckable( true );
362  mVariablesMenu->menuAction()->setChecked( variableActive );
363 
364  if ( hasExp )
365  {
366  QString expString = getExpression();
367  if ( expString.length() > 35 )
368  {
369  expString.truncate( 35 );
370  expString.append( "..." );
371  }
372 
373  expString.prepend( tr( "Current: " ) );
374 
375  if ( !mActionExpression )
376  {
377  mActionExpression = new QAction( expString, this );
378  mActionExpression->setCheckable( true );
379  }
380  else
381  {
382  mActionExpression->setText( expString );
383  }
384  mDefineMenu->addAction( mActionExpression );
385  mActionExpression->setChecked( useExpression() && !variableActive );
386 
387  mDefineMenu->addAction( mActionExpDialog );
388  mDefineMenu->addAction( mActionCopyExpr );
389  mDefineMenu->addAction( mActionPasteExpr );
390  mDefineMenu->addAction( mActionClearExpr );
391  }
392  else
393  {
394  mDefineMenu->addAction( mActionExpDialog );
395  mDefineMenu->addAction( mActionPasteExpr );
396  }
397 
398  if ( mAssistant.data() )
399  {
400  mDefineMenu->addSeparator();
401  mDefineMenu->addAction( mActionAssistant );
402  }
403 }
404 
405 void QgsDataDefinedButton::menuActionTriggered( QAction* action )
406 {
407  if ( action == mActionActive )
408  {
409  setActive( mActionActive->data().toBool() );
410  updateGui();
411  }
412  else if ( action == mActionDescription )
413  {
414  showDescriptionDialog();
415  }
416  else if ( action == mActionExpDialog )
417  {
418  showExpressionDialog();
419  }
420  else if ( action == mActionExpression )
421  {
422  setUseExpression( true );
423  setActive( true );
424  updateGui();
425  }
426  else if ( action == mActionCopyExpr )
427  {
428  QApplication::clipboard()->setText( getExpression() );
429  }
430  else if ( action == mActionPasteExpr )
431  {
432  QString exprString = QApplication::clipboard()->text();
433  if ( !exprString.isEmpty() )
434  {
435  setExpression( exprString );
436  setUseExpression( true );
437  setActive( true );
438  updateGui();
439  }
440  }
441  else if ( action == mActionClearExpr )
442  {
443  // only deactivate if defined expression is being used
444  if ( isActive() && useExpression() )
445  {
446  setUseExpression( false );
447  setActive( false );
448  }
449  setExpression( QString() );
450  updateGui();
451  }
452  else if ( action == mActionAssistant )
453  {
454  showAssistant();
455  }
456  else if ( mFieldsMenu->actions().contains( action ) ) // a field name clicked
457  {
458  if ( action->isEnabled() )
459  {
460  if ( getField() != action->text() )
461  {
462  setField( action->data().toString() );
463  }
464  setUseExpression( false );
465  setActive( true );
466  updateGui();
467  }
468  }
469  else if ( mVariablesMenu->actions().contains( action ) ) // a variable name clicked
470  {
471  if ( getExpression() != action->text().prepend( "@" ) )
472  {
473  setExpression( action->data().toString().prepend( "@" ) );
474  }
475  setUseExpression( true );
476  setActive( true );
477  updateGui();
478  }
479 }
480 
481 void QgsDataDefinedButton::showDescriptionDialog()
482 {
483  QgsMessageViewer* mv = new QgsMessageViewer( this );
484  mv->setWindowTitle( tr( "Data definition description" ) );
485  mv->setMessageAsHtml( mFullDescription );
486  mv->exec();
487 }
488 
489 void QgsDataDefinedButton::showAssistant()
490 {
491  if ( !mAssistant.data() )
492  return;
493 
494  if ( mAssistant->exec() == QDialog::Accepted )
495  {
496  QgsDataDefined dd = mAssistant->dataDefined();
498  setActive( dd.isActive() );
499  if ( dd.isActive() && dd.useExpression() )
501  else if ( dd.isActive() )
502  setField( dd.field() );
503  updateGui();
504  }
505  activateWindow(); // reset focus to parent window
506 }
507 
508 void QgsDataDefinedButton::showExpressionDialog()
509 {
510  QgsExpressionContext context = mExpressionContextGenerator ? mExpressionContextGenerator->createExpressionContext() : QgsExpressionContext();
511 
512  QgsExpressionBuilderDialog d( const_cast<QgsVectorLayer*>( mVectorLayer ), getExpression(), this, QStringLiteral( "generic" ), context );
513  if ( d.exec() == QDialog::Accepted )
514  {
515  QString newExp = d.expressionText();
516  setExpression( d.expressionText().trimmed() );
517  bool hasExp = !newExp.isEmpty();
518 
519  setUseExpression( hasExp );
520  setActive( hasExp );
521  updateGui();
522  }
523  activateWindow(); // reset focus to parent window
524 }
525 
526 void QgsDataDefinedButton::updateGui()
527 {
528  QString oldDef = mCurrentDefinition;
529  QString newDef( QLatin1String( "" ) );
530  bool hasExp = !getExpression().isEmpty();
531  bool hasField = !getField().isEmpty();
532 
533  if ( useExpression() && !hasExp )
534  {
535  setActive( false );
536  setUseExpression( false );
537  }
538  else if ( !useExpression() && !hasField )
539  {
540  setActive( false );
541  }
542 
543  QIcon icon = mIconDataDefine;
544  QString deftip = tr( "undefined" );
545  if ( useExpression() && hasExp )
546  {
547  icon = isActive() ? mIconDataDefineExpressionOn : mIconDataDefineExpression;
548  newDef = deftip = getExpression();
549 
550  QgsExpression exp( getExpression() );
551  if ( exp.hasParserError() )
552  {
553  setActive( false );
554  icon = mIconDataDefineExpressionError;
555  deftip = tr( "Parse error: %1" ).arg( exp.parserErrorString() );
556  newDef = QLatin1String( "" );
557  }
558  }
559  else if ( !useExpression() && hasField )
560  {
561  icon = isActive() ? mIconDataDefineOn : mIconDataDefine;
562  newDef = deftip = getField();
563 
564  if ( !mFieldNameList.contains( getField() ) )
565  {
566  setActive( false );
567  icon = mIconDataDefineError;
568  deftip = tr( "'%1' field missing" ).arg( getField() );
569  newDef = QLatin1String( "" );
570  }
571  }
572 
573  setIcon( icon );
574 
575  // update and emit current definition
576  if ( newDef != oldDef )
577  {
578  mCurrentDefinition = newDef;
579  emit dataDefinedChanged( mCurrentDefinition );
580  }
581 
582  // build full description for tool tip and popup dialog
583  mFullDescription = tr( "<b><u>Data defined override</u></b><br>" );
584 
585  mFullDescription += tr( "<b>Active: </b>%1&nbsp;&nbsp;&nbsp;<i>(ctrl|right-click toggles)</i><br>" ).arg( isActive() ? tr( "yes" ) : tr( "no" ) );
586 
587  if ( !mUsageInfo.isEmpty() )
588  {
589  mFullDescription += tr( "<b>Usage:</b><br>%1<br>" ).arg( mUsageInfo );
590  }
591 
592  if ( !mInputDescription.isEmpty() )
593  {
594  mFullDescription += tr( "<b>Expected input:</b><br>%1<br>" ).arg( mInputDescription );
595  }
596 
597  if ( !mDataTypesString.isEmpty() )
598  {
599  mFullDescription += tr( "<b>Valid input types:</b><br>%1<br>" ).arg( mDataTypesString );
600  }
601 
602  QString deftype( QLatin1String( "" ) );
603  if ( deftip != tr( "undefined" ) )
604  {
605  deftype = QStringLiteral( " (%1)" ).arg( useExpression() ? tr( "expression" ) : tr( "field" ) );
606  }
607 
608  // truncate long expressions, or tool tip may be too wide for screen
609  if ( deftip.length() > 75 )
610  {
611  deftip.truncate( 75 );
612  deftip.append( "..." );
613  }
614 
615  mFullDescription += tr( "<b>Current definition %1:</b><br>%2" ).arg( deftype, deftip );
616 
617  setToolTip( mFullDescription );
618 
619 }
620 
622 {
623  if ( isActive() != active )
624  {
625  mProperty.insert( QStringLiteral( "active" ), active ? "1" : "0" );
626  emit dataDefinedActivated( active );
627  }
628 }
629 
630 void QgsDataDefinedButton::registerEnabledWidgets( const QList<QWidget*>& wdgts )
631 {
632  for ( int i = 0; i < wdgts.size(); ++i )
633  {
634  registerEnabledWidget( wdgts.at( i ) );
635  }
636 }
637 
639 {
640  QPointer<QWidget> wdgtP( wdgt );
641  if ( !mEnabledWidgets.contains( wdgtP ) )
642  {
643  mEnabledWidgets.append( wdgtP );
644  }
645 }
646 
648 {
649  QList<QWidget*> wdgtList;
650  wdgtList.reserve( mEnabledWidgets.size() );
651  for ( int i = 0; i < mEnabledWidgets.size(); ++i )
652  {
653  wdgtList << mEnabledWidgets.at( i );
654  }
655  return wdgtList;
656 }
657 
659 {
660  for ( int i = 0; i < mEnabledWidgets.size(); ++i )
661  {
662  mEnabledWidgets.at( i )->setDisabled( disable );
663  }
664 }
665 
666 void QgsDataDefinedButton::registerCheckedWidgets( const QList<QWidget*>& wdgts )
667 {
668  for ( int i = 0; i < wdgts.size(); ++i )
669  {
670  registerCheckedWidget( wdgts.at( i ) );
671  }
672 }
673 
675 {
676  QPointer<QWidget> wdgtP( wdgt );
677  if ( !mCheckedWidgets.contains( wdgtP ) )
678  {
679  mCheckedWidgets.append( wdgtP );
680  }
681 }
682 
684 {
685  QList<QWidget*> wdgtList;
686  wdgtList.reserve( mCheckedWidgets.size() );
687  for ( int i = 0; i < mCheckedWidgets.size(); ++i )
688  {
689  wdgtList << mCheckedWidgets.at( i );
690  }
691  return wdgtList;
692 }
693 
695 {
696  mExpressionContextGenerator = generator;
697 }
698 
700 {
701  mActionAssistant->setText( title.isEmpty() ? tr( "Assistant..." ) : title );
702  mAssistant.reset( assistant );
703  mAssistant.data()->setParent( this, Qt::Dialog );
704 }
705 
707 {
708  return mAssistant.data();
709 }
710 
712 {
713  // don't uncheck, only set to checked
714  if ( !check )
715  {
716  return;
717  }
718  for ( int i = 0; i < mCheckedWidgets.size(); ++i )
719  {
720  QAbstractButton *btn = qobject_cast< QAbstractButton * >( mCheckedWidgets.at( i ) );
721  if ( btn && btn->isCheckable() )
722  {
723  btn->setChecked( true );
724  continue;
725  }
726  QGroupBox *grpbx = qobject_cast< QGroupBox * >( mCheckedWidgets.at( i ) );
727  if ( grpbx && grpbx->isCheckable() )
728  {
729  grpbx->setChecked( true );
730  }
731  }
732 }
733 
735 {
736  // just something to reduce translation redundancy
737  return tr( "string " );
738 }
739 
741 {
742  return tr( "single character" );
743 }
744 
746 {
747  return tr( "bool [<b>1</b>=True|<b>0</b>=False]" );
748 }
749 
751 {
752  return tr( "string of variable length" );
753 }
754 
756 {
757  return tr( "int [&lt;= 0 =&gt;]" );
758 }
759 
761 {
762  return tr( "int [&gt;= 0]" );
763 }
764 
766 {
767  return tr( "int [&gt;= 1]" );
768 }
769 
771 {
772  return tr( "double [&lt;= 0.0 =&gt;]" );
773 }
774 
776 {
777  return tr( "double [&gt;= 0.0]" );
778 }
779 
781 {
782  return tr( "double [0.0-1.0]" );
783 }
784 
786 {
787  return tr( "double coord [<b>X,Y</b>] as &lt;= 0.0 =&gt;" );
788 }
789 
791 {
792  return tr( "double [-180.0 - 180.0]" );
793 }
794 
796 {
797  return tr( "int [0-100]" );
798 }
799 
801 {
802  return trString() + "[<b>MM</b>|<b>MapUnit</b>]";
803 }
804 
806 {
807  return trString() + "[<b>MM</b>|<b>MapUnit</b>|<b>Percent</b>]";
808 }
809 
811 {
812  return tr( "string [<b>r,g,b</b>] as int 0-255" );
813 }
814 
816 {
817  return tr( "string [<b>r,g,b,a</b>] as int 0-255" );
818 }
819 
821 {
822  return trString() + "[<b>Left</b>|<b>Center</b>|<b>Right</b>]";
823 }
824 
826 {
827  return trString() + "[<b>Bottom</b>|<b>Middle</b>|<b>Top</b>]";
828 }
829 
831 {
832  return trString() + "[<b>bevel</b>|<b>miter</b>|<b>round</b>]";
833 }
834 
836 {
837  return trString() + QStringLiteral( "[<b>Normal</b>|<b>Lighten</b>|<b>Screen</b>|<b>Dodge</b>|<br>"
838  "<b>Addition</b>|<b>Darken</b>|<b>Multiply</b>|<b>Burn</b>|<b>Overlay</b>|<br>"
839  "<b>SoftLight</b>|<b>HardLight</b>|<b>Difference</b>|<b>Subtract</b>]" );
840 }
841 
843 {
844  return trString() + QStringLiteral( "[<b>filepath</b>] as<br>"
845  "<b>''</b>=empty|absolute|search-paths-relative|<br>"
846  "project-relative|URL" );
847 }
848 
850 {
851  return tr( "string [<b>filepath</b>]" );
852 }
853 
855 {
856  return trString() + QStringLiteral( "[<b>A5</b>|<b>A4</b>|<b>A3</b>|<b>A2</b>|<b>A1</b>|<b>A0</b>"
857  "<b>B5</b>|<b>B4</b>|<b>B3</b>|<b>B2</b>|<b>B1</b>|<b>B0</b>"
858  "<b>Legal</b>|<b>Ansi A</b>|<b>Ansi B</b>|<b>Ansi C</b>|<b>Ansi D</b>|<b>Ansi E</b>"
859  "<b>Arch A</b>|<b>Arch B</b>|<b>Arch C</b>|<b>Arch D</b>|<b>Arch E</b>|<b>Arch E1</b>]"
860  );
861 }
862 
864 {
865  return trString() + QStringLiteral( "[<b>portrait</b>|<b>landscape</b>]" );
866 }
867 
869 {
870  return trString() + QStringLiteral( "[<b>left</b>|<b>center</b>|<b>right</b>]" );
871 }
872 
874 {
875  return trString() + QStringLiteral( "[<b>top</b>|<b>center</b>|<b>bottom</b>]" );
876 }
877 
879 {
880  return trString() + QStringLiteral( "[<b>linear</b>|<b>radial</b>|<b>conical</b>]" );
881 }
882 
884 {
885  return trString() + QStringLiteral( "[<b>feature</b>|<b>viewport</b>]" );
886 }
887 
889 {
890  return trString() + QStringLiteral( "[<b>pad</b>|<b>repeat</b>|<b>reflect</b>]" );
891 }
892 
894 {
895  return trString() + QStringLiteral( "[<b>no</b>|<b>solid</b>|<b>dash</b>|<b>dot</b>|<b>dash dot</b>|<b>dash dot dot</b>]" );
896 }
897 
899 {
900  return trString() + QStringLiteral( "[<b>square</b>|<b>flat</b>|<b>round</b>]" );
901 }
902 
904 {
905  return trString() + QStringLiteral( "[<b>solid</b>|<b>horizontal</b>|<b>vertical</b>|<b>cross</b>|<b>b_diagonal</b>|<b>f_diagonal"
906  "</b>|<b>diagonal_x</b>|<b>dense1</b>|<b>dense2</b>|<b>dense3</b>|<b>dense4</b>|<b>dense5"
907  "</b>|<b>dense6</b>|<b>dense7</b>|<b>no]" );
908 }
909 
911 {
912  return trString() + QStringLiteral( "[<b>circle</b>|<b>rectangle</b>|<b>diamond</b>|<b>cross</b>|<b>triangle"
913  "</b>|<b>right_half_triangle</b>|<b>left_half_triangle</b>|<b>semi_circle</b>]" );
914 }
915 
917 {
918  return tr( "[<b><dash>;<space></b>] e.g. '8;2;1;2'" );
919 }
Class for parsing and evaluation of expressions (formerly called "search strings").
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
void setActive(bool active)
static QString gradientSpreadDesc()
void setVectorLayer(QgsVectorLayer *layer)
Sets the vector layer associated with the button.
An assistant (wizard) dialog, accessible from a QgsDataDefinedButton.
void setField(const QString &field)
Set the current defined field.
bool isReadOnly(const QString &name) const
Returns whether a variable is read only, and should not be modifiable by users.
A container class for data source field mapping or expression.
QString name
Definition: qgsfield.h:55
static QString doublePosDesc()
static QString colorNoAlphaDesc()
static QString textVertAlignDesc()
QList< QWidget * > registeredEnabledWidgets()
Return widget siblings that get disabled/enabled when data definition or expression is set/unset...
static QString paperOrientationDesc()
void dataDefinedChanged(const QString &definition)
Emitted when data definition or expression is changed.
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
bool useExpression() const
Whether the current expression is to be used instead of field mapping.
void registerEnabledWidgets(const QList< QWidget *> &wdgts)
Register list of sibling widgets that get disabled/enabled when data definition or expression is set/...
static QString unitsMmMuDesc()
static QString anyStringDesc()
void disableEnabledWidgets(bool disable)
Set siblings&#39; enabled property when data definition or expression is set/unset.
static QString lineStyleDesc()
static QString horizontalAnchorDesc()
QString parserErrorString() const
Returns parser error.
void mouseReleaseEvent(QMouseEvent *event) override
bool useExpression() const
Returns if the field or the expression part is active.
QgsFields fields() const
Returns the list of fields of this layer.
void setMessageAsHtml(const QString &msg)
void setUseExpression(bool use)
Controls if the field or the expression part is active.
void setExpression(const QString &exp)
Set the current defined expression.
bool isActive() const
Whether the current data definition or expression is to be used.
void setActive(bool active)
Set whether the current data definition or expression is to be used.
static QString unitsMmMuPercentDesc()
virtual QgsExpressionContext createExpressionContext() const =0
This method needs to be reimplemented in all classes which implement this interface and return an exp...
void registerEnabledWidget(QWidget *wdgt)
Register a sibling widget that gets disabled/enabled when data definition or expression is set/unset...
static QString textHorzAlignDesc()
static QString penJoinStyleDesc()
static QString double180RotDesc()
static QString gradientTypeDesc()
void setField(const QString &field)
Set the field name which this QgsDataDefined represents.
QString getField() const
The current defined field.
QString expressionString() const
Returns the expression string of this QgsDataDefined.
static QString intTranspDesc()
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:47
void registerExpressionContextGenerator(QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
QStringList variableNames() const
Returns a list of variables names set by all scopes in the context.
QgsDataDefinedAssistant * assistant()
Returns the assistant used to defined the data defined object properties, if set. ...
Abstract interface for generating an expression context.
QList< QWidget * > registeredCheckedWidgets()
Return widget siblings that get checked when data definition or expression is active.
static QString markerStyleDesc()
void dataDefinedActivated(bool active)
Emitted when active state changed.
QString field() const
Get the field which this QgsDataDefined represents.
static QString blendModesDesc()
QgsDataDefined currentDataDefined() const
Returns a QgsDataDefined which reflects the current settings from the button.
static QString gradientCoordModeDesc()
static QString trString()
Common descriptions for expected input values.
void registerCheckedWidget(QWidget *wdgt)
Register a sibling widget that get checked when data definition or expression is active.
void setAssistant(const QString &title, QgsDataDefinedAssistant *assistant)
Sets an assistant used to define the data defined object properties.
static QString verticalAnchorDesc()
static QString fillStyleDesc()
static QString paperSizeDesc()
void setUseExpression(bool use)
Set whether the current expression is to be used instead of field mapping.
void checkCheckedWidgets(bool check)
Set siblings&#39; checked property when data definition or expression is active.
A generic message view for displaying QGIS messages.
static QString intPosOneDesc()
QString getExpression() const
The current defined expression.
void registerCheckedWidgets(const QList< QWidget *> &wdgts)
Register list of sibling widgets that get checked when data definition or expression is active...
static QString customDashDesc()
Represents a vector layer which manages a vector based data sets.
QgsDataDefinedButton(QWidget *parent=nullptr, const QgsVectorLayer *vl=nullptr, const QgsDataDefined *datadefined=nullptr, QgsDataDefinedButton::DataTypes datatypes=AnyType, const QString &description=QString())
Construct a new data defined button.
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:98
void updateDataDefined(QgsDataDefined *dd) const
Updates a QgsDataDefined with the current settings from the button.
void setExpressionString(const QString &expr)
Sets the expression for this QgsDataDefined.
bool isActive() const
void init(const QgsVectorLayer *vl, const QgsDataDefined *datadefined=nullptr, QgsDataDefinedButton::DataTypes datatypes=AnyType, const QString &description=QString())
Initialize a newly constructed data defined button (useful if button already included from form layou...
A generic dialog for building expression strings.
static QString double0to1Desc()
static QString colorAlphaDesc()