QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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 
16 #include "qgsexpressionlineedit.h"
17 #include "qgsfilterlineedit.h"
18 #include "qgsexpressioncontext.h"
19 #include "qgsapplication.h"
21 #include "qgscodeeditorsql.h"
22 #include <QHBoxLayout>
23 #include <QVBoxLayout>
24 #include <QToolButton>
25 
26 
28  : QWidget( parent )
29  , mLineEdit( nullptr )
30  , mCodeEditor( nullptr )
31  , mExpressionDialogTitle( tr( "Expression dialog" ) )
32  , mDa( nullptr )
33  , mLayer( nullptr )
34 {
35  mButton = new QToolButton();
36  mButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
37  mButton->setIcon( QgsApplication::getThemeIcon( "/mIconExpression.svg" ) );
38  connect( mButton, SIGNAL( clicked() ), this, SLOT( editExpression() ) );
39 
40  //sets up layout
41  setMultiLine( false );
42 
43  mExpressionContext = QgsExpressionContext();
44  mExpressionContext << QgsExpressionContextUtils::globalScope()
46 }
47 
49 {
50  mExpressionDialogTitle = title;
51 }
52 
54 {
55  QString exp = expression();
56 
57  if ( multiLine && !mCodeEditor )
58  {
59  mCodeEditor = new QgsCodeEditorSQL();
60  mCodeEditor->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
61  delete mLineEdit;
62  mLineEdit = nullptr;
63 
64  QHBoxLayout* newLayout = new QHBoxLayout();
65  newLayout->setContentsMargins( 0, 0, 0, 0 );
66  newLayout->addWidget( mCodeEditor );
67 
68  QVBoxLayout* vLayout = new QVBoxLayout();
69  vLayout->addWidget( mButton );
70  vLayout->addStretch();
71  newLayout->addLayout( vLayout );
72 
73  delete layout();
74  setLayout( newLayout );
75 
76  setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
77 
78  setFocusProxy( mCodeEditor );
79  connect( mCodeEditor, SIGNAL( textChanged() ), this, SLOT( expressionEdited() ) );
80 
81  setExpression( exp );
82  }
83  else if ( !multiLine && !mLineEdit )
84  {
85  delete mCodeEditor;
86  mCodeEditor = nullptr;
87  mLineEdit = new QgsFilterLineEdit();
88  mLineEdit->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
89 
90  QHBoxLayout* newLayout = new QHBoxLayout();
91  newLayout->setContentsMargins( 0, 0, 0, 0 );
92  newLayout->addWidget( mLineEdit );
93  newLayout->addWidget( mButton );
94 
95  delete layout();
96  setLayout( newLayout );
97 
98  setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
99 
100  setFocusProxy( mLineEdit );
101  connect( mLineEdit, SIGNAL( textChanged( QString ) ), this, SLOT( expressionEdited( QString ) ) );
102 
103  setExpression( exp );
104  }
105 }
106 
108 {
109  mDa.reset( new QgsDistanceArea( da ) );
110 }
111 
113 {
114  mLayer = layer;
115 }
116 
118 {
119  if ( mLineEdit )
120  return mLineEdit->text();
121  else if ( mCodeEditor )
122  return mCodeEditor->text();
123 
124  return QString();
125 }
126 
127 bool QgsExpressionLineEdit::isValidExpression( QString *expressionError ) const
128 {
129  QString temp;
130  return QgsExpression::isValid( expression(), &mExpressionContext, expressionError ? *expressionError : temp );
131 }
132 
133 void QgsExpressionLineEdit::setExpression( const QString& newExpression )
134 {
135  if ( mLineEdit )
136  mLineEdit->setText( newExpression );
137  else if ( mCodeEditor )
138  mCodeEditor->setText( newExpression );
139 }
140 
141 void QgsExpressionLineEdit::editExpression()
142 {
143  QString currentExpression = expression();
144 
145  QgsExpressionContext context = mExpressionContext;
146 
147  QgsExpressionBuilderDialog dlg( mLayer, currentExpression, this, "generic", context );
148  if ( !mDa.isNull() )
149  {
150  dlg.setGeomCalculator( *mDa );
151  }
152  dlg.setWindowTitle( mExpressionDialogTitle );
153 
154  if ( dlg.exec() )
155  {
156  QString newExpression = dlg.expressionText();
157  setExpression( newExpression );
158  }
159 }
160 
161 void QgsExpressionLineEdit::expressionEdited()
162 {
163  emit expressionChanged( expression() );
164 }
165 
166 void QgsExpressionLineEdit::expressionEdited( const QString& expression )
167 {
168  updateLineEditStyle( expression );
169  emit expressionChanged( expression );
170 }
171 
173 {
174  if ( event->type() == QEvent::EnabledChange )
175  {
176  updateLineEditStyle( expression() );
177  }
178 }
179 
180 void QgsExpressionLineEdit::updateLineEditStyle( const QString& expression )
181 {
182  if ( !mLineEdit )
183  return;
184 
186  if ( !isEnabled() )
187  {
188  palette.setColor( QPalette::Text, Qt::gray );
189  }
190  else
191  {
192  bool isValid = true;
193  if ( !expression.isEmpty() )
194  {
195  isValid = isExpressionValid( expression );
196  }
197  if ( !isValid )
198  {
199  palette.setColor( QPalette::Text, Qt::red );
200  }
201  else
202  {
203  palette.setColor( QPalette::Text, Qt::black );
204  }
205  }
206  mLineEdit->setPalette( palette );
207 }
208 
209 bool QgsExpressionLineEdit::isExpressionValid( const QString& expressionStr )
210 {
211  QgsExpression expression( expressionStr );
212  expression.prepare( &mExpressionContext );
213  return !expression.hasParserError();
214 }
QLayout * layout() const
Class for parsing and evaluation of expressions (formerly called "search strings").
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
Type type() const
void setContentsMargins(int left, int top, int right, int bottom)
const QPalette & palette() const
void setColor(ColorGroup group, ColorRole role, const QColor &color)
Q_DECL_DEPRECATED bool prepare(const QgsFields &fields)
Get the expression ready for evaluation - find out column indexes.
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
void setMultiLine(bool multiLine)
Sets whether the widget should show a multiline text editor.
int exec()
void setIcon(const QIcon &icon)
void reset(T *other)
bool isEnabled() const
void addWidget(QWidget *widget, int stretch, QFlags< Qt::AlignmentFlag > alignment)
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
void setLayout(QLayout *layout)
void setExpression(const QString &expression)
Sets the current expression to show in the widget.
bool isValid() const
Checks if this expression is valid.
QString expression() const
Returns the current expression shown in the widget.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFocusProxy(QWidget *w)
bool isEmpty() const
void setGeomCalculator(const QgsDistanceArea &da)
Sets geometry calculator used in distance/area calculations.
QLineEdit subclass with built in support for clearing the widget&#39;s value and handling custom null val...
void setSizePolicy(QSizePolicy)
void setGeomCalculator(const QgsDistanceArea &distanceArea)
Set the geometry calculator used in the expression dialog.
void expressionChanged(const QString &expression)
Emitted when the expression is changed.
void changeEvent(QEvent *event) override
General purpose distance and area calculator.
bool isNull() const
void setExpressionDialogTitle(const QString &title)
Sets the title used in the expression builder dialog.
void setLayer(QgsVectorLayer *layer)
Sets a layer associated with the widget.
A SQL editor based on QScintilla2.
void addStretch(int stretch)
void setWindowTitle(const QString &)
bool isValidExpression(QString *expressionError=nullptr) const
Returns true if the current expression is valid.
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
QgsExpressionLineEdit(QWidget *parent=nullptr)
Constructor for QgsExpressionLineEdit.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Represents a vector layer which manages a vector based data sets.
virtual bool event(QEvent *event)
A generic dialog for building expression strings.
void addLayout(QLayout *layout, int stretch)