QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
qgscodeeditorhtml.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgscodeeditorhtml.cpp - A HTML editor based on QScintilla
3 --------------------------------------
4 Date : 20-Jul-2014
5 Copyright : (C) 2014 by Nathan Woodrow
6 Email : woodrow.nathan (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 "qgscodeeditorhtml.h"
17#include "moc_qgscodeeditorhtml.cpp"
18#include "qgspythonrunner.h"
19#include "qgsprocessingutils.h"
20
21#include <QWidget>
22#include <QString>
23#include <QFont>
24#include <Qsci/qscilexerhtml.h>
25
26
28 : QgsCodeEditor( parent, QString(), false, false, QgsCodeEditor::Flag::CodeFolding )
29{
30 if ( !parent )
31 {
32 setTitle( tr( "HTML Editor" ) );
33 }
35
38 {
39 // we could potentially check for beautifulsoup4 import here and reflect the capability accordingly.
40 // (current approach is to to always indicate this capability and raise a user-friendly warning
41 // when attempting to reformat if the libraries can't be imported)
43 }
44}
45
50
55
57{
58 QFont font = lexerFont();
60
61 QsciLexerHTML *lexer = new QsciLexerHTML( this );
62 lexer->setDefaultFont( font );
63 lexer->setDefaultColor( defaultColor );
65 lexer->setFont( font, -1 );
66
67 font.setItalic( true );
68 lexer->setFont( font, QsciLexerHTML::HTMLComment );
69 lexer->setFont( font, QsciLexerHTML::JavaScriptComment );
70 lexer->setFont( font, QsciLexerHTML::JavaScriptCommentLine );
71
72 lexer->setColor( defaultColor, QsciLexerHTML::Default );
73 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Tag ), QsciLexerHTML::Tag );
74 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::UnknownTag ), QsciLexerHTML::UnknownTag );
75 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Method ), QsciLexerHTML::Attribute );
76 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Method ), QsciLexerHTML::UnknownAttribute );
77 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Class ), QsciLexerHTML::Entity );
78 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Number ), QsciLexerHTML::HTMLNumber );
79 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Comment ), QsciLexerHTML::HTMLComment );
80 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Comment ), QsciLexerHTML::JavaScriptComment );
81 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::CommentLine ), QsciLexerHTML::JavaScriptCommentLine );
82 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Number ), QsciLexerHTML::JavaScriptNumber );
83 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Keyword ), QsciLexerHTML::JavaScriptKeyword );
84 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::DoubleQuote ), QsciLexerHTML::JavaScriptDoubleQuotedString );
85 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::SingleQuote ), QsciLexerHTML::JavaScriptSingleQuotedString );
86 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::SingleQuote ), QsciLexerHTML::HTMLSingleQuotedString );
87 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::DoubleQuote ), QsciLexerHTML::HTMLDoubleQuotedString );
88
89 setLexer( lexer );
91}
92
93QString QgsCodeEditorHTML::reformatCodeString( const QString &string )
94{
96 {
97 return string;
98 }
99 QString newText = string;
100
101 const QString definePrettify = QStringLiteral(
102 "def __qgis_prettify(text):\n"
103 " try:\n"
104 " from bs4 import BeautifulSoup\n"
105 " return BeautifulSoup(text, 'html.parser').prettify()\n"
106 " except ImportError:\n"
107 " try:\n"
108 " import re\n"
109 " from lxml import etree, html\n"
110 " text = re.sub('>\\\\s+<', '><', text)\n"
111 " text = re.sub('\\n\\\\s*', '', text)\n"
112 " document_root = html.fromstring(text)\n"
113 " return etree.tostring(document_root, encoding='utf-8', pretty_print=True).decode('utf-8')\n"
114 " except ImportError:\n"
115 " return '_ImportError'\n"
116 );
117
118
119 if ( !QgsPythonRunner::run( definePrettify ) )
120 {
121 QgsDebugError( QStringLiteral( "Error running script: %1" ).arg( definePrettify ) );
122 return string;
123 }
124
125 const QString script = QStringLiteral( "__qgis_prettify(%1)" ).arg( QgsProcessingUtils::stringToPythonLiteral( newText ) );
126 QString result;
127 if ( QgsPythonRunner::eval( script, result ) )
128 {
129 if ( result == QLatin1String( "_ImportError" ) )
130 {
131 showMessage( tr( "Reformat Code" ), tr( "HTML reformatting requires bs4 or lxml python modules to be installed" ), Qgis::MessageLevel::Warning );
132 }
133 else
134 {
135 newText = result;
136 }
137 }
138 else
139 {
140 QgsDebugError( QStringLiteral( "Error running script: %1" ).arg( script ) );
141 return newText;
142 }
143
144 return newText;
145}
146
148{
149 if ( isReadOnly() )
150 {
151 return;
152 }
153
154 const QString commentStart( "<!--" );
155 const QString commentEnd( "-->" );
156
157 int startLine, startPos, endLine, endPos;
158 if ( hasSelectedText() )
159 {
160 getSelection( &startLine, &startPos, &endLine, &endPos );
161 }
162 else
163 {
164 getCursorPosition( &startLine, &startPos );
165 endLine = startLine;
166 endPos = startPos;
167 }
168
169
170 // Compute first and last non-blank lines
171 while ( text( startLine ).trimmed().isEmpty() )
172 {
173 startLine++;
174 if ( startLine > endLine )
175 {
176 // Only blank lines selected
177 return;
178 }
179 }
180 while ( text( endLine ).trimmed().isEmpty() )
181 {
182 endLine--;
183 }
184
185 // Remove leading spaces from the start line
186 QString startLineTrimmed = text( startLine );
187 startLineTrimmed.remove( QRegularExpression( "^\\s+" ) );
188 // Remove trailing spaces from the end line
189 QString endLineTrimmed = text( endLine );
190 endLineTrimmed.remove( QRegularExpression( "\\s+$" ) );
191
192 const bool commented = startLineTrimmed.startsWith( commentStart ) && endLineTrimmed.endsWith( commentEnd );
193
194 // Special case, selected text is <!--> or <!--->
195 if ( commented && startLine == endLine && text( endLine ).trimmed().size() < commentStart.size() + commentEnd.size() )
196 {
197 return;
198 }
199
200 beginUndoAction();
201
202 // Selection is commented: uncomment it
203 if ( commented )
204 {
205 int c1, c2;
206
207 // Remove trailing comment tag ( --> )
208 c2 = endLineTrimmed.size();
209 if ( endLineTrimmed.endsWith( QStringLiteral( " " ) + commentEnd ) )
210 {
211 c1 = c2 - commentEnd.size() - 1;
212 }
213 else
214 {
215 c1 = c2 - commentEnd.size();
216 }
217
218 setSelection( endLine, c1, endLine, c2 );
219 removeSelectedText();
220
221 // Remove leading comment tag ( <!-- )
222 c1 = indentation( startLine );
223 if ( startLineTrimmed.startsWith( commentStart + QStringLiteral( " " ) ) )
224 {
225 c2 = c1 + commentStart.size() + 1;
226 }
227 else
228 {
229 c2 = c1 + commentStart.size();
230 }
231
232 setSelection( startLine, c1, startLine, c2 );
233 removeSelectedText();
234 }
235 // Selection is not commented: comment it
236 else
237 {
238 insertAt( QStringLiteral( " " ) + commentEnd, endLine, endLineTrimmed.size() );
239 insertAt( commentStart + QStringLiteral( " " ), startLine, indentation( startLine ) );
240 }
241
242 endUndoAction();
243
244 // Restore selection
245 setSelection( startLine, startPos, endLine, endPos );
246}
@ Warning
Warning message.
Definition qgis.h:156
@ Reformat
Language supports automatic code reformatting.
@ ToggleComment
Language supports comment toggling.
ScriptLanguage
Scripting languages.
Definition qgis.h:4244
QFlags< ScriptLanguageCapability > ScriptLanguageCapabilities
Script language capabilities.
Definition qgis.h:4279
@ DoubleQuote
Double quote color.
@ CommentLine
Line comment color.
@ SingleQuote
Single quote color.
Qgis::ScriptLanguage language() const override
Returns the associated scripting language.
Qgis::ScriptLanguageCapabilities languageCapabilities() const override
Returns the associated scripting language capabilities.
void initializeLexer() override
Called when the dialect specific code lexer needs to be initialized (or reinitialized).
QString reformatCodeString(const QString &string) override
Applies code reformatting to a string and returns the result.
QgsCodeEditorHTML(QWidget *parent=nullptr)
Constructor for QgsCodeEditorHTML.
void toggleComment() override
Toggle comment for the selected text.
A text editor based on QScintilla2.
void runPostLexerConfigurationTasks()
Performs tasks which must be run after a lexer has been set for the widget.
virtual void showMessage(const QString &title, const QString &message, Qgis::MessageLevel level)
Shows a user facing message (eg a warning message).
void setTitle(const QString &title)
Set the widget title.
Flag
Flags controlling behavior of code 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.
static QString stringToPythonLiteral(const QString &string)
Converts a string to a Python string literal.
static bool run(const QString &command, const QString &messageOnError=QString())
Execute a Python statement.
static bool eval(const QString &command, QString &result)
Eval a Python statement.
static bool isValid()
Returns true if the runner has an instance (and thus is able to run commands)
#define QgsDebugError(str)
Definition qgslogger.h:38