Index: build_tools/dmgpack.sh
===================================================================
--- build_tools/dmgpack.sh	(revision 369ac54e92fd700fe5ef6cba0597f8f6d6b6c6fd)
+++ build_tools/dmgpack.sh	(revision 369ac54e92fd700fe5ef6cba0597f8f6d6b6c6fd)
@@ -0,0 +1,65 @@
+#! /bin/bash
+
+# dmgpack volume [file|dir]+
+#
+#    Copy a group of files/directories to a compressed disk image.
+#    The resulting image is stored in volume.dmg.
+#
+#    Files are copied with 'ditto' to preserve resource forks.  For
+#    convenience we also call FixupResourceForks after copying.  This
+#    allows you to use /Developer/Tools/SplitFork on your tree and 
+#    manipulate it with CVS, tar, etc.  Don't forget the -kb option 
+#    when adding or committing app and ._app files to CVS!
+#
+#    This command will fail if a volume of the given name is already
+#    mounted.  It could also fail if the size of the resource forks
+#    is large compared to the size of the data forks. Change the
+#    scale factor internally from 11/10 to a more appropriate number
+#    if it complains it is running out of space.
+#
+#    It is possible to add a license agreement to a dmg file.  See
+#    the "Software License Agreements for UDIFs" sdk available at
+#    http://developer.apple.com/sdk/index.html
+
+test $# -lt 2 && echo "usage: $0 diskname [file|dir]+" && exit 1
+#set -x
+NAME="${1%.dmg}" ; shift
+DISK=/tmp/dmgpack$$.dmg
+COMPRESSED="$NAME.dmg"
+VOLUME="$NAME"
+
+# compute needed image size; scale it by 10%
+SIZE=$(du -ck "$@" | tail -1 | sed -e 's/ *total//')
+SIZE=$(echo $SIZE*11/10 | bc)
+test $SIZE -lt 4200 && SIZE=4200
+
+# create the disk
+rm -f $DISK
+hdiutil create -size ${SIZE}k $DISK -layout NONE
+
+# create a file system on the disk; last line of output is
+# the device on which the disk was attached.
+DEVICE=$(hdiutil attach $DISK -nomount | tail -1)
+newfs_hfs -v "$VOLUME" $DEVICE
+
+# mount the file system
+mkdir $DISK-mount
+mount -t hfs $DEVICE $DISK-mount || (echo "mount $DISK-mount failed" && exit 1)
+
+# copy stuff to the disk and fixup resource forks
+for f in "$@"; do 
+    f=${f%/}		;# strip trailing /
+    dest="$DISK-mount/${f##*/}"
+    ditto -rsrc "$f" "$dest" 
+    test -d "$f" && /System/Library/CoreServices/FixupResourceForks "$dest"
+done
+
+# eject the disk
+umount $DISK-mount
+rmdir $DISK-mount
+hdiutil eject $DEVICE
+
+# compress the disk and make it read only
+rm -f "$COMPRESSED"
+hdiutil convert -format UDZO $DISK -imagekey zlib-level=9 -o "$COMPRESSED"
+rm -f $DISK
Index: build_tools/jenkins_osx_build.sh
===================================================================
--- build_tools/jenkins_osx_build.sh	(revision 460f5f28b60461087d1144a7e83ae444de6b09e4)
+++ build_tools/jenkins_osx_build.sh	(revision e9e3e38b882d3d5b555083662d2209607426c67f)
@@ -46,4 +46,4 @@
 python setup_mac.py py2app
 
-cd $WORKSPACE/sasview/dist
-tar -czf `python -c "import pkg_resources;print '%s.tar.gz' % pkg_resources.get_distribution('sasview').egg_name()"` sasview.app
+#cd $WORKSPACE/sasview/dist
+#tar -czf `python -c "import pkg_resources;print '%s.tar.gz SasView-%s.app' % (pkg_resources.get_distribution('sasview').egg_name(),pkg_resources.get_distribution('sasview').version)"`
Index: sasview.latestversion
===================================================================
--- sasview.latestversion	(revision 0ea31caa7c7dff8f23817dfa04e8be1d9dd3f8d8)
+++ sasview.latestversion	(revision 9533593bd68a5d03ddc7e4bfede0191634e13336)
@@ -1,1 +1,1 @@
-3.1.0
+3.1.1
Index: sasview/README.txt
===================================================================
--- sasview/README.txt	(revision 8bea15191a52dbae9314bf9d5df83190bd0b98fa)
+++ sasview/README.txt	(revision 9533593bd68a5d03ddc7e4bfede0191634e13336)
@@ -4,4 +4,9 @@
 1- Features
 ===========
+
+   - New in Version 3.1.1
+     --------------------
+     - Fixes bug #457 that prevented SasView from starting if the user was not
+       connected to the internet, or was behind a proxy server.
 
    - New in Version 3.1.0
@@ -302,4 +307,8 @@
           different browser and set that as your default browser. Issues have
           been noted with Internet Explorer 11.
+        - Check for Updates may fail (with the status bar message ' Cannot 
+          connect to the application server') if your internet connection uses 
+          a proxy server. Tested resolutions for this are described on the 
+          website FAQ.
         - The copy and paste functions (^C, ^V) in the batch mode results grid
           require two clicks: one to select the cell and a second to select the
Index: sasview/__init__.py
===================================================================
--- sasview/__init__.py	(revision bc84fa7ee20ffc3ec40239d645a48f79863db33d)
+++ sasview/__init__.py	(revision 9533593bd68a5d03ddc7e4bfede0191634e13336)
@@ -1,2 +1,2 @@
-__version__ = "3.1.0"
+__version__ = "3.1.1"
 __build__ = "1"
Index: sasview/local_config.py
===================================================================
--- sasview/local_config.py	(revision 5846bb5eebffb424f9ff395021847a922503ed7a)
+++ sasview/local_config.py	(revision 957af0dc596ff456a7b4745fe74937a9cea56f8f)
@@ -13,7 +13,5 @@
 __build__ = sas.sasview.__build__
 __download_page__ = 'https://github.com/SasView/sasview/releases'
-__update_URL__ = ['raw.githubusercontent.com',
-                  '/SasView/sasview/master/sasview.latestversion']
-
+__update_URL__ = 'http://www.sasview.org/latestversion.json'
 
 # Debug message flag
@@ -131,4 +129,7 @@
 DEFAULT_PERSPECTIVE = 'None'
 
+# Time out for updating sasview
+UPDATE_TIMEOUT = 2
+
 def printEVT(message):
     if __EVT_DEBUG__:
Index: sasview/setup_mac.py
===================================================================
--- sasview/setup_mac.py	(revision 018582fab454a9dec3a4a7c811c9d49d1495e95a)
+++ sasview/setup_mac.py	(revision 49cd7122b6a4b227afe01531b2ebf4c8508aebf2)
@@ -116,4 +116,11 @@
                                    CFBundleTypeRole="Shell" )],)
 
+#Get version - NB nasty hack. Need to find correct way to give path to installed sasview (AJJ)
+import __init__ as sasviewver
+
+VERSION = sasviewver.__version__
+APPNAME = "SasView "+VERSION
+DMGNAME = "SasView-"+VERSION
+
 APP = ['sasview.py']
 DATA_FILES += ['images','test','media']
@@ -133,5 +140,5 @@
            }
 setup(
-    name="sasview",
+    name=APPNAME,
     app=APP,
     data_files=DATA_FILES,
@@ -140,2 +147,9 @@
     setup_requires=['py2app'],
 )
+
+#Build dmg
+DMG="dist/%s.dmg"%DMGNAME
+if os.path.exists(DMG): os.unlink(DMG)
+os.system('cd dist && ../../build_tools/dmgpack.sh "%s" "%s.app"'%(DMGNAME,APPNAME))
+os.system('chmod a+r "%s"'%DMG)
+
Index: src/sas/guiframe/config.py
===================================================================
--- src/sas/guiframe/config.py	(revision 5846bb5eebffb424f9ff395021847a922503ed7a)
+++ src/sas/guiframe/config.py	(revision 9989a6a054cbc467449d53ad28bf14b305e61ede)
@@ -10,6 +10,5 @@
 __build__ = '1'
 __download_page__ = 'https://github.com/SasView/sasview/releases'
-__update_URL__ = ['raw.githubusercontent.com',
-                  '/SasView/sasview/master/sasview.latestversion']
+__update_URL__ = 'http://www.sasview.org/latestversion.json'
 
 
Index: src/sas/guiframe/data_processor.py
===================================================================
--- src/sas/guiframe/data_processor.py	(revision e54dbc3e09fa34ae993dfe14522c13c8bb50e315)
+++ src/sas/guiframe/data_processor.py	(revision 44d20afb283734cce1a7aef490219c0398d11978)
@@ -1,4 +1,16 @@
 """
-Implement grid used to store data
+Implement grid used to store results of a batch fit.
+
+This is in Guiframe rather than fitting which is probably where it should be.
+Actually could be a generic framework implemented in fit gui module.  At this
+point however there this grid behaves independently of the fitting panel and
+only knows about information sent to it but not about the fits or fit panel and
+thus cannot feed back to the fitting panel.  This could change in the future.
+
+The organization of the classes goes as:
+
+.. image::  ../../user/guiframe/BatchGridClassLayout.png
+   :align:   center
+
 """
 import wx
@@ -26,7 +38,9 @@
     """
     Object describing a cell in  the grid.
-
     """
     def __init__(self):
+        """
+        Initialize attributes of class (label, value, col, row, object)
+        """
         self.label = ""
         self.value = None
@@ -39,7 +53,10 @@
     """
     Return a dictionary of column label and index or row selected
+
     :param sentence: String to parse
     :param list: list of columns label
+    :returns: col_dict
     """
+
     p2 = re.compile(r'\d+')
     p = re.compile(r'[\+\-\*\%\/]')
@@ -81,5 +98,16 @@
 
 class SPanel(ScrolledPanel):
+    """
+    ensure proper scrolling of GridPanel 
+    
+    Adds a SetupScrolling call to the normal ScrolledPanel init.    
+    GridPanel then subclasses this class
+    
+    """
     def __init__(self, parent, *args, **kwds):
+        """
+        initialize ScrolledPanel then force a call to SetupScrolling
+
+        """
         ScrolledPanel.__init__(self, parent, *args, **kwds)
         self.SetupScrolling()
@@ -87,12 +115,56 @@
 
 class GridCellEditor(sheet.CCellEditor):
-    """ Custom cell editor """
+    """
+    Custom cell editor
+
+    This subclasses the sheet.CCellEditor (itself a subclass of
+    grid.GridCellEditor) in order to override two of its methods:
+    PaintBackrgound and EndEdit.
+    
+    This is necessary as the sheet module is broken in wx 3.0.2 and
+    improperly subclasses grid.GridCellEditor
+    """
     def __init__(self, grid):
+        """
+        Override of CCellEditor init. Runs the grid.GridCellEditor init code
+        """
         super(GridCellEditor, self).__init__(grid)
 
+    def PaintBackground(self, dc, rect, attr):
+        """
+        Overrides wx.sheet.CCellEditor.PaintBackground which incorrectly calls
+        the base class method.
+
+        In wx3.0 all paint objects must explicitly
+        have a wxPaintDC (Device Context) object.  Thus the paint event which
+        generates a call to this method provides such a DC object and the
+        base class in grid expects to receive that object.  sheet was apparently
+        not updated to reflect this and hence fails.  This could thus
+        become obsolete in a future bug fix of wxPython.
+
+        Apart from adding a dc variable in the list of arguments in the def
+        and in the call to the base class the rest of this method is copied
+        as is from sheet.CCellEditor.PaintBackground
+
+        **From original GridCellEditor docs:**
+
+        Draws the part of the cell not occupied by the edit control.  The
+        base class version just fills it with background colour from the
+        attribute.
+
+        NOTE: There is no need to override this if you don't need
+        to do something out of the ordinary.
+
+        :param dc: the wxDC object for the paint
+        """
+        # Call base class method.
+        DC = dc
+        super(sheet.CCellEditor,self).PaintBackground(DC, rect, attr)
+
     def EndEdit(self, row, col, grid, previous):
