QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
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
18#include <memory>
19
20#include "qgsapplication.h"
26#include "qgsfilterlineedit.h"
27#include "qgsproject.h"
28#include "qgsvectorlayer.h"
29
30#include <QHBoxLayout>
31#include <QString>
32#include <QToolButton>
33#include <QVBoxLayout>
34
35#include "moc_qgsexpressionlineedit.cpp"
36
37using namespace Qt::StringLiterals;
38
40 : QWidget( parent )
41 , mExpressionDialogTitle( tr( "Expression Builder" ) )
42{
43 mButton = new QToolButton();
44 mButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
45 mButton->setIcon( QgsApplication::getThemeIcon( u"/mIconExpression.svg"_s ) );
46 connect( mButton, &QAbstractButton::clicked, this, &QgsExpressionLineEdit::editExpression );
47
48 //sets up layout
49 setMultiLine( false );
50
51 mExpressionContext = QgsExpressionContext();
52 mExpressionContext << QgsExpressionContextUtils::globalScope()
54}
55
57
59{
60 mExpressionDialogTitle = title;
61}
62
64{
65 const QString exp = expression();
66
67 if ( multiLine && !mCodeEditor )
68 {
69 mCodeEditor = new QgsCodeEditorExpression();
70 mCodeEditor->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
71 delete mLineEdit;
72 mLineEdit = nullptr;
73
74 QHBoxLayout *newLayout = new QHBoxLayout();
75 newLayout->setContentsMargins( 0, 0, 0, 0 );
76 newLayout->addWidget( mCodeEditor );
77
78 QVBoxLayout *vLayout = new QVBoxLayout();
79 vLayout->addWidget( mButton );
80 vLayout->addStretch();
81 newLayout->addLayout( vLayout );
82
83 delete layout();
84 setLayout( newLayout );
85
86 setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
87
88 setFocusProxy( mCodeEditor );
89 connect( mCodeEditor, &QsciScintilla::textChanged, this, static_cast<void ( QgsExpressionLineEdit::* )()>( &QgsExpressionLineEdit::expressionEdited ) );
90
91 setExpression( exp );
92 }
93 else if ( !multiLine && !mLineEdit )
94 {
95 delete mCodeEditor;
96 mCodeEditor = nullptr;
97 mLineEdit = new QgsFilterLineEdit();
98 mLineEdit->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
99
100 QHBoxLayout *newLayout = new QHBoxLayout();
101 newLayout->setContentsMargins( 0, 0, 0, 0 );
102 newLayout->addWidget( mLineEdit );
103 newLayout->addWidget( mButton );
104
105 delete layout();
106 setLayout( newLayout );
107
108 setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
109
110 setFocusProxy( mLineEdit );
111 connect( mLineEdit, &QLineEdit::textChanged, this, static_cast<void ( QgsExpressionLineEdit::* )( const QString & )>( &QgsExpressionLineEdit::expressionEdited ) );
112
113 setExpression( exp );
114 }
115}
116
118{
119 return mExpectedOutputFormat;
120}
121
123{
124 mExpectedOutputFormat = expected;
125}
126
128{
129 mDa = std::make_unique<QgsDistanceArea>( da );
130}
131
133{
134 if ( !mExpressionContextGenerator || mExpressionContextGenerator == mLayer )
135 mExpressionContextGenerator = layer;
136 mLayer = layer;
137}
138
140{
141 if ( mLineEdit )
142 return mLineEdit->text();
143 else if ( mCodeEditor )
144 return mCodeEditor->text();
145
146 return QString();
147}
148
149bool QgsExpressionLineEdit::isValidExpression( QString *expressionError ) const
150{
151 QString temp;
152 const QgsExpressionContext context = mExpressionContextGenerator ? mExpressionContextGenerator->createExpressionContext() : mExpressionContext;
153 return QgsExpression::checkExpression( expression(), &context, expressionError ? *expressionError : temp );
154}
155
157{
158 mExpressionContextGenerator = generator;
159}
160
161void QgsExpressionLineEdit::setExpression( const QString &newExpression )
162{
163 if ( mLineEdit )
164 mLineEdit->setText( newExpression );
165 else if ( mCodeEditor )
166 mCodeEditor->setText( newExpression );
167}
168
169void QgsExpressionLineEdit::editExpression()
170{
171 const QString currentExpression = expression();
172
173 const QgsExpressionContext context = mExpressionContextGenerator ? mExpressionContextGenerator->createExpressionContext() : mExpressionContext;
174
175 QgsExpressionBuilderDialog dlg( mLayer, currentExpression, this, u"generic"_s, context );
176 dlg.setExpectedOutputFormat( mExpectedOutputFormat );
177 if ( mDa )
178 {
179 dlg.setGeomCalculator( *mDa );
180 }
181 dlg.setWindowTitle( mExpressionDialogTitle );
182
183 if ( dlg.exec() )
184 {
185 const QString newExpression = dlg.expressionText();
186 setExpression( newExpression );
187 }
188}
189
190void QgsExpressionLineEdit::expressionEdited()
191{
193}
194
195void QgsExpressionLineEdit::expressionEdited( const QString &expression )
196{
197 updateLineEditStyle( expression );
199}
200
202{
203 if ( event->type() == QEvent::EnabledChange )
204 {
205 updateLineEditStyle( expression() );
206 }
207}
208
209void QgsExpressionLineEdit::updateLineEditStyle( const QString &expression )
210{
211 if ( !mLineEdit )
212 return;
213
214 QPalette appPalette = qApp->palette();
215 QPalette palette = mLineEdit->palette();
216 if ( !isEnabled() )
217 {
218 palette.setColor( QPalette::Text, appPalette.color( QPalette::Disabled, QPalette::Text ) );
219 }
220 else
221 {
222 bool isValid = true;
223 if ( !expression.isEmpty() )
224 {
225 isValid = isExpressionValid( expression );
226 }
227 if ( !isValid )
228 {
229 palette.setColor( QPalette::Text, Qt::red );
230 }
231 else
232 {
233 palette.setColor( QPalette::Text, appPalette.color( QPalette::Text ) );
234 }
235 }
236 mLineEdit->setPalette( palette );
237}
238
239bool QgsExpressionLineEdit::isExpressionValid( const QString &expressionStr )
240{
241 QgsExpression expression( expressionStr );
242
243 const QgsExpressionContext context = mExpressionContextGenerator ? mExpressionContextGenerator->createExpressionContext() : mExpressionContext;
244 expression.prepare( &mExpressionContext );
245 return !expression.hasParserError();
246}
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...
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.
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.
Represents a vector layer which manages a vector based dataset.