Skip to content
Permalink
Browse files

[console] Fix exception when running scripts (followup cce7aa7)

and move responsibility for showing warning messages to QgsCodeEditor
base class, so that the same code can be used by other dialog script editors
  • Loading branch information
nyalldawson committed Oct 12, 2020
1 parent aaa813a commit 5c8013df6129a2bc06d25a98ff20dbf27621bff5
@@ -80,31 +80,18 @@ def eventFilter(self, obj, event):

class Editor(QgsCodeEditorPython):

MARKER_NUM = 6

def __init__(self, parent=None):
super().__init__(parent)
self.parent = parent
# recent modification time
self.lastModified = 0
self.opening = ['(', '{', '[', "'", '"']
self.closing = [')', '}', ']', "'", '"']

# List of marker line to be deleted from check syntax
self.bufferMarkerLine = []

self.settings = QgsSettings()

self.markerDefine(QgsApplication.getThemePixmap("console/iconSyntaxErrorConsole.svg"),
self.MARKER_NUM)

self.setMinimumHeight(120)

self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)

# Annotations
self.setAnnotationDisplay(QsciScintilla.ANNOTATION_BOXED)

# Disable command key
ctrl, shift = self.SCMOD_CTRL << 16, self.SCMOD_SHIFT << 16
self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord('L') + ctrl)
@@ -160,9 +147,9 @@ def contextMenuEvent(self, e):
QCoreApplication.translate("PythonConsole", "Hide Editor"),
self.hideEditor)
menu.addSeparator() # ------------------------------
syntaxCheck = menu.addAction(QgsApplication.getThemeIcon("console/iconSyntaxErrorConsole.svg"),
QCoreApplication.translate("PythonConsole", "Check Syntax"),
self.syntaxCheck, 'Ctrl+4')
syntaxCheckAction = menu.addAction(QgsApplication.getThemeIcon("console/iconSyntaxErrorConsole.svg"),
QCoreApplication.translate("PythonConsole", "Check Syntax"),
self.syntaxCheck, 'Ctrl+4')
runSelected = menu.addAction(QgsApplication.getThemeIcon("console/mIconRunConsole.svg"), # spellok
QCoreApplication.translate("PythonConsole", "Run Selected"),
self.runSelectedCode, 'Ctrl+E') # spellok
@@ -218,7 +205,7 @@ def contextMenuEvent(self, e):
menu.addAction(QgsApplication.getThemeIcon("console/iconSettingsConsole.svg"),
QCoreApplication.translate("PythonConsole", "Options…"),
self.parent.pc.openSettings)
syntaxCheck.setEnabled(False)
syntaxCheckAction.setEnabled(False)
pasteAction.setEnabled(False)
pyQGISHelpAction.setEnabled(False)
gist_menu.setEnabled(False)
@@ -237,7 +224,7 @@ def contextMenuEvent(self, e):
pyQGISHelpAction.setEnabled(True)
if not self.text() == '':
selectAllAction.setEnabled(True)
syntaxCheck.setEnabled(True)
syntaxCheckAction.setEnabled(True)
if self.isUndoAvailable():
undoAction.setEnabled(True)
if self.isRedoAvailable():
@@ -461,7 +448,7 @@ def runScriptCode(self):
self.parent.pc.callWidgetMessageBarEditor(msgEditorBlank, 0, True)
return

if self.syntaxCheck(fromContextMenu=False):
if self.syntaxCheck():
if filename and self.isModified() and autoSave:
self.parent.save(filename)
elif not filename or self.isModified():
@@ -496,16 +483,13 @@ def goToLine(self, objName, linenr):
self.setFocus()

def syntaxCheck(self):
eline = None
ecolumn = 0
edescr = ''
source = self.text()
self.clearWarnings()
try:
filename = self.parent.tw.currentWidget().path
if not filename:
tmpFile = self.createTempFile()
filename = tmpFile
# source = open(filename, 'r').read() + '\n'
if isinstance(source, type("")):
source = source.encode('utf-8')
if isinstance(filename, type("")):
@@ -514,37 +498,16 @@ def syntaxCheck(self):
compile(source, filename, 'exec')
except SyntaxError as detail:
eline = detail.lineno and detail.lineno or 1
eline -= 1
ecolumn = detail.offset and detail.offset or 1
edescr = detail.msg
if eline is not None:
eline -= 1
for markerLine in self.bufferMarkerLine:
self.markerDelete(markerLine)
self.clearAnnotations(markerLine)
self.bufferMarkerLine.remove(markerLine)
if (eline) not in self.bufferMarkerLine:
self.bufferMarkerLine.append(eline)