-        """ 
-            Commit editing the current cell. Returns True if the value has changed.
-            @param previous: previous value in the cell
+        """
+        Commit editing the current cell. Returns True if the value has changed.
+
+        :param previous: previous value in the cell
         """
         changed = False                             # Assume value not changed
@@ -108,10 +180,18 @@
 class GridPage(sheet.CSheet):
     """
+    Class that receives the results of a batch fit.
+
+    GridPage displays the received results in a wx.grid using sheet.  This is
+    then used by GridPanel and GridFrame to present the full GUI.
     """
     def __init__(self, parent, panel=None):
         """
+        Initialize
+
+        Initialize all the attributes of GridPage, and the events. include
+        the init stuff from sheet.CSheet as well.
         """
         #sheet.CSheet.__init__(self, parent)
-        
+
         # The following is the __init__ from CSheet. ##########################
         # We re-write it here because the class is broken in wx 3.0,
@@ -139,13 +219,24 @@
 
         # Sink events
+        self.Bind(wx.grid.EVT_GRID_RANGE_SELECT, self.OnRangeSelect)
+        self.Bind(wx.grid.EVT_GRID_ROW_SIZE, self.OnRowSize)
+        self.Bind(wx.grid.EVT_GRID_COL_SIZE, self.OnColSize)
+        self.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.OnGridSelectCell)
+        # NOTE: the following bind to standard sheet methods that are
+        # overriden in this subclassn - actually we have currently
+        # disabled the on_context_menu that would override the OnRightClick
+        self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnCellChange)
         self.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnLeftClick)
         self.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK, self.OnRightClick)
         #self.Bind(wx.grid.EVT_GRID_CELL_LEFT_DCLICK, self.OnLeftDoubleClick)
-        self.Bind(wx.grid.EVT_GRID_RANGE_SELECT, self.OnRangeSelect)
-        self.Bind(wx.grid.EVT_GRID_ROW_SIZE, self.OnRowSize)
-        self.Bind(wx.grid.EVT_GRID_COL_SIZE, self.OnColSize)
-        self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnCellChange)
-        self.Bind(wx.grid.EVT_GRID_SELECT_CELL, self.OnGridSelectCell)
         # This ends the __init__ section for CSheet. ##########################
+
+
+
+        # The following events must be bound even if CSheet is working 
+        # properly and does not need the above re-implementation of the
+        # CSheet init method.  Basically these override any intrinsic binding
+        self.Bind(wx.grid.EVT_GRID_LABEL_RIGHT_CLICK, self.on_right_click)
+        self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.on_left_click)
 
         self.AdjustScrollbars()
@@ -187,4 +278,7 @@
         if self.GetNumberCols() > 0:
             self.default_col_width = self.GetColSize(0)
+        # We have moved these to the top of the init section with the
+        # rest of the grid event bindings from the sheet init when
+        # appropriate
         #self.Bind(wx.grid.EVT_GRID_LABEL_LEFT_CLICK, self.on_left_click)
         #self.Bind(wx.grid.EVT_GRID_LABEL_RIGHT_CLICK, self.on_right_click)
@@ -194,9 +288,21 @@
 
     def OnLeftClick(self, event):
+        """
+        Overrides sheet.CSheet.OnLefClick.
+
+        Processes when a cell is selected by left clicking on that cell. First
+        process the base Sheet method then the current class specific method
+        """
         sheet.CSheet.OnLeftClick(self, event)
         self.on_selected_cell(event)
-        
-    def on_edit_cell(self, event):
-        """
+
+
+    def OnCellChange(self, event):
+        """
+        Overrides sheet.CSheet.OnCellChange.  
+
+        Processes when a cell has been edited by a cell editor. Checks for the
+        edited row being outside the max row to use attribute and if so updates
+        the last row.  Then calls the base handler using skip.
         """
         row, _ = event.GetRow(), event.GetCol()
@@ -209,6 +315,9 @@
     def on_selected_cell(self, event):
         """
-        Handler catching cell selection
-        """
+        Handler catching cell selection.
+
+        Called after calling base 'on left click' method.
+        """
+
         flag = event.CmdDown() or event.ControlDown()
         flag_shift = event.ShiftDown()
@@ -280,6 +389,12 @@
     def on_left_click(self, event):
         """
-        Catch the left click on label mouse event
-        """
+        Is triggered when the left mouse button is clicked while the mouse
+        is hovering over the column 'label.'
+
+        This processes the information on the selected column: the column name
+        (in row 0 of column) and the range of cells with a valid value to be
+        used by the GridPanel set_axis methods.
+        """
+
         flag = event.CmdDown() or event.ControlDown()
 
@@ -324,6 +439,16 @@
     def on_right_click(self, event):
         """
-        Catch the right click mouse
-        """
+        Is triggered when the right mouse button is clicked while the mouse
+        is hovering over the column 'label.'
+
+        This brings up a context menu that allows the deletion of the column,
+        or the insertion of a new column either to the right or left of the
+        current column.  If inserting a new column can insert a blank column or
+        choose a number of hidden columns.  By default all the error parameters
+        are in hidden columns so as to save space on the grid.  Also any other
+        intrinsic variables stored with the data such as Temperature, pressure,
+        time etc can be used to populate this menu.
+        """
+
         col = event.GetCol()
         row = event.GetRow()
@@ -360,5 +485,8 @@
     def insert_col_menu(self, menu, label, window):
         """
-        """
+        method called to populate the 'insert column before current column'
+        submenu.
+        """
+
         if self.data is None:
             return
@@ -380,5 +508,8 @@
     def insert_after_col_menu(self, menu, label, window):
         """
-        """
+        Method called to populate the 'insert column after current column'
+        submenu
+        """
+
         if self.data is None:
             return
@@ -401,5 +532,8 @@
     def on_remove_column(self, event=None):
         """
-        """
+        Called when user chooses remove from the column right click menu
+        Checks the columnn exists then calls the remove_column method
+        """
+
         if self.selected_cols is not None or len(self.selected_cols) > 0:
             col = self.selected_cols[0]
@@ -408,6 +542,7 @@
     def remove_column(self, col, numCols=1):
         """
-        Remove column to the current grid
-        """
+        Remove the col column from the current grid
+        """
+
         # add data to the grid    
         row = 0
@@ -429,5 +564,13 @@
     def on_insert_column(self, event):
         """
-        """
+        Called when user chooses insert 'column before' submenu
+        of the column context menu obtained when right clicking on a given
+        column header.
+
+        Sets up to insert column into the current grid before the current
+        highlighted column location and sets up what to populate that column
+        with.  Then calls insert_column method to actually do the insertion. 
+        """
+
         if self.selected_cols is not None or len(self.selected_cols) > 0:
             col = self.selected_cols[0]
@@ -442,6 +585,13 @@
     def on_insert_after_column(self, event):
         """
-        Insert the given column after the highlighted column
-        """
+        Called when user chooses insert 'column after' submenu
+        of the column context menu obtained when right clicking on a given
+        column header.
+
+        Sets up to insert column into the current grid after the current
+        highlighted column location and sets up what to populate that column
+        with.  Then calls insert_column method to actually do the insertion. 
+        """
+
         if self.selected_cols is not None or len(self.selected_cols) > 0:
             col = self.selected_cols[0] + 1
@@ -455,5 +605,8 @@
     def insert_column(self, col, col_name):
         """
-        """
+        Insert column at position col with data[col_name] into the current
+        grid.
+        """
+
         row = 0
         self.InsertCols(pos=col, numCols=1, updateLabels=True)
@@ -477,10 +630,14 @@
     def on_set_x_axis(self, event):
         """
-        """
+        Just calls the panel version of the method
+        """
+
         self.panel.set_xaxis(x=self.axis_value, label=self.axis_label)
 
     def on_set_y_axis(self, event):
         """
-        """
+        Just calls the panel version of the method
+        """
+
         self.panel.set_yaxis(y=self.axis_value, label=self.axis_label)
 
@@ -488,7 +645,9 @@
         """
         Add data to the grid
+
         :param data_inputs: data to use from the context menu of the grid
-        :param data_ouputs: default columns deplayed
-        """
+        :param data_ouputs: default columns displayed
+        """
+
         self.file_name = file_name
         self.details = details
@@ -527,4 +686,5 @@
         Set the values in grids
         """
+
         # add data to the grid
         row = 0
@@ -562,4 +722,5 @@
         Return value contained in the grid
         """
+
         grid_view = {}
         for col in xrange(self.GetNumberCols()):
@@ -584,6 +745,13 @@
     def onContextMenu(self, event):
         """
-        Default context menu
-        """
+        Method to handle cell right click context menu. 
+
+        THIS METHOD IS NOT CURRENTLY USED.  It is designed to provide a
+        cell pop up context by right clicking on a cell and gives the
+        option to cut, paste, and clear. This will probably be removed in
+        future versions and is being superceded by more traditional cut and
+        paste options.
+        """
+
         wx_id = wx.NewId()
         c_menu = wx.Menu()
@@ -620,12 +788,24 @@
     def on_copy(self, event):
         """
-        On copy event from the contextmenu
-        """
+        Called when copy is chosen from cell right click context menu
+
+        THIS METHOD IS NOT CURRENTLY USED.  it is part of right click cell
+        context menu which is being removed. This will probably be removed in
+        future versions and is being superceded by more traditional cut and
+        paste options
+        """
+
         self.Copy()
 
     def on_paste(self, event):
         """
-        On paste event from the contextmenu
-        """
+        Called when paste is chosen from cell right click context menu
+
+        THIS METHOD IS NOT CURRENTLY USED.  it is part of right click cell
+        context menu which is being removed. This will probably be removed in
+        future versions and is being superceded by more traditional cut and
+        paste options
+        """
+
         if self.data == None:
             self.data = {}
@@ -636,6 +816,12 @@
     def on_clear(self, event):
         """
-        Clear the cells selected
-        """
+        Called when clear cell is chosen from cell right click context menu
+
+        THIS METHOD IS NOT CURRENTLY USED.  it is part of right click cell
+        context menu which is being removed. This will probably be removed in
+        future versions and is being superceded by more traditional cut and
+        paste options
+        """
+
         self.Clear()
 
@@ -646,4 +832,5 @@
     ## Title to appear on top of the window
     """
+
     window_caption = "Notebook "
 
@@ -682,7 +869,8 @@
     def enable_close_button(self):
         """
-        display the close button on tab for more than 1 tabs else remove the
-        close button
-        """
+        display the close button on the tab if more than 1 tab exits.
+        Otherwise remove the close button
+        """
+
         if self.GetPageCount() <= 1:
             style = self.GetWindowStyleFlag()
@@ -700,7 +888,8 @@
     def on_edit_axis(self):
         """
-        Return the select cell of a given selected column. Check that all cells
-        are from the same column
-        """
+        Return the select cell range from a given selected column. Checks that
+        all cells are from the same column
+        """
+
         pos = self.GetSelection()
         grid = self.GetPage(pos)
@@ -732,4 +921,5 @@
         Add highlight rows
         """
+
         pos = self.GetSelection()
         grid = self.GetPage(pos)
@@ -759,6 +949,7 @@
     def get_column_labels(self):
         """
-        return dictionary of columns labels of the current page
-        """
+        return dictionary of columns labels on the current page
+        """
+
         pos = self.GetSelection()
         grid = self.GetPage(pos)
@@ -773,7 +964,7 @@
         """
         Receive a list of cells and  create a string presenting the selected
-        cells.
+        cells that can be used as data for one axis of a plot.
+
         :param cell_list: list of tuple
-
         """
         pos = self.GetSelection()
@@ -853,4 +1044,5 @@
         close the page
         """
+
         if self.GetPageCount() == 1:
             event.Veto()
@@ -858,4 +1050,6 @@
 
     def set_data(self, data_inputs, data_outputs, details="", file_name=None):
+        """
+        """
         if data_outputs is None or data_outputs == {}:
             return
@@ -880,6 +1074,8 @@
     def get_odered_results(self, inputs, outputs=None):
         """
-        Get ordered the results
-        """
+        Order a list of 'inputs.' Used to sort rows and columns to present
+        in batch results grid.
+        """
+
         # Let's re-order the data from the keys in 'Data' name.
         if outputs == None:
