Skip to content

Commit

Permalink
[FEATURE] - Split-pane entry and output for PyQGIS console
Browse files Browse the repository at this point in the history
  • Loading branch information
slarosa committed Oct 26, 2012
1 parent 1fdaa04 commit f15b4e1
Show file tree
Hide file tree
Showing 4 changed files with 227 additions and 47 deletions.
1 change: 1 addition & 0 deletions python/CMakeLists.txt
Expand Up @@ -147,6 +147,7 @@ SET(PY_FILES
console_sci.py
console_help.py
console_settings.py
console_output.py
utils.py
)
FILE(GLOB UI_FILES *.ui)
Expand Down
74 changes: 48 additions & 26 deletions python/console.py
Expand Up @@ -23,6 +23,7 @@
from PyQt4.QtGui import *
from qgis.utils import iface
from console_sci import PythonEdit
from console_output import EditorOutput
from console_help import HelpDialog
from console_settings import optionsDialog

Expand Down Expand Up @@ -58,20 +59,6 @@ def console_displayhook(obj):
global _console_output
_console_output = obj

class QgisOutputCatcher:
def __init__(self):
self.data = ''
def write(self, stuff):
self.data += stuff
def get_and_clean_data(self):
tmp = self.data
self.data = ''
return tmp
def flush(self):
pass

sys.stdout = QgisOutputCatcher()

class PythonConsole(QDockWidget):
def __init__(self, parent=None):
QDockWidget.__init__(self, parent)
Expand All @@ -96,11 +83,19 @@ def activate(self):
class PythonConsoleWidget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setWindowTitle(QCoreApplication.translate("PythonConsole", "Python Console"))

self.setWindowTitle(QCoreApplication.translate("PythonConsole", "Python Console"))
self.widgetButton = QWidget()
#self.widgetEditors = QWidget()

self.options = optionsDialog(self)

self.splitter = QSplitter(self)
self.splitter.setOrientation(Qt.Vertical)
self.splitter.setHandleWidth(3)
self.splitter.setChildrenCollapsible(False)

#self.textEdit = QTextEdit()

self.toolBar = QToolBar()
self.toolBar.setEnabled(True)
#self.toolBar.setFont(font)
Expand All @@ -115,12 +110,18 @@ def __init__(self, parent=None):
#self.toolBar.setAllowedAreas(Qt.RightToolBarArea)
#self.toolBar.setObjectName(_fromUtf8("toolMappa"))

self.b = QVBoxLayout(self.widgetButton)
self.e = QHBoxLayout(self)
#self.gridLayout = QGridLayout(self)

self.b = QGridLayout(self.widgetButton)
#self.e = QGridLayout(self.widgetEditors)
self.f = QGridLayout(self)

self.e.setMargin(0)
self.e.setSpacing(0)
#self.e.setMargin(0)
#self.e.setSpacing(0)
self.f.setMargin(0)
self.f.setSpacing(0)
self.b.setMargin(0)
self.b.setSpacing(0)

## Action for Clear button
clearBt = QCoreApplication.translate("PythonConsole", "Clear console")
Expand Down Expand Up @@ -268,12 +269,32 @@ def __init__(self, parent=None):

self.b.addWidget(self.toolBar)
self.edit = PythonEdit()
self.setFocusProxy( self.edit )
self.textEditOut = EditorOutput()

self.e.addWidget(self.widgetButton)
self.e.addWidget(self.edit)
#self.textEdit = PythonEditOutput()
#self.textEdit.setReadOnly(True)
#self.textEdit.setMinimumHeight(80)

self.clearButton.triggered.connect(self.edit.clearConsole)
self.setFocusProxy(self.edit)

sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.widgetButton.sizePolicy().hasHeightForWidth())
self.widgetButton.setSizePolicy(sizePolicy)
#self.e.addWidget(self.textEdit)
#self.e.addWidget(self.edit)

self.splitter.addWidget(self.textEditOut)
self.splitter.addWidget(self.edit)
self.f.addWidget(self.widgetButton, 0, 0, 1, 1)
self.f.addWidget(self.splitter, 0, 1, 1, 1)
#self.f.addWidget(self.widgetEditors)

#self.f.setStretchFactor(self.widgetEditors, 1)


