Index: src/sas/qtgui/DataExplorer.py
===================================================================
--- src/sas/qtgui/DataExplorer.py	(revision e540cd2f6e912b110651b7e76c9b4cc9c7183d9b)
+++ src/sas/qtgui/DataExplorer.py	(revision 0cd861274c705e809cccd5c60271a4621dee35d3)
@@ -13,5 +13,5 @@
 
 # SAS
-from GuiUtils import *
+import GuiUtils
 from Plotter import Plotter
 from sas.sascalc.dataloader.loader import Loader
@@ -307,5 +307,5 @@
         """
 
-        plots = plotsFromCheckedItems(self.model)
+        plots = GuiUtils.plotsFromCheckedItems(self.model)
 
         # Call show on requested plots
@@ -334,5 +334,5 @@
             paths = [str(f) for f in paths]
 
-        if type(paths) is not list:
+        if not isinstance(paths, list):
             paths = [paths]
 
@@ -358,5 +358,5 @@
             basename = os.path.basename(p_file)
             _, extension = os.path.splitext(basename)
-            if extension.lower() in EXTENSIONS:
+            if extension.lower() in GuiUtils.EXTENSIONS:
                 any_error = True
                 log_msg = "Data Loader cannot "
@@ -430,9 +430,12 @@
 
         if any_error or error_message:
-            self.communicator.statusBarUpdateSignal.emit(error_message)
+            logging.error(error_message)
+            status_bar_message = "Errors occurred while loading %s" % format(basename)
+            self.communicator.statusBarUpdateSignal.emit(status_bar_message)
 
         else:
             message = "Loading Data Complete! "
         message += log_msg
+        # Notify the progress bar that the updates are over.
         self.communicator.progressBarUpdateSignal.emit(-1)
 
@@ -485,5 +488,5 @@
 
                 try:
-                    is1D = type(item.child(0).data().toPyObject()) is Data1D
+                    is1D = isinstance(item.child(0).data().toPyObject(), Data1D)
                 except AttributeError:
                     msg = "Bad structure of the data model."
@@ -499,5 +502,5 @@
 
                 try:
-                    is1D = type(item.child(0).data().toPyObject()) is Data1D
+                    is1D = isinstance(item.child(0).data().toPyObject(), Data1D)
                 except AttributeError:
                     msg = "Bad structure of the data model."
@@ -513,5 +516,5 @@
                 item.setCheckState(QtCore.Qt.Unchecked)
                 try:
-                    is2D = type(item.child(0).data().toPyObject()) is Data2D
+                    is2D = isinstance(item.child(0).data().toPyObject(), Data2D)
                 except AttributeError:
                     msg = "Bad structure of the data model."
@@ -527,5 +530,5 @@
 
                 try:
-                    is2D = type(item.child(0).data().toPyObject()) is Data2D
+                    is2D = isinstance(item.child(0).data().toPyObject(), Data2D)
                 except AttributeError:
                     msg = "Bad structure of the data model."
@@ -602,5 +605,5 @@
 
         # Add rows for display in the view
-        info_item = infoFromData(data)
+        info_item = GuiUtils.infoFromData(data)
 
         # Set info_item as the only child
@@ -616,5 +619,5 @@
         """
         # Assert the correct type
-        if type(model_item) != QtGui.QStandardItem:
+        if not isinstance(model_item, QtGui.QStandardItem):
             msg = "Wrong data type returned from calculations."
             raise AttributeError, msg
Index: src/sas/qtgui/GuiManager.py
===================================================================
--- src/sas/qtgui/GuiManager.py	(revision e540cd2f6e912b110651b7e76c9b4cc9c7183d9b)
+++ src/sas/qtgui/GuiManager.py	(revision 0cd861274c705e809cccd5c60271a4621dee35d3)
@@ -1,3 +1,4 @@
 import sys
+import os
 import subprocess
 import logging
@@ -15,6 +16,8 @@
 from sas.sasgui.guiframe.proxy import Connection
 
+from SasviewLogger import XStream
+
 import LocalConfig
-from GuiUtils import *
+import GuiUtils
 from UI.AcknowledgementsUI import Acknowledgements
 from AboutBox import AboutBox
@@ -34,5 +37,4 @@
         """
         """
-
         self._workspace = mainWindow
         self._parent = parent
@@ -58,14 +60,14 @@
         # Widgets
         #