@@ -914,4 +1110,7 @@
         Append a new column to the grid
         """
+
+        # I Believe this is no longer used now that we have removed the 
+        # edit menu from the menubar - PDB July 12, 2015
         pos = self.GetSelection()
         grid = self.GetPage(pos)
@@ -922,4 +1121,6 @@
         Remove the selected column from the grid
         """
+        # I Believe this is no longer used now that we have removed the 
+        # edit menu from the menubar - PDB July 12, 2015
         pos = self.GetSelection()
         grid = self.GetPage(pos)
@@ -927,6 +1128,15 @@
 
 class GridPanel(SPanel):
+    """
+    A ScrolledPanel class that contains the grid sheet as well as a number of
+    widgets to create interesting plots and buttons for help etc.
+    """
+
     def __init__(self, parent, data_inputs=None,
                  data_outputs=None, *args, **kwds):
+        """
+        Initialize the GridPanel
+        """
+
         SPanel.__init__(self, parent, *args, **kwds)
 
@@ -990,5 +1200,4 @@
     def get_plot_axis(self, col, list):
         """
-
         """
         axis = []
@@ -1015,6 +1224,8 @@
     def on_view(self, event):
         """
-        Get object represented buy the given cell and plot them.
-        """
+        Get object represented by the given cells and plot them.  Basically
+        plot the colum in y vs the column in x.
+        """
+
         pos = self.notebook.GetSelection()
         grid = self.notebook.GetPage(pos)
@@ -1096,4 +1307,5 @@
         Evaluate the contains of textcrtl and plot result
         """
+
         pos = self.notebook.GetSelection()
         grid = self.notebook.GetPage(pos)
@@ -1203,6 +1415,7 @@
         running "file:///...."
 
-    :param evt: Triggers on clicking the help button
-    """
+        :param evt: Triggers on clicking the help button
+        """
+
         #import documentation window here to avoid circular imports
         #if put at top of file with rest of imports.
@@ -1218,4 +1431,5 @@
         Get sentence from dict
         """
+
         for tok, (col_name, list) in dict.iteritems():
             col = column_names[col_name]
@@ -1230,6 +1444,8 @@
     def layout_grid(self):
         """
-        Draw the area related to the grid
-        """
+        Draw the area related to the grid by adding it as the first element
+        in the panel's grid_sizer
+        """
+
         self.notebook = Notebook(parent=self)
         self.notebook.set_data(self._data_inputs, self._data_outputs)
@@ -1238,6 +1454,8 @@
     def layout_plotting_area(self):
         """
-        Draw area containing options to plot
-        """
+        Add the area containing all the plot options, buttons etc to a plotting
+        area sizer to later be added to the top level grid_sizer
+        """
+
         view_description = wx.StaticBox(self, -1, 'Plot Fits/Residuals')
         note = "To plot the fits (or residuals), click the 'View Fits' button"
@@ -1281,5 +1499,5 @@
                                    (self.plot_button, 0,
                                     wx.LEFT | wx.TOP | wx.BOTTOM, 12),
-                                   (self.help_button,0, 
+                                   (self.help_button,0,
                                     wx.LEFT | wx.TOP | wx.BOTTOM, 12)])
 
@@ -1316,4 +1534,5 @@
         Get the selected column on  the visible grid and set values for axis
         """
+
         try:
             cell_list = self.notebook.on_edit_axis()
@@ -1335,7 +1554,8 @@
         Receive a list of cells and  create a string presenting the selected
         cells.
+
         :param cell_list: list of tuple
-
-        """
+        """
+
         if self.notebook is not None:
             return self.notebook.create_axis_label(cell_list)
@@ -1345,4 +1565,5 @@
         get controls to modify
         """
+
         if label != None:
             tcrtl_label.SetValue(str(label))
@@ -1353,4 +1574,6 @@
         """
         """
+        # I Believe this is no longer used now that we have removed the
+        # edit menu from the menubar - PDB July 12, 2015
         if self.notebook is not None:
             self.notebook.add_column()
@@ -1359,4 +1582,6 @@
         """
         """
+        # I Believe this is no longer used now that we have removed the
+        # edit menu from the menubar - PDB July 12, 2015
         if self.notebook is not None:
             self.notebook.on_remove_column()
@@ -1364,6 +1589,14 @@
 
 class GridFrame(wx.Frame):
+    """
+    The main wx.Frame for the batch results grid
+    """
+
     def __init__(self, parent=None, data_inputs=None, data_outputs=None, id=-1,
-                 title="Grid Window", size=(800, 500)):
+                 title="Batch Fitting Results Panel", size=(800, 500)):
+        """
+        Initialize the Frame
+        """
+
         wx.Frame.__init__(self, parent=parent, id=id, title=title, size=size)
         self.parent = parent
@@ -1389,11 +1622,24 @@
         wx.EVT_MENU(self, self.save_menu.GetId(), self.on_save_page)
 
-        # To add the edit menu, call add_edit_menu() here.
-        self.edit = None
+        # We need to grab a WxMenu handle here, otherwise the next one to grab
+        # the handle will be treated as the Edit Menu handle when checking in
+        # on_menu_open event handler and thus raise an exception when it hits an 
+        # unitialized object.  Alternative is to comment out that whole section
+        # in on_menu_open, but that would make it more difficult to undo the
+        # hidding of the menu.   PDB  July 12, 2015.
+        #
+        # To enable the Edit menubar comment out next line and uncomment the
+        # following line.
+        self.edit = wx.Menu()
+        #self.add_edit_menu()
+
         self.Bind(wx.EVT_MENU_OPEN, self.on_menu_open)
-        
         self.Bind(wx.EVT_CLOSE, self.on_close)
 
     def add_edit_menu(self, menubar):
+        """
+        populates the edit menu on the menubar.  Not activated as of SasView
+        3.1.0
+        """
         self.edit = wx.Menu()
 
@@ -1429,6 +1675,8 @@
     def on_copy(self, event):
         """
-        On Copy
-        """
+        On Copy from the Edit menu item on the menubar
+        """
+        # I Believe this is no longer used now that we have removed the 
+        # edit menu from the menubar - PDB July 12, 2015
         if event != None:
             event.Skip()
@@ -1439,6 +1687,8 @@
     def on_paste(self, event):
         """
-        On Paste
-        """
+        On Paste from the Edit menu item on the menubar
+        """
+        # I Believe this is no longer used now that we have removed the 
+        # edit menu from the menubar - PDB July 12, 2015
         if event != None:
             event.Skip()
@@ -1449,6 +1699,8 @@
     def on_clear(self, event):
         """
-        On Clear
-        """
+        On Clear from the Edit menu item on the menubar
+        """
+        # I Believe this is no longer used now that we have removed the 
+        # edit menu from the menubar - PDB July 12, 2015
         pos = self.panel.notebook.GetSelection()
         grid = self.panel.notebook.GetPage(pos)
@@ -1466,6 +1718,8 @@
     def on_remove_column(self, event):
         """
-        On remove column
-        """
+        On remove column from the Edit menu Item on the menubar
+        """
+        # I Believe this is no longer used now that we have removed the 
+        # edit menu from the menubar - PDB July 12, 2015
         pos = self.panel.notebook.GetSelection()
         grid = self.panel.notebook.GetPage(pos)
@@ -1535,5 +1789,10 @@
     def on_save_page(self, event):
         """
-        """
+        Saves data in grid to a csv file.
+
+        At this time only the columns displayed get saved.  Thus any error
+        bars not inserted before saving will not be saved in the file
+        """
+
         if self.parent is not None:
             pos = self.panel.notebook.GetSelection()
@@ -1566,6 +1825,7 @@
     def on_open(self, event):
         """
-        Open file containg batch result
-        """
+        Open file containing batch result
+        """
+
         if self.parent is not None:
             self.parent.on_read_batch_tofile(self)
@@ -1575,4 +1835,5 @@
         open excel and display batch result in Excel
         """
+
         if self.parent is not None:
             pos = self.panel.notebook.GetSelection()
@@ -1625,8 +1886,11 @@
                  details="", *args, **kwds):
         """
+        Initialize dialog
+
         :param parent: Window instantiating this dialog
-        :param result: result to display in a grid or export to an external
+        :param result: result to display in a grid or export to an external\
                 application.
         """
+
         #kwds['style'] = wx.CAPTION|wx.SYSTEM_MENU
         wx.Frame.__init__(self, parent, *args, **kwds)
@@ -1651,4 +1915,5 @@
         Draw the content of the current dialog window
         """
+
         vbox = wx.BoxSizer(wx.VERTICAL)
         box_description = wx.StaticBox(self.panel, -1, str("Batch Outputs"))
@@ -1704,4 +1969,5 @@
         Get the user selection and display output to the selected application
         """
+
         if self.flag == 1:
             self.parent.open_with_localapp(data_inputs=self.data_inputs,
@@ -1715,4 +1981,5 @@
         close the Window
         """
+
         self.Close()
 
@@ -1721,5 +1988,4 @@
         Receive event and display data into third party application
         or save data to file.
-
         """
         if self.save_to_file.GetValue():
Index: src/sas/guiframe/documentation_window.py
===================================================================
--- src/sas/guiframe/documentation_window.py	(revision 7a508b6034b12b3845b63d1181489cc7ad8b0a89)
+++ src/sas/guiframe/documentation_window.py	(revision fb3f9af6b7f4c21e4835a63ed3f7428632d42bc2)
@@ -43,8 +43,8 @@
     (self, parent, dummy_id, path, url_instruction, title, size=(850, 540))
 
-    :param path: path to html file beginning AFTER /doc/ and ending in the
-    file.html
-    :param url_instructions: anchor string or other query e.g. '#MyAnchor
-    :param title - text to place in the title bar of the help panel
+    :param path: path to html file beginning AFTER /doc/ and ending in the\
+    file.html.
+    :param url_instructions: anchor string or other query e.g. '#MyAnchor'
+    :param title: text to place in the title bar of the help panel
     """
     def __init__(self, parent, dummy_id, path, url_instruction, title, size=(850, 540)):
Index: src/sas/guiframe/gui_manager.py
===================================================================
--- src/sas/guiframe/gui_manager.py	(revision 78f75d02db7f9a239d14f47da8aa9c7db4f134b5)
+++ src/sas/guiframe/gui_manager.py	(revision 957af0dc596ff456a7b4745fe74937a9cea56f8f)
@@ -27,5 +27,5 @@
 import urllib
 import urllib2
-
+import json
 
 from sas.guiframe.events import EVT_CATEGORY
@@ -46,5 +46,7 @@
 from sas.guiframe.CategoryManager import CategoryManager
 from sas.dataloader.loader import Loader
+from sas.guiframe.proxy import Connection
 from matplotlib import _pylab_helpers
+
 
 def get_app_dir():
@@ -52,4 +54,6 @@
         The application directory is the one where the default custom_config.py
         file resides.
+
+        :returns: app_path - the path to the applicatin directory
     """
     # First, try the directory of the executable we are running
@@ -68,5 +72,5 @@
 
     # Finally, try the directory of the sasview module
-    #TODO: gui_manager will have to know about sasview until we
+    # TODO: gui_manager will have to know about sasview until we
     # clean all these module variables and put them into a config class
     # that can be passed by sasview.py.
@@ -830,9 +834,9 @@
     def PushStatusText(self, *args, **kwds):
         """
-            FIXME: No message is passed. What is this supposed to do?
+        .. todo:: No message is passed. What is this supposed to do?
         """
         field = self.sb.get_msg_position()
         wx.Frame.PushStatusText(self, field=field,
-                                string="FIXME: PushStatusText called without text")
+                                string="FIXME - PushStatusText called without text")
 
     def add_perspective(self, plugin):
@@ -890,5 +894,5 @@
         :param dir: directory in which to look for plug-ins
 
