QGIS API Documentation  2.12.0-Lyon
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  Q_FOREACH ( QPushButton* button, mOperatorsGroupBox->findChildren<QPushButton *>() )
62  {
63  connect( button, SIGNAL( pressed() ), this, SLOT( operatorButtonClicked() ) );
64  }
65 
66  txtSearchEdit->setPlaceholderText( tr( "Search" ) );
67 
68  mValuesModel = new QStringListModel();
69  mProxyValues = new QSortFilterProxyModel();
70  mProxyValues->setSourceModel( mValuesModel );
71  mValuesListView->setModel( mProxyValues );
72  txtSearchEditValues->setPlaceholderText( tr( "Search" ) );
73 
74  QSettings settings;
75  splitter->restoreState( settings.value( "/windows/QgsExpressionBuilderWidget/splitter" ).toByteArray() );
76  functionsplit->restoreState( settings.value( "/windows/QgsExpressionBuilderWidget/functionsplitter" ).toByteArray() );
77 
78  txtExpressionString->setFoldingVisible( false );
79 
80  updateFunctionTree();
81 
83  {
84  QgsPythonRunner::eval( "qgis.user.expressionspath", mFunctionsPath );
86  // The scratch file gets written each time the widget opens.
87  saveFunctionFile( "scratch" );
88  updateFunctionFileList( mFunctionsPath );
89  }
90  else
91  {
92  tab_2->setEnabled( false );
93  }
94 
95  // select the first item in the function list
96  // in order to avoid a blank help widget
97  QModelIndex firstItem = mProxyModel->index( 0, 0, QModelIndex() );
98  expressionTree->setCurrentIndex( firstItem );
99 }
100 
101 
103 {
104  QSettings settings;
105  settings.setValue( "/windows/QgsExpressionBuilderWidget/splitter", splitter->saveState() );
106  settings.setValue( "/windows/QgsExpressionBuilderWidget/functionsplitter", functionsplit->saveState() );
107 
108  delete mModel;
109  delete mProxyModel;
110  delete mValuesModel;
111  delete mProxyValues;
112 }
113 
115 {
116  mLayer = layer;
117 
118  //TODO - remove existing layer scope from context
119 
120  if ( mLayer )
121  mExpressionContext << QgsExpressionContextUtils::layerScope( mLayer );
122 }
123 
125 {
126  txtSearchEditValues->setText( QString( "" ) );
127 
128  // Get the item
129  QModelIndex idx = mProxyModel->mapToSource( index );
130  QgsExpressionItem* item = dynamic_cast<QgsExpressionItem*>( mModel->itemFromIndex( idx ) );
131  if ( !item )
132  return;
133 
134  if ( item->getItemType() == QgsExpressionItem::Field && mFieldValues.contains( item->text() ) )
135  {
136  const QStringList& values = mFieldValues[item->text()];
137  mValuesModel->setStringList( values );
138  }
139 
140  mLoadGroupBox->setVisible( item->getItemType() == QgsExpressionItem::Field && mLayer );
141  mValueGroupBox->setVisible(( item->getItemType() == QgsExpressionItem::Field && mLayer ) || mValuesListView->model()->rowCount() > 0 );
142 
143  // Show the help for the current item.
144  QString help = loadFunctionHelp( item );
145  txtHelpText->setText( help );
146 }
147 
149 {
150  saveFunctionFile( cmbFileNames->currentText() );
151  runPythonCode( txtPython->text() );
152 }
153 
154 void QgsExpressionBuilderWidget::runPythonCode( const QString& code )
155 {
156  if ( QgsPythonRunner::isValid() )
157  {
158  QString pythontext = code;
159  QgsPythonRunner::run( pythontext );
160  }
161  updateFunctionTree();
162  loadFieldNames();
163  loadRecent( mRecentKey );
164 }
165 
167 {
168  QDir myDir( mFunctionsPath );
169  if ( !myDir.exists() )
170  {
171  myDir.mkpath( mFunctionsPath );
172  }
173 
174  if ( !fileName.endsWith( ".py" ) )
175  {
176  fileName.append( ".py" );
177  }
178 
179  fileName = mFunctionsPath + QDir::separator() + fileName;
180  QFile myFile( fileName );
181  if ( myFile.open( QIODevice::WriteOnly ) )
182  {
183  QTextStream myFileStream( &myFile );
184  myFileStream << txtPython->text() << endl;
185  myFile.close();
186  }
187 }
188 
190 {
191  mFunctionsPath = path;
192  QDir dir( path );
193  dir.setNameFilters( QStringList() << "*.py" );
194  QStringList files = dir.entryList( QDir::Files );
195  cmbFileNames->clear();
196  Q_FOREACH ( const QString& name, files )
197  {
198  QFileInfo info( mFunctionsPath + QDir::separator() + name );
199  if ( info.baseName() == "__init__" ) continue;
200  cmbFileNames->addItem( info.baseName() );
201  }
202 }
203 
205 {
206  QString templatetxt;
207  QgsPythonRunner::eval( "qgis.user.expressions.template", templatetxt );
208  txtPython->setText( templatetxt );
209  int index = cmbFileNames->findText( fileName );
210  if ( index == -1 )
211  cmbFileNames->setEditText( fileName );
212  else
213  cmbFileNames->setCurrentIndex( index );
214 }
215 
217 {
218  newFunctionFile();
219 }
220 
222 {
223  if ( index == -1 )
224  return;
225 
226  QString path = mFunctionsPath + QDir::separator() + cmbFileNames->currentText();
227  loadCodeFromFile( path );
228 }
229 
231 {
232  if ( !path.endsWith( ".py" ) )
233  path.append( ".py" );
234 
235  txtPython->loadScript( path );
236 }
237 
239 {
240  txtPython->setText( code );
241 }
242 
244 {
245  QString name = cmbFileNames->currentText();
246  saveFunctionFile( name );
247  int index = cmbFileNames->findText( name );
248  if ( index == -1 )
249  {
250  cmbFileNames->addItem( name );
251  cmbFileNames->setCurrentIndex( cmbFileNames->count() - 1 );
252  }
253 }
254 
256 {
257  QModelIndex idx = mProxyModel->mapToSource( index );
258  QgsExpressionItem* item = dynamic_cast<QgsExpressionItem*>( mModel->itemFromIndex( idx ) );
259  if ( item == 0 )
260  return;
261 
262  // Don't handle the double click it we are on a header node.
263  if ( item->getItemType() == QgsExpressionItem::Header )
264  return;
265 
266  // Insert the expression text or replace selected text
267  txtExpressionString->insertText( item->getExpressionText() );
268  txtExpressionString->setFocus();
269 }
270 
272 {
273  // TODO We should really return a error the user of the widget that
274  // the there is no layer set.
275  if ( !mLayer )
276  return;
277 
278  loadFieldNames( mLayer->fields() );
279 }
280 
282 {
283  if ( fields.isEmpty() )
284  return;
285 
286  QStringList fieldNames;
287  //Q_FOREACH ( const QgsField& field, fields )
288  fieldNames.reserve( fields.count() );
289  for ( int i = 0; i < fields.count(); ++i )
290  {
291  QString fieldName = fields[i].name();
292  fieldNames << fieldName;
293  registerItem( "Fields and Values", fieldName, " \"" + fieldName + "\" ", "", QgsExpressionItem::Field, false, i );
294  }
295 // highlighter->addFields( fieldNames );
296 }
297 
299 {
300  QgsFields fields;
301  Q_FOREACH ( const QString& fieldName, fieldValues.keys() )
302  {
303  fields.append( QgsField( fieldName ) );
304  }
305  loadFieldNames( fields );
306  mFieldValues = fieldValues;
307 }
308 
309 void QgsExpressionBuilderWidget::fillFieldValues( const QString& fieldName, int countLimit )
310 {
311  // TODO We should really return a error the user of the widget that
312  // the there is no layer set.
313  if ( !mLayer )
314  return;
315 
316  // TODO We should thread this so that we don't hold the user up if the layer is massive.
317 
318  int fieldIndex = mLayer->fieldNameIndex( fieldName );
319 
320  if ( fieldIndex < 0 )
321  return;
322 
323  QList<QVariant> values;
324  QStringList strValues;
325  mLayer->uniqueValues( fieldIndex, values, countLimit );
326  Q_FOREACH ( const QVariant& value, values )
327  {
328  QString strValue;
329  if ( value.isNull() )
330  strValue = "NULL";
331  else if ( value.type() == QVariant::Int || value.type() == QVariant::Double || value.type() == QVariant::LongLong )
332  strValue = value.toString();
333  else
334  strValue = "'" + value.toString().replace( "'", "''" ) + "'";
335  strValues.append( strValue );
336  }
337  mValuesModel->setStringList( strValues );
338  mFieldValues[fieldName] = strValues;
339 }
340 
342  const QString& label,
343  const QString& expressionText,
344  const QString& helpText,
345  QgsExpressionItem::ItemType type, bool highlightedItem, int sortOrder )
346 {
347  QgsExpressionItem* item = new QgsExpressionItem( label, expressionText, helpText, type );
348  item->setData( label, Qt::UserRole );
349  item->setData( sortOrder, QgsExpressionItem::CustomSortRole );
350 
351  // Look up the group and insert the new function.
352  if ( mExpressionGroups.contains( group ) )
353  {
354  QgsExpressionItem *groupNode = mExpressionGroups.value( group );
355  groupNode->appendRow( item );
356  }
357  else
358  {
359  // If the group doesn't exist yet we make it first.
361  newgroupNode->setData( group, Qt::UserRole );
362  //Recent group should always be last group
363  newgroupNode->setData( group.startsWith( "Recent (" ) ? 2 : 1, QgsExpressionItem::CustomSortRole );
364  newgroupNode->appendRow( item );
365  newgroupNode->setBackground( QBrush( QColor( "#eee" ) ) );
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  int i = 0;
421  Q_FOREACH ( const QString& expression, expressions )
422  {
423  this->registerItem( name, expression, expression, expression, QgsExpressionItem::ExpressionNode, false, i );
424  i++;
425  }
426 }
427 
428 void QgsExpressionBuilderWidget::updateFunctionTree()
429 {
430  mModel->clear();
431  mExpressionGroups.clear();
432  // TODO Can we move this stuff to QgsExpression, like the functions?
433  registerItem( "Operators", "+", " + " );
434  registerItem( "Operators", "-", " - " );
435  registerItem( "Operators", "*", " * " );
436  registerItem( "Operators", "/", " / " );
437  registerItem( "Operators", "%", " % " );
438  registerItem( "Operators", "^", " ^ " );
439  registerItem( "Operators", "=", " = " );
440  registerItem( "Operators", ">", " > " );
441  registerItem( "Operators", "<", " < " );
442  registerItem( "Operators", "<>", " <> " );
443  registerItem( "Operators", "<=", " <= " );
444  registerItem( "Operators", ">=", " >= " );
445  registerItem( "Operators", "||", " || " );
446  registerItem( "Operators", "IN", " IN " );
447  registerItem( "Operators", "LIKE", " LIKE " );
448  registerItem( "Operators", "ILIKE", " ILIKE " );
449  registerItem( "Operators", "IS", " IS " );
450  registerItem( "Operators", "OR", " OR " );
451  registerItem( "Operators", "AND", " AND " );
452  registerItem( "Operators", "NOT", " NOT " );
453 
454  QString casestring = "CASE WHEN condition THEN result END";
455  registerItem( "Conditionals", "CASE", casestring );
456 
457  registerItem( "Fields and Values", "NULL", "NULL" );
458 
459  // Load the functions from the QgsExpression class
460  int count = QgsExpression::functionCount();
461  for ( int i = 0; i < count; i++ )
462  {
464  QString name = func->name();
465  if ( name.startsWith( "_" ) ) // do not display private functions
466  continue;
467  if ( func->group() == "deprecated" ) // don't show deprecated functions
468  continue;
469  if ( func->isContextual() )
470  {
471  //don't show contextual functions by default - it's up the the QgsExpressionContext
472  //object to provide them if supported
473  continue;
474  }
475  if ( func->params() != 0 )
476  name += "(";
477  else if ( !name.startsWith( "$" ) )
478  name += "()";
479  registerItem( func->group(), func->name(), " " + name + " ", func->helptext() );
480  }
481 
483  for ( int i = 0; i < specials.size(); ++i )
484  {
485  QString name = specials[i]->name();
486  registerItem( specials[i]->group(), name, " " + name + " " );
487  }
488 
489  loadExpressionContext();
490 }
491 
493 {
494  mDa = da;
495 }
496 
498 {
499  return txtExpressionString->text();
500 }
501 
503 {
504  txtExpressionString->setText( expression );
505 }
506 
508 {
509  mExpressionContext = context;
510 
511  loadExpressionContext();
512 }
513 
515 {
516  QString text = expressionText();
517 
518  // If the string is empty the expression will still "fail" although
519  // we don't show the user an error as it will be confusing.
520  if ( text.isEmpty() )
521  {
522  lblPreview->setText( "" );
523  lblPreview->setStyleSheet( "" );
524  txtExpressionString->setToolTip( "" );
525  lblPreview->setToolTip( "" );
526  emit expressionParsed( false );
527  return;
528  }
529 
530  QgsExpression exp( text );
531 
532  if ( mLayer )
533  {
534  // Only set calculator if we have layer, else use default.
535  exp.setGeomCalculator( mDa );
536 
537  if ( !mFeature.isValid() )
538  {
539  mLayer->getFeatures().nextFeature( mFeature );
540  }
541 
542  if ( mFeature.isValid() )
543  {
544  mExpressionContext.setFeature( mFeature );
545  QVariant value = exp.evaluate( &mExpressionContext );
546  if ( !exp.hasEvalError() )
547  lblPreview->setText( formatPreviewString( value.toString() ) );
548  }
549  else
550  {
551  // The feature is invalid because we don't have one but that doesn't mean user can't
552  // build a expression string. They just get no preview.
553  lblPreview->setText( "" );
554  }
555  }
556  else
557  {
558  // No layer defined
559  QVariant value = exp.evaluate( &mExpressionContext );
560  if ( !exp.hasEvalError() )
561  {
562  lblPreview->setText( formatPreviewString( value.toString() ) );
563  }
564  }
565 
566  if ( exp.hasParserError() || exp.hasEvalError() )
567  {
568  QString tooltip = QString( "<b>%1:</b><br>%2" ).arg( tr( "Parser Error" ), exp.parserErrorString() );
569  if ( exp.hasEvalError() )
570  tooltip += QString( "<br><br><b>%1:</b><br>%2" ).arg( tr( "Eval Error" ), exp.evalErrorString() );
571 
572  lblPreview->setText( tr( "Expression is invalid <a href=""more"">(more info)</a>" ) );
573  lblPreview->setStyleSheet( "color: rgba(255, 6, 10, 255);" );
574  txtExpressionString->setToolTip( tooltip );
575  lblPreview->setToolTip( tooltip );
576  emit expressionParsed( false );
577  return;
578  }
579  else
580  {
581  lblPreview->setStyleSheet( "" );
582  txtExpressionString->setToolTip( "" );
583  lblPreview->setToolTip( "" );
584  emit expressionParsed( true );
585  }
586 }
587 
588 QString QgsExpressionBuilderWidget::formatPreviewString( const QString& previewString ) const
589 {
590  if ( previewString.length() > 63 )
591  {
592  return QString( tr( "%1..." ) ).arg( previewString.left( 60 ) );
593  }
594  else
595  {
596  return previewString;
597  }
598 }
599 
600 void QgsExpressionBuilderWidget::loadExpressionContext()
601 {
602  QStringList variableNames = mExpressionContext.filteredVariableNames();
603  Q_FOREACH ( const QString& variable, variableNames )
604  {
605  registerItem( "Variables", variable, " @" + variable + " ",
606  QgsExpression::variableHelpText( variable, true, mExpressionContext.variable( variable ) ),
608  mExpressionContext.isHighlightedVariable( variable ) );
609  }
610 
611  // Load the functions from the expression context
612  QStringList contextFunctions = mExpressionContext.functionNames();
613  Q_FOREACH ( const QString& functionName, contextFunctions )
614  {
615  QgsExpression::Function* func = mExpressionContext.function( functionName );
616  QString name = func->name();
617  if ( name.startsWith( "_" ) ) // do not display private functions
618  continue;
619  if ( func->params() != 0 )
620  name += "(";
621  registerItem( func->group(), func->name(), " " + name + " ", func->helptext() );
622  }
623 }
624 
626 {
627  mProxyModel->setFilterWildcard( txtSearchEdit->text() );
628  if ( txtSearchEdit->text().isEmpty() )
629  expressionTree->collapseAll();
630  else
631  expressionTree->expandAll();
632 }
633 
635 {
636  mProxyValues->setFilterCaseSensitivity( Qt::CaseInsensitive );
637  mProxyValues->setFilterWildcard( txtSearchEditValues->text() );
638 }
639 
641 {
642  Q_UNUSED( link );
643  QgsMessageViewer * mv = new QgsMessageViewer( this );
644  mv->setWindowTitle( tr( "More info on expression error" ) );
645  mv->setMessageAsHtml( txtExpressionString->toolTip() );
646  mv->exec();
647 }
648 
650 {
651  // Insert the item text or replace selected text
652  txtExpressionString->insertText( " " + index.data( Qt::DisplayRole ).toString() + " " );
653  txtExpressionString->setFocus();
654 }
655 
657 {
658  QPushButton* button = dynamic_cast<QPushButton*>( sender() );
659 
660  // Insert the button text or replace selected text
661  txtExpressionString->insertText( " " + button->text() + " " );
662  txtExpressionString->setFocus();
663 }
664 
666 {
667  QModelIndex idx = expressionTree->indexAt( pt );
668  idx = mProxyModel->mapToSource( idx );
669  QgsExpressionItem* item = dynamic_cast<QgsExpressionItem*>( mModel->itemFromIndex( idx ) );
670  if ( !item )
671  return;
672 
673  if ( item->getItemType() == QgsExpressionItem::Field && mLayer )
674  {
675  QMenu* menu = new QMenu( this );
676  menu->addAction( tr( "Load top 10 unique values" ), this, SLOT( loadSampleValues() ) );
677  menu->addAction( tr( "Load all unique values" ), this, SLOT( loadAllValues() ) );
678  menu->popup( expressionTree->mapToGlobal( pt ) );
679  }
680 }
681 
683 {
684  QModelIndex idx = mProxyModel->mapToSource( expressionTree->currentIndex() );
685  QgsExpressionItem* item = dynamic_cast<QgsExpressionItem*>( mModel->itemFromIndex( idx ) );
686  // TODO We should really return a error the user of the widget that
687  // the there is no layer set.
688  if ( !mLayer || !item )
689  return;
690 
691  mValueGroupBox->show();
692  fillFieldValues( item->text(), 10 );
693 }
694 
696 {
697  QModelIndex idx = mProxyModel->mapToSource( expressionTree->currentIndex() );
698  QgsExpressionItem* item = dynamic_cast<QgsExpressionItem*>( mModel->itemFromIndex( idx ) );
699  // TODO We should really return a error the user of the widget that
700  // the there is no layer set.
701  if ( !mLayer || !item )
702  return;
703 
704  mValueGroupBox->show();
705  fillFieldValues( item->text(), -1 );
706 }
707 
708 void QgsExpressionBuilderWidget::setExpressionState( bool state )
709 {
710  mExpressionValid = state;
711 }
712 
713 QString QgsExpressionBuilderWidget::helpStylesheet() const
714 {
715  //start with default QGIS report style
717 
718  //add some tweaks
719  style += " .functionname {color: #0a6099; font-weight: bold;} "
720  " .argument {font-family: monospace; color: #bf0c0c; font-style: italic; } "
721  " td.argument { padding-right: 10px; }";
722 
723  return style;
724 }
725 
726 QString QgsExpressionBuilderWidget::loadFunctionHelp( QgsExpressionItem* expressionItem )
727 {
728  if ( !expressionItem )
729  return "";
730 
731  QString helpContents = expressionItem->getHelpText();
732 
733  // Return the function help that is set for the function if there is one.
734  if ( helpContents.isEmpty() )
735  {
736  QString name = expressionItem->data( Qt::UserRole ).toString();
737 
738  if ( expressionItem->getItemType() == QgsExpressionItem::Field )
739  helpContents = QgsExpression::helptext( "Field" );
740  else
741  helpContents = QgsExpression::helptext( name );
742  }
743 
744  return "<head><style>" + helpStylesheet() + "</style></head><body>" + helpContents + "</body>";
745 }
746 
747 
748 
void customContextMenuRequested(const QPoint &pos)
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const
void registerItem(const QString &group, const QString &label, const QString &expressionText, const QString &helpText="", QgsExpressionItem::ItemType type=QgsExpressionItem::ExpressionNode, bool highlightedItem=false, int sortOrder=1)
Registers a node item for the expression builder.
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:92
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 setFilterCaseSensitivity(Qt::CaseSensitivity cs)
void setupUi(QWidget *widget)
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
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:170
static QString group(const QString &group)
Returns the translated name for a function group.
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 setBackground(const QBrush &brush)
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
void reserve(int alloc)
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
QStyle * style() const
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)
int exec()
void on_lblPreview_linkActivated(const QString &link)
Container of fields for a vector layer.
Definition: qgsfield.h:177
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 loadFunctionCode(const QString &code)
Load code into the function editor.
void loadCodeFromFile(QString path)
Load code from the given file into the function editor.
void newFunctionFile(const QString &fileName="scratch")
Create a new file in 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 updateFunctionFileList(const QString &path)
Update the list of function files found at the given path.
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 on_mValuesListView_doubleClicked(const QModelIndex &index)
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
void append(const T &value)
Search proxy used to filter the QgsExpressionBuilderWidget tree.
void popup(const QPoint &p, QAction *atAction)
bool isNull() const
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 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:261
int count() const
Return number of items.
Definition: qgsfield.cpp:311
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 setExpressionContext(const QgsExpressionContext &context)
Sets the expression context for the widget.
static bool eval(const QString &command, QString &result)
Eval a python statement.
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
QVariant data(int role) const
QString group()
The group the function belongs to.
static bool run(const QString &command, const QString &messageOnError=QString())
Execute a python statement.
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:306
QString parserErrorString() const
Returns parser error.
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
void setStringList(const QStringList &strings)
virtual QVariant data(int role) 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