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 The function accepts the following parameters\n\
214 : param [any]: Define any parameters you want to pass to your function before\n\
215 the following arguments.\n\
216 : param feature: The current feature\n\
217 : param parent: The QgsExpression object\n\
218 : param context: If there is an argument called ``context`` found at the last\n\
219 position, this variable will contain a ``QgsExpressionContext``\n\
220 object, that gives access to various additional information like\n\
221 expression variables. E.g. ``context.variable( 'layer_id' )``\n\
222 : returns: The result of the expression.\n\
226 The @qgsfunction decorator accepts the following arguments:\n\
229 : param args: Defines the number of arguments. With ``args = 'auto'`` the number of\n\
230 arguments will automatically be extracted from the signature.\n\
231 With ``args = -1``, any number of arguments are accepted.\n\
232 : param group: The name of the group under which this expression function will\n\
234 : param handlesnull: Set this to True if your function has custom handling for NULL values.\n\
235 If False, the result will always be NULL as soon as any parameter is NULL.\n\
236 Defaults to False.\n\
237 : param usesgeometry : Set this to True if your function requires access to\n\
238 feature.geometry(). Defaults to False.\n\
239 : param referenced_columns: An array of attribute names that are required to run\n\
240 this function. Defaults to [QgsFeatureRequest.ALL_ATTRIBUTES].\n\
248 settings.
setValue( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/splitter" ), splitter->saveState() );
249 settings.
setValue( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/editorsplitter" ), editorSplit->saveState() );
250 settings.
setValue( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/functionsplitter" ), functionsplit->saveState() );
251 delete mExpressionTreeMenuProvider;
259 mExpressionTreeView->loadRecent( recentCollection );
262 mExpressionTreeView->loadUserExpressions();
267 init( context, recentCollection, flags );
273 init( context, recentCollection, flags );
274 mExpressionTreeView->loadFieldNames( fields );
281 mExpressionTreeView->setLayer( mLayer );
282 mExpressionPreviewWidget->setLayer( mLayer );
289 expressionContextUpdated();
290 txtExpressionString->setFields( mLayer->
fields() );
294void QgsExpressionBuilderWidget::expressionContextUpdated()
296 txtExpressionString->setExpressionContext( mExpressionContext );
297 mExpressionTreeView->setExpressionContext( mExpressionContext );
298 mExpressionPreviewWidget->setExpressionContext( mExpressionContext );
306void QgsExpressionBuilderWidget::expressionTreeItemChanged(
QgsExpressionItem *item )
308 txtSearchEditValues->clear();
316 mValuesModel->clear();
319 cbxValuesInUse->setChecked(
false );
321 mValueGroupBox->setVisible( isField );
323 mShowHelpButton->setText( isField ? tr(
"Show Values" ) : tr(
"Show Help" ) );
326 QString help = loadFunctionHelp( item );
327 txtHelpText->setText( help );
329 bool isUserExpression = item->parent() && item->parent()->text() == mUserExpressionsGroupName;
331 btnRemoveExpression->setEnabled( isUserExpression );
332 btnEditExpression->setEnabled( isUserExpression );
335void QgsExpressionBuilderWidget::btnRun_pressed()
337 if ( !cmbFileNames->currentItem() )
340 QString file = cmbFileNames->currentItem()->text();
342 runPythonCode( txtPython->text() );
345void QgsExpressionBuilderWidget::runPythonCode(
const QString &code )
349 QString pythontext = code;
352 mExpressionTreeView->refresh();
372 QDir myDir( mFunctionsPath );
373 if ( !myDir.exists() )
375 myDir.mkpath( mFunctionsPath );
378 if ( !fileName.endsWith( QLatin1String(
".py" ) ) )
380 fileName.append(
".py" );
383 fileName = mFunctionsPath + QDir::separator() + fileName;
384 QFile myFile( fileName );
385 if ( myFile.open( QIODevice::WriteOnly | QFile::Truncate ) )
387 QTextStream myFileStream( &myFile );
388#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
389 myFileStream.setCodec(
"UTF-8" );
391 myFileStream << txtPython->text() << Qt::endl;
398 mFunctionsPath = path;
400 dir.setNameFilters( QStringList() << QStringLiteral(
"*.py" ) );
401 QStringList files = dir.entryList( QDir::Files );
402 cmbFileNames->clear();
403 const auto constFiles = files;
404 for (
const QString &name : constFiles )
406 QFileInfo info( mFunctionsPath + QDir::separator() + name );
407 if ( info.baseName() == QLatin1String(
"__init__" ) )
continue;
408 QListWidgetItem *item =
new QListWidgetItem(
QgsApplication::getThemeIcon( QStringLiteral(
"console/iconTabEditorConsole.svg" ) ), info.baseName() );
409 cmbFileNames->addItem( item );
411 if ( !cmbFileNames->currentItem() )
413 cmbFileNames->setCurrentRow( 0 );
416 if ( cmbFileNames->count() == 0 )
420 txtPython->setText( QStringLiteral(
"'''\n#Sample custom function file\n"
421 "#(uncomment to use and customize or Add button to create a new file) \n%1 \n '''" ).arg( txtPython->text() ) );
428 QList<QListWidgetItem *> items = cmbFileNames->findItems( fileName, Qt::MatchExactly );
429 if ( !items.isEmpty() )
432 QListWidgetItem *item =
new QListWidgetItem(
QgsApplication::getThemeIcon( QStringLiteral(
"console/iconTabEditorConsole.svg" ) ), fileName );
433 cmbFileNames->insertItem( 0, item );
434 cmbFileNames->setCurrentRow( 0 );
438 txtPython->setText( templatetxt );
442void QgsExpressionBuilderWidget::btnNewFile_pressed()
445 QString text = QInputDialog::getText(
this, tr(
"New File" ),
446 tr(
"New file name:" ), QLineEdit::Normal,
448 if ( ok && !text.isEmpty() )
454void QgsExpressionBuilderWidget::btnRemoveFile_pressed()
456 if ( QMessageBox::question(
this, tr(
"Remove File" ),
457 tr(
"Are you sure you want to remove current functions file?" ),
458 QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) == QMessageBox::No )
461 int currentRow = cmbFileNames->currentRow();
462 QString fileName = cmbFileNames->currentItem()->text();
463 if ( QFile::remove( mFunctionsPath + QDir::separator() + fileName.append(
".py" ) ) )
466 QListWidgetItem *itemToRemove =
whileBlocking( cmbFileNames )->takeItem( currentRow );
470 if ( cmbFileNames->count() > 0 )
472 whileBlocking( cmbFileNames )->setCurrentRow( currentRow > 0 ? currentRow - 1 : 0 );
473 loadCodeFromFile( mFunctionsPath + QDir::separator() + cmbFileNames->currentItem()->text() );
477 btnRemoveFile->setEnabled(
false );
483 QMessageBox::warning(
this, tr(
"Remove file" ), tr(
"Failed to remove function file '%1'." ).arg( fileName ) );
487void QgsExpressionBuilderWidget::cmbFileNames_currentItemChanged( QListWidgetItem *item, QListWidgetItem *lastitem )
491 QString filename = lastitem->text();
494 QString path = mFunctionsPath + QDir::separator() + item->text();
500 if ( !path.endsWith( QLatin1String(
".py" ) ) )
501 path.append(
".py" );
503 txtPython->loadScript( path );
508 txtPython->setText( code );
511void QgsExpressionBuilderWidget::insertExpressionText(
const QString &text )
514 txtExpressionString->insertText( text );
515 txtExpressionString->setFocus();
520 Q_UNUSED( fieldValues )
524void QgsExpressionBuilderWidget::fillFieldValues(
const QString &fieldName,
QgsVectorLayer *layer,
int countLimit,
bool forceUsedValues )
536 if ( fieldIndex < 0 )
543 if ( cbxValuesInUse->isVisible() && !cbxValuesInUse->isChecked() && !forceUsedValues )
547 values =
formatter->availableValues( setup.
config(), countLimit, fieldFormatterContext );
553 std::sort( values.begin(), values.end() );
555 mValuesModel->clear();
556 for (
const QVariant &value : std::as_const( values ) )
559 bool forceRepresentedValue =
false;
561 strValue = QStringLiteral(
"NULL" );
562 else if ( value.type() == QVariant::Int || value.type() == QVariant::Double || value.type() == QVariant::LongLong )
563 strValue = value.toString();
564 else if ( value.type() == QVariant::StringList )
567 const QStringList strList = value.toStringList();
568 for ( QString
str : strList )
570 if ( !result.isEmpty() )
571 result.append( QStringLiteral(
", " ) );
573 result.append(
'\'' +
str.replace(
'\'', QLatin1String(
"''" ) ) +
'\'' );
575 strValue = QStringLiteral(
"array(%1)" ).arg( result );
576 forceRepresentedValue =
true;
578 else if ( value.type() == QVariant::List )
581 const QList list = value.toList();
582 for (
const QVariant &item : list )
584 if ( !result.isEmpty() )
585 result.append( QStringLiteral(
", " ) );
587 result.append( item.toString() );
589 strValue = QStringLiteral(
"array(%1)" ).arg( result );
590 forceRepresentedValue =
true;
593 strValue =
'\'' + value.toString().replace(
'\'', QLatin1String(
"''" ) ) +
'\'';
595 QString representedValue =
formatter->representValue(
layer, fieldIndex, setup.
config(), QVariant(), value );
596 if ( forceRepresentedValue || representedValue != value.toString() )
597 representedValue = representedValue + QStringLiteral(
" [" ) + strValue +
']';
599 QStandardItem *item =
new QStandardItem( representedValue );
600 item->setData( strValue );
601 mValuesModel->appendRow( item );
612 return QStringLiteral(
"<head><style>" ) + helpStylesheet() + QStringLiteral(
"</style></head><body>" ) + helpContents + QStringLiteral(
"</body>" );
620 return mExpressionValid;
625 mExpressionTreeView->saveToRecent(
expressionText(), collection );
630 mExpressionTreeView->loadRecent( collection );
635 return mExpressionTreeView;
646 mExpressionTreeView->saveToUserExpressions( label, expression, helpText );
651 mExpressionTreeView->removeFromUserExpressions( label );
657 mExpressionPreviewWidget->setGeomCalculator( da );
662 return txtExpressionString->text();
667 txtExpressionString->setText( expression );
672 return lblExpected->text();
677 lblExpected->setText( expected );
678 mExpectedOutputFrame->setVisible( !expected.isNull() );
683 mExpressionContext = context;
684 expressionContextUpdated();
687void QgsExpressionBuilderWidget::txtExpressionString_textChanged()
691 btnClearEditor->setEnabled( ! txtExpressionString->text().isEmpty() );
692 btnSaveExpression->setEnabled(
false );
694 mExpressionPreviewWidget->setExpressionText( text );
699 return mExpressionPreviewWidget->parserError();
704 mExpressionPreviewWidget->setVisible( isVisible );
709 return mExpressionPreviewWidget->evalError();
715 return mExpressionTreeView->model();
727 mExpressionTreeView->setProject(
project );
732 QWidget::showEvent( e );
733 txtExpressionString->setFocus();
736void QgsExpressionBuilderWidget::createErrorMarkers(
const QList<QgsExpression::ParserError> &errors )
741 int errorFirstLine = error.firstLine - 1 ;
742 int errorFirstColumn = error.firstColumn - 1;
743 int errorLastColumn = error.lastColumn - 1;
744 int errorLastLine = error.lastLine - 1;
750 errorFirstLine = errorLastLine;
751 errorFirstColumn = errorLastColumn - 1;
753 txtExpressionString->fillIndicatorRange( errorFirstLine,
756 errorLastColumn, error.errorType );
767 txtExpressionString->SendScintilla( QsciScintilla::SCI_SETINDICATORCURRENT, FUNCTION_MARKER_ID );
768 txtExpressionString->SendScintilla( QsciScintilla::SCI_SETINDICATORVALUE, node->
fnIndex() );
771 int start_pos = txtExpressionString->positionFromLineIndex( inNode->
parserFirstLine - 1, start );
772 txtExpressionString->SendScintilla( QsciScintilla::SCI_INDICATORFILLRANGE, start_pos, end - start );
775 const QList< QgsExpressionNode * > nodeList = node->
args()->
list();
790 createMarkers( node->
operand() );
803 createMarkers( node->
opLeft() );
804 createMarkers( node->
opRight() );
816 const QList< QgsExpressionNode * > nodeList = node->
list()->
list();
827 const QList<QgsExpressionNodeCondition::WhenThen *> conditions = node->
conditions();
830 createMarkers( cond->whenExp() );
831 createMarkers( cond->thenExp() );
835 createMarkers( node->
elseExp() );
846void QgsExpressionBuilderWidget::clearFunctionMarkers()
848 int lastLine = txtExpressionString->lines() - 1;
849 txtExpressionString->clearIndicatorRange( 0, 0, lastLine, txtExpressionString->text( lastLine ).length() - 1, FUNCTION_MARKER_ID );
852void QgsExpressionBuilderWidget::clearErrors()
854 int lastLine = txtExpressionString->lines() - 1;
863void QgsExpressionBuilderWidget::txtSearchEditValues_textChanged()
865 mProxyValues->setFilterCaseSensitivity( Qt::CaseInsensitive );
866 mProxyValues->setFilterWildcard( txtSearchEditValues->text() );
869void QgsExpressionBuilderWidget::mValuesListView_doubleClicked(
const QModelIndex &index )
872 txtExpressionString->insertText(
' ' + index.data( Qt::UserRole + 1 ).toString() +
' ' );
873 txtExpressionString->setFocus();
876void QgsExpressionBuilderWidget::operatorButtonClicked()
878 QPushButton *button = qobject_cast<QPushButton *>( sender() );
881 txtExpressionString->insertText(
' ' + button->text() +
' ' );
882 txtExpressionString->setFocus();
901 mValueGroupBox->show();
921 mValueGroupBox->show();
941 mValueGroupBox->show();
961 mValueGroupBox->show();
965void QgsExpressionBuilderWidget::txtPython_textChanged()
967 lblAutoSave->setText( tr(
"Saving…" ) );
977 if ( tabWidget->currentIndex() != 1 )
980 QListWidgetItem *item = cmbFileNames->currentItem();
984 QString file = item->text();
986 lblAutoSave->setText( QStringLiteral(
"Saved" ) );
987 QGraphicsOpacityEffect *effect =
new QGraphicsOpacityEffect();
988 lblAutoSave->setGraphicsEffect( effect );
989 QPropertyAnimation *anim =
new QPropertyAnimation( effect,
"opacity" );
990 anim->setDuration( 2000 );
991 anim->setStartValue( 1.0 );
992 anim->setEndValue( 0.0 );
993 anim->setEasingCurve( QEasingCurve::OutQuad );
994 anim->start( QAbstractAnimation::DeleteWhenStopped );
1001 if ( dlg.exec() == QDialog::DialogCode::Accepted )
1003 mExpressionTreeView->saveToUserExpressions( dlg.label().simplified(), dlg.expression(), dlg.helpText() );
1017 ( item->parent() && item->parent()->text() != mUserExpressionsGroupName ) )
1024 if ( dlg.exec() == QDialog::DialogCode::Accepted )
1027 if ( dlg.isLabelModified() )
1029 mExpressionTreeView->removeFromUserExpressions( item->text() );
1032 mExpressionTreeView->saveToUserExpressions( dlg.label().simplified(), dlg.expression(), dlg.helpText() );
1047 ( item->parent() && item->parent()->text() != mUserExpressionsGroupName ) )
1050 if ( QMessageBox::Yes == QMessageBox::question(
this, tr(
"Remove Stored Expression" ),
1051 tr(
"Do you really want to remove stored expressions '%1'?" ).arg( item->text() ),
1052 QMessageBox::Yes | QMessageBox::No ) )
1054 mExpressionTreeView->removeFromUserExpressions( item->text() );
1059void QgsExpressionBuilderWidget::exportUserExpressions_pressed()
1062 QString lastSaveDir = settings.
value( QStringLiteral(
"lastExportExpressionsDir" ), QDir::homePath(),
QgsSettings::App ).toString();
1063 QString saveFileName = QFileDialog::getSaveFileName(
1065 tr(
"Export User Expressions" ),
1067 tr(
"User expressions" ) +
" (*.json)" );
1069 if ( saveFileName.isEmpty() )
1072 QFileInfo saveFileInfo( saveFileName );
1074 if ( saveFileInfo.suffix().isEmpty() )
1076 QString saveFileNameWithSuffix = saveFileName.append(
".json" );
1077 saveFileInfo = QFileInfo( saveFileNameWithSuffix );
1082 QJsonDocument exportJson = mExpressionTreeView->exportUserExpressions();
1083 QFile jsonFile( saveFileName );
1085 if ( !jsonFile.open( QFile::WriteOnly | QIODevice::Truncate ) )
1086 QMessageBox::warning(
this, tr(
"Export user expressions" ), tr(
"Error while creating the expressions file." ) );
1088 if ( ! jsonFile.write( exportJson.toJson() ) )
1089 QMessageBox::warning(
this, tr(
"Export user expressions" ), tr(
"Error while creating the expressions file." ) );
1094void QgsExpressionBuilderWidget::importUserExpressions_pressed()
1097 QString lastImportDir = settings.
value( QStringLiteral(
"lastImportExpressionsDir" ), QDir::homePath(),
QgsSettings::App ).toString();
1098 QString loadFileName = QFileDialog::getOpenFileName(
1100 tr(
"Import User Expressions" ),
1102 tr(
"User expressions" ) +
" (*.json)" );
1104 if ( loadFileName.isEmpty() )
1107 QFileInfo loadFileInfo( loadFileName );
1111 QFile jsonFile( loadFileName );
1113 if ( !jsonFile.open( QFile::ReadOnly ) )
1114 QMessageBox::warning(
this, tr(
"Import User Expressions" ), tr(
"Error while reading the expressions file." ) );
1116 QTextStream jsonStream( &jsonFile );
1117 QString jsonString = jsonFile.readAll();
1120 QJsonDocument importJson = QJsonDocument::fromJson( jsonString.toUtf8() );
1122 if ( importJson.isNull() )
1124 QMessageBox::warning(
this, tr(
"Import User Expressions" ), tr(
"Error while reading the expressions file." ) );
1128 mExpressionTreeView->loadExpressionsFromJson( importJson );
1134 return mExpressionTreeView->findExpressions( label );
1137void QgsExpressionBuilderWidget::indicatorClicked(
int line,
int index, Qt::KeyboardModifiers state )
1139 if ( state & Qt::ControlModifier )
1141 int position = txtExpressionString->positionFromLineIndex( line, index );
1142 long fncIndex = txtExpressionString->SendScintilla( QsciScintilla::SCI_INDICATORVALUEAT, FUNCTION_MARKER_ID,
static_cast<long int>( position ) );
1144 QString help = getFunctionHelp( func );
1145 txtHelpText->setText( help );
1149void QgsExpressionBuilderWidget::onExpressionParsed(
bool state )
1153 mExpressionValid = state;
1156 createMarkers( mExpressionPreviewWidget->rootNode() );
1160 createErrorMarkers( mExpressionPreviewWidget->parserErrors() );
1164QString QgsExpressionBuilderWidget::helpStylesheet()
const
1170 style +=
" .functionname {color: #0a6099; font-weight: bold;} "
1171 " .argument {font-family: monospace; color: #bf0c0c; font-style: italic; } "
1172 " td.argument { padding-right: 10px; }";
1177QString QgsExpressionBuilderWidget::loadFunctionHelp(
QgsExpressionItem *expressionItem )
1179 if ( !expressionItem )
1182 QString helpContents = expressionItem->
getHelpText();
1185 if ( helpContents.isEmpty() )
1187 QString name = expressionItem->data( Qt::UserRole ).toString();
1195 return "<head><style>" + helpStylesheet() +
"</style></head><body>" + helpContents +
"</body>";
1202QMenu *QgsExpressionBuilderWidget::ExpressionTreeMenuProvider::createContextMenu(
QgsExpressionItem *item )
1204 QMenu *menu =
nullptr;
1208 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.
@ ntBetweenOperator
Between operator.
@ ntIndexOperator
Index operator.
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.
void loadUserExpressions()
Loads the user expressions.
static const QList< QgsExpressionFunction * > & Functions()
static 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.
#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.