35 #include <QTextStream> 37 #include <QInputDialog> 39 #include <QGraphicsOpacityEffect> 40 #include <QPropertyAnimation> 48 connect( btnRun, &QToolButton::pressed,
this, &QgsExpressionBuilderWidget::btnRun_pressed );
49 connect( btnNewFile, &QToolButton::pressed,
this, &QgsExpressionBuilderWidget::btnNewFile_pressed );
50 connect( cmbFileNames, &QListWidget::currentItemChanged,
this, &QgsExpressionBuilderWidget::cmbFileNames_currentItemChanged );
51 connect( expressionTree, &QTreeView::doubleClicked,
this, &QgsExpressionBuilderWidget::expressionTree_doubleClicked );
52 connect( txtExpressionString, &QgsCodeEditorSQL::textChanged,
this, &QgsExpressionBuilderWidget::txtExpressionString_textChanged );
53 connect( txtPython, &QgsCodeEditorPython::textChanged,
this, &QgsExpressionBuilderWidget::txtPython_textChanged );
54 connect( txtSearchEditValues, &QgsFilterLineEdit::textChanged,
this, &QgsExpressionBuilderWidget::txtSearchEditValues_textChanged );
55 connect( txtSearchEdit, &QgsFilterLineEdit::textChanged,
this, &QgsExpressionBuilderWidget::txtSearchEdit_textChanged );
56 connect( lblPreview, &QLabel::linkActivated,
this, &QgsExpressionBuilderWidget::lblPreview_linkActivated );
57 connect( mValuesListView, &QListView::doubleClicked,
this, &QgsExpressionBuilderWidget::mValuesListView_doubleClicked );
59 mValueGroupBox->hide();
60 mLoadGroupBox->hide();
63 mModel =
new QStandardItemModel();
65 mProxyModel->setDynamicSortFilter(
true );
66 mProxyModel->setSourceModel( mModel );
67 expressionTree->setModel( mProxyModel );
68 expressionTree->setSortingEnabled(
true );
69 expressionTree->sortByColumn( 0, Qt::AscendingOrder );
71 expressionTree->setContextMenuPolicy( Qt::CustomContextMenu );
73 connect( expressionTree, &QWidget::customContextMenuRequested,
this, &QgsExpressionBuilderWidget::showContextMenu );
74 connect( expressionTree->selectionModel(), &QItemSelectionModel::currentChanged,
75 this, &QgsExpressionBuilderWidget::currentChanged );
80 Q_FOREACH ( QPushButton *button, mOperatorsGroupBox->findChildren<QPushButton *>() )
82 connect( button, &QAbstractButton::pressed,
this, &QgsExpressionBuilderWidget::operatorButtonClicked );
85 txtSearchEdit->setShowSearchIcon(
true );
86 txtSearchEdit->setPlaceholderText( tr(
"Search" ) );
88 mValuesModel =
new QStringListModel();
89 mProxyValues =
new QSortFilterProxyModel();
90 mProxyValues->setSourceModel( mValuesModel );
91 mValuesListView->setModel( mProxyValues );
92 txtSearchEditValues->setShowSearchIcon(
true );
93 txtSearchEditValues->setPlaceholderText( tr(
"Search" ) );
96 splitter->restoreState( settings.
value( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/splitter" ) ).toByteArray() );
97 editorSplit->restoreState( settings.
value( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/editorsplitter" ) ).toByteArray() );
98 functionsplit->restoreState( settings.
value( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/functionsplitter" ) ).toByteArray() );
100 txtExpressionString->setFoldingVisible(
false );
102 updateFunctionTree();
116 QModelIndex firstItem = mProxyModel->index( 0, 0, QModelIndex() );
117 expressionTree->setCurrentIndex( firstItem );
119 txtExpressionString->setWrapMode( QsciScintilla::WrapWord );
120 lblAutoSave->clear();
128 #if defined(QSCINTILLA_VERSION) && QSCINTILLA_VERSION >= 0x20a00 135 txtExpressionString->setIndicatorForegroundColor( QColor( Qt::red ), -1 );
136 txtExpressionString->setIndicatorHoverForegroundColor( QColor( Qt::red ), -1 );
137 txtExpressionString->setIndicatorOutlineColor( QColor( Qt::red ), -1 );
140 txtExpressionString->indicatorDefine( QgsCodeEditor::HiddenIndicator, FUNCTION_MARKER_ID );
141 txtExpressionString->setIndicatorForegroundColor( QColor( Qt::blue ), FUNCTION_MARKER_ID );
142 txtExpressionString->setIndicatorHoverForegroundColor( QColor( Qt::blue ), FUNCTION_MARKER_ID );
143 txtExpressionString->setIndicatorHoverStyle( QgsCodeEditor::DotsIndicator, FUNCTION_MARKER_ID );
145 connect( txtExpressionString, &QgsCodeEditorSQL::indicatorClicked,
this, &QgsExpressionBuilderWidget::indicatorClicked );
154 settings.
setValue( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/splitter" ), splitter->saveState() );
155 settings.
setValue( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/editorsplitter" ), editorSplit->saveState() );
156 settings.
setValue( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/functionsplitter" ), functionsplit->saveState() );
174 void QgsExpressionBuilderWidget::currentChanged(
const QModelIndex &index,
const QModelIndex & )
176 txtSearchEditValues->clear();
179 QModelIndex idx = mProxyModel->mapToSource( index );
186 const QStringList &values = mFieldValues[item->text()];
187 mValuesModel->setStringList( values );
194 QString help = loadFunctionHelp( item );
195 txtHelpText->setText( help );
198 void QgsExpressionBuilderWidget::btnRun_pressed()
200 if ( !cmbFileNames->currentItem() )
203 QString file = cmbFileNames->currentItem()->text();
205 runPythonCode( txtPython->text() );
208 void QgsExpressionBuilderWidget::runPythonCode(
const QString &code )
212 QString pythontext = code;
215 updateFunctionTree();
222 QDir myDir( mFunctionsPath );
223 if ( !myDir.exists() )
225 myDir.mkpath( mFunctionsPath );
228 if ( !fileName.endsWith( QLatin1String(
".py" ) ) )
230 fileName.append(
".py" );
233 fileName = mFunctionsPath + QDir::separator() + fileName;
234 QFile myFile( fileName );
235 if ( myFile.open( QIODevice::WriteOnly | QFile::Truncate ) )
237 QTextStream myFileStream( &myFile );
238 myFileStream << txtPython->text() << endl;
245 mFunctionsPath = path;
247 dir.setNameFilters( QStringList() << QStringLiteral(
"*.py" ) );
248 QStringList files = dir.entryList( QDir::Files );
249 cmbFileNames->clear();
250 Q_FOREACH (
const QString &name, files )
252 QFileInfo info( mFunctionsPath + QDir::separator() + name );
253 if ( info.baseName() == QLatin1String(
"__init__" ) )
continue;
254 QListWidgetItem *item =
new QListWidgetItem(
QgsApplication::getThemeIcon( QStringLiteral(
"console/iconTabEditorConsole.svg" ) ), info.baseName() );
255 cmbFileNames->addItem( item );
257 if ( !cmbFileNames->currentItem() )
258 cmbFileNames->setCurrentRow( 0 );
263 QList<QListWidgetItem *> items = cmbFileNames->findItems( fileName, Qt::MatchExactly );
264 if ( !items.isEmpty() )
267 QListWidgetItem *item =
new QListWidgetItem(
QgsApplication::getThemeIcon( QStringLiteral(
"console/iconTabEditorConsole.svg" ) ), fileName );
268 cmbFileNames->insertItem( 0, item );
269 cmbFileNames->setCurrentRow( 0 );
273 txtPython->setText( templatetxt );
277 void QgsExpressionBuilderWidget::btnNewFile_pressed()
280 QString text = QInputDialog::getText(
this, tr(
"Enter new file name" ),
281 tr(
"File name:" ), QLineEdit::Normal,
282 QLatin1String(
"" ), &ok );
283 if ( ok && !text.isEmpty() )
289 void QgsExpressionBuilderWidget::cmbFileNames_currentItemChanged( QListWidgetItem *item, QListWidgetItem *lastitem )
293 QString filename = lastitem->text();
296 QString path = mFunctionsPath + QDir::separator() + item->text();
302 if ( !path.endsWith( QLatin1String(
".py" ) ) )
303 path.append(
".py" );
305 txtPython->loadScript( path );
310 txtPython->setText( code );
313 void QgsExpressionBuilderWidget::expressionTree_doubleClicked(
const QModelIndex &index )
315 QModelIndex idx = mProxyModel->mapToSource( index );
326 txtExpressionString->setFocus();
344 QStringList fieldNames;
346 fieldNames.reserve( fields.
count() );
347 for (
int i = 0; i < fields.
count(); ++i )
349 QString fieldName = fields.
at( i ).
name();
350 fieldNames << fieldName;
359 for (
auto it = fieldValues.constBegin(); it != fieldValues.constEnd(); ++it )
364 mFieldValues = fieldValues;
367 void QgsExpressionBuilderWidget::fillFieldValues(
const QString &fieldName,
int countLimit )
378 if ( fieldIndex < 0 )
381 QStringList strValues;
382 QList<QVariant> values = mLayer->
uniqueValues( fieldIndex, countLimit ).toList();
383 std::sort( values.begin(), values.end() );
384 Q_FOREACH (
const QVariant &value, values )
387 if ( value.isNull() )
388 strValue = QStringLiteral(
"NULL" );
389 else if ( value.type() == QVariant::Int || value.type() == QVariant::Double || value.type() == QVariant::LongLong )
390 strValue = value.toString();
392 strValue =
'\'' + value.toString().replace(
'\'', QLatin1String(
"''" ) ) +
'\'';
393 strValues.append( strValue );
395 mValuesModel->setStringList( strValues );
396 mFieldValues[fieldName] = strValues;
406 return "<head><style>" + helpStylesheet() +
"</style></head><body>" + helpContents +
"</body>";
411 const QString &label,
413 const QString &helpText,
417 item->setData( label, Qt::UserRole );
421 if ( mExpressionGroups.contains( group ) )
424 groupNode->appendRow( item );
430 newgroupNode->setData( group, Qt::UserRole );
433 newgroupNode->appendRow( item );
434 newgroupNode->setBackground( QBrush( QColor( 238, 238, 238 ) ) );
435 mModel->appendRow( newgroupNode );
436 mExpressionGroups.insert( group, newgroupNode );
439 if ( highlightedItem )
443 topLevelItem->setData( label, Qt::UserRole );
445 QFont font = topLevelItem->font();
446 font.setBold(
true );
447 topLevelItem->setFont( font );
448 mModel->appendRow( topLevelItem );
455 return mExpressionValid;
461 QString location = QStringLiteral(
"/expressions/recent/%1" ).arg( collection );
462 QStringList expressions = settings.
value( location ).toStringList();
467 while ( expressions.count() > 20 )
469 expressions.pop_back();
472 settings.
setValue( location, expressions );
478 mRecentKey = collection;
479 QString name = tr(
"Recent (%1)" ).arg( collection );
480 if ( mExpressionGroups.contains( name ) )
483 node->removeRows( 0, node->rowCount() );
487 QString location = QStringLiteral(
"/expressions/recent/%1" ).arg( collection );
488 QStringList expressions = settings.
value( location ).toStringList();
490 Q_FOREACH (
const QString &expression, expressions )
497 void QgsExpressionBuilderWidget::loadLayers()
502 QMap<QString, QgsMapLayer *> layers = mProject->mapLayers();
503 QMap<QString, QgsMapLayer *>::const_iterator layerIt = layers.constBegin();
504 for ( ; layerIt != layers.constEnd(); ++layerIt )
506 registerItemForAllGroups( QStringList() << tr(
"Map Layers" ), layerIt.value()->name(), QStringLiteral(
"'%1'" ).arg( layerIt.key() ), formatLayerHelp( layerIt.value() ) );
510 void QgsExpressionBuilderWidget::loadRelations()
515 QMap<QString, QgsRelation> relations = mProject->relationManager()->relations();
516 QMap<QString, QgsRelation>::const_iterator relIt = relations.constBegin();
517 for ( ; relIt != relations.constEnd(); ++relIt )
519 registerItemForAllGroups( QStringList() << tr(
"Relations" ), relIt->name(), QStringLiteral(
"'%1'" ).arg( relIt->id() ), formatRelationHelp( relIt.value() ) );
523 void QgsExpressionBuilderWidget::updateFunctionTree()
526 mExpressionGroups.clear();
528 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"+" ), QStringLiteral(
" + " ) );
529 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"-" ), QStringLiteral(
" - " ) );
530 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"*" ), QStringLiteral(
" * " ) );
531 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"/" ), QStringLiteral(
" / " ) );
532 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"%" ), QStringLiteral(
" % " ) );
533 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"^" ), QStringLiteral(
" ^ " ) );
534 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"=" ), QStringLiteral(
" = " ) );
535 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"~" ), QStringLiteral(
" ~ " ) );
536 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
">" ), QStringLiteral(
" > " ) );
537 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"<" ), QStringLiteral(
" < " ) );
538 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"<>" ), QStringLiteral(
" <> " ) );
539 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"<=" ), QStringLiteral(
" <= " ) );
540 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
">=" ), QStringLiteral(
" >= " ) );
541 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"||" ), QStringLiteral(
" || " ) );
542 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"IN" ), QStringLiteral(
" IN " ) );
543 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"LIKE" ), QStringLiteral(
" LIKE " ) );
544 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"ILIKE" ), QStringLiteral(
" ILIKE " ) );
545 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"IS" ), QStringLiteral(
" IS " ) );
546 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"OR" ), QStringLiteral(
" OR " ) );
547 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"AND" ), QStringLiteral(
" AND " ) );
548 registerItem( QStringLiteral(
"Operators" ), QStringLiteral(
"NOT" ), QStringLiteral(
" NOT " ) );
550 QString casestring = QStringLiteral(
"CASE WHEN condition THEN result END" );
551 registerItem( QStringLiteral(
"Conditionals" ), QStringLiteral(
"CASE" ), casestring );
553 registerItem( QStringLiteral(
"Fields and Values" ), QStringLiteral(
"NULL" ), QStringLiteral(
"NULL" ) );
557 for (
int i = 0; i < count; i++ )
560 QString name = func->
name();
561 if ( name.startsWith(
'_' ) )
571 if ( func->
params() != 0 )
573 else if ( !name.startsWith(
'$' ) )
574 name += QLatin1String(
"()" );
575 registerItemForAllGroups( func->
groups(), func->
name(),
' ' + name +
' ', func->
helpText() );
584 loadExpressionContext();
594 return txtExpressionString->text();
599 txtExpressionString->setText( expression );
604 return lblExpected->text();
609 lblExpected->setText( expected );
610 mExpectedOutputFrame->setVisible( !expected.isNull() );
615 mExpressionContext = context;
616 updateFunctionTree();
621 void QgsExpressionBuilderWidget::txtExpressionString_textChanged()
628 if ( text.isEmpty() )
631 lblPreview->setStyleSheet( QLatin1String(
"" ) );
632 txtExpressionString->setToolTip( QLatin1String(
"" ) );
633 lblPreview->setToolTip( QLatin1String(
"" ) );
635 setParserError(
true );
636 setEvalError(
true );
657 QVariant value = exp.
evaluate( &mExpressionContext );
668 tooltip = QStringLiteral(
"<b>%1:</b>" 669 "%2" ).arg( tr(
"Parser Errors" ), errorString );
672 tooltip += QStringLiteral(
"<b>%1:</b> %2" ).arg( tr(
"Eval Error" ), exp.
evalErrorString() );
674 lblPreview->setText( tr(
"Expression is invalid <a href=""more"">(more info)</a>" ) );
675 lblPreview->setStyleSheet( QStringLiteral(
"color: rgba(255, 6, 10, 255);" ) );
676 txtExpressionString->setToolTip( tooltip );
677 lblPreview->setToolTip( tooltip );
686 lblPreview->setStyleSheet( QString() );
687 txtExpressionString->setToolTip( QString() );
688 lblPreview->setToolTip( QString() );
690 setParserError(
false );
691 setEvalError(
false );
697 void QgsExpressionBuilderWidget::loadExpressionContext()
700 Q_FOREACH (
const QString &variable, variableNames )
702 registerItem( QStringLiteral(
"Variables" ), variable,
" @" + variable +
' ',
709 QStringList contextFunctions = mExpressionContext.
functionNames();
710 Q_FOREACH (
const QString &functionName, contextFunctions )
713 QString name = func->
name();
714 if ( name.startsWith(
'_' ) )
716 if ( func->
params() != 0 )
718 registerItemForAllGroups( func->
groups(), func->
name(),
' ' + name +
' ', func->
helpText() );
722 void QgsExpressionBuilderWidget::registerItemForAllGroups(
const QStringList &groups,
const QString &label,
const QString &
expressionText,
const QString &helpText,
QgsExpressionItem::ItemType type,
bool highlightedItem,
int sortOrder )
724 Q_FOREACH (
const QString &group, groups )
730 QString QgsExpressionBuilderWidget::formatRelationHelp(
const QgsRelation &relation )
const 732 QString text = QStringLiteral(
"<p>%1</p>" ).arg( tr(
"Inserts the relation ID for the relation named '%1'." ).arg( relation.
name() ) );
733 text.append( QStringLiteral(
"<p>%1</p>" ).arg( tr(
"Current value: '%1'" ).arg( relation.
id() ) ) );
737 QString QgsExpressionBuilderWidget::formatLayerHelp(
const QgsMapLayer *layer )
const 739 QString text = QStringLiteral(
"<p>%1</p>" ).arg( tr(
"Inserts the layer ID for the layer named '%1'." ).arg( layer->
name() ) );
740 text.append( QStringLiteral(
"<p>%1</p>" ).arg( tr(
"Current value: '%1'" ).arg( layer->
id() ) ) );
749 void QgsExpressionBuilderWidget::setParserError(
bool parserError )
751 if ( parserError == mParserError )
763 void QgsExpressionBuilderWidget::setEvalError(
bool evalError )
765 if ( evalError == mEvalError )
785 updateFunctionTree();
790 QWidget::showEvent( e );
791 txtExpressionString->setFocus();
794 void QgsExpressionBuilderWidget::createErrorMarkers( QList<QgsExpression::ParserError> errors )
799 int errorFirstLine = error.firstLine - 1 ;
800 int errorFirstColumn = error.firstColumn - 1;
801 int errorLastColumn = error.lastColumn - 1;
802 int errorLastLine = error.lastLine - 1;
808 errorFirstLine = errorLastLine;
809 errorFirstColumn = errorLastColumn - 1;
811 txtExpressionString->fillIndicatorRange( errorFirstLine,
814 errorLastColumn, error.errorType );
818 void QgsExpressionBuilderWidget::createMarkers(
const QgsExpressionNode *inNode )
822 case QgsExpressionNode::NodeType::ntFunction:
825 txtExpressionString->SendScintilla( QsciScintilla::SCI_SETINDICATORCURRENT, FUNCTION_MARKER_ID );
826 txtExpressionString->SendScintilla( QsciScintilla::SCI_SETINDICATORVALUE, node->
fnIndex() );
829 int start_pos = txtExpressionString->positionFromLineIndex( inNode->
parserFirstLine - 1, start );
830 txtExpressionString->SendScintilla( QsciScintilla::SCI_INDICATORFILLRANGE, start_pos, end - start );
833 const QList< QgsExpressionNode * > nodeList = node->
args()->
list();
841 case QgsExpressionNode::NodeType::ntLiteral:
845 case QgsExpressionNode::NodeType::ntUnaryOperator:
848 createMarkers( node->
operand() );
851 case QgsExpressionNode::NodeType::ntBinaryOperator:
854 createMarkers( node->
opLeft() );
855 createMarkers( node->
opRight() );
858 case QgsExpressionNode::NodeType::ntColumnRef:
862 case QgsExpressionNode::NodeType::ntInOperator:
867 const QList< QgsExpressionNode * > nodeList = node->
list()->
list();
875 case QgsExpressionNode::NodeType::ntCondition:
880 createMarkers( cond->whenExp() );
881 createMarkers( cond->thenExp() );
885 createMarkers( node->
elseExp() );
892 void QgsExpressionBuilderWidget::clearFunctionMarkers()
894 int lastLine = txtExpressionString->lines() - 1;
895 txtExpressionString->clearIndicatorRange( 0, 0, lastLine, txtExpressionString->text( lastLine ).length() - 1, FUNCTION_MARKER_ID );
898 void QgsExpressionBuilderWidget::clearErrors()
900 int lastLine = txtExpressionString->lines() - 1;
909 void QgsExpressionBuilderWidget::txtSearchEdit_textChanged()
911 mProxyModel->setFilterWildcard( txtSearchEdit->text() );
912 if ( txtSearchEdit->text().isEmpty() )
914 expressionTree->collapseAll();
918 expressionTree->expandAll();
919 QModelIndex index = mProxyModel->index( 0, 0 );
920 if ( mProxyModel->hasChildren( index ) )
922 QModelIndex child = mProxyModel->index( 0, 0, index );
923 expressionTree->selectionModel()->setCurrentIndex( child, QItemSelectionModel::ClearAndSelect );
928 void QgsExpressionBuilderWidget::txtSearchEditValues_textChanged()
930 mProxyValues->setFilterCaseSensitivity( Qt::CaseInsensitive );
931 mProxyValues->setFilterWildcard( txtSearchEditValues->text() );
934 void QgsExpressionBuilderWidget::lblPreview_linkActivated(
const QString &link )
938 mv->setWindowTitle( tr(
"More Info on Expression Error" ) );
943 void QgsExpressionBuilderWidget::mValuesListView_doubleClicked(
const QModelIndex &index )
946 txtExpressionString->insertText(
' ' + index.data( Qt::DisplayRole ).toString() +
' ' );
947 txtExpressionString->setFocus();
950 void QgsExpressionBuilderWidget::operatorButtonClicked()
952 QPushButton *button =
dynamic_cast<QPushButton *
>( sender() );
955 txtExpressionString->insertText(
' ' + button->text() +
' ' );
956 txtExpressionString->setFocus();
959 void QgsExpressionBuilderWidget::showContextMenu( QPoint pt )
961 QModelIndex idx = expressionTree->indexAt( pt );
962 idx = mProxyModel->mapToSource( idx );
969 QMenu *menu =
new QMenu(
this );
970 menu->addAction( tr(
"Load First 10 Unique Values" ),
this, SLOT(
loadSampleValues() ) );
971 menu->addAction( tr(
"Load All Unique Values" ),
this, SLOT(
loadAllValues() ) );
972 menu->popup( expressionTree->mapToGlobal( pt ) );
978 QModelIndex idx = mProxyModel->mapToSource( expressionTree->currentIndex() );
982 if ( !mLayer || !item )
985 mValueGroupBox->show();
986 fillFieldValues( item->text(), 10 );
991 QModelIndex idx = mProxyModel->mapToSource( expressionTree->currentIndex() );
995 if ( !mLayer || !item )
998 mValueGroupBox->show();
999 fillFieldValues( item->text(), -1 );
1002 void QgsExpressionBuilderWidget::txtPython_textChanged()
1004 lblAutoSave->setText( tr(
"Saving…" ) );
1014 if ( tabWidget->currentIndex() != 1 )
1017 QListWidgetItem *item = cmbFileNames->currentItem();
1021 QString file = item->text();
1023 lblAutoSave->setText( QStringLiteral(
"Saved" ) );
1024 QGraphicsOpacityEffect *effect =
new QGraphicsOpacityEffect();
1025 lblAutoSave->setGraphicsEffect( effect );
1026 QPropertyAnimation *anim =
new QPropertyAnimation( effect,
"opacity" );
1027 anim->setDuration( 2000 );
1028 anim->setStartValue( 1.0 );
1029 anim->setEndValue( 0.0 );
1030 anim->setEasingCurve( QEasingCurve::OutQuad );
1031 anim->start( QAbstractAnimation::DeleteWhenStopped );
1034 void QgsExpressionBuilderWidget::indicatorClicked(
int line,
int index, Qt::KeyboardModifiers state )
1036 if ( state & Qt::ControlModifier )
1038 int position = txtExpressionString->positionFromLineIndex( line, index );
1039 long fncIndex = txtExpressionString->SendScintilla( QsciScintilla::SCI_INDICATORVALUEAT, FUNCTION_MARKER_ID, (
long int )position );
1041 QString help = getFunctionHelp( func );
1042 txtHelpText->setText( help );
1046 void QgsExpressionBuilderWidget::setExpressionState(
bool state )
1048 mExpressionValid = state;
1051 QString QgsExpressionBuilderWidget::helpStylesheet()
const 1057 style +=
" .functionname {color: #0a6099; font-weight: bold;} " 1058 " .argument {font-family: monospace; color: #bf0c0c; font-style: italic; } " 1059 " td.argument { padding-right: 10px; }";
1064 QString QgsExpressionBuilderWidget::loadFunctionHelp(
QgsExpressionItem *expressionItem )
1066 if ( !expressionItem )
1067 return QLatin1String(
"" );
1069 QString helpContents = expressionItem->
getHelpText();
1072 if ( helpContents.isEmpty() )
1074 QString name = expressionItem->data( Qt::UserRole ).toString();
1082 return "<head><style>" + helpStylesheet() +
"</style></head><body>" + helpContents +
"</body>";
1091 setFilterCaseSensitivity( Qt::CaseInsensitive );
1096 QModelIndex index = sourceModel()->index( source_row, 0, source_parent );
1099 int count = sourceModel()->rowCount( index );
1100 bool matchchild =
false;
1101 for (
int i = 0; i < count; ++i )
1103 if ( filterAcceptsRow( i, index ) )
1116 return QSortFilterProxyModel::filterAcceptsRow( source_row, source_parent );
1123 if ( leftSort != rightSort )
1124 return leftSort < rightSort;
1126 QString leftString = sourceModel()->data( left, Qt::DisplayRole ).toString();
1127 QString rightString = sourceModel()->data( right, Qt::DisplayRole ).toString();
1130 if ( leftString.startsWith(
'$' ) )
1131 leftString = leftString.mid( 1 );
1132 if ( rightString.startsWith(
'$' ) )
1133 rightString = rightString.mid( 1 );
1135 return QString::localeAwareCompare( leftString, rightString ) < 0;
int lookupField(const QString &fieldName) const
Look up field's index from the field name.
bool isValid() const
Returns the validity of this feature.
Class for parsing and evaluation of expressions (formerly called "search strings").
int parserFirstColumn
First column in the parser this node was found.
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Base class for all map layer types.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
QStringList filteredVariableNames() const
Returns a filtered list of variables names set by all scopes in the context.
int params() const
The number of parameters this function takes.
QStringList groups() const
Returns a list of the groups the function belongs to.
This class is a composition of two QSettings instances:
static QString group(const QString &group)
Returns the translated name for a function group.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
QgsExpressionNode * opRight() const
Returns the node to the right of the operator.
WhenThenList conditions() const
The list of WHEN THEN expression parts of the expression.
Details about any parser errors that were found when parsing the expression.
QVariant evaluate()
Evaluate the feature and return the result.
An expression node for CASE WHEN clauses.
QString evalErrorString() const
Returns evaluation error.
Container of fields for a vector layer.
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
QgsExpressionNode::NodeList * list() const
Returns the list of nodes to search for matching values within.
QList< QgsExpression::ParserError > parserErrors() const
Returns parser error details including location of error.
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const override
Calculates a list of unique values contained within an attribute in the layer.
QgsExpressionNode * opLeft() const
Returns the node to the left of the operator.
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
static QString formatPreviewString(const QVariant &value)
Formats an expression result for friendly display to the user.
static QString reportStyleSheet()
Returns a standard css style sheet for reports.
QgsExpressionItemSearchProxy()
int count() const
Returns number of items.
QString parserErrorString() const
Returns parser error.
QVariant variable(const QString &name) const
Fetches a matching variable from the context.
Function was called with invalid args.
Non named function arg used after named arg.
QString description(const QString &name) const
Returns a translated description string for the variable with specified name.
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
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.
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
QgsFields fields() const override
Returns the list of fields of this layer.
bool isHighlightedVariable(const QString &name) const
Returns true if the specified variable name is intended to be highlighted to the user.
Function was called with the wrong number of args.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
An expression node for value IN or NOT IN clauses.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
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) ...
Reads and writes project states.
Abstract base class for all nodes that can appear in an expression.
static const int ITEM_TYPE_ROLE
Item type role.
Encapsulate a field in an attribute table or data source.
An expression node for expression functions.
QgsExpressionNode * elseExp() const
The ELSE expression used for the condition.
static const QList< QgsExpressionFunction * > & Functions()
static QString formatVariableHelp(const QString &description, bool showValue=true, const QVariant &value=QVariant())
Returns formatted help text for a variable.
static bool eval(const QString &command, QString &result)
Eval a Python statement.
QgsExpressionItem::ItemType getItemType() const
Gets the type of expression item, e.g., header, field, ExpressionNode.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const override
Query the layer for features specified in request.
static const int CUSTOM_SORT_ROLE
Custom sort order role.
QString name() const
The name of the function.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations...
A abstract base class for defining QgsExpression functions.
An expression item that can be used in the QgsExpressionBuilderWidget tree.
void setGeomCalculator(const QgsDistanceArea *calc)
Sets the geometry calculator used for distance and area calculations in expressions.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
int parserFirstLine
First line in the parser this node was found.
QStringList functionNames() const
Retrieves a list of function names contained in the context.
const QString helpText() const
The help text for the function.
static bool run(const QString &command, const QString &messageOnError=QString())
Execute a Python statement.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
QString getExpressionText() const
const QgsExpressionNode * rootNode() const
Returns root node of the expression. Root node is null is parsing has failed.
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
A unary node is either negative as in boolean (not) or as in numbers (minus).
A binary expression operator, which operates on two values.
A generic message view for displaying QGIS messages.
bool isEmpty() const
Check whether the container is empty.
static QString helpText(QString name)
Returns the help text for a specified function.
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
QString getHelpText() const
Gets the help text that is associated with this expression item.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
bool nextFeature(QgsFeature &f)
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
Represents a vector layer which manages a vector based data sets.
virtual bool isDeprecated() const
Returns true if the function is deprecated and should not be presented as a valid option to users in ...
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
QgsExpressionNode * operand() const
Returns the node the operator will operate upon.
static bool isValid()
Returns true if the runner has an instance (and thus is able to run commands)
Represents a "WHEN... THEN..." portation of a CASE WHEN clause in an expression.
QgsExpressionFunction * function(const QString &name) const
Fetches a matching function from the context.
int parserLastColumn
Last column in the parser this node was found.
bool isContextual() const
Returns whether the function is only available if provided by a QgsExpressionContext object...
int fnIndex() const
Returns the index of the node's function.