QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgscodeeditorexpression.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscodeeditorexpressoin.cpp - An expression editor based on QScintilla
3  --------------------------------------
4  Date : 8.9.2018
5  Copyright : (C) 2018 by Matthias Kuhn
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 
16 #include "qgsapplication.h"
18 #include "qgssymbollayerutils.h"
19 
20 #include <QString>
21 #include <QFont>
22 #include <QLabel>
23 
25  : QgsCodeEditor( parent )
26 {
27  if ( !parent )
28  {
29  setTitle( tr( "Expression Editor" ) );
30  }
31  setMarginVisible( false );
32  setFoldingVisible( true );
33  setAutoCompletionCaseSensitivity( false );
34  initializeLexer();
35 }
36 
38 {
39  mVariables.clear();
40 
41  const QStringList variableNames = context.filteredVariableNames();
42  for ( const QString &var : variableNames )
43  {
44  mVariables << '@' + var;
45  }
46 
47  mContextFunctions = context.functionNames();
48 
49  mFunctions.clear();
50 
51  const int count = QgsExpression::functionCount();
52  for ( int i = 0; i < count; i++ )
53  {
55  if ( func->isDeprecated() ) // don't show deprecated functions
56  continue;
57  if ( func->isContextual() )
58  {
59  //don't show contextual functions by default - it's up the the QgsExpressionContext
60  //object to provide them if supported
61  continue;
62  }
63 
64  QString signature = func->name();
65  if ( !signature.startsWith( '$' ) )
66  {
67  signature += '(';
68 
69  QStringList paramNames;
70  const auto &parameters = func->parameters();
71  for ( const auto &param : parameters )
72  {
73  paramNames << param.name();
74  }
75 
76  // No named parameters but there should be parameteres? Show an ellipsis at least
77  if ( parameters.isEmpty() && func->params() )
78  signature += QChar( 0x2026 );
79 
80  signature += paramNames.join( ", " );
81 
82  signature += ')';
83  }
84  mFunctions << signature;
85  }
86 
87  updateApis();
88 }
89 
91 {
92  mFieldNames.clear();
93 
94  for ( const QgsField &field : fields )
95  {
96  mFieldNames << field.name();
97  }
98 
99  updateApis();
100 }
101 
102 
103 void QgsCodeEditorExpression::initializeLexer()
104 {
105  QHash< QString, QColor > colors;
106  if ( QgsApplication::instance()->themeName() != QStringLiteral( "default" ) )
107  {
108  QSettings ini( QgsApplication::instance()->uiThemes().value( QgsApplication::instance()->themeName() ) + "/qscintilla.ini", QSettings::IniFormat );
109  for ( const auto &key : ini.allKeys() )
110  {
111  colors.insert( key, QgsSymbolLayerUtils::decodeColor( ini.value( key ).toString() ) );
112  }
113  }
114 
115  QFont font = getMonospaceFont();
116 #ifdef Q_OS_MAC
117  // The font size gotten from getMonospaceFont() is too small on Mac
118  font.setPointSize( QLabel().font().pointSize() );
119 #endif
120  QColor defaultColor = colors.value( QStringLiteral( "sql/defaultFontColor" ), Qt::black );
121 
122  mSqlLexer = new QgsLexerExpression( this );
123  mSqlLexer->setDefaultFont( font );
124  mSqlLexer->setDefaultColor( defaultColor );
125  mSqlLexer->setDefaultPaper( colors.value( QStringLiteral( "sql/paperBackgroundColor" ), Qt::white ) );
126  mSqlLexer->setFont( font, -1 );
127  font.setBold( true );
128  mSqlLexer->setFont( font, QsciLexerSQL::Keyword );
129 
130  mSqlLexer->setColor( Qt::darkYellow, QsciLexerSQL::DoubleQuotedString ); // fields
131 
132  mSqlLexer->setColor( defaultColor, QsciLexerSQL::Default );
133  mSqlLexer->setColor( colors.value( QStringLiteral( "sql/commentFontColor" ), QColor( 142, 144, 140 ) ), QsciLexerSQL::Comment );
134  mSqlLexer->setColor( colors.value( QStringLiteral( "sql/commentLineFontColor" ), QColor( 142, 144, 140 ) ), QsciLexerSQL::CommentLine );
135  mSqlLexer->setColor( colors.value( QStringLiteral( "sql/numberFontColor" ), QColor( 200, 40, 41 ) ), QsciLexerSQL::Number );
136  mSqlLexer->setColor( colors.value( QStringLiteral( "sql/keywordFontColor" ), QColor( 137, 89, 168 ) ), QsciLexerSQL::Keyword );
137  mSqlLexer->setColor( colors.value( QStringLiteral( "sql/singleQuoteFontColor" ), QColor( 113, 140, 0 ) ), QsciLexerSQL::SingleQuotedString );
138  mSqlLexer->setColor( colors.value( QStringLiteral( "sql/doubleQuoteFontColor" ), QColor( 234, 183, 0 ) ), QsciLexerSQL::DoubleQuotedString );
139  mSqlLexer->setColor( colors.value( QStringLiteral( "sql/operatorFontColor" ), QColor( 66, 113, 174 ) ), QsciLexerSQL::Operator );
140  mSqlLexer->setColor( colors.value( QStringLiteral( "sql/identifierFontColor" ), QColor( 62, 153, 159 ) ), QsciLexerSQL::Identifier );
141  mSqlLexer->setColor( colors.value( QStringLiteral( "sql/QuotedIdentifierFontColor" ), Qt::black ), QsciLexerSQL::QuotedIdentifier );
142  mSqlLexer->setColor( colors.value( QStringLiteral( "sql/QuotedOperatorFontColor" ), Qt::black ), QsciLexerSQL::QuotedOperator );
143 
144  setLexer( mSqlLexer );
145 }
146 
147 void QgsCodeEditorExpression::updateApis()
148 {
149  mApis = new QgsSciApisExpression( mSqlLexer );
150 
151  for ( const QString &var : qgis::as_const( mVariables ) )
152  {
153  mApis->add( var );
154  }
155 
156  for ( const QString &function : qgis::as_const( mContextFunctions ) )
157  {
158  mApis->add( function );
159  }
160 
161  for ( const QString &function : qgis::as_const( mFunctions ) )
162  {
163  mApis->add( function );
164  }
165 
166  for ( const QString &fieldName : qgis::as_const( mFieldNames ) )
167  {
168  mApis->add( fieldName );
169  }
170 
171  mApis->prepare();
172  mSqlLexer->setAPIs( mApis );
173 }
174 
176 QgsLexerExpression::QgsLexerExpression( QObject *parent )
177  : QsciLexerSQL( parent )
178 {
179 }
180 
181 const char *QgsLexerExpression::language() const
182 {
183  return "QGIS Expression";
184 }
185 
186 bool QgsLexerExpression::caseSensitive() const
187 {
188  return false;
189 }
190 
191 const char *QgsLexerExpression::wordCharacters() const
192 {
193  return "[email protected]";
194 }
195 
196 QgsSciApisExpression::QgsSciApisExpression( QsciLexer *lexer )
197  : QsciAPIs( lexer )
198 {
199 
200 }
201 
202 QStringList QgsSciApisExpression::callTips( const QStringList &context, int commas, QsciScintilla::CallTipsStyle style, QList<int> &shifts )
203 {
204  const QStringList originalTips = QsciAPIs::callTips( context, commas, style, shifts );
205  QStringList lowercaseTips;
206  for ( const QString &tip : originalTips )
207  lowercaseTips << tip.toLower();
208 
209  return lowercaseTips;
210 }
A text editor based on QScintilla2.
Definition: qgscodeeditor.h:38
static QgsApplication * instance()
Returns the singleton instance of the QgsApplication.
void setFoldingVisible(bool folding)
Set folding visible state.
QFont getMonospaceFont()
void setFields(const QgsFields &fields)
Field names will be added to the API.
Container of fields for a vector layer.
Definition: qgsfields.h:42
QString name() const
The name of the function.
void setExpressionContext(const QgsExpressionContext &context)
Variables and functions from this expression context will be added to the API.
static int functionCount()
Returns the number of functions defined in the parser.
QgsCodeEditorExpression(QWidget *parent=nullptr)
Constructor for QgsCodeEditorExpression.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QStringList functionNames() const
Retrieves a list of function names contained in the context.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:48
static const QList< QgsExpressionFunction * > & Functions()
int params() const
The number of parameters this function takes.
virtual bool isDeprecated() const
Returns true if the function is deprecated and should not be presented as a valid option to users in ...
void setMarginVisible(bool margin)
Set margin visible state.
A abstract base class for defining QgsExpression functions.
const QgsExpressionFunction::ParameterList & parameters() const
Returns the list of named parameters for the function, if set.
QStringList filteredVariableNames() const
Returns a filtered list of variables names set by all scopes in the context.
void setTitle(const QString &title)
Set the widget title.
bool isContextual() const
Returns whether the function is only available if provided by a QgsExpressionContext object...
static QColor decodeColor(const QString &str)