class Editor(QsciScintilla): def __init__(self, parent=None): super(Editor,self).__init__(parent) self.parent = parent self.settings = QSettings() # Enable non-ascii chars for editor self.setUtf8(True) # Set the default font font = QFont() font.setFamily('Courier') font.setFixedPitch(True) font.setPointSize(10) self.setFont(font) self.setMarginsFont(font) # Margin 0 is used for line numbers #fm = QFontMetrics(font) #fontmetrics = QFontMetrics(font) self.setMarginsFont(font) self.setMarginWidth(1, "00000") self.setMarginLineNumbers(1, True) self.setMarginsForegroundColor(QColor("#3E3EE3")) self.setMarginsBackgroundColor(QColor("#f9f9f9")) self.setCaretLineVisible(True) self.setCaretLineBackgroundColor(QColor("#fcf3ed")) # Clickable margin 1 for showing markers # self.setMarginSensitivity(1, True) # self.connect(self, # SIGNAL('marginClicked(int, int, Qt::KeyboardModifiers)'), # self.on_margin_clicked) # self.markerDefine(QsciScintilla.RightArrow, # self.ARROW_MARKER_NUM) # self.setMarkerBackgroundColor(QColor("#ee1111"), # self.ARROW_MARKER_NUM) self.setMinimumHeight(120) #self.setMinimumWidth(300) # Folding self.setFolding(QsciScintilla.PlainFoldStyle) self.setFoldMarginColors(QColor("#f4f4f4"),QColor("#f4f4f4")) #self.setWrapMode(QsciScintilla.WrapCharacter) ## Edge Mode self.setEdgeMode(QsciScintilla.EdgeLine) self.setEdgeColumn(80) self.setEdgeColor(QColor("#FF0000")) #self.setWrapMode(QsciScintilla.WrapCharacter) self.setWhitespaceVisibility(QsciScintilla.WsVisibleAfterIndent) #self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) self.settingsEditor() # Annotations #self.setAnnotationDisplay(QsciScintilla.ANNOTATION_BOXED) # Indentation self.setAutoIndent(True) self.setIndentationsUseTabs(False) self.setIndentationWidth(4) self.setTabIndents(True) self.setBackspaceUnindents(True) self.setTabWidth(4) self.setIndentationGuides(True) ## Disable command key ctrl, shift = self.SCMOD_CTRL<<16, self.SCMOD_SHIFT<<16 self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord('L')+ ctrl) self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord('T')+ ctrl) self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord('D')+ ctrl) #self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord('Z')+ ctrl) self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord('Y')+ ctrl) self.SendScintilla(QsciScintilla.SCI_CLEARCMDKEY, ord('L')+ ctrl+shift) ## New QShortcut = ctrl+space/ctrl+alt+space for Autocomplete self.newShortcutCS = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Space), self) self.newShortcutCS.setContext(Qt.WidgetShortcut) self.newShortcutCS.activated.connect(self.autoCompleteKeyBinding) self.runScut = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_E), self) self.runScut.setContext(Qt.WidgetShortcut) self.runScut.activated.connect(self.runSelectedCode) self.runScriptScut = QShortcut(QKeySequence(Qt.SHIFT + Qt.CTRL + Qt.Key_E), self) self.runScriptScut.setContext(Qt.WidgetShortcut) self.runScriptScut.activated.connect(self.runScriptCode) self.commentScut = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_3), self) self.commentScut.setContext(Qt.WidgetShortcut) self.commentScut.activated.connect(self.parent.pc.commentCode) self.uncommentScut = QShortcut(QKeySequence(Qt.SHIFT + Qt.CTRL + Qt.Key_3), self) self.uncommentScut.setContext(Qt.WidgetShortcut) self.uncommentScut.activated.connect(self.parent.pc.uncommentCode) def settingsEditor(self): # Set Python lexer self.setLexers() threshold = self.settings.value("pythonConsole/autoCompThresholdEditor", 2).toInt()[0] radioButtonSource = self.settings.value("pythonConsole/autoCompleteSourceEditor", 'fromAPI').toString() autoCompEnabled = self.settings.value("pythonConsole/autoCompleteEnabledEditor", True).toBool() self.setAutoCompletionThreshold(threshold) if autoCompEnabled: if radioButtonSource == 'fromDoc': self.setAutoCompletionSource(self.AcsDocument) elif radioButtonSource == 'fromAPI': self.setAutoCompletionSource(self.AcsAPIs) elif radioButtonSource == 'fromDocAPI': self.setAutoCompletionSource(self.AcsAll) else: self.setAutoCompletionSource(self.AcsNone) def autoCompleteKeyBinding(self): radioButtonSource = self.settings.value("pythonConsole/autoCompleteSourceEditor").toString() autoCompEnabled = self.settings.value("pythonConsole/autoCompleteEnabledEditor").toBool() if autoCompEnabled: if radioButtonSource == 'fromDoc': self.autoCompleteFromDocument() elif radioButtonSource == 'fromAPI': self.autoCompleteFromAPIs() elif radioButtonSource == 'fromDocAPI': self.autoCompleteFromAll() def on_margin_clicked(self, nmargin, nline, modifiers): # Toggle marker for the line the margin was clicked on if self.markersAtLine(nline) != 0: self.markerDelete(nline, self.ARROW_MARKER_NUM) else: self.markerAdd(nline, self.ARROW_MARKER_NUM) def setLexers(self): from qgis.core import QgsApplication self.lexer = QsciLexerPython() self.lexer.setIndentationWarning(QsciLexerPython.Inconsistent) self.lexer.setFoldComments(True) self.lexer.setFoldQuotes(True) loadFont = self.settings.value("pythonConsole/fontfamilytextEditor", "Monospace").toString() fontSize = self.settings.value("pythonConsole/fontsizeEditor", 10).toInt()[0] font = QFont(loadFont) font.setFixedPitch(True) font.setPointSize(fontSize) font.setStyleHint(QFont.TypeWriter) font.setStretch(QFont.SemiCondensed) font.setLetterSpacing(QFont.PercentageSpacing, 87.0) font.setBold(False) self.lexer.setDefaultFont(font) self.lexer.setColor(Qt.red, 1) self.lexer.setColor(Qt.darkGreen, 5) self.lexer.setColor(Qt.darkBlue, 15) self.lexer.setFont(font, 1) self.lexer.setFont(font, 3) self.lexer.setFont(font, 4) self.api = QsciAPIs(self.lexer) chekBoxAPI = self.settings.value("pythonConsole/preloadAPI", True).toBool() if chekBoxAPI: self.api.loadPrepared( QgsApplication.pkgDataPath() + "/python/qsci_apis/pyqgis_master.pap" ) else: apiPath = self.settings.value("pythonConsole/userAPI").toStringList() for i in range(0, len(apiPath)): self.api.load(QString(unicode(apiPath[i]))) self.api.prepare() self.lexer.setAPIs(self.api) self.setLexer(self.lexer) def move_cursor_to_end(self): """Move cursor to end of text""" line, index = self.get_end_pos() self.setCursorPosition(line, index) self.ensureCursorVisible() self.ensureLineVisible(line) def get_end_pos(self): """Return (line, index) position of the last character""" line = self.lines() - 1 return (line, self.text(line).length()) def contextMenuEvent(self, e): menu = QMenu(self) iconRun = QgsApplication.getThemeIcon("console/iconRunConsole.png") iconCodePad = QgsApplication.getThemeIcon("console/iconCodepadConsole.png") iconNewEditor = QgsApplication.getThemeIcon("console/iconTabEditorConsole.png") iconCommentEditor = QgsApplication.getThemeIcon("console/iconCommentEditorConsole.png") iconUncommentEditor = QgsApplication.getThemeIcon("console/iconUncommentEditorConsole.png") iconSettings = QgsApplication.getThemeIcon("console/iconSettingsConsole.png") hideEditorAction = menu.addAction("Hide Editor", self.hideEditor) menu.addSeparator() newTabAction = menu.addAction(iconNewEditor, "New Tab", self.parent.newTab, 'Ctrl+T') closeTabAction = menu.addAction("Close Tab", self.parent.close, 'Ctrl+W') menu.addSeparator() runSelected = menu.addAction(iconRun, "Enter selected", self.runSelectedCode, 'Ctrl+E') runScript = menu.addAction(iconRun, "Run Script", self.runScriptCode, 'Shift+Ctrl+E') menu.addSeparator() undoAction = menu.addAction("Undo", self.undo, QKeySequence.Undo) redoAction = menu.addAction("Redo", self.redo, QKeySequence.Redo) menu.addSeparator() cutAction = menu.addAction("Cut", self.cut, QKeySequence.Cut) copyAction = menu.addAction("Copy", self.copy, QKeySequence.Copy) pasteAction = menu.addAction("Paste", self.paste, QKeySequence.Paste) menu.addSeparator() commentCodeAction = menu.addAction(iconCommentEditor, "Comment", self.parent.pc.commentCode, 'Ctrl+3') uncommentCodeAction = menu.addAction(iconUncommentEditor, "Uncomment", self.parent.pc.uncommentCode, 'Shift+Ctrl+3') menu.addSeparator() codePadAction = menu.addAction(iconCodePad, "Share on codepad", self.codepad) menu.addSeparator() showCodeInspection = menu.addAction("Hide/Show Object list", self.objectListEditor) menu.addSeparator() selectAllAction = menu.addAction("Select All", self.selectAll, QKeySequence.SelectAll) menu.addSeparator() settingsDialog = menu.addAction(iconSettings, "Settings", self.parent.pc.openSettings) pasteAction.setEnabled(False) codePadAction.setEnabled(False) cutAction.setEnabled(False) runSelected.setEnabled(False) copyAction.setEnabled(False) selectAllAction.setEnabled(False) closeTabAction.setEnabled(False) undoAction.setEnabled(False) redoAction.setEnabled(False) if self.parent.mw.count() > 1: closeTabAction.setEnabled(True) if self.hasSelectedText(): runSelected.setEnabled(True) copyAction.setEnabled(True) cutAction.setEnabled(True) codePadAction.setEnabled(True) if not self.text() == '': selectAllAction.setEnabled(True) if self.isUndoAvailable(): undoAction.setEnabled(True) if self.isRedoAvailable(): redoAction.setEnabled(True) if QApplication.clipboard().text() != "": pasteAction.setEnabled(True) action = menu.exec_(self.mapToGlobal(e.pos())) def objectListEditor(self): listObj = self.parent.pc.listClassMethod if listObj.isVisible(): listObj.hide() self.parent.pc.objectListButton.setChecked(False) else: listObj.show() self.parent.pc.objectListButton.setChecked(True) def codepad(self): import urllib2, urllib listText = self.selectedText().split('\n') getCmd = [] for strLine in listText: if strLine != "": #if s[0:3] in (">>>", "..."): # filter for special command (_save,_clear) and comment if strLine[4] != "_" and strLine[:2] != "##": strLine.replace(">>> ", "").replace("... ", "") getCmd.append(unicode(strLine)) pasteText= u"\n".join(getCmd) url = 'http://codepad.org' values = {'lang' : 'Python', 'code' : pasteText, 'submit':'Submit'} try: response = urllib2.urlopen(url, urllib.urlencode(values)) url = response.read() for href in url.split("</a>"): if "Link:" in href: ind=href.index('Link:') found = href[ind+5:] for i in found.split('">'): if '<a href=' in i: link = i.replace('<a href="',"").strip() if link: QApplication.clipboard().setText(link) msgText = QCoreApplication.translate('PythonConsole', 'URL copied to clipboard.') self.parent.pc.callWidgetMessageBarEditor(msgText) except urllib2.URLError, e: msgText = QCoreApplication.translate('PythonConsole', 'Connection error: ') self.parent.pc.callWidgetMessageBarEditor(msgText + str(e.args))
def __init__(self, parent = None): QsciScintilla.__init__(self, parent) # Time that should enlapse for the tool tip to show self.tool_tip_delay = 1 # Whether or not annotations should be displayed self.annotations_active = False # Set python as language lexer = QsciLexerPython() api = Qsci.QsciAPIs(lexer) self.setLexer(lexer) self.lexer = lexer # NOTE: For some reasone self.lexer() doesn't work # Addictional API api.prepare() lexer.setFoldComments(True) lexer.setFoldCompact(False) # QsciScintilla editing defaults self.setAutoCompletionThreshold(1) self.setAutoCompletionSource(QsciScintilla.AcsAll) self.setAutoIndent(True) self.setIndentationsUseTabs(False) self.setTabIndents(True) self.setBackspaceUnindents(True) self.setIndentationWidth(4) # QScintilla code guides self.setIndentationGuides(True) self.setEdgeMode(QsciScintilla.EDGE_LINE) # Margin 0 is used to display problem markers (errors and warnings) self.setMarginType(0, QsciScintilla.SymbolMargin) self.setMarginWidth(0, 16) self.setMarginMarkerMask(0, 8) # Margin 1 is used to display line numbers self.setMarginType(1, QsciScintilla.TextMarginRightJustified) self._adjust_margin_width() self.setMarginLineNumbers(1, True) self.setMarginMarkerMask(1, 0) # Margin 2 is used to display folding commands self.setMarginType(2, QsciScintilla.SymbolMargin) self.setFolding(QsciScintilla.CircledTreeFoldStyle) # Syntax errors highlight symbols crosscircle_icon = QPixmap("images/crosscircle.png") self._syntax_error_marker = self.markerDefine(crosscircle_icon, 3) self._syntax_error_indicator = self.indicatorDefine( QsciScintilla.SquiggleIndicator) self.setIndicatorForegroundColor(Qt.red, self._syntax_error_indicator) # SyntaxError list self._syntax_errors = [] # Ensure the margin width is enough to show line numbers self.linesChanged.connect(self._adjust_margin_width) # Enable mouse tracking for tooltips QsciScintilla.setMouseTracking(self, True) # Line tool tip timer self._tool_tip_timer = QTimer(self) self._tool_tip_timer.setSingleShot(True) self._tool_tip_timer.timeout.connect(self._show_tool_tip) # Keep track of the mouse position self._mouse_position = None self._global_mouse_position = None