QGIS API Documentation  3.0.2-Girona (307d082)
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"
22 #include "qgscodeeditorsql.h"
23 #include "qgsproject.h"
24 #include "qgsvectorlayer.h"
25 #include <QHBoxLayout>
26 #include <QVBoxLayout>
27 #include <QToolButton>
28 
29 
31  : QWidget( parent )
32  , mExpressionDialogTitle( tr( "Expression Dialog" ) )
33 {
34  mButton = new QToolButton();
35  mButton->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
36  mButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconExpression.svg" ) ) );
37  connect( mButton, &QAbstractButton::clicked, this, &QgsExpressionLineEdit::editExpression );
38 
39  //sets up layout
40  setMultiLine( false );
41 
42  mExpressionContext = QgsExpressionContext();
43  mExpressionContext << QgsExpressionContextUtils::globalScope()
45 }
46 
48 {
49  mExpressionDialogTitle = title;
50 }
51 
53 {
54  QString exp = expression();
55 
56  if ( multiLine && !mCodeEditor )
57  {
58  mCodeEditor = new QgsCodeEditorSQL();
59  mCodeEditor->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
60  delete mLineEdit;
61  mLineEdit = nullptr;
62 
63  QHBoxLayout *newLayout = new QHBoxLayout();
64  newLayout->setContentsMargins( 0, 0, 0, 0 );
65  newLayout->addWidget( mCodeEditor );
66 
67  QVBoxLayout *vLayout = new QVBoxLayout();
68  vLayout->addWidget( mButton );
69  vLayout->addStretch();
70  newLayout->addLayout( vLayout );
71 
72  delete layout();
73  setLayout( newLayout );
74 
75  setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
76 
77  setFocusProxy( mCodeEditor );
78  connect( mCodeEditor, &QsciScintilla::textChanged, this, static_cast < void ( QgsExpressionLineEdit::* )() > ( &QgsExpressionLineEdit::expressionEdited ) );
79 
80  setExpression( exp );
81  }
82  else if ( !multiLine && !mLineEdit )
83  {
84  delete mCodeEditor;
85  mCodeEditor = nullptr;
86  mLineEdit = new QgsFilterLineEdit();
87  mLineEdit->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
88 
89  QHBoxLayout *newLayout = new QHBoxLayout();
90  newLayout->setContentsMargins( 0, 0, 0, 0 );
91  newLayout->addWidget( mLineEdit );
92  newLayout->addWidget( mButton );
93 
94  delete layout();
95  setLayout( newLayout );
96 
97  setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Minimum );
98 
99  setFocusProxy( mLineEdit );
100  connect( mLineEdit, &QLineEdit::textChanged, this, static_cast < void ( QgsExpressionLineEdit::* )( const QString & ) > ( &QgsExpressionLineEdit::expressionEdited ) );
101 
102  setExpression( exp );
103  }
104 }
105 
107 {
108  mDa.reset( new QgsDistanceArea( da ) );
109 }
110 
112 {
113  if ( !mExpressionContextGenerator || mExpressionContextGenerator == mLayer )
114  mExpressionContextGenerator = layer;
115  mLayer = layer;
116 }
117 
119 {
120  if ( mLineEdit )
121  return mLineEdit->text();
122  else if ( mCodeEditor )
123  return mCodeEditor->text();
124 
125  return QString();
126 }
127 
128 bool QgsExpressionLineEdit::isValidExpression( QString *expressionError ) const
129 {
130  QString temp;
131  return QgsExpression::checkExpression( expression(), &mExpressionContext, expressionError ? *expressionError : temp );
132 }
133 
135 {
136  mExpressionContextGenerator = generator;
137 }
138 
139 void QgsExpressionLineEdit::setExpression( const QString &newExpression )
140 {
141  if ( mLineEdit )
142  mLineEdit->setText( newExpression );
143  else if ( mCodeEditor )
144  mCodeEditor->setText( newExpression );
145 }
146 
147 void QgsExpressionLineEdit::editExpression()
148 {
149  QString currentExpression = expression();
150 
151  QgsExpressionContext context = mExpressionContextGenerator ? mExpressionContextGenerator->createExpressionContext() : mExpressionContext;
152 
153  QgsExpressionBuilderDialog dlg( mLayer, currentExpression, this, QStringLiteral( "generic" ), context );
154  if ( mDa )
155  {
156  dlg.setGeomCalculator( *mDa );
157  }
158  dlg.setWindowTitle( mExpressionDialogTitle );
159 
160  if ( dlg.exec() )
161  {
162  QString newExpression = dlg.expressionText();
163  setExpression( newExpression );
164  }
165 }
166 
167 void QgsExpressionLineEdit::expressionEdited()
168 {
169  emit expressionChanged( expression() );
170 }
171 
172 void QgsExpressionLineEdit::expressionEdited( const QString &expression )
173 {
174  updateLineEditStyle( expression );
175  emit expressionChanged( expression );
176 }
177 
179 {
180  if ( event->type() == QEvent::EnabledChange )
181  {
182  updateLineEditStyle( expression() );
183  }
184 }
185 
186 void QgsExpressionLineEdit::updateLineEditStyle( const QString &expression )
187 {
188  if ( !mLineEdit )
189  return;
190 
191  QPalette palette;
192  if ( !isEnabled() )
193  {
194  palette.setColor( QPalette::Text, Qt::gray );
195  }
196  else
197  {
198  bool isValid = true;
199  if ( !expression.isEmpty() )
200  {
201  isValid = isExpressionValid( expression );
202  }
203  if ( !isValid )
204  {
205  palette.setColor( QPalette::Text, Qt::red );
206  }
207  else
208  {
209  palette.setColor( QPalette::Text, Qt::black );
210  }
211  }
212  mLineEdit->setPalette( palette );
213 }
214 
215 bool QgsExpressionLineEdit::isExpressionValid( const QString &expressionStr )
216 {
217  QgsExpression expression( expressionStr );
218  expression.prepare( &mExpressionContext );
219  return !expression.hasParserError();
220 }
void setMultiLine(bool multiLine)
Sets whether the widget should show a multiline text editor.
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
virtual QgsExpressionContext createExpressionContext() const =0
This method needs to be reimplemented in all classes which implement this interface and return an exp...
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
void setExpression(const QString &expression)
Sets the current expression to show in the widget.
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 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 setGeomCalculator(const QgsDistanceArea &distanceArea)
Set the geometry calculator used in the expression dialog.
Abstract interface for generating an expression context.
void expressionChanged(const QString &expression)
Emitted when the expression is changed.
void changeEvent(QEvent *event) override
A general purpose distance and area calculator, capable of performing ellipsoid based calculations...
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.
The QgsExpressionLineEdit widget includes a line edit for entering expressions together with a button...
void registerExpressionContextGenerator(const QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:383
bool isValidExpression(QString *expressionError=nullptr) const
Returns true if the current expression is valid.
QgsExpressionLineEdit(QWidget *parent=nullptr)
Constructor for QgsExpressionLineEdit.
Represents a vector layer which manages a vector based data sets.
A generic dialog for building expression strings.