self.clearButton.triggered.connect(self.textEditOut.clearConsole)
self.optionsButton.triggered.connect(self.openSettings)
self.loadIfaceButton.triggered.connect(self.iface)
self.loadSextanteButton.triggered.connect(self.sextante)
Expand Down Expand Up @@ -326,7 +347,7 @@ def saveScriptFile(self):
if not filename.endswith(".py"):
fName += ".py"
sF = open(fName,'w')
listText = self.edit.getTextFromEditor()
listText = self.textEditOut.getTextFromEditor()
is_first_line = True
for s in listText:
if s[0:3] in (">>>", "..."):
Expand All @@ -337,7 +358,7 @@ def saveScriptFile(self):
sF.write('\n')
sF.write(s)
sF.close()

def openHelp(self):
dlg = HelpDialog()
dlg.exec_()
Expand All @@ -348,6 +369,7 @@ def openSettings(self):

def prefChanged(self):
self.edit.refreshLexerProperties()
self.textEditOut.refreshLexerProperties()

def closeEvent(self, event):
self.edit.writeHistoryFile()
Expand Down
137 changes: 137 additions & 0 deletions python/console_output.py
@@ -0,0 +1,137 @@
# -*- coding:utf-8 -*-
"""
/***************************************************************************
Python Conosle for QGIS
-------------------
begin : 2012-09-10
copyright : (C) 2012 by Salvatore Larosa
email : lrssvtml (at) gmail (dot) com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
Some portions of code were taken from https://code.google.com/p/pydee/
"""

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.Qsci import (QsciScintilla,
QsciScintillaBase,
QsciLexerPython)

import sys

class writeOut:
def __init__(self, edit, out=None, style=None):
"""
This class allow to write stdout and stderr
"""
self.editor = edit
self.out = None
self.style = style

def write(self, m):
if self.style == "traceback":
self.editor.SendScintilla(QsciScintilla.SCI_SETSTYLING, len(m), 1)
self.editor.append(m)
self.editor.SendScintilla(QsciScintilla.SCI_SETSTYLING, len(m), 1)
else:
self.editor.append(m)
self.move_cursor_to_end()

if self.out:
self.out.write(m)

def move_cursor_to_end(self):
"""Move cursor to end of text"""
line, index = self.get_end_pos()
self.editor.setCursorPosition(line, index)
self.editor.ensureCursorVisible()
self.editor.ensureLineVisible(line)

def get_end_pos(self):
"""Return (line, index) position of the last character"""
line = self.editor.lines() - 1
return (line, self.editor.text(line).length())

def flush(self):
pass

class EditorOutput(QsciScintilla):
def __init__(self, parent=None):
#QsciScintilla.__init__(self, parent)
super(EditorOutput,self).__init__(parent)
# Enable non-ascii chars for editor
self.setUtf8(True)

sys.stdout = writeOut(self, sys.stdout)
sys.stderr = writeOut(self, sys.stderr, "traceback")

self.setLexers()
self.setReadOnly(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)
self.setMarginsFont(font)
self.setMarginWidth(1, "000")
self.setMarginLineNumbers(1, True)
self.setMarginsBackgroundColor(QColor("#ffe4e4"))

# Folding
#self.setFolding(QsciScintilla.BoxedTreeFoldStyle)
#self.setFoldMarginColors(QColor("#99CC66"),QColor("#333300"))
#self.setWrapMode(QsciScintilla.WrapCharacter)

## Edge Mode : does not seems to work
#self.setEdgeMode(QsciScintilla.EdgeLine)
#self.setEdgeColumn(80)
#self.setEdgeColor(QColor("#FF0000"))

self.SendScintilla(QsciScintilla.SCI_SETWRAPMODE, 2)
self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0)

def refreshLexerProperties(self):
self.setLexers()

def setLexers(self):
self.lexer = QsciLexerPython()

settings = QSettings()
loadFont = settings.value("pythonConsole/fontfamilytext").toString()
fontSize = settings.value("pythonConsole/fontsize").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, 2)
self.lexer.setFont(font, 3)
self.lexer.setFont(font, 4)

self.setLexer(self.lexer)

def getTextFromEditor(self):
text = self.text()
textList = text.split("\n")
return textList

def clearConsole(self):
#self.SendScintilla(QsciScintilla.SCI_CLEARALL)
self.setText('')

0 comments on commit f15b4e1

Please sign in to comment.