[GRASS-SVN] r29496 - in grass/trunk/gui/wxpython: . gui_modules

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Dec 22 17:39:05 EST 2007


Author: martinl
Date: 2007-12-22 17:39:05 -0500 (Sat, 22 Dec 2007)
New Revision: 29496

Modified:
   grass/trunk/gui/wxpython/gui_modules/dbm.py
   grass/trunk/gui/wxpython/wxgrass
   grass/trunk/gui/wxpython/wxgui.py
Log:
wxGUI: Ability to specify workspace file from command-line, e.g. wxgrass file.grc
Fix Attribute Table Manager when no DB connection is defined.


Modified: grass/trunk/gui/wxpython/gui_modules/dbm.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/dbm.py	2007-12-21 23:48:55 UTC (rev 29495)
+++ grass/trunk/gui/wxpython/gui_modules/dbm.py	2007-12-22 22:39:05 UTC (rev 29496)
@@ -40,6 +40,7 @@
 import wx.lib.mixins.listctrl as listmix
 import wx.lib.flatnotebook as FN
 import wx.lib.colourselect as csel
+import wx.lib.scrolledpanel as scrolled
 
 import sqlbuilder
 import grassenv
@@ -362,11 +363,11 @@
         self.mapDBInfo = VectorDBInfo(self.vectmap)
 
         if len(self.mapDBInfo.layers.keys()) == 0:
