QGIS API Documentation 3.41.0-Master (3440c17df1d)
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,
29 QString(),
30 false,
31 false,
32 QgsCodeEditor::Flag::CodeFolding )
33{
34 if ( !parent )
35 {
36 setTitle( tr( "HTML Editor" ) );
37 }
39
42 {
43 // we could potentially check for beautifulsoup4 import here and reflect the capability accordingly.
44 // (current approach is to to always indicate this capability and raise a user-friendly warning
45 // when attempting to reformat if the libraries can't be imported)
47 }
48}
49
54
59
61{
62 QFont font = lexerFont();
64
65 QsciLexerHTML *lexer = new QsciLexerHTML( this );
66 lexer->setDefaultFont( font );
67 lexer->setDefaultColor( defaultColor );
69 lexer->setFont( font, -1 );
70
71 font.setItalic( true );
72 lexer->setFont( font, QsciLexerHTML::HTMLComment );
73 lexer->setFont( font, QsciLexerHTML::JavaScriptComment );
74 lexer->setFont( font, QsciLexerHTML::JavaScriptCommentLine );
75
76 lexer->setColor( defaultColor, QsciLexerHTML::Default );
77 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Tag ), QsciLexerHTML::Tag );
78 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::UnknownTag ), QsciLexerHTML::UnknownTag );
79 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Method ), QsciLexerHTML::Attribute );
80 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Method ), QsciLexerHTML::UnknownAttribute );
81 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Class ), QsciLexerHTML::Entity );
82 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Number ), QsciLexerHTML::HTMLNumber );
83 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Comment ), QsciLexerHTML::HTMLComment );
84 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Comment ), QsciLexerHTML::JavaScriptComment );
85 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::CommentLine ), QsciLexerHTML::JavaScriptCommentLine );
86 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Number ), QsciLexerHTML::JavaScriptNumber );
87 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::Keyword ), QsciLexerHTML::JavaScriptKeyword );
88 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::DoubleQuote ), QsciLexerHTML::JavaScriptDoubleQuotedString );
89 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::SingleQuote ), QsciLexerHTML::JavaScriptSingleQuotedString );
90 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::SingleQuote ), QsciLexerHTML::HTMLSingleQuotedString );
91 lexer->setColor( lexerColor( QgsCodeEditorColorScheme::ColorRole::DoubleQuote ), QsciLexerHTML::HTMLDoubleQuotedString );
92
93 setLexer( lexer );
95}
96
97QString QgsCodeEditorHTML::reformatCodeString( const QString &string )
98{
100 {
101 return string;
102 }
103 QString newText = string;
104
105 const QString definePrettify = QStringLiteral(
106 "def __qgis_prettify(text):\n"
107 " try:\n"
108 " from bs4 import BeautifulSoup\n"
109 " return BeautifulSoup(text, 'html.parser').prettify()\n"
110 " except ImportError:\n"
111 " try:\n"
112 " import re\n"
113 " from lxml import etree, html\n"
114 " text = re.sub('>\\\\s+<', '><', text)\n"
115 " text = re.sub('\\n\\\\s*', '', text)\n"
116 " document_root = html.fromstring(text)\n"
117 " return etree.tostring(document_root, encoding='utf-8', pretty_print=True).decode('utf-8')\n"
118 " except ImportError:\n"
119 " return '_ImportError'\n" );
120
121
122 if ( !QgsPythonRunner::run( definePrettify ) )
123 {
124 QgsDebugError( QStringLiteral( "Error running script: %1" ).arg( definePrettify ) );
125 return string;
126 }
127
128 const QString script = QStringLiteral( "__qgis_prettify(%1)" ).arg( QgsProcessingUtils::stringToPythonLiteral( newText ) );
129 QString result;
130 if ( QgsPythonRunner::eval( script, result ) )
131 {
132 if ( result == QLatin1String( "_ImportError" ) )
133 {
134 showMessage( tr( "Reformat Code" ), tr( "HTML reformatting requires bs4 or lxml python modules to be installed" ), Qgis::MessageLevel::Warning );
135 }
136 else
137 {
138 newText = result;
139 }
140 }
141 else
142 {
143 QgsDebugError( QStringLiteral( "Error running script: %1" ).arg( script ) );
144 return newText;
145 }
146
147 return newText;
148}
149
151{
152 if ( isReadOnly() )
153 {
154 return;
155 }
156
157 const QString commentStart( "<!--" );
158 const QString commentEnd( "-->" );
159
160 int startLine, startPos, endLine, endPos;
161 if ( hasSelectedText() )
162 {
163 getSelection( &startLine, &startPos, &endLine, &endPos );
164 }
165 else
166 {
167 getCursorPosition( &startLine, &startPos );
168 endLine = startLine;
169 endPos = startPos;
170 }
171
172
173 // Compute first and last non-blank lines
174 while ( text( startLine ).trimmed().isEmpty() )
175 {
176 startLine++;
177 if ( startLine > endLine )
178 {
179 // Only blank lines selected
180 return;
181 }
182 }
183 while ( text( endLine ).trimmed().isEmpty() )
184 {
185 endLine--;
186 }
187
188 // Remove leading spaces from the start line
189 QString startLineTrimmed = text( startLine );
190 startLineTrimmed.remove( QRegularExpression( "^\\s+" ) );
191 // Remove trailing spaces from the end line
192 QString endLineTrimmed = text( endLine );
193 endLineTrimmed.remove( QRegularExpression( "\\s+$" ) );
194
195 const bool commented = startLineTrimmed.startsWith( commentStart ) && endLineTrimmed.endsWith( commentEnd );
196
197 // Special case, selected text is <!--> or <!--->
198 if ( commented && startLine == endLine && text( endLine ).trimmed().size() < commentStart.size() + commentEnd.size() )
199 {
200 return;
201 }
202
203 beginUndoAction();
204
205 // Selection is commented: uncomment it
206 if ( commented )
207 {
208 int c1, c2;
209
210 // Remove trailing comment tag ( --> )
211 c2 = endLineTrimmed.size();
212 if ( endLineTrimmed.endsWith( QStringLiteral( " " ) + commentEnd ) )
213 {
214 c1 = c2 - commentEnd.size() - 1;
215 }
216 else
217 {
218 c1 = c2 - commentEnd.size();
219 }
220
221 setSelection( endLine, c1, endLine, c2 );
222 removeSelectedText();
223
224 // Remove leading comment tag ( <!-- )
225 c1 = indentation( startLine );
226 if ( startLineTrimmed.startsWith( commentStart + QStringLiteral( " " ) ) )
227 {
228 c2 = c1 + commentStart.size() + 1;
229 }
230 else
231 {
232 c2 = c1 + commentStart.size();
233 }
234
235 setSelection( startLine, c1, startLine, c2 );
236 removeSelectedText();
237 }
238 // Selection is not commented: comment it
239 else
240 {
241 insertAt( QStringLiteral( " " ) + commentEnd, endLine, endLineTrimmed.size() );
242 insertAt( commentStart + QStringLiteral( " " ), startLine, indentation( startLine ) );
243 }
244
245 endUndoAction();
246
247 // Restore selection
248 setSelection( startLine, startPos, endLine, endPos );
249}
@ Warning
Warning message.
Definition qgis.h:156
@ Reformat
Language supports automatic code reformatting.
@ ToggleComment
Language supports comment toggling.
ScriptLanguage
Scripting languages.
Definition qgis.h:4181
QFlags< ScriptLanguageCapability > ScriptLanguageCapabilities
Script language capabilities.
Definition qgis.h:4216
@ 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