-        # Add FileDialog widget as docked
-        self.filesWidget = DataExplorerWindow(parent, self)
-
-        self.dockedFilesWidget = QtGui.QDockWidget("Data explorer", self._workspace)
-        self.dockedFilesWidget.setWidget(self.filesWidget)
-        self.dockedFilesWidget.setFeatures(QtGui.QDockWidget.NoDockWidgetFeatures)
-        self._workspace.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.dockedFilesWidget)
-
-        self.ackWidget = Acknowledgements()
-        self.aboutWidget = AboutBox()
+        self.addWidgets()
+
+        # Fork off logging messages to the Log Window
+        XStream.stdout().messageWritten.connect( self.listWidget.insertPlainText  )
+        XStream.stderr().messageWritten.connect( self.listWidget.insertPlainText  )
+
+        # Log the start of the session
+        logging.info(" --- SasView session started ---")
+        # Log the python version
+        logging.info("Python: %s" % sys.version)
 
         # Set up the status bar
@@ -94,4 +96,33 @@
         # Default perspective
         self._current_perspective = self.invariantWidget
+
+    def addWidgets(self):
+        """
+        Populate the main window with widgets
+
+        TODO: overwrite close() on Log and DR widgets so they can be hidden/shown
+        on request
+        """
+        # Add FileDialog widget as docked
+        self.filesWidget = DataExplorerWindow(self._parent, self)
+
+        self.dockedFilesWidget = QtGui.QDockWidget("Data Explorer", self._workspace)
+        self.dockedFilesWidget.setWidget(self.filesWidget)
+        # Disable maximize/minimize and close buttons
+        self.dockedFilesWidget.setFeatures(QtGui.QDockWidget.NoDockWidgetFeatures)
+        self._workspace.addDockWidget(QtCore.Qt.LeftDockWidgetArea,
+                                      self.dockedFilesWidget)
+
+        # Add the console window as another docked widget
+        self.logDockWidget = QtGui.QDockWidget("Log Explorer", self._workspace)
+        self.logDockWidget.setObjectName("LogDockWidget")
+        self.listWidget = QtGui.QTextBrowser()
+        self.logDockWidget.setWidget(self.listWidget)
+        self._workspace.addDockWidget(QtCore.Qt.BottomDockWidgetArea,
+                                      self.logDockWidget)
+
+        # Add other, minor widgets
+        self.ackWidget = Acknowledgements()
+        self.aboutWidget = AboutBox()
 
     def statusBarSetup(self):
