QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgscodeeditorpython.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgscodeeditorpython.cpp - A Python editor based on QScintilla
3 --------------------------------------
4 Date : 06-Oct-2013
5 Copyright : (C) 2013 by Salvatore Larosa
6 Email : lrssvtml (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 "qgsapplication.h"
17#include "qgscodeeditorpython.h"
18#include "qgslogger.h"
19#include "qgssymbollayerutils.h"
20#include "qgssettings.h"
21#include "qgis.h"
22
23#include <QWidget>
24#include <QString>
25#include <QFont>
26#include <QUrl>
27#include <QFileInfo>
28#include <QMessageBox>
29#include <QTextStream>
30#include <Qsci/qscilexerpython.h>
31#include <QDesktopServices>
32
33QgsCodeEditorPython::QgsCodeEditorPython( QWidget *parent, const QList<QString> &filenames )
34 : QgsCodeEditor( parent,
35 QString(),
36 false,
37 false,
38 QgsCodeEditor::Flag::CodeFolding )
39 , mAPISFilesList( filenames )
40{
41 if ( !parent )
42 {
43 setTitle( tr( "Python Editor" ) );
44 }
45
46 setCaretWidth( 2 );
47
49}
50
52{
53 // current line
54 setEdgeMode( QsciScintilla::EdgeLine );
55 setEdgeColumn( 80 );
57
58 setWhitespaceVisibility( QsciScintilla::WsVisibleAfterIndent );
59
60 QFont font = lexerFont();
62
63 QsciLexerPython *pyLexer = new QgsQsciLexerPython( this );
64
65 pyLexer->setIndentationWarning( QsciLexerPython::Inconsistent );
66 pyLexer->setFoldComments( true );
67 pyLexer->setFoldQuotes( true );
68
69 pyLexer->setDefaultFont( font );
70 pyLexer->setDefaultColor( defaultColor );
72 pyLexer->setFont( font, -1 );
73
74 font.setItalic( true );
75 pyLexer->setFont( font, QsciLexerPython::Comment );
76 pyLexer->setFont( font, QsciLexerPython::CommentBlock );
77
78 font.setItalic( false );
79 font.setBold( true );
80 pyLexer->setFont( font, QsciLexerPython::SingleQuotedString );
81 pyLexer->setFont( font, QsciLexerPython::DoubleQuotedString );
82
83 pyLexer->setColor( defaultColor, QsciLexerPython::Default );
84 pyLexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Class ), QsciLexerPython::ClassName );
85 pyLexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Method ), QsciLexerPython::FunctionMethodName );
86 pyLexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Number ), QsciLexerPython::Number );
87 pyLexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Operator ), QsciLexerPython::Operator );
88 pyLexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Identifier ), QsciLexerPython::Identifier );
89 pyLexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Comment ), QsciLexerPython::Comment );
90 pyLexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::CommentBlock ), QsciLexerPython::CommentBlock );
91 pyLexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Keyword ), QsciLexerPython::Keyword );
92 pyLexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Decoration ), QsciLexerPython::Decorator );
93 pyLexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::SingleQuote ), QsciLexerPython::SingleQuotedString );
94 pyLexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::DoubleQuote ), QsciLexerPython::DoubleQuotedString );
95 pyLexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::TripleSingleQuote ), QsciLexerPython::TripleSingleQuotedString );
96 pyLexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::TripleDoubleQuote ), QsciLexerPython::TripleDoubleQuotedString );
97
98 QsciAPIs *apis = new QsciAPIs( pyLexer );
99
100 const QgsSettings settings;
101
102 if ( mAPISFilesList.isEmpty() )
103 {
104 if ( settings.value( QStringLiteral( "pythonConsole/preloadAPI" ), true ).toBool() )
105 {
106 mPapFile = QgsApplication::pkgDataPath() + QStringLiteral( "/python/qsci_apis/pyqgis.pap" );
107 apis->loadPrepared( mPapFile );
108 }
109 else if ( settings.value( QStringLiteral( "pythonConsole/usePreparedAPIFile" ), false ).toBool() )
110 {
111 apis->loadPrepared( settings.value( QStringLiteral( "pythonConsole/preparedAPIFile" ) ).toString() );
112 }
113 else
114 {
115 const QStringList apiPaths = settings.value( QStringLiteral( "pythonConsole/userAPI" ) ).toStringList();
116 for ( const QString &path : apiPaths )
117 {
118 if ( !QFileInfo::exists( path ) )
119 {
120 QgsDebugMsg( QStringLiteral( "The apis file %1 was not found" ).arg( path ) );
121 }
122 else
123 {
124 apis->load( path );
125 }
126 }
127 apis->prepare();
128 pyLexer->setAPIs( apis );
129 }
130 }
131 else if ( mAPISFilesList.length() == 1 && mAPISFilesList[0].right( 3 ) == QLatin1String( "pap" ) )
132 {
133 if ( !QFileInfo::exists( mAPISFilesList[0] ) )
134 {
135 QgsDebugMsg( QStringLiteral( "The apis file %1 not found" ).arg( mAPISFilesList.at( 0 ) ) );
136 return;
137 }
138 mPapFile = mAPISFilesList[0];
139 apis->loadPrepared( mPapFile );
140 }
141 else
142 {
143 for ( const QString &path : mAPISFilesList )
144 {
145 if ( !QFileInfo::exists( path ) )
146 {
147 QgsDebugMsg( QStringLiteral( "The apis file %1 was not found" ).arg( path ) );
148 }
149 else
150 {
151 apis->load( path );
152 }
153 }
154 apis->prepare();
155 pyLexer->setAPIs( apis );
156 }
157 setLexer( pyLexer );
158
159 const int threshold = settings.value( QStringLiteral( "pythonConsole/autoCompThreshold" ), 2 ).toInt();
160 setAutoCompletionThreshold( threshold );
161 if ( !settings.value( "pythonConsole/autoCompleteEnabled", true ).toBool() )
162 {
163 setAutoCompletionSource( AcsNone );
164 }
165 else
166 {
167 const QString autoCompleteSource = settings.value( QStringLiteral( "pythonConsole/autoCompleteSource" ), QStringLiteral( "fromAPI" ) ).toString();
168 if ( autoCompleteSource == QLatin1String( "fromDoc" ) )
169 setAutoCompletionSource( AcsDocument );
170 else if ( autoCompleteSource == QLatin1String( "fromDocAPI" ) )
171 setAutoCompletionSource( AcsAll );
172 else
173 setAutoCompletionSource( AcsAPIs );
174 }
175
176 setLineNumbersVisible( true );
177 setIndentationsUseTabs( false );
178 setIndentationGuides( true );
179
181}
182
184{
185 switch ( autoCompletionSource() )
186 {
187 case AcsDocument:
188 autoCompleteFromDocument();
189 break;
190
191 case AcsAPIs:
192 autoCompleteFromAPIs();
193 break;
194
195 case AcsAll:
196 autoCompleteFromAll();
197 break;
198
199 case AcsNone:
200 break;
201 }
202}
203
204void QgsCodeEditorPython::loadAPIs( const QList<QString> &filenames )
205{
206 mAPISFilesList = filenames;
207 //QgsDebugMsg( QStringLiteral( "The apis files: %1" ).arg( mAPISFilesList[0] ) );
209}
210
211bool QgsCodeEditorPython::loadScript( const QString &script )
212{
213 QgsDebugMsgLevel( QStringLiteral( "The script file: %1" ).arg( script ), 2 );
214 QFile file( script );
215 if ( !file.open( QIODevice::ReadOnly ) )
216 {
217 return false;
218 }
219
220 QTextStream in( &file );
221
222 setText( in.readAll().trimmed() );
223 file.close();
224
226 return true;
227}
228
230{
231 if ( !hasSelectedText() )
232 return;
233
234 QString text = selectedText();
235 text = text.replace( QLatin1String( ">>> " ), QString() ).replace( QLatin1String( "... " ), QString() ).trimmed(); // removing prompts
236 const QString version = QString( Qgis::version() ).split( '.' ).mid( 0, 2 ).join( '.' );
237 QDesktopServices::openUrl( QUrl( QStringLiteral( "https://qgis.org/pyqgis/%1/search.html?q=%2" ).arg( version, text ) ) );
238}
239
241//
242// QgsQsciLexerPython
243//
244QgsQsciLexerPython::QgsQsciLexerPython( QObject *parent )
245 : QsciLexerPython( parent )
246{
247
248}
249
250const char *QgsQsciLexerPython::keywords( int set ) const
251{
252 if ( set == 1 )
253 {
254 return "True False and as assert break class continue def del elif else except exec "
255 "finally for from global if import in is lambda None not or pass "
256 "print raise return try while with yield";
257 }
258
259 return QsciLexerPython::keywords( set );
260}
static QString version()
Version string.
Definition: qgis.cpp:277
static QString pkgDataPath()
Returns the common root path of all application data directories.
@ TripleSingleQuote
Triple single quote color.
@ CommentBlock
Comment block color.
@ DoubleQuote
Double quote color.
@ SingleQuote
Single quote color.
@ TripleDoubleQuote
Triple double quote color.
void autoComplete()
Triggers the autocompletion popup.
void searchSelectedTextInPyQGISDocs()
Searches the selected text in the official PyQGIS online documentation.
void loadAPIs(const QList< QString > &filenames)
Load APIs from one or more files.
void initializeLexer() override
Called when the dialect specific code lexer needs to be initialized (or reinitialized).
bool loadScript(const QString &script)
Load a script file.
QgsCodeEditorPython(QWidget *parent=nullptr, const QList< QString > &filenames=QList< QString >())
Construct a new Python editor.
A text editor based on QScintilla2.
Definition: qgscodeeditor.h:42
void runPostLexerConfigurationTasks()
Performs tasks which must be run after a lexer has been set for the widget.
void setTitle(const QString &title)
Set the widget title.
Flag
Flags controlling behavior of code editor.
Definition: qgscodeeditor.h:68
void setLineNumbersVisible(bool visible)
Sets whether line numbers should be visible in the editor.
QFont lexerFont() const
Returns the font to use in the lexer.
QColor lexerColor(QgsCodeEditorColorScheme::ColorRole role) const
Returns the color to use in the lexer for the specified role.
static QColor defaultColor(QgsCodeEditorColorScheme::ColorRole role, const QString &theme=QString())
Returns the default color for the specified role.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugMsg(str)
Definition: qgslogger.h:38