QGIS API Documentation  2.4.0-Chugiak
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 
30 
37 
39  const QgsVectorLayer* vl,
40  const QgsDataDefined* datadefined,
41  DataTypes datatypes,
42  QString description )
43  : QToolButton( parent )
44 {
45  // set up static icons
46  if ( mIconDataDefine.isNull() )
47  {
48  mIconDataDefine = QgsApplication::getThemeIcon( "/mIconDataDefine.svg" );
49  mIconDataDefineOn = QgsApplication::getThemeIcon( "/mIconDataDefineOn.svg" );
50  mIconDataDefineError = QgsApplication::getThemeIcon( "/mIconDataDefineError.svg" );
51  mIconDataDefineExpression = QgsApplication::getThemeIcon( "/mIconDataDefineExpression.svg" );
52  mIconDataDefineExpressionOn = QgsApplication::getThemeIcon( "/mIconDataDefineExpressionOn.svg" );
53  mIconDataDefineExpressionError = QgsApplication::getThemeIcon( "/mIconDataDefineExpressionError.svg" );
54  }
55 
56  // set default tool button icon properties
57  setFixedSize( 28, 24 );
58  setStyleSheet( QString( "QToolButton{ background: none; border: none;}" ) );
59  setIconSize( QSize( 24, 24 ) );
60  setPopupMode( QToolButton::InstantPopup );
61 
62  mDefineMenu = new QMenu( this );
63  connect( mDefineMenu, SIGNAL( aboutToShow() ), this, SLOT( aboutToShowMenu() ) );
64  connect( mDefineMenu, SIGNAL( triggered( QAction* ) ), this, SLOT( menuActionTriggered( QAction* ) ) );
65  setMenu( mDefineMenu );
66 
67  mFieldsMenu = new QMenu( this );
68 
69  mActionDataTypes = new QAction( this );
70  // list fields and types in submenu, since there may be many
71  mActionDataTypes->setMenu( mFieldsMenu );
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  mActionExpDialog = new QAction( tr( "Edit..." ), this );
82  mActionPasteExpr = new QAction( tr( "Paste" ), this );
83  mActionCopyExpr = new QAction( tr( "Copy" ), this );
84  mActionClearExpr = new QAction( tr( "Clear" ), this );
85 
86  // set up sibling widget connections
87  connect( this, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( disableEnabledWidgets( bool ) ) );
88  connect( this, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( checkCheckedWidgets( bool ) ) );
89 
90  init( vl, datadefined, datatypes, description );
91 }
92 
94 {
95  mEnabledWidgets.clear();
96  mCheckedWidgets.clear();
97 }
98 
100  const QgsDataDefined* datadefined,
101  DataTypes datatypes,
102  QString description )
103 {
104  mVectorLayer = vl;
105  // construct default property if none or incorrect passed in
106  if ( !datadefined )
107  {
108  mProperty.insert( "active", "0" );
109  mProperty.insert( "useexpr", "0" );
110  mProperty.insert( "expression", "" );
111  mProperty.insert( "field", "" );
112  }
113  else
114  {
115  mProperty.insert( "active", datadefined->isActive() ? "1" : "0" );
116  mProperty.insert( "useexpr", datadefined->useExpression() ? "1" : "0" );
117  mProperty.insert( "expression", datadefined->expressionString() );
118  mProperty.insert( "field", datadefined->field() );
119  }
120 
121  mDataTypes = datatypes;
122  mFieldNameList.clear();
123  mFieldTypeList.clear();
124 
125  mInputDescription = description;
126  mFullDescription = QString( "" );
127  mUsageInfo = QString( "" );
128  mCurrentDefinition = QString( "" );
129 
130  // set up data types string
131  mDataTypesString = QString( "" );
132 
133  QStringList ts;
134  if ( mDataTypes.testFlag( AnyType ) || mDataTypes.testFlag( String ) )
135  {
136  ts << tr( "string" );
137  }
138  if ( mDataTypes.testFlag( AnyType ) || mDataTypes.testFlag( Int ) )
139  {
140  ts << tr( "int" );
141  }
142  if ( mDataTypes.testFlag( AnyType ) || mDataTypes.testFlag( Double ) )
143  {
144  ts << tr( "double" );
145  }
146 
147  if ( !ts.isEmpty() )
148  {
149  mDataTypesString = ts.join( ", " );
150  mActionDataTypes->setText( tr( "Field type: " ) + mDataTypesString );
151  }
152 
153  if ( mVectorLayer )
154  {
155  // store just a list of fields of unknown type or those that match the expected type
156  const QgsFields& fields = mVectorLayer->pendingFields();
157  for ( int i = 0; i < fields.count(); ++i )
158  {
159  const QgsField& f = fields.at( i );
160  bool fieldMatch = false;
161  // NOTE: these are the only QVariant enums supported at this time (see QgsField)
162  QString fieldType;
163  switch ( f.type() )
164  {
165  case QVariant::String:
166  fieldMatch = mDataTypes.testFlag( String );
167  fieldType = tr( "string" );
168  break;
169  case QVariant::Int:
170  fieldMatch = mDataTypes.testFlag( Int );
171  fieldType = tr( "integer" );
172  break;
173  case QVariant::Double:
174  fieldMatch = mDataTypes.testFlag( Double );
175  fieldType = tr( "double" );
176  break;
177  case QVariant::Invalid:
178  default:
179  fieldMatch = true; // field type is unknown
180  fieldType = tr( "unknown type" );
181  }
182  if ( fieldMatch || mDataTypes.testFlag( AnyType ) )
183  {
184  mFieldNameList << f.name();
185  mFieldTypeList << fieldType;
186  }
187  }
188  }
189 
190  updateGui();
191 }
192 
193 void QgsDataDefinedButton::mouseReleaseEvent( QMouseEvent *event )
194 {
195  // Ctrl-click to toggle activated state
196  if (( event->modifiers() & ( Qt::ControlModifier ) )
197  || event->button() == Qt::RightButton )
198  {
199  setActive( !isActive() );
200  updateGui();
201  event->ignore();
202  return;
203  }
204 
205  // pass to default behaviour
206  QToolButton::mousePressEvent( event );
207 }
208 
210 {
211  mDefineMenu->clear();
212 
213  bool hasExp = !getExpression().isEmpty();
214  bool hasField = !getField().isEmpty();
215  QString ddTitle = tr( "Data defined override" );
216 
217  QAction* ddTitleAct = mDefineMenu->addAction( ddTitle );
218  QFont titlefont = ddTitleAct->font();
219  titlefont.setItalic( true );
220  ddTitleAct->setFont( titlefont );
221  ddTitleAct->setEnabled( false );
222 
223  bool addActiveAction = false;
224  if ( useExpression() && hasExp )
225  {
226  QgsExpression exp( getExpression() );
227  // whether expression is parse-able
228  addActiveAction = !exp.hasParserError();
229  }
230  else if ( !useExpression() && hasField )
231  {
232  // whether field exists
233  addActiveAction = mFieldNameList.contains( getField() );
234  }
235 
236  if ( addActiveAction )
237  {
238  ddTitleAct->setText( ddTitle + " (" + ( useExpression() ? tr( "expression" ) : tr( "field" ) ) + ")" );
239  mDefineMenu->addAction( mActionActive );
240  mActionActive->setText( isActive() ? tr( "Deactivate" ) : tr( "Activate" ) );
241  mActionActive->setData( QVariant( isActive() ? false : true ) );
242  }
243 
244  if ( !mFullDescription.isEmpty() )
245  {
246  mDefineMenu->addAction( mActionDescription );
247  }
248 
249  mDefineMenu->addSeparator();
250 
251  if ( !mDataTypesString.isEmpty() )
252  {
253  QAction* fieldTitleAct = mDefineMenu->addAction( tr( "Attribute field" ) );
254  fieldTitleAct->setFont( titlefont );
255  fieldTitleAct->setEnabled( false );
256 
257  mDefineMenu->addAction( mActionDataTypes );
258 
259  mFieldsMenu->clear();
260 
261  if ( mFieldNameList.size() > 0 )
262  {
263 
264  for ( int j = 0; j < mFieldNameList.count(); ++j )
265  {
266  QString fldname = mFieldNameList.at( j );
267  QAction* act = mFieldsMenu->addAction( fldname + " (" + mFieldTypeList.at( j ) + ")" );
268  act->setData( QVariant( fldname ) );
269  if ( getField() == fldname )
270  {
271  act->setCheckable( true );
272  act->setChecked( !useExpression() );
273  }
274  }
275  }
276  else
277  {
278  QAction* act = mFieldsMenu->addAction( tr( "No matching field types found" ) );
279  act->setEnabled( false );
280  }
281 
282  mDefineMenu->addSeparator();
283  }
284 
285  QAction* exprTitleAct = mDefineMenu->addAction( tr( "Expression" ) );
286  exprTitleAct->setFont( titlefont );
287  exprTitleAct->setEnabled( false );
288 
289  if ( hasExp )
290  {
291  QString expString = getExpression();
292  if ( expString.length() > 35 )
293  {
294  expString.truncate( 35 );
295  expString.append( "..." );
296  }
297 
298  expString.prepend( tr( "Current: " ) );
299 
300  if ( !mActionExpression )
301  {
302  mActionExpression = new QAction( expString, this );
303  mActionExpression->setCheckable( true );
304  }
305  else
306  {
307  mActionExpression->setText( expString );
308  }
309  mDefineMenu->addAction( mActionExpression );
310  mActionExpression->setChecked( useExpression() );
311 
312  mDefineMenu->addAction( mActionExpDialog );
313  mDefineMenu->addAction( mActionCopyExpr );
314  mDefineMenu->addAction( mActionPasteExpr );
315  mDefineMenu->addAction( mActionClearExpr );
316  }
317  else
318  {
319  mDefineMenu->addAction( mActionExpDialog );
320  mDefineMenu->addAction( mActionPasteExpr );
321  }
322 
323 }
324 
326 {
327  if ( action == mActionActive )
328  {
329  setActive( mActionActive->data().toBool() );
330  updateGui();
331  }
332  else if ( action == mActionDescription )
333  {
335  }
336  else if ( action == mActionExpDialog )
337  {
339  }
340  else if ( action == mActionExpression )
341  {
342  setUseExpression( true );
343  setActive( true );
344  updateGui();
345  }
346  else if ( action == mActionCopyExpr )
347  {
348  QApplication::clipboard()->setText( getExpression() );
349  }
350  else if ( action == mActionPasteExpr )
351  {
352  QString exprString = QApplication::clipboard()->text();
353  if ( !exprString.isEmpty() )
354  {
355  setExpression( exprString );
356  setUseExpression( true );
357  setActive( true );
358  updateGui();
359  }
360  }
361  else if ( action == mActionClearExpr )
362  {
363  // only deactivate if defined expression is being used
364  if ( isActive() && useExpression() )
365  {
366  setUseExpression( false );
367  setActive( false );
368  }
369  setExpression( QString( "" ) );
370  updateGui();
371  }
372  else if ( mFieldsMenu->actions().contains( action ) ) // a field name clicked
373  {
374  if ( action->isEnabled() )
375  {
376  if ( getField() != action->text() )
377  {
378  setField( action->data().toString() );
379  }
380  setUseExpression( false );
381  setActive( true );
382  updateGui();
383  }
384  }
385 }
386 
388 {
389  QgsMessageViewer* mv = new QgsMessageViewer( this );
390  mv->setWindowTitle( tr( "Data definition description" ) );
392  mv->exec();
393 }
394 
396 {
397  QgsExpressionBuilderDialog d( const_cast<QgsVectorLayer*>( mVectorLayer ), getExpression() );
398  if ( d.exec() == QDialog::Accepted )
399  {
400  QString newExp = d.expressionText();
401  setExpression( d.expressionText().trimmed() );
402  bool hasExp = !newExp.isEmpty();
403 
404  setUseExpression( hasExp );
405  setActive( hasExp );
406  updateGui();
407  }
408  activateWindow(); // reset focus to parent window
409 }
410 
412 {
413  QString oldDef = mCurrentDefinition;
414  QString newDef( "" );
415  bool hasExp = !getExpression().isEmpty();
416  bool hasField = !getField().isEmpty();
417 
418  if ( useExpression() && !hasExp )
419  {
420  setActive( false );
421  setUseExpression( false );
422  }
423  else if ( !useExpression() && !hasField )
424  {
425  setActive( false );
426  }
427 
428  QIcon icon = mIconDataDefine;
429  QString deftip = tr( "undefined" );
430  if ( useExpression() && hasExp )
431  {
433  newDef = deftip = getExpression();
434 
435  QgsExpression exp( getExpression() );
436  if ( exp.hasParserError() )
437  {
438  setActive( false );
440  deftip = tr( "Parse error: %1" ).arg( exp.parserErrorString() );
441  newDef = "";
442  }
443  }
444  else if ( !useExpression() && hasField )
445  {
447  newDef = deftip = getField();
448 
449  if ( !mFieldNameList.contains( getField() ) )
450  {
451  setActive( false );
452  icon = mIconDataDefineError;
453  deftip = tr( "'%1' field missing" ).arg( getField() );
454  newDef = "";
455  }
456  }
457 
458  setIcon( icon );
459 
460  // update and emit current definition
461  if ( newDef != oldDef )
462  {
463  mCurrentDefinition = newDef;
465  }
466 
467  // build full description for tool tip and popup dialog
468  mFullDescription = tr( "<b><u>Data defined override</u></b><br>" );
469 
470  mFullDescription += tr( "<b>Active: </b>%1&nbsp;&nbsp;&nbsp;<i>(ctrl|right-click toggles)</i><br>" ).arg( isActive() ? tr( "yes" ) : tr( "no" ) );
471 
472  if ( !mUsageInfo.isEmpty() )
473  {
474  mFullDescription += tr( "<b>Usage:</b><br>%1<br>" ).arg( mUsageInfo );
475  }
476 
477  if ( !mInputDescription.isEmpty() )
478  {
479  mFullDescription += tr( "<b>Expected input:</b><br>%1<br>" ).arg( mInputDescription );
480  }
481 
482  if ( !mDataTypesString.isEmpty() )
483  {
484  mFullDescription += tr( "<b>Valid input types:</b><br>%1<br>" ).arg( mDataTypesString );
485  }
486 
487  QString deftype( "" );
488  if ( deftip != tr( "undefined" ) )
489  {
490  deftype = QString( " (%1)" ).arg( useExpression() ? tr( "expression" ) : tr( "field" ) );
491  }
492 
493  // truncate long expressions, or tool tip may be too wide for screen
494  if ( deftip.length() > 75 )
495  {
496  deftip.truncate( 75 );
497  deftip.append( "..." );
498  }
499 
500  mFullDescription += tr( "<b>Current definition %1:</b><br>%2" ).arg( deftype ).arg( deftip );
501 
502  setToolTip( mFullDescription );
503 
504 }
505 
507 {
508  if ( isActive() != active )
509  {
510  mProperty.insert( "active", active ? "1" : "0" );
511  emit dataDefinedActivated( active );
512  }
513 }
514 
515 void QgsDataDefinedButton::registerEnabledWidgets( QList<QWidget*> wdgts )
516 {
517  for ( int i = 0; i < wdgts.size(); ++i )
518  {
519  registerEnabledWidget( wdgts.at( i ) );
520  }
521 }
522 
524 {
525  QPointer<QWidget> wdgtP( wdgt );
526  if ( !mEnabledWidgets.contains( wdgtP ) )
527  {
528  mEnabledWidgets.append( wdgtP );
529  }
530 }
531 
533 {
534  QList<QWidget*> wdgtList;
535  for ( int i = 0; i < mEnabledWidgets.size(); ++i )
536  {
537  wdgtList << mEnabledWidgets.at( i );
538  }
539  return wdgtList;
540 }
541 
543 {
544  for ( int i = 0; i < mEnabledWidgets.size(); ++i )
545  {
546  mEnabledWidgets.at( i )->setDisabled( disable );
547  }
548 }
549 
550 void QgsDataDefinedButton::registerCheckedWidgets( QList<QWidget*> wdgts )
551 {
552  for ( int i = 0; i < wdgts.size(); ++i )
553  {
554  registerCheckedWidget( wdgts.at( i ) );
555  }
556 }
557 
559 {
560  QPointer<QWidget> wdgtP( wdgt );
561  if ( !mCheckedWidgets.contains( wdgtP ) )
562  {
563  mCheckedWidgets.append( wdgtP );
564  }
565 }
566 
568 {
569  QList<QWidget*> wdgtList;
570  for ( int i = 0; i < mCheckedWidgets.size(); ++i )
571  {
572  wdgtList << mCheckedWidgets.at( i );
573  }
574  return wdgtList;
575 }
576 
578 {
579  // don't uncheck, only set to checked
580  if ( !check )
581  {
582  return;
583  }
584  for ( int i = 0; i < mCheckedWidgets.size(); ++i )
585  {
586  QAbstractButton *btn = qobject_cast< QAbstractButton * >( mCheckedWidgets.at( i ) );
587  if ( btn && btn->isCheckable() )
588  {
589  btn->setChecked( true );
590  continue;
591  }
592  QGroupBox *grpbx = qobject_cast< QGroupBox * >( mCheckedWidgets.at( i ) );
593  if ( grpbx && grpbx->isCheckable() )
594  {
595  grpbx->setChecked( true );
596  }
597  }
598 }
599 
601 {
602  // just something to reduce translation redundancy
603  return tr( "string " );
604 }
605 
607 {
608  return tr( "bool [<b>1</b>=True|<b>0</b>=False]" );
609 }
610 
612 {
613  return tr( "string of variable length" );
614 }
615 
617 {
618  return tr( "int [&lt;= 0 =&gt;]" );
619 }
620 
622 {
623  return tr( "int [&gt;= 0]" );
624 }
625 
627 {
628  return tr( "int [&gt;= 1]" );
629 }
630 
632 {
633  return tr( "double [&lt;= 0.0 =&gt;]" );
634 }
635 
637 {
638  return tr( "double [&gt;= 0.0]" );
639 }
640 
642 {
643  return tr( "double coord [<b>X,Y</b>] as &lt;= 0.0 =&gt;" );
644 }
645 
647 {
648  return tr( "double [-180.0 - 180.0]" );
649 }
650 
652 {
653  return tr( "int [0-100]" );
654 }
655 
657 {
658  return trString() + "[<b>MM</b>|<b>MapUnit</b>]";
659 }
660 
662 {
663  return trString() + "[<b>MM</b>|<b>MapUnit</b>|<b>Percent</b>]";
664 }
665 
667 {
668  return tr( "string [<b>r,g,b</b>] as int 0-255" );
669 }
670 
672 {
673  return tr( "string [<b>r,g,b,a</b>] as int 0-255" );
674 }
675 
677 {
678  return trString() + "[<b>Left</b>|<b>Center</b>|<b>Right</b>]";
679 }
680 
682 {
683  return trString() + "[<b>Bottom</b>|<b>Middle</b>|<b>Top</b>]";
684 }
685 
687 {
688  return trString() + "[<b>Bevel</b>|<b>Miter</b>|<b>Round</b>]";
689 }
690 
692 {
693  return trString() + QString( "[<b>Normal</b>|<b>Lighten</b>|<b>Screen</b>|<b>Dodge</b>|<br>"
694  "<b>Addition</b>|<b>Darken</b>|<b>Multiply</b>|<b>Burn</b>|<b>Overlay</b>|<br>"
695  "<b>SoftLight</b>|<b>HardLight</b>|<b>Difference</b>|<b>Subtract</b>" );
696 }
697 
699 {
700  return trString() + QString( "[<b>filepath</b>] as<br>"
701  "<b>''</b>=empty|absolute|search-paths-relative|<br>"
702  "project-relative|URL" );
703 }
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:89
const QString & name() const
Gets the name of the field.
Definition: qgsfield.cpp:58
static QIcon mIconDataDefineExpressionError
void setExpression(QString exp)
Set the current defined expression.
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Definition: qgsexpression.h:96
void setField(QString field)
Set the current defined field.
bool isActive()
Whether the current data definition or expression is to be used.
A container class for data source field mapping or expression.
QgsDataDefinedButton(QWidget *parent=0, const QgsVectorLayer *vl=0, const QgsDataDefined *datadefined=0, DataTypes datatypes=AnyType, QString description=QString(""))
Construct a new data defined button.
static QString doublePosDesc()
static QString colorNoAlphaDesc()
static QString textVertAlignDesc()
QString field() const
QList< QWidget * > registeredEnabledWidgets()
Return widget siblings that get disabled/enabled when data definition or expression is set/unset...
void dataDefinedChanged(const QString &definition)
Emitted when data definition or expression is changed.
void menuActionTriggered(QAction *action)
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
static QString unitsMmMuDesc()
void registerCheckedWidgets(QList< QWidget * > wdgts)
Register list of sibling widgets that get checked when data definition or expression is active...
static QString anyStringDesc()
Container of fields for a vector layer.
Definition: qgsfield.h:161
void disableEnabledWidgets(bool disable)
Set siblings' enabled property when data definition or expression is set/unset.
bool useExpression()
Whether the current expression is to be used instead of field mapping.
QString expressionString() const
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.h:208
void init(const QgsVectorLayer *vl, const QgsDataDefined *datadefined=0, DataTypes datatypes=AnyType, QString description=QString(""))
Initialize a newly constructed data defined button (useful if button already included from form layou...
static QIcon icon(QString icon)
void setMessageAsHtml(const QString &msg)
void setActive(bool active)
Set whether the current data definition or expression is to be used.
static QString unitsMmMuPercentDesc()
static QIcon mIconDataDefineExpression
void registerEnabledWidget(QWidget *wdgt)
Register a sibling widget that gets disabled/enabled when data definition or expression is set/unset...
static QString textHorzAlignDesc()
QList< QPointer< QWidget > > mCheckedWidgets
void mouseReleaseEvent(QMouseEvent *event)
static QString penJoinStyleDesc()
static QString double180RotDesc()
static QString intTranspDesc()
QString getExpression() const
The current defined expression.
int count() const
Return number of items.
Definition: qgsfield.h:195
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:31
bool useExpression() const
void registerEnabledWidgets(QList< QWidget * > wdgts)
Register list of sibling widgets that get disabled/enabled when data definition or expression is set/...
QList< QWidget * > registeredCheckedWidgets()
Return widget siblings that get checked when data definition or expression is active.
void dataDefinedActivated(bool active)
Emitted when active state changed.
static QIcon mIconDataDefineExpressionOn
const QgsVectorLayer * mVectorLayer
static QString blendModesDesc()
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.
QString getField() const
The current defined field.
void setUseExpression(bool use)
Set whether the current expression is to be used instead of field mapping.
void checkCheckedWidgets(bool check)
Set siblings' checked property when data definition or expression is active.
A generic message view for displaying QGIS messages.
static QString intPosOneDesc()
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
QList< QPointer< QWidget > > mEnabledWidgets
Represents a vector layer which manages a vector based data sets.
QString parserErrorString() const
Returns parser error.
Definition: qgsexpression.h:98
bool isActive() const
A generic dialog for building expression strings.
QMap< QString, QString > mProperty
static QString colorAlphaDesc()
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:63
#define tr(sourceText)