From f5f03991714612e18f51bc263a88b12c9d8a39c9 Mon Sep 17 00:00:00 2001 From: Alexander Bruy Date: Tue, 30 Jan 2018 17:31:18 +0200 Subject: [PATCH] [processing] use custom editor class, as QgsCodeEditor is not available on some platforms --- .../plugins/processing/script/ScriptEdit.py | 197 ++++++++++++++++++ .../processing/script/ScriptEditorDialog.py | 1 + .../plugins/processing/ui/DlgScriptEditor.ui | 6 +- 3 files changed, 201 insertions(+), 3 deletions(-) create mode 100644 python/plugins/processing/script/ScriptEdit.py diff --git a/python/plugins/processing/script/ScriptEdit.py b/python/plugins/processing/script/ScriptEdit.py new file mode 100644 index 00000000000..61bda7fb9a9 --- /dev/null +++ b/python/plugins/processing/script/ScriptEdit.py @@ -0,0 +1,197 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + ScriptEdit.py + --------------------- + Date : April 2013 + Copyright : (C) 2013 by Alexander Bruy + Email : alexander dot bruy 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. * +* * +*************************************************************************** +""" + +__author__ = 'Alexander Bruy' +__date__ = 'April 2013' +__copyright__ = '(C) 2013, Alexander Bruy' + +# This will get replaced with a git SHA1 when you do a git archive + +__revision__ = '$Format:%H$' + +import os + +from qgis.PyQt.QtCore import Qt +from qgis.PyQt.QtGui import QFont, QColor, QKeySequence +from qgis.PyQt.QtWidgets import QShortcut +from qgis.core import QgsApplication, QgsSettings + +from qgis.PyQt.Qsci import QsciScintilla, QsciLexerPython, QsciAPIs + + +class ScriptEdit(QsciScintilla): + + def __init__(self, parent=None): + QsciScintilla.__init__(self, parent) + + self.lexer = None + self.api = None + + self.setCommonOptions() + self.initShortcuts() + + def setCommonOptions(self): + # Enable non-ASCII characters + self.setUtf8(True) + + # Default font + font = QFont() + font.setFamily('Courier') + font.setFixedPitch(True) + font.setPointSize(20) + self.setFont(font) + self.setMarginsFont(font) + + self.setBraceMatching(QsciScintilla.SloppyBraceMatch) + + self.setWrapMode(QsciScintilla.WrapWord) + self.setWrapVisualFlags(QsciScintilla.WrapFlagByText, + QsciScintilla.WrapFlagNone, 4) + + self.setSelectionForegroundColor(QColor('#2e3436')) + self.setSelectionBackgroundColor(QColor('#babdb6')) + + # Show line numbers + self.setMarginWidth(1, '000') + self.setMarginLineNumbers(1, True) + self.setMarginsForegroundColor(QColor('#2e3436')) + self.setMarginsBackgroundColor(QColor('#babdb6')) + + # Highlight current line + self.setCaretLineVisible(True) + self.setCaretLineBackgroundColor(QColor('#d3d7cf')) + + # Folding + self.setFolding(QsciScintilla.BoxedTreeFoldStyle) + self.setFoldMarginColors(QColor('#d3d7cf'), QColor('#d3d7cf')) + + # Mark column 80 with vertical line + self.setEdgeMode(QsciScintilla.EdgeLine) + self.setEdgeColumn(80) + self.setEdgeColor(QColor('#eeeeec')) + + # Indentation + self.setAutoIndent(True) + self.setIndentationsUseTabs(False) + self.setIndentationWidth(4) + self.setTabIndents(True) + self.setBackspaceUnindents(True) + self.setTabWidth(4) + + # Autocomletion + self.setAutoCompletionThreshold(2) + self.setAutoCompletionSource(QsciScintilla.AcsAPIs) + + self.setFonts(10) + self.initLexer() + + def setFonts(self, size): + # Load font from Python console settings + settings = QgsSettings() + fontName = settings.value('pythonConsole/fontfamilytext', 'Monospace') + fontSize = int(settings.value('pythonConsole/fontsize', size)) + + self.defaultFont = QFont(fontName) + self.defaultFont.setFixedPitch(True) + self.defaultFont.setPointSize(fontSize) + self.defaultFont.setStyleHint(QFont.TypeWriter) + self.defaultFont.setStretch(QFont.SemiCondensed) + self.defaultFont.setLetterSpacing(QFont.PercentageSpacing, 87.0) + self.defaultFont.setBold(False) + + self.boldFont = QFont(self.defaultFont) + self.boldFont.setBold(True) + + self.italicFont = QFont(self.defaultFont) + self.italicFont.setItalic(True) + + self.setFont(self.defaultFont) + self.setMarginsFont(self.defaultFont) + + def initShortcuts(self): + (ctrl, shift) = (self.SCMOD_CTRL << 16, self.SCMOD_SHIFT << 16) + + # Disable some shortcuts + self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord('D') + ctrl) + self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord('L') + ctrl) + self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord('L') + ctrl + + shift) + self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord('T') + ctrl) + + # self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord("Z") + ctrl) + # self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord("Y") + ctrl) + + # Use Ctrl+Space for autocompletion + self.shortcutAutocomplete = QShortcut(QKeySequence(Qt.CTRL + + Qt.Key_Space), self) + self.shortcutAutocomplete.setContext(Qt.WidgetShortcut) + self.shortcutAutocomplete.activated.connect(self.autoComplete) + + def autoComplete(self): + self.autoCompleteFromAll() + + def initLexer(self): + self.lexer = QsciLexerPython() + + colorDefault = QColor('#2e3436') + colorComment = QColor('#c00') + colorCommentBlock = QColor('#3465a4') + colorNumber = QColor('#4e9a06') + colorType = QColor('#4e9a06') + colorKeyword = QColor('#204a87') + colorString = QColor('#ce5c00') + + self.lexer.setDefaultFont(self.defaultFont) + self.lexer.setDefaultColor(colorDefault) + + self.lexer.setColor(colorComment, 1) + self.lexer.setColor(colorNumber, 2) + self.lexer.setColor(colorString, 3) + self.lexer.setColor(colorString, 4) + self.lexer.setColor(colorKeyword, 5) + self.lexer.setColor(colorString, 6) + self.lexer.setColor(colorString, 7) + self.lexer.setColor(colorType, 8) + self.lexer.setColor(colorCommentBlock, 12) + self.lexer.setColor(colorString, 15) + + self.lexer.setFont(self.italicFont, 1) + self.lexer.setFont(self.boldFont, 5) + self.lexer.setFont(self.boldFont, 8) + self.lexer.setFont(self.italicFont, 12) + + self.api = QsciAPIs(self.lexer) + + settings = QgsSettings() + useDefaultAPI = bool(settings.value('pythonConsole/preloadAPI', + True)) + if useDefaultAPI: + # Load QGIS API shipped with Python console + self.api.loadPrepared( + os.path.join(QgsApplication.pkgDataPath(), + 'python', 'qsci_apis', 'pyqgis.pap')) + else: + # Load user-defined API files + apiPaths = settings.value('pythonConsole/userAPI', []) + for path in apiPaths: + self.api.load(path) + self.api.prepare() + self.lexer.setAPIs(self.api) + + self.setLexer(self.lexer) diff --git a/python/plugins/processing/script/ScriptEditorDialog.py b/python/plugins/processing/script/ScriptEditorDialog.py index d184d76ebee..3edbd68260a 100644 --- a/python/plugins/processing/script/ScriptEditorDialog.py +++ b/python/plugins/processing/script/ScriptEditorDialog.py @@ -56,6 +56,7 @@ class ScriptEditorDialog(BASE, WIDGET): QgsGui.instance().enableAutoGeometryRestore(self) + self.editor.initLexer() self.searchWidget.setVisible(False) self.toolBar.setIconSize(iface.iconSize()) diff --git a/python/plugins/processing/ui/DlgScriptEditor.ui b/python/plugins/processing/ui/DlgScriptEditor.ui index 8ccc6824afc..f3943b8f760 100644 --- a/python/plugins/processing/ui/DlgScriptEditor.ui +++ b/python/plugins/processing/ui/DlgScriptEditor.ui @@ -16,7 +16,7 @@ - + @@ -248,9 +248,9 @@ - QgsCodeEditorPython + ScriptEdit QTextEdit -
qgis.gui
+
processing.script.ScriptEdit