@@ -266,5 +297,5 @@
         Method defining all signal connections for the gui manager
         """
-        self.communicate = Communicate()
+        self.communicate = GuiUtils.Communicate()
         self.communicate.fileDataReceivedSignal.connect(self.fileRead)
         self.communicate.statusBarUpdateSignal.connect(self.updateStatusBar)
@@ -411,5 +442,7 @@
         """
         """
-        print("actionReset TRIGGERED")
+        logging.warning(" *** actionOpen_Analysis logging *******")
+        print("actionReset print TRIGGERED")
+        sys.stderr.write("STDERR - TRIGGERED")
         pass
 
Index: src/sas/qtgui/MainWindow.py
===================================================================
--- src/sas/qtgui/MainWindow.py	(revision e540cd2f6e912b110651b7e76c9b4cc9c7183d9b)
+++ src/sas/qtgui/MainWindow.py	(revision 0cd861274c705e809cccd5c60271a4621dee35d3)
@@ -8,4 +8,7 @@
 # Local UI
 from UI.MainWindowUI import MainWindow
+
+# Initialize logging
+import SasviewLogger
 
 class MainSasViewWindow(MainWindow):
@@ -54,5 +57,6 @@
     # Show the main SV window
     mainwindow = MainSasViewWindow(reactor)
-    mainwindow.show()
+    #mainwindow.show()
+    mainwindow.showMaximized()
 
     # no more splash screen
Index: src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py
===================================================================
--- src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py	(revision e540cd2f6e912b110651b7e76c9b4cc9c7183d9b)
+++ src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py	(revision 0cd861274c705e809cccd5c60271a4621dee35d3)
@@ -12,6 +12,5 @@
 from sas.sascalc.invariant import invariant
 from sas.sasgui.guiframe.dataFitting import Data1D
-# from sas.qtgui.GuiUtils import *
-from GuiUtils import *
+import GuiUtils
 
 # local
@@ -67,5 +66,5 @@
         self._high_power_value  = False
 
-        self.communicate = Communicate()
+        self.communicate = GuiUtils.Communicate()
 
         # Mask file selector
@@ -278,5 +277,5 @@
 
             # This needs to run in the main thread
-            reactor.callFromThread(updateModelItem, self._model_item, variant_item, title)
+            reactor.callFromThread(GuiUtils.updateModelItem, self._model_item, variant_item, title)
 
         if self._high_extrapolate:
Index: src/sas/qtgui/SasviewLogger.py
===================================================================
--- src/sas/qtgui/SasviewLogger.py	(revision 0cd861274c705e809cccd5c60271a4621dee35d3)
+++ src/sas/qtgui/SasviewLogger.py	(revision 0cd861274c705e809cccd5c60271a4621dee35d3)
@@ -0,0 +1,62 @@
+import os
+import sys
+import logging
+
+from PyQt4 import QtCore
+
+
+class XStream(QtCore.QObject):
+    _stdout = None
+    _stderr = None
+    messageWritten = QtCore.pyqtSignal(str)
+
+    def flush(self):
+        pass
+
+    def fileno(self):
+        return -1
+
+    def write(self, msg):
+        if(not self.signalsBlocked()):
+            self.messageWritten.emit(unicode(msg))
+
+    @staticmethod
+    def stdout():
+        if(not XStream._stdout):
+            XStream._stdout = XStream()
+            sys.stdout = XStream._stdout
+        return XStream._stdout
+
+    @staticmethod
+    def stderr():
+        if(not XStream._stderr):
+            XStream._stderr = XStream()
+            sys.stderr = XStream._stderr
+        return XStream._stderr
+
+class QtHandler(logging.Handler):
+    """
+    Version of logging handler
+    "emitting" the message to custom stdout()
+    """
+    def __init__(self):
+        logging.Handler.__init__(self)
+
+    def emit(self, record):
+        record = self.format(record)
+        if record:
+            XStream.stdout().write('%s\n'%record)
+
+
+# Define the default logger
+logger = logging.getLogger()
+
+# Add the file handler
+logging.basicConfig(level=logging.INFO,
+                    format='%(asctime)s %(levelname)s %(message)s',
+                    filename=os.path.join(os.path.expanduser("~"),
+                                          'sasview.log'))
+# Add the qt-signal logger
+handler = QtHandler()
+handler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
+logger.addHandler(handler)
Index: src/sas/qtgui/UI/MainWindowUI.py
===================================================================
--- src/sas/qtgui/UI/MainWindowUI.py	(revision e540cd2f6e912b110651b7e76c9b4cc9c7183d9b)
+++ src/sas/qtgui/UI/MainWindowUI.py	(revision 0cd861274c705e809cccd5c60271a4621dee35d3)
@@ -56,4 +56,9 @@
         MainWindow.setMenuBar(self.menubar)
         self.statusbar = QtGui.QStatusBar(MainWindow)
+        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.statusbar.sizePolicy().hasHeightForWidth())
+        self.statusbar.setSizePolicy(sizePolicy)
         self.statusbar.setObjectName(_fromUtf8("statusbar"))
         MainWindow.setStatusBar(self.statusbar)
Index: src/sas/qtgui/UI/MainWindowUI.ui
===================================================================
--- src/sas/qtgui/UI/MainWindowUI.ui	(revision e540cd2f6e912b110651b7e76c9b4cc9c7183d9b)
+++ src/sas/qtgui/UI/MainWindowUI.ui	(revision 0cd861274c705e809cccd5c60271a4621dee35d3)
@@ -149,5 +149,12 @@
    <addaction name="menuHelp"/>
   </widget>
-  <widget class="QStatusBar" name="statusbar"/>
+  <widget class="QStatusBar" name="statusbar">
+   <property name="sizePolicy">
+    <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+     <horstretch>0</horstretch>
+     <verstretch>0</verstretch>
+    </sizepolicy>
+   </property>
+  </widget>
   <widget class="QToolBar" name="toolBar">
    <property name="windowTitle">
Index: src/sas/qtgui/UnitTesting/DataExplorerTest.py
===================================================================
--- src/sas/qtgui/UnitTesting/DataExplorerTest.py	(revision e540cd2f6e912b110651b7e76c9b4cc9c7183d9b)
+++ src/sas/qtgui/UnitTesting/DataExplorerTest.py	(revision 0cd861274c705e809cccd5c60271a4621dee35d3)
@@ -95,5 +95,5 @@
         """
         Test if all required widgets got added
-        """        
+        """
     def testLoadButton(self):
         loadButton = self.form.cmdLoad
Index: src/sas/qtgui/UnitTesting/GuiManagerTest.py
===================================================================
--- src/sas/qtgui/UnitTesting/GuiManagerTest.py	(revision e540cd2f6e912b110651b7e76c9b4cc9c7183d9b)
+++ src/sas/qtgui/UnitTesting/GuiManagerTest.py	(revision 0cd861274c705e809cccd5c60271a4621dee35d3)
@@ -48,9 +48,40 @@
         self.assertIsInstance(self.manager.filesWidget, DataExplorerWindow)
         self.assertIsInstance(self.manager.dockedFilesWidget, QDockWidget)
