QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
qgsexpressionpreviewwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsexpressionpreviewwidget.cpp
3  --------------------------------------
4  Date : march 2020 - quarantine day 12
5  Copyright : (C) 2020 by Denis Rouzaud
6  Email : [email protected]
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 "qgsmessageviewer.h"
18 #include "qgsvectorlayer.h"
19 #include "qgsfeaturepickerwidget.h"
20 
21 
22 
23 
24 
26  : QWidget( parent )
27 {
28  setupUi( this );
29  mPreviewLabel->clear();
30  mFeaturePickerWidget->setShowBrowserButtons( true );
31 
33  connect( mPreviewLabel, &QLabel::linkActivated, this, &QgsExpressionPreviewWidget::linkActivated );
34 }
35 
37 {
38  mLayer = layer;
39  mFeaturePickerWidget->setLayer( layer );
40 }
41 
42 void QgsExpressionPreviewWidget::setExpressionText( const QString &expression )
43 {
44  mExpressionText = expression;
45  refreshPreview();
46 }
47 
49 {
50  // todo: update the combo box if it has been set externaly?
51 
52  mExpressionContext.setFeature( feature );
53  refreshPreview();
54 }
55 
57 {
58  mDa = da;
59  mUseGeomCalculator = true;
60 }
61 
63 {
64  mExpressionContext = context;
65 }
66 
67 void QgsExpressionPreviewWidget::refreshPreview()
68 {
69  // If the string is empty the expression will still "fail" although
70  // we don't show the user an error as it will be confusing.
71  if ( mExpressionText.isEmpty() )
72  {
73  mPreviewLabel->clear();
74  mPreviewLabel->setStyleSheet( QString() );
75  setExpressionToolTip( QString() );
76  emit expressionParsed( false );
77  mExpression = QgsExpression();
78  }
79  else
80  {
81  mExpression = QgsExpression( mExpressionText );
82 
83  if ( !mExpressionContext.feature().isValid() )
84  {
85  if ( !mExpression.referencedColumns().isEmpty() || mExpression.needsGeometry() )
86  {
87  mPreviewLabel->setText( tr( "No feature was found on this layer to evaluate the expression." ) );
88  mPreviewLabel->setStyleSheet( QStringLiteral( "color: rgba(255, 6, 10, 255);" ) );
89  return;
90  }
91  }
92 
93  if ( mUseGeomCalculator )
94  {
95  // only set an explicit geometry calculator if a call to setGeomCalculator was made. If not,
96  // let the expression context handle this correctly
97  mExpression.setGeomCalculator( &mDa );
98  }
99 
100  QVariant value = mExpression.evaluate( &mExpressionContext );
101  QString preview = QgsExpression::formatPreviewString( value );
102  if ( !mExpression.hasEvalError() )
103  {
104  mPreviewLabel->setText( preview );
105  }
106 
107  if ( mExpression.hasParserError() || mExpression.hasEvalError() )
108  {
109  QString errorString = mExpression.parserErrorString().replace( "\n", "<br>" );
110  QString tooltip;
111  if ( mExpression.hasParserError() )
112  tooltip = QStringLiteral( "<b>%1:</b>"
113  "%2" ).arg( tr( "Parser Errors" ), errorString );
114  // Only show the eval error if there is no parser error.
115  if ( !mExpression.hasParserError() && mExpression.hasEvalError() )
116  tooltip += QStringLiteral( "<b>%1:</b> %2" ).arg( tr( "Eval Error" ), mExpression.evalErrorString() );
117 
118  mPreviewLabel->setText( tr( "Expression is invalid <a href=""more"">(more info)</a>" ) );
119  mPreviewLabel->setStyleSheet( QStringLiteral( "color: rgba(255, 6, 10, 255);" ) );
120  setExpressionToolTip( tooltip );
121  emit expressionParsed( false );
122  setParserError( mExpression.hasParserError() );
123  setEvalError( mExpression.hasEvalError() );
124  }
125  else
126  {
127  mPreviewLabel->setStyleSheet( QString() );
128  QString longerPreview = QgsExpression::formatPreviewString( value, true, 255 );
129  if ( longerPreview != preview )
130  setExpressionToolTip( longerPreview );
131  else
132  setExpressionToolTip( QString() );
133  emit expressionParsed( true );
134  setParserError( false );
135  setEvalError( false );
136  }
137  }
138 }
139 
140 void QgsExpressionPreviewWidget::linkActivated( const QString & )
141 {
142  QgsMessageViewer mv( this, QgsGuiUtils::ModalDialogFlags, false );
143  mv.setWindowTitle( tr( "More Info on Expression Error" ) );
144  mv.setMessageAsHtml( mToolTip );
145  mv.exec();
146 }
147 
148 void QgsExpressionPreviewWidget::setExpressionToolTip( const QString &toolTip )
149 {
150  if ( toolTip == mToolTip )
151  return;
152 
153  mToolTip = toolTip;
154  mPreviewLabel->setToolTip( mToolTip );
155  emit toolTipChanged( mToolTip );
156 }
157 
158 void QgsExpressionPreviewWidget::setParserError( bool parserError )
159 {
160  if ( parserError != mParserError )
161  {
162  mParserError = parserError;
163  emit parserErrorChanged();
164  }
165 }
167 {
168  return mParserError;
169 }
170 
171 void QgsExpressionPreviewWidget::setEvalError( bool evalError )
172 {
173  if ( evalError == mEvalError )
174  return;
175 
176  mEvalError = evalError;
177  emit evalErrorChanged();
178 }
179 
181 {
182  return mEvalError;
183 }
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsFeature feature() const
Convenience function for retrieving the feature for the context, if set.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
QgsExpressionPreviewWidget(QWidget *parent=nullptr)
Constructor.
void parserErrorChanged()
Will be set to true if the current expression text reported a parser error with the context.
void evalErrorChanged()
Will be set to true if the current expression text reported an eval error with the context.
void toolTipChanged(const QString &toolTip)
Emitted whenever the tool tip changed.
bool parserError() const
Will be set to true if the current expression text reports a parser error with the context.
void setGeomCalculator(const QgsDistanceArea &da)
Sets geometry calculator used in distance/area calculations.
void expressionParsed(bool isValid)
Emitted when the user changes the expression in the widget.
bool evalError() const
Will be set to true if the current expression text reported an eval error with the context.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context for the widget.
void setLayer(QgsVectorLayer *layer)
Sets the layer used in the preview.
void setCurrentFeature(const QgsFeature &feature)
sets the current feature used
void setExpressionText(const QString &expression)
Sets the expression.
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.
QString evalErrorString() const
Returns evaluation error.
QString parserErrorString() const
Returns parser error.
static QString formatPreviewString(const QVariant &value, bool htmlOutput=true, int maximumPreviewLength=60)
Formats an expression result for friendly display to the user.
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
void setGeomCalculator(const QgsDistanceArea *calc)
Sets the geometry calculator used for distance and area calculations in expressions.
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QVariant evaluate()
Evaluate the feature and return the result.
void featureChanged(const QgsFeature &feature)
Sends the feature as soon as it is chosen.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:190
A generic message view for displaying QGIS messages.
Represents a vector layer which manages a vector based data sets.