20#include <QInputDialog>
22#include <QGraphicsOpacityEffect>
23#include <QPropertyAnimation>
25#include <QVersionNumber>
27#include <QJsonDocument>
61 if ( fieldIndex != -1 )
79 connect( btnRun, &QToolButton::pressed,
this, &QgsExpressionBuilderWidget::btnRun_pressed );
80 connect( btnNewFile, &QPushButton::clicked,
this, &QgsExpressionBuilderWidget::btnNewFile_pressed );
81 connect( btnRemoveFile, &QPushButton::clicked,
this, &QgsExpressionBuilderWidget::btnRemoveFile_pressed );
82 connect( cmbFileNames, &QListWidget::currentItemChanged,
this, &QgsExpressionBuilderWidget::cmbFileNames_currentItemChanged );
83 connect( txtExpressionString, &QgsCodeEditorExpression::textChanged,
this, &QgsExpressionBuilderWidget::txtExpressionString_textChanged );
84 connect( txtPython, &QgsCodeEditorPython::textChanged,
this, &QgsExpressionBuilderWidget::txtPython_textChanged );
85 connect( txtSearchEditValues, &QgsFilterLineEdit::textChanged,
this, &QgsExpressionBuilderWidget::txtSearchEditValues_textChanged );
86 connect( mValuesListView, &QListView::doubleClicked,
this, &QgsExpressionBuilderWidget::mValuesListView_doubleClicked );
90 connect( btnImportExpressions, &QToolButton::clicked,
this, &QgsExpressionBuilderWidget::importUserExpressions_pressed );
91 connect( btnExportExpressions, &QToolButton::clicked,
this, &QgsExpressionBuilderWidget::exportUserExpressions_pressed );
92 connect( btnClearEditor, &QToolButton::clicked, txtExpressionString, &QgsCodeEditorExpression::clear );
105 mExpressionTreeMenuProvider =
new ExpressionTreeMenuProvider(
this );
106 mExpressionTreeView->setMenuProvider( mExpressionTreeMenuProvider );
108 txtHelpText->setOpenExternalLinks(
true );
109 mValueGroupBox->hide();
126 const auto pushButtons { mOperatorsGroupBox->findChildren<QPushButton *>() };
127 for ( QPushButton *button : pushButtons )
129 connect( button, &QAbstractButton::clicked,
this, &QgsExpressionBuilderWidget::operatorButtonClicked );
132 txtSearchEdit->setShowSearchIcon(
true );
133 txtSearchEdit->setPlaceholderText( tr(
"Search…" ) );
135 mValuesModel = std::make_unique<QStandardItemModel>();
136 mProxyValues = std::make_unique<QSortFilterProxyModel>();
137 mProxyValues->setSourceModel( mValuesModel.get() );
138 mValuesListView->setModel( mProxyValues.get() );
139 txtSearchEditValues->setShowSearchIcon(
true );
140 txtSearchEditValues->setPlaceholderText( tr(
"Search…" ) );
142 editorSplit->setSizes( QList<int>( {175, 300} ) );
144 functionsplit->setCollapsible( 0,
false );
145 connect( mShowHelpButton, &QPushButton::clicked,
this, [ = ]()
147 functionsplit->setSizes( QList<int>( {mOperationListGroup->width() - mHelpAndValuesWidget->minimumWidth(),
148 mHelpAndValuesWidget->minimumWidth()
150 mShowHelpButton->setEnabled(
false );
152 connect( functionsplit, &QSplitter::splitterMoved,
this, [ = ](
int,
int )
154 mShowHelpButton->setEnabled( functionsplit->sizes().at( 1 ) == 0 );
158 splitter->restoreState( settings.value( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/splitter" ) ).toByteArray() );
159 editorSplit->restoreState( settings.value( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/editorsplitter" ) ).toByteArray() );
160 functionsplit->restoreState( settings.value( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/functionsplitter" ) ).toByteArray() );
161 mShowHelpButton->setEnabled( functionsplit->sizes().at( 1 ) == 0 );
167 btnRemoveFile->setEnabled( cmbFileNames->count() > 0 );
174 txtExpressionString->setWrapMode( QsciScintilla::WrapWord );
175 lblAutoSave->clear();
182#if defined(QSCINTILLA_VERSION) && QSCINTILLA_VERSION >= 0x20a00
189 txtExpressionString->setIndicatorForegroundColor( QColor( Qt::red ), -1 );
190 txtExpressionString->setIndicatorHoverForegroundColor( QColor( Qt::red ), -1 );
191 txtExpressionString->setIndicatorOutlineColor( QColor( Qt::red ), -1 );
194 txtExpressionString->indicatorDefine( QgsCodeEditor::HiddenIndicator, FUNCTION_MARKER_ID );
195 txtExpressionString->setIndicatorForegroundColor( QColor( Qt::blue ), FUNCTION_MARKER_ID );
196 txtExpressionString->setIndicatorHoverForegroundColor( QColor( Qt::blue ), FUNCTION_MARKER_ID );
197 txtExpressionString->setIndicatorHoverStyle( QgsCodeEditor::DotsIndicator, FUNCTION_MARKER_ID );
199 connect( txtExpressionString, &QgsCodeEditorExpression::indicatorClicked,
this, &QgsExpressionBuilderWidget::indicatorClicked );
200 txtExpressionString->setAutoCompletionCaseSensitivity(
false );
201 txtExpressionString->setAutoCompletionSource( QsciScintilla::AcsAPIs );
202 txtExpressionString->setCallTipsVisible( 0 );
205 mFunctionBuilderHelp->setLineNumbersVisible(
false );
206 mFunctionBuilderHelp->setFoldingVisible(
false );
207 mFunctionBuilderHelp->setEdgeMode( QsciScintilla::EdgeNone );
208 mFunctionBuilderHelp->setEdgeColumn( 0 );
209 mFunctionBuilderHelp->setReadOnly(
true );
210 mFunctionBuilderHelp->setText( tr(
"\"\"\"Define a new function using the @qgsfunction decorator.\n\
212 Besides its normal arguments, the function may specify the following arguments in its signature\n\
213 Those will not need to be specified when calling the function, but will be automatically injected \n\
215 : param feature: The current feature\n\
216 : param parent: The QgsExpression object\n\
217 : param context: ``QgsExpressionContext`` object, that gives access to various additional information like\n\
218 expression variables. E.g. ``context.variable( 'layer_id' )``\n\
219 : returns: The result of the expression.\n\
223 The @qgsfunction decorator accepts the following arguments:\n\
226 : param group: The name of the group under which this expression function will\n\
228 : param handlesnull: Set this to True if your function has custom handling for NULL values.\n\
229 If False, the result will always be NULL as soon as any parameter is NULL.\n\
230 Defaults to False.\n\
231 : param usesgeometry : Set this to True if your function requires access to\n\
232 feature.geometry(). Defaults to False.\n\
233 : param referenced_columns: An array of attribute names that are required to run\n\
234 this function. Defaults to [QgsFeatureRequest.ALL_ATTRIBUTES].\n\
235 : param params_as_list : Set this to True to pass the function parameters as a list. Can be used to mimic \n\
236 behavior before 3.32, when args was not \"auto\". Defaults to False.\n\
244 settings.
setValue( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/splitter" ), splitter->saveState() );
245 settings.
setValue( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/editorsplitter" ), editorSplit->saveState() );
246 settings.
setValue( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/functionsplitter" ), functionsplit->saveState() );
247 delete mExpressionTreeMenuProvider;
255 mExpressionTreeView->loadRecent( recentCollection );
258 mExpressionTreeView->loadUserExpressions();
263 init( context, recentCollection, flags );
269 init( context, recentCollection, flags );
270 mExpressionTreeView->loadFieldNames( fields );
277 mExpressionTreeView->setLayer( mLayer );
278 mExpressionPreviewWidget->setLayer( mLayer );
285 expressionContextUpdated();
286 txtExpressionString->setFields( mLayer->
fields() );
290void QgsExpressionBuilderWidget::expressionContextUpdated()
292 txtExpressionString->setExpressionContext( mExpressionContext );
293 mExpressionTreeView->setExpressionContext( mExpressionContext );
294 mExpressionPreviewWidget->setExpressionContext( mExpressionContext );
302void QgsExpressionBuilderWidget::expressionTreeItemChanged(
QgsExpressionItem *item )
304 txtSearchEditValues->clear();
312 mValuesModel->clear();
315 cbxValuesInUse->setChecked(
false );
317 mValueGroupBox->setVisible( isField );
319 mShowHelpButton->setText( isField ? tr(
"Show Values" ) : tr(
"Show Help" ) );
322 QString help = loadFunctionHelp( item );
323 txtHelpText->setText( help );
325 bool isUserExpression = item->parent() && item->parent()->text() == mUserExpressionsGroupName;
327 btnRemoveExpression->setEnabled( isUserExpression );
328 btnEditExpression->setEnabled( isUserExpression );
331void QgsExpressionBuilderWidget::btnRun_pressed()
333 if ( !cmbFileNames->currentItem() )
336 QString file = cmbFileNames->currentItem()->text();
338 runPythonCode( txtPython->text() );
341void QgsExpressionBuilderWidget::runPythonCode(
const QString &code )
345 QString pythontext = code;
348 mExpressionTreeView->refresh();
368 QDir myDir( mFunctionsPath );
369 if ( !myDir.exists() )
371 myDir.mkpath( mFunctionsPath );
374 if ( !fileName.endsWith( QLatin1String(
".py" ) ) )
376 fileName.append(
".py" );
379 fileName = mFunctionsPath + QDir::separator() + fileName;
380 QFile myFile( fileName );
381 if ( myFile.open( QIODevice::WriteOnly | QFile::Truncate ) )
383 QTextStream myFileStream( &myFile );
384 myFileStream << txtPython->text() << Qt::endl;
391 mFunctionsPath = path;
393 dir.setNameFilters( QStringList() << QStringLiteral(
"*.py" ) );
394 QStringList
files = dir.entryList( QDir::Files );
395 cmbFileNames->clear();
396 const auto constFiles =
files;
397 for (
const QString &name : constFiles )
399 QFileInfo info( mFunctionsPath + QDir::separator() + name );
400 if ( info.baseName() == QLatin1String(
"__init__" ) )
continue;
401 QListWidgetItem *item =
new QListWidgetItem(
QgsApplication::getThemeIcon( QStringLiteral(
"console/iconTabEditorConsole.svg" ) ), info.baseName() );
402 cmbFileNames->addItem( item );
404 if ( !cmbFileNames->currentItem() )
406 cmbFileNames->setCurrentRow( 0 );
409 if ( cmbFileNames->count() == 0 )
413 txtPython->setText( QStringLiteral(
"'''\n#Sample custom function file\n"
414 "#(uncomment to use and customize or Add button to create a new file) \n%1 \n '''" ).arg( txtPython->text() ) );
421 QList<QListWidgetItem *> items = cmbFileNames->findItems( fileName, Qt::MatchExactly );
422 if ( !items.isEmpty() )
425 QListWidgetItem *item =
new QListWidgetItem(
QgsApplication::getThemeIcon( QStringLiteral(
"console/iconTabEditorConsole.svg" ) ), fileName );
426 cmbFileNames->insertItem( 0, item );
427 cmbFileNames->setCurrentRow( 0 );
431 txtPython->setText( templatetxt );
435void QgsExpressionBuilderWidget::btnNewFile_pressed()
438 QString text = QInputDialog::getText(
this, tr(
"New File" ),
439 tr(
"New file name:" ), QLineEdit::Normal,
441 if ( ok && !text.isEmpty() )
447void QgsExpressionBuilderWidget::btnRemoveFile_pressed()
449 if ( QMessageBox::question(
this, tr(
"Remove File" ),
450 tr(
"Are you sure you want to remove current functions file?" ),
451 QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) == QMessageBox::No )
454 int currentRow = cmbFileNames->currentRow();
455 QString fileName = cmbFileNames->currentItem()->text();
456 if ( QFile::remove( mFunctionsPath + QDir::separator() + fileName.append(
".py" ) ) )
459 QListWidgetItem *itemToRemove =
whileBlocking( cmbFileNames )->takeItem( currentRow );
463 if ( cmbFileNames->count() > 0 )
465 whileBlocking( cmbFileNames )->setCurrentRow( currentRow > 0 ? currentRow - 1 : 0 );
466 loadCodeFromFile( mFunctionsPath + QDir::separator() + cmbFileNames->currentItem()->text() );
470 btnRemoveFile->setEnabled(
false );
476 QMessageBox::warning(
this, tr(
"Remove file" ), tr(
"Failed to remove function file '%1'." ).arg( fileName ) );
480void QgsExpressionBuilderWidget::cmbFileNames_currentItemChanged( QListWidgetItem *item, QListWidgetItem *lastitem )
484 QString filename = lastitem->text();
487 QString path = mFunctionsPath + QDir::separator() + item->text();
493 if ( !path.endsWith( QLatin1String(
".py" ) ) )
494 path.append(
".py" );
496 txtPython->loadScript( path );
501 txtPython->setText( code );
504void QgsExpressionBuilderWidget::insertExpressionText(
const QString &text )
507 txtExpressionString->insertText( text );
508 txtExpressionString->setFocus();
513 Q_UNUSED( fieldValues )
517void QgsExpressionBuilderWidget::fillFieldValues(
const QString &fieldName,
QgsVectorLayer *layer,
int countLimit,
bool forceUsedValues )
529 if ( fieldIndex < 0 )
536 if ( cbxValuesInUse->isVisible() && !cbxValuesInUse->isChecked() && !forceUsedValues )
540 values =
formatter->availableValues( setup.
config(), countLimit, fieldFormatterContext );
546 std::sort( values.begin(), values.end() );
548 mValuesModel->clear();
549 for (
const QVariant &value : std::as_const( values ) )
552 bool forceRepresentedValue =
false;
554 strValue = QStringLiteral(
"NULL" );
555 else if ( value.type() == QVariant::Int || value.type() == QVariant::Double || value.type() == QVariant::LongLong )
556 strValue = value.toString();
557 else if ( value.type() == QVariant::StringList )
560 const QStringList strList = value.toStringList();
561 for ( QString
str : strList )
563 if ( !result.isEmpty() )
564 result.append( QStringLiteral(
", " ) );
566 result.append(
'\'' +
str.replace(
'\'', QLatin1String(
"''" ) ) +
'\'' );
568 strValue = QStringLiteral(
"array(%1)" ).arg( result );
569 forceRepresentedValue =
true;
571 else if ( value.type() == QVariant::List )
574 const QList list = value.toList();
575 for (
const QVariant &item : list )
577 if ( !result.isEmpty() )
578 result.append( QStringLiteral(
", " ) );
580 result.append( item.toString() );
582 strValue = QStringLiteral(
"array(%1)" ).arg( result );
583 forceRepresentedValue =
true;
586 strValue =
'\'' + value.toString().replace(
'\'', QLatin1String(
"''" ) ) +
'\'';
588 QString representedValue =
formatter->representValue(
layer, fieldIndex, setup.
config(), QVariant(), value );
589 if ( forceRepresentedValue || representedValue != value.toString() )
590 representedValue = representedValue + QStringLiteral(
" [" ) + strValue +
']';
592 QStandardItem *item =
new QStandardItem( representedValue );
593 item->setData( strValue );
594 mValuesModel->appendRow( item );
605 return QStringLiteral(
"<head><style>" ) + helpStylesheet() + QStringLiteral(
"</style></head><body>" ) + helpContents + QStringLiteral(
"</body>" );
613 return mExpressionValid;
618 mExpressionTreeView->saveToRecent(
expressionText(), collection );
623 mExpressionTreeView->loadRecent( collection );
628 return mExpressionTreeView;
634 mExpressionTreeView->loadUserExpressions();
639 mExpressionTreeView->saveToUserExpressions( label, expression, helpText );
644 mExpressionTreeView->removeFromUserExpressions( label );
650 mExpressionPreviewWidget->setGeomCalculator( da );
655 return txtExpressionString->text();
660 txtExpressionString->setText( expression );
665 return lblExpected->text();
670 lblExpected->setText( expected );
671 mExpectedOutputFrame->setVisible( !expected.isNull() );
676 mExpressionContext = context;
677 expressionContextUpdated();
680void QgsExpressionBuilderWidget::txtExpressionString_textChanged()
684 btnClearEditor->setEnabled( ! txtExpressionString->text().isEmpty() );
685 btnSaveExpression->setEnabled(
false );
687 mExpressionPreviewWidget->setExpressionText( text );
692 return mExpressionPreviewWidget->parserError();
697 mExpressionPreviewWidget->setVisible( isVisible );
702 return mExpressionPreviewWidget->evalError();
708 return mExpressionTreeView->model();
720 mExpressionTreeView->setProject(
project );
725 QWidget::showEvent( e );
726 txtExpressionString->setFocus();
729void QgsExpressionBuilderWidget::createErrorMarkers(
const QList<QgsExpression::ParserError> &errors )
734 int errorFirstLine = error.firstLine - 1 ;
735 int errorFirstColumn = error.firstColumn - 1;
736 int errorLastColumn = error.lastColumn - 1;
737 int errorLastLine = error.lastLine - 1;
743 errorFirstLine = errorLastLine;
744 errorFirstColumn = errorLastColumn - 1;
746 txtExpressionString->fillIndicatorRange( errorFirstLine,
749 errorLastColumn, error.errorType );
757 case QgsExpressionNode::NodeType::ntFunction:
760 txtExpressionString->SendScintilla( QsciScintilla::SCI_SETINDICATORCURRENT, FUNCTION_MARKER_ID );
761 txtExpressionString->SendScintilla( QsciScintilla::SCI_SETINDICATORVALUE, node->
fnIndex() );
764 int start_pos = txtExpressionString->positionFromLineIndex( inNode->
parserFirstLine - 1, start );
765 txtExpressionString->SendScintilla( QsciScintilla::SCI_INDICATORFILLRANGE, start_pos, end - start );
768 const QList< QgsExpressionNode * > nodeList = node->
args()->
list();
776 case QgsExpressionNode::NodeType::ntLiteral:
780 case QgsExpressionNode::NodeType::ntUnaryOperator:
783 createMarkers( node->
operand() );
786 case QgsExpressionNode::NodeType::ntBetweenOperator:
793 case QgsExpressionNode::NodeType::ntBinaryOperator:
796 createMarkers( node->
opLeft() );
797 createMarkers( node->
opRight() );
800 case QgsExpressionNode::NodeType::ntColumnRef:
804 case QgsExpressionNode::NodeType::ntInOperator:
809 const QList< QgsExpressionNode * > nodeList = node->
list()->
list();
817 case QgsExpressionNode::NodeType::ntCondition:
820 const QList<QgsExpressionNodeCondition::WhenThen *> conditions = node->
conditions();
823 createMarkers( cond->whenExp() );
824 createMarkers( cond->thenExp() );
828 createMarkers( node->
elseExp() );
832 case QgsExpressionNode::NodeType::ntIndexOperator:
839void QgsExpressionBuilderWidget::clearFunctionMarkers()
841 int lastLine = txtExpressionString->lines() - 1;
842 txtExpressionString->clearIndicatorRange( 0, 0, lastLine, txtExpressionString->text( lastLine ).length() - 1, FUNCTION_MARKER_ID );
845void QgsExpressionBuilderWidget::clearErrors()
847 int lastLine = txtExpressionString->lines() - 1;
856void QgsExpressionBuilderWidget::txtSearchEditValues_textChanged()
858 mProxyValues->setFilterCaseSensitivity( Qt::CaseInsensitive );
859 mProxyValues->setFilterWildcard( txtSearchEditValues->text() );
862void QgsExpressionBuilderWidget::mValuesListView_doubleClicked(
const QModelIndex &index )
865 txtExpressionString->insertText(
' ' + index.data( Qt::UserRole + 1 ).toString() +
' ' );
866 txtExpressionString->setFocus();
869void QgsExpressionBuilderWidget::operatorButtonClicked()
871 QPushButton *button = qobject_cast<QPushButton *>( sender() );
874 txtExpressionString->insertText(
' ' + button->text() +
' ' );
875 txtExpressionString->setFocus();
894 mValueGroupBox->show();
914 mValueGroupBox->show();
934 mValueGroupBox->show();
954 mValueGroupBox->show();
958void QgsExpressionBuilderWidget::txtPython_textChanged()
960 lblAutoSave->setText( tr(
"Saving…" ) );
970 if ( tabWidget->currentIndex() != 1 )
973 QListWidgetItem *item = cmbFileNames->currentItem();
977 QString file = item->text();
979 lblAutoSave->setText( QStringLiteral(
"Saved" ) );
980 QGraphicsOpacityEffect *effect =
new QGraphicsOpacityEffect();
981 lblAutoSave->setGraphicsEffect( effect );
982 QPropertyAnimation *anim =
new QPropertyAnimation( effect,
"opacity" );
983 anim->setDuration( 2000 );
984 anim->setStartValue( 1.0 );
985 anim->setEndValue( 0.0 );
986 anim->setEasingCurve( QEasingCurve::OutQuad );
987 anim->start( QAbstractAnimation::DeleteWhenStopped );
994 if ( dlg.exec() == QDialog::DialogCode::Accepted )
996 mExpressionTreeView->saveToUserExpressions( dlg.label().simplified(), dlg.expression(), dlg.helpText() );
1010 ( item->parent() && item->parent()->text() != mUserExpressionsGroupName ) )
1014 QString helpText = settings.
value( QStringLiteral(
"user/%1/helpText" ).arg( item->text() ),
"", QgsSettings::Section::Expressions ).toString();
1017 if ( dlg.exec() == QDialog::DialogCode::Accepted )
1020 if ( dlg.isLabelModified() )
1022 mExpressionTreeView->removeFromUserExpressions( item->text() );
1025 mExpressionTreeView->saveToUserExpressions( dlg.label().simplified(), dlg.expression(), dlg.helpText() );
1040 ( item->parent() && item->parent()->text() != mUserExpressionsGroupName ) )
1043 if ( QMessageBox::Yes == QMessageBox::question(
this, tr(
"Remove Stored Expression" ),
1044 tr(
"Do you really want to remove stored expressions '%1'?" ).arg( item->text() ),
1045 QMessageBox::Yes | QMessageBox::No ) )
1047 mExpressionTreeView->removeFromUserExpressions( item->text() );
1052void QgsExpressionBuilderWidget::exportUserExpressions_pressed()
1055 QString lastSaveDir = settings.
value( QStringLiteral(
"lastExportExpressionsDir" ), QDir::homePath(),
QgsSettings::App ).toString();
1056 QString saveFileName = QFileDialog::getSaveFileName(
1058 tr(
"Export User Expressions" ),
1060 tr(
"User expressions" ) +
" (*.json)" );
1062 if ( saveFileName.isEmpty() )
1065 QFileInfo saveFileInfo( saveFileName );
1067 if ( saveFileInfo.suffix().isEmpty() )
1069 QString saveFileNameWithSuffix = saveFileName.append(
".json" );
1070 saveFileInfo = QFileInfo( saveFileNameWithSuffix );
1075 QJsonDocument exportJson = mExpressionTreeView->exportUserExpressions();
1076 QFile jsonFile( saveFileName );
1078 if ( !jsonFile.open( QFile::WriteOnly | QIODevice::Truncate ) )
1079 QMessageBox::warning(
this, tr(
"Export user expressions" ), tr(
"Error while creating the expressions file." ) );
1081 if ( ! jsonFile.write( exportJson.toJson() ) )
1082 QMessageBox::warning(
this, tr(
"Export user expressions" ), tr(
"Error while creating the expressions file." ) );
1087void QgsExpressionBuilderWidget::importUserExpressions_pressed()
1090 QString lastImportDir = settings.
value( QStringLiteral(
"lastImportExpressionsDir" ), QDir::homePath(),
QgsSettings::App ).toString();
1091 QString loadFileName = QFileDialog::getOpenFileName(
1093 tr(
"Import User Expressions" ),
1095 tr(
"User expressions" ) +
" (*.json)" );
1097 if ( loadFileName.isEmpty() )
1100 QFileInfo loadFileInfo( loadFileName );
1104 QFile jsonFile( loadFileName );
1106 if ( !jsonFile.open( QFile::ReadOnly ) )
1107 QMessageBox::warning(
this, tr(
"Import User Expressions" ), tr(
"Error while reading the expressions file." ) );
1109 QTextStream jsonStream( &jsonFile );
1110 QString jsonString = jsonFile.readAll();
1113 QJsonDocument importJson = QJsonDocument::fromJson( jsonString.toUtf8() );
1115 if ( importJson.isNull() )
1117 QMessageBox::warning(
this, tr(
"Import User Expressions" ), tr(
"Error while reading the expressions file." ) );
1121 mExpressionTreeView->loadExpressionsFromJson( importJson );
1127 return mExpressionTreeView->findExpressions( label );
1130void QgsExpressionBuilderWidget::indicatorClicked(
int line,
int index, Qt::KeyboardModifiers state )
1132 if ( state & Qt::ControlModifier )
1134 int position = txtExpressionString->positionFromLineIndex( line, index );
1135 long fncIndex = txtExpressionString->SendScintilla( QsciScintilla::SCI_INDICATORVALUEAT, FUNCTION_MARKER_ID,
static_cast<long int>( position ) );
1137 QString help = getFunctionHelp( func );
1138 txtHelpText->setText( help );
1142void QgsExpressionBuilderWidget::onExpressionParsed(
bool state )
1146 mExpressionValid = state;
1149 createMarkers( mExpressionPreviewWidget->rootNode() );
1153 createErrorMarkers( mExpressionPreviewWidget->parserErrors() );
1157QString QgsExpressionBuilderWidget::helpStylesheet()
const
1163 style +=
" .functionname {color: #0a6099; font-weight: bold;} "
1164 " .argument {font-family: monospace; color: #bf0c0c; font-style: italic; } "
1165 " td.argument { padding-right: 10px; }";
1170QString QgsExpressionBuilderWidget::loadFunctionHelp(
QgsExpressionItem *expressionItem )
1172 if ( !expressionItem )
1175 QString helpContents = expressionItem->
getHelpText();
1178 if ( helpContents.isEmpty() )
1180 QString name = expressionItem->data( Qt::UserRole ).toString();
1188 return "<head><style>" + helpStylesheet() +
"</style></head><body>" + helpContents +
"</body>";
1195QMenu *QgsExpressionBuilderWidget::ExpressionTreeMenuProvider::createContextMenu(
QgsExpressionItem *item )
1197 QMenu *menu =
nullptr;
1201 menu =
new QMenu( mExpressionBuilderWidget );
static QString reportStyleSheet(QgsApplication::StyleSheetType styleSheetType=QgsApplication::StyleSheetType::Qt)
Returns a css style sheet for reports, the styleSheetType argument determines what type of stylesheet...
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QgsFieldFormatterRegistry * fieldFormatterRegistry()
Gets the registry of available field formatters.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
A abstract base class for defining QgsExpression functions.
QString name() const
The name of the function.
An expression item that can be used in the QgsExpressionBuilderWidget tree.
static const int LAYER_ID_ROLE
Layer ID role.
QString getExpressionText() const
QgsExpressionItem::ItemType getItemType() const
Gets the type of expression item, e.g., header, field, ExpressionNode.
QString getHelpText() const
Gets the help text that is associated with this expression item.
static const int ITEM_NAME_ROLE
Item name role.
SQL-like BETWEEN and NOT BETWEEN predicates.
QgsExpressionNode * lowerBound() const
Returns the lower bound expression node of the range.
QgsExpressionNode * higherBound() const
Returns the higher bound expression node of the range.
A binary expression operator, which operates on two values.
QgsExpressionNode * opLeft() const
Returns the node to the left of the operator.
QgsExpressionNode * opRight() const
Returns the node to the right of the operator.
Represents a "WHEN... THEN..." portation of a CASE WHEN clause in an expression.
An expression node for CASE WHEN clauses.
QgsExpressionNode * elseExp() const
The ELSE expression used for the condition.
WhenThenList conditions() const
The list of WHEN THEN expression parts of the expression.
An expression node for expression functions.
int fnIndex() const
Returns the index of the node's function.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
An expression node for value IN or NOT IN clauses.
QgsExpressionNode::NodeList * list() const
Returns the list of nodes to search for matching values within.
A unary node is either negative as in boolean (not) or as in numbers (minus).
QgsExpressionNode * operand() const
Returns the node the operator will operate upon.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
Abstract base class for all nodes that can appear in an expression.
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
int parserFirstLine
First line in the parser this node was found.
int parserLastColumn
Last column in the parser this node was found.
int parserFirstColumn
First column in the parser this node was found.
A generic dialog for editing expression text, label and help text.
QgsExpressionTreeView is a tree view to list all expressions functions, variables and fields that can...
void expressionItemDoubleClicked(const QString &text)
Emitted when a expression item is double clicked.
void currentExpressionItemChanged(QgsExpressionItem *item)
Emitter when the current expression item changed.
void setSearchText(const QString &text)
Sets the text to filter the expression tree.
static const QList< QgsExpressionFunction * > & Functions()
static PRIVATE QString helpText(QString name)
Returns the help text for a specified function.
static QString group(const QString &group)
Returns the translated name for a function group.
A context for field formatter containing information like the project.
void setProject(QgsProject *project)
Sets the project used in field formatter.
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Container of fields for a vector layer.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
static QgsProject * instance()
Returns the QgsProject singleton instance.
static bool run(const QString &command, const QString &messageOnError=QString())
Execute a Python statement.
static bool eval(const QString &command, QString &result)
Eval a Python statement.
static bool isValid()
Returns true if the runner has an instance (and thus is able to run commands)
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based data sets.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const FINAL
Calculates a list of unique values contained within an attribute in the layer.
CORE_EXPORT const QStringList files(const QString &zip)
Returns the list of files within a zip file.
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Details about any parser errors that were found when parsing the expression.
@ FunctionInvalidParams
Function was called with invalid args.
@ Unknown
Unknown error type.
@ FunctionUnknown
Function was unknown.
@ FunctionNamedArgsError
Non named function arg used after named arg.
@ FunctionWrongArgs
Function was called with the wrong number of args.