-            wx.MessageBox(patent=self.parent,
+            wx.MessageBox(parent=self.parent,
                           message=_("Database connection for map <%s> "
-                                    "is not defined in DB file") % self.vectmap,
-                          caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
-            return
+                                    "is not defined in DB file.") % self.vectmap,
+                          caption=_("Attribute Table Manager"),
+                          style=wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
 
         #
         # default settings (TODO global settings file)
@@ -439,7 +440,7 @@
         # buttons
         #
         self.btnApply      = wx.Button(parent=self, id=wx.ID_APPLY)
-        self.btnQuit       = wx.Button(parent=self, id=wx.ID_CANCEL)
+        self.btnQuit       = wx.Button(parent=self, id=wx.ID_EXIT)
         # self.btn_unselect = wx.Button(self, -1, "Unselect")
 
         # events
@@ -593,11 +594,15 @@
 
 
         self.browsePage.SetSelection(0) # select first layer
-        self.layer = self.mapDBInfo.layers.keys()[0]
-        self.OnChangeSql(None)
-        self.log.write(_("Number of loaded records: %d") % \
+        try:
+            self.layer = self.mapDBInfo.layers.keys()[0]
+            self.OnChangeSql(None)
+            self.log.write(_("Number of loaded records: %d") % \
                            self.FindWindowById(self.layerPage[self.layer]['data']).GetItemCount())
-
+        except IndexError:
+            self.layer = None
+        
+        
     def __createManageTablePage(self, onlyLayer=-1):
         """Create manage page (create/link and alter tables)"""
         for layer in self.mapDBInfo.layers.keys():
@@ -744,7 +749,10 @@
             self.layerPage[layer]['dbinfo'] = infoCollapse.GetId()
 
         self.manageTablePage.SetSelection(0) # select first layer
-        self.layer = self.mapDBInfo.layers.keys()[0]
+        try:
+            self.layer = self.mapDBInfo.layers.keys()[0]
+        except IndexError:
+            self.layer = None
 
     def __createTableDesc(self, parent, table):
         """Create list with table description"""
@@ -866,10 +874,11 @@
         mainSizer = wx.BoxSizer(wx.VERTICAL)
 
         # buttons
-        btnSizer = wx.StdDialogButtonSizer()
-        btnSizer.AddButton(self.btnQuit)
-        btnSizer.AddButton(self.btnApply)
-        btnSizer.Realize()
+        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
+        btnSizer.Add(item=self.btnQuit, proportion=1,
+                     flag=wx.ALL | wx.ALIGN_RIGHT | wx.SHAPED, border=5)
+        btnSizer.Add(item=self.btnApply,
+                     flag=wx.ALL, border=5)
 
         mainSizer.Add(item=self.notebook, proportion=1, flag=wx.EXPAND)
         mainSizer.Add(item=btnSizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
@@ -1678,11 +1687,11 @@
             # if self.browsePage.GetPageText(page).replace('Layer ', '').strip() == str(layer):
             # self.browsePage.DeletePage(page)
             # break
-            self.browsePage.RemovePage(self.mapDBInfo.layers.keys().index(layer))
-            self.manageTablePage.RemovePage(self.mapDBInfo.layers.keys().index(layer))
+            self.browsePage.DeletePage(self.mapDBInfo.layers.keys().index(layer))
+            self.manageTablePage.DeletePage(self.mapDBInfo.layers.keys().index(layer))
             # set current page selection
             self.notebook.SetSelection(2)
-
+            
         # fetch fresh db info
         self.mapDBInfo = VectorDBInfo(self.vectmap)    
 
@@ -1705,15 +1714,25 @@
         self.layerList.Populate(update=True)
         # update selected widgets
         listOfLayers = map(str, self.mapDBInfo.layers.keys())
+        ### delete layer page
         self.manageLayerBook.deleteLayer.SetItems(listOfLayers)
-        self.manageLayerBook.deleteLayer.SetStringSelection(listOfLayers[0])
-        tableName = self.mapDBInfo.layers[int(listOfLayers[0])]['table']
+        if len(listOfLayers) > 0:
+            self.manageLayerBook.deleteLayer.SetStringSelection(listOfLayers[0])
+            tableName = self.mapDBInfo.layers[int(listOfLayers[0])]['table']
+            maxLayer = max(self.mapDBInfo.layers.keys())
+        else:
+            tableName = ''
+            maxLayer = 0
         self.manageLayerBook.deleteTable.SetLabel( \
             _('Drop also linked attribute table (%s)') % \
                 tableName)
+        ### add layer page
         self.manageLayerBook.addLayerWidgets['layer'][1].SetValue(\
-            max(self.mapDBInfo.layers.keys())+1)
-
+            maxLayer+1)
+        ### modify layer
+        self.manageLayerBook.modifyLayerWidgets['layer'][1].SetItems(listOfLayers)
+        self.manageLayerBook.OnChangeLayer(event=None)
+        
 #     def OnMapClick(self, event):
 #         """
 #         Gets coordinates from mouse clicking on display window
@@ -1858,6 +1877,8 @@
                            int(self.table[column]['length']))
             i = i + 1
 
+        self.SendSizeEvent()
+        
         return itemData
 
 class LayerListCtrl(wx.ListCtrl,
@@ -1921,6 +1942,8 @@
             if self.GetColumnWidth(col=i) < 60:
                 self.SetColumnWidth(col=i, width=60)
 
+        self.SendSizeEvent()
+        
         return itemData
 
 class LayerBook(wx.Notebook):
@@ -1962,8 +1985,8 @@
         self.defaultTables = self.__getTables(self.defaultDriver, self.defaultDatabase)
         try:
             self.defaultColumns = self.__getColumns(self.defaultDriver, self.defaultDatabase,
-                                               listOfTables[0])
-        except:
+                                                    self.defaultTables[0])
+        except IndexError:
             self.defaultColumns = []
 
         self.__createAddPage()
@@ -1975,6 +1998,10 @@
         self.addPanel = wx.Panel(parent=self, id=wx.ID_ANY)
         self.AddPage(page=self.addPanel, text=_("Add new layer"))
 
+        try:
+            maxLayer = max(self.mapDBInfo.layers.keys())
+        except ValueError:
+            maxLayer = 0
         #
         # list of layer widgets (label, value)
         #
@@ -1982,7 +2009,7 @@
                                     (wx.StaticText(parent=self.addPanel, id=wx.ID_ANY,
                                                    label='%s:' % _("Layer")),
                                      wx.SpinCtrl(parent=self.addPanel, id=wx.ID_ANY, size=(65, -1),
-                                                 initial=max(self.mapDBInfo.layers.keys())+1,
+                                                 initial=maxLayer+1,
                                                  min=1, max=1e6)),
                                 'driver':
                                     (wx.StaticText(parent=self.addPanel, id=wx.ID_ANY,
@@ -2148,15 +2175,22 @@
         self.deleteLayer = wx.ComboBox(parent=self.deletePanel, id=wx.ID_ANY, size=(100, -1),
                                        style=wx.CB_SIMPLE | wx.CB_READONLY,
                                        choices=map(str, self.mapDBInfo.layers.keys()))
-        self.deleteLayer.SetSelection(0)
+        self.deleteLayer.SetSelection(0)           
         self.deleteLayer.Bind(wx.EVT_COMBOBOX, self.OnChangeLayer)
 
-        tableName = self.mapDBInfo.layers[int(self.deleteLayer.GetStringSelection())]['table']
-
+        try:
+            tableName = self.mapDBInfo.layers[int(self.deleteLayer.GetStringSelection())]['table']
+        except ValueError:
+            tableName = ''
+            
         self.deleteTable = wx.CheckBox(parent=self.deletePanel, id=wx.ID_ANY,
                                        label=_('Drop also linked attribute table (%s)') % \
-                                           tableName)
+                                       tableName)
 
+        if tableName == '':
+            self.deleteLayer.Enable(False)
+            self.deleteTable.Enable(False)
+            
         btnDelete   = wx.Button(self.deletePanel, wx.ID_DELETE, _("&Delete layer"),
                                 size=(125,-1))
         btnDelete.Bind(wx.EVT_BUTTON, self.OnDeleteLayer)
@@ -2241,17 +2275,24 @@
         
         # set default values for widgets
         self.modifyLayerWidgets['layer'][1].SetSelection(0)
-        layer    = int(self.modifyLayerWidgets['layer'][1].GetStringSelection())
-        driver   = self.mapDBInfo.layers[layer]['driver']
-        database = self.mapDBInfo.layers[layer]['database']
-        table    = self.mapDBInfo.layers[layer]['table']
-        listOfColumns = self.__getColumns(driver, database, table)
-        self.modifyLayerWidgets['driver'][1].SetStringSelection(driver)
-        self.modifyLayerWidgets['database'][1].SetValue(database)
-        self.modifyLayerWidgets['table'][1].SetStringSelection(table)
-        self.modifyLayerWidgets['key'][1].SetItems(listOfColumns)
-        self.modifyLayerWidgets['key'][1].SetSelection(0)
+        try:
+            layer = int(self.modifyLayerWidgets['layer'][1].GetStringSelection())
+        except ValueError:
+            layer = None
+            for label in self.modifyLayerWidgets.keys():
+                self.modifyLayerWidgets[label][1].Enable(False)
 
+        if layer:
+            driver   = self.mapDBInfo.layers[layer]['driver']
+            database = self.mapDBInfo.layers[layer]['database']
+            table    = self.mapDBInfo.layers[layer]['table']
+            listOfColumns = self.__getColumns(driver, database, table)
+            self.modifyLayerWidgets['driver'][1].SetStringSelection(driver)
+            self.modifyLayerWidgets['database'][1].SetValue(database)
+            self.modifyLayerWidgets['table'][1].SetStringSelection(table)
+            self.modifyLayerWidgets['key'][1].SetItems(listOfColumns)
+            self.modifyLayerWidgets['key'][1].SetSelection(0)
+
         # events
         self.modifyLayerWidgets['layer'][1].Bind(wx.EVT_COMBOBOX, self.OnChangeLayer)
         # self.modifyLayerWidgets['driver'][1].Bind(wx.EVT_CHOICE, self.OnDriverChanged)
@@ -2447,6 +2488,13 @@
             # increase layer number
             layerWin.SetValue(layer+1)
 
+        if len(self.mapDBInfo.layers.keys()) == 1:
+            # first layer add --- enable previously disabled widgets
+            self.deleteLayer.Enable()
+            self.deleteTable.Enable()
+            for label in self.modifyLayerWidgets.keys():
+                self.modifyLayerWidgets[label][1].Enable()
+            
     def OnDeleteLayer(self, event):
         """Delete layer"""
 
@@ -2478,6 +2526,13 @@
         # update db info
         self.mapDBInfo = self.parentDialog.mapDBInfo
 
+        if len(self.mapDBInfo.layers.keys()) == 0:
+            # disable selected widgets
+            self.deleteLayer.Enable(False)
+            self.deleteTable.Enable(False)
+            for label in self.modifyLayerWidgets.keys():
+                self.modifyLayerWidgets[label][1].Enable(False)
+            
         event.Skip()
 
     def OnChangeLayer(self, event):
@@ -2488,7 +2543,7 @@
             try:
                 layer = self.mapDBInfo.layers.keys()[0]
             except:
-                layer = 1
+                return
 
         if self.GetCurrentPage() == self.modifyPanel:
             driver   = self.mapDBInfo.layers[layer]['driver']
@@ -2821,9 +2876,14 @@
                 else: # change status 'add' -> 'update'
                     self.action = "update"
 
-            panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
+            # use scrolled panel instead (and fix initial max height of the window to 480px)
+            ### panel = wx.Panel(parent=self.notebook, id=wx.ID_ANY)
+            panel = scrolled.ScrolledPanel(parent=self.notebook, id=wx.ID_ANY,
+                                           size=(-1, 300))
+            panel.SetupScrolling(scroll_x=False)
+            
             self.notebook.AddPage(page=panel, text=_(" %s %d ") % (_("Layer"), layer))
-
+            
             # notebook body
             border = wx.BoxSizer(wx.VERTICAL)
 
@@ -2847,8 +2907,9 @@
                 flexSizer.AddGrowableCol(3)
                 # columns
                 for name in columns.keys():
-                    type  = columns[name]['type']
-                    value = columns[name]['values'][idx]
+                    vtype  = columns[name]['type']
+                    value = str(columns[name]['values'][idx])
+
                     if name.lower() == "cat":
                         box    = wx.StaticBox (parent=panel, id=wx.ID_ANY,
                                                label=" %s %s " % (_("Category"), value))
@@ -2861,11 +2922,10 @@
                         colName = wx.StaticText(parent=panel, id=wx.ID_ANY,
                                                 label=name)
                         colType = wx.StaticText(parent=panel, id=wx.ID_ANY,
-                                                label="[" + type.lower() + "]")
+                                                label="[" + vtype.lower() + "]")
                         delimiter = wx.StaticText(parent=panel, id=wx.ID_ANY, label=":")
 
-                        colValue = wx.TextCtrl(parent=panel, id=wx.ID_ANY, value=value,
-                                               size=(-1, -1)) # TODO: validator
+                        colValue = wx.TextCtrl(parent=panel, id=wx.ID_ANY, value=value) # TODO: validator
                         colValue.SetName(name)
                         self.Bind(wx.EVT_TEXT, self.OnSQLStatement, colValue)
 
@@ -3083,7 +3143,7 @@
         for column, value in data:
             label = wx.StaticText(parent=self.panel, id=wx.ID_ANY,
                                   label=column + ":")
-            value = wx.TextCtrl(parent=self.panel, id=wx.ID_ANY,
+            value = wx.Texttrl(parent=self.panel, id=wx.ID_ANY,
                                 value=value, size=(250, -1))
             if keyEditable[0] > -1: # id given
                 if keyEditable[0] == id:

Modified: grass/trunk/gui/wxpython/wxgrass
===================================================================
--- grass/trunk/gui/wxpython/wxgrass	2007-12-21 23:48:55 UTC (rev 29495)
+++ grass/trunk/gui/wxpython/wxgrass	2007-12-22 22:39:05 UTC (rev 29496)
@@ -10,7 +10,12 @@
 #if [ "$SYSTEM" = "Darwin" ] ; then
 #	pythonw "$GISBASE/etc/wx/wxgui.py" -name wxgui_py
 #else
-    python "$GISBASE/etc/wx/wxgui.py" -name wxgui_py &
+if [ ! -z "$1" ] ; then
+    # load workspace file
+    python "$GISBASE/etc/wx/wxgui.py" "--workspace" "$1" &
+else
+    python "$GISBASE/etc/wx/wxgui.py" &
+fi
 #fi
 
 exit 0

Modified: grass/trunk/gui/wxpython/wxgui.py
===================================================================
--- grass/trunk/gui/wxpython/wxgui.py	2007-12-21 23:48:55 UTC (rev 29495)
+++ grass/trunk/gui/wxpython/wxgui.py	2007-12-22 22:39:05 UTC (rev 29496)
@@ -28,7 +28,7 @@
 import traceback
 import types
 import re
-# for GRC (workspace file) parsering
+### for GRC (workspace file) parsering
 # xmlproc not available on Mac OS
 # from xml.parsers.xmlproc import xmlproc
 # from xml.parsers.xmlproc import xmlval
@@ -77,8 +77,8 @@
 import gui_modules.georect as georect
 import gui_modules.dbm as dbm
 import gui_modules.globalvar as globalvar
+from   gui_modules.debug import Debug as Debug
 from   icons.icon import Icons as Icons
-from   gui_modules.debug import Debug as Debug
 
 menucmd = {}
 
@@ -88,7 +88,8 @@
     GRASS GIS. Includes command console page for typing GRASS
     (and other) commands, tree widget page for managing GIS map layers.
     """
-    def __init__(self, parent, id=wx.ID_ANY, title=_("GRASS GIS Layer Manager")):
+    def __init__(self, parent, id=wx.ID_ANY, title=_("GRASS GIS Layer Manager"),
+                 workspace=None):
         self.parent    = parent
         self.baseTitle = title
         self.iconsize  = (16, 16)
@@ -117,7 +118,7 @@
         self.curr_page     = ''           # currently selected page for layer tree notebook
         self.curr_pagenum  = ''           # currently selected page number for layer tree notebook
         self.encoding      = 'ISO-8859-1' # default encoding for display fonts
-        self.workspaceFile = None         # workspace file
+        self.workspaceFile = workspace    # workspace file
 
         # bindings
         self.Bind(wx.EVT_CLOSE,     self.OnCloseWindow)
@@ -145,6 +146,14 @@
 
         # start default initial display
         self.NewDisplay()
+        
+        # load workspace file if requested
+        if (self.workspaceFile):
+            # load given workspace file
+            if self.LoadGrcXmlToLayerTree(self.workspaceFile):
+                self.SetTitle(self.baseTitle + " - " +  os.path.basename(self.workspaceFile))
+            else:
+                self.workspaceFile = None
 
     def __doLayout(self):
         """Do Layout (unused bacause of aui manager...)"""
@@ -534,13 +543,11 @@
             maptree.Map.ReverseListOfLayers()
 
             file.close()
-        except Exception, err:
-            dlg = wx.MessageDialog(parent=self,
-                                   message=_("Unable to read workspace file <%s>.\n\n%s") % \
-                                       (filename, err),
-                                   caption=_("Error"), style=wx.OK | wx.ICON_ERROR)
-            dlg.ShowModal()
-            dlg.Destroy()
+        except IOError, err:
+            wx.MessageBox(parent=self,
+                          message=_("Unable to read workspace file <%s>.%s%s") % \
+                          (filename, os.linesep, err),
+                          caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
             return False
 
         return True
@@ -1235,9 +1242,13 @@
     """
     GMApp class
     """
+    def __init__(self, workspace=None):
+        self.workspaceFile = workspace
+        
+        # call parent class initializer
+        wx.App.__init__(self)
+        
     def OnInit(self):
-        # reexec_with_pythonw()
-
         # initialize all available image handlers
         wx.InitAllImageHandlers()
 
@@ -1250,7 +1261,9 @@
         wx.Yield()
 
         # create and show main frame
-        mainframe = GMFrame(parent=None, id=wx.ID_ANY, title=_("GRASS GIS Layer Manager"))
+        mainframe = GMFrame(parent=None, id=wx.ID_ANY,
+                            title=_("GRASS GIS Layer Manager"),
+                            workspace = self.workspaceFile)
 
         mainframe.Show()
         self.SetTopWindow(mainframe)
@@ -1376,57 +1389,73 @@
             self.value += ch
 
 def reexec_with_pythonw():
-  if sys.platform == 'darwin' and\
+  if sys.platform == 'darwin' and \
     not sys.executable.endswith('MacOS/Python'):
     print >> sys.stderr, _('re-executing using pythonw')
-    os.execvp('pythonw',['pythonw',__file__] + sys.argv[1:])
+    os.execvp('pythonw', ['pythonw', __file__] + sys.argv[1:])
 
-### 2007/11 -- seems to be unused...
-# class GRasterDialog(wx.Frame):
-#     def __init__(self,parent,id=-1,title="Set raster layer"):
-#         wx.Frame.__init__(self, parent, id , title, size=(50,600))
+class Usage(Exception):
+    def __init__(self, msg):
+        self.msg = msg
 
-#         # sizers
-#         sizer = wx.BoxSizer(wx.VERTICAL)
-#         buttsizer = wx.BoxSizer(wx.HORIZONTAL)
+def printHelp():
+    """Print program help"""
+    print >> sys.stderr, "Usage:"
+    print >> sys.stderr, " python wxgui.py [options]"
+    print >> sys.stderr, "%sOptions:" % os.linesep
+    print >> sys.stderr, " -w\t--workspace file\tWorkspace file to load"
+    sys.exit(0)
 
-#         # labels
-#         lmap = wx.StaticText(self,-1,"Map name")
-#         lvalues = wx.StaticText(self,-1,"List of values to be displayed")
-#         lopaque = wx.StaticText(self,-1,"Transparency")
+def process_opt(opts, args):
+    """Process command-line arguments"""
+    workspaceFile = None
+    for o, a in opts:
+        if o in ("-h", "--help"):
+            printHelp()
+            
+        if o in ("-w", "--workspace"):
+            if a != '':
+                workspaceFile = str(a)
+            else:
+                workspaceFile = args.pop(0)
 
-#         # checkboxes
-#         cboverlay = wx.CheckBox(self, -1, "Overlay (non-null values)")
-#         cboverlay.SetValue(True)
+    return (workspaceFile,)
 
-#         # text entries
-#         tmapname = wx.TextCtrl(self,-1,size=(-1,-1))
-#         tvalues = wx.TextCtrl(self,-1,size=(-1,-1))
+def main(argv=None):
+    #
+    # reexec for MacOS
+    #
+    reexec_with_pythonw()
 
-#         # buttons
-#         bsize=(75,-1)
-#         bok = wx.Button(self,-1, "OK",size=bsize)
-#         bapply = wx.Button(self,-1, "Apply", size=bsize)
-#         bcancel = wx.Button(self,-1, "Cancel", size=bsize)
+    #
+    # process command-line arguments
+    #
+    if argv is None:
+        argv = sys.argv
+    try:
+        try:
+            opts, args = getopt.getopt(argv[1:], "hw:",
+                                       ["help", "workspace"])
+        except getopt.error, msg:
+            raise Usage(msg)
 
-#         buttsizer.Add(bok, 0, wx.ADJUST_MINSIZE, 1)
-#         buttsizer.Add(bapply, 0, wx.ADJUST_MINSIZE, 1)
-#         buttsizer.Add(bcancel, 0, wx.ADJUST_MINSIZE, 1)
-#         sizer.Add(lopaque,1, wx.EXPAND,  1)
-#         sizer.Add(lmap,0, wx.EXPAND,  1)
-#         sizer.Add(tmapname,0, wx.EXPAND,  1)
-#         sizer.Add(lvalues,0, wx.EXPAND,  1)
-#         sizer.Add(tvalues,0, wx.EXPAND,  1)
-#         sizer.Add(cboverlay,1, wx.EXPAND,  1)
-#         sizer.Add(buttsizer,0, wx.ADJUST_MINSIZE, 1)
-#         self.SetSizer(sizer)
-#         sizer.Fit(self)
-#         self.Layout()
+    except Usage, err:
+        print >> sys.stderr, err.msg
+        print >> sys.stderr, "for help use --help"
+        printHelp()
 
+    workspaceFile = process_opt(opts, args)[0]
+
+    # replace with the appropriate catalog name
+    gettext.install("GMApp") 
+
+    #
+    # run application
+    #
+    app = GMApp(workspaceFile)
+    app.MainLoop()
+
 if __name__ == "__main__":
-  reexec_with_pythonw()
-
-  import gettext
-  gettext.install("GMApp") # replace with the appropriate catalog name
-  app = GMApp(0)
-  app.MainLoop()
+    import getopt
+    import gettext
+    sys.exit(main())



More information about the grass-commit mailing list