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 );
90 settings.setValue(
"/windows/QgsExpressionBuilderWidget/splitter", splitter->saveState() );
91 settings.setValue(
"/windows/QgsExpressionBuilderWidget/functionsplitter", functionsplit->saveState() );
102 QModelIndex idx = mProxyModel->mapToSource( index );
109 mValueListWidget->clear();
116 QString help = loadFunctionHelp( item );
117 txtHelpText->setText( help );
118 txtHelpText->setToolTip( txtHelpText->toPlainText() );
124 runPythonCode( txtPython->text() );
127 void QgsExpressionBuilderWidget::runPythonCode( QString code )
131 QString pythontext = code;
134 updateFunctionTree();
139 QDir myDir( mFunctionsPath );
140 if ( !myDir.exists() )
142 myDir.mkpath( mFunctionsPath );
145 if ( !fileName.endsWith(
".py" ) )
147 fileName.append(
".py" );
150 fileName = mFunctionsPath + QDir::separator() + fileName;
151 QFile myFile( fileName );
152 if ( myFile.open( QIODevice::WriteOnly ) )
154 QTextStream myFileStream( &myFile );
155 myFileStream << txtPython->text() << endl;
162 mFunctionsPath = path;
164 dir.setNameFilters( QStringList() <<
"*.py" );
165 QStringList files = dir.entryList( QDir::Files );
166 cmbFileNames->clear();
167 foreach ( QString name, files )
169 QFileInfo info( mFunctionsPath + QDir::separator() + name );
170 if ( info.baseName() ==
"__init__" )
continue;
171 cmbFileNames->addItem( info.baseName() );
179 txtPython->setText( templatetxt );
180 int index = cmbFileNames->findText( fileName );
182 cmbFileNames->setEditText( fileName );
184 cmbFileNames->setCurrentIndex( index );
197 QString path = mFunctionsPath + QDir::separator() + cmbFileNames->currentText();
203 if ( !path.endsWith(
".py" ) )
204 path.append(
".py" );
206 txtPython->loadScript( path );
211 txtPython->setText( code );
216 QString name = cmbFileNames->currentText();
218 int index = cmbFileNames->findText( name );
221 cmbFileNames->addItem( name );
222 cmbFileNames->setCurrentIndex( cmbFileNames->count() - 1 );
228 QModelIndex idx = mProxyModel->mapToSource( index );
239 txtExpressionString->setFocus();
257 QStringList fieldNames;
259 for (
int i = 0; i < fields.
count(); ++i )
261 QString fieldName = fields[i].name();
262 fieldNames << fieldName;
268 void QgsExpressionBuilderWidget::fillFieldValues(
int fieldIndex,
int countLimit )
276 mValueListWidget->clear();
278 if ( fieldIndex < 0 )
281 mValueListWidget->setUpdatesEnabled(
false );
282 mValueListWidget->blockSignals(
true );
284 QList<QVariant> values;
286 foreach ( QVariant value, values )
288 if ( value.isNull() )
289 mValueListWidget->addItem(
"NULL" );
290 else if ( value.type() == QVariant::Int || value.type() == QVariant::Double || value.type() == QVariant::LongLong )
291 mValueListWidget->addItem( value.toString() );
293 mValueListWidget->addItem(
"'" + value.toString().replace(
"'",
"''" ) +
"'" );
296 mValueListWidget->setUpdatesEnabled(
true );
297 mValueListWidget->blockSignals(
false );
302 QString expressionText,
307 item->setData( label, Qt::UserRole );
309 if ( mExpressionGroups.contains( group ) )
312 groupNode->appendRow( item );
318 newgroupNode->setData( group, Qt::UserRole );
319 newgroupNode->appendRow( item );
320 mModel->appendRow( newgroupNode );
321 mExpressionGroups.insert( group, newgroupNode );
327 return mExpressionValid;
333 QString location = QString(
"/expressions/recent/%1" ).arg( key );
334 QStringList expressions = settings.value( location ).toStringList();
339 while ( expressions.count() > 20 )
341 expressions.pop_back();
344 settings.setValue( location, expressions );
350 QString name =
tr(
"Recent (%1)" ).arg( key );
351 if ( mExpressionGroups.contains( name ) )
354 node->removeRows( 0, node->rowCount() );
358 QString location = QString(
"/expressions/recent/%1" ).arg( key );
359 QStringList expressions = settings.value( location ).toStringList();
360 foreach ( QString expression, expressions )
362 this->
registerItem( name, expression, expression, expression );
366 void QgsExpressionBuilderWidget::updateFunctionTree()
369 mExpressionGroups.clear();
371 registerItem(
"Operators",
"+",
" + ",
tr(
"Addition operator" ) );
372 registerItem(
"Operators",
"-",
" - ",
tr(
"Subtraction operator" ) );
373 registerItem(
"Operators",
"*",
" * ",
tr(
"Multiplication operator" ) );
374 registerItem(
"Operators",
"/",
" / ",
tr(
"Division operator" ) );
378 registerItem(
"Operators",
">",
" > ",
tr(
"Greater as operator" ) );
379 registerItem(
"Operators",
"<",
" < ",
tr(
"Less than operator" ) );
380 registerItem(
"Operators",
"<>",
" <> ",
tr(
"Unequal operator" ) );
381 registerItem(
"Operators",
"<=",
" <= ",
tr(
"Less or equal operator" ) );
382 registerItem(
"Operators",
">=",
" >= ",
tr(
"Greater or equal operator" ) );
384 QString(
"<b>|| %1</b><br><i>%2</i><br><i>%3:</i>%4" )
385 .arg(
tr(
"(String Concatenation)" ) )
386 .arg(
tr(
"Joins two values together into a string" ) )
387 .arg(
tr(
"Usage" ) )
388 .arg(
tr(
"'Dia' || Diameter" ) ) );
397 QString casestring =
"CASE WHEN condition THEN result END";
398 QString caseelsestring =
"CASE WHEN condition THEN result ELSE result END";
400 registerItem(
"Conditionals",
"CASE ELSE", caseelsestring );
404 for (
int i = 0; i < count; i++ )
407 QString name = func->
name();
408 if ( name.startsWith(
"_" ) )
410 if ( func->
params() != 0 )
416 for (
int i = 0; i < specials.size(); ++i )
418 QString name = specials[i]->name();
419 registerItem( specials[i]->group(), name,
" " + name +
" " );
430 return txtExpressionString->text();
435 txtExpressionString->setText( expression );
444 if ( text.isEmpty() )
446 lblPreview->setText(
"" );
447 lblPreview->setStyleSheet(
"" );
448 txtExpressionString->setToolTip(
"" );
449 lblPreview->setToolTip(
"" );
470 lblPreview->setText( value.toString() );
476 lblPreview->setText(
"" );
485 lblPreview->setText( value.toString() );
491 QString tooltip = QString(
"<b>%1:</b><br>%2" ).arg(
tr(
"Parser Error" ) ).arg( exp.
parserErrorString() );
493 tooltip += QString(
"<br><br><b>%1:</b><br>%2" ).arg(
tr(
"Eval Error" ) ).arg( exp.
evalErrorString() );
495 lblPreview->setText(
tr(
"Expression is invalid <a href=""more"">(more info)</a>" ) );
496 lblPreview->setStyleSheet(
"color: rgba(255, 6, 10, 255);" );
497 txtExpressionString->setToolTip( tooltip );
498 lblPreview->setToolTip( tooltip );
504 lblPreview->setStyleSheet(
"" );
505 txtExpressionString->setToolTip(
"" );
506 lblPreview->setToolTip(
"" );
513 mProxyModel->setFilterWildcard( txtSearchEdit->text() );
514 if ( txtSearchEdit->text().isEmpty() )
515 expressionTree->collapseAll();
517 expressionTree->expandAll();
524 mv->setWindowTitle(
tr(
"More info on expression error" ) );
532 txtExpressionString->insertText(
" " + item->text() +
" " );
533 txtExpressionString->setFocus();
538 QPushButton* button =
dynamic_cast<QPushButton*
>( sender() );
541 txtExpressionString->insertText(
" " + button->text() +
" " );
542 txtExpressionString->setFocus();
547 QModelIndex idx = expressionTree->indexAt( pt );
548 idx = mProxyModel->mapToSource( idx );
555 QMenu* menu =
new QMenu(
this );
556 menu->addAction(
tr(
"Load top 10 unique values" ),
this, SLOT(
loadSampleValues() ) );
557 menu->addAction(
tr(
"Load all unique values" ),
this, SLOT(
loadAllValues() ) );
558 menu->popup( expressionTree->mapToGlobal( pt ) );
564 QModelIndex idx = mProxyModel->mapToSource( expressionTree->currentIndex() );
568 if ( !mLayer || !item )
571 mValueGroupBox->show();
574 fillFieldValues( fieldIndex, 10 );
579 QModelIndex idx = mProxyModel->mapToSource( expressionTree->currentIndex() );
583 if ( !mLayer || !item )
586 mValueGroupBox->show();
588 fillFieldValues( fieldIndex, -1 );
591 void QgsExpressionBuilderWidget::setExpressionState(
bool state )
593 mExpressionValid = state;
596 QString QgsExpressionBuilderWidget::loadFunctionHelp(
QgsExpressionItem* expressionItem )
598 if ( !expressionItem )
601 QString helpContents = expressionItem->
getHelpText();
604 if ( helpContents.isEmpty() )
606 QString name = expressionItem->data( Qt::UserRole ).toString();
615 return "<head><style>" + myStyle +
"</style></head><body>" + helpContents +
"</body>";