-        :return: list of plug-ins
+        :returns: list of plug-ins
 
         """
@@ -937,5 +941,5 @@
                             file.close()
         except:
-            # Should raise and catch at a higher level and 
+            # Should raise and catch at a higher level and
             # display error on status bar
             logging.error(sys.exc_value)
@@ -984,5 +988,5 @@
 
         # Set up welcome panel
-        #TODO: this needs serious simplification
+        # TODO: this needs serious simplification
         if self.welcome_panel_class is not None:
             welcome_panel = MDIFrame(self, None, 'None', (100, 200))
@@ -1074,4 +1078,8 @@
     def onfreeze(self, theory_id):
         """
+        Saves theory/model and passes to data loader.
+
+        ..warning:: This seems to be the exact same code as the next
+        function called simply freeze. This probably needs fixing
         """
         data_state_list = self._data_manager.freeze(theory_id)
@@ -1085,4 +1093,8 @@
     def freeze(self, data_id, theory_id):
         """
+        Saves theory/model and passes to data loader.
+
+        ..warning:: This seems to be the exact same code as the next
+        function called simply freeze. This probably needs fixing
         """
         data_state_list = self._data_manager.freeze_theory(data_id=data_id,
@@ -1149,5 +1161,5 @@
         :param p: panel object to add to the AUI manager
 
-        :return: ID of the event associated with the new panel [int]
+        :returns: ID of the event associated with the new panel [int]
 
         """
@@ -1170,5 +1182,5 @@
         # Append nummber
         captions = self._get_plotpanel_captions()
-        #FIXME: Fix this aweful loop
+        # FIXME: Fix this awful loop
         while (1):
             caption = windowcaption + '%s' % str(self.graph_num)
@@ -2031,24 +2043,34 @@
         a call-back method when the current version number has been obtained.
         """
-        try:
-            req = urllib2.Request('https://github.com/SasView/sasview/releases/latest')
-            res = urllib2.urlopen(req)
-            get_url= res.geturl()
-            content = get_url.partition('/v')[2]
-            logging.info("connected to GitHub. sasview.latestversion = %s"
-                         % (content))
-        except:
-            msg = traceback.format_exc()
-            logging.info(msg)
-            logging.info("failed to connect to GitHub")
-            content = "0.0.0"
-
-        version = content.strip()
-        logging.info("Latest SasView version number: %s" % (version))
-        if len(re.findall('\d+\.\d+\.\d+$', version)) < 0:
-            content = "0.0.0"
-        self._process_version(content, standalone=event == None)
-
-    def _process_version(self, version, standalone=True):
+        version_info = {"version": "0.0.0"}
+        c = Connection(config.__update_URL__, config.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._process_version(version_info, standalone=event == None)    
+
+        
+        
+#         
+#         try:
+#             req = urllib2.Request(config.__update_URL__)
+#             res = urllib2.urlopen(req)
+#             content = res.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")
+#             version_info = {"version": "0.0.0"}
+#         self._process_version(version_info, standalone=event == None)
+
+    def _process_version(self, version_info, standalone=True):
         """
         Call-back method for the process of checking for updates.
@@ -2063,4 +2085,5 @@
         """
         try:
+            version = version_info["version"]
             if version == "0.0.0":
                 msg = "Could not connect to the application server."
@@ -2071,5 +2094,8 @@
                 if not standalone:
                     import webbrowser
-                    webbrowser.open(config.__download_page__)
+                    if "download_url" in version_info:
+                        webbrowser.open(version_info["download_url"])
+                    else:
+                        webbrowser.open(config.__download_page__)
                 else:
                     msg += "See the help menu to download it."
@@ -2435,5 +2461,6 @@
         """
         Save file as txt
-        :TODO: Refactor and remove this method. See TODO in _onSave.
+
+        .. todo:: Refactor and remove this method. See 'TODO' in _onSave.
         """
         if not path == None:
@@ -2863,5 +2890,5 @@
                     # Append nummber
                     inc = 1
-                    #FIXME: fix this terrible loop
+                    # FIXME: fix this terrible loop
                     while (1):
                         caption = new_caption + '_%s' % str(inc)
@@ -2886,5 +2913,5 @@
 
         :param name: window_name in AuiPaneInfo
-        :return: AuiPaneInfo of the name
+        :returns: AuiPaneInfo of the name
         """
         for panel in self.plot_panels.values():
@@ -3058,10 +3085,10 @@
                 pass
 
-        # Draw all panels 
+        # Draw all panels
         if count == 1:
             f_draw(self.schedule_full_draw_list[0])
         else:
             map(f_draw, self.schedule_full_draw_list)
-        # Reset the attr  
+        # Reset the attr
         if len(self.schedule_full_draw_list) == 0:
             self.set_schedule(False)
@@ -3104,5 +3131,6 @@
         Get window size
 
-        :return size: tuple
+        :returns: size
+        :rtype: tuple
         """
         width, height = self.GetSizeTuple()
@@ -3125,5 +3153,5 @@
             pass
 
-        # restart idle        
+        # restart idle
         self._redraw_idle(*args, **kwargs)
 
@@ -3133,5 +3161,5 @@
         Restart Idle
         """
-        # restart idle   
+        # restart idle
         self.idletimer.Restart(100 * TIME_FACTOR, *args, **kwargs)
 
@@ -3290,5 +3318,5 @@
         """
         is_maximized = False
-        # Get size of screen without 
+        # Get size of screen without
         for screenCount in range(wx.Display().GetCount()):
             screen = wx.Display(screenCount)
@@ -3307,5 +3335,5 @@
             customHeight = displayHeight * 0.9
         else:
-            # If the custom screen is bigger than the 
+            # If the custom screen is bigger than the
             # window screen than make maximum size
             if customWidth > displayWidth:
@@ -3405,4 +3433,8 @@
     def show_data_panel(self, action):
         """
+        Turns on the data panel
+
+        The the data panel is optional.  Most of its functions can be
+        performed from the menu bar and from the plots.
         """
         self.parent.show_data_panel(action)
Index: src/sas/guiframe/local_perspectives/plotting/Plotter1D.py
===================================================================
--- src/sas/guiframe/local_perspectives/plotting/Plotter1D.py	(revision b99a4552f37a4044c9efa7ced7eda5ed5176dc85)
+++ src/sas/guiframe/local_perspectives/plotting/Plotter1D.py	(revision 098f3d277d54e6ae4bae35ed0188be84b67fb171)
@@ -564,7 +564,4 @@
             self._slicerpop.Append(wx_id, '&Print Image', 'Print image ')
             wx.EVT_MENU(self, wx_id, self.onPrint)
-            wx_id = wx.NewId()
-            self._slicerpop.Append(wx_id, '&Print Preview', 'Print preview')
-            wx.EVT_MENU(self, wx_id, self.onPrinterPreview)
 
             wx_id = wx.NewId()
Index: src/sas/guiframe/local_perspectives/plotting/Plotter2D.py
===================================================================
--- src/sas/guiframe/local_perspectives/plotting/Plotter2D.py	(revision c039589ad31dec3058311cae229f7aa1dc56faf8)
+++ src/sas/guiframe/local_perspectives/plotting/Plotter2D.py	(revision 098f3d277d54e6ae4bae35ed0188be84b67fb171)
@@ -300,8 +300,4 @@
 
         wx_id = wx.NewId()
-        slicerpop.Append(wx_id, '&Print Preview', 'Print preview')
-        wx.EVT_MENU(self, wx_id, self.onPrinterPreview)
-
-        wx_id = wx.NewId()
         slicerpop.Append(wx_id, '&Copy to Clipboard', 'Copy to the clipboard')
         wx.EVT_MENU(self, wx_id, self.OnCopyFigureMenu)
Index: src/sas/guiframe/local_perspectives/plotting/SimplePlot.py
===================================================================
--- src/sas/guiframe/local_perspectives/plotting/SimplePlot.py	(revision b40ad402cdc9c4a7e69f4ce5a13e29b50b8242fc)
+++ src/sas/guiframe/local_perspectives/plotting/SimplePlot.py	(revision 098f3d277d54e6ae4bae35ed0188be84b67fb171)
@@ -58,8 +58,4 @@
         slicerpop.Append(wx_id, '&Print Image', 'Print image')
         wx.EVT_MENU(self, wx_id, self.onPrint)
-
-        wx_id = wx.NewId()
-        slicerpop.Append(wx_id, '&Print Preview', 'Print preview')
-        wx.EVT_MENU(self, wx_id, self.onPrinterPreview)
 
         wx_id = wx.NewId()
@@ -234,10 +230,4 @@
         wx.EVT_MENU(self, id, self.on_print_image)
 
-        id = wx.NewId()
-        item = wx.MenuItem(menu, id, "&Print Preview")
-        item.SetBitmap(preview_bmp)
-        menu.AppendItem(item)
-        wx.EVT_MENU(self, id, self.on_print_preview)
-
         menu.AppendSeparator()
         id = wx.NewId()
Index: src/sas/guiframe/proxy.py
===================================================================
--- src/sas/guiframe/proxy.py	(revision 957af0dc596ff456a7b4745fe74937a9cea56f8f)
+++ src/sas/guiframe/proxy.py	(revision 957af0dc596ff456a7b4745fe74937a9cea56f8f)
@@ -0,0 +1,158 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+import urllib2
+import sys
+import json
+import logging
+import re
+
+'''
+HTTP Proxy parser and Connection
+
+connect() function:
+    - auto detects proxy in windows, osx
+    - in ux systems, the http_proxy enviroment variable must be set
+    - if it fails, try to find the proxy.pac address.
+      - parses the file, and looks up for all possible proxies
+'''
+
+
+class Connection(object):
+
+    def __init__(self, url, timeout):
+        self.url = url
+        self.timeout = timeout
+
+    def _get_addresses_of_proxy_pac(self):
+        """
+        Return a list of possible auto proxy .pac files being used,
+        based on the system registry (win32) or system preferences (OSX).
+        @return: list of urls
+        """
+        pac_files = []
+        if sys.platform == 'win32':
+            try:
+                import _winreg as winreg  # used from python 2.0-2.6
+            except:
+                import winreg  # used from python 2.7 onwards
+            net = winreg.OpenKey(
+                winreg.HKEY_CURRENT_USER,
+                "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
+            )
+            n_subs, n_vals, last_mod = winreg.QueryInfoKey(net)
+            subkeys = {}
+            for i in range(n_vals):
+                this_name, this_val, this_type = winreg.EnumValue(net, i)
+                subkeys[this_name] = this_val
+            if 'AutoConfigURL' in subkeys.keys() and len(subkeys['AutoConfigURL']) > 0:
+                pac_files.append(subkeys['AutoConfigURL'])
+        elif sys.platform == 'darwin':
+            import plistlib
+            sys_prefs = plistlib.readPlist(
+                '/Library/Preferences/SystemConfiguration/preferences.plist')
+            networks = sys_prefs['NetworkServices']
+            # loop through each possible network (e.g. Ethernet, Airport...)
+            for network in networks.items():
+                # the first part is a long identifier
+                net_key, network = network
+                if 'ProxyAutoConfigURLString' in network['Proxies'].keys():
+                    pac_files.append(
+                        network['Proxies']['ProxyAutoConfigURLString'])
+        return list(set(pac_files))  # remove redundant ones
+
+    def _parse_proxy_pac(self, pac_urls_list):
+        '''
+        For every pac file url in pac_urls_list, it tryes to connect.
+        If the connection is successful parses the file in search for
+        http proxies.
+        @param pac_urls_list: List with urls for the pac files
+        @return: list with all found http proxies
+        '''
+        proxy_url_list = []
+        for this_pac_url in pac_urls_list:
+            logging.debug('Trying pac file (%s)...' % this_pac_url)
+            try:
+                response = urllib2.urlopen(
+                    this_pac_url, timeout=self.timeout)
+                logging.debug('Succeeded (%s)...' % this_pac_url)
+            except Exception:
+                logging.debug('Failled (%s)...' % this_pac_url)
+                continue
+            pacStr = response.read()
+            possProxies = re.findall(
+                r"PROXY\s([^\s;,:]+:[0-9]{1,5})[^0-9]", pacStr + '\n')
+            for thisPoss in possProxies:
+                prox_url = 'http://' + thisPoss
+                proxy_dic = {'http': prox_url}
+                proxy_url_list.append(proxy_dic)
+        return proxy_url_list
+
+    def _set_proxy(self,proxy_dic=None):
+        '''
+        Sets connection proxy.
+        if proxy_dic is None get's teh proxy from the system.
+        To disable autodetected proxy pass an empty dictionary: {}
+        @param proxy_dic: format: {'http': 'http://www.example.com:3128/'}               
+        '''
+        if proxy_dic is None:
+            # The default is to read the list of proxies from the environment variables <protocol>_proxy.
+            # If no proxy environment variables are set, then in a Windows environment proxy settings are
+            # obtained from the registry's Internet Settings section, and in a Mac OS X environment proxy
+            # information is retrieved from the OS X System Configuration
+            # Framework.
+            proxy = urllib2.ProxyHandler()
+        else:
+            # If proxies is given, it must be a dictionary mapping protocol names to
+            # URLs of proxies.
+            proxy = urllib2.ProxyHandler(proxy_dic)
+        opener = urllib2.build_opener(proxy)
+        urllib2.install_opener(opener)
+    
+    
+   
+    
+    def connect(self):
+        '''
+        Performs the request and gets a response from self.url
+        @return: response object from urllib2.urlopen
+        '''
+        req = urllib2.Request(self.url)
+        response = None
+        try:
+            logging.debug("Trying Direct connection to %s..."%self.url)
+            response = urllib2.urlopen(req, timeout=self.timeout)
+        except Exception, e:
+            logging.debug("Failed!")
+            logging.debug(e)
+            try:
+                logging.debug("Trying to use system proxy if it exists...")
+                self._set_proxy()
+                response = urllib2.urlopen(req, timeout=self.timeout)
+            except Exception, e:
+                logging.debug("Failed!")
+                logging.debug(e)
+                pac_urls = self._get_addresses_of_proxy_pac()
+                proxy_urls = self._parse_proxy_pac(pac_urls)
+                for proxy in proxy_urls:
+                    try:
+                        logging.debug("Trying to use the proxy %s found in proxy.pac configuration"%proxy)
+                        self._set_proxy(proxy)
+                        response = urllib2.urlopen(req, timeout=self.timeout)
+                    except Exception, e:
+                        logging.debug("Failed!")
+                        logging.debug(e)
+        if response is not None:
+            logging.debug("The connection to %s was successful."%self.url)
+        else:
+            logging.warning("Connection to %s failed..."%self.url)
+        return response
+
+
+if __name__ == "__main__":
+    from pprint import pprint
+    c = Connection()
+    response = c.connect()
+    if response is not None:
+        print 50 * '-'
+        content = json.loads(response.read().strip())
+        pprint(content)
Index: src/sas/guiframe/report_dialog.py
===================================================================
--- src/sas/guiframe/report_dialog.py	(revision e8bb5b62d717c7b44481a4b621030699e4efdaf4)
+++ src/sas/guiframe/report_dialog.py	(revision 098f3d277d54e6ae4bae35ed0188be84b67fb171)
@@ -66,10 +66,4 @@
         hbox.Add(button_close)
         button_close.SetFocus()
-
-        button_preview = wx.Button(self, wx.NewId(), "Preview")
-        button_preview.SetToolTipString("Print preview this report.")
-        button_preview.Bind(wx.EVT_BUTTON, self.onPreview,
-                            id=button_preview.GetId()) 
-        hbox.Add(button_preview)
 
         button_print = wx.Button(self, wx.NewId(), "Print")
Index: src/sas/models/CoreMultiShellModel.py
===================================================================
--- src/sas/models/CoreMultiShellModel.py	(revision ac7be54ccf932e813cbe6e41e05b682a1630a03e)
+++ src/sas/models/CoreMultiShellModel.py	(revision e0c16ce98473cdb3b4705e5df48c3cf15ac1b858)
@@ -53,6 +53,5 @@
         ## parameters with orientation: can be removed since there is no orientational params
         self._set_orientation_params()
-                
-        
+
     def _clone(self, obj):
         """