+        self.assertIsInstance(self.manager.dockedFilesWidget.widget(), DataExplorerWindow)
         self.assertEqual(self.manager.dockedFilesWidget.features(), QDockWidget.NoDockWidgetFeatures)
         self.assertEqual(self.manager._workspace.dockWidgetArea(self.manager.dockedFilesWidget), Qt.LeftDockWidgetArea)
+
+        self.assertIsInstance(self.manager.logDockWidget, QDockWidget)
+        self.assertIsInstance(self.manager.logDockWidget.widget(), QTextBrowser)
+        self.assertEqual(self.manager._workspace.dockWidgetArea(self.manager.logDockWidget), Qt.BottomDockWidgetArea)
+
         self.assertIsInstance(self.manager.ackWidget, Acknowledgements)
         self.assertIsInstance(self.manager.aboutWidget, AboutBox)
         self.assertIsInstance(self.manager.welcomePanel, WelcomePanel)
+
+    def testLogging(self):
+        """
+        Test logging of stdout, stderr and log messages
+        """
+        # See if the log window is empty
+        self.assertEqual(self.manager.logDockWidget.widget().toPlainText(), "")
+
+        # Now, send some message to stdout.
+        # We are in the MainWindow scope, so simple 'print' will work
+        message = "from stdout"
+        print message
+        self.assertIn(message, self.manager.logDockWidget.widget().toPlainText())
+
+        # Send some message to stderr
+        message = "from stderr"
+        sys.stderr.write(message)
+        self.assertIn(message, self.manager.logDockWidget.widget().toPlainText())
+
+        # And finally, send a log message
+        import logging
+        message = "from logging"
+        message_logged = "ERROR: " + message
+        logging.error(message)
+        self.assertIn(message_logged, self.manager.logDockWidget.widget().toPlainText())
 
     def testUpdatePerspective(self):
Index: src/sas/qtgui/UnitTesting/SasviewLoggerTest.py
===================================================================
--- src/sas/qtgui/UnitTesting/SasviewLoggerTest.py	(revision 0cd861274c705e809cccd5c60271a4621dee35d3)
+++ src/sas/qtgui/UnitTesting/SasviewLoggerTest.py	(revision 0cd861274c705e809cccd5c60271a4621dee35d3)
@@ -0,0 +1,56 @@
+import sys
+import unittest
+import logging
+
+from PyQt4.QtGui import *
+from PyQt4.QtTest import QTest
+from PyQt4.QtCore import *
+
+# Local
+from SasviewLogger import XStream
+from SasviewLogger import QtHandler
+
+app = QApplication(sys.argv)
+
+class SasviewLoggerTest(unittest.TestCase):
+    def setUp(self):
+        """
+        Prepare the logger
+        """
+        self.logger = logging.getLogger(__name__)
+        handler = QtHandler()
+        handler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
+        self.logger.addHandler(handler)
+        self.logger.setLevel(logging.DEBUG)
+
+        self.outHandlerGui=QTextBrowser()
+
+
+    def test_stdout(self):
+        """
+        Test redirection of all levels of logging
+        """
+        # Attach the listeners
+        XStream.stderr().messageWritten.connect( self.outHandlerGui.insertPlainText )
+        XStream.stdout().messageWritten.connect( self.outHandlerGui.insertPlainText )
+
+        # Send the signals
+        self.logger.debug('debug message')
+        self.logger.info('info message')
+        self.logger.warning('warning message')
+        self.logger.error('error message')
+        sys.stdout.write('with stdout')
+        sys.stderr.write('with stderr')
+
+        out=self.outHandlerGui.toPlainText()
+
+        # Assure everything got logged
+        self.assertIn('DEBUG: debug message', out)
+        self.assertIn('INFO: info message', out)
+        self.assertIn('WARNING: warning message', out)
+        self.assertIn('ERROR: error message', out)
+        self.assertIn('with stdout', out)
+        self.assertIn('with stderr', out)
+
+if __name__ == "__main__":
+    unittest.main()
Index: src/sas/qtgui/run_tests.sh
===================================================================
--- src/sas/qtgui/run_tests.sh	(revision f82ab8cebb48e29a3c2598340d12929e037d764c)
+++ src/sas/qtgui/run_tests.sh	(revision 0cd861274c705e809cccd5c60271a4621dee35d3)
@@ -7,2 +7,3 @@
 python -m UnitTesting.AboutBoxTest
 python -m UnitTesting.DroppableDataLoadWidgetTest
+python -m UnitTesting.SasviewLoggerTest
