Index: src/sas/qtgui/DataExplorer.py
===================================================================
--- src/sas/qtgui/DataExplorer.py	(revision 1042dbac0d9a9f513386ed723f3d110463dce201)
+++ src/sas/qtgui/DataExplorer.py	(revision 9e426c11367c4fe13f88ce18932880794884e04f)
@@ -85,5 +85,5 @@
         """
         dir = QtGui.QFileDialog.getExistingDirectory(self, "Choose a directory", "",
-              QtGui.QFileDialog.ShowDirsOnly)
+              QtGui.QFileDialog.ShowDirsOnly | QtGui.QFileDialog.DontUseNativeDialog)
         if dir is None:
             return
@@ -171,4 +171,6 @@
         """
         Create a new matplotlib chart from selected data
+
+        TODO: Add 2D-functionality
         """
 
@@ -192,18 +194,16 @@
         # Location is automatically saved - no need to keep track of the last dir
         # But only with Qt built-in dialog (non-platform native)
-        paths = QtGui.QFileDialog.getOpenFileName(self, "Choose a file", "",
+        paths = QtGui.QFileDialog.getOpenFileNames(self, "Choose a file", "",
                 wlist, None, QtGui.QFileDialog.DontUseNativeDialog)
         if paths is None:
             return
 
+        if type(paths) == QtCore.QStringList:
+            paths = [str(f) for f in paths]
+
         if paths.__class__.__name__ != "list":
             paths = [paths]
 
-        path_str=[]
-        for path in paths:
-            if str(path):
-                path_str.append(str(path))
-
-        return path_str
+        return paths
 
     def readData(self, path):
@@ -402,6 +402,10 @@
         Post message to status bar and update the data manager
         """
+        # Don't show "empty" rows with data objects
+        self.proxy.setFilterRegExp(r"[^()]")
+
+        # Reset the model so the view gets updated.
         self.model.reset()
-        assert(type(output), tuple)
+        assert type(output)== tuple
 
         output_data = output[0]
@@ -433,7 +437,4 @@
         checkbox_item.setText(os.path.basename(p_file))
 
-        # Add "Info" item
-        # info_item = QtGui.QStandardItem("Info")
-
         # Add the actual Data1D/Data2D object
         object_item = QtGui.QStandardItem()
@@ -443,5 +444,4 @@
 
         # Add rows for display in the view
-        # self.addExtraRows(info_item, data)
         info_item = infoFromData(data)
 
@@ -452,7 +452,4 @@
         self.model.appendRow(checkbox_item)
         
-        # Don't show "empty" rows with data objects
-        self.proxy.setFilterRegExp(r"[^()]")
-
     def updateModelFromPerspective(self, model_item):
         """
Index: src/sas/qtgui/GuiManager.py
===================================================================
--- src/sas/qtgui/GuiManager.py	(revision 1042dbac0d9a9f513386ed723f3d110463dce201)
+++ src/sas/qtgui/GuiManager.py	(revision 9e426c11367c4fe13f88ce18932880794884e04f)
@@ -1,3 +1,7 @@
 import sys
+import subprocess
+import logging
+import json
+import webbrowser
 
 from PyQt4 import QtCore
@@ -9,6 +13,9 @@
 # General SAS imports
 from sas.sasgui.guiframe.data_manager import DataManager
+from sas.sasgui.guiframe.proxy import Connection
+
 import LocalConfig
 from GuiUtils import *
+from UI.AcknowledgementsUI import Acknowledgements
 
 # Perspectives
@@ -21,4 +28,6 @@
     Main SasView window functionality
     """