@@ -67,12 +66,11 @@
 
         return obj
-    
-    
+
     def _set_dispersion(self):
         """
         model dispersions
         Polydispersion should not be applied to s_model
-        """ 
-        ##set dispersion from model 
+        """
+        ##set dispersion from model
         for name , value in self.model.dispersion.iteritems():      
             nshell = 0
@@ -82,13 +80,13 @@
                     if name.split('_')[-1] == 'shell%s' % str(nshell):
                         self.dispersion[name] = value
-                    else: 
+                    else:
                         continue
             else:
                 self.dispersion[name] = value
-                
+
     def _set_orientation_params(self):
         """
         model orientation and magnetic parameters, same params for this model
-        """ 
+        """
         ##set dispersion from model 
         for param in self.model.orientation_params:     
@@ -104,10 +102,10 @@
                     self.orientation_params.append(param)
                     self.magnetic_params.append(param)
-                    continue                           
+                    continue
 
     def _set_params(self):
         """
         Concatenate the parameters of the model to create
-        this model parameters 
+        this model parameters
         """
         # rearrange the parameters for the given # of shells
@@ -128,18 +126,18 @@
             else:
                 self.params[name]= value
-            
+
         # set constrained values for the original model params
-        self._set_xtra_model_param()       
-  
+        self._set_xtra_model_param()
+
     def _set_details(self):
         """
         Concatenate details of the original model to create
-        this model details 
+        this model details
         """
         for name ,detail in self.model.details.iteritems():
             if name in self.params.iterkeys():
                 self.details[name]= detail
-            
-    
+
+
     def _set_xtra_model_param(self):
         """
@@ -163,13 +161,13 @@
                                 self.model.setParam(key, 0.0)
                         except: pass
-                     
+
 
     def getProfile(self):
         """
-        Get SLD profile 
-        
-        : return: (r, beta) where r is a list of radius of the transition points
-            beta is a list of the corresponding SLD values
-        : Note: This works only for func_shell num = 2.
+        Get SLD profile
+        **Note:** This works only for func_shell num = 2.
+
+        :return: (r, beta) where r is a list of radius of the transition points\
+         and beta is a list of the corresponding SLD values.
         """
         r = []
@@ -181,9 +179,9 @@
         r.append(self.params['rad_core0'])
         beta.append(self.params['sld_core0'])
-        
+
         # for shells
         for n in range(1, self.n_shells+1):
             # Left side of each shells
-            r0 = r[len(r)-1]            
+            r0 = r[len(r)-1]
             r.append(r0)
             exec "beta.append(self.params['sld_shell%s'% str(n)])"
@@ -193,5 +191,5 @@
             r.append(r0)
             exec "beta.append(self.params['sld_shell%s'% str(n)])"
-            
+
         # for solvent
         r0 = r[len(r)-1]            
@@ -201,17 +199,17 @@
         r.append(r_solv)
         beta.append(self.params['sld_solv'])
-        
+
         return r, beta
 
     def setParam(self, name, value):
-        """ 
+        """
         Set the value of a model parameter
-    
-        : param name: name of the parameter
-        : param value: value of the parameter
+
+        :param name: name of the parameter
+        :param value: value of the parameter
         """
         # set param to new model
         self._setParamHelper( name, value)
-        ## setParam to model 
+        ## setParam to model
         if name == 'sld_solv':
             # the sld_*** model.params not in params must set to value of sld_solv
@@ -243,8 +241,7 @@
                 self.params[item] = value
                 return
-        
         #raise ValueError, "Model does not contain parameter %s" % name
-             
-   
+
+
     def _set_fixed_params(self):
         """
@@ -252,15 +249,15 @@
         """
         for item in self.model.fixed:
-            if item.split('.')[0] in self.params.keys(): 
+            if item.split('.')[0] in self.params.keys():
                 self.fixed.append(item)
 
         self.fixed.sort()
-                
+
     def run(self, x = 0.0):
-        """ 
+        """
         Evaluate the model
-        
-        : param x: input q-value (float or [float, float] as [r, theta])
-        : return: (DAB value)
+
+        :param x: input q-value (float or [float, float] as [r, theta])
+        :return: (DAB value)
         """
         # set effective radius and scaling factor before run
@@ -269,50 +266,48 @@
 
     def runXY(self, x = 0.0):
-        """ 
+        """
         Evaluate the model
-        
-        : param x: input q-value (float or [float, float] as [qx, qy])
-        : return: DAB value
+
+        :param x: input q-value (float or [float, float] as [qx, qy])
+        :return: DAB value
         """  
         # set effective radius and scaling factor before run
 
         return self.model.runXY(x)
-    
+
     ## Now (May27,10) directly uses the model eval function 
     ## instead of the for-loop in Base Component.
     def evalDistribution(self, x = []):
-        """ 
+        """
         Evaluate the model in cartesian coordinates
-        
-        : param x: input q[], or [qx[], qy[]]
-        : return: scattering function P(q[])
+
+        :param x: input q[], or [qx[], qy[]]
+        :return: scattering function P(q[])
         """
         # set effective radius and scaling factor before run
         return self.model.evalDistribution(x)
-    
+
     def calculate_ER(self):
-        """ 
+        """
         Calculate the effective radius for P(q)*S(q)
-        
+
         :return: the value of the effective radius
-        
-        """       
+        """
         return self.model.calculate_ER() 
-    
+
     def calculate_VR(self):
-        """ 
+        """
         Calculate the volf ratio for P(q)*S(q)
-        
+
         :return: the value of the volf ratio
-        
-        """       
+        """
         return self.model.calculate_VR()
-    
+
     def set_dispersion(self, parameter, dispersion):
         """
         Set the dispersion object for a model parameter
-        
-        : param parameter: name of the parameter [string]
-        :dispersion: dispersion object of type DispersionModel
+
+        :param parameter: name of the parameter [string]
+        :param dispersion: dispersion object of type DispersionModel
         """
         value = None
@@ -323,3 +318,3 @@
             return value
         except:
-            raise 
+            raise
Index: src/sas/models/MultiplicationModel.py
===================================================================
--- src/sas/models/MultiplicationModel.py	(revision ac7be54ccf932e813cbe6e41e05b682a1630a03e)
+++ src/sas/models/MultiplicationModel.py	(revision fb3f9af6b7f4c21e4835a63ed3f7428632d42bc2)
@@ -10,7 +10,8 @@
         which will be calculated from P(Q) via calculate_ER(), 
         and 2) 'scale' in P model which is synchronized w/ volfraction in S 
-        then P*S is multiplied by a new param, 'scale_factor'.
+        then P*S is multiplied by a new parameter, 'scale_factor'.
         The polydispersion is applicable only to P(Q), not to S(Q).
-        Note: P(Q) refers to 'form factor' model while S(Q) does to 'structure factor'.
+
+        .. note:: P(Q) refers to 'form factor' model while S(Q) does to 'structure factor'.
     """
     def __init__(self, p_model, s_model ):
@@ -81,6 +82,6 @@
     def _clone(self, obj):
         """
-            Internal utility function to copy the internal
-            data members to a fresh copy.
+        Internal utility function to copy the internal data members to a
+        fresh copy.
         """
         obj.params     = copy.deepcopy(self.params)
@@ -96,6 +97,6 @@
     def _set_dispersion(self):
         """
-           combined the two models dispersions
-           Polydispersion should not be applied to s_model
+        combine the two models' dispersions. Polydispersity should not be
+        applied to s_model
         """
         ##set dispersion only from p_model 
@@ -107,7 +108,8 @@
         Get SLD profile of p_model if exists
         
-        : return: (r, beta) where r is a list of radius of the transition points
-                beta is a list of the corresponding SLD values 
-        : Note: This works only for func_shell num = 2 (exp function).
+        :return: (r, beta) where r is a list of radius of the transition points\
+                beta is a list of the corresponding SLD values
+
+        .. note:: This works only for func_shell num = 2 (exp function).
         """
         try:
@@ -121,6 +123,6 @@
     def _set_params(self):
         """
-            Concatenate the parameters of the two models to create
-            this model parameters 
+        Concatenate the parameters of the two models to create
+        these model parameters 
         """
 
@@ -141,6 +143,6 @@
     def _set_details(self):
         """
-            Concatenate details of the two models to create
-            this model details 
+        Concatenate details of the two models to create
+        this model's details 
         """
         for name, detail in self.p_model.details.iteritems():
@@ -154,5 +156,5 @@
     def _set_scale_factor(self):
         """
