title: Duplicate stdout, stderr in QTextEdit widget
body: <p>I've been having difficulty with my PySide program for a few days now. I don't think the problem is incredibly difficult because there are answer out there. Problem I have is none of them seem to work for me. </p>
  
  <p>I want to 'listen' to the file objects stdout and stderr and output the contents to QText Edit widget while my PySide program is running. Now, I already realise this question (or something similar) has been asked before on here but like I said, can't get it to work for me for some reason and most other solutions out there are based on the one that I can't get working, so a very frustrating last few days for me. This solution (OutLog), is included in my code snippet below, just in case one of you guys can see a botched implementation on my part. </p>
  
  <p>Things to remember: </p>
  
  <p>1 I'm doing this on Windows 7(duuuh, da, da, duh)</p>
  
  <p>2 I'm using eclipse and running it from inside the IDE(duh, da, da, duh, DUUUUH: It would be really handy if the suggestions worked with either commandline or an IDE)</p>
  
  <p>3 I really just want to duplicate the output of stdout and stderr to the widget while the program runs. For this to happen line-by-line would be a dream but even if it all comes out as a chunk at the end of a loop or something, that would be fab. </p>
  
  <p>4 Oh, and also regarding OutLog, could somebody tell me how, if self.out is set to 'None' in the <strong>init</strong>, this class can actually work? I mean, self.out is <strong>always</strong> a NoneType object, right???</p>
  
  <p>Any help would be appreciated, even if it's just pointers to where I could find more information. I've been trying to build my own solution (I'm a bit of a sadist that way) but I've found it hard to find relevant info on how these objects work to do that. </p>
  
  <p>Anyway, whine over. Here's my code:</p>
  
  <pre><code>#!/usr/bin/env python
  import sys
  import logging
  import system_utilities
  
  log = logging.getLogger()
  log.setLevel("DEBUG")
  log.addHandler(system_utilities.SystemLogger())
  
  import matplotlib
  matplotlib.use("Qt4Agg")
  matplotlib.rcParams["backend.qt4"] = "PySide"
  import subprocess
  import plot_widget
  
  from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
  from matplotlib.figure import Figure
  
  from PySide import QtCore, QtGui
  
  
  class MainWindow(QtGui.QMainWindow):
      """This is the main window class and displays the primary UI when launched.
      Inherits from QMainWindow.
      """
  
      def __init__(self):
          """Init function. 
          """
          super(MainWindow, self).__init__()
          self.x = None
          self.y = None
          self.data_plot = None
          self.plot_layout = None
          self.terminal = None
          self.setup_plot()
          self.setup_interface()
  
      def  setup_plot(self):
          """Member function to setup the graph window in the main UI.
          """
  
          #Create a PlotWidget object
          self.data_plot = plot_widget.PlotWidget()
  
          #Create a BoxLayout element to hold PlotWidget
          self.plot_layout = QtGui.QVBoxLayout()
          self.plot_layout.addWidget(self.data_plot)
  
  
      def setup_interface(self):
          """Member function to instantiate and build the composite elements of the 
          UI."""
  
          #Main widget houses layout elements (Layout cannot be placed directly in a QMainWindow).
          central_widget = QtGui.QWidget()
          test_splitter = QtGui.QSplitter(QtCore.Qt.Vertical)
          button_splitter = QtGui.QSplitter(QtCore.Qt.Horizontal)
  
          #UI BoxLayout elements
          central_layout = QtGui.QVBoxLayout()
          #button_layout = QtGui.QHBoxLayout()
  
          #UI PushButton elements
          exit_button = QtGui.QPushButton("Close")
          run_button = QtGui.QPushButton("Run...")
  
          #UI Text output
          self.editor = QtGui.QTextEdit()
          self.editor.setReadOnly(True)
          self.terminal = QtGui.QTextBrowser()
          self.terminal.setReadOnly(True)
  
  
          #UI PushButton signals
          run_button.clicked.connect(self.run_c_program)
          run_button.clicked.connect(self.data_plot.redraw_plot)
          exit_button.clicked.connect(QtCore.QCoreApplication.instance().quit)
  
          #Build the UI from composite elements
          central_layout.addLayout(self.plot_layout)
          central_layout.addWidget(self.editor)
          button_splitter.addWidget(run_button)
          button_splitter.addWidget(exit_button)
          test_splitter.addWidget(button_splitter)
          test_splitter.addWidget(self.terminal)
          test_splitter.setCollapsible(1, True)
          central_layout.addWidget(test_splitter)
          central_widget.setLayout(central_layout)
          self.setCentralWidget(central_widget)
  
  
          self.show()
  
  class OutLog:
      def __init__(self, edit, out=None, color=None):
          """(edit, out=None, color=None) -&gt; can write stdout, stderr to a
          QTextEdit.
          edit = QTextEdit
          out = alternate stream ( can be the original sys.stdout )
          color = alternate color (i.e. color stderr a different color)
          """
          self.edit = edit
          self.out = None
          self.color = color
  
      def write(self, m):
          if self.color:
              tc = self.edit.textColor()
              self.edit.setTextColor(self.color)
  
          self.edit.moveCursor(QtGui.QTextCursor.End)
          log.debug("this is m {}".format(m))
          self.edit.insertPlainText( m )
  
          if self.color:
              self.edit.setTextColor(tc)
  
          if self.out:
              self.out.write(m)
  
  
  
  
  def main():
  
  
      app = QtGui.QApplication(sys.argv)
  
      log.debug("Window starting.")
      window = MainWindow()
      sys.stdout = OutLog(window.terminal, sys.stdout)
      sys.stderr = OutLog(window.terminal, sys.stderr, QtGui.QColor(255,0,0))
      window.show()
  
      sys.exit(app.exec_())
      log.info("System shutdown.")
  
  
  if __name__ == '__main__':
      main()
  </code></pre>
  
  <p>"Help me Obi-Wan..."</p>
  
  <p>Thanks in advance guys (and gals :-))</p>