+    HELP_DIRECTORY_LOCATION="html"
+
     def __init__(self, mainWindow=None, reactor=None, parent=None):
         """
@@ -56,5 +65,9 @@
         self.dockedFilesWidget.setWidget(self.filesWidget)
         self._workspace.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.dockedFilesWidget)
+
+        self.ackWidget = Acknowledgements()
+
         # Disable the close button (?)
+
         # Show the Welcome panel
         self.welcomePanel = WelcomePanel()
@@ -63,5 +76,11 @@
         # Current help file
         self._helpView = QtWebKit.QWebView()
-        self._helpLocation = "html/index.html"
+        # Needs URL like path, so no path.join() here
+        self._helpLocation = self.HELP_DIRECTORY_LOCATION + "/index.html"
+
+        # Current tutorial location
+        self._tutorialLocation = os.path.join(self.HELP_DIRECTORY_LOCATION,
+                                              "_downloads",
+                                              "Tutorial.pdf")
 
         #==========================================================
@@ -77,5 +96,4 @@
         """
         """
-        print("FILE %s "%data)
         pass
     
@@ -161,6 +179,91 @@
             logging.info(msg)
 
+    def quitApplication(self):
+        """
+        Close the reactor and exit nicely.
+        """
+        # Display confirmation messagebox
+        quit_msg = "Are you sure you want to exit the application?"
+        reply = QtGui.QMessageBox.question(
+                        self._parent,
+                        'Warning',
+                        quit_msg,
+                        QtGui.QMessageBox.Yes,
+                        QtGui.QMessageBox.No)
+
+        if reply == QtGui.QMessageBox.No:
+            return
+
+        # Exit if yes
+        reactor.callFromThread(reactor.stop)
+        reactor.stop
+        sys.exit()
+
+    def checkUpdate(self):
+        """
+        Check with the deployment server whether a new version
+        of the application is available.
+        A thread is started for the connecting with the server. The thread calls
+        a call-back method when the current version number has been obtained.
+        """
+        version_info = {"version": "0.0.0"}
+        c = Connection(LocalConfig.__update_URL__, LocalConfig.UPDATE_TIMEOUT)
+        response = c.connect()
+        if response is not None:
+            try:
+                content = response.read().strip()
+                logging.info("Connected to www.sasview.org. Latest version: %s"
+                             % (content))
+                version_info = json.loads(content)
+            except:
+                logging.info("Failed to connect to www.sasview.org")
+        self.processVersion(version_info)  
+  
+    def processVersion(self, version_info, standalone=False):
+        """
+        Call-back method for the process of checking for updates.
+        This methods is called by a VersionThread object once the current
+        version number has been obtained. If the check is being done in the
+        background, the user will not be notified unless there's an update.
+
+        :param version: version string
+        :param standalone: True of the update is being checked in
+           the background, False otherwise.
+
+        """
+        try:
+            version = version_info["version"]
+            if version == "0.0.0":
+                msg = "Could not connect to the application server."
+                msg += " Please try again later."
+                #self.SetStatusText(msg)
+                self.communicate.statusBarUpdateSignal.emit(msg)
+
+            elif cmp(version, LocalConfig.__version__) > 0:
+                msg = "Version %s is available! " % str(version)
+                if not standalone:
+                    if "download_url" in version_info:
+                        webbrowser.open(version_info["download_url"])
+                    else:
+                        webbrowser.open(LocalConfig.__download_page__)
+                else:
+                    msg += "See the help menu to download it."
+                self.communicate.statusBarUpdateSignal.emit(msg)
+            else:
+                msg = "You have the latest version"
+                msg += " of %s" % str(LocalConfig.__appname__)
+                self.communicate.statusBarUpdateSignal.emit(msg)
+        except:
+            msg = "guiframe: could not get latest application"
+            msg += " version number\n  %s" % sys.exc_value
+            logging.error(msg)
+            if not standalone:
+                msg = "Could not connect to the application server."
+                msg += " Please try again later."
+                self.communicate.statusBarUpdateSignal.emit(msg)
+
     def addCallbacks(self):
         """
+        Method defining all signal connections for the gui manager
         """
         self.communicate = Communicate()
@@ -234,5 +337,5 @@
     def actionLoadData(self):
         """
-        Load file from Data Explorer
+        Menu File/Load Data File(s)
         """
         self.filesWidget.loadFile()
@@ -240,4 +343,5 @@
     def actionLoad_Data_Folder(self):
         """
+        Menu File/Load Data Folder
         """
         self.filesWidget.loadFolder()
@@ -272,15 +376,5 @@
         Close the reactor, exit the application.
         """
