class PythonEdit(QsciScintilla, code.InteractiveInterpreter): def __init__(self, parent=None): #QsciScintilla.__init__(self, parent) super(PythonEdit, self).__init__(parent) code.InteractiveInterpreter.__init__(self, locals=None) self.parent = parent # Enable non-ascii chars for editor self.setUtf8(True) self.new_input_line = True self.setMarginWidth(0, 0) self.setMarginWidth(1, 0) self.setMarginWidth(2, 0) self.buffer = [] self.displayPrompt(False) for line in _init_commands: self.runsource(line) self.history = QStringList() self.historyIndex = 0 # Read history command file self.readHistoryFile() # Brace matching: enable for a brace immediately before or after # the current position self.setBraceMatching(QsciScintilla.SloppyBraceMatch) #self.moveToMatchingBrace() #self.selectToMatchingBrace() # Current line visible with special background color #self.setCaretLineVisible(True) #self.setCaretLineBackgroundColor(QColor("#ffe4e4")) self.setCaretWidth(2) # Set Python lexer self.setLexers() # Indentation #self.setAutoIndent(True) #self.setIndentationsUseTabs(False) #self.setIndentationWidth(4) #self.setTabIndents(True) #self.setBackspaceUnindents(True) #self.setTabWidth(4) self.setAutoCompletionThreshold(2) self.setAutoCompletionSource(self.AcsAPIs) # Don't want to see the horizontal scrollbar at all # Use raw message to Scintilla here (all messages are documented # here: http://www.scintilla.org/ScintillaDoc.html) self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) # not too small #self.setMinimumSize(500, 300) self.setMinimumHeight(20) self.setWrapMode(QsciScintilla.WrapCharacter) self.SendScintilla(QsciScintilla.SCI_EMPTYUNDOBUFFER) ## 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.newShortcutCAS = QShortcut( QKeySequence(Qt.CTRL + Qt.ALT + Qt.Key_Space), self) self.newShortcutCS.activated.connect(self.autoComplete) self.newShortcutCAS.activated.connect(self.showHistory) self.connect(self, SIGNAL('userListActivated(int, const QString)'), self.completion_list_selected) def showHistory(self): self.showUserList(1, QStringList(self.history)) def autoComplete(self): self.autoCompleteFromAll() def commandConsole(self, command): if not self.is_cursor_on_last_line(): self.move_cursor_to_end() line, pos = self.getCursorPosition() selCmdLenght = self.text(line).length() self.setSelection(line, 4, line, selCmdLenght) self.removeSelectedText() if command == "sextante": # import Sextante class self.append('import sextante') elif command == "qtCore": # import QtCore class self.append('from PyQt4.QtCore import *') elif command == "qtGui": # import QtGui class self.append('from PyQt4.QtGui import *') self.entered() self.move_cursor_to_end() self.setFocus() def setLexers(self): self.lexer = QsciLexerPython() settings = QSettings() loadFont = settings.value("pythonConsole/fontfamilytext", "Monospace").toString() fontSize = settings.value("pythonConsole/fontsize", 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 = settings.value("pythonConsole/preloadAPI", True).toBool() if chekBoxAPI: self.api.loadPrepared(QgsApplication.pkgDataPath() + "/python/qsci_apis/pyqgis_master.pap") else: apiPath = 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) ## TODO: show completion list for file and directory def completion_list_selected(self, id, txt): if id == 1: txt = unicode(txt) # get current cursor position line, pos = self.getCursorPosition() selCmdLength = self.text(line).length() # select typed text self.setSelection(line, 4, line, selCmdLength) self.removeSelectedText() self.insert(txt) def getText(self): """ Get the text as a unicode string. """ value = self.getBytes().decode('utf-8') # print (value) printing can give an error because the console font # may not have all unicode characters return value def getBytes(self): """ Get the text as bytes (utf-8 encoded). This is how the data is stored internally. """ len = self.SendScintilla(self.SCI_GETLENGTH) + 1 bb = QByteArray(len, '0') N = self.SendScintilla(self.SCI_GETTEXT, len, bb) return bytes(bb)[:-1] def getTextLength(self): return self.SendScintilla(QsciScintilla.SCI_GETLENGTH) def get_end_pos(self): """Return (line, index) position of the last character""" line = self.lines() - 1 return (line, self.text(line).length()) def is_cursor_at_end(self): """Return True if cursor is at the end of text""" cline, cindex = self.getCursorPosition() return (cline, cindex) == self.get_end_pos() 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 on_new_line(self): # """On new input line""" # self.move_cursor_to_end() # self.new_input_line = False def is_cursor_on_last_line(self): """Return True if cursor is on the last line""" cline, _ = self.getCursorPosition() return cline == self.lines() - 1 def is_cursor_on_edition_zone(self): """ Return True if the cursor is in the edition zone """ cline, cindex = self.getCursorPosition() return cline == self.lines() - 1 and cindex >= 4 def new_prompt(self, prompt): """ Print a new prompt and save its (line, index) position """ self.write(prompt, prompt=True) # now we update our cursor giving end of prompt line, index = self.getCursorPosition() self.ensureCursorVisible() self.ensureLineVisible(line) def refreshLexerProperties(self): self.setLexers() # def check_selection(self): # """ # Check if selected text is r/w, # otherwise remove read-only parts of selection # """ # #if self.current_prompt_pos is None: # #self.move_cursor_to_end() # #return # line_from, index_from, line_to, index_to = self.getSelection() # pline, pindex = self.getCursorPosition() # if line_from < pline or \ # (line_from == pline and index_from < pindex): # self.setSelection(pline, pindex, line_to, index_to) def displayPrompt(self, more=False): self.append("... ") if more else self.append(">>> ") self.move_cursor_to_end() def updateHistory(self, command): if isinstance(command, QStringList): for line in command: self.history.append(line) elif not command == "": if len(self.history) <= 0 or \ not command == self.history[-1]: self.history.append(command) self.historyIndex = len(self.history) def writeHistoryFile(self): wH = open(_historyFile, 'w') for s in self.history: wH.write(s + '\n') wH.close() def readHistoryFile(self): fileExist = QFile.exists(_historyFile) if fileExist: rH = open(_historyFile, 'r') for line in rH: if line != "\n": l = line.rstrip('\n') self.updateHistory(l) else: return def clearHistoryFile(self): cH = open(_historyFile, 'w') cH.close() def showPrevious(self): if self.historyIndex < len( self.history) and not self.history.isEmpty(): line, pos = self.getCursorPosition() selCmdLenght = self.text(line).length() self.setSelection(line, 4, line, selCmdLenght) self.removeSelectedText() self.historyIndex += 1 if self.historyIndex == len(self.history): self.insert("") pass else: self.insert(self.history[self.historyIndex]) self.move_cursor_to_end() #self.SendScintilla(QsciScintilla.SCI_DELETEBACK) def showNext(self): if self.historyIndex > 0 and not self.history.isEmpty(): line, pos = self.getCursorPosition() selCmdLenght = self.text(line).length() self.setSelection(line, 4, line, selCmdLenght) self.removeSelectedText() self.historyIndex -= 1 if self.historyIndex == len(self.history): self.insert("") else: self.insert(self.history[self.historyIndex]) self.move_cursor_to_end() #self.SendScintilla(QsciScintilla.SCI_DELETEBACK) def keyPressEvent(self, e): startLine, _, endLine, _ = self.getSelection() # handle invalid cursor position and multiline selections if not self.is_cursor_on_edition_zone() or startLine < endLine: # allow to copy and select if e.modifiers() & (Qt.ControlModifier | Qt.MetaModifier): if e.key() in (Qt.Key_C, Qt.Key_A): QsciScintilla.keyPressEvent(self, e) return # allow selection if e.modifiers() & Qt.ShiftModifier: if e.key() in (Qt.Key_Left, Qt.Key_Right, Qt.Key_Home, Qt.Key_End): QsciScintilla.keyPressEvent(self, e) return # all other keystrokes get sent to the input line self.move_cursor_to_end() line, index = self.getCursorPosition() cmd = self.text(line) if e.key() in (Qt.Key_Return, Qt.Key_Enter) and not self.isListActive(): self.entered() elif e.key() in (Qt.Key_Left, Qt.Key_Home): QsciScintilla.keyPressEvent(self, e) # check whether the cursor is moved out of the edition zone newline, newindex = self.getCursorPosition() if newline < line or newindex < 4: # fix selection and the cursor position if self.hasSelectedText(): self.setSelection(line, self.getSelection()[3], line, 4) else: self.setCursorPosition(line, 4) elif e.key() in (Qt.Key_Backspace, Qt.Key_Delete): QsciScintilla.keyPressEvent(self, e) # check whether the cursor is moved out of the edition zone _, newindex = self.getCursorPosition() if newindex < 4: # restore the prompt chars (if removed) and # fix the cursor position self.insert(cmd[:3 - newindex] + " ") self.setCursorPosition(line, 4) self.recolor() elif e.modifiers() & (Qt.ControlModifier | Qt.MetaModifier) and \ e.key() == Qt.Key_V: self.paste() e.accept() elif e.key() == Qt.Key_Down and not self.isListActive(): self.showPrevious() elif e.key() == Qt.Key_Up and not self.isListActive(): self.showNext() ## TODO: press event for auto-completion file directory else: QsciScintilla.keyPressEvent(self, e) def contextMenuEvent(self, e): menu = QMenu(self) copyAction = menu.addAction("Copy", self.copy, QKeySequence.Copy) pasteAction = menu.addAction("Paste", self.paste, QKeySequence.Paste) copyAction.setEnabled(False) pasteAction.setEnabled(False) if self.hasSelectedText(): copyAction.setEnabled(True) if QApplication.clipboard().text() != "": pasteAction.setEnabled(True) action = menu.exec_(self.mapToGlobal(e.pos())) def mousePressEvent(self, e): """ Re-implemented to handle the mouse press event. e: the mouse press event (QMouseEvent) """ self.setFocus() if e.button() == Qt.MidButton: stringSel = unicode(QApplication.clipboard().text( QClipboard.Selection)) if not self.is_cursor_on_last_line(): self.move_cursor_to_end() self.insertFromDropPaste(stringSel) e.accept() else: QsciScintilla.mousePressEvent(self, e) def paste(self): """ Method to display data from the clipboard. XXX: It should reimplement the virtual QScintilla.paste method, but it seems not used by QScintilla code. """ stringPaste = unicode(QApplication.clipboard().text()) if self.is_cursor_on_last_line(): if self.hasSelectedText(): self.removeSelectedText() else: self.move_cursor_to_end() self.insertFromDropPaste(stringPaste) ## Drag and drop def dropEvent(self, e): if e.mimeData().hasText(): stringDrag = e.mimeData().text() self.insertFromDropPaste(stringDrag) self.setFocus() e.setDropAction(Qt.MoveAction) e.accept() else: QsciScintillaCompat.dropEvent(self, e) def insertFromDropPaste(self, textDP): pasteList = textDP.split("\n") for line in pasteList[:-1]: line.replace(">>> ", "").replace("... ", "") self.insert(line) self.move_cursor_to_end() self.runCommand(unicode(self.currentCommand())) if pasteList[-1] != "": line = pasteList[-1] line.replace(">>> ", "").replace("... ", "") self.insert(unicode(line)) self.move_cursor_to_end() # def getTextFromEditor(self): # text = self.text() # textList = text.split("\n") # return textList def insertTextFromFile(self, listOpenFile): for line in listOpenFile[:-1]: self.append(line) self.move_cursor_to_end() self.SendScintilla(QsciScintilla.SCI_DELETEBACK) self.runCommand(unicode(self.currentCommand())) self.append(unicode(listOpenFile[-1])) self.move_cursor_to_end() self.SendScintilla(QsciScintilla.SCI_DELETEBACK) def entered(self): self.move_cursor_to_end() self.runCommand(unicode(self.currentCommand())) self.setFocus() self.move_cursor_to_end() #self.SendScintilla(QsciScintilla.SCI_EMPTYUNDOBUFFER) def currentCommand(self): linenr, index = self.getCursorPosition() #for i in range(0, linenr): txtLength = self.text(linenr).length() string = self.text() cmdLine = string.right(txtLength - 4) cmd = unicode(cmdLine) return cmd def runCommand(self, cmd): self.write_stdout(cmd) import webbrowser self.updateHistory(cmd) line, pos = self.getCursorPosition() selCmdLenght = self.text(line).length() self.setSelection(line, 0, line, selCmdLenght) self.removeSelectedText() if cmd in ('_save', '_clear', '_clearAll', '_pyqgis', '_api'): if cmd == '_save': self.writeHistoryFile() msgText = QCoreApplication.translate( 'PythonConsole', 'History saved successfully.') elif cmd == '_clear': self.clearHistoryFile() msgText = QCoreApplication.translate( 'PythonConsole', 'History cleared successfully.') elif cmd == '_clearAll': self.history = QStringList() self.clearHistoryFile() msgText = QCoreApplication.translate( 'PythonConsole', 'Session and file history cleared successfully.') elif cmd == '_pyqgis': webbrowser.open("http://www.qgis.org/pyqgis-cookbook/") elif cmd == '_api': webbrowser.open("http://www.qgis.org/api/") if msgText: self.parent.callWidgetMessageBar(msgText) self.displayPrompt(False) else: self.buffer.append(cmd) src = u"\n".join(self.buffer) more = self.runsource(src, "<input>") if not more: self.buffer = [] self.move_cursor_to_end() self.displayPrompt(more) def write(self, txt): sys.stderr.write(txt) def write_stdout(self, txt): if len(txt) > 0: getCmdString = self.text() prompt = getCmdString[0:4] sys.stdout.write(prompt + txt + '\n')
class ShellScintilla(QsciScintilla, code.InteractiveInterpreter): def __init__(self, parent=None): super(ShellScintilla,self).__init__(parent) code.InteractiveInterpreter.__init__(self, locals=None) self.parent = parent self.opening = ['(', '{', '[', "'", '"'] self.closing = [')', '}', ']', "'", '"'] self.settings = QSettings() # Enable non-ascii chars for editor self.setUtf8(True) self.new_input_line = True self.setMarginWidth(0, 0) self.setMarginWidth(1, 0) self.setMarginWidth(2, 0) self.buffer = [] self.displayPrompt(False) for line in _init_commands: self.runsource(line) self.history = [] self.historyIndex = 0 # Read history command file self.readHistoryFile() self.historyDlg = HistoryDialog(self) # Brace matching: enable for a brace immediately before or after # the current position self.setBraceMatching(QsciScintilla.SloppyBraceMatch) self.setMatchedBraceBackgroundColor(QColor("#b7f907")) # Current line visible with special background color self.setCaretWidth(2) self.refreshSettingsShell() # Don't want to see the horizontal scrollbar at all # Use raw message to Scintilla here (all messages are documented # here: http://www.scintilla.org/ScintillaDoc.html) self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) # not too small #self.setMinimumSize(500, 300) self.setWrapMode(QsciScintilla.WrapCharacter) self.SendScintilla(QsciScintilla.SCI_EMPTYUNDOBUFFER) ## 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.newShortcutCSS = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_Space), self) self.newShortcutCAS = QShortcut(QKeySequence(Qt.CTRL + Qt.ALT + Qt.Key_Space), self) self.newShortcutCSS.setContext(Qt.WidgetShortcut) self.newShortcutCAS.setContext(Qt.WidgetShortcut) self.newShortcutCAS.activated.connect(self.autoCompleteKeyBinding) self.newShortcutCSS.activated.connect(self.showHistory) def _setMinimumHeight(self): fnt = self.settings.value("pythonConsole/fontfamilytext", "Monospace") fntSize = self.settings.value("pythonConsole/fontsize", 10, type=int) fm = QFontMetrics(QFont(fnt, fntSize)) self.setMinimumHeight(fm.height() + 10) def refreshSettingsShell(self): # Set Python lexer self.setLexers() threshold = self.settings.value("pythonConsole/autoCompThreshold", 2, type=int) self.setAutoCompletionThreshold(threshold) radioButtonSource = self.settings.value("pythonConsole/autoCompleteSource", 'fromAPI') autoCompEnabled = self.settings.value("pythonConsole/autoCompleteEnabled", True, type=bool) 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) cursorColor = self.settings.value("pythonConsole/cursorColor", QColor(Qt.black)) self.setCaretForegroundColor(cursorColor) # Sets minimum height for input area based of font metric self._setMinimumHeight() def showHistory(self): if not self.historyDlg.isVisible(): self.historyDlg.show() self.historyDlg._reloadHistory() self.historyDlg.activateWindow() def autoCompleteKeyBinding(self): radioButtonSource = self.settings.value("pythonConsole/autoCompleteSource", 'fromAPI') autoCompEnabled = self.settings.value("pythonConsole/autoCompleteEnabled", True, type=bool) if autoCompEnabled: if radioButtonSource == 'fromDoc': self.autoCompleteFromDocument() elif radioButtonSource == 'fromAPI': self.autoCompleteFromAPIs() elif radioButtonSource == 'fromDocAPI': self.autoCompleteFromAll() def commandConsole(self, command): if not self.is_cursor_on_last_line(): self.move_cursor_to_end() line, pos = self.getCursorPosition() selCmdLenght = len(self.text(line)) self.setSelection(line, 4, line, selCmdLenght) self.removeSelectedText() if command == "processing": # import Processing class self.append('import processing') elif command == "qtCore": # import QtCore class self.append('from PyQt4.QtCore import *') elif command == "qtGui": # import QtGui class self.append('from PyQt4.QtGui import *') self.entered() self.move_cursor_to_end() self.setFocus() def setLexers(self): self.lexer = QsciLexerPython() loadFont = self.settings.value("pythonConsole/fontfamilytext", "Monospace") fontSize = self.settings.value("pythonConsole/fontsize", 10, type=int) 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.setDefaultColor(QColor(self.settings.value("pythonConsole/defaultFontColor", QColor(Qt.black)))) self.lexer.setColor(QColor(self.settings.value("pythonConsole/commentFontColor", QColor(Qt.gray))), 1) self.lexer.setColor(QColor(self.settings.value("pythonConsole/keywordFontColor", QColor(Qt.darkGreen))), 5) self.lexer.setColor(QColor(self.settings.value("pythonConsole/classFontColor", QColor(Qt.blue))), 8) self.lexer.setColor(QColor(self.settings.value("pythonConsole/methodFontColor", QColor(Qt.darkGray))), 9) self.lexer.setColor(QColor(self.settings.value("pythonConsole/decorFontColor", QColor(Qt.darkBlue))), 15) self.lexer.setColor(QColor(self.settings.value("pythonConsole/commentBlockFontColor", QColor(Qt.gray))), 12) self.lexer.setColor(QColor(self.settings.value("pythonConsole/singleQuoteFontColor", QColor(Qt.blue))), 4) self.lexer.setColor(QColor(self.settings.value("pythonConsole/doubleQuoteFontColor", QColor(Qt.blue))), 3) self.lexer.setColor(QColor(self.settings.value("pythonConsole/tripleSingleQuoteFontColor", QColor(Qt.blue))), 6) self.lexer.setColor(QColor(self.settings.value("pythonConsole/tripleDoubleQuoteFontColor", QColor(Qt.blue))), 7) self.lexer.setFont(font, 1) self.lexer.setFont(font, 3) self.lexer.setFont(font, 4) for style in range(0, 33): paperColor = QColor(self.settings.value("pythonConsole/paperBackgroundColor", QColor(Qt.white))) self.lexer.setPaper(paperColor, style) self.api = QsciAPIs(self.lexer) chekBoxAPI = self.settings.value("pythonConsole/preloadAPI", True, type=bool) chekBoxPreparedAPI = self.settings.value("pythonConsole/usePreparedAPIFile", False, type=bool) if chekBoxAPI: pap = os.path.join(QgsApplication.pkgDataPath(), "python", "qsci_apis", "pyqgis.pap") self.api.loadPrepared(pap) elif chekBoxPreparedAPI: self.api.loadPrepared(self.settings.value("pythonConsole/preparedAPIFile")) else: apiPath = self.settings.value("pythonConsole/userAPI", []) for i in range(0, len(apiPath)): self.api.load(unicode(apiPath[i])) self.api.prepare() self.lexer.setAPIs(self.api) self.setLexer(self.lexer) ## TODO: show completion list for file and directory def getText(self): """ Get the text as a unicode string. """ value = self.getBytes().decode('utf-8') # print (value) printing can give an error because the console font # may not have all unicode characters return value def getBytes(self): """ Get the text as bytes (utf-8 encoded). This is how the data is stored internally. """ len = self.SendScintilla(self.SCI_GETLENGTH)+1 bb = QByteArray(len,'0') N = self.SendScintilla(self.SCI_GETTEXT, len, bb) return bytes(bb)[:-1] def getTextLength(self): return self.SendScintilla(QsciScintilla.SCI_GETLENGTH) def get_end_pos(self): """Return (line, index) position of the last character""" line = self.lines() - 1 return (line, len(self.text(line))) def is_cursor_at_end(self): """Return True if cursor is at the end of text""" cline, cindex = self.getCursorPosition() return (cline, cindex) == self.get_end_pos() 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 is_cursor_on_last_line(self): """Return True if cursor is on the last line""" cline, _ = self.getCursorPosition() return cline == self.lines() - 1 def is_cursor_on_edition_zone(self): """ Return True if the cursor is in the edition zone """ cline, cindex = self.getCursorPosition() return cline == self.lines() - 1 and cindex >= 4 def new_prompt(self, prompt): """ Print a new prompt and save its (line, index) position """ self.write(prompt, prompt=True) # now we update our cursor giving end of prompt line, index = self.getCursorPosition() self.ensureCursorVisible() self.ensureLineVisible(line) def displayPrompt(self, more=False): self.append("... ") if more else self.append(">>> ") self.move_cursor_to_end() def updateHistory(self, command): if isinstance(command, list): for line in command: self.history.append(line) elif not command == "": if len(self.history) <= 0 or \ not command == self.history[-1]: self.history.append(command) self.historyIndex = len(self.history) def writeHistoryFile(self, fromCloseConsole=False): ok = False try: wH = codecs.open(_historyFile, 'w', encoding='utf-8') for s in self.history: wH.write(s + '\n') ok = True except: raise wH.close() if ok and not fromCloseConsole: msgText = QCoreApplication.translate('PythonConsole', 'History saved successfully.') self.parent.callWidgetMessageBar(msgText) def readHistoryFile(self): fileExist = QFile.exists(_historyFile) if fileExist: rH = codecs.open(_historyFile, 'r', encoding='utf-8') for line in rH: if line != "\n": l = line.rstrip('\n') self.updateHistory(l) else: return def clearHistory(self, clearSession=False): if clearSession: self.history = [] msgText = QCoreApplication.translate('PythonConsole', 'Session and file history cleared successfully.') self.parent.callWidgetMessageBar(msgText) return ok = False try: cH = codecs.open(_historyFile, 'w', encoding='utf-8') ok = True except: raise cH.close() if ok: msgText = QCoreApplication.translate('PythonConsole', 'History cleared successfully.') self.parent.callWidgetMessageBar(msgText) def clearHistorySession(self): self.clearHistory(True) def showPrevious(self): if self.historyIndex < len(self.history) and self.history: line, pos = self.getCursorPosition() selCmdLenght = len(self.text(line)) self.setSelection(line, 4, line, selCmdLenght) self.removeSelectedText() self.historyIndex += 1 if self.historyIndex == len(self.history): self.insert("") pass else: self.insert(self.history[self.historyIndex]) self.move_cursor_to_end() #self.SendScintilla(QsciScintilla.SCI_DELETEBACK) def showNext(self): if self.historyIndex > 0 and self.history: line, pos = self.getCursorPosition() selCmdLenght = len(self.text(line)) self.setSelection(line, 4, line, selCmdLenght) self.removeSelectedText() self.historyIndex -= 1 if self.historyIndex == len(self.history): self.insert("") else: self.insert(self.history[self.historyIndex]) self.move_cursor_to_end() #self.SendScintilla(QsciScintilla.SCI_DELETEBACK) def keyPressEvent(self, e): startLine, startPos, endLine, endPos = self.getSelection() # handle invalid cursor position and multiline selections if not self.is_cursor_on_edition_zone() or startLine < endLine: # allow to copy and select if e.modifiers() & (Qt.ControlModifier | Qt.MetaModifier): if e.key() in (Qt.Key_C, Qt.Key_A): QsciScintilla.keyPressEvent(self, e) return # allow selection if e.modifiers() & Qt.ShiftModifier: if e.key() in (Qt.Key_Left, Qt.Key_Right, Qt.Key_Home, Qt.Key_End): QsciScintilla.keyPressEvent(self, e) return # all other keystrokes get sent to the input line self.move_cursor_to_end() line, index = self.getCursorPosition() cmd = self.text(line) if e.key() in (Qt.Key_Return, Qt.Key_Enter) and not self.isListActive(): self.entered() elif e.key() in (Qt.Key_Left, Qt.Key_Home): QsciScintilla.keyPressEvent(self, e) # check whether the cursor is moved out of the edition zone newline, newindex = self.getCursorPosition() if newline < line or newindex < 4: # fix selection and the cursor position if self.hasSelectedText(): self.setSelection(line, self.getSelection()[3], line, 4) else: self.setCursorPosition(line, 4) elif e.key() in (Qt.Key_Backspace, Qt.Key_Delete): QsciScintilla.keyPressEvent(self, e) # check whether the cursor is moved out of the edition zone _, newindex = self.getCursorPosition() if newindex < 4: # restore the prompt chars (if removed) and # fix the cursor position self.insert( cmd[:3-newindex] + " " ) self.setCursorPosition(line, 4) self.recolor() elif (e.modifiers() & (Qt.ControlModifier | Qt.MetaModifier) and \ e.key() == Qt.Key_V) or \ (e.modifiers() & Qt.ShiftModifier and e.key() == Qt.Key_Insert): self.paste() e.accept() elif e.key() == Qt.Key_Down and not self.isListActive(): self.showPrevious() elif e.key() == Qt.Key_Up and not self.isListActive(): self.showNext() ## TODO: press event for auto-completion file directory else: t = unicode(e.text()) self.autoCloseBracket = self.settings.value("pythonConsole/autoCloseBracket", False, type=bool) self.autoImport = self.settings.value("pythonConsole/autoInsertionImport", True, type=bool) txt = cmd[:index].replace('>>> ', '').replace('... ', '') ## Close bracket automatically if t in self.opening and self.autoCloseBracket: i = self.opening.index(t) if self.hasSelectedText() and startPos != 0: selText = self.selectedText() self.removeSelectedText() self.insert(self.opening[i] + selText + self.closing[i]) self.setCursorPosition(endLine, endPos+2) return elif t == '(' and (re.match(r'^[ \t]*def \w+$', txt) \ or re.match(r'^[ \t]*class \w+$', txt)): self.insert('):') else: self.insert(self.closing[i]) ## FIXES #8392 (automatically removes the redundant char ## when autoclosing brackets option is enabled) elif t in [')', ']', '}'] and self.autoCloseBracket: txt = self.text(line) try: if txt[index-1] in self.opening and t == txt[index]: self.setCursorPosition(line, index+1) self.SendScintilla(QsciScintilla.SCI_DELETEBACK) except IndexError: pass elif t == ' ' and self.autoImport: ptrn = r'^[ \t]*from [\w.]+$' if re.match(ptrn, txt): self.insert(' import') self.setCursorPosition(line, index + 7) QsciScintilla.keyPressEvent(self, e) def contextMenuEvent(self, e): menu = QMenu(self) subMenu = QMenu(menu) titleHistoryMenu = QCoreApplication.translate("PythonConsole", "Command History") subMenu.setTitle(titleHistoryMenu) showHistoryAction = subMenu.addAction( QCoreApplication.translate("PythonConsole", "Show"), self.showHistory, 'Ctrl+Shift+SPACE') subMenu.addSeparator() saveHistoryAction = subMenu.addAction( QCoreApplication.translate("PythonConsole", "Save"), self.writeHistoryFile) subMenu.addSeparator() clearHistoryAction = subMenu.addAction( QCoreApplication.translate("PythonConsole", "Clear File"), self.clearHistory) clearSessHistoryAction = subMenu.addAction( QCoreApplication.translate("PythonConsole", "Clear Session"), self.clearHistorySession) menu.addMenu(subMenu) menu.addSeparator() copyAction = menu.addAction( QCoreApplication.translate("PythonConsole", "Copy"), self.copy, QKeySequence.Copy) pasteAction = menu.addAction( QCoreApplication.translate("PythonConsole", "Paste"), self.paste, QKeySequence.Paste) copyAction.setEnabled(False) pasteAction.setEnabled(False) if self.hasSelectedText(): copyAction.setEnabled(True) if QApplication.clipboard().text(): pasteAction.setEnabled(True) action = menu.exec_(self.mapToGlobal(e.pos())) def mousePressEvent(self, e): """ Re-implemented to handle the mouse press event. e: the mouse press event (QMouseEvent) """ self.setFocus() if e.button() == Qt.MidButton: stringSel = unicode(QApplication.clipboard().text(QClipboard.Selection)) if not self.is_cursor_on_last_line(): self.move_cursor_to_end() self.insertFromDropPaste(stringSel) e.accept() else: QsciScintilla.mousePressEvent(self, e) def paste(self): """ Method to display data from the clipboard. XXX: It should reimplement the virtual QScintilla.paste method, but it seems not used by QScintilla code. """ stringPaste = unicode(QApplication.clipboard().text()) if self.is_cursor_on_last_line(): if self.hasSelectedText(): self.removeSelectedText() else: self.move_cursor_to_end() self.insertFromDropPaste(stringPaste) ## Drag and drop def dropEvent(self, e): if e.mimeData().hasText(): stringDrag = e.mimeData().text() self.insertFromDropPaste(stringDrag) self.setFocus() e.setDropAction(Qt.CopyAction) e.accept() else: QsciScintillaCompat.dropEvent(self, e) def insertFromDropPaste(self, textDP): pasteList = unicode(textDP).splitlines() if pasteList: for line in pasteList[:-1]: cleanLine = line.replace(">>> ", "").replace("... ", "") self.insert(unicode(cleanLine)) self.move_cursor_to_end() self.runCommand(unicode(self.currentCommand())) if pasteList[-1] != "": line = pasteList[-1] cleanLine = line.replace(">>> ", "").replace("... ", "") self.insert(unicode(cleanLine)) self.move_cursor_to_end() def insertTextFromFile(self, listOpenFile): for line in listOpenFile[:-1]: self.append(line) self.move_cursor_to_end() self.SendScintilla(QsciScintilla.SCI_DELETEBACK) self.runCommand(unicode(self.currentCommand())) self.append(unicode(listOpenFile[-1])) self.move_cursor_to_end() self.SendScintilla(QsciScintilla.SCI_DELETEBACK) def entered(self): self.move_cursor_to_end() self.runCommand( unicode(self.currentCommand()) ) self.setFocus() self.move_cursor_to_end() def currentCommand(self): linenr, index = self.getCursorPosition() txtLength = len(self.text(linenr)) string = self.text() cmdLine = string[4:] cmd = unicode(cmdLine) return cmd def runCommand(self, cmd): self.writeCMD(cmd) import webbrowser self.updateHistory(cmd) if cmd in ('_pyqgis', '_api'): if cmd == '_pyqgis': webbrowser.open( "http://qgis.org/pyqgis-cookbook/" ) elif cmd == '_api': webbrowser.open( "http://qgis.org/api/" ) more = False else: self.buffer.append(cmd) src = u"\n".join(self.buffer) more = self.runsource(src, "<input>") if not more: self.buffer = [] ## prevents to commands with more lines to break the console ## in the case they have a eol different from '\n' self.setText('') self.move_cursor_to_end() self.displayPrompt(more) def write(self, txt): sys.stderr.write(txt) def writeCMD(self, txt): if len(txt) > 0: getCmdString = self.text() prompt = getCmdString[0:4] sys.stdout.write(prompt+txt+'\n')
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))
class ShellScintilla(QsciScintilla, code.InteractiveInterpreter): def __init__(self, parent=None): super(ShellScintilla, self).__init__(parent) code.InteractiveInterpreter.__init__(self, locals=None) self.parent = parent self.settings = QSettings() # Enable non-ascii chars for editor self.setUtf8(True) self.new_input_line = True self.setMarginWidth(0, 0) self.setMarginWidth(1, 0) self.setMarginWidth(2, 0) self.buffer = [] self.displayPrompt(False) for line in _init_commands: self.runsource(line) self.history = QStringList() self.historyIndex = 0 # Read history command file self.readHistoryFile() # Brace matching: enable for a brace immediately before or after # the current position self.setBraceMatching(QsciScintilla.SloppyBraceMatch) # Current line visible with special background color self.setCaretWidth(2) self.settingsShell() # Don't want to see the horizontal scrollbar at all # Use raw message to Scintilla here (all messages are documented # here: http://www.scintilla.org/ScintillaDoc.html) self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) # not too small # self.setMinimumSize(500, 300) self.setMinimumHeight(20) self.setWrapMode(QsciScintilla.WrapCharacter) self.SendScintilla(QsciScintilla.SCI_EMPTYUNDOBUFFER) ## 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.newShortcutCSS = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_Space), self) self.newShortcutCAS = QShortcut(QKeySequence(Qt.CTRL + Qt.ALT + Qt.Key_Space), self) self.newShortcutCSS.setContext(Qt.WidgetShortcut) self.newShortcutCAS.setContext(Qt.WidgetShortcut) self.newShortcutCAS.activated.connect(self.autoCompleteKeyBinding) self.newShortcutCSS.activated.connect(self.showHistory) self.connect(self, SIGNAL("userListActivated(int, const QString)"), self.completion_list_selected) def settingsShell(self): # Set Python lexer self.setLexers() threshold = self.settings.value("pythonConsole/autoCompThreshold", 2).toInt()[0] self.setAutoCompletionThreshold(threshold) radioButtonSource = self.settings.value("pythonConsole/autoCompleteSource", "fromAPI").toString() autoCompEnabled = self.settings.value("pythonConsole/autoCompleteEnabled", 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 showHistory(self): self.showUserList(1, QStringList(self.history)) def autoCompleteKeyBinding(self): radioButtonSource = self.settings.value("pythonConsole/autoCompleteSource").toString() autoCompEnabled = self.settings.value("pythonConsole/autoCompleteEnabled").toBool() if autoCompEnabled: if radioButtonSource == "fromDoc": self.autoCompleteFromDocument() elif radioButtonSource == "fromAPI": self.autoCompleteFromAPIs() elif radioButtonSource == "fromDocAPI": self.autoCompleteFromAll() def commandConsole(self, command): if not self.is_cursor_on_last_line(): self.move_cursor_to_end() line, pos = self.getCursorPosition() selCmdLenght = self.text(line).length() self.setSelection(line, 4, line, selCmdLenght) self.removeSelectedText() if command == "sextante": # import Sextante class self.append("import sextante") elif command == "qtCore": # import QtCore class self.append("from PyQt4.QtCore import *") elif command == "qtGui": # import QtGui class self.append("from PyQt4.QtGui import *") self.entered() self.move_cursor_to_end() self.setFocus() def setLexers(self): self.lexer = QsciLexerPython() loadFont = self.settings.value("pythonConsole/fontfamilytext", "Monospace").toString() fontSize = self.settings.value("pythonConsole/fontsize", 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) ## TODO: show completion list for file and directory def completion_list_selected(self, id, txt): if id == 1: txt = unicode(txt) # get current cursor position line, pos = self.getCursorPosition() selCmdLength = self.text(line).length() # select typed text self.setSelection(line, 4, line, selCmdLength) self.removeSelectedText() self.insert(txt) def getText(self): """ Get the text as a unicode string. """ value = self.getBytes().decode("utf-8") # print (value) printing can give an error because the console font # may not have all unicode characters return value def getBytes(self): """ Get the text as bytes (utf-8 encoded). This is how the data is stored internally. """ len = self.SendScintilla(self.SCI_GETLENGTH) + 1 bb = QByteArray(len, "0") N = self.SendScintilla(self.SCI_GETTEXT, len, bb) return bytes(bb)[:-1] def getTextLength(self): return self.SendScintilla(QsciScintilla.SCI_GETLENGTH) def get_end_pos(self): """Return (line, index) position of the last character""" line = self.lines() - 1 return (line, self.text(line).length()) def is_cursor_at_end(self): """Return True if cursor is at the end of text""" cline, cindex = self.getCursorPosition() return (cline, cindex) == self.get_end_pos() 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 on_new_line(self): # """On new input line""" # self.move_cursor_to_end() # self.new_input_line = False def is_cursor_on_last_line(self): """Return True if cursor is on the last line""" cline, _ = self.getCursorPosition() return cline == self.lines() - 1 def is_cursor_on_edition_zone(self): """ Return True if the cursor is in the edition zone """ cline, cindex = self.getCursorPosition() return cline == self.lines() - 1 and cindex >= 4 def new_prompt(self, prompt): """ Print a new prompt and save its (line, index) position """ self.write(prompt, prompt=True) # now we update our cursor giving end of prompt line, index = self.getCursorPosition() self.ensureCursorVisible() self.ensureLineVisible(line) def displayPrompt(self, more=False): self.append("... ") if more else self.append(">>> ") self.move_cursor_to_end() def updateHistory(self, command): if isinstance(command, QStringList): for line in command: self.history.append(line) elif not command == "": if len(self.history) <= 0 or not command == self.history[-1]: self.history.append(command) self.historyIndex = len(self.history) def writeHistoryFile(self): wH = open(_historyFile, "w") for s in self.history: wH.write(s + "\n") wH.close() def readHistoryFile(self): fileExist = QFile.exists(_historyFile) if fileExist: rH = open(_historyFile, "r") for line in rH: if line != "\n": l = line.rstrip("\n") self.updateHistory(l) else: return def clearHistoryFile(self): cH = open(_historyFile, "w") cH.close() def showPrevious(self): if self.historyIndex < len(self.history) and not self.history.isEmpty(): line, pos = self.getCursorPosition() selCmdLenght = self.text(line).length() self.setSelection(line, 4, line, selCmdLenght) self.removeSelectedText() self.historyIndex += 1 if self.historyIndex == len(self.history): self.insert("") pass else: self.insert(self.history[self.historyIndex]) self.move_cursor_to_end() # self.SendScintilla(QsciScintilla.SCI_DELETEBACK) def showNext(self): if self.historyIndex > 0 and not self.history.isEmpty(): line, pos = self.getCursorPosition() selCmdLenght = self.text(line).length() self.setSelection(line, 4, line, selCmdLenght) self.removeSelectedText() self.historyIndex -= 1 if self.historyIndex == len(self.history): self.insert("") else: self.insert(self.history[self.historyIndex]) self.move_cursor_to_end() # self.SendScintilla(QsciScintilla.SCI_DELETEBACK) def keyPressEvent(self, e): startLine, _, endLine, _ = self.getSelection() # handle invalid cursor position and multiline selections if not self.is_cursor_on_edition_zone() or startLine < endLine: # allow to copy and select if e.modifiers() & (Qt.ControlModifier | Qt.MetaModifier): if e.key() in (Qt.Key_C, Qt.Key_A): QsciScintilla.keyPressEvent(self, e) return # allow selection if e.modifiers() & Qt.ShiftModifier: if e.key() in (Qt.Key_Left, Qt.Key_Right, Qt.Key_Home, Qt.Key_End): QsciScintilla.keyPressEvent(self, e) return # all other keystrokes get sent to the input line self.move_cursor_to_end() line, index = self.getCursorPosition() cmd = self.text(line) if e.key() in (Qt.Key_Return, Qt.Key_Enter) and not self.isListActive(): self.entered() elif e.key() in (Qt.Key_Left, Qt.Key_Home): QsciScintilla.keyPressEvent(self, e) # check whether the cursor is moved out of the edition zone newline, newindex = self.getCursorPosition() if newline < line or newindex < 4: # fix selection and the cursor position if self.hasSelectedText(): self.setSelection(line, self.getSelection()[3], line, 4) else: self.setCursorPosition(line, 4) elif e.key() in (Qt.Key_Backspace, Qt.Key_Delete): QsciScintilla.keyPressEvent(self, e) # check whether the cursor is moved out of the edition zone _, newindex = self.getCursorPosition() if newindex < 4: # restore the prompt chars (if removed) and # fix the cursor position self.insert(cmd[: 3 - newindex] + " ") self.setCursorPosition(line, 4) self.recolor() elif e.modifiers() & (Qt.ControlModifier | Qt.MetaModifier) and e.key() == Qt.Key_V: self.paste() e.accept() elif e.key() == Qt.Key_Down and not self.isListActive(): self.showPrevious() elif e.key() == Qt.Key_Up and not self.isListActive(): self.showNext() ## TODO: press event for auto-completion file directory else: QsciScintilla.keyPressEvent(self, e) def contextMenuEvent(self, e): menu = QMenu(self) copyAction = menu.addAction("Copy", self.copy, QKeySequence.Copy) pasteAction = menu.addAction("Paste", self.paste, QKeySequence.Paste) copyAction.setEnabled(False) pasteAction.setEnabled(False) if self.hasSelectedText(): copyAction.setEnabled(True) if QApplication.clipboard().text() != "": pasteAction.setEnabled(True) action = menu.exec_(self.mapToGlobal(e.pos())) def mousePressEvent(self, e): """ Re-implemented to handle the mouse press event. e: the mouse press event (QMouseEvent) """ self.setFocus() if e.button() == Qt.MidButton: stringSel = unicode(QApplication.clipboard().text(QClipboard.Selection)) if not self.is_cursor_on_last_line(): self.move_cursor_to_end() self.insertFromDropPaste(stringSel) e.accept() else: QsciScintilla.mousePressEvent(self, e) def paste(self): """ Method to display data from the clipboard. XXX: It should reimplement the virtual QScintilla.paste method, but it seems not used by QScintilla code. """ stringPaste = unicode(QApplication.clipboard().text()) if self.is_cursor_on_last_line(): if self.hasSelectedText(): self.removeSelectedText() else: self.move_cursor_to_end() self.insertFromDropPaste(stringPaste) ## Drag and drop def dropEvent(self, e): if e.mimeData().hasText(): stringDrag = e.mimeData().text() self.insertFromDropPaste(stringDrag) self.setFocus() e.setDropAction(Qt.CopyAction) e.accept() else: QsciScintillaCompat.dropEvent(self, e) def insertFromDropPaste(self, textDP): pasteList = str(textDP).splitlines() for line in pasteList[:-1]: line.replace(">>> ", "").replace("... ", "") self.insert(unicode(line)) self.move_cursor_to_end() self.runCommand(unicode(self.currentCommand())) if pasteList[-1] != "": line = pasteList[-1] line.replace(">>> ", "").replace("... ", "") self.insert(unicode(line)) self.move_cursor_to_end() def insertTextFromFile(self, listOpenFile): for line in listOpenFile[:-1]: self.append(line) self.move_cursor_to_end() self.SendScintilla(QsciScintilla.SCI_DELETEBACK) self.runCommand(unicode(self.currentCommand())) self.append(unicode(listOpenFile[-1])) self.move_cursor_to_end() self.SendScintilla(QsciScintilla.SCI_DELETEBACK) def entered(self): self.move_cursor_to_end() self.runCommand(unicode(self.currentCommand())) self.setFocus() self.move_cursor_to_end() # self.SendScintilla(QsciScintilla.SCI_EMPTYUNDOBUFFER) def currentCommand(self): linenr, index = self.getCursorPosition() # for i in range(0, linenr): txtLength = self.text(linenr).length() string = self.text() cmdLine = string.right(txtLength - 4) cmd = unicode(cmdLine) return cmd def runCommand(self, cmd): self.writeCMD(cmd) import webbrowser self.updateHistory(cmd) line, pos = self.getCursorPosition() selCmdLenght = self.text(line).length() self.setSelection(line, 0, line, selCmdLenght) self.removeSelectedText() if cmd in ("_save", "_clear", "_clearAll", "_pyqgis", "_api"): if cmd == "_save": self.writeHistoryFile() msgText = QCoreApplication.translate("PythonConsole", "History saved successfully.") elif cmd == "_clear": self.clearHistoryFile() msgText = QCoreApplication.translate("PythonConsole", "History cleared successfully.") elif cmd == "_clearAll": self.history = QStringList() self.clearHistoryFile() msgText = QCoreApplication.translate("PythonConsole", "Session and file history cleared successfully.") elif cmd == "_pyqgis": webbrowser.open("http://www.qgis.org/pyqgis-cookbook/") elif cmd == "_api": webbrowser.open("http://www.qgis.org/api/") if msgText: self.parent.callWidgetMessageBar(msgText) self.displayPrompt(False) else: self.buffer.append(cmd) src = u"\n".join(self.buffer) more = self.runsource(src, "<input>") if not more: self.buffer = [] ## prevents to commands with more lines to break the console ## in the case they have a eol different from '\n' self.setText("") self.move_cursor_to_end() self.displayPrompt(more) def write(self, txt): sys.stderr.write(txt) def writeCMD(self, txt): if len(txt) > 0: getCmdString = self.text() prompt = getCmdString[0:4] sys.stdout.write(prompt + txt + "\n")
class PythonEdit(QsciScintilla, code.InteractiveInterpreter): def __init__(self, parent=None): #QsciScintilla.__init__(self, parent) super(PythonEdit,self).__init__(parent) code.InteractiveInterpreter.__init__(self, locals=None) # Enable non-ascii chars for editor self.setUtf8(True) self.new_input_line = True self.setMarginWidth(0, 0) self.setMarginWidth(1, 0) self.setMarginWidth(2, 0) self.buffer = [] self.insertInitText() self.displayPrompt(False) for line in _init_commands: self.runsource(line) self.history = QStringList() self.historyIndex = 0 # Read history command file self.readHistoryFile() # Brace matching: enable for a brace immediately before or after # the current position self.setBraceMatching(QsciScintilla.SloppyBraceMatch) #self.moveToMatchingBrace() #self.selectToMatchingBrace() # Current line visible with special background color self.setCaretLineVisible(True) self.setCaretLineBackgroundColor(QColor("#ffe4e4")) self.setCaretWidth(2) # Set Python lexer # Set style for Python comments (style number 1) to a fixed-width # courier. self.setLexers() # Indentation #self.setAutoIndent(True) #self.setIndentationsUseTabs(False) #self.setIndentationWidth(4) #self.setTabIndents(True) #self.setBackspaceUnindents(True) #self.setTabWidth(4) self.setAutoCompletionThreshold(2) self.setAutoCompletionSource(self.AcsAPIs) # Don't want to see the horizontal scrollbar at all # Use raw message to Scintilla here (all messages are documented # here: http://www.scintilla.org/ScintillaDoc.html) self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) # not too small #self.setMinimumSize(500, 300) self.setMinimumHeight(125) self.SendScintilla(QsciScintilla.SCI_SETWRAPMODE, 1) self.SendScintilla(QsciScintilla.SCI_EMPTYUNDOBUFFER) ## 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.newShortcutCAS = QShortcut(QKeySequence(Qt.CTRL + Qt.ALT + Qt.Key_Space), self) self.newShortcutCS.activated.connect(self.autoComplete) self.newShortcutCAS.activated.connect(self.showHistory) self.connect(self, SIGNAL('userListActivated(int, const QString)'), self.completion_list_selected) def showHistory(self): self.showUserList(1, QStringList(self.history)) def autoComplete(self): self.autoCompleteFromAll() def clearConsole(self): """Clear the contents of the console.""" self.SendScintilla(QsciScintilla.SCI_CLEARALL) #self.setText('') self.insertInitText() self.displayPrompt(False) self.setFocus() def commandConsole(self, command): if not self.is_cursor_on_last_line(): self.move_cursor_to_end() line, pos = self.getCursorPosition() selCmdLenght = self.text(line).length() self.setSelection(line, 4, line, selCmdLenght) self.removeSelectedText() if command == "iface": """Import QgisInterface class""" self.append('from qgis.utils import iface') self.move_cursor_to_end() elif command == "sextante": """Import Sextante class""" self.append('from sextante.core.Sextante import Sextante') self.move_cursor_to_end() elif command == "cLayer": """Retrieve current Layer from map camvas""" self.append('cLayer = iface.mapCanvas().currentLayer()') self.move_cursor_to_end() elif command == "qtCore": """Import QtCore class""" self.append('from PyQt4.QtCore import *') self.move_cursor_to_end() elif command == "qtGui": """Import QtGui class""" self.append('from PyQt4.QtGui import *') self.move_cursor_to_end() self.setFocus() def setLexers(self): from qgis.core import QgsApplication self.lexer = QsciLexerPython() settings = QSettings() loadFont = settings.value("pythonConsole/fontfamilytext", "Monospace").toString() fontSize = settings.value("pythonConsole/fontsize", 10).toInt()[0] font = QFont(loadFont) font.setFixedPitch(True) font.setPointSize(fontSize) 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 = settings.value( "pythonConsole/preloadAPI" ).toBool() if chekBoxAPI: self.api.loadPrepared( QgsApplication.pkgDataPath() + "/python/qsci_apis/pyqgis_master.pap" ) else: apiPath = 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) ## TODO: show completion list for file and directory def completion_list_selected(self, id, txt): if id == 1: txt = unicode(txt) # get current cursor position line, pos = self.getCursorPosition() selCmdLength = self.text(line).length() # select typed text self.setSelection(line, 4, line, selCmdLength) self.removeSelectedText() self.insert(txt) def insertInitText(self): #self.setLexers(False) txtInit = QCoreApplication.translate("PythonConsole", "## To access Quantum GIS environment from this console\n" "## use qgis.utils.iface object (instance of QgisInterface class). Read help for more info.\n\n") initText = self.setText(txtInit) def getText(self): """ Get the text as a unicode string. """ value = self.getBytes().decode('utf-8') # print (value) printing can give an error because the console font # may not have all unicode characters return value def getBytes(self): """ Get the text as bytes (utf-8 encoded). This is how the data is stored internally. """ len = self.SendScintilla(self.SCI_GETLENGTH)+1 bb = QByteArray(len,'0') N = self.SendScintilla(self.SCI_GETTEXT, len, bb) return bytes(bb)[:-1] def getTextLength(self): return self.SendScintilla(QsciScintilla.SCI_GETLENGTH) def get_end_pos(self): """Return (line, index) position of the last character""" line = self.lines() - 1 return (line, self.text(line).length()) def is_cursor_at_end(self): """Return True if cursor is at the end of text""" cline, cindex = self.getCursorPosition() return (cline, cindex) == self.get_end_pos() 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 on_new_line(self): # """On new input line""" # self.move_cursor_to_end() # self.new_input_line = False def is_cursor_on_last_line(self): """Return True if cursor is on the last line""" cline, _ = self.getCursorPosition() return cline == self.lines() - 1 def is_cursor_on_edition_zone(self): """ Return True if the cursor is in the edition zone """ cline, cindex = self.getCursorPosition() return cline == self.lines() - 1 and cindex >= 4 def new_prompt(self, prompt): """ Print a new prompt and save its (line, index) position """ self.write(prompt, prompt=True) # now we update our cursor giving end of prompt line, index = self.getCursorPosition() self.ensureCursorVisible() self.ensureLineVisible(line) def refreshLexerProperties(self): self.setLexers() # def check_selection(self): # """ # Check if selected text is r/w, # otherwise remove read-only parts of selection # """ # #if self.current_prompt_pos is None: # #self.move_cursor_to_end() # #return # line_from, index_from, line_to, index_to = self.getSelection() # pline, pindex = self.getCursorPosition() # if line_from < pline or \ # (line_from == pline and index_from < pindex): # self.setSelection(pline, pindex, line_to, index_to) def displayPrompt(self, more=False): self.append("... ") if more else self.append(">>> ") self.move_cursor_to_end() def updateHistory(self, command): if isinstance(command, QStringList): for line in command: self.history.append(line) elif not command == "": if len(self.history) <= 0 or \ not command == self.history[-1]: self.history.append(command) self.historyIndex = len(self.history) def writeHistoryFile(self): wH = open(_historyFile, 'w') for s in self.history: wH.write(s + '\n') wH.close() def readHistoryFile(self): fileExist = QFile.exists(_historyFile) if fileExist: rH = open(_historyFile, 'r') for line in rH: if line != "\n": l = line.rstrip('\n') self.updateHistory(l) else: return def clearHistoryFile(self): cH = open(_historyFile, 'w') cH.close() def showPrevious(self): if self.historyIndex < len(self.history) and not self.history.isEmpty(): line, pos = self.getCursorPosition() selCmdLenght = self.text(line).length() self.setSelection(line, 4, line, selCmdLenght) self.removeSelectedText() self.historyIndex += 1 if self.historyIndex == len(self.history): self.insert("") pass else: self.insert(self.history[self.historyIndex]) self.move_cursor_to_end() #self.SendScintilla(QsciScintilla.SCI_DELETEBACK) def showNext(self): if self.historyIndex > 0 and not self.history.isEmpty(): line, pos = self.getCursorPosition() selCmdLenght = self.text(line).length() self.setSelection(line, 4, line, selCmdLenght) self.removeSelectedText() self.historyIndex -= 1 if self.historyIndex == len(self.history): self.insert("") else: self.insert(self.history[self.historyIndex]) self.move_cursor_to_end() #self.SendScintilla(QsciScintilla.SCI_DELETEBACK) def keyPressEvent(self, e): startLine, _, endLine, _ = self.getSelection() # handle invalid cursor position and multiline selections if not self.is_cursor_on_edition_zone() or startLine < endLine: # allow to copy and select if e.modifiers() & (Qt.ControlModifier | Qt.MetaModifier): if e.key() in (Qt.Key_C, Qt.Key_A): QsciScintilla.keyPressEvent(self, e) return # allow selection if e.modifiers() & Qt.ShiftModifier: if e.key() in (Qt.Key_Left, Qt.Key_Right, Qt.Key_Home, Qt.Key_End): QsciScintilla.keyPressEvent(self, e) return # all other keystrokes get sent to the input line self.move_cursor_to_end() line, index = self.getCursorPosition() cmd = self.text(line) if e.key() in (Qt.Key_Return, Qt.Key_Enter) and not self.isListActive(): self.entered() elif e.key() in (Qt.Key_Left, Qt.Key_Home): QsciScintilla.keyPressEvent(self, e) # check whether the cursor is moved out of the edition zone newline, newindex = self.getCursorPosition() if newline < line or newindex < 4: # fix selection and the cursor position if self.hasSelectedText(): self.setSelection(line, self.getSelection()[3], line, 4) else: self.setCursorPosition(line, 4) elif e.key() in (Qt.Key_Backspace, Qt.Key_Delete): QsciScintilla.keyPressEvent(self, e) # check whether the cursor is moved out of the edition zone _, newindex = self.getCursorPosition() if newindex < 4: # restore the prompt chars (if removed) and # fix the cursor position self.insert( cmd[:3-newindex] + " " ) self.setCursorPosition(line, 4) elif e.modifiers() & (Qt.ControlModifier | Qt.MetaModifier) and \ e.key() == Qt.Key_V: self.paste() e.accept() elif e.key() == Qt.Key_Down and not self.isListActive(): self.showPrevious() elif e.key() == Qt.Key_Up and not self.isListActive(): self.showNext() ## TODO: press event for auto-completion file directory else: QsciScintilla.keyPressEvent(self, e) def mousePressEvent(self, e): """ Re-implemented to handle the mouse press event. e: the mouse press event (QMouseEvent) """ self.setFocus() if e.button() == Qt.MidButton: stringSel = unicode(QApplication.clipboard().text(QClipboard.Selection)) if not self.is_cursor_on_last_line(): self.move_cursor_to_end() self.insertFromDropPaste(stringSel) e.accept() else: QsciScintilla.mousePressEvent(self, e) def paste(self): """ Method to display data from the clipboard. XXX: It should reimplement the virtual QScintilla.paste method, but it seems not used by QScintilla code. """ stringPaste = unicode(QApplication.clipboard().text()) if self.is_cursor_on_last_line(): if self.hasSelectedText(): self.removeSelectedText() else: self.move_cursor_to_end() self.insertFromDropPaste(stringPaste) ## Drag and drop def dropEvent(self, e): if e.mimeData().hasText(): stringDrag = e.mimeData().text() self.insertFromDropPaste(stringDrag) self.setFocus() e.setDropAction(Qt.MoveAction) e.accept() else: QsciScintillaCompat.dropEvent(self, e) def insertFromDropPaste(self, textDP): pasteList = textDP.split("\n") for line in pasteList[:-1]: self.insert(line) self.move_cursor_to_end() #self.SendScintilla(QsciScintilla.SCI_DELETEBACK) self.runCommand(unicode(self.currentCommand())) if pasteList[-1] != "": self.insert(unicode(pasteList[-1])) self.move_cursor_to_end() def getTextFromEditor(self): text = self.text() textList = text.split("\n") return textList def insertTextFromFile(self, listOpenFile): for line in listOpenFile[:-1]: self.append(line) self.move_cursor_to_end() self.SendScintilla(QsciScintilla.SCI_DELETEBACK) self.runCommand(unicode(self.currentCommand())) self.append(unicode(listOpenFile[-1])) self.move_cursor_to_end() self.SendScintilla(QsciScintilla.SCI_DELETEBACK) def entered(self): self.move_cursor_to_end() self.runCommand( unicode(self.currentCommand()) ) self.setFocus() self.move_cursor_to_end() #self.SendScintilla(QsciScintilla.SCI_EMPTYUNDOBUFFER) def currentCommand(self): linenr, index = self.getCursorPosition() #for i in range(0, linenr): txtLength = self.text(linenr).length() string = self.text() cmdLine = string.right(txtLength - 4) cmd = unicode(cmdLine) return cmd def runCommand(self, cmd): import webbrowser self.updateHistory(cmd) self.SendScintilla(QsciScintilla.SCI_NEWLINE) if cmd in ('_save', '_clear', '_clearAll', '_pyqgis', '_api'): if cmd == '_save': self.writeHistoryFile() print QCoreApplication.translate("PythonConsole", "## History saved successfully ##") elif cmd == '_clear': self.clearHistoryFile() print QCoreApplication.translate("PythonConsole", "## History cleared successfully ##") elif cmd == '_clearAll': res = QMessageBox.question(self, "Python Console", QCoreApplication.translate("PythonConsole", "Are you sure you want to completely\n" "delete the command history ?"), QMessageBox.Yes | QMessageBox.No) if res == QMessageBox.No: self.SendScintilla(QsciScintilla.SCI_DELETEBACK) return self.history = QStringList() self.clearHistoryFile() print QCoreApplication.translate("PythonConsole", "## History cleared successfully ##") elif cmd == '_pyqgis': webbrowser.open( "http://www.qgis.org/pyqgis-cookbook/" ) elif cmd == '_api': webbrowser.open( "http://www.qgis.org/api/" ) output = sys.stdout.get_and_clean_data() if output: self.append(output) self.displayPrompt(False) else: self.buffer.append(cmd) src = u"\n".join(self.buffer) more = self.runsource(src, "<input>") if not more: self.buffer = [] output = sys.stdout.get_and_clean_data() if output: self.append(output) self.move_cursor_to_end() self.displayPrompt(more) def write(self, txt): self.SendScintilla(QsciScintilla.SCI_SETSTYLING, len(txt), 1) self.append(txt) self.SendScintilla(QsciScintilla.SCI_SETSTYLING, len(txt), 1)
class CommandShell(QsciScintilla): def __init__(self, parent=None): super(CommandShell, self).__init__(parent) self.setMinimumHeight(50) self.setMaximumHeight(50) self.settings = QSettings() self.lex = QsciLexerPython(self) self.apis = QsciAPIs(self.lex) self.lex.setAPIs(self.apis) self.setLexers() self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) self.SendScintilla(QsciScintilla.SCI_SETVSCROLLBAR, 0) self.setFolding(0) self._start_prompt = _start_prompt self.prompt = self._start_prompt self.currentfunction = None self.setAutoCompletionSource(self.AcsAPIs) self.setAutoCompletionThreshold(1) self.setAutoCompletionReplaceWord(True) self.setCallTipsStyle(QsciScintilla.CallTipsNoContext) self.parent().installEventFilter(self) self.textChanged.connect(self.text_changed) self._lastcompletions = None def text_changed(self): if not self.get_data().strip(): return try: completions = command.completions_for_line(self.get_data()) if completions == self._lastcompletions: self.autoCompleteFromAPIs() return self._lastcompletions = completions self.apis.cancelPreparation() self.apis.clear() for value in completions: data = u"{}".format(value) self.apis.add(data) self.apis.prepare() except command.NoFunction: return def end(self): self.parent().removeEventFilter(self) self.close() def eventFilter(self, object, event): if event.type() == QEvent.Resize: self.adjust_size() return QWidget.eventFilter(self, object, event) def keyPressEvent(self, e): if e.key() in (Qt.Key_Return, Qt.Key_Enter): self.entered() elif e.key() == Qt.Key_Escape: self.close() elif e.key() in (Qt.Key_Backspace, Qt.Key_Delete): _, newindex = self.getCursorPosition() if newindex > len(self.prompt): QsciScintilla.keyPressEvent(self, e) else: QsciScintilla.keyPressEvent(self, e) def show_prompt(self, prompt=_start_prompt, data=None): self.clear() if not prompt == _start_prompt: prompt += ":" text = prompt if data: text = prompt + str(data) self.setText(text) self.prompt = prompt self.move_cursor_to_end() def get_end_pos(self): """Return (line, index) position of the last character""" line = self.lines() - 1 return (line, len(self.text(line))) 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_data(self): line = self.text() line = line[len(self.prompt):] return line def entered(self): line = self.get_data() if not self.currentfunction: try: gen = command.parse_line_data(line) except command.NoFunction: return if gen: self.currentfunction = gen line = None else: self.currentfunction = None self.show_prompt() return try: prompt, data = self.currentfunction.send(line) self.show_prompt(prompt, data) except StopIteration: self.currentfunction = None self.show_prompt() def setLexers(self): loadFont = self.settings.value("pythonConsole/fontfamilytext", "Monospace") fontSize = self.settings.value("pythonConsole/fontsize", 10, type=int) 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.lex.setFont(font) self.lex.setDefaultFont(font) self.setLexer(self.lex) def adjust_size(self): fm = QFontMetrics(self.font()) self.setMaximumHeight(20) self.resize(self.parent().width(), 20) self.move(0, self.parent().height() - self.height()) def showEvent(self, event): self.adjust_size() self.show_prompt() self.setFocus() def activated(self): visible = self.isVisible() self.setVisible(not visible)
class ScintillaPythonEditBox(QsciScintilla, BasePythonEditBox): def __init__(self, parent=None): QsciScintilla.__init__(self, parent) self.lexer = None self.api = None self.lexerType = -1 self.setCommonOptions() self.initShortcuts() def setCommonOptions(self): # Enable non-ASCII characters self.setUtf8(True) # Default font # Load font from Python console settings settings = QSettings() fontName = settings.value('pythonConsole/fontfamilytext', 'Monospace') fontSize = int(settings.value('pythonConsole/fontsize', 10)) 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) self.setFont(self.defaultFont) self.setMarginsFont(self.defaultFont) self.initLexer() 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')) # 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.AcsAll) 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 setLexerType(self, lexerType): self.lexerType = lexerType self.initLexer() 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 = QSettings() 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) #impliment base editor def insertPlainText(self, text): self.insert(text) pos = self.getCursorPosition() self.setCursorPosition(pos[0], pos[1] + len(text)) def toPlainText(self): return self.text() def get_font_size(self): return self.font().pointSize() def set_font_size(self, new_point_size): font = self.font() self.setFont(QFont(font.family(), new_point_size)) def wheelEvent(self, event): if event.modifiers() == Qt.ControlModifier: self.emit(SIGNAL("wheelEvent(QWheelEvent)"), event) else: super(ScintillaPythonEditBox, self).wheelEvent(event)
class ScintillaPythonEditBox(QsciScintilla, BasePythonEditBox): def __init__(self, parent=None): QsciScintilla.__init__(self, parent) self.lexer = None self.api = None self.lexerType = -1 self.setCommonOptions() self.initShortcuts() def setCommonOptions(self): # Enable non-ASCII characters self.setUtf8(True) # Default font # Load font from Python console settings settings = QSettings() fontName = settings.value('pythonConsole/fontfamilytext', 'Monospace') fontSize = int(settings.value('pythonConsole/fontsize', 10)) 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) self.setFont(self.defaultFont) self.setMarginsFont(self.defaultFont) self.initLexer() 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')) # 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.AcsAll) 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 setLexerType(self, lexerType): self.lexerType = lexerType self.initLexer() 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 = QSettings() 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) #impliment base editor def insertPlainText(self, text): self.insert(text) pos = self.getCursorPosition() self.setCursorPosition(pos[0], pos[1]+len(text)) def toPlainText(self): return self.text() def get_font_size(self): return self.font().pointSize() def set_font_size(self, new_point_size): font = self.font() self.setFont(QFont(font.family(), new_point_size)) def wheelEvent(self, event): if event.modifiers() == Qt.ControlModifier: self.emit(SIGNAL("wheelEvent(QWheelEvent)"), event) else: super(ScintillaPythonEditBox, self).wheelEvent(event)
class CommandShell(QsciScintilla): def __init__(self, parent=None): super(CommandShell, self).__init__(parent) self.setMinimumHeight(50) self.setMaximumHeight(50) self.settings = QSettings() self.lex = QsciLexerPython(self) self.apis = QsciAPIs(self.lex) self.lex.setAPIs(self.apis) self.setLexers() self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0) self.SendScintilla(QsciScintilla.SCI_SETVSCROLLBAR, 0) self.setFolding(0) self._start_prompt = _start_prompt self.prompt = self._start_prompt self.currentfunction = None self.setAutoCompletionSource(self.AcsAPIs) self.setAutoCompletionThreshold(1) self.setAutoCompletionReplaceWord(True) self.setCallTipsStyle(QsciScintilla.CallTipsNoContext) self.parent().installEventFilter(self) self.textChanged.connect(self.text_changed) self._lastcompletions = None self.autocompletemodel = QStandardItemModel() self.autocompletefilter = QSortFilterProxyModel() self.autocompletefilter.setSourceModel(self.autocompletemodel) self.autocompleteview = QListView(self.parent()) self.autocompleteview.setModel(self.autocompletefilter) self.autocompleteview.hide() self.selectionmodel = self.autocompleteview.selectionModel() def adjust_auto_complete(self): self.autocompleteview.resize(self.parent().width(), 100) self.autocompleteview.move(0, self.parent().height() - self.height() - self.autocompleteview.height()) def add_completions(self, completions): self.autocompletemodel.clear() for value in completions: data = u"{}".format(unicode(value)) self.autocompletemodel.appendRow(QStandardItem(data)) self._lastcompletions = completions def text_changed(self): completions, userdata = command.completions_for_line(self.get_data()) if not completions == self._lastcompletions: self.add_completions(completions) fuzzy = "".join(["{}.*".format(c) for c in userdata]) self.autocompletefilter.setFilterRegExp(fuzzy) index = self.autocompletefilter.index(0, 0) if index.isValid(): self.selectionmodel.select(index, QItemSelectionModel.Select) hasdata = self.autocompletemodel.rowCount() > 0 self.adjust_auto_complete() self.autocompleteview.setVisible(hasdata) def end(self): self.parent().removeEventFilter(self) self.close() def eventFilter(self, object, event): if event.type() == QEvent.Resize: self.adjust_size() return QWidget.eventFilter(self, object, event) def keyPressEvent(self, e): if e.key() in (Qt.Key_Return, Qt.Key_Enter): self.entered() elif e.key() == Qt.Key_Escape: self.close() elif e.key() == Qt.Key_Tab: self.complete() elif e.key() in (Qt.Key_Backspace, Qt.Key_Delete): _, newindex = self.getCursorPosition() if newindex > len(self.prompt): QsciScintilla.keyPressEvent(self, e) else: QsciScintilla.keyPressEvent(self, e) def complete(self): try: index = self.autocompleteview.selectedIndexes()[0] except IndexError: return if index.isValid(): text = self.autocompletefilter.data(index) # Wrap text with space in quotes if ' ' in text: text = "'{}'".format(text) line = self.get_data() space = line.rfind(' ') newline = line[:space + 1] + text + " " self.show_prompt(self.prompt, newline) def close(self): self.currentfunction = None self.autocompleteview.close() super(CommandShell, self).close() def show_prompt(self, prompt=_start_prompt, data=None): self.clear() if not prompt == _start_prompt: prompt += ":" text = prompt if data: text = prompt + str(data) self.setText(text) self.prompt = prompt self.move_cursor_to_end() def get_end_pos(self): """Return (line, index) position of the last character""" line = self.lines() - 1 return (line, len(self.text(line))) 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_data(self): line = self.text() line = line[len(self.prompt):] return line def entered(self): print self.currentfunction line = self.get_data() if not line: return if not self.currentfunction: try: gen = command.parse_line_data(line) except command.NoFunction: return if gen: self.currentfunction = gen line = None else: self.currentfunction = None self.show_prompt() return try: print "Sednign something to the function" prompt, data = self.currentfunction.send(line) self.show_prompt(prompt, data) except StopIteration: self.currentfunction = None self.show_prompt() except command.NoFunction: self.currentfunction = None def setLexers(self): loadFont = self.settings.value("pythonConsole/fontfamilytext", "Monospace") fontSize = self.settings.value("pythonConsole/fontsize", 10, type=int) 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.lex.setFont(font) self.lex.setDefaultFont(font) self.setLexer(self.lex) def adjust_size(self): fm = QFontMetrics(self.font()) self.setMaximumHeight(20) self.resize(self.parent().width(), 20) self.move(0, self.parent().height() - self.height()) self.adjust_auto_complete() def showEvent(self, event): self.adjust_size() self.show_prompt() self.setFocus() self.autocompleteview.show() def activated(self): visible = self.isVisible() self.setVisible(not visible)