-            Set scale=volfraction to P model
+        Set scale=volfraction for P model
         """
         value = self.params['volfraction']
@@ -168,5 +170,5 @@
     def _set_effect_radius(self):
         """
-            Set effective radius to S(Q) model
+        Set effective radius to S(Q) model
         """
         if not 'effect_radius' in self.s_model.params.keys():
@@ -206,5 +208,5 @@
     def _setParamHelper(self, name, value):
         """
-            Helper function to setparam
+        Helper function to setparam
         """
         # Look for dispersion parameters
@@ -229,5 +231,5 @@
     def _set_fixed_params(self):
         """
-             fill the self.fixed list with the p_model fixed list
+        Fill the self.fixed list with the p_model fixed list
         """
         for item in self.p_model.fixed:
@@ -240,4 +242,5 @@
         """ 
         Evaluate the model
+        
         :param x: input q-value (float or [float, float] as [r, theta])
         :return: (scattering function value)
@@ -250,7 +253,9 @@
 
     def runXY(self, x = 0.0):
-        """ Evaluate the model
-            @param x: input q-value (float or [float, float] as [qx, qy])
-            @return: scattering function value
+        """ 
+        Evaluate the model
+        
+        :param x: input q-value (float or [float, float] as [qx, qy])
+        :return: scattering function value
         """  
         # set effective radius and scaling factor before run
@@ -266,4 +271,5 @@
         """ 
         Evaluate the model in cartesian coordinates
+        
         :param x: input q[], or [qx[], qy[]]
         :return: scattering function P(q[])
@@ -279,4 +285,5 @@
         """
         Set the dispersion object for a model parameter
+        
         :param parameter: name of the parameter [string]
         :dispersion: dispersion object of type DispersionModel
@@ -293,5 +300,5 @@
     def fill_description(self, p_model, s_model):
         """
-            Fill the description for P(Q)*S(Q)
+        Fill the description for P(Q)*S(Q)
         """
         description = ""
Index: src/sas/models/c_extension/c_models/GelFit.cpp
===================================================================
--- src/sas/models/c_extension/c_models/GelFit.cpp	(revision 794922220f2fb3b23dd08c648aabf87b4850596c)
+++ src/sas/models/c_extension/c_models/GelFit.cpp	(revision 1d115ef0ea20114c0109dad8c815846e6281604a)
@@ -34,5 +34,5 @@
     radius = Parameter(104.0,true);
     radius.set_min(2.0);
-    scale = Parameter(2.0,true);
+    FractalExp = Parameter(2.0,true);
     background = Parameter(0.01);
 }
@@ -43,5 +43,5 @@
     dp[0] = zeta();
     dp[1] = radius();
-    dp[2] = scale();
+    dp[2] = FractalExp();
     
     if (dp[2] <= 0)
Index: src/sas/models/c_extension/python_wrapper/WrapperGenerator.py
===================================================================
--- src/sas/models/c_extension/python_wrapper/WrapperGenerator.py	(revision 13e46abe8f84f07d1ddf4b73efdf7a78c7abf47a)
+++ src/sas/models/c_extension/python_wrapper/WrapperGenerator.py	(revision 1f5f206cb54d8f1284dcdc7778dd1c77213dd744)
@@ -560,9 +560,11 @@
     def replaceToken(self, line, key, value): #pylint: disable-msg=R0201
         """ Replace a token in the template file 
-            @param line: line of text to inspect
-            @param key: token to look for
-            @param value: string value to replace the token with
-            @return: new string value
+            :param line: line of text to inspect
+            :param key: token to look for
+            :param value: string value to replace the token with
+            :return: new string value
         """
+        _str_value = str(value)
+        _new_value = _str_value.replace('\\','/')
         lenkey = len(key)
         newline = line
@@ -570,5 +572,5 @@
         while newline.count(key) > 0:
             index = newline.index(key)
-            newline = newline[:index] + value + newline[index + lenkey:]
+            newline = newline[:index] + _new_value + newline[index + lenkey:]
 
         return newline
Index: src/sas/models/c_extension/python_wrapper/modelTemplate.txt
===================================================================
--- src/sas/models/c_extension/python_wrapper/modelTemplate.txt	(revision c93122ee680b57fbb71017748fd8f0dcefc114ac)
+++ src/sas/models/c_extension/python_wrapper/modelTemplate.txt	(revision 1f5f206cb54d8f1284dcdc7778dd1c77213dd744)
@@ -17,5 +17,4 @@
 
 .. WARNING::
-
    THIS FILE WAS GENERATED BY WRAPPERGENERATOR.PY
    DO NOT MODIFY THIS FILE, MODIFY
@@ -30,5 +29,5 @@
 def create_[PYTHONCLASS]():
     """
-       Create a model instance
+    Create a model instance
     """
     obj = [PYTHONCLASS]()
@@ -100,4 +99,5 @@
         """
         Evaluate the model
+
         :param x: input q, or [q,phi]
         :return: scattering function P(q)
@@ -108,4 +108,5 @@
         """
         Evaluate the model in cartesian coordinates
+
         :param x: input q, or [qx, qy]
         :return: scattering function P(q)
@@ -116,4 +117,5 @@
         """
         Evaluate the model in cartesian coordinates
+
         :param x: input q[], or [qx[], qy[]]
         :return: scattering function P(q[])
@@ -124,4 +126,5 @@
         """
         Calculate the effective radius for P(q)*S(q)
+
         :return: the value of the effective radius
         """
@@ -131,4 +134,5 @@
         """
         Calculate the volf ratio for P(q)*S(q)
+
         :return: the value of the volf ratio
         """
@@ -138,4 +142,5 @@
         """
         Set the dispersion object for a model parameter
+
         :param parameter: name of the parameter [string]
         :param dispersion: dispersion object of type DispersionModel
Index: src/sas/models/include/GelFit.h
===================================================================
--- src/sas/models/include/GelFit.h	(revision 794922220f2fb3b23dd08c648aabf87b4850596c)
+++ src/sas/models/include/GelFit.h	(revision 1d115ef0ea20114c0109dad8c815846e6281604a)
@@ -33,6 +33,6 @@
   Parameter radius;
 
-  //  [DEFAULT]=scale= 2
-  Parameter scale;
+  //  [DEFAULT]=FractalExp= 2
+  Parameter FractalExp;
 
   //  [DEFAULT]=background= 0.01
Index: src/sas/models/include/dabmodel.h
===================================================================
--- src/sas/models/include/dabmodel.h	(revision 794922220f2fb3b23dd08c648aabf87b4850596c)
+++ src/sas/models/include/dabmodel.h	(revision f008ee25abcc6518da3fa5cb3efabb05e64c9c98)
@@ -17,6 +17,7 @@
 // [PYTHONCLASS] = DABModel
 // [DISP_PARAMS] = length, scale, background
-// [DESCRIPTION] = <text>Provide F(x) = scale/( 1 + (x*L)^2 )^(2) + background
-//    DAB (Debye Anderson Brumberger) function as a BaseComponent model
+// [DESCRIPTION] = <text>DAB (Debye Anderson Brumberger) Model
+//    F(x) = scale * L^3/( 1 + (q*L)^2 )^2 + background
+//    L: the correlation length
 //     </text>
 // [FIXED] = 
Index: src/sas/models/sas_extension/__init__.py
===================================================================
--- src/sas/models/sas_extension/__init__.py	(revision 794922220f2fb3b23dd08c648aabf87b4850596c)
+++ src/sas/models/sas_extension/__init__.py	(revision fb3f9af6b7f4c21e4835a63ed3f7428632d42bc2)
@@ -0,0 +1,3 @@
+"""
+This is an empty package - should probably delete
+"""
Index: src/sas/perspectives/fitting/fitpage.py
===================================================================
--- src/sas/perspectives/fitting/fitpage.py	(revision d06c34cc03669e6a26b82db94d97c3e490e60c9f)
+++ src/sas/perspectives/fitting/fitpage.py	(revision 098f3d277d54e6ae4bae35ed0188be84b67fb171)
@@ -2218,11 +2218,7 @@
         """
         # compute weight for the current data
-        from sas.perspectives.fitting.utils import get_weight
         flag_weight = self.get_weight_flag()
         if is_2D == None:
             is_2D = self._is_2D()
