-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7835 from m-kuhn/expressionCodeCompletion
Code completion for expression builder [FEATURE]
- Loading branch information
Showing
9 changed files
with
360 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/************************************************************************ | ||
* This file has been generated automatically from * | ||
* * | ||
* src/gui/qgscodeeditorexpression.h * | ||
* * | ||
* Do not edit manually ! Edit header and run scripts/sipify.pl again * | ||
************************************************************************/ | ||
|
||
|
||
|
||
|
||
|
||
class QgsCodeEditorExpression : QgsCodeEditor | ||
{ | ||
%Docstring | ||
|
||
A QGIS expression editor based on QScintilla2. Adds syntax highlighting and | ||
code autocompletion. | ||
|
||
.. versionadded:: 3.4 | ||
%End | ||
|
||
%TypeHeaderCode | ||
#include "qgscodeeditorexpression.h" | ||
%End | ||
public: | ||
QgsCodeEditorExpression( QWidget *parent /TransferThis/ = 0 ); | ||
%Docstring | ||
Constructor for QgsCodeEditorExpression | ||
%End | ||
|
||
void setExpressionContext( const QgsExpressionContext &context ); | ||
%Docstring | ||
Variables and functions from this expression context will be added to | ||
the API. | ||
Will also reload all globally registered functions. | ||
%End | ||
|
||
void setFields( const QgsFields &fields ); | ||
%Docstring | ||
Field names will be added to the API. | ||
%End | ||
|
||
}; | ||
|
||
|
||
/************************************************************************ | ||
* This file has been generated automatically from * | ||
* * | ||
* src/gui/qgscodeeditorexpression.h * | ||
* * | ||
* Do not edit manually ! Edit header and run scripts/sipify.pl again * | ||
************************************************************************/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
/*************************************************************************** | ||
qgscodeeditorexpressoin.cpp - An expression editor based on QScintilla | ||
-------------------------------------- | ||
Date : 8.9.2018 | ||
Copyright : (C) 2018 by Matthias Kuhn | ||
Email : matthias@opengis.ch | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#include "qgsapplication.h" | ||
#include "qgscodeeditorexpression.h" | ||
|
||
#include <QString> | ||
#include <QFont> | ||
#include <QLabel> | ||
|
||
QgsCodeEditorExpression::QgsCodeEditorExpression( QWidget *parent ) | ||
: QgsCodeEditor( parent ) | ||
{ | ||
if ( !parent ) | ||
{ | ||
setTitle( tr( "Expression Editor" ) ); | ||
} | ||
setMarginVisible( false ); | ||
setFoldingVisible( true ); | ||
setAutoCompletionCaseSensitivity( false ); | ||
initializeLexer(); | ||
} | ||
|
||
void QgsCodeEditorExpression::setExpressionContext( const QgsExpressionContext &context ) | ||
{ | ||
mVariables.clear(); | ||
|
||
const QStringList variableNames = context.filteredVariableNames(); | ||
for ( const QString &var : variableNames ) | ||
{ | ||
mVariables << '@' + var; | ||
} | ||
|
||
mContextFunctions = context.functionNames(); | ||
|
||
mFunctions.clear(); | ||
|
||
const int count = QgsExpression::functionCount(); | ||
for ( int i = 0; i < count; i++ ) | ||
{ | ||
QgsExpressionFunction *func = QgsExpression::Functions()[i]; | ||
if ( func->isDeprecated() ) // don't show deprecated functions | ||
continue; | ||
if ( func->isContextual() ) | ||
{ | ||
//don't show contextual functions by default - it's up the the QgsExpressionContext | ||
//object to provide them if supported | ||
continue; | ||
} | ||
|
||
QString signature = func->name(); | ||
if ( !signature.startsWith( '$' ) ) | ||
{ | ||
signature += '('; | ||
|
||
QStringList paramNames; | ||
const auto ¶meters = func->parameters(); | ||
for ( const auto ¶m : parameters ) | ||
{ | ||
paramNames << param.name(); | ||
} | ||
|
||
// No named parameters but there should be parameteres? Show an ellipsis at least | ||
if ( parameters.isEmpty() && func->params() ) | ||
signature += QChar( 0x2026 ); | ||
|
||
signature += paramNames.join( ", " ); | ||
|
||
signature += ')'; | ||
} | ||
mFunctions << signature; | ||
} | ||
|
||
updateApis(); | ||
} | ||
|
||
void QgsCodeEditorExpression::setFields( const QgsFields &fields ) | ||
{ | ||
mFieldNames.clear(); | ||
|
||
for ( const QgsField &field : fields ) | ||
{ | ||
mFieldNames << field.name(); | ||
} | ||
|
||
updateApis(); | ||
} | ||
|
||
|
||
void QgsCodeEditorExpression::initializeLexer() | ||
{ | ||
QFont font = getMonospaceFont(); | ||
#ifdef Q_OS_MAC | ||
// The font size gotten from getMonospaceFont() is too small on Mac | ||
font.setPointSize( QLabel().font().pointSize() ); | ||
#endif | ||
mSqlLexer = new QgsLexerExpression( this ); | ||
mSqlLexer->setDefaultFont( font ); | ||
mSqlLexer->setFont( font, -1 ); | ||
font.setBold( true ); | ||
mSqlLexer->setFont( font, QsciLexerSQL::Keyword ); | ||
mSqlLexer->setColor( Qt::darkYellow, QsciLexerSQL::DoubleQuotedString ); // fields | ||
|
||
setLexer( mSqlLexer ); | ||
} | ||
|
||
void QgsCodeEditorExpression::updateApis() | ||
{ | ||
mApis = new QgsSciApisExpression( mSqlLexer ); | ||
|
||
for ( const QString &var : qgis::as_const( mVariables ) ) | ||
{ | ||
mApis->add( var ); | ||
} | ||
|
||
for ( const QString &function : qgis::as_const( mContextFunctions ) ) | ||
{ | ||
mApis->add( function ); | ||
} | ||
|
||
for ( const QString &function : qgis::as_const( mFunctions ) ) | ||
{ | ||
mApis->add( function ); | ||
} | ||
|
||
for ( const QString &fieldName : qgis::as_const( mFieldNames ) ) | ||
{ | ||
mApis->add( fieldName ); | ||
} | ||
|
||
mApis->prepare(); | ||
mSqlLexer->setAPIs( mApis ); | ||
} | ||
|
||
///@cond PRIVATE | ||
QgsLexerExpression::QgsLexerExpression( QObject *parent ) | ||
: QsciLexerSQL( parent ) | ||
{ | ||
} | ||
|
||
const char *QgsLexerExpression::language() const | ||
{ | ||
return "QGIS Expression"; | ||
} | ||
|
||
bool QgsLexerExpression::caseSensitive() const | ||
{ | ||
return false; | ||
} | ||
|
||
const char *QgsLexerExpression::wordCharacters() const | ||
{ | ||
return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_@"; | ||
} | ||
|
||
QgsSciApisExpression::QgsSciApisExpression( QsciLexer *lexer ) | ||
: QsciAPIs( lexer ) | ||
{ | ||
|
||
} | ||
|
||
QStringList QgsSciApisExpression::callTips( const QStringList &context, int commas, QsciScintilla::CallTipsStyle style, QList<int> &shifts ) | ||
{ | ||
const QStringList originalTips = QsciAPIs::callTips( context, commas, style, shifts ); | ||
QStringList lowercaseTips; | ||
for ( const QString &tip : originalTips ) | ||
lowercaseTips << tip.toLower(); | ||
|
||
return lowercaseTips; | ||
} | ||
///@endcond |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/*************************************************************************** | ||
qgscodeeditorsql.h - A SQL editor based on QScintilla | ||
-------------------------------------- | ||
Date : 06-Oct-2013 | ||
Copyright : (C) 2013 by Salvatore Larosa | ||
Email : lrssvtml (at) gmail (dot) com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
|
||
#ifndef QGSCODEEDITOREXPRESSION_H | ||
#define QGSCODEEDITOREXPRESSION_H | ||
|
||
#include "qgis_sip.h" | ||
#include "qgis_gui.h" | ||
#include "qgscodeeditor.h" | ||
#include "qgsexpressioncontext.h" | ||
|
||
#include <Qsci/qscilexersql.h> | ||
|
||
SIP_IF_MODULE( HAVE_QSCI_SIP ) | ||
|
||
/** | ||
* \ingroup gui | ||
* | ||
* A QGIS expression editor based on QScintilla2. Adds syntax highlighting and | ||
* code autocompletion. | ||
* | ||
* \since QGIS 3.4 | ||
*/ | ||
class GUI_EXPORT QgsCodeEditorExpression : public QgsCodeEditor | ||
{ | ||
Q_OBJECT | ||
|
||
public: | ||
//! Constructor for QgsCodeEditorExpression | ||
QgsCodeEditorExpression( QWidget *parent SIP_TRANSFERTHIS = nullptr ); | ||
|
||
/** | ||
* Variables and functions from this expression context will be added to | ||
* the API. | ||
* Will also reload all globally registered functions. | ||
*/ | ||
void setExpressionContext( const QgsExpressionContext &context ); | ||
|
||
/** | ||
* Field names will be added to the API. | ||
*/ | ||
void setFields( const QgsFields &fields ); | ||
|
||
private: | ||
void initializeLexer(); | ||
void updateApis(); | ||
QsciAPIs *mApis = nullptr; | ||
QsciLexerSQL *mSqlLexer; | ||
|
||
QStringList mVariables; | ||
QStringList mContextFunctions; | ||
QStringList mFunctions; | ||
QStringList mFieldNames; | ||
}; | ||
|
||
#ifndef SIP_RUN | ||
///@cond PRIVATE | ||
|
||
/** | ||
* Internal use. | ||
setAutoCompletionCaseSensitivity( false ) is not sufficient when installing | ||
a lexer, since its caseSensitive() method is actually used, and defaults | ||
to true. | ||
\note not available in Python bindings | ||
\ingroup gui | ||
*/ | ||
class QgsLexerExpression : public QsciLexerSQL | ||
{ | ||
Q_OBJECT | ||
|
||
public: | ||
//! Constructor | ||
explicit QgsLexerExpression( QObject *parent = nullptr ); | ||
|
||
const char *language() const override; | ||
|
||
bool caseSensitive() const override; | ||
|
||
const char *wordCharacters() const override; | ||
}; | ||
|
||
class QgsSciApisExpression : public QsciAPIs | ||
{ | ||
public: | ||
QgsSciApisExpression( QsciLexer *lexer ); | ||
|
||
QStringList callTips( const QStringList &context, int commas, QsciScintilla::CallTipsStyle style, QList<int> &shifts ) override; | ||
}; | ||
///@endcond | ||
#endif | ||
|
||
#endif |
Oops, something went wrong.