summaryrefslogtreecommitdiff
path: root/portato/gui/qt/terminal.py
diff options
context:
space:
mode:
Diffstat (limited to 'portato/gui/qt/terminal.py')
-rw-r--r--portato/gui/qt/terminal.py193
1 files changed, 193 insertions, 0 deletions
diff --git a/portato/gui/qt/terminal.py b/portato/gui/qt/terminal.py
new file mode 100644
index 0000000..9fbc39c
--- /dev/null
+++ b/portato/gui/qt/terminal.py
@@ -0,0 +1,193 @@
+# -*- coding: utf-8 -*-
+#
+# File: portato/gui/qt/terminal.py
+# This file is part of the Portato-Project, a graphical portage-frontend.
+#
+# Copyright (C) 2007 René 'Necoro' Neumann
+# This is free software. You may redistribute copies of it under the terms of
+# the GNU General Public License version 2.
+# There is NO WARRANTY, to the extent permitted by law.
+#
+# Written by René 'Necoro' Neumann <necoro@necoro.net>
+
+from PyQt4 import QtGui, QtCore
+
+from threading import Thread, Lock
+from os import read
+
+from portato.gui.wrapper import Console
+from portato.helper import debug
+
+class BoldFormat (QtGui.QTextCharFormat):
+
+ def __init__(self):
+ QtGui.QTextCharFormat.__init__(self)
+ self.setFontWeight(QtGui.QFont.Bold)
+
+class UnderlineFormat (QtGui.QTextCharFormat):
+
+ def __init__(self):
+ QtGui.QTextCharFormat.__init__(self)
+ self.setFontUnderline(True)
+
+class ColorFormat (QtGui.QTextCharFormat):
+
+ def __init__(self, color):
+ QtGui.QTextCharFormat.__init__(self)
+
+ self.setForeground(QtGui.QBrush(QtGui.QColor(color)))
+
+# we only support a subset of the commands
+esc_seq = ("\x1b", "[")
+reset_seq = "39;49;00"
+seq_end = "m"
+seq_sep = ";"
+backspace = 8
+title_seq = ("\x1b", "]")
+title_end = "\x07"
+
+attr = {}
+attr[0] = None # normal
+attr[1] = BoldFormat() # bold
+attr[4] = UnderlineFormat() # underline
+attr[30] = ColorFormat("black")
+attr[31] = ColorFormat("red")
+attr[32] = ColorFormat("green")
+attr[33] = ColorFormat("yellow")
+attr[34] = ColorFormat("blue")
+attr[35] = ColorFormat("magenta")
+attr[36] = ColorFormat("cyan")
+attr[37] = ColorFormat("white")
+attr[39] = None # default
+
+class QtConsole (Console, QtGui.QTextEdit):
+
+ def __init__ (self, parent):
+ QtGui.QTextEdit.__init__(self, parent)
+
+ self.pty = None
+ self.running = False
+ self.stdFormat = self.currentCharFormat()
+ self.formatQueue = []
+ self.formatLock = Lock()
+ self.title = None
+
+ self.setReadOnly(True)
+
+ QtCore.QObject.connect(self, QtCore.SIGNAL("doSomeWriting"), self._write)
+ QtCore.QObject.connect(self, QtCore.SIGNAL("deletePrevChar()"), self._deletePrev)
+
+ def _deletePrev (self):
+ self.textCursor().deletePreviousChar()
+
+ def _write (self, text):
+ if text == esc_seq[0]:
+ self.setCurrentCharFormat(self.get_format())
+ else:
+
+ if not self.textCursor().atEnd(): # move cursor and re-set format
+ f = self.currentCharFormat()
+ self.moveCursor(QtGui.QTextCursor.End)
+ self.setCurrentCharFormat(f)
+
+ # insert the text
+ self.textCursor().insertText(text)
+
+ # scroll down if needed
+ self.ensureCursorVisible()
+
+ def write(self, text):
+ self.emit(QtCore.SIGNAL("doSomeWriting"), text)
+
+ def set_pty (self, pty):
+ if not self.running:
+ self.pty = pty
+
+ t = Thread(target=self.__run)
+ t.setDaemon(True) # close application even if this thread is running
+ t.start()
+
+ self.running = True
+ else:
+ self.clear()
+ self.pty = pty # set this after clearing to lose no chars :)
+
+ def __run (self):
+ while True:
+ s = read(self.pty, 1)
+ if s == "": break
+
+ if ord(s) == backspace:
+ self.emit(QtCore.SIGNAL("deletePrevChar()"))
+ continue
+
+ if s == esc_seq[0]: # -> 0x27
+ s = read(self.pty, 1)
+ if s == esc_seq[1]: # -> [
+ while True:
+ _s = read(self.pty, 1)
+ s += _s
+ if _s == seq_end: break
+ self.parse_seq(s[1:-1])
+ continue
+
+ elif s == title_seq[1]: # -> ]
+ while True:
+ _s = read(self.pty, 1)
+ s += _s
+ if _s == title_end: break
+
+ self.parse_title(s[1:-1])
+ continue
+ else:
+ self.write(esc_seq[0]+s)
+
+ if s == "\r": continue
+ self.write(s)
+
+ def parse_seq (self, seq):
+ global attr
+
+ format = self.virgin_format()
+
+ if seq != reset_seq: # resettet -> done
+ seq = seq.split(seq_sep)
+ for s in seq:
+ try:
+ s = int(s)
+ except ValueError:
+ format = self.virgin_format()
+ break
+
+ if attr[s] is not None:
+ format.merge(attr[s])
+ else:
+ format = self.virgin_format()
+ break
+
+ self.add_format(format)
+ self.write(esc_seq[0])
+
+ def parse_title (self, seq):
+
+ if not seq.startswith("0;"):
+ return
+
+ self.title = seq[2:]
+
+ def get_window_title (self):
+ return self.title
+
+ def add_format (self, format):
+ self.formatLock.acquire()
+ self.formatQueue.append(format)
+ self.formatLock.release()
+
+ def get_format (self):
+ self.formatLock.acquire()
+ f = self.formatQueue.pop(0)
+ self.formatLock.release()
+ return f
+
+ def virgin_format (self):
+ return QtGui.QTextCharFormat(self.stdFormat)