QGIS API Documentation  2.10.1-Pisa
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsexpressionbuilderwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgisexpressionbuilderwidget.cpp - A genric expression string builder widget.
3  --------------------------------------
4  Date : 29-May-2011
5  Copyright : (C) 2011 by Nathan Woodrow
6  Email : woodrow.nathan 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 #include "qgslogger.h"
18 #include "qgsexpression.h"
19 #include "qgsmessageviewer.h"
20 #include "qgsapplication.h"
21 #include "qgspythonrunner.h"
22 
23 #include <QSettings>
24 #include <QMenu>
25 #include <QFile>
26 #include <QTextStream>
27 #include <QDir>
28 #include <QComboBox>
29 
31  : QWidget( parent )
32  , mLayer( NULL )
33  , highlighter( NULL )
34  , mExpressionValid( false )
35 {
36  setupUi( this );
37 
38  mValueGroupBox->hide();
39  mLoadGroupBox->hide();
40 // highlighter = new QgsExpressionHighlighter( txtExpressionString->document() );
41 
42  mModel = new QStandardItemModel();
43  mProxyModel = new QgsExpressionItemSearchProxy();
44  mProxyModel->setSourceModel( mModel );
45  expressionTree->setModel( mProxyModel );
46 
47  expressionTree->setContextMenuPolicy( Qt::CustomContextMenu );
48  connect( this, SIGNAL( expressionParsed( bool ) ), this, SLOT( setExpressionState( bool ) ) );
49  connect( expressionTree, SIGNAL( customContextMenuRequested( const QPoint & ) ), this, SLOT( showContextMenu( const QPoint & ) ) );
50  connect( expressionTree->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ),
51  this, SLOT( currentChanged( const QModelIndex &, const QModelIndex & ) ) );
52 
53  connect( btnLoadAll, SIGNAL( pressed() ), this, SLOT( loadAllValues() ) );
54  connect( btnLoadSample, SIGNAL( pressed() ), this, SLOT( loadSampleValues() ) );
55 
56  foreach ( QPushButton* button, mOperatorsGroupBox->findChildren<QPushButton *>() )
57  {
58  connect( button, SIGNAL( pressed() ), this, SLOT( operatorButtonClicked() ) );
59  }
60 
61  txtSearchEdit->setPlaceholderText( tr( "Search" ) );
62 
63  QSettings settings;
64  splitter->restoreState( settings.value( "/windows/QgsExpressionBuilderWidget/splitter" ).toByteArray() );
65  functionsplit->restoreState( settings.value( "/windows/QgsExpressionBuilderWidget/functionsplitter" ).toByteArray() );
66 
67  txtExpressionString->setFoldingVisible( false );
68 
69  updateFunctionTree();
70 
72  {
73  QgsPythonRunner::eval( "qgis.user.expressionspath", mFunctionsPath );
75  // The scratch file gets written each time the widget opens.
76  saveFunctionFile( "scratch" );
77  updateFunctionFileList( mFunctionsPath );
78  }
79  else
80  {
81  tab_2->setEnabled( false );
82  }
83 
84  // select the first item in the function list
85  // in order to avoid a blank help widget
86  QModelIndex firstItem = mProxyModel->index( 0, 0, QModelIndex() );
87  expressionTree->setCurrentIndex( firstItem );
88 }
89 
90 
92 {
93  QSettings settings;
94  settings.setValue( "/windows/QgsExpressionBuilderWidget/splitter", splitter->saveState() );
95  settings.setValue( "/windows/QgsExpressionBuilderWidget/functionsplitter", functionsplit->saveState() );
96 }
97 
99 {
100  mLayer = layer;
101 }
102 
104 {
105  // Get the item
106  QModelIndex idx = mProxyModel->mapToSource( index );
107  QgsExpressionItem* item = dynamic_cast<QgsExpressionItem*>( mModel->itemFromIndex( idx ) );
108  if ( !item )
109  return;
110 
111  if ( item->getItemType() != QgsExpressionItem::Field )
112  {
113  mValueListWidget->clear();
114  }
115 
116  mLoadGroupBox->setVisible( item->getItemType() == QgsExpressionItem::Field && mLayer );
117  mValueGroupBox->setVisible( item->getItemType() == QgsExpressionItem::Field && mLayer );
118 
119  // Show the help for the current item.
120  QString help = loadFunctionHelp( item );
121  txtHelpText->setText( help );
122  txtHelpText->setToolTip( txtHelpText->toPlainText() );
123 }
124 
126 {
127  saveFunctionFile( cmbFileNames->currentText() );
128  runPythonCode( txtPython->text() );
129 }
130 
131 void QgsExpressionBuilderWidget::runPythonCode( QString code )
132 {
133  if ( QgsPythonRunner::isValid() )
134  {
135  QString pythontext = code;
136  QgsPythonRunner::run( pythontext );
137  }
138  updateFunctionTree();
139  loadFieldNames();
140  loadRecent( mRecentKey );
141 }
142 
144 {
145  QDir myDir( mFunctionsPath );
146  if ( !myDir.exists() )
147  {
148  myDir.mkpath( mFunctionsPath );
149  }
150 
151  if ( !fileName.endsWith( ".py" ) )
152  {
153  fileName.append( ".py" );
154  }
155 
156  fileName = mFunctionsPath + QDir::separator() + fileName;
157  QFile myFile( fileName );
158  if ( myFile.open( QIODevice::WriteOnly ) )
159  {
160  QTextStream myFileStream( &myFile );
161  myFileStream << txtPython->text() << endl;
162  myFile.close();
163  }
164 }
165 
167 {
168  mFunctionsPath = path;
169  QDir dir( path );
170  dir.setNameFilters( QStringList() << "*.py" );
171  QStringList files = dir.entryList( QDir::Files );
172  cmbFileNames->clear();
173  foreach ( QString name, files )
174  {
175  QFileInfo info( mFunctionsPath + QDir::separator() + name );
176  if ( info.baseName() == "__init__" ) continue;
177  cmbFileNames->addItem( info.baseName() );
178  }
179 }
180 
182 {
183  QString templatetxt;
184  QgsPythonRunner::eval( "qgis.user.expressions.template", templatetxt );
185  txtPython->setText( templatetxt );
186  int index = cmbFileNames->findText( fileName );
187  if ( index == -1 )
188  cmbFileNames->setEditText( fileName );
189  else
190  cmbFileNames->setCurrentIndex( index );
191 }
192 
194 {
195  newFunctionFile();
196 }
197 
199 {
200  if ( index == -1 )
201  return;
202 
203  QString path = mFunctionsPath + QDir::separator() + cmbFileNames->currentText();
204  loadCodeFromFile( path );
205 }
206 
208 {
209  if ( !path.endsWith( ".py" ) )
210  path.append( ".py" );
211 
212  txtPython->loadScript( path );
213 }
214 
216 {
217  txtPython->setText( code );
218 }
219 
221 {
222  QString name = cmbFileNames->currentText();
223  saveFunctionFile( name );
224  int index = cmbFileNames->findText( name );
225  if ( index == -1 )
226  {
227  cmbFileNames->addItem( name );
228  cmbFileNames->setCurrentIndex( cmbFileNames->count() - 1 );
229  }
230 }
231 
233 {
234  QModelIndex idx = mProxyModel->mapToSource( index );
235  QgsExpressionItem* item = dynamic_cast<QgsExpressionItem*>( mModel->itemFromIndex( idx ) );
236  if ( item == 0 )
237  return;
238 
239  // Don't handle the double click it we are on a header node.
240  if ( item->getItemType() == QgsExpressionItem::Header )
241  return;
242 
243  // Insert the expression text or replace selected text
244  txtExpressionString->insertText( item->getExpressionText() );
245  txtExpressionString->setFocus();
246 }
247 
249 {
250  // TODO We should really return a error the user of the widget that
251  // the there is no layer set.
252  if ( !mLayer )
253  return;
254 
255  loadFieldNames( mLayer->pendingFields() );
256 }
257 
259 {
260  if ( fields.isEmpty() )
261  return;
262 
263  QStringList fieldNames;
264  //foreach ( const QgsField& field, fields )
265  for ( int i = 0; i < fields.count(); ++i )
266  {
267  QString fieldName = fields[i].name();
268  fieldNames << fieldName;
269  registerItem( "Fields and Values", fieldName, " \"" + fieldName + "\" ", "", QgsExpressionItem::Field );
270  }
271 // highlighter->addFields( fieldNames );
272 }
273 
274 void QgsExpressionBuilderWidget::fillFieldValues( int fieldIndex, int countLimit )
275 {
276  // TODO We should really return a error the user of the widget that
277  // the there is no layer set.
278  if ( !mLayer )
279  return;
280 
281  // TODO We should thread this so that we don't hold the user up if the layer is massive.
282  mValueListWidget->clear();
283 
284  if ( fieldIndex < 0 )
285  return;
286 
287  mValueListWidget->setUpdatesEnabled( false );
288  mValueListWidget->blockSignals( true );
289 
290  QList<QVariant> values;
291  mLayer->uniqueValues( fieldIndex, values, countLimit );
292  foreach ( QVariant value, values )
293  {
294  if ( value.isNull() )
295  mValueListWidget->addItem( "NULL" );
296  else if ( value.type() == QVariant::Int || value.type() == QVariant::Double || value.type() == QVariant::LongLong )
297  mValueListWidget->addItem( value.toString() );
298  else
299  mValueListWidget->addItem( "'" + value.toString().replace( "'", "''" ) + "'" );
300  }
301 
302  mValueListWidget->setUpdatesEnabled( true );
303  mValueListWidget->blockSignals( false );
304 }
305 
307  QString label,
308  QString expressionText,
309  QString helpText,
311 {
312  QgsExpressionItem* item = new QgsExpressionItem( label, expressionText, helpText, type );
313  item->setData( label, Qt::UserRole );
314  // Look up the group and insert the new function.
315  if ( mExpressionGroups.contains( group ) )
316  {
317  QgsExpressionItem *groupNode = mExpressionGroups.value( group );
318  groupNode->appendRow( item );
319  }
320  else
321  {
322  // If the group doesn't exist yet we make it first.
324  newgroupNode->setData( group, Qt::UserRole );
325  newgroupNode->appendRow( item );
326  mModel->appendRow( newgroupNode );
327  mExpressionGroups.insert( group, newgroupNode );
328  }
329 }
330 
332 {
333  return mExpressionValid;
334 }
335 
337 {
338  QSettings settings;
339  QString location = QString( "/expressions/recent/%1" ).arg( key );
340  QStringList expressions = settings.value( location ).toStringList();
341  expressions.removeAll( this->expressionText() );
342 
343  expressions.prepend( this->expressionText() );
344 
345  while ( expressions.count() > 20 )
346  {
347  expressions.pop_back();
348  }
349 
350  settings.setValue( location, expressions );
351  this->loadRecent( key );
352 }
353 
355 {
356  mRecentKey = key;
357  QString name = tr( "Recent (%1)" ).arg( key );
358  if ( mExpressionGroups.contains( name ) )
359  {
360  QgsExpressionItem* node = mExpressionGroups.value( name );
361  node->removeRows( 0, node->rowCount() );
362  }
363 
364  QSettings settings;
365  QString location = QString( "/expressions/recent/%1" ).arg( key );
366  QStringList expressions = settings.value( location ).toStringList();
367  foreach ( QString expression, expressions )
368  {
369  this->registerItem( name, expression, expression, expression );
370  }
371 }
372 
373 void QgsExpressionBuilderWidget::updateFunctionTree()
374 {
375  mModel->clear();
376  mExpressionGroups.clear();
377  // TODO Can we move this stuff to QgsExpression, like the functions?
378  registerItem( "Operators", "+", " + ", tr( "Addition operator" ) );
379  registerItem( "Operators", "-", " - ", tr( "Subtraction operator" ) );
380  registerItem( "Operators", "*", " * ", tr( "Multiplication operator" ) );
381  registerItem( "Operators", "/", " / ", tr( "Division operator" ) );
382  registerItem( "Operators", "%", " % ", tr( "Modulo operator" ) );
383  registerItem( "Operators", "^", " ^ ", tr( "Power operator" ) );
384  registerItem( "Operators", "=", " = ", tr( "Equal operator" ) );
385  registerItem( "Operators", ">", " > ", tr( "Greater as operator" ) );
386  registerItem( "Operators", "<", " < ", tr( "Less than operator" ) );
387  registerItem( "Operators", "<>", " <> ", tr( "Unequal operator" ) );
388  registerItem( "Operators", "<=", " <= ", tr( "Less or equal operator" ) );
389  registerItem( "Operators", ">=", " >= ", tr( "Greater or equal operator" ) );
390  registerItem( "Operators", "||", " || ",
391  QString( "<b>|| %1</b><br><i>%2</i><br><i>%3:</i>%4" )
392  .arg( tr( "(String Concatenation)" ) )
393  .arg( tr( "Joins two values together into a string" ) )
394  .arg( tr( "Usage" ) )
395  .arg( tr( "'Dia' || Diameter" ) ) );
396  registerItem( "Operators", "IN", " IN " );
397  registerItem( "Operators", "LIKE", " LIKE " );
398  registerItem( "Operators", "ILIKE", " ILIKE " );
399  registerItem( "Operators", "IS", " IS " );
400  registerItem( "Operators", "OR", " OR " );
401  registerItem( "Operators", "AND", " AND " );
402  registerItem( "Operators", "NOT", " NOT " );
403 
404  QString casestring = "CASE WHEN condition THEN result END";
405  QString caseelsestring = "CASE WHEN condition THEN result ELSE result END";
406  registerItem( "Conditionals", "CASE", casestring );
407  registerItem( "Conditionals", "CASE ELSE", caseelsestring );
408 
409  registerItem( "Fields and Values", "NULL", "NULL" );
410 
411  // Load the functions from the QgsExpression class
412  int count = QgsExpression::functionCount();
413  for ( int i = 0; i < count; i++ )
414  {
416  QString name = func->name();
417  if ( name.startsWith( "_" ) ) // do not display private functions
418  continue;
419  if ( func->params() != 0 )
420  name += "(";
421  else if ( !name.startsWith( "$" ) )
422  name += "()";
423  registerItem( func->group(), func->name(), " " + name + " ", func->helptext() );
424  }
425 
427  for ( int i = 0; i < specials.size(); ++i )
428  {
429  QString name = specials[i]->name();
430  registerItem( specials[i]->group(), name, " " + name + " " );
431  }
432 }
433 
435 {
436  mDa = da;
437 }
438 
440 {
441  return txtExpressionString->text();
442 }
443 
445 {
446  txtExpressionString->setText( expression );
447 }
448 
450 {
451  QString text = expressionText();
452 
453  // If the string is empty the expression will still "fail" although
454  // we don't show the user an error as it will be confusing.
455  if ( text.isEmpty() )
456  {
457  lblPreview->setText( "" );
458  lblPreview->setStyleSheet( "" );
459  txtExpressionString->setToolTip( "" );
460  lblPreview->setToolTip( "" );
461  emit expressionParsed( false );
462  return;
463  }
464 
465  QgsExpression exp( text );
466 
467  if ( mLayer )
468  {
469  // Only set calculator if we have layer, else use default.
470  exp.setGeomCalculator( mDa );
471 
472  if ( !mFeature.isValid() )
473  {
474  mLayer->getFeatures().nextFeature( mFeature );
475  }
476 
477  if ( mFeature.isValid() )
478  {
479  QVariant value = exp.evaluate( &mFeature, mLayer->pendingFields() );
480  if ( !exp.hasEvalError() )
481  lblPreview->setText( formatPreviewString( value.toString() ) );
482  }
483  else
484  {
485  // The feature is invalid because we don't have one but that doesn't mean user can't
486  // build a expression string. They just get no preview.
487  lblPreview->setText( "" );
488  }
489  }
490  else
491  {
492  // No layer defined
493  QVariant value = exp.evaluate();
494  if ( !exp.hasEvalError() )
495  {
496  lblPreview->setText( formatPreviewString( value.toString() ) );
497  }
498  }
499 
500  if ( exp.hasParserError() || exp.hasEvalError() )
501  {
502  QString tooltip = QString( "<b>%1:</b><br>%2" ).arg( tr( "Parser Error" ) ).arg( exp.parserErrorString() );
503  if ( exp.hasEvalError() )
504  tooltip += QString( "<br><br><b>%1:</b><br>%2" ).arg( tr( "Eval Error" ) ).arg( exp.evalErrorString() );
505 
506  lblPreview->setText( tr( "Expression is invalid <a href=""more"">(more info)</a>" ) );
507  lblPreview->setStyleSheet( "color: rgba(255, 6, 10, 255);" );
508  txtExpressionString->setToolTip( tooltip );
509  lblPreview->setToolTip( tooltip );
510  emit expressionParsed( false );
511  return;
512  }
513  else
514  {
515  lblPreview->setStyleSheet( "" );
516  txtExpressionString->setToolTip( "" );
517  lblPreview->setToolTip( "" );
518  emit expressionParsed( true );
519  }
520 }
521 
522 QString QgsExpressionBuilderWidget::formatPreviewString( const QString& previewString ) const
523 {
524  if ( previewString.length() > 63 )
525  {
526  return QString( tr( "%1..." ) ).arg( previewString.left( 60 ) );
527  }
528  else
529  {
530  return previewString;
531  }
532 }
533 
535 {
536  mProxyModel->setFilterWildcard( txtSearchEdit->text() );
537  if ( txtSearchEdit->text().isEmpty() )
538  expressionTree->collapseAll();
539  else
540  expressionTree->expandAll();
541 }
542 
544 {
545  Q_UNUSED( link );
546  QgsMessageViewer * mv = new QgsMessageViewer( this );
547  mv->setWindowTitle( tr( "More info on expression error" ) );
548  mv->setMessageAsHtml( txtExpressionString->toolTip() );
549  mv->exec();
550 }
551 
553 {
554  // Insert the item text or replace selected text
555  txtExpressionString->insertText( " " + item->text() + " " );
556  txtExpressionString->setFocus();
557 }
558 
560 {
561  QPushButton* button = dynamic_cast<QPushButton*>( sender() );
562 
563  // Insert the button text or replace selected text
564  txtExpressionString->insertText( " " + button->text() + " " );
565  txtExpressionString->setFocus();
566 }
567 
569 {
570  QModelIndex idx = expressionTree->indexAt( pt );
571  idx = mProxyModel->mapToSource( idx );
572  QgsExpressionItem* item = dynamic_cast<QgsExpressionItem*>( mModel->itemFromIndex( idx ) );
573  if ( !item )
574  return;
575 
576  if ( item->getItemType() == QgsExpressionItem::Field && mLayer )
577  {
578  QMenu* menu = new QMenu( this );
579  menu->addAction( tr( "Load top 10 unique values" ), this, SLOT( loadSampleValues() ) );
580  menu->addAction( tr( "Load all unique values" ), this, SLOT( loadAllValues() ) );
581  menu->popup( expressionTree->mapToGlobal( pt ) );
582  }
583 }
584 
586 {
587  QModelIndex idx = mProxyModel->mapToSource( expressionTree->currentIndex() );
588  QgsExpressionItem* item = dynamic_cast<QgsExpressionItem*>( mModel->itemFromIndex( idx ) );
589  // TODO We should really return a error the user of the widget that
590  // the there is no layer set.
591  if ( !mLayer || !item )
592  return;
593 
594  mValueGroupBox->show();
595  int fieldIndex = mLayer->fieldNameIndex( item->text() );
596 
597  fillFieldValues( fieldIndex, 10 );
598 }
599 
601 {
602  QModelIndex idx = mProxyModel->mapToSource( expressionTree->currentIndex() );
603  QgsExpressionItem* item = dynamic_cast<QgsExpressionItem*>( mModel->itemFromIndex( idx ) );
604  // TODO We should really return a error the user of the widget that
605  // the there is no layer set.
606  if ( !mLayer || !item )
607  return;
608 
609  mValueGroupBox->show();
610  int fieldIndex = mLayer->fieldNameIndex( item->text() );
611  fillFieldValues( fieldIndex, -1 );
612 }
613 
614 void QgsExpressionBuilderWidget::setExpressionState( bool state )
615 {
616  mExpressionValid = state;
617 }
618 
619 QString QgsExpressionBuilderWidget::loadFunctionHelp( QgsExpressionItem* expressionItem )
620 {
621  if ( !expressionItem )
622  return "";
623 
624  QString helpContents = expressionItem->getHelpText();
625 
626  // Return the function help that is set for the function if there is one.
627  if ( helpContents.isEmpty() )
628  {
629  QString name = expressionItem->data( Qt::UserRole ).toString();
630 
631  if ( expressionItem->getItemType() == QgsExpressionItem::Field )
632  helpContents = QgsExpression::helptext( "Field" );
633  else
634  helpContents = QgsExpression::helptext( name );
635  }
636 
638  return "<head><style>" + myStyle + "</style></head><body>" + helpContents + "</body>";
639 }
void customContextMenuRequested(const QPoint &pos)
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:86
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
void clear()
QByteArray toByteArray() const
static unsigned index
void saveFunctionFile(QString fileName)
Save the current function editor text to the given file.
QString & append(QChar ch)
void setupUi(QWidget *widget)
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Definition: qgsexpression.h:93
bool contains(const Key &key) const
void setNameFilters(const QStringList &nameFilters)
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:168
QVariant evaluate(const QgsFeature *f=NULL)
Evaluate the feature and return the result.
A abstract base class for defining QgsExpression functions.
virtual void setSourceModel(QAbstractItemModel *sourceModel)
void setGeomCalculator(const QgsDistanceArea &da)
Sets geometry calculator used in distance/area calculations.
void uniqueValues(int index, QList< QVariant > &uniqueValues, int limit=-1)
Returns unique values for column.
QObject * sender() const
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
void setLayer(QgsVectorLayer *layer)
Sets layer in order to get the fields and values.
static QString helptext(QString name)
void addAction(QAction *action)
static bool eval(QString command, QString &result)
Eval a python statement.
void updateFunctionFileList(QString path)
Update the list of function files found at the given path.
int exec()
Container of fields for a vector layer.
Definition: qgsfield.h:173
static QString group(QString group)
static QString reportStyleSheet()
get a standard css style sheet for reports.
void clear()
QChar separator()
QString tr(const char *sourceText, const char *disambiguation, int n)
QString text() const
void loadCodeFromFile(QString path)
Load code from the given file into the function editor.
int size() const
virtual void setData(const QVariant &value, int role)
static const QList< Function * > & Functions()
QList< T > findChildren(const QString &name) const
void setMessageAsHtml(const QString &msg)
void setValue(const QString &key, const QVariant &value)
static int functionCount()
Returns the number of functions defined in the parser.
const char * name() const
int count(const T &value) const
bool exists() const
Search proxy used to filter the QgsExpressionBuilderWidget tree.
void popup(const QPoint &p, QAction *atAction)
bool isNull() const
static bool run(QString command, QString messageOnError=QString())
execute a python statement
void on_mValueListWidget_itemDoubleClicked(QListWidgetItem *item)
void setFocus()
void appendRow(const QList< QStandardItem * > &items)
bool isEmpty() const
int removeAll(const T &value)
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
void loadFunctionCode(QString code)
Load code into the function editor.
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
int count() const
Return number of items.
Definition: qgsfield.cpp:283
void on_expressionTree_doubleClicked(const QModelIndex &index)
void loadFieldNames()
Loads all the field names from the layer.
void removeRows(int row, int count)
QString name()
The name of the function.
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
void pop_back()
void newFunctionFile(QString fileName="scratch")
Create a new file in the function editor.
QgsExpressionItem::ItemType getItemType()
Get the type of expression item eg header, field, ExpressionNode.
virtual void close()
void setFilterWildcard(const QString &pattern)
General purpose distance and area calculator.
QString & replace(int position, int n, QChar after)
An expression item that can be used in the QgsExpressionBuilderWidget tree.
void currentChanged(const QModelIndex &index, const QModelIndex &)
QVariant value(const QString &key, const QVariant &defaultValue) const
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const
QStringList toStringList() const
QString group()
The group the function belongs to.
QStandardItem * itemFromIndex(const QModelIndex &index) const
QStringList entryList(QFlags< QDir::Filter > filters, QFlags< QDir::SortFlag > sort) const
static QList< Function * > specialColumns()
Returns a list of special Column definitions.
int params()
The number of parameters this function takes.
void setWindowTitle(const QString &)
A generic message view for displaying QGIS messages.
const QString helptext()
The help text for the function.
int length() const
QString expressionText()
Gets the expression string that has been set in the expression area.
void registerItem(QString group, QString label, QString expressionText, QString helpText="", QgsExpressionItem::ItemType type=QgsExpressionItem::ExpressionNode)
Registers a node item for the expression builder.
QString left(int n) const
void setGeomCalculator(const QgsDistanceArea &calc)
Sets the geometry calculator used in evaluation of expressions,.
void setExpressionText(const QString &expression)
Sets the expression string for the widget.
int rowCount() const
void prepend(const T &value)
iterator insert(const Key &key, const T &value)
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
bool nextFeature(QgsFeature &f)
Type type() const
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Represents a vector layer which manages a vector based data sets.
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
void expressionParsed(bool isValid)
Emitted when the user changes the expression in the widget.
bool isEmpty() const
Check whether the container is empty.
Definition: qgsfield.cpp:278
QString parserErrorString() const
Returns parser error.
Definition: qgsexpression.h:95
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString getHelpText()
Get the help text that is associated with this expression item.
QString toString() const
QString evalErrorString() const
Returns evaluation error.
static bool isValid()
returns true if the runner has an instance (and thus is able to run commands)
void appendRow(const QList< QStandardItem * > &items)
QString baseName() const
virtual QVariant data(int role) const
QString text() const
bool mkpath(const QString &dirPath) const
const T value(const Key &key) const