20#include <QInputDialog>
22#include <QGraphicsOpacityEffect>
23#include <QPropertyAnimation>
25#include <QVersionNumber>
27#include <QJsonDocument>
60 if ( fieldIndex != -1 )
65 return (
formatter->flags() & QgsFieldFormatter::CanProvideAvailableValues );
80 QVBoxLayout *vl =
new QVBoxLayout();
81 vl->setContentsMargins( 0, 0, 0, 0 );
82 vl->addWidget( codeEditorWidget );
83 mExpressionEditorContainer->setLayout( vl );
85 connect( btnRun, &QToolButton::pressed,
this, &QgsExpressionBuilderWidget::btnRun_pressed );
86 connect( btnNewFile, &QPushButton::clicked,
this, &QgsExpressionBuilderWidget::btnNewFile_pressed );
87 connect( btnRemoveFile, &QPushButton::clicked,
this, &QgsExpressionBuilderWidget::btnRemoveFile_pressed );
88 connect( cmbFileNames, &QListWidget::currentItemChanged,
this, &QgsExpressionBuilderWidget::cmbFileNames_currentItemChanged );
89 connect( txtExpressionString, &QgsCodeEditorExpression::textChanged,
this, &QgsExpressionBuilderWidget::txtExpressionString_textChanged );
90 connect( txtPython, &QgsCodeEditorPython::textChanged,
this, &QgsExpressionBuilderWidget::txtPython_textChanged );
91 connect( txtSearchEditValues, &QgsFilterLineEdit::textChanged,
this, &QgsExpressionBuilderWidget::txtSearchEditValues_textChanged );
92 connect( mValuesListView, &QListView::doubleClicked,
this, &QgsExpressionBuilderWidget::mValuesListView_doubleClicked );
96 connect( btnImportExpressions, &QToolButton::clicked,
this, &QgsExpressionBuilderWidget::importUserExpressions_pressed );
97 connect( btnExportExpressions, &QToolButton::clicked,
this, &QgsExpressionBuilderWidget::exportUserExpressions_pressed );
98 connect( btnClearEditor, &QToolButton::clicked, txtExpressionString, &QgsCodeEditorExpression::clear );
111 mExpressionTreeMenuProvider =
new ExpressionTreeMenuProvider(
this );
112 mExpressionTreeView->setMenuProvider( mExpressionTreeMenuProvider );
114 txtHelpText->setOpenExternalLinks(
true );
115 mValueGroupBox->hide();
132 const auto pushButtons { mOperatorsGroupBox->findChildren<QPushButton *>() };
133 for ( QPushButton *button : pushButtons )
135 connect( button, &QAbstractButton::clicked,
this, &QgsExpressionBuilderWidget::operatorButtonClicked );
138 txtSearchEdit->setShowSearchIcon(
true );
139 txtSearchEdit->setPlaceholderText( tr(
"Search…" ) );
141 mValuesModel = std::make_unique<QStandardItemModel>();
142 mProxyValues = std::make_unique<QSortFilterProxyModel>();
143 mProxyValues->setSourceModel( mValuesModel.get() );
144 mValuesListView->setModel( mProxyValues.get() );
145 txtSearchEditValues->setShowSearchIcon(
true );
146 txtSearchEditValues->setPlaceholderText( tr(
"Search…" ) );
148 editorSplit->setSizes( QList<int>( {175, 300} ) );
150 functionsplit->setCollapsible( 0,
false );
151 connect( mShowHelpButton, &QPushButton::clicked,
this, [ = ]()
153 functionsplit->setSizes( QList<int>( {mOperationListGroup->width() - mHelpAndValuesWidget->minimumWidth(),
154 mHelpAndValuesWidget->minimumWidth()
156 mShowHelpButton->setEnabled(
false );
158 connect( functionsplit, &QSplitter::splitterMoved,
this, [ = ](
int,
int )
160 mShowHelpButton->setEnabled( functionsplit->sizes().at( 1 ) == 0 );
164 splitter->restoreState( settings.value( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/splitter" ) ).toByteArray() );
165 editorSplit->restoreState( settings.value( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/editorsplitter" ) ).toByteArray() );
166 functionsplit->restoreState( settings.value( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/functionsplitter" ) ).toByteArray() );
167 mShowHelpButton->setEnabled( functionsplit->sizes().at( 1 ) == 0 );
173 btnRemoveFile->setEnabled( cmbFileNames->count() > 0 );
180 txtExpressionString->setWrapMode( QsciScintilla::WrapWord );
181 lblAutoSave->clear();
188#if defined(QSCINTILLA_VERSION) && QSCINTILLA_VERSION >= 0x20a00
195 txtExpressionString->setIndicatorForegroundColor( QColor( Qt::red ), -1 );
196 txtExpressionString->setIndicatorHoverForegroundColor( QColor( Qt::red ), -1 );
197 txtExpressionString->setIndicatorOutlineColor( QColor( Qt::red ), -1 );
200 txtExpressionString->indicatorDefine( QgsCodeEditor::HiddenIndicator, FUNCTION_MARKER_ID );
201 txtExpressionString->setIndicatorForegroundColor( QColor( Qt::blue ), FUNCTION_MARKER_ID );
202 txtExpressionString->setIndicatorHoverForegroundColor( QColor( Qt::blue ), FUNCTION_MARKER_ID );
203 txtExpressionString->setIndicatorHoverStyle( QgsCodeEditor::DotsIndicator, FUNCTION_MARKER_ID );
205 connect( txtExpressionString, &QgsCodeEditorExpression::indicatorClicked,
this, &QgsExpressionBuilderWidget::indicatorClicked );
206 txtExpressionString->setAutoCompletionCaseSensitivity(
false );
207 txtExpressionString->setAutoCompletionSource( QsciScintilla::AcsAPIs );
208 txtExpressionString->setCallTipsVisible( 0 );
211 mFunctionBuilderHelp->setLineNumbersVisible(
false );
212 mFunctionBuilderHelp->setFoldingVisible(
false );
213 mFunctionBuilderHelp->setEdgeMode( QsciScintilla::EdgeNone );
214 mFunctionBuilderHelp->setEdgeColumn( 0 );
215 mFunctionBuilderHelp->setReadOnly(
true );
216 mFunctionBuilderHelp->setText( tr(
"\"\"\"Define a new function using the @qgsfunction decorator.\n\
218 Besides its normal arguments, the function may specify the following arguments in its signature\n\
219 Those will not need to be specified when calling the function, but will be automatically injected \n\
221 : param feature: The current feature\n\
222 : param parent: The QgsExpression object\n\
223 : param context: ``QgsExpressionContext`` object, that gives access to various additional information like\n\
224 expression variables. E.g. ``context.variable( 'layer_id' )``\n\
225 : returns: The result of the expression.\n\
229 The @qgsfunction decorator accepts the following arguments:\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\
241 : param params_as_list : Set this to True to pass the function parameters as a list. Can be used to mimic \n\
242 behavior before 3.32, when args was not \"auto\". Defaults to False.\n\
250 settings.
setValue( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/splitter" ), splitter->saveState() );
251 settings.
setValue( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/editorsplitter" ), editorSplit->saveState() );
252 settings.
setValue( QStringLiteral(
"Windows/QgsExpressionBuilderWidget/functionsplitter" ), functionsplit->saveState() );
253 delete mExpressionTreeMenuProvider;
261 mExpressionTreeView->loadRecent( recentCollection );
264 mExpressionTreeView->loadUserExpressions();
269 init( context, recentCollection, flags );
275 init( context, recentCollection, flags );
276 mExpressionTreeView->loadFieldNames( fields );
283 mExpressionTreeView->setLayer( mLayer );
284 mExpressionPreviewWidget->setLayer( mLayer );
291 expressionContextUpdated();
296void QgsExpressionBuilderWidget::expressionContextUpdated()
299 mExpressionTreeView->setExpressionContext( mExpressionContext );
300 mExpressionPreviewWidget->setExpressionContext( mExpressionContext );
308void QgsExpressionBuilderWidget::expressionTreeItemChanged(
QgsExpressionItem *item )
310 txtSearchEditValues->clear();
318 mValuesModel->clear();
321 cbxValuesInUse->setChecked(
false );
323 mValueGroupBox->setVisible( isField );
325 mShowHelpButton->setText( isField ? tr(
"Show Values" ) : tr(
"Show Help" ) );
328 QString help = loadFunctionHelp( item );
329 txtHelpText->setText( help );
331 bool isUserExpression = item->parent() && item->parent()->text() == mUserExpressionsGroupName;
333 btnRemoveExpression->setEnabled( isUserExpression );
334 btnEditExpression->setEnabled( isUserExpression );
337void QgsExpressionBuilderWidget::btnRun_pressed()
339 if ( !cmbFileNames->currentItem() )
342 QString file = cmbFileNames->currentItem()->text();
344 runPythonCode( txtPython->text() );
347void QgsExpressionBuilderWidget::runPythonCode(
const QString &code )
351 QString pythontext = code;
354 mExpressionTreeView->refresh();
374 QDir myDir( mFunctionsPath );
375 if ( !myDir.exists() )
377 myDir.mkpath( mFunctionsPath );
380 if ( !fileName.endsWith( QLatin1String(
".py" ) ) )
382 fileName.append(
".py" );
385 fileName = mFunctionsPath + QDir::separator() + fileName;
386 QFile myFile( fileName );
387 if ( myFile.open( QIODevice::WriteOnly | QFile::Truncate ) )
389 QTextStream myFileStream( &myFile );
390#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
391 myFileStream.setCodec(
"UTF-8" );
393 myFileStream << txtPython->text() << Qt::endl;
400 mFunctionsPath = path;
402 dir.setNameFilters( QStringList() << QStringLiteral(
"*.py" ) );
403 QStringList files = dir.entryList( QDir::Files );
404 cmbFileNames->clear();
405 const auto constFiles = files;
406 for (
const QString &name : constFiles )
408 QFileInfo info( mFunctionsPath + QDir::separator() + name );
409 if ( info.baseName() == QLatin1String(
"__init__" ) )
continue;
410 QListWidgetItem *item =
new QListWidgetItem(
QgsApplication::getThemeIcon( QStringLiteral(
"console/iconTabEditorConsole.svg" ) ), info.baseName() );
411 cmbFileNames->addItem( item );
413 if ( !cmbFileNames->currentItem() )
415 cmbFileNames->setCurrentRow( 0 );
418 if ( cmbFileNames->count() == 0 )
422 txtPython->setText( QStringLiteral(
"'''\n#Sample custom function file\n"
423 "#(uncomment to use and customize or Add button to create a new file) \n%1 \n '''" ).arg( txtPython->text() ) );
430 QList<QListWidgetItem *> items = cmbFileNames->findItems( fileName, Qt::MatchExactly );
431 if ( !items.isEmpty() )
434 QListWidgetItem *item =
new QListWidgetItem(
QgsApplication::getThemeIcon( QStringLiteral(
"console/iconTabEditorConsole.svg" ) ), fileName );
435 cmbFileNames->insertItem( 0, item );
436 cmbFileNames->setCurrentRow( 0 );
440 txtPython->setText( templatetxt );
444void QgsExpressionBuilderWidget::btnNewFile_pressed()
447 QString text = QInputDialog::getText(
this, tr(
"New File" ),
448 tr(
"New file name:" ), QLineEdit::Normal,
450 if ( ok && !text.isEmpty() )
453 btnRemoveFile->setEnabled( cmbFileNames->count() > 0 );
457void QgsExpressionBuilderWidget::btnRemoveFile_pressed()
459 if ( QMessageBox::question(
this, tr(
"Remove File" ),
460 tr(
"Are you sure you want to remove current functions file?" ),
461 QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) == QMessageBox::No )
464 int currentRow = cmbFileNames->currentRow();
465 QString fileName = cmbFileNames->currentItem()->text();
466 if ( QFile::remove( mFunctionsPath + QDir::separator() + fileName.append(
".py" ) ) )
469 QListWidgetItem *itemToRemove =
whileBlocking( cmbFileNames )->takeItem( currentRow );
473 if ( cmbFileNames->count() > 0 )
475 whileBlocking( cmbFileNames )->setCurrentRow( currentRow > 0 ? currentRow - 1 : 0 );
476 loadCodeFromFile( mFunctionsPath + QDir::separator() + cmbFileNames->currentItem()->text() );
480 btnRemoveFile->setEnabled(
false );
486 QMessageBox::warning(
this, tr(
"Remove file" ), tr(
"Failed to remove function file '%1'." ).arg( fileName ) );
490void QgsExpressionBuilderWidget::cmbFileNames_currentItemChanged( QListWidgetItem *item, QListWidgetItem *lastitem )
494 QString filename = lastitem->text();
497 QString path = mFunctionsPath + QDir::separator() + item->text();
503 if ( !path.endsWith( QLatin1String(
".py" ) ) )
504 path.append(
".py" );
506 txtPython->loadScript( path );
511 txtPython->setText( code );
514void QgsExpressionBuilderWidget::insertExpressionText(
const QString &text )
518 txtExpressionString->setFocus();
523 Q_UNUSED( fieldValues )
527void QgsExpressionBuilderWidget::fillFieldValues(
const QString &fieldName,
QgsVectorLayer *layer,
int countLimit,
bool forceUsedValues )
539 if ( fieldIndex < 0 )
546 if ( cbxValuesInUse->isVisible() && !cbxValuesInUse->isChecked() && !forceUsedValues )
550 values =
formatter->availableValues( setup.
config(), countLimit, fieldFormatterContext );
556 std::sort( values.begin(), values.end() );
558 mValuesModel->clear();
559 for (
const QVariant &value : std::as_const( values ) )
562 bool forceRepresentedValue =
false;
564 strValue = QStringLiteral(
"NULL" );
565 else if ( value.userType() == QMetaType::Type::Int || value.userType() == QMetaType::Type::Double || value.userType() == QMetaType::Type::LongLong || value.userType() == QMetaType::Type::Bool )
566 strValue = value.toString();
567 else if ( value.userType() == QMetaType::Type::QStringList )
570 const QStringList strList = value.toStringList();
571 for ( QString
str : strList )
573 if ( !result.isEmpty() )
574 result.append( QStringLiteral(
", " ) );
576 result.append(
'\'' +
str.replace(
'\'', QLatin1String(
"''" ) ) +
'\'' );
578 strValue = QStringLiteral(
"array(%1)" ).arg( result );
579 forceRepresentedValue =
true;
581 else if ( value.userType() == QMetaType::Type::QVariantList )
584 const QList list = value.toList();
585 for (
const QVariant &item : list )
587 if ( !result.isEmpty() )
588 result.append( QStringLiteral(
", " ) );
590 result.append( item.toString() );
592 strValue = QStringLiteral(
"array(%1)" ).arg( result );
593 forceRepresentedValue =
true;
596 strValue =
'\'' + value.toString().replace(
'\'', QLatin1String(
"''" ) ) +
'\'';
598 QString representedValue =
formatter->representValue(
layer, fieldIndex, setup.
config(), QVariant(), value );
599 if ( forceRepresentedValue || representedValue != value.toString() )
600 representedValue = representedValue + QStringLiteral(
" [" ) + strValue +
']';
602 QStandardItem *item =
new QStandardItem( representedValue );
603 item->setData( strValue );
604 mValuesModel->appendRow( item );
615 return QStringLiteral(
"<head><style>" ) + helpStylesheet() + QStringLiteral(
"</style></head><body>" ) + helpContents + QStringLiteral(
"</body>" );
623 return mExpressionValid;
628 mExpressionPreviewWidget->setCustomPreviewGenerator( label, choices, previewContextGenerator );
633 mExpressionTreeView->saveToRecent(
expressionText(), collection );
638 mExpressionTreeView->loadRecent( collection );
643 return mExpressionTreeView;
654 mExpressionTreeView->saveToUserExpressions( label, expression, helpText );
659 mExpressionTreeView->removeFromUserExpressions( label );
665 mExpressionPreviewWidget->setGeomCalculator( da );
670 return txtExpressionString->text();
675 txtExpressionString->setText( expression );
680 return lblExpected->text();
685 lblExpected->setText( expected );
686 mExpectedOutputFrame->setVisible( !expected.isNull() );
691 mExpressionContext = context;
692 expressionContextUpdated();
695void QgsExpressionBuilderWidget::txtExpressionString_textChanged()
699 btnClearEditor->setEnabled( ! txtExpressionString->text().isEmpty() );
700 btnSaveExpression->setEnabled(
false );
702 mExpressionPreviewWidget->setExpressionText( text );
707 return mExpressionPreviewWidget->parserError();
712 mExpressionPreviewWidget->setVisible( isVisible );
717 return mExpressionPreviewWidget->evalError();
723 return mExpressionTreeView->model();
735 mExpressionTreeView->setProject(
project );
740 QWidget::showEvent( e );
741 txtExpressionString->setFocus();
744void QgsExpressionBuilderWidget::createErrorMarkers(
const QList<QgsExpression::ParserError> &errors )
749 int errorFirstLine = error.firstLine - 1 ;
750 int errorFirstColumn = error.firstColumn - 1;
751 int errorLastColumn = error.lastColumn - 1;
752 int errorLastLine = error.lastLine - 1;
758 errorFirstLine = errorLastLine;
759 errorFirstColumn = errorLastColumn - 1;
761 txtExpressionString->fillIndicatorRange( errorFirstLine,
764 errorLastColumn, error.errorType );
775 txtExpressionString->SendScintilla( QsciScintilla::SCI_SETINDICATORCURRENT, FUNCTION_MARKER_ID );
776 txtExpressionString->SendScintilla( QsciScintilla::SCI_SETINDICATORVALUE, node->
fnIndex() );
779 int start_pos = txtExpressionString->positionFromLineIndex( inNode->
parserFirstLine - 1, start );
780 txtExpressionString->SendScintilla( QsciScintilla::SCI_INDICATORFILLRANGE, start_pos, end - start );
783 const QList< QgsExpressionNode * > nodeList = node->
args()->
list();
798 createMarkers( node->
operand() );
811 createMarkers( node->
opLeft() );
812 createMarkers( node->
opRight() );
824 const QList< QgsExpressionNode * > nodeList = node->
list()->
list();
835 const QList<QgsExpressionNodeCondition::WhenThen *> conditions = node->
conditions();
838 createMarkers( cond->whenExp() );
839 createMarkers( cond->thenExp() );
843 createMarkers( node->
elseExp() );
854void QgsExpressionBuilderWidget::clearFunctionMarkers()
856 int lastLine = txtExpressionString->lines() - 1;
857 txtExpressionString->clearIndicatorRange( 0, 0, lastLine, txtExpressionString->text( lastLine ).length() - 1, FUNCTION_MARKER_ID );
860void QgsExpressionBuilderWidget::clearErrors()
862 int lastLine = txtExpressionString->lines() - 1;
871void QgsExpressionBuilderWidget::txtSearchEditValues_textChanged()
873 mProxyValues->setFilterCaseSensitivity( Qt::CaseInsensitive );
874 mProxyValues->setFilterWildcard( txtSearchEditValues->text() );
877void QgsExpressionBuilderWidget::mValuesListView_doubleClicked(
const QModelIndex &index )
880 txtExpressionString->
insertText(
' ' + index.data( Qt::UserRole + 1 ).toString() +
' ' );
881 txtExpressionString->setFocus();
884void QgsExpressionBuilderWidget::operatorButtonClicked()
886 QPushButton *button = qobject_cast<QPushButton *>( sender() );
889 txtExpressionString->
insertText(
' ' + button->text() +
' ' );
890 txtExpressionString->setFocus();
909 mValueGroupBox->show();
929 mValueGroupBox->show();
949 mValueGroupBox->show();
969 mValueGroupBox->show();
973void QgsExpressionBuilderWidget::txtPython_textChanged()
975 lblAutoSave->setText( tr(
"Saving…" ) );
985 if ( tabWidget->currentIndex() != 1 )
988 QListWidgetItem *item = cmbFileNames->currentItem();
992 QString file = item->text();
994 lblAutoSave->setText( QStringLiteral(
"Saved" ) );
995 QGraphicsOpacityEffect *effect =
new QGraphicsOpacityEffect();
996 lblAutoSave->setGraphicsEffect( effect );
997 QPropertyAnimation *anim =
new QPropertyAnimation( effect,
"opacity" );
998 anim->setDuration( 2000 );
999 anim->setStartValue( 1.0 );
1000 anim->setEndValue( 0.0 );
1001 anim->setEasingCurve( QEasingCurve::OutQuad );
1002 anim->start( QAbstractAnimation::DeleteWhenStopped );
1009 if ( dlg.exec() == QDialog::DialogCode::Accepted )
1011 mExpressionTreeView->saveToUserExpressions( dlg.label().simplified(), dlg.expression(), dlg.helpText() );
1025 ( item->parent() && item->parent()->text() != mUserExpressionsGroupName ) )
1032 if ( dlg.exec() == QDialog::DialogCode::Accepted )
1035 if ( dlg.isLabelModified() )
1037 mExpressionTreeView->removeFromUserExpressions( item->text() );
1040 mExpressionTreeView->saveToUserExpressions( dlg.label().simplified(), dlg.expression(), dlg.helpText() );
1055 ( item->parent() && item->parent()->text() != mUserExpressionsGroupName ) )
1058 if ( QMessageBox::Yes == QMessageBox::question(
this, tr(
"Remove Stored Expression" ),
1059 tr(
"Do you really want to remove stored expressions '%1'?" ).arg( item->text() ),
1060 QMessageBox::Yes | QMessageBox::No ) )
1062 mExpressionTreeView->removeFromUserExpressions( item->text() );
1067void QgsExpressionBuilderWidget::exportUserExpressions_pressed()
1070 QString lastSaveDir = settings.
value( QStringLiteral(
"lastExportExpressionsDir" ), QDir::homePath(),
QgsSettings::App ).toString();
1071 QString saveFileName = QFileDialog::getSaveFileName(
1073 tr(
"Export User Expressions" ),
1075 tr(
"User expressions" ) +
" (*.json)" );
1080 if ( saveFileName.isEmpty() )
1083 QFileInfo saveFileInfo( saveFileName );
1085 if ( saveFileInfo.suffix().isEmpty() )
1087 QString saveFileNameWithSuffix = saveFileName.append(
".json" );
1088 saveFileInfo = QFileInfo( saveFileNameWithSuffix );
1093 QJsonDocument exportJson = mExpressionTreeView->exportUserExpressions();
1094 QFile jsonFile( saveFileName );
1096 if ( !jsonFile.open( QFile::WriteOnly | QIODevice::Truncate ) )
1097 QMessageBox::warning(
this, tr(
"Export user expressions" ), tr(
"Error while creating the expressions file." ) );
1099 if ( ! jsonFile.write( exportJson.toJson() ) )
1100 QMessageBox::warning(
this, tr(
"Export user expressions" ), tr(
"Error while creating the expressions file." ) );
1105void QgsExpressionBuilderWidget::importUserExpressions_pressed()
1108 QString lastImportDir = settings.
value( QStringLiteral(
"lastImportExpressionsDir" ), QDir::homePath(),
QgsSettings::App ).toString();
1109 QString loadFileName = QFileDialog::getOpenFileName(
1111 tr(
"Import User Expressions" ),
1113 tr(
"User expressions" ) +
" (*.json)" );
1115 if ( loadFileName.isEmpty() )
1118 QFileInfo loadFileInfo( loadFileName );
1122 QFile jsonFile( loadFileName );
1124 if ( !jsonFile.open( QFile::ReadOnly ) )
1125 QMessageBox::warning(
this, tr(
"Import User Expressions" ), tr(
"Error while reading the expressions file." ) );
1127 QTextStream jsonStream( &jsonFile );
1128 QString jsonString = jsonFile.readAll();
1131 QJsonDocument importJson = QJsonDocument::fromJson( jsonString.toUtf8() );
1133 if ( importJson.isNull() )
1135 QMessageBox::warning(
this, tr(
"Import User Expressions" ), tr(
"Error while reading the expressions file." ) );
1139 mExpressionTreeView->loadExpressionsFromJson( importJson );
1145 return mExpressionTreeView->findExpressions( label );
1148void QgsExpressionBuilderWidget::indicatorClicked(
int line,
int index, Qt::KeyboardModifiers state )
1150 if ( state & Qt::ControlModifier )
1152 int position = txtExpressionString->positionFromLineIndex( line, index );
1153 long fncIndex = txtExpressionString->SendScintilla( QsciScintilla::SCI_INDICATORVALUEAT, FUNCTION_MARKER_ID,
static_cast<long int>( position ) );
1155 QString help = getFunctionHelp( func );
1156 txtHelpText->setText( help );
1160void QgsExpressionBuilderWidget::onExpressionParsed(
bool state )
1164 mExpressionValid = state;
1167 createMarkers( mExpressionPreviewWidget->rootNode() );
1171 createErrorMarkers( mExpressionPreviewWidget->parserErrors() );
1175QString QgsExpressionBuilderWidget::helpStylesheet()
const
1181 style +=
" .functionname {color: #0a6099; font-weight: bold;} "
1182 " .argument {font-family: monospace; color: #bf0c0c; font-style: italic; } "
1183 " td.argument { padding-right: 10px; }";
1188QString QgsExpressionBuilderWidget::loadFunctionHelp(
QgsExpressionItem *expressionItem )
1190 if ( !expressionItem )
1193 QString helpContents = expressionItem->
getHelpText();
1196 if ( helpContents.isEmpty() )
1198 QString name = expressionItem->data( Qt::UserRole ).toString();
1206 return "<head><style>" + helpStylesheet() +
"</style></head><body>" + helpContents +
"</body>";
1213QMenu *QgsExpressionBuilderWidget::ExpressionTreeMenuProvider::createContextMenu(
QgsExpressionItem *item )
1215 QMenu *menu =
nullptr;
1219 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 QGIS expression editor based on QScintilla2.
void setExpressionContext(const QgsExpressionContext &context)
Variables and functions from this expression context will be added to the API.
void setFields(const QgsFields &fields)
Field names will be added to the API.
void insertText(const QString &text)
Insert text at cursor position, or replace any selected text if user has made a selection.
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 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).
Q_INVOKABLE 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, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based data sets.
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.