QGIS API Documentation 3.27.0-Master (1d7a28cfd2)
qgsexpressionlineedit.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsexpressionlineedit.cpp
3 ------------------------
4 Date : 18.08.2016
5 Copyright : (C) 2016 Nyall Dawson
6 Email : nyall dot dawson at gmail dot com
7***************************************************************************
8* *
9* This program is free software; you can redistribute it and/or modify *
10* it under the terms of the GNU General Public License as published by *
11* the Free Software Foundation; either version 2 of the License, or *
12* (at your option) any later version. *
13* *
14***************************************************************************/
15
17#include "qgsfilterlineedit.h"
19#include "qgsapplication.h"
22#include "qgscodeeditorsql.h"
23#include "qgsproject.h"
24#include "qgsvectorlayer.h"
26
27#include <QHBoxLayout>
28#include <QVBoxLayout>
29#include <QToolButton>
30
31
33 : QWidget( parent )
34 , mExpressionDialogTitle( tr( "Expression Dialog" ) )
35{
36 mButton = new QToolButton();
37 mButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
38 mButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconExpression.svg" ) ) );
39 connect( mButton, &QAbstractButton::clicked, this, &QgsExpressionLineEdit::editExpression );
40
41 //sets up layout
42 setMultiLine( false );
43
44 mExpressionContext = QgsExpressionContext();
45 mExpressionContext << QgsExpressionContextUtils::globalScope()
47}
48
50
52{
53 mExpressionDialogTitle = title;
54}
55
57{
58 const QString exp = expression();
59
60 if ( multiLine && !mCodeEditor )
61 {
62 mCodeEditor = new QgsCodeEditorExpression();
63 mCodeEditor->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
64 delete mLineEdit;
65 mLineEdit = nullptr;
66
67 QHBoxLayout *newLayout = new QHBoxLayout();
68 newLayout->setContentsMargins( 0, 0, 0, 0 );
69 newLayout->addWidget( mCodeEditor );
70
71 QVBoxLayout *vLayout = new QVBoxLayout();
72 vLayout->addWidget( mButton );
73 vLayout->addStretch();
74 newLayout->addLayout( vLayout );
75
76 delete layout();
77 setLayout( newLayout );
78
79 setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
80
81 setFocusProxy( mCodeEditor );
82 connect( mCodeEditor, &QsciScintilla::textChanged, this, static_cast < void ( QgsExpressionLineEdit::* )() > ( &QgsExpressionLineEdit::expressionEdited ) );
83
84 setExpression( exp );
85 }
86 else if ( !multiLine && !mLineEdit )
87 {
88 delete mCodeEditor;
89 mCodeEditor = nullptr;
90 mLineEdit = new QgsFilterLineEdit();
91 mLineEdit->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
92
93 QHBoxLayout *newLayout = new QHBoxLayout();
94 newLayout->setContentsMargins( 0, 0, 0, 0 );
95 newLayout->addWidget( mLineEdit );
96 newLayout->addWidget( mButton );
97
98 delete layout();
99 setLayout( newLayout );
100
101 setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
102
103 setFocusProxy( mLineEdit );
104 connect( mLineEdit, &QLineEdit::textChanged, this, static_cast < void ( QgsExpressionLineEdit::* )( const QString & ) > ( &QgsExpressionLineEdit::expressionEdited ) );
105
106 setExpression( exp );
107 }
108}
109
111{
112 return mExpectedOutputFormat;
113}
114
116{
117 mExpectedOutputFormat = expected;
118}
119
121{
122 mDa.reset( new QgsDistanceArea( da ) );
123}
124
126{
127 if ( !mExpressionContextGenerator || mExpressionContextGenerator == mLayer )
128 mExpressionContextGenerator = layer;
129 mLayer = layer;
130}
131
133{
134 if ( mLineEdit )
135 return mLineEdit->text();
136 else if ( mCodeEditor )
137 return mCodeEditor->text();
138
139 return QString();
140}
141
142bool QgsExpressionLineEdit::isValidExpression( QString *expressionError ) const
143{
144 QString temp;
145 const QgsExpressionContext context = mExpressionContextGenerator ? mExpressionContextGenerator->createExpressionContext() : mExpressionContext;
146 return QgsExpression::checkExpression( expression(), &context, expressionError ? *expressionError : temp );
147}
148
150{
151 mExpressionContextGenerator = generator;
152}
153
154void QgsExpressionLineEdit::setExpression( const QString &newExpression )
155{
156 if ( mLineEdit )
157 mLineEdit->setText( newExpression );
158 else if ( mCodeEditor )
159 mCodeEditor->setText( newExpression );
160}
161
162void QgsExpressionLineEdit::editExpression()
163{
164 const QString currentExpression = expression();
165
166 const QgsExpressionContext context = mExpressionContextGenerator ? mExpressionContextGenerator->createExpressionContext() : mExpressionContext;
167
168 QgsExpressionBuilderDialog dlg( mLayer, currentExpression, this, QStringLiteral( "generic" ), context );
169 dlg.setExpectedOutputFormat( mExpectedOutputFormat );
170 if ( mDa )
171 {
172 dlg.setGeomCalculator( *mDa );
173 }
174 dlg.setWindowTitle( mExpressionDialogTitle );
175
176 if ( dlg.exec() )
177 {
178 const QString newExpression = dlg.expressionText();
179 setExpression( newExpression );
180 }
181}
182
183void QgsExpressionLineEdit::expressionEdited()
184{
186}
187
188void QgsExpressionLineEdit::expressionEdited( const QString &expression )
189{
190 updateLineEditStyle( expression );
192}
193
195{
196 if ( event->type() == QEvent::EnabledChange )
197 {
198 updateLineEditStyle( expression() );
199 }
200}
201
202void QgsExpressionLineEdit::updateLineEditStyle( const QString &expression )
203{
204 if ( !mLineEdit )
205 return;
206
207 QPalette palette = mLineEdit->palette();
208 if ( !isEnabled() )
209 {
210 palette.setColor( QPalette::Text, Qt::gray );
211 }
212 else
213 {
214 bool isValid = true;
215 if ( !expression.isEmpty() )
216 {
217 isValid = isExpressionValid( expression );
218 }
219 if ( !isValid )
220 {
221 palette.setColor( QPalette::Text, Qt::red );
222 }
223 else
224 {
225 palette.setColor( QPalette::Text, Qt::black );
226 }
227 }
228 mLineEdit->setPalette( palette );
229}
230
231bool QgsExpressionLineEdit::isExpressionValid( const QString &expressionStr )
232{
233 QgsExpression expression( expressionStr );
234
235 const QgsExpressionContext context = mExpressionContextGenerator ? mExpressionContextGenerator->createExpressionContext() : mExpressionContext;
236 expression.prepare( &mExpressionContext );
237 return !expression.hasParserError();
238}
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
A QGIS expression editor based on QScintilla2.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
A generic dialog for building expression strings.
Abstract interface for generating an expression context.
virtual QgsExpressionContext createExpressionContext() const =0
This method needs to be reimplemented in all classes which implement this interface and return an exp...
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
The QgsExpressionLineEdit widget includes a line edit for entering expressions together with a button...
QString expression() const
Returns the current expression shown in the widget.
void setMultiLine(bool multiLine)
Sets whether the widget should show a multiline text editor.
void changeEvent(QEvent *event) override
bool isValidExpression(QString *expressionError=nullptr) const
Determines if the current expression is valid.
~QgsExpressionLineEdit() override
void expressionChanged(const QString &expression)
Emitted when the expression is changed.
void registerExpressionContextGenerator(const QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
void setExpectedOutputFormat(const QString &expected)
Set the expected format string, which is shown in the expression builder dialog for the widget.
void setGeomCalculator(const QgsDistanceArea &distanceArea)
Set the geometry calculator used in the expression dialog.
void setExpressionDialogTitle(const QString &title)
Sets the title used in the expression builder dialog.
void setExpression(const QString &expression)
Sets the current expression to show in the widget.
QString expectedOutputFormat() const
Returns the expected format string, which is shown in the expression builder dialog for the widget.
QgsExpressionLineEdit(QWidget *parent=nullptr)
Constructor for QgsExpressionLineEdit.
void setLayer(QgsVectorLayer *layer)
Sets a layer associated with the widget.
Class for parsing and evaluation of expressions (formerly called "search strings").
static bool checkExpression(const QString &text, const QgsExpressionContext *context, QString &errorMessage)
Tests whether a string is a valid expression.
QLineEdit subclass with built in support for clearing the widget's value and handling custom null val...
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:477
Represents a vector layer which manages a vector based data sets.