-        # display messagebox
-        quit_msg = "Are you sure you want to exit the application?"
-        reply = QtGui.QMessageBox.question(self._parent, 'Warning', quit_msg,
-                QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
-
-        if reply == QtGui.QMessageBox.No:
-            return
-
-        # exit if yes
-        reactor.callFromThread(reactor.stop)
-        sys.exit()
+        self.quitApplication()
 
     #============ EDIT =================
@@ -509,4 +603,7 @@
     def actionDocumentation(self):
         """
+        Display the documentation
+
+        TODO: use QNetworkAccessManager to assure _helpLocation is valid
         """
         self._helpView.load(QtCore.QUrl(self._helpLocation))
@@ -515,17 +612,22 @@
     def actionTutorial(self):
         """
-        """
-        print("actionTutorial TRIGGERED")
-        pass
+        Open the tutorial PDF file with default PDF renderer
+        """
+        # Not terribly safe here. Shell injection warning.
+        # isfile() helps but this probably needs a better solution.
+        if os.path.isfile(self._tutorialLocation):
+            result = subprocess.Popen([self._tutorialLocation], shell=True)
 
     def actionAcknowledge(self):
         """
-        """
-        print("actionAcknowledge TRIGGERED")
-        pass
+        Open the Acknowledgements widget
+        """
+        self.ackWidget.show()
 
     def actionAbout(self):
         """
-        """
+        Open the About box
+        """
+        
         print("actionAbout TRIGGERED")
         pass
@@ -533,6 +635,8 @@
     def actionCheck_for_update(self):
         """
-        """
-        print("actionCheck_for_update TRIGGERED")
-        pass
-
+        Menu Help/Check for Update
+        """
+        self.checkUpdate()
+
+        pass
+
Index: src/sas/qtgui/GuiUtils.py
===================================================================
--- src/sas/qtgui/GuiUtils.py	(revision 1042dbac0d9a9f513386ed723f3d110463dce201)
+++ src/sas/qtgui/GuiUtils.py	(revision 9e426c11367c4fe13f88ce18932880794884e04f)
Index: src/sas/qtgui/MainWindow.py
===================================================================
--- src/sas/qtgui/MainWindow.py	(revision f721030e66e61dc6279aa8e024da03b25f8e0d42)
+++ src/sas/qtgui/MainWindow.py	(revision 9e426c11367c4fe13f88ce18932880794884e04f)
@@ -21,6 +21,11 @@
         # Create the gui manager
         from GuiManager import GuiManager
-        guiManager = GuiManager(self, reactor, self)
+        self.guiManager = GuiManager(self, reactor, self)
 
+    def closeEvent(self, event):
+        from twisted.internet import reactor
+        reactor.stop
+        event.accept()
+        sys.exit()
         
 def SplashScreen():
@@ -60,3 +65,2 @@
     reactor.run()
 
-    # TODO : in the VS debugger, the Qt loop doesn't seem to end - investigate
Index: src/sas/qtgui/UI/AcknowledgementsUI.ui
===================================================================
--- src/sas/qtgui/UI/AcknowledgementsUI.ui	(revision 9e426c11367c4fe13f88ce18932880794884e04f)
+++ src/sas/qtgui/UI/AcknowledgementsUI.ui	(revision 9e426c11367c4fe13f88ce18932880794884e04f)
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Acknowledgements</class>
+ <widget class="QWidget" name="Acknowledgements">
+  <property name="windowModality">
+   <enum>Qt::ApplicationModal</enum>
+  </property>
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>436</width>
+    <height>212</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>Acknowledging SasView</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;To ensure the long term support and development of this software please remember to&lt;/p&gt;&lt;ol style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Acknowledge its use in your publications as suggested below&lt;br/&gt;&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Reference the following website: http://www.sasview.org&lt;br/&gt;&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Reference the model you used if appropriate (see documentation for refs) &lt;br/&gt;&lt;/li&gt;&lt;li style=&quot; margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Send us your reference for our records: developers@sasview.org&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QTextBrowser" name="textBrowser">
+     <property name="html">
+      <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;This work benefited from the use of the SasView application, originally&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;developed under NSF award DMR-0520547.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
Index: src/sas/qtgui/UI/DataExplorerUI.py
===================================================================
--- src/sas/qtgui/UI/DataExplorerUI.py	(revision f721030e66e61dc6279aa8e024da03b25f8e0d42)
+++ 	(revision )
@@ -1,162 +1,0 @@
-# -*- coding: utf-8 -*-
-
-# Form implementation generated from reading ui file 'DataExplorerUI.ui'
-#
-# Created by: PyQt4 UI code generator 4.11.4
-#
-# WARNING! All changes made in this file will be lost!
-
-from PyQt4 import QtCore, QtGui
-
-try:
-    _fromUtf8 = QtCore.QString.fromUtf8
-except AttributeError:
-    def _fromUtf8(s):
-        return s
-
-try:
-    _encoding = QtGui.QApplication.UnicodeUTF8
-    def _translate(context, text, disambig):
-        return QtGui.QApplication.translate(context, text, disambig, _encoding)
-except AttributeError:
-    def _translate(context, text, disambig):
-        return QtGui.QApplication.translate(context, text, disambig)
-
-class Ui_DataExplorerUI(object):
-    def setupUi(self, DataExplorerUI):
-        DataExplorerUI.setObjectName(_fromUtf8("DataExplorerUI"))
-        DataExplorerUI.resize(454, 577)
-        self.gridLayout_4 = QtGui.QGridLayout(DataExplorerUI)
-        self.gridLayout_4.setObjectName(_fromUtf8("gridLayout_4"))
-        self.label = QtGui.QLabel(DataExplorerUI)
-        self.label.setObjectName(_fromUtf8("label"))
-        self.gridLayout_4.addWidget(self.label, 0, 0, 1, 1)
-        self.comboBox = QtGui.QComboBox(DataExplorerUI)
-        self.comboBox.setObjectName(_fromUtf8("comboBox"))
-        self.comboBox.addItem(_fromUtf8(""))
-        self.comboBox.addItem(_fromUtf8(""))
-        self.comboBox.addItem(_fromUtf8(""))
-        self.comboBox.addItem(_fromUtf8(""))
-        self.comboBox.addItem(_fromUtf8(""))
-        self.comboBox.addItem(_fromUtf8(""))
-        self.gridLayout_4.addWidget(self.comboBox, 1, 0, 1, 1)
-        spacerItem = QtGui.QSpacerItem(278, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
-        self.gridLayout_4.addItem(spacerItem, 1, 1, 1, 1)
-        self.groupBox = QtGui.QGroupBox(DataExplorerUI)
-        self.groupBox.setObjectName(_fromUtf8("groupBox"))
-        self.gridLayout = QtGui.QGridLayout(self.groupBox)
-        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
-        self.treeView = QtGui.QTreeView(self.groupBox)
-        self.treeView.setDragEnabled(True)
-        self.treeView.setDragDropMode(QtGui.QAbstractItemView.DragDrop)
-        self.treeView.setDefaultDropAction(QtCore.Qt.CopyAction)
-        self.treeView.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
-        self.treeView.setObjectName(_fromUtf8("treeView"))
-        self.gridLayout.addWidget(self.treeView, 0, 0, 1, 1)
-        self.verticalLayout = QtGui.QVBoxLayout()
-        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
-        self.pushButton = QtGui.QPushButton(self.groupBox)
-        self.pushButton.setObjectName(_fromUtf8("pushButton"))
-        self.verticalLayout.addWidget(self.pushButton)
-        self.pushButton_2 = QtGui.QPushButton(self.groupBox)
-        self.pushButton_2.setObjectName(_fromUtf8("pushButton_2"))
-        self.verticalLayout.addWidget(self.pushButton_2)
-        spacerItem1 = QtGui.QSpacerItem(20, 141, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
-        self.verticalLayout.addItem(spacerItem1)
-        self.gridLayout.addLayout(self.verticalLayout, 0, 1, 1, 1)
-        self.horizontalLayout = QtGui.QHBoxLayout()
-        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
-        self.pushButton_6 = QtGui.QPushButton(self.groupBox)
-        self.pushButton_6.setObjectName(_fromUtf8("pushButton_6"))
-        self.horizontalLayout.addWidget(self.pushButton_6)
-        self.comboBox_3 = QtGui.QComboBox(self.groupBox)
-        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed)
-        sizePolicy.setHorizontalStretch(0)
-        sizePolicy.setVerticalStretch(0)
-        sizePolicy.setHeightForWidth(self.comboBox_3.sizePolicy().hasHeightForWidth())
-        self.comboBox_3.setSizePolicy(sizePolicy)
-        self.comboBox_3.setObjectName(_fromUtf8("comboBox_3"))
-        self.comboBox_3.addItem(_fromUtf8(""))
-        self.comboBox_3.addItem(_fromUtf8(""))
-        self.comboBox_3.addItem(_fromUtf8(""))
-        self.horizontalLayout.addWidget(self.comboBox_3)
-        self.checkBox = QtGui.QCheckBox(self.groupBox)
-        self.checkBox.setObjectName(_fromUtf8("checkBox"))
-        self.horizontalLayout.addWidget(self.checkBox)
-        spacerItem2 = QtGui.QSpacerItem(197, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
-        self.horizontalLayout.addItem(spacerItem2)
-        self.gridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 2)
-        self.gridLayout_4.addWidget(self.groupBox, 2, 0, 1, 2)
-        self.groupBox_2 = QtGui.QGroupBox(DataExplorerUI)
-        self.groupBox_2.setObjectName(_fromUtf8("groupBox_2"))
-        self.gridLayout_2 = QtGui.QGridLayout(self.groupBox_2)
-        self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
-        self.listView = QtGui.QListView(self.groupBox_2)
-        self.listView.setObjectName(_fromUtf8("listView"))
-        self.gridLayout_2.addWidget(self.listView, 0, 0, 2, 1)
-        self.pushButton_3 = QtGui.QPushButton(self.groupBox_2)
-        self.pushButton_3.setObjectName(_fromUtf8("pushButton_3"))
-        self.gridLayout_2.addWidget(self.pushButton_3, 0, 1, 1, 1)
-        spacerItem3 = QtGui.QSpacerItem(20, 198, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
-        self.gridLayout_2.addItem(spacerItem3, 1, 1, 1, 1)
-        self.gridLayout_4.addWidget(self.groupBox_2, 3, 0, 1, 2)
-        self.groupBox_3 = QtGui.QGroupBox(DataExplorerUI)
-        self.groupBox_3.setObjectName(_fromUtf8("groupBox_3"))
-        self.gridLayout_3 = QtGui.QGridLayout(self.groupBox_3)
-        self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3"))
-        self.pushButton_4 = QtGui.QPushButton(self.groupBox_3)
-        self.pushButton_4.setObjectName(_fromUtf8("pushButton_4"))
-        self.gridLayout_3.addWidget(self.pushButton_4, 0, 0, 1, 1)
-        self.pushButton_5 = QtGui.QPushButton(self.groupBox_3)
-        self.pushButton_5.setObjectName(_fromUtf8("pushButton_5"))
-        self.gridLayout_3.addWidget(self.pushButton_5, 1, 0, 1, 1)
-        self.comboBox_2 = QtGui.QComboBox(self.groupBox_3)
-        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed)
-        sizePolicy.setHorizontalStretch(0)
-        sizePolicy.setVerticalStretch(0)
-        sizePolicy.setHeightForWidth(self.comboBox_2.sizePolicy().hasHeightForWidth())
-        self.comboBox_2.setSizePolicy(sizePolicy)
-        self.comboBox_2.setObjectName(_fromUtf8("comboBox_2"))
-        self.comboBox_2.addItem(_fromUtf8(""))
-        self.gridLayout_3.addWidget(self.comboBox_2, 1, 1, 1, 1)
-        self.gridLayout_4.addWidget(self.groupBox_3, 4, 0, 1, 1)
-        self.groupBox_3.raise_()
-        self.groupBox_2.raise_()
-        self.groupBox.raise_()
-        self.comboBox.raise_()
-        self.label.raise_()
-
-        self.retranslateUi(DataExplorerUI)
-        QtCore.QMetaObject.connectSlotsByName(DataExplorerUI)
-
-    def retranslateUi(self, DataExplorerUI):
-        DataExplorerUI.setWindowTitle(_translate("DataExplorerUI", "Dialog", None))
-        self.label.setText(_translate("DataExplorerUI", "Selection Options", None))
-        self.comboBox.setItemText(0, _translate("DataExplorerUI", "Select all", None))
-        self.comboBox.setItemText(1, _translate("DataExplorerUI", "Unselect all", None))
-        self.comboBox.setItemText(2, _translate("DataExplorerUI", "Select all 1D", None))
-        self.comboBox.setItemText(3, _translate("DataExplorerUI", "Unselect all 1D", None))
-        self.comboBox.setItemText(4, _translate("DataExplorerUI", "Select all 2D", None))
-        self.comboBox.setItemText(5, _translate("DataExplorerUI", "Unselect all 2D", None))
-        self.groupBox.setTitle(_translate("DataExplorerUI", "Data", None))
-        self.pushButton.setText(_translate("DataExplorerUI", "Load", None))
-        self.pushButton_2.setText(_translate("DataExplorerUI", "Delete", None))
-        self.pushButton_6.setText(_translate("DataExplorerUI", "Send to", None))
-        self.comboBox_3.setItemText(0, _translate("DataExplorerUI", "Fitting", None))
-        self.comboBox_3.setItemText(1, _translate("DataExplorerUI", "Pr inversion", None))
-        self.comboBox_3.setItemText(2, _translate("DataExplorerUI", "Invariant", None))
-        self.checkBox.setText(_translate("DataExplorerUI", "Batch mode", None))
-        self.groupBox_2.setTitle(_translate("DataExplorerUI", "Theory", None))
-        self.pushButton_3.setText(_translate("DataExplorerUI", "Freeze", None))
-        self.groupBox_3.setTitle(_translate("DataExplorerUI", "Plot", None))
-        self.pushButton_4.setText(_translate("DataExplorerUI", "New", None))
-        self.pushButton_5.setText(_translate("DataExplorerUI", "Append to", None))
-        self.comboBox_2.setItemText(0, _translate("DataExplorerUI", "Graph1", None))
-
-
-class DataExplorerUI(QtGui.QDialog, Ui_DataExplorerUI):
-    def __init__(self, parent=None, f=QtCore.Qt.WindowFlags()):
-        QtGui.QDialog.__init__(self, parent, f)
-
-        self.setupUi(self)
-
Index: src/sas/qtgui/UnitTesting/DataExplorerTest.py
===================================================================
--- src/sas/qtgui/UnitTesting/DataExplorerTest.py	(revision 1042dbac0d9a9f513386ed723f3d110463dce201)
+++ src/sas/qtgui/UnitTesting/DataExplorerTest.py	(revision 9e426c11367c4fe13f88ce18932880794884e04f)
@@ -72,6 +72,10 @@
         loadButton = self.form.cmdLoad
 
-        # Mock the system file open method
-        QtGui.QFileDialog.getOpenFileName = MagicMock(return_value=None)
+        filename = "cyl_400_20.txt"
+        # Initialize signal spy instances
+        spy_file_read = QtSignalSpy(self.form, self.form.communicate.fileReadSignal)
+
+        # Return no files.
+        QtGui.QFileDialog.getOpenFileNames = MagicMock(return_value=None)
 
         # Click on the Load button
@@ -79,6 +83,23 @@
 
         # Test the getOpenFileName() dialog called once
-        self.assertTrue(QtGui.QFileDialog.getOpenFileName.called)
-        QtGui.QFileDialog.getOpenFileName.assert_called_once()
+        self.assertTrue(QtGui.QFileDialog.getOpenFileNames.called)
+        QtGui.QFileDialog.getOpenFileNames.assert_called_once()
+
+        # Make sure the signal has not been emitted
+        self.assertEqual(spy_file_read.count(), 0)
+
+        # Now, return a single file
+        QtGui.QFileDialog.getOpenFileNames = MagicMock(return_value=filename)
+        
+        # Click on the Load button
+        QTest.mouseClick(loadButton, Qt.LeftButton)
+
+        # Test the getOpenFileName() dialog called once
+        self.assertTrue(QtGui.QFileDialog.getOpenFileNames.called)
+        QtGui.QFileDialog.getOpenFileNames.assert_called_once()
+
+        # Expected one spy instance
+        self.assertEqual(spy_file_read.count(), 1)
+        self.assertIn(filename, str(spy_file_read.called()[0]['args'][0]))
 
     def testDeleteButton(self):
@@ -131,5 +152,4 @@
         QTest.mouseClick(deleteButton, Qt.LeftButton)
 
-
     def testSendToButton(self):
         """
@@ -166,5 +186,4 @@
         # Assure the message box popped up
         QtGui.QMessageBox.assert_called_once()
-
 
     def testDataSelection(self):
@@ -272,5 +291,4 @@
         Test the callback method updating the data object
         """
-
         message="Loading Data Complete"
         data_dict = {"a1":Data1D()}
Index: src/sas/qtgui/UnitTesting/GuiManagerTest.py
===================================================================
--- src/sas/qtgui/UnitTesting/GuiManagerTest.py	(revision 5032ea687fa17c1323c1124c0a7aa9d80184bf0b)
+++ src/sas/qtgui/UnitTesting/GuiManagerTest.py	(revision 9e426c11367c4fe13f88ce18932880794884e04f)
@@ -1,8 +1,12 @@
 import sys
+import subprocess
 import unittest
+import webbrowser
+import logging
 
 from PyQt4.QtGui import *
 from PyQt4.QtTest import QTest
 from PyQt4.QtCore import *
+from PyQt4.QtWebKit import *
 from mock import MagicMock
 
@@ -10,4 +14,5 @@
 from GuiManager import GuiManager
 from UI.MainWindowUI import MainWindow
+from UnitTesting.TestUtils import QtSignalSpy
 
 app = QApplication(sys.argv)
@@ -56,4 +61,113 @@
         pass
 
+    def testQuitApplication(self):
+        """
+        Test that the custom exit method is called on shutdown
+        """
+        # Must mask sys.exit, otherwise the whole testing process stops.
+        sys.exit = MagicMock()
+
+        # Say No to the close dialog
+        QMessageBox.question = MagicMock(return_value=QMessageBox.No)
+
+        # Open, then close the manager
+        self.manager.quitApplication()
+
+        # See that the MessageBox method got called
+        self.assertTrue(QMessageBox.question.called)
+        # sys.exit() not called this time
+        self.assertFalse(sys.exit.called)
+
+        # Say Yes to the close dialog
+        QMessageBox.question = MagicMock(return_value=QMessageBox.Yes)
+
+        # Open, then close the manager
+        self.manager.quitApplication()
+
+        # See that the MessageBox method got called
+        self.assertTrue(QMessageBox.question.called)
+        # Also, sys.exit() called
+        self.assertTrue(sys.exit.called)
+
+    def testCheckUpdate(self):
+        """
+        Tests the SasView website version polling
+        """
+        self.manager.processVersion = MagicMock()
+        version = {'update_url'  : 'http://www.sasview.org/sasview.latestversion', 
+                   'version'     : '3.1.2',
+                   'download_url': 'https://github.com/SasView/sasview/releases'}
+        self.manager.checkUpdate()
+
+        self.manager.processVersion.assert_called_with(version)
+
+        pass
+
+    def testProcessVersion(self):
+        """
+        Tests the version checker logic
+        """
+        # 1. version = 0.0.0
+        version_info = {u'version' : u'0.0.0'}
+        spy_status_update = QtSignalSpy(self.manager, self.manager.communicate.statusBarUpdateSignal)
+
+        self.manager.processVersion(version_info)
+
+        self.assertEqual(spy_status_update.count(), 1)
+        message = 'Could not connect to the application server. Please try again later.'
+        self.assertIn(message, str(spy_status_update.signal(index=0)))
+
+        # 2. version < LocalConfig.__version__
+        version_info = {u'version' : u'0.0.1'}
+        spy_status_update = QtSignalSpy(self.manager, self.manager.communicate.statusBarUpdateSignal)
+
+        self.manager.processVersion(version_info)
+
+        self.assertEqual(spy_status_update.count(), 1)
+        message = 'You have the latest version of SasView'
+        self.assertIn(message, str(spy_status_update.signal(index=0)))
+
+        # 3. version > LocalConfig.__version__
+        version_info = {u'version' : u'999.0.0'}
+        spy_status_update = QtSignalSpy(self.manager, self.manager.communicate.statusBarUpdateSignal)
+        webbrowser.open = MagicMock()
+
+        self.manager.processVersion(version_info)
+
+        self.assertEqual(spy_status_update.count(), 1)
+        message = 'Version 999.0.0 is available!'
+        self.assertIn(message, str(spy_status_update.signal(index=0)))
+
+        webbrowser.open.assert_called_with("https://github.com/SasView/sasview/releases")
+
+        # 4. version > LocalConfig.__version__ and standalone
+        version_info = {u'version' : u'999.0.0'}
+        spy_status_update = QtSignalSpy(self.manager, self.manager.communicate.statusBarUpdateSignal)
+        webbrowser.open = MagicMock()
+
+        self.manager.processVersion(version_info, standalone=True)
+
+        self.assertEqual(spy_status_update.count(), 1)
+        message = 'See the help menu to download it'
+        self.assertIn(message, str(spy_status_update.signal(index=0)))
+
+        self.assertFalse(webbrowser.open.called)
+
+        # 5. couldn't load version
+        version_info = {}
+        logging.error = MagicMock()
+        spy_status_update = QtSignalSpy(self.manager, self.manager.communicate.statusBarUpdateSignal)
+
+        self.manager.processVersion(version_info)
+
+        # Retrieve and compare arguments of the mocked call
+        message = "guiframe: could not get latest application version number"
+        args, _ = logging.error.call_args
+        self.assertIn(message, args[0])
+
+        # Check the signal message
+        message = 'Could not connect to the application server.'
+        self.assertIn(message, str(spy_status_update.signal(index=0)))
+
     def testActions(self):
         """
@@ -66,14 +180,66 @@
         """
         # Mock the system file open method
-        QFileDialog.getOpenFileName = MagicMock(return_value=None)
+        QFileDialog.getOpenFileNames = MagicMock(return_value=None)
 
         # invoke the action
+        self.manager.actionLoadData()
 
         # Test the getOpenFileName() dialog called once
-        #self.assertTrue(QtGui.QFileDialog.getOpenFileName.called)
-        #QtGui.QFileDialog.getOpenFileName.assert_called_once()
+        self.assertTrue(QFileDialog.getOpenFileNames.called)
         
-
-    # test each action separately
+    def testActionDocumentation(self):
+        """
+        Menu Help/Documentation
+        """
+        #Mock the QWebView method
+        QWebView.show = MagicMock()
+
+        # Assure the filename is correct
+        self.assertIn("index.html", self.manager._helpLocation)
+
+        # Invoke the action
+        self.manager.actionDocumentation()
+
+        # Check if show() got called
+        self.assertTrue(QWebView.show.called)
+
+    def testActionTutorial(self):
+        """
+        Menu Help/Tutorial
+        """
+        # Mock subprocess.Popen
+        subprocess.Popen = MagicMock()
+
+        tested_location = self.manager._tutorialLocation
+
+        # Assure the filename is correct
+        self.assertIn("Tutorial.pdf", tested_location)
+
+        # Invoke the action
+        self.manager.actionTutorial()
+
+        # Check if popen() got called
+        self.assertTrue(subprocess.Popen.called)
+
+        #Check the popen() call arguments
+        subprocess.Popen.assert_called_with([tested_location], shell=True)
+
+    def testActionAcknowledge(self):
+        """
+        Menu Help/Acknowledge
+        """
+        pass
+
+    def testActionCheck_for_update(self):
+        """
+        Menu Help/Check for update
+        """
+        # Just make sure checkUpdate is called.
+        self.manager.checkUpdate = MagicMock()
+
+        self.manager.actionCheck_for_update()
+
+        self.assertTrue(self.manager.checkUpdate.called)
+             
        
 if __name__ == "__main__":
Index: src/sas/qtgui/UnitTesting/MainWindowTest.py
===================================================================
--- src/sas/qtgui/UnitTesting/MainWindowTest.py	(revision f721030e66e61dc6279aa8e024da03b25f8e0d42)
+++ src/sas/qtgui/UnitTesting/MainWindowTest.py	(revision 9e426c11367c4fe13f88ce18932880794884e04f)
@@ -2,7 +2,7 @@
 import unittest
 
-from PyQt4.QtGui import *
-from PyQt4.QtTest import QTest
-from PyQt4.QtCore import *
+from PyQt4 import QtGui
+from PyQt4 import QtTest
+from PyQt4 import QtCore
 from mock import MagicMock
 
@@ -11,28 +11,41 @@
 from MainWindow import SplashScreen
 
-app = QApplication(sys.argv)
+app = QtGui.QApplication(sys.argv)
 
 class MainWindowTest(unittest.TestCase):
-    '''Test the Main Window GUI'''
+    """Test the Main Window GUI"""
     def setUp(self):
-        '''Create the GUI'''
+        """Create the GUI"""
 
         self.widget = MainSasViewWindow(None)
 
     def tearDown(self):
-        '''Destroy the GUI'''
-        self.widget.close()
+        """Destroy the GUI"""
         self.widget = None
 
     def testDefaults(self):
-        '''Test the GUI in its default state'''
-        self.assertIsInstance(self.widget, QMainWindow)
-        self.assertIsInstance(self.widget.centralWidget(), QWorkspace)
+        """Test the GUI in its default state"""
+        self.assertIsInstance(self.widget, QtGui.QMainWindow)
+        self.assertIsInstance(self.widget.centralWidget(), QtGui.QWorkspace)
         
     def testSplashScreen(self):
+        """ Test the splash screen """
+        splash = SplashScreen()
+        self.assertIsInstance(splash, QtGui.QSplashScreen)
+
+    def testExit(self):
         """
+        Test that the custom exit method is called on shutdown
         """
-        splash = SplashScreen()
-        self.assertIsInstance(splash, QSplashScreen)
+        # Must mask sys.exit, otherwise the whole testing process stops.
+        sys.exit = MagicMock()
+        QtGui.QMessageBox.question = MagicMock(return_value=QtGui.QMessageBox.Yes)
+
+        # Open, then close the main window
+        tmp_main = MainSasViewWindow(None)
+        tmp_main.close()
+
+        # See that the MessageBox method got called
+        self.assertTrue(QtGui.QMessageBox.question.called)
        
 if __name__ == "__main__":