-        weight = get_weight(data=self.data,
-                            is2d=is_2D,
-                            flag=flag_weight)
         self._manager.set_fit_weight(uid=self.uid,
                                      flag=flag_weight,
@@ -2242,6 +2238,4 @@
         self._update_paramv_on_fit()
 
-        # msg default
-        msg = None
         if event != None:
             tcrtl = event.GetEventObject()
@@ -2257,5 +2251,5 @@
         # if any value is changed
         if is_new_pinhole:
-            msg = self._set_pinhole_smear()
+            self._set_pinhole_smear()
         # hide all silt sizer
         self._hide_all_smear_info()
Index: src/sas/perspectives/fitting/fitting.py
===================================================================
--- src/sas/perspectives/fitting/fitting.py	(revision f21d4969d416d232125ec9af18b6bb0189f68ace)
+++ src/sas/perspectives/fitting/fitting.py	(revision 098f3d277d54e6ae4bae35ed0188be84b67fb171)
@@ -539,5 +539,5 @@
                         self.add_fit_page(data=[data])
             except:
-                msg = "Fitting Set_data: " + str(sys.exc_value)
+                msg = "Fitting set_data: " + str(sys.exc_value)
                 wx.PostEvent(self.parent, StatusEvent(status=msg, info="error"))
 
@@ -670,4 +670,8 @@
         :param weight: current dy data
         """
+        # If we are not dealing with a specific fit problem, then
+        # there is no point setting the weights.
+        if fid is None:
+            return
         if uid in self.page_finder.keys():
             self.page_finder[uid].set_weight(flag=flag, is2d=is2d)
Index: src/sas/perspectives/fitting/resultpanel.py
===================================================================
--- src/sas/perspectives/fitting/resultpanel.py	(revision 2f4b43041eaa7b7f496750f223a299cb33cd268e)
+++ src/sas/perspectives/fitting/resultpanel.py	(revision 9df6a03015af83c5e84c1877daf2f74af85ad4e0)
@@ -9,4 +9,8 @@
 import wx.lib.newevent
 from wx.aui import AuiNotebook as Notebook
+
+from bumps.gui.convergence_view import ConvergenceView
+from bumps.gui.uncertainty_view import UncertaintyView, CorrelationView, TraceView
+from bumps.dream.stats import var_stats, format_vars
 
 from sas.guiframe.panel_base import PanelBase
@@ -55,32 +59,36 @@
         result = event.result[0][0]
         if hasattr(result, 'convergence'):
-            from bumps.gui.convergence_view import ConvergenceView
             best, pop = result.convergence[:, 0], result.convergence[:, 1:]
-            self.get_panel(ConvergenceView).update(best, pop)
+            self._get_view(ConvergenceView).update(best, pop)
+        else:
+            self._del_view(ConvergenceView)
         if hasattr(result, 'uncertainty_state'):
-            from bumps.gui.uncertainty_view import UncertaintyView, CorrelationView, TraceView
-            from bumps.dream.stats import var_stats, format_vars
             stats = var_stats(result.uncertainty_state.draw())
             msg = format_vars(stats)
-            self.get_panel(CorrelationView).update(result.uncertainty_state)
-            self.get_panel(UncertaintyView).update((result.uncertainty_state, stats))
-            self.get_panel(TraceView).update(result.uncertainty_state)
+            self._get_view(CorrelationView).update(result.uncertainty_state)
+            self._get_view(UncertaintyView).update((result.uncertainty_state, stats))
+            self._get_view(TraceView).update(result.uncertainty_state)
             # TODO: stats should be stored in result rather than computed in bumps UncertaintyView
             wx.PostEvent(self.frame.parent,
                          StatusEvent(status=msg, info="info"))
-            print
+        else:
+            for view in (CorrelationView, UncertaintyView, TraceView):
+                self._del_view(view)
 
     def get_frame(self):
         return self.frame
 
-    def add_panel(self, panel):
-        self.AddPage(panel, panel.title)
-
-    def get_panel(self, panel_class):
+    def _get_view(self, view_class):
         for idx in range(self.PageCount):
-            if self.GetPageText(idx) == panel_class.title:
+            if self.GetPageText(idx) == view_class.title:
                 return self.GetPage(idx)
         else:
-            panel = panel_class(self)
-            self.add_panel(panel)
+            panel = view_class(self)
+            self.AddPage(panel, panel.title)
             return panel
+
+    def _del_view(self, view_class):
+        for idx in range(self.PageCount):
+            if self.GetPageText(idx) == view_class.title:
+                self.DeletePage(idx)
+
Index: src/sas/plottools/PlotPanel.py
===================================================================
--- src/sas/plottools/PlotPanel.py	(revision 7e0f9b55273843a20a74196a1fed0b9a76b3f411)
+++ src/sas/plottools/PlotPanel.py	(revision d3d67f06423dc337fd087c81b7cbd502dc7e1084)
@@ -3,4 +3,5 @@
 """
 import logging
+import traceback
 import wx
 # Try a normal import first
@@ -21,5 +22,4 @@
 
 from plottables import Graph
-from plottables import Text
 from TextDialog import TextDialog
 from LabelDialog import LabelDialog
@@ -32,5 +32,6 @@
 import numpy
 
-from sas.guiframe.events import StatusEvent
+from ..guiframe.events import StatusEvent
+from .toolbar import NavigationToolBar, PlotPrintout, bind
 
 def show_tree(obj, d=0):
@@ -88,18 +89,4 @@
             lo, hi = math.pow(10., lo), math.pow(10., hi)
     return (lo, hi)
-
-
-def CopyImage(canvas):
-    """
-    0: matplotlib plot
-    1: wx.lib.plot
-    2: other
-    """
-    bmp = wx.BitmapDataObject()
-    bmp.SetBitmap(canvas.bitmap)
-
-    wx.TheClipboard.Open()
-    wx.TheClipboard.SetData(bmp)
-    wx.TheClipboard.Close()
 
 
@@ -333,6 +320,7 @@
         """
         self.enable_toolbar = True
-        from toolbar import NavigationToolBar
         self.toolbar = NavigationToolBar(parent=self, canvas=self.canvas)
+        bind(self.toolbar, wx.EVT_TOOL, self.onResetGraph, id=self.toolbar._NTB2_RESET)
+        bind(self.toolbar, wx.EVT_TOOL, self.onContextMenu, id=self.toolbar._NTB2_HOME)
         self.toolbar.Realize()
         ## The 'SetToolBar()' is not working on MAC: JHC
@@ -634,19 +622,19 @@
         when clicking on linear Fit on context menu , display Fitting Dialog
         """
-        list = {}
+        plot_dict = {}
         menu = event.GetEventObject()
-        id = event.GetId()
-        self.set_selected_from_menu(menu, id)
+        event_id = event.GetId()
+        self.set_selected_from_menu(menu, event_id)
         plotlist = self.graph.returnPlottable()
         if self.graph.selected_plottable is not None:
             for item in plotlist:
                 if item.id == self.graph.selected_plottable:
-                    list[item] = plotlist[item]
+                    plot_dict[item] = plotlist[item]
         else:
-            list = plotlist
+            plot_dict = plotlist
         from fitDialog import LinearFit
 
-        if len(list.keys()) > 0:
-            first_item = list.keys()[0]
+        if len(plot_dict.keys()) > 0:
+            first_item = plot_dict.keys()[0]
             dlg = LinearFit(parent=None, plottable=first_item,
                             push_data=self.onFitDisplay,
@@ -862,5 +850,5 @@
         Implement save image
         """
-        self.toolbar.save(evt)
+        self.toolbar.save_figure(evt)
 
     def onContextMenu(self, event):
@@ -870,58 +858,50 @@
         """
         # Slicer plot popup menu
-        id = wx.NewId()
+        wx_id = wx.NewId()
         slicerpop = wx.Menu()
-        slicerpop.Append(id, '&Save image', 'Save image as PNG')
-        wx.EVT_MENU(self, id, self.onSaveImage)
-
-        id = wx.NewId()
-        slicerpop.Append(id, '&Printer setup', 'Set image size')
-        wx.EVT_MENU(self, id, self.onPrinterSetup)
-
-        id = wx.NewId()
-        slicerpop.Append(id, '&Printer Preview', 'Set image size')
-        wx.EVT_MENU(self, id, self.onPrinterPreview)
-
-        id = wx.NewId()
-        slicerpop.Append(id, '&Print image', 'Print image ')
-        wx.EVT_MENU(self, id, self.onPrint)
-
-        id = wx.NewId()
-        slicerpop.Append(id, '&Copy', 'Copy to the clipboard')
-        wx.EVT_MENU(self, id, self.OnCopyFigureMenu)
-
-        #id = wx.NewId()
-        #slicerpop.Append(id, '&Load 1D data file')
-        #wx.EVT_MENU(self, id, self._onLoad1DData)
-
-        id = wx.NewId()
+        slicerpop.Append(wx_id, '&Save image', 'Save image as PNG')
+        wx.EVT_MENU(self, wx_id, self.onSaveImage)
+
+        wx_id = wx.NewId()
+        slicerpop.Append(wx_id, '&Printer setup', 'Set image size')
+        wx.EVT_MENU(self, wx_id, self.onPrinterSetup)
+
+        wx_id = wx.NewId()
+        slicerpop.Append(wx_id, '&Print image', 'Print image ')
+        wx.EVT_MENU(self, wx_id, self.onPrint)
+
+        wx_id = wx.NewId()
+        slicerpop.Append(wx_id, '&Copy', 'Copy to the clipboard')
+        wx.EVT_MENU(self, wx_id, self.OnCopyFigureMenu)
+
+        wx_id = wx.NewId()
         slicerpop.AppendSeparator()
-        slicerpop.Append(id, '&Properties')
-        wx.EVT_MENU(self, id, self._onProperties)
-
-        id = wx.NewId()
+        slicerpop.Append(wx_id, '&Properties')
+        wx.EVT_MENU(self, wx_id, self._onProperties)
+
+        wx_id = wx.NewId()
         slicerpop.AppendSeparator()
-        slicerpop.Append(id, '&Linear Fit')
-        wx.EVT_MENU(self, id, self.onFitting)
-
-        id = wx.NewId()
+        slicerpop.Append(wx_id, '&Linear Fit')
+        wx.EVT_MENU(self, wx_id, self.onFitting)
+
+        wx_id = wx.NewId()
         slicerpop.AppendSeparator()
-        slicerpop.Append(id, '&Toggle Legend On/Off', 'Toggle Legend On/Off')
-        wx.EVT_MENU(self, id, self.onLegend)
+        slicerpop.Append(wx_id, '&Toggle Legend On/Off', 'Toggle Legend On/Off')
+        wx.EVT_MENU(self, wx_id, self.onLegend)
 
         loc_menu = wx.Menu()
         for label in self._loc_labels:
-            id = wx.NewId()
-            loc_menu.Append(id, str(label), str(label))
-            wx.EVT_MENU(self, id, self.onChangeLegendLoc)
-        id = wx.NewId()
-        slicerpop.AppendMenu(id, '&Modify Legend Location', loc_menu)
-
-        id = wx.NewId()
-        slicerpop.Append(id, '&Modify Y Axis Label')
-        wx.EVT_MENU(self, id, self._on_yaxis_label)
-        id = wx.NewId()
-        slicerpop.Append(id, '&Modify X Axis Label')
-        wx.EVT_MENU(self, id, self._on_xaxis_label)
+            wx_id = wx.NewId()
+            loc_menu.Append(wx_id, str(label), str(label))
+            wx.EVT_MENU(self, wx_id, self.onChangeLegendLoc)
+        wx_id = wx.NewId()
+        slicerpop.AppendMenu(wx_id, '&Modify Legend Location', loc_menu)
+
+        wx_id = wx.NewId()
+        slicerpop.Append(wx_id, '&Modify Y Axis Label')
+        wx.EVT_MENU(self, wx_id, self._on_yaxis_label)
+        wx_id = wx.NewId()
+        slicerpop.Append(wx_id, '&Modify X Axis Label')
+        wx.EVT_MENU(self, wx_id, self._on_xaxis_label)
 
         try:
@@ -1922,8 +1902,5 @@
         self.xmax = xmax
         #In case need to change the range of data plotted
-        list = []
-        list = self.graph.returnPlottable()
-        for item in list:
-            #item.onFitRange(xminView,xmaxView)
+        for item in self.graph.returnPlottable():
             item.onFitRange(None, None)
         # Create new data plottable with result
@@ -1969,7 +1946,5 @@
         Reset the graph by plotting the full range of data
         """
-        list = []
-        list = self.graph.returnPlottable()
-        for item in list:
+        for item in self.graph.returnPlottable():
             item.onReset()
         self.graph.render(self)
@@ -1978,4 +1953,7 @@
         self.toolbar.update()
 
+    def onPrint(self, event=None):
+        self.toolbar.print_figure(event)
+
     def onPrinterSetup(self, event=None):
         """
@@ -1986,26 +1964,35 @@
     def onPrinterPreview(self, event=None):
         """
+        Matplotlib camvas can no longer print itself.  Thus need to do
+        everything ourselves: need to create a printpreview frame to to
+        see the preview but needs a parent frame object.  Also needs a
+        printout object (just as any printing task).
         """
         try:
-            self.canvas.Printer_Preview(event=event)
-            self.Update()
+            #check if parent is a frame.  If not keep getting the higher
+            #parent till we find a frame
+            _plot = self
+            while not isinstance(_plot, wx.Frame):
+                _plot = _plot.GetParent()
+                assert _plot is not None
+
+            #now create the printpeview object
+            _preview = wx.PrintPreview(PlotPrintout(self.canvas),
+                                       PlotPrintout(self.canvas))
+            #and tie it to a printpreview frame then show it
+            _frame = wx.PreviewFrame(_preview, _plot, "Print Preview", wx.Point(100, 100), wx.Size(600, 650))
+            _frame.Centre(wx.BOTH)
+            _frame.Initialize()
+            _frame.Show(True)
         except:
+            traceback.print_exc()
             pass
 
-    def onPrint(self, event=None):
-        """
+    def OnCopyFigureMenu(self, evt):
+        """
+        Copy the current figure to clipboard
         """
         try:
-            self.canvas.Printer_Print(event=event)
-            self.Update()
-        except:
-            pass
-
-    def OnCopyFigureMenu(self, evt):
-        """
-        Copy the current figure to clipboard
-        """
-        try:
-            CopyImage(self.canvas)
+            self.toolbar.copy_figure()
         except:
             print "Error in copy Image"
Index: src/sas/plottools/TextDialog.py
===================================================================
--- src/sas/plottools/TextDialog.py	(revision 3477478de6317fb51d4dd0dbaf9ab2a1236faf28)
+++ src/sas/plottools/TextDialog.py	(revision 649806d8cadcd2797d6f9c42ca6968c1726e7b34)
@@ -8,5 +8,5 @@
     FONT_VARIANT = 1
     PNL_WIDTH = 500
-FAMILY = ['serif', 'sas-serif', 'fantasy', 'monospace']
+FAMILY = ['serif', 'sans-serif', 'fantasy', 'monospace']
 SIZE = [8, 9, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72]
 STYLE = ['normal', 'italic']
@@ -20,5 +20,5 @@
         Dialog window pops- up when selecting 'Add Text' on the toolbar
         """
-        wx.Dialog.__init__(self, parent, id, title, size=(PNL_WIDTH, 280))
+        wx.Dialog.__init__(self, parent, id, title, size=(PNL_WIDTH, 300))
         self.parent = parent
         # Font
@@ -35,6 +35,6 @@
         text_box = wx.BoxSizer(wx.HORIZONTAL)
         sizer = wx.GridBagSizer(1, 3)
-        _BOX_WIDTH = 60
-        font_description = wx.StaticBox(self, -1, 'Font', size=(PNL_WIDTH - 20, 70))
+        _BOX_WIDTH = 70
+        font_description = wx.StaticBox(self, -1, 'Font')
         font_box = wx.StaticBoxSizer(font_description, wx.VERTICAL)
         family_box = wx.BoxSizer(wx.HORIZONTAL)
@@ -103,5 +103,5 @@
         self.font_style.SetToolTipString("Font style of the text.")
         # font color
-        self.font_color = wx.ComboBox(self, -1, style=wx.CB_READONLY)
+        self.font_color = wx.ComboBox(self, -1, style = wx.CB_READONLY)
         wx.EVT_COMBOBOX(self.font_color, -1, self.on_color)
         self.font_color.SetMinSize((_BOX_WIDTH, -1))
@@ -111,6 +111,8 @@
         # Buttons on the bottom
         self.static_line_1 = wx.StaticLine(self, -1)
-        self.ok_button = wx.Button(self, wx.ID_OK, 'OK', size=(_BOX_WIDTH, 25))
-        self.close_button = wx.Button(self, wx.ID_CANCEL, 'Cancel', size=(_BOX_WIDTH, 25))
+        self.ok_button = wx.Button(self, wx.ID_OK, 'OK',
+                                   size = (_BOX_WIDTH, 25))
+        self.close_button = wx.Button(self, wx.ID_CANCEL, 'Cancel',
+                                      size = (_BOX_WIDTH, 25))
 
         # Intro
@@ -121,23 +123,29 @@
         sizer.Add(wx.StaticText(self, -1, explanation), (iy, ix),
                   (1, 1), wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
-        family_box.Add(wx.StaticText(self, -1, 'Family :'), -1, 0)
-        family_box.Add(self.font_family, -1, 0)
+        family_box.Add(wx.StaticText(self, -1, 'Family :', size = (50, -1)),
+                       0, wx.TOP, 5)
+        family_box.Add(self.font_family, 0, 0)
         family_box.Add((_BOX_WIDTH / 2, -1))
-        family_box.Add(wx.StaticText(self, -1, 'Size :'), -1, 0)
-        family_box.Add(self.font_size, -1, 0)
+        family_box.Add(wx.StaticText(self, -1, 'Size :', size = (50, -1)),
+                       0, wx.TOP, 5)
+        family_box.Add(self.font_size, 0, 0)
         if unit_box != None:
             family_box.Add((_BOX_WIDTH / 2, -1))
-            family_box.Add(tick_label_text, -1, 0)
-            family_box.Add(self.tick_label_check, -1, 0)
-        style_box.Add(wx.StaticText(self, -1, 'Style :'), -1, 0)
-        style_box.Add(self.font_style, -1, 0)
+            family_box.Add(tick_label_text, 0, 0)
+            family_box.Add(self.tick_label_check, 0, 0)
+        style_box.Add(wx.StaticText(self, -1, 'Style :', size = (50, -1)),
+                      0, wx.TOP, 5)
+        style_box.Add(self.font_style, 0, 0)
         style_box.Add((_BOX_WIDTH / 2, -1))
-        style_box.Add(wx.StaticText(self, -1, 'Weight :'), -1, 0)
-        style_box.Add(self.font_weight, -1, 0)
+        style_box.Add(wx.StaticText(self, -1, 'Weight :', size = (50, -1)),
+                      0, wx.TOP, 5)
+        style_box.Add(self.font_weight, 0, 0)
         style_box.Add((_BOX_WIDTH / 2, -1))
-        style_box.Add(wx.StaticText(self, -1, 'Color :'), -1, 0)
-        style_box.Add(self.font_color, -1, 0)
-        font_box.Add(family_box, -1, 10)
-        font_box.Add(style_box, -1, 10)
+        style_box.Add(wx.StaticText(self, -1, 'Color :', size = (45, -1)),
+                      0, wx.TOP, 5)
+        style_box.Add(self.font_color, 0, 0)
+        font_box.Add(family_box, 0, 10)
+        font_box.Add((0,5))
+        font_box.Add(style_box, 0, 10)
         iy += 1
         ix = 0
@@ -152,6 +160,6 @@
         vbox.Add(text_box, 0, wx.EXPAND, 15)
         if unit_box != None:
-            unit_box.Add(unit_text, -1, 0)
-            unit_box.Add(self.unit_ctrl, -1, 0)
+            unit_box.Add(unit_text, 0, 0)
+            unit_box.Add(self.unit_ctrl, 0, 0)
             vbox.Add((5, 5))
             vbox.Add(unit_box, 0, wx.LEFT, 15)
Index: src/sas/plottools/config.py
===================================================================
--- src/sas/plottools/config.py	(revision 794922220f2fb3b23dd08c648aabf87b4850596c)
+++ src/sas/plottools/config.py	(revision d3d67f06423dc337fd087c81b7cbd502dc7e1084)
@@ -58,2 +58,10 @@
 matplotlib.rcParams[param] = 0.05
 matplotlib.rcParams['legend.numpoints'] = 1
+
+# this should happen after initial matplotlib configuration
+from .toolbar import NavigationToolBar
+from matplotlib.backends import backend_wxagg
+backend_wxagg.NavigationToolbar2WxAgg = NavigationToolBar
+
+# CRUFT: bumps 0.7.5.6 and older uses wrong toolbar
+backend_wxagg.NavigationToolbar2Wx = NavigationToolBar
Index: src/sas/plottools/toolbar.py
===================================================================
--- src/sas/plottools/toolbar.py	(revision 3477478de6317fb51d4dd0dbaf9ab2a1236faf28)
+++ src/sas/plottools/toolbar.py	(revision d3d67f06423dc337fd087c81b7cbd502dc7e1084)
@@ -31,12 +31,12 @@
     def _init_toolbar(self):
         self._parent = self.canvas.GetParent()
-        _NTB2_HOME = wx.NewId()
+        self._NTB2_HOME = wx.NewId()
         self._NTB2_BACK = wx.NewId()
         self._NTB2_FORWARD = wx.NewId()
         self._NTB2_PAN = wx.NewId()
         self._NTB2_ZOOM = wx.NewId()
-        _NTB2_SAVE = wx.NewId()
-        _NTB2_PRINT = wx.NewId()
-        _NTB2_RESET = wx.NewId()
+        self._NTB2_SAVE = wx.NewId()
+        self._NTB2_PRINT = wx.NewId()
+        self._NTB2_RESET = wx.NewId()
 
         # for mpl 1.2+ compatibility
@@ -53,5 +53,5 @@
         context_tip += '    right-click the data symbols.'
         context = wx.ArtProvider.GetBitmap(wx.ART_LIST_VIEW, wx.ART_TOOLBAR)
-        self.AddSimpleTool(_NTB2_HOME, context, context_tip, context_tip)
+        self.AddSimpleTool(self._NTB2_HOME, context, context_tip, context_tip)
 
         self.InsertSeparator(1)
@@ -69,28 +69,25 @@
 
         self.AddSeparator()
-        self.AddSimpleTool(_NTB2_SAVE, _load_bitmap('filesave.png'),
+        self.AddSimpleTool(self._NTB2_SAVE, _load_bitmap('filesave.png'),
                            'Save', 'Save plot contents to file')
 
         print_bmp = wx.ArtProvider.GetBitmap(wx.ART_PRINT, wx.ART_TOOLBAR)
-        self.AddSimpleTool(_NTB2_PRINT, print_bmp, 'Print', 'Print plot')
+        self.AddSimpleTool(self._NTB2_PRINT, print_bmp, 'Print', 'Print plot')
 
         reset_bmp = wx.ArtProvider.GetBitmap(wx.ART_GO_HOME, wx.ART_TOOLBAR)
-        self.AddSimpleTool(_NTB2_RESET, reset_bmp, 'Reset', 'Reset graph range')
+        self.AddSimpleTool(self._NTB2_RESET, reset_bmp, 'Reset', 'Reset graph range')
 
-        bind(self, wx.EVT_TOOL, self.on_menu, id=_NTB2_HOME)
+        bind(self, wx.EVT_TOOL, self.context_menu, id=self._NTB2_HOME)
         bind(self, wx.EVT_TOOL, self.forward, id=self._NTB2_FORWARD)
         bind(self, wx.EVT_TOOL, self.back, id=self._NTB2_BACK)
         bind(self, wx.EVT_TOOL, self.zoom, id=self._NTB2_ZOOM)
         bind(self, wx.EVT_TOOL, self.pan, id=self._NTB2_PAN)
-        bind(self, wx.EVT_TOOL, self.save_figure, id=_NTB2_SAVE)
-        bind(self, wx.EVT_TOOL, self.on_print, id=_NTB2_PRINT)
-        bind(self, wx.EVT_TOOL, self.on_reset, id=_NTB2_RESET)
+        bind(self, wx.EVT_TOOL, self.save_figure, id=self._NTB2_SAVE)
+        bind(self, wx.EVT_TOOL, self.print_figure, id=self._NTB2_PRINT)
+        bind(self, wx.EVT_TOOL, self.home, id=self._NTB2_RESET)
 
         self.Realize()
 
     def on_menu(self, event):
-        """
-            Plot menu
-        """
         try:
             self._parent.onToolContextMenu(event=event)
@@ -98,19 +95,80 @@
             logging.error("Plot toolbar could not show menu")
 
-    def on_reset(self, event):
+    def context_menu(self, event):
         """
-            Reset plot
+        Default context menu for a plot panel
+
         """
+        # Slicer plot popup menu
+        wx_id = wx.NewId()
+        popup = wx.Menu()
+        popup.Append(wx_id, '&Save image', 'Save image as PNG')
+        wx.EVT_MENU(self, wx_id, self.save_figure)
+
+        wx_id = wx.NewId()
+        popup.Append(wx_id, '&Print image', 'Print image ')
+        wx.EVT_MENU(self, wx_id, self.print_figure)
+
+        wx_id = wx.NewId()
+        popup.Append(wx_id, '&Copy to Clipboard', 'Copy image to the clipboard')
+        wx.EVT_MENU(self, wx_id, self.copy_figure)
+
+        # Show the popup menu relative to the location of the toolbar
+        self.PopupMenu(popup, (0,0))
+
+
+    def print_figure(self, event):
         try:
-            self._parent.onResetGraph(event=event)
+            _printer = wx.Printer()
+            _printer.Print(self.canvas, PlotPrintout(self.canvas), True)
         except:
-            logging.error("Plot toolbar could not reset plot")
+            import traceback
+            logging.error(traceback.format_exc())
 
-    def on_print(self, event):
+    def copy_figure(self, event):
+        copy_image_to_clipboard(self.canvas)
+
+class PlotPrintout(wx.Printout):
+    """
+    Create the wx.Printout object for matplotlib figure from the PlotPanel.
+    Provides the required OnPrintPage and HasPage overrides.  Other methods
+    may be added/overriden in the future.
+    :TODO: this needs LOTS of TLC .. but fixes immediate problem
+    """
+    def __init__(self, canvas):
         """
-            Print
+        Initialize wx.Printout and get passed figure object
         """
-        try:
-            self.canvas.Printer_Preview(event=event)
-        except:
-            logging.error("Plot toolbar could not print")
+        wx.Printout.__init__(self)
+        self.canvas = canvas
+
+    def OnPrintPage(self, page):
+        """
+        Most rudimentry OnPrintPage overide.  instatiates a dc object, gets
+        its size, gets the size of the figure object, scales it to the dc
+        canvas size keeping the aspect ratio intact, then prints as bitmap
+        """
+        _dc = self.GetDC()
+        (_dcX, _dcY) = _dc.GetSizeTuple()
+        (_bmpX,_bmpY) = self.canvas.GetSize()
+        _scale = min(_dcX/_bmpX, _dcY/_bmpY)
+        _dc.SetUserScale(_scale, _scale)
+        _dc.DrawBitmap(self.canvas.bitmap, 0, 0, False,)
+        return True
+
+    def GetPageInfo(self):
+        """
+        just sets the page to 1 - no flexibility for now
+        """
+        return (1, 1, 1, 1)
+
+
+def copy_image_to_clipboard(canvas):
+    bmp = wx.BitmapDataObject()
+    bmp.SetBitmap(canvas.bitmap)
+
+    wx.TheClipboard.Open()
+    wx.TheClipboard.SetData(bmp)
+    wx.TheClipboard.Close()
+
+
