QGIS API Documentation  2.11.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules 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 
30 
31 
33  : QWidget( parent )
34  , mLayer( NULL )
35  , highlighter( NULL )
36  , mExpressionValid( false )
37 {
38  setupUi( this );
39 
40  mValueGroupBox->hide();
41  mLoadGroupBox->hide();
42 // highlighter = new QgsExpressionHighlighter( txtExpressionString->document() );
43 
44  mModel = new QStandardItemModel();
45  mProxyModel = new QgsExpressionItemSearchProxy();
46  mProxyModel->setDynamicSortFilter( true );
47  mProxyModel->setSourceModel( mModel );
48  expressionTree->setModel( mProxyModel );
49  expressionTree->setSortingEnabled( true );
50  expressionTree->sortByColumn( 0, Qt::AscendingOrder );
51 
52  expressionTree->setContextMenuPolicy( Qt::CustomContextMenu );
53  connect( this, SIGNAL( expressionParsed( bool ) ), this, SLOT( setExpressionState( bool ) ) );
54  connect( expressionTree, SIGNAL( customContextMenuRequested( const QPoint & ) ), this, SLOT( showContextMenu( const QPoint & ) ) );
55  connect( expressionTree->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ),
56  this, SLOT( currentChanged( const QModelIndex &, const QModelIndex & ) ) );
57 
58  connect( btnLoadAll, SIGNAL( pressed() ), this, SLOT( loadAllValues() ) );
59  connect( btnLoadSample, SIGNAL( pressed() ), this, SLOT( loadSampleValues() ) );
60 
61  foreach ( QPushButton* button, mOperatorsGroupBox->findChildren<QPushButton *>() )
62  {
63  connect( button, SIGNAL( pressed() ), this, SLOT( operatorButtonClicked() ) );
64  }
65 
66  txtSearchEdit->setPlaceholderText( tr( "Search" ) );
67 
68  QSettings settings;
69  splitter->restoreState( settings.value( "/windows/QgsExpressionBuilderWidget/splitter" ).toByteArray() );
70  functionsplit->restoreState( settings.value( "/windows/QgsExpressionBuilderWidget/functionsplitter" ).toByteArray() );
71 
72  txtExpressionString->setFoldingVisible( false );
73 
74  updateFunctionTree();
75 
77  {
78  QgsPythonRunner::eval( "qgis.user.expressionspath", mFunctionsPath );
80  // The scratch file gets written each time the widget opens.
81  saveFunctionFile( "scratch" );
82  updateFunctionFileList( mFunctionsPath );
83  }
84  else
85  {
86  tab_2->setEnabled( false );
87  }
88 
89  // select the first item in the function list
90  // in order to avoid a blank help widget
91  QModelIndex firstItem = mProxyModel->index( 0, 0, QModelIndex() );
92  expressionTree->setCurrentIndex( firstItem );
93 }
94 
95 
97 {
98  QSettings settings;
99  settings.setValue( "/windows/QgsExpressionBuilderWidget/splitter", splitter->saveState() );
100  settings.setValue( "/windows/QgsExpressionBuilderWidget/functionsplitter", functionsplit->saveState() );
101 
102  delete mModel;
103  delete mProxyModel;
104 }
105 
107 {
108  mLayer = layer;
109 
110  //TODO - remove existing layer scope from context
111 
112  if ( mLayer )
113  mExpressionContext << QgsExpressionContextUtils::layerScope( mLayer );
114 }
115 
117 {
118  // Get the item
119  QModelIndex idx = mProxyModel->mapToSource( index );
120  QgsExpressionItem* item = dynamic_cast<QgsExpressionItem*>( mModel->itemFromIndex( idx ) );
121  if ( !item )
122  return;
123 
124  mValueListWidget->clear();
125  if ( item->getItemType() == QgsExpressionItem::Field && mFieldValues.contains( item->text() ) )
126  {
127  const QStringList& values = mFieldValues[item->text()];
128  mValueListWidget->setUpdatesEnabled( false );
129  mValueListWidget->blockSignals( true );
130  mValueListWidget->addItems( values );
131  mValueListWidget->setUpdatesEnabled( true );
132  mValueListWidget->blockSignals( false );
133  }
134 
135  mLoadGroupBox->setVisible( item->getItemType() == QgsExpressionItem::Field && mLayer );
136  mValueGroupBox->setVisible(( item->getItemType() == QgsExpressionItem::Field && mLayer ) || mValueListWidget->count() > 0 );
137 
138  // Show the help for the current item.
139  QString help = loadFunctionHelp( item );
140  txtHelpText->setText( help );
141  txtHelpText->setToolTip( txtHelpText->toPlainText() );
142 }
143 
145 {
146  saveFunctionFile( cmbFileNames->currentText() );
147  runPythonCode( txtPython->text() );
148 }
149 
150 void QgsExpressionBuilderWidget::runPythonCode( QString code )
151 {
152  if ( QgsPythonRunner::isValid() )
153  {
154  QString pythontext = code;
155  QgsPythonRunner::run( pythontext );
156  }
157  updateFunctionTree();
158  loadFieldNames();
159  loadRecent( mRecentKey );
160 }
161 
163 {
164  QDir myDir( mFunctionsPath );
165  if ( !myDir.exists() )
166  {
167  myDir.mkpath( mFunctionsPath );
168  }
169 
170  if ( !fileName.endsWith( ".py" ) )
171  {
172  fileName.append( ".py" );
173  }
174 
175  fileName = mFunctionsPath + QDir::separator() + fileName;
176  QFile myFile( fileName );
177  if ( myFile.open( QIODevice::WriteOnly ) )
178  {
179  QTextStream myFileStream( &myFile );
180  myFileStream << txtPython->text() << endl;
181  myFile.close();
182  }
183 }
184 
186 {
187  mFunctionsPath = path;
188  QDir dir( path );
189  dir.setNameFilters( QStringList() << "*.py" );
190  QStringList files = dir.entryList( QDir::Files );
191  cmbFileNames->clear();
192  foreach ( QString name, files )
193  {
194  QFileInfo info( mFunctionsPath + QDir::separator() + name );
195  if ( info.baseName() == "__init__" ) continue;
196  cmbFileNames->addItem( info.baseName() );
197  }
198 }
199 
201 {
202  QString templatetxt;
203  QgsPythonRunner::eval( "qgis.user.expressions.template", templatetxt );
204  txtPython->setText( templatetxt );
205  int index = cmbFileNames->findText( fileName );
206  if ( index == -1 )
207  cmbFileNames->setEditText( fileName );
208  else
209  cmbFileNames->setCurrentIndex( index );
210 }
211 
213 {
214  newFunctionFile();
215 }
216 
218 {
219  if ( index == -1 )
220  return;
221 
222  QString path = mFunctionsPath + QDir::separator() + cmbFileNames->currentText();
223  loadCodeFromFile( path );
224 }
225 
227 {
228  if ( !path.endsWith( ".py" ) )
229  path.append( ".py" );
230 
231  txtPython->loadScript( path );
232 }
233 
235 {
236  txtPython->setText( code );
237 }
238 
240 {
241  QString name = cmbFileNames->currentText();
242  saveFunctionFile( name );
243  int index = cmbFileNames->findText( name );
244  if ( index == -1 )
245  {
246  cmbFileNames->addItem( name );
247  cmbFileNames->setCurrentIndex( cmbFileNames->count() - 1 );
248  }
249 }
250 
252 {
253  QModelIndex idx = mProxyModel->mapToSource( index );
254  QgsExpressionItem* item = dynamic_cast<QgsExpressionItem*>( mModel->itemFromIndex( idx ) );
255  if ( item == 0 )
256  return;
257 
258  // Don't handle the double click it we are on a header node.
259  if ( item->getItemType() == QgsExpressionItem::Header )
260  return;
261 
262  // Insert the expression text or replace selected text
263  txtExpressionString->insertText( item->getExpressionText() );
264  txtExpressionString->setFocus();
265 }
266 
268 {
269  // TODO We should really return a error the user of the widget that
270  // the there is no layer set.
271  if ( !mLayer )
272  return;
273 
274  loadFieldNames( mLayer->fields() );
275 }
276 
278 {
279  if ( fields.isEmpty() )
280  return;
281 
282  QStringList fieldNames;
283  //foreach ( const QgsField& field, fields )
284  for ( int i = 0; i < fields.count(); ++i )
285  {
286  QString fieldName = fields[i].name();
287  fieldNames << fieldName;
288  registerItem( "Fields and Values", fieldName, " \"" + fieldName + "\" ", "", QgsExpressionItem::Field, false, i );
289  }
290 // highlighter->addFields( fieldNames );
291 }
292 
294 {
295  QgsFields fields;
296  foreach ( const QString& fieldName, fieldValues.keys() )
297  {
298  fields.append( QgsField( fieldName ) );
299  }
300  loadFieldNames( fields );
301  mFieldValues = fieldValues;
302 }
303 
304 void QgsExpressionBuilderWidget::fillFieldValues( const QString& fieldName, int countLimit )
305 {
306  // TODO We should really return a error the user of the widget that
307  // the there is no layer set.
308  if ( !mLayer )
309  return;
310 
311  // TODO We should thread this so that we don't hold the user up if the layer is massive.
312  mValueListWidget->clear();
313 
314  int fieldIndex = mLayer->fieldNameIndex( fieldName );
315 
316  if ( fieldIndex < 0 )
317  return;
318 
319  mValueListWidget->setUpdatesEnabled( false );
320  mValueListWidget->blockSignals( true );
321 
322  QList<QVariant> values;
323  QStringList strValues;
324  mLayer->uniqueValues( fieldIndex, values, countLimit );
325  foreach ( QVariant value, values )
326  {
327  QString strValue;
328  if ( value.isNull() )
329  strValue = "NULL";
330  else if ( value.type() == QVariant::Int || value.type() == QVariant::Double || value.type() == QVariant::LongLong )
331  strValue = value.toString();
332  else
333  strValue = "'" + value.toString().replace( "'", "''" ) + "'";
334  mValueListWidget->addItem( strValue );
335  strValues.append( strValue );
336  }
337  mFieldValues[fieldName] = strValues;
338 
339  mValueListWidget->setUpdatesEnabled( true );
340  mValueListWidget->blockSignals( false );
341 }
342 
344  QString label,
345  QString expressionText,
346  QString helpText,
347  QgsExpressionItem::ItemType type, bool highlightedItem, int sortOrder )
348 {
349  QgsExpressionItem* item = new QgsExpressionItem( label, expressionText, helpText, type );
350  item->setData( label, Qt::UserRole );
351  item->setData( sortOrder, QgsExpressionItem::CustomSortRole );
352 
353  // Look up the group and insert the new function.
354  if ( mExpressionGroups.contains( group ) )
355  {
356  QgsExpressionItem *groupNode = mExpressionGroups.value( group );
357  groupNode->appendRow( item );
358  }
359  else
360  {
361  // If the group doesn't exist yet we make it first.
363  newgroupNode->setData( group, Qt::UserRole );
364  newgroupNode->setData( group == "Recent (Selection)" ? 2 : 1, QgsExpressionItem::CustomSortRole );
365  newgroupNode->appendRow( item );
366  mModel->appendRow( newgroupNode );
367  mExpressionGroups.insert( group, newgroupNode );
368  }
369 
370  if ( highlightedItem )
371  {
372  //insert a copy as a top level item
373  QgsExpressionItem* topLevelItem = new QgsExpressionItem( label, expressionText, helpText, type );
374  topLevelItem->setData( label, Qt::UserRole );
376  QFont font = topLevelItem->font();
377  font.setBold( true );
378  topLevelItem->setFont( font );
379  mModel->appendRow( topLevelItem );
380  }
381 
382 }
383 
385 {
386  return mExpressionValid;
387 }
388 
390 {
391  QSettings settings;
392  QString location = QString( "/expressions/recent/%1" ).arg( key );
393  QStringList expressions = settings.value( location ).toStringList();
394  expressions.removeAll( this->expressionText() );
395 
396  expressions.prepend( this->expressionText() );
397 
398  while ( expressions.count() > 20 )
399  {
400  expressions.pop_back();
401  }
402 
403  settings.setValue( location, expressions );
404  this->loadRecent( key );
405 }
406 
408 {
409  mRecentKey = key;
410  QString name = tr( "Recent (%1)" ).arg( key );
411  if ( mExpressionGroups.contains( name ) )
412  {
413  QgsExpressionItem* node = mExpressionGroups.value( name );
414  node->removeRows( 0, node->rowCount() );
415  }
416 
417  QSettings settings;
418  QString location = QString( "/expressions/recent/%1" ).arg( key );
419  QStringList expressions = settings.value( location ).toStringList();
420  foreach ( QString expression, expressions )
421  {
422  this->registerItem( name, expression, expression, expression );
423  }
424 }
425 
426 void QgsExpressionBuilderWidget::updateFunctionTree()
427 {
428  mModel->clear();
429  mExpressionGroups.clear();
430  // TODO Can we move this stuff to QgsExpression, like the functions?
431  registerItem( "Operators", "+", " + ", tr( "Addition operator" ) );
432  registerItem( "Operators", "-", " - ", tr( "Subtraction operator" ) );
433  registerItem( "Operators", "*", " * ", tr( "Multiplication operator" ) );
434  registerItem( "Operators", "/", " / ", tr( "Division operator" ) );
435  registerItem( "Operators", "%", " % ", tr( "Modulo operator" ) );
436  registerItem( "Operators", "^", " ^ ", tr( "Power operator" ) );
437  registerItem( "Operators", "=", " = ", tr( "Equal operator" ) );
438  registerItem( "Operators", ">", " > ", tr( "Greater as operator" ) );
439  registerItem( "Operators", "<", " < ", tr( "Less than operator" ) );
440  registerItem( "Operators", "<>", " <> ", tr( "Unequal operator" ) );
441  registerItem( "Operators", "<=", " <= ", tr( "Less or equal operator" ) );
442  registerItem( "Operators", ">=", " >= ", tr( "Greater or equal operator" ) );
443  registerItem( "Operators", "||", " || ",
444  QString( "<b>|| %1</b><br><i>%2</i><br><i>%3:</i>%4" )
445  .arg( tr( "(String Concatenation)" ) )
446  .arg( tr( "Joins two values together into a string" ) )
447  .arg( tr( "Usage" ) )
448  .arg( tr( "'Dia' || Diameter" ) ) );
449  registerItem( "Operators", "IN", " IN " );
450  registerItem( "Operators", "LIKE", " LIKE " );
451  registerItem( "Operators", "ILIKE", " ILIKE " );
452  registerItem( "Operators", "IS", " IS " );
453  registerItem( "Operators", "OR", " OR " );
454  registerItem( "Operators", "AND", " AND " );
455  registerItem( "Operators", "NOT", " NOT " );
456 
457  QString casestring = "CASE WHEN condition THEN result END";
458  QString caseelsestring = "CASE WHEN condition THEN result ELSE result END";
459  registerItem( "Conditionals", "CASE", casestring );
460  registerItem( "Conditionals", "CASE ELSE", caseelsestring );
461 
462  registerItem( "Fields and Values", "NULL", "NULL" );
463 
464  // Load the functions from the QgsExpression class
465  int count = QgsExpression::functionCount();
466  for ( int i = 0; i < count; i++ )
467  {
469  QString name = func->name();
470  if ( name.startsWith( "_" ) ) // do not display private functions
471  continue;
472  if ( func->isContextual() )
473  {
474  //don't show contextual functions by default - it's up the the QgsExpressionContext
475  //object to provide them if supported
476  continue;
477  }
478  if ( func->params() != 0 )
479  name += "(";
480  else if ( !name.startsWith( "$" ) )
481  name += "()";
482  registerItem( func->group(), func->name(), " " + name + " ", func->helptext() );
483  }
484 
486  for ( int i = 0; i < specials.size(); ++i )
487  {
488  QString name = specials[i]->name();
489  registerItem( specials[i]->group(), name, " " + name + " " );
490  }
491 
492  loadExpressionContext();
493 }
494 
496 {
497  mDa = da;
498 }
499 
501 {
502  return txtExpressionString->text();
503 }
504 
506 {
507  txtExpressionString->setText( expression );
508 }
509 
511 {
512  mExpressionContext = context;
513 
514  loadExpressionContext();
515 }
516 
518 {
519  QString text = expressionText();
520 
521  // If the string is empty the expression will still "fail" although
522  // we don't show the user an error as it will be confusing.
523  if ( text.isEmpty() )
524  {
525  lblPreview->setText( "" );
526  lblPreview->setStyleSheet( "" );
527  txtExpressionString->setToolTip( "" );
528  lblPreview->setToolTip( "" );
529  emit expressionParsed( false );
530  return;
531  }
532 
533  QgsExpression exp( text );
534 
535  if ( mLayer )
536  {
537  // Only set calculator if we have layer, else use default.
538  exp.setGeomCalculator( mDa );
539 
540  if ( !mFeature.isValid() )
541  {
542  mLayer->getFeatures().nextFeature( mFeature );
543  }
544 
545  if ( mFeature.isValid() )
546  {
547  mExpressionContext.setFeature( mFeature );
548  QVariant value = exp.evaluate( &mExpressionContext );
549  if ( !exp.hasEvalError() )
550  lblPreview->setText( formatPreviewString( value.toString() ) );
551  }
552  else
553  {
554  // The feature is invalid because we don't have one but that doesn't mean user can't
555  // build a expression string. They just get no preview.
556  lblPreview->setText( "" );
557  }
558  }
559  else
560  {
561  // No layer defined
562  QVariant value = exp.evaluate( &mExpressionContext );
563  if ( !exp.hasEvalError() )
564  {
565  lblPreview->setText( formatPreviewString( value.toString() ) );
566  }
567  }
568 
569  if ( exp.hasParserError() || exp.hasEvalError() )
570  {
571  QString tooltip = QString( "<b>%1:</b><br>%2" ).arg( tr( "Parser Error" ) ).arg( exp.parserErrorString() );
572  if ( exp.hasEvalError() )
573  tooltip += QString( "<br><br><b>%1:</b><br>%2" ).arg( tr( "Eval Error" ) ).arg( exp.evalErrorString() );
574 
575  lblPreview->setText( tr( "Expression is invalid <a href=""more"">(more info)</a>" ) );
576  lblPreview->setStyleSheet( "color: rgba(255, 6, 10, 255);" );
577  txtExpressionString->setToolTip( tooltip );
578  lblPreview->setToolTip( tooltip );
579  emit expressionParsed( false );
580  return;
581  }
582  else
583  {
584  lblPreview->setStyleSheet( "" );
585  txtExpressionString->setToolTip( "" );
586  lblPreview->setToolTip( "" );
587  emit expressionParsed( true );
588  }
589 }
590 
591 QString QgsExpressionBuilderWidget::formatPreviewString( const QString& previewString ) const
592 {
593  if ( previewString.length() > 63 )
594  {
595  return QString( tr( "%1..." ) ).arg( previewString.left( 60 ) );
596  }
597  else
598  {
599  return previewString;
600  }
601 }
602 
603 void QgsExpressionBuilderWidget::loadExpressionContext()
604 {
605  QStringList variableNames = mExpressionContext.filteredVariableNames();
606  Q_FOREACH ( QString variable, variableNames )
607  {
608  registerItem( "Variables", variable, " @" + variable + " ",
609  QgsExpression::variableHelpText( variable, true, mExpressionContext.variable( variable ) ),
611  mExpressionContext.isHighlightedVariable( variable ) );
612  }
613 
614  // Load the functions from the expression context
615  QStringList contextFunctions = mExpressionContext.functionNames();
616  Q_FOREACH ( QString functionName, contextFunctions )
617  {
618  QgsExpression::Function* func = mExpressionContext.function( functionName );
619  QString name = func->name();
620  if ( name.startsWith( "_" ) ) // do not display private functions
621  continue;
622  if ( func->params() != 0 )
623  name += "(";
624  registerItem( func->group(), func->name(), " " + name + " ", func->helptext() );
625  }
626 }
627 
629 {
630  mProxyModel->setFilterWildcard( txtSearchEdit->text() );
631  if ( txtSearchEdit->text().isEmpty() )
632  expressionTree->collapseAll();
633  else
634  expressionTree->expandAll();
635 }
636 
638 {
639  Q_UNUSED( link );
640  QgsMessageViewer * mv = new QgsMessageViewer( this );
641  mv->setWindowTitle( tr( "More info on expression error" ) );
642  mv->setMessageAsHtml( txtExpressionString->toolTip() );
643  mv->exec();
644 }
645 
647 {
648  // Insert the item text or replace selected text
649  txtExpressionString->insertText( " " + item->text() + " " );
650  txtExpressionString->setFocus();
651 }
652 
654 {
655  QPushButton* button = dynamic_cast<QPushButton*>( sender() );
656 
657  // Insert the button text or replace selected text
658  txtExpressionString->insertText( " " + button->text() + " " );
659  txtExpressionString->setFocus();
660 }
661 
663 {
664  QModelIndex idx = expressionTree->indexAt( pt );
665  idx = mProxyModel->mapToSource( idx );
666  QgsExpressionItem* item = dynamic_cast<QgsExpressionItem*>( mModel->itemFromIndex( idx ) );
667  if ( !item )
668  return;
669 
670  if ( item->getItemType() == QgsExpressionItem::Field && mLayer )
671  {
672  QMenu* menu = new QMenu( this );
673  menu->addAction( tr( "Load top 10 unique values" ), this, SLOT( loadSampleValues() ) );
674  menu->addAction( tr( "Load all unique values" ), this, SLOT( loadAllValues() ) );
675  menu->popup( expressionTree->mapToGlobal( pt ) );
676  }
677 }
678 
680 {
681  QModelIndex idx = mProxyModel->mapToSource( expressionTree->currentIndex() );
682  QgsExpressionItem* item = dynamic_cast<QgsExpressionItem*>( mModel->itemFromIndex( idx ) );
683  // TODO We should really return a error the user of the widget that
684  // the there is no layer set.
685  if ( !mLayer || !item )
686  return;
687 
688  mValueGroupBox->show();
689  fillFieldValues( item->text(), 10 );
690 }
691 
693 {
694  QModelIndex idx = mProxyModel->mapToSource( expressionTree->currentIndex() );
695  QgsExpressionItem* item = dynamic_cast<QgsExpressionItem*>( mModel->itemFromIndex( idx ) );
696  // TODO We should really return a error the user of the widget that
697  // the there is no layer set.
698  if ( !mLayer || !item )
699  return;
700 
701  mValueGroupBox->show();
702  fillFieldValues( item->text(), -1 );
703 }
704 
705 void QgsExpressionBuilderWidget::setExpressionState( bool state )
706 {
707  mExpressionValid = state;
708 }
709 
710 QString QgsExpressionBuilderWidget::loadFunctionHelp( QgsExpressionItem* expressionItem )
711 {
712  if ( !expressionItem )
713  return "";
714 
715  QString helpContents = expressionItem->getHelpText();
716 
717  // Return the function help that is set for the function if there is one.
718  if ( helpContents.isEmpty() )
719  {
720  QString name = expressionItem->data( Qt::UserRole ).toString();
721 
722  if ( expressionItem->getItemType() == QgsExpressionItem::Field )
723  helpContents = QgsExpression::helptext( "Field" );
724  else
725  helpContents = QgsExpression::helptext( name );
726  }
727 
729  return "<head><style>" + myStyle + "</style></head><body>" + helpContents + "</body>";
730 }
731 
732 
733 
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:88
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
void clear()
bool isHighlightedVariable(const QString &name) const
Returns true if the specified variable name is intended to be highlighted to the user.
QByteArray toByteArray() const
static unsigned index
void saveFunctionFile(QString fileName)
Save the current function editor text to the given file.
QString getExpressionText() const
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:95
bool contains(const Key &key) const
void setNameFilters(const QStringList &nameFilters)
Q_DECL_DEPRECATED QVariant evaluate(const QgsFeature *f)
Evaluate the feature and return the result.
QString getHelpText() const
Get the help text that is associated with this expression item.
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:168
static const int CustomSortRole
Custom sort order role.
A abstract base class for defining QgsExpression functions.
virtual void setSourceModel(QAbstractItemModel *sourceModel)
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
QgsFields fields() const
Returns the list of fields of this layer.
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)
Returns the help text for a specified function.
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:177
static QString group(QString group)
Returns the translated name for a function 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.
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
int size() const
virtual void setData(const QVariant &value, int role)
void setBold(bool enable)
static const QList< Function * > & Functions()
QList< T > findChildren(const QString &name) const
QList< Key > keys() const
void setMessageAsHtml(const QString &msg)
void setValue(const QString &key, const QVariant &value)
void registerItem(QString group, QString label, QString expressionText, QString helpText="", QgsExpressionItem::ItemType type=QgsExpressionItem::ExpressionNode, bool highlightedItem=false, int sortOrder=1)
Registers a node item for the expression builder.
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
void append(const T &value)
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 isContextual() const
Returns whether the function is only available if provided by a QgsExpressionContext object...
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
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.
void setDynamicSortFilter(bool enable)
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Append a field. The field must have unique name, otherwise it is rejected (returns false) ...
Definition: qgsfield.cpp:235
int count() const
Return number of items.
Definition: qgsfield.cpp:285
void on_expressionTree_doubleClicked(const QModelIndex &index)
void loadFieldNames()
Loads all the field names from the layer.
QStringList functionNames() const
Retrieves a list of function names contained in the context.
void removeRows(int row, int count)
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:40
QString name()
The name of the function.
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
void pop_back()
void setFont(const QFont &font)
void newFunctionFile(QString fileName="scratch")
Create a new file in the function editor.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context for the widget.
const QFont & font() const
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 &)
QFont font() const
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.
void loadFieldsAndValues(const QMap< QString, QStringList > &fieldValues)
Loads field names and values from the specified map.
int params()
The number of parameters this function takes.
QStringList filteredVariableNames() const
Returns a filtered list of variables names set by all scopes in the context.
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.
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)
static QString variableHelpText(const QString &variableName, bool showValue=true, const QVariant &value=QVariant())
Returns the help text for a specified variable.
iterator insert(const Key &key, const T &value)
QgsExpression::Function * function(const QString &name) const
Fetches a matching function from the context.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
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:280
QString parserErrorString() const
Returns parser error.
Definition: qgsexpression.h:97
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
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
QgsExpressionItem::ItemType getItemType() const
Get the type of expression item eg header, field, ExpressionNode.
const T value(const Key &key) const