26 #include <QTextStream> 35 , mExpressionValid( false )
39 mValueGroupBox->hide();
40 mLoadGroupBox->hide();
43 mModel =
new QStandardItemModel();
45 mProxyModel->setSourceModel( mModel );
46 expressionTree->setModel( mProxyModel );
48 expressionTree->setContextMenuPolicy( Qt::CustomContextMenu );
49 connect(
this, SIGNAL(
expressionParsed(
bool ) ),
this, SLOT( setExpressionState(
bool ) ) );
50 connect( expressionTree, SIGNAL( customContextMenuRequested(
const QPoint & ) ),
this, SLOT(
showContextMenu(
const QPoint & ) ) );
51 connect( expressionTree->selectionModel(), SIGNAL(
currentChanged(
const QModelIndex &,
const QModelIndex & ) ),
52 this, SLOT(
currentChanged(
const QModelIndex &,
const QModelIndex & ) ) );
54 connect( btnLoadAll, SIGNAL( pressed() ),
this, SLOT(
loadAllValues() ) );
55 connect( btnLoadSample, SIGNAL( pressed() ),
this, SLOT(
loadSampleValues() ) );
57 foreach ( QPushButton* button, mOperatorsGroupBox->findChildren<QPushButton *>() )
62 txtSearchEdit->setPlaceholderText(
tr(
"Search" ) );
65 splitter->restoreState( settings.value(
"/windows/QgsExpressionBuilderWidget/splitter" ).toByteArray() );
66 functionsplit->restoreState( settings.value(
"/windows/QgsExpressionBuilderWidget/functionsplitter" ).toByteArray() );
68 txtExpressionString->setFoldingVisible(
false );
82 tab_2->setEnabled(
false );
87 QModelIndex firstItem = mProxyModel->index( 0, 0, QModelIndex() );
88 expressionTree->setCurrentIndex( firstItem );
95 settings.setValue(
"/windows/QgsExpressionBuilderWidget/splitter", splitter->saveState() );
96 settings.setValue(
"/windows/QgsExpressionBuilderWidget/functionsplitter", functionsplit->saveState() );
107 QModelIndex idx = mProxyModel->mapToSource( index );
114 mValueListWidget->clear();
121 QString help = loadFunctionHelp( item );
122 txtHelpText->setText( help );
123 txtHelpText->setToolTip( txtHelpText->toPlainText() );
129 runPythonCode( txtPython->text() );
132 void QgsExpressionBuilderWidget::runPythonCode( QString code )
136 QString pythontext = code;
139 updateFunctionTree();
146 QDir myDir( mFunctionsPath );
147 if ( !myDir.exists() )
149 myDir.mkpath( mFunctionsPath );
152 if ( !fileName.endsWith(
".py" ) )
154 fileName.append(
".py" );
157 fileName = mFunctionsPath + QDir::separator() + fileName;
158 QFile myFile( fileName );
159 if ( myFile.open( QIODevice::WriteOnly ) )
161 QTextStream myFileStream( &myFile );
162 myFileStream << txtPython->text() << endl;
169 mFunctionsPath = path;
171 dir.setNameFilters( QStringList() <<
"*.py" );
172 QStringList files = dir.entryList( QDir::Files );
173 cmbFileNames->clear();
174 foreach ( QString name, files )
176 QFileInfo info( mFunctionsPath + QDir::separator() + name );
177 if ( info.baseName() ==
"__init__" )
continue;
178 cmbFileNames->addItem( info.baseName() );
186 txtPython->setText( templatetxt );
187 int index = cmbFileNames->findText( fileName );
189 cmbFileNames->setEditText( fileName );
191 cmbFileNames->setCurrentIndex( index );
204 QString path = mFunctionsPath + QDir::separator() + cmbFileNames->currentText();
210 if ( !path.endsWith(
".py" ) )
211 path.append(
".py" );
213 txtPython->loadScript( path );
218 txtPython->setText( code );
223 QString name = cmbFileNames->currentText();
225 int index = cmbFileNames->findText( name );
228 cmbFileNames->addItem( name );
229 cmbFileNames->setCurrentIndex( cmbFileNames->count() - 1 );
235 QModelIndex idx = mProxyModel->mapToSource( index );
246 txtExpressionString->setFocus();
264 QStringList fieldNames;
266 for (
int i = 0; i < fields.
count(); ++i )
268 QString fieldName = fields[i].name();
269 fieldNames << fieldName;
275 void QgsExpressionBuilderWidget::fillFieldValues(
int fieldIndex,
int countLimit )
283 mValueListWidget->clear();
285 if ( fieldIndex < 0 )
288 mValueListWidget->setUpdatesEnabled(
false );
289 mValueListWidget->blockSignals(
true );
291 QList<QVariant> values;
293 foreach ( QVariant value, values )
295 if ( value.isNull() )
296 mValueListWidget->addItem(
"NULL" );
297 else if ( value.type() == QVariant::Int || value.type() == QVariant::Double || value.type() == QVariant::LongLong )
298 mValueListWidget->addItem( value.toString() );
300 mValueListWidget->addItem(
"'" + value.toString().replace(
"'",
"''" ) +
"'" );
303 mValueListWidget->setUpdatesEnabled(
true );
304 mValueListWidget->blockSignals(
false );
314 item->setData( label, Qt::UserRole );
316 if ( mExpressionGroups.contains( group ) )
319 groupNode->appendRow( item );
325 newgroupNode->setData( group, Qt::UserRole );
326 newgroupNode->appendRow( item );
327 mModel->appendRow( newgroupNode );
328 mExpressionGroups.insert( group, newgroupNode );
334 return mExpressionValid;
340 QString location = QString(
"/expressions/recent/%1" ).arg( key );
341 QStringList expressions = settings.value( location ).toStringList();
346 while ( expressions.count() > 20 )
348 expressions.pop_back();
351 settings.setValue( location, expressions );
358 QString name =
tr(
"Recent (%1)" ).arg( key );
359 if ( mExpressionGroups.contains( name ) )
362 node->removeRows( 0, node->rowCount() );
366 QString location = QString(
"/expressions/recent/%1" ).arg( key );
367 QStringList expressions = settings.value( location ).toStringList();
368 foreach ( QString expression, expressions )
370 this->
registerItem( name, expression, expression, expression );
374 void QgsExpressionBuilderWidget::updateFunctionTree()
377 mExpressionGroups.clear();
379 registerItem(
"Operators",
"+",
" + ",
tr(
"Addition operator" ) );
380 registerItem(
"Operators",
"-",
" - ",
tr(
"Subtraction operator" ) );
381 registerItem(
"Operators",
"*",
" * ",
tr(
"Multiplication operator" ) );
382 registerItem(
"Operators",
"/",
" / ",
tr(
"Division operator" ) );
386 registerItem(
"Operators",
">",
" > ",
tr(
"Greater as operator" ) );
387 registerItem(
"Operators",
"<",
" < ",
tr(
"Less than operator" ) );
388 registerItem(
"Operators",
"<>",
" <> ",
tr(
"Unequal operator" ) );
389 registerItem(
"Operators",
"<=",
" <= ",
tr(
"Less or equal operator" ) );
390 registerItem(
"Operators",
">=",
" >= ",
tr(
"Greater or equal operator" ) );
392 QString(
"<b>|| %1</b><br><i>%2</i><br><i>%3:</i>%4" )
393 .arg(
tr(
"(String Concatenation)" ) )
394 .arg(
tr(
"Joins two values together into a string" ) )
395 .arg(
tr(
"Usage" ) )
396 .arg(
tr(
"'Dia' || Diameter" ) ) );
405 QString casestring =
"CASE WHEN condition THEN result END";
406 QString caseelsestring =
"CASE WHEN condition THEN result ELSE result END";
408 registerItem(
"Conditionals",
"CASE ELSE", caseelsestring );
414 for (
int i = 0; i < count; i++ )
417 QString name = func->
name();
418 if ( name.startsWith(
"_" ) )
420 if ( func->
params() != 0 )
426 for (
int i = 0; i < specials.size(); ++i )
428 QString name = specials[i]->name();
429 registerItem( specials[i]->group(), name,
" " + name +
" " );
440 return txtExpressionString->text();
445 txtExpressionString->setText( expression );
454 if ( text.isEmpty() )
456 lblPreview->setText(
"" );
457 lblPreview->setStyleSheet(
"" );
458 txtExpressionString->setToolTip(
"" );
459 lblPreview->setToolTip(
"" );
480 lblPreview->setText( formatPreviewString( value.toString() ) );
486 lblPreview->setText(
"" );
495 lblPreview->setText( formatPreviewString( value.toString() ) );
501 QString tooltip = QString(
"<b>%1:</b><br>%2" ).arg(
tr(
"Parser Error" ) ).arg( exp.
parserErrorString() );
503 tooltip += QString(
"<br><br><b>%1:</b><br>%2" ).arg(
tr(
"Eval Error" ) ).arg( exp.
evalErrorString() );
505 lblPreview->setText(
tr(
"Expression is invalid <a href=""more"">(more info)</a>" ) );
506 lblPreview->setStyleSheet(
"color: rgba(255, 6, 10, 255);" );
507 txtExpressionString->setToolTip( tooltip );
508 lblPreview->setToolTip( tooltip );
514 lblPreview->setStyleSheet(
"" );
515 txtExpressionString->setToolTip(
"" );
516 lblPreview->setToolTip(
"" );
521 QString QgsExpressionBuilderWidget::formatPreviewString(
const QString& previewString )
const 523 if ( previewString.length() > 63 )
525 return QString(
tr(
"%1..." ) ).arg( previewString.left( 60 ) );
529 return previewString;
535 mProxyModel->setFilterWildcard( txtSearchEdit->text() );
536 if ( txtSearchEdit->text().isEmpty() )
537 expressionTree->collapseAll();
539 expressionTree->expandAll();
546 mv->setWindowTitle(
tr(
"More info on expression error" ) );
554 txtExpressionString->insertText(
" " + item->text() +
" " );
555 txtExpressionString->setFocus();
560 QPushButton* button =
dynamic_cast<QPushButton*
>( sender() );
563 txtExpressionString->insertText(
" " + button->text() +
" " );
564 txtExpressionString->setFocus();
569 QModelIndex idx = expressionTree->indexAt( pt );
570 idx = mProxyModel->mapToSource( idx );
577 QMenu* menu =
new QMenu(
this );
578 menu->addAction(
tr(
"Load top 10 unique values" ),
this, SLOT(
loadSampleValues() ) );
579 menu->addAction(
tr(
"Load all unique values" ),
this, SLOT(
loadAllValues() ) );
580 menu->popup( expressionTree->mapToGlobal( pt ) );
586 QModelIndex idx = mProxyModel->mapToSource( expressionTree->currentIndex() );
590 if ( !mLayer || !item )
593 mValueGroupBox->show();
596 fillFieldValues( fieldIndex, 10 );
601 QModelIndex idx = mProxyModel->mapToSource( expressionTree->currentIndex() );
605 if ( !mLayer || !item )
608 mValueGroupBox->show();
610 fillFieldValues( fieldIndex, -1 );
613 void QgsExpressionBuilderWidget::setExpressionState(
bool state )
615 mExpressionValid = state;
618 QString QgsExpressionBuilderWidget::loadFunctionHelp(
QgsExpressionItem* expressionItem )
620 if ( !expressionItem )
623 QString helpContents = expressionItem->
getHelpText();
626 if ( helpContents.isEmpty() )
628 QString name = expressionItem->data( Qt::UserRole ).toString();
637 return "<head><style>" + myStyle +
"</style></head><body>" + helpContents +
"</body>";
Class for parsing and evaluation of expressions (formerly called "search strings").
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
bool isValid() const
Return the validity of this feature.
QVariant evaluate(const QgsFeature *f=NULL)
Evaluate the feature and return the result.
A abstract base class for defining QgsExpression functions.
void uniqueValues(int index, QList< QVariant > &uniqueValues, int limit=-1)
Returns unique values for column.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
static QString helptext(QString name)
static bool eval(QString command, QString &result)
Eval a python statement.
Container of fields for a vector layer.
static QString group(QString group)
QString getExpressionText()
static QString reportStyleSheet()
get a standard css style sheet for reports.
static const QList< Function * > & Functions()
void setMessageAsHtml(const QString &msg)
static int functionCount()
Returns the number of functions defined in the parser.
Search proxy used to filter the QgsExpressionBuilderWidget tree.
static bool run(QString command, QString messageOnError=QString())
execute a python statement
int count() const
Return number of items.
QString helptext()
The help text for the function.
QString name()
The name of the function.
QgsExpressionItem::ItemType getItemType()
Get the type of expression item eg header, field, ExpressionNode.
General purpose distance and area calculator.
An expression item that can be used in the QgsExpressionBuilderWidget tree.
QString group()
The group the function belongs to.
static QList< Function * > specialColumns()
Returns a list of special Column definitions.
int params()
The number of parameters this function takes.
A generic message view for displaying QGIS messages.
void setGeomCalculator(const QgsDistanceArea &calc)
Sets the geometry calculator used in evaluation of expressions,.
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
bool nextFeature(QgsFeature &f)
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.
bool isEmpty() const
Check whether the container is empty.
QString parserErrorString() const
Returns parser error.
QString getHelpText()
Get the help text that is associated with this expression item.
QString evalErrorString() const
Returns evaluation error.
static bool isValid()
returns true if the runner has an instance (and thus is able to run commands)