self.setMarginWidth(1, "0000")
self.markerAdd(eline, self.MARKER_NUM)
font = self.lexerFont()
font.setItalic(True)
styleAnn = QsciStyle(-1, "Annotation",
QColor(255, 0, 0),
QColor(255, 200, 0),
font,
True)
self.annotate(eline, edescr, styleAnn)

self.addWarning(eline, edescr)
self.setCursorPosition(eline, ecolumn - 1)
# self.setSelection(eline, ecolumn, eline, self.lineLength(eline)-1)
self.ensureLineVisible(eline)
# self.ensureCursorVisible()
return False
else:
self.setMarginWidth(1, 0)
self.markerDeleteAll()
self.clearAnnotations()
return True

return True

def keyPressEvent(self, e):
t = e.text()
@@ -120,6 +120,24 @@ Returns the monospaced font to use for code editors.
%End


void addWarning( int lineNumber, const QString &warning );
%Docstring
Adds a ``warning`` message and indicator to the specified a ``lineNumber``.

.. seealso:: :py:func:`clearWarnings`

.. versionadded:: 3.16
%End

void clearWarnings();
%Docstring
Clears all warning messages from the editor.

.. seealso:: :py:func:`addWarning`

.. versionadded:: 3.16
%End

protected:

bool isFixedPitch( const QFont &font );
@@ -27,6 +27,7 @@
#include <QFontDatabase>
#include <QDebug>
#include <QFocusEvent>
#include <Qsci/qscistyle.h>

QMap< QgsCodeEditorColorScheme::ColorRole, QString > QgsCodeEditor::sColorRoleToSettingsKey
{
@@ -88,6 +89,13 @@ QgsCodeEditor::QgsCodeEditor( QWidget *parent, const QString &title, bool foldin
SendScintilla( SCI_SETMULTIPASTE, 1 );
SendScintilla( SCI_SETVIRTUALSPACEOPTIONS, SCVS_RECTANGULARSELECTION );

markerDefine( QgsApplication::getThemePixmap( "console/iconSyntaxErrorConsole.svg" ),
MARKER_NUMBER );
SendScintilla( SCI_SETMARGINTYPEN, 3, SC_MARGIN_SYMBOL );
SendScintilla( SCI_SETMARGINMASKN, 3, 1 << MARKER_NUMBER );
setMarginWidth( 3, 0 );
setAnnotationDisplay( QsciScintilla::AnnotationBoxed );

connect( QgsGui::instance(), &QgsGui::optionsChanged, this, [ = ]
{
setSciWidget();
@@ -443,3 +451,29 @@ void QgsCodeEditor::setCustomAppearance( const QString &scheme, const QMap<QgsCo
setSciWidget();
initializeLexer();
}

void QgsCodeEditor::addWarning( const int lineNumber, const QString &warning )
{
setMarginWidth( 3, "000" );
markerAdd( lineNumber, MARKER_NUMBER );
QFont font = lexerFont();
font.setItalic( true );
const QsciStyle styleAnn = QsciStyle( -1, QStringLiteral( "Annotation" ),
lexerColor( QgsCodeEditorColorScheme::ColorRole::Error ),
QColor( 255, 200, 0 ), // TODO - expose as configurable color!
font,
true );
annotate( lineNumber, warning, styleAnn );
mWarningLines.push_back( lineNumber );
}

void QgsCodeEditor::clearWarnings()
{
for ( int line : mWarningLines )
{
markerDelete( line );
clearAnnotations( line );
}
setMarginWidth( 3, 0 );
mWarningLines.clear();
}
@@ -135,6 +135,22 @@ class GUI_EXPORT QgsCodeEditor : public QsciScintilla
*/
void setCustomAppearance( const QString &scheme = QString(), const QMap< QgsCodeEditorColorScheme::ColorRole, QColor > &customColors = QMap< QgsCodeEditorColorScheme::ColorRole, QColor >(), const QString &fontFamily = QString(), int fontSize = 0 ) SIP_SKIP;

/**
* Adds a \a warning message and indicator to the specified a \a lineNumber.
*
* \see clearWarnings()
* \since QGIS 3.16
*/
void addWarning( int lineNumber, const QString &warning );

/**
* Clears all warning messages from the editor.
*
* \see addWarning()
* \since QGIS 3.16
*/
void clearWarnings();

protected:

bool isFixedPitch( const QFont &font );
@@ -188,7 +204,11 @@ class GUI_EXPORT QgsCodeEditor : public QsciScintilla
QString mFontFamily;
int mFontSize = 0;

QVector< int > mWarningLines;

static QMap< QgsCodeEditorColorScheme::ColorRole, QString > sColorRoleToSettingsKey;

static constexpr int MARKER_NUMBER = 6;
};

// clazy:excludeall=qstring-allocations

0 comments on commit 5c8013d

Please sign in to comment.
You can’t perform that action at this time.