[GRASS-SVN] r55314 - in grass/branches/develbranch_6: gui/wxpython gui/wxpython/gui_core gui/wxpython/location_wizard lib/python

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Mar 11 06:27:21 PDT 2013


Author: annakrat
Date: 2013-03-11 06:27:20 -0700 (Mon, 11 Mar 2013)
New Revision: 55314

Modified:
   grass/branches/develbranch_6/gui/wxpython/gis_set.py
   grass/branches/develbranch_6/gui/wxpython/gui_core/dialogs.py
   grass/branches/develbranch_6/gui/wxpython/gui_core/widgets.py
   grass/branches/develbranch_6/gui/wxpython/location_wizard/wizard.py
   grass/branches/develbranch_6/lib/python/core.py
Log:
wxGUI/startup: merge changes from #1889

Modified: grass/branches/develbranch_6/gui/wxpython/gis_set.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gis_set.py	2013-03-11 12:43:20 UTC (rev 55313)
+++ grass/branches/develbranch_6/gui/wxpython/gis_set.py	2013-03-11 13:27:20 UTC (rev 55314)
@@ -26,6 +26,7 @@
 import copy
 import platform
 import codecs
+import getpass
 
 ### i18N
 import gettext
@@ -44,7 +45,11 @@
 from core.gcmd      import GMessage, GError, DecodeString, RunCommand, GWarning
 from core.utils     import GetListOfLocations, GetListOfMapsets
 from location_wizard.dialogs import RegionDef
+from gui_core.dialogs import TextEntryDialog
+from gui_core.widgets import GenericValidator
 
+from grass.script import core as grass
+
 sys.stderr = codecs.getwriter('utf8')(sys.stderr)
 
 class GRASSStartup(wx.Frame):
@@ -428,7 +433,17 @@
             else:
                 self.SetDefaultRegion(location = gWizard.location)
 
-            self.ExitSuccessfully()
+            dlg = TextEntryDialog(parent=self,
+                                  message=_("Do you want to create new mapset?"),
+                                  caption=_("Create new mapset"),
+                                  defaultValue=self._getDefaultMapsetName(),
+                                  validator=GenericValidator(grass.legal_name, self._nameValidationFailed),
+                                  style=wx.OK | wx.CANCEL | wx.HELP)
+            help = dlg.FindWindowById(wx.ID_HELP)
+            help.Bind(wx.EVT_BUTTON, self.OnHelp)
+            if dlg.ShowModal() == wx.ID_OK:
+                mapsetName = dlg.GetValue()
+                self.CreateNewMapset(mapsetName)
 
     def SetDefaultRegion(self, location):
         """!Asks to set default region."""
@@ -511,9 +526,10 @@
                                  'This mapset cannot be renamed.'))
             return
         
-        dlg = wx.TextEntryDialog(parent = self,
-                                 message = _('Current name: %s\n\nEnter new name:') % mapset,
-                                 caption = _('Rename selected mapset'))
+        dlg = TextEntryDialog(parent = self,
+                              message = _('Current name: %s\n\nEnter new name:') % mapset,
+                              caption = _('Rename selected mapset'),
+                              validator = GenericValidator(grass.legal_name, self._nameValidationFailed))
         
         if dlg.ShowModal() ==  wx.ID_OK:
             newmapset = dlg.GetValue()
@@ -546,9 +562,10 @@
         """
         location = self.listOfLocations[self.lblocations.GetSelection()]
 
-        dlg = wx.TextEntryDialog(parent = self,
-                                 message = _('Current name: %s\n\nEnter new name:') % location,
-                                 caption = _('Rename selected location'))
+        dlg = TextEntryDialog(parent = self,
+                              message = _('Current name: %s\n\nEnter new name:') % location,
+                              caption = _('Rename selected location'),
+                              validator = GenericValidator(grass.legal_name, self._nameValidationFailed))
 
         if dlg.ShowModal() ==  wx.ID_OK:
             newlocation = dlg.GetValue()
@@ -774,39 +791,44 @@
         
         dlg.Destroy()
 
-    def OnCreateMapset(self,event):
+    def OnCreateMapset(self, event):
         """!Create new mapset"""
-        self.gisdbase = self.tgisdbase.GetValue()
-        location = self.listOfLocations[self.lblocations.GetSelection()]
 
-        dlg = wx.TextEntryDialog(parent = self,
+        dlg = TextEntryDialog(parent = self,
                                  message = _('Enter name for new mapset:'),
-                                 caption = _('Create new mapset'))
+                                 caption = _('Create new mapset'),
+                                 defaultValue = self._getDefaultMapsetName(),
+                                 validator = GenericValidator(grass.legal_name, self._nameValidationFailed))
 
-        if dlg.ShowModal() ==  wx.ID_OK:
+        if dlg.ShowModal() == wx.ID_OK:
             mapset = dlg.GetValue()
-            if mapset in self.listOfMapsets:
-                GMessage(parent = self,
-                         message = _("Mapset <%s> already exists.") % mapset)
-                return
-            
-            try:
-                os.mkdir(os.path.join(self.gisdbase, location, mapset))
-                # copy WIND file and its permissions from PERMANENT and set permissions to u+rw,go+r
-                shutil.copy(os.path.join(self.gisdbase, location, 'PERMANENT', 'WIND'),
-                            os.path.join(self.gisdbase, location, mapset))
-                # os.chmod(os.path.join(database,location,mapset,'WIND'), 0644)
-                self.OnSelectLocation(None)
-                self.lbmapsets.SetSelection(self.listOfMapsets.index(mapset))
-            except StandardError, e:
-                GError(parent = self,
-                       message = _("Unable to create new mapset: %s") % e,
-                       showTraceback = False)
-                return False
+            return self.CreateNewMapset(mapset = mapset)
+        else:
+            return False
+
+    def CreateNewMapset(self, mapset):
+        if mapset in self.listOfMapsets:
+            GMessage(parent = self,
+                     message = _("Mapset <%s> already exists.") % mapset)
+            return False
         
-        self.bstart.SetFocus()
-        
-        return True
+        try:
+            self.gisdbase = self.tgisdbase.GetValue()
+            location = self.listOfLocations[self.lblocations.GetSelection()]
+            os.mkdir(os.path.join(self.gisdbase, location, mapset))
+            # copy WIND file and its permissions from PERMANENT and set permissions to u+rw,go+r
+            shutil.copy(os.path.join(self.gisdbase, location, 'PERMANENT', 'WIND'),
+                        os.path.join(self.gisdbase, location, mapset))
+            # os.chmod(os.path.join(database,location,mapset,'WIND'), 0644)
+            self.OnSelectLocation(None)
+            self.lbmapsets.SetSelection(self.listOfMapsets.index(mapset))
+            self.bstart.SetFocus()
+            return True
+        except StandardError, e:
+            GError(parent = self,
+                   message = _("Unable to create new mapset: %s") % e,
+                   showTraceback = False)
+            return False
 
     def OnStart(self, event):
         """'Start GRASS' button clicked"""
@@ -862,8 +884,18 @@
                    set = "LOCATION_NAME=%s" % location)
         RunCommand("g.gisenv",
                    set = "MAPSET=%s" % mapset)
-        
 
+
+    def _getDefaultMapsetName(self):
+        """!Returns default name for mapset."""
+        try:
+            defaultName = getpass.getuser()
+            defaultName.encode('ascii') # raise error if not ascii (not valid mapset name)
+        except: # whatever might go wrong
+            defaultName = 'user'
+
+        return defaultName
+
     def ExitSuccessfully(self):
         self.Destroy()
         sys.exit(0)
@@ -885,6 +917,12 @@
         event.Skip()
         sys.exit(2)
 
+    def _nameValidationFailed(self, ctrl):
+        message = _("Name <%(name)s> is not a valid name for location or mapset. "
+                    "Please use only ASCII characters excluding %(chars)s "
+                    "and space.") % {'name': ctrl.GetValue(), 'chars': '/"\'@,=*~'}
+        GError(parent=self, message=message, caption=_("Invalid name"))
+
 class GListBox(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
     """!Use wx.ListCtrl instead of wx.ListBox, different style for
     non-selectable items (e.g. mapsets with denied permission)"""

Modified: grass/branches/develbranch_6/gui/wxpython/gui_core/dialogs.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_core/dialogs.py	2013-03-11 12:43:20 UTC (rev 55313)
+++ grass/branches/develbranch_6/gui/wxpython/gui_core/dialogs.py	2013-03-11 13:27:20 UTC (rev 55314)
@@ -2406,3 +2406,34 @@
         """!Returns currently selected symbol full path.
         """
         return os.path.join(self.symbolPath, self.selectedDir, self.selected)
+
+class TextEntryDialog(wx.Dialog):
+    """!Simple dialog with text field. 
+
+    It differs from wx.TextEntryDialog because it allows adding validator.
+    """
+    def __init__(self, parent, message, caption='',
+                 defaultValue='', pos=wx.DefaultPosition, validator=wx.DefaultValidator,
+                 style=wx.OK | wx.CANCEL):
+        wx.Dialog.__init__(self, parent=parent, id=wx.ID_ANY, title=caption, pos=pos)
+
+        vbox = wx.BoxSizer(wx.VERTICAL)
+
+        stline = wx.StaticText(self, id=wx.ID_ANY, label=message)
+        vbox.Add(item=stline, proportion=0, flag=wx.EXPAND | wx.ALL, border=10)
+
+        self._textCtrl = wx.TextCtrl(self, id=wx.ID_ANY, size = (300, -1),
+                                     value=defaultValue, validator=validator)
+        vbox.Add(item=self._textCtrl, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=10)
+        self._textCtrl.SetFocus()
+
+        sizer = self.CreateSeparatedButtonSizer(style)
+        vbox.Add(item=sizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=10)
+
+        self.SetSizerAndFit(vbox)
+        
+    def GetValue(self):
+        return self._textCtrl.GetValue()
+
+    def SetValue(self, value):
+        self._textCtrl.SetValue(value)

Modified: grass/branches/develbranch_6/gui/wxpython/gui_core/widgets.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/gui_core/widgets.py	2013-03-11 12:43:20 UTC (rev 55313)
+++ grass/branches/develbranch_6/gui/wxpython/gui_core/widgets.py	2013-03-11 13:27:20 UTC (rev 55314)
@@ -335,7 +335,52 @@
         # Returning without calling even.Skip eats the event before it
         # gets to the text control
         return  
-    
+
+
+class GenericValidator(wx.PyValidator):
+    """ This validator checks condition and calls callback
+    in case the condition is not fulfilled.
+    """
+    def __init__(self, condition, callback):
+        """ Standard constructor.
+
+        @param condition function which accepts string value and returns T/F
+        @param callback function which is called when condition is not fulfilled
+        """
+        wx.PyValidator.__init__(self)
+        self._condition = condition
+        self._callback = callback
+
+    def Clone(self):
+        """ Standard cloner.
+
+        Note that every validator must implement the Clone() method.
+        """
+        return GenericValidator(self._condition, self._callback)
+
+    def Validate(self, win):
+        """ Validate the contents of the given text control.
+        """
+        ctrl = self.GetWindow()
+        text = ctrl.GetValue()
+        if not self._condition(text):
+            self._callback(ctrl)
+            return False
+        else:
+            return True
+
+    def TransferToWindow(self):
+        """ Transfer data from validator to window.
+        """
+        return True # Prevent wxDialog from complaining.
+
+
+    def TransferFromWindow(self):
+        """ Transfer data from window to validator.
+        """
+        return True # Prevent wxDialog from complaining.
+
+
 class ItemTree(CT.CustomTreeCtrl):
     def __init__(self, parent, id = wx.ID_ANY,
                  ctstyle = CT.TR_HIDE_ROOT | CT.TR_FULL_ROW_HIGHLIGHT | CT.TR_HAS_BUTTONS |

Modified: grass/branches/develbranch_6/gui/wxpython/location_wizard/wizard.py
===================================================================
--- grass/branches/develbranch_6/gui/wxpython/location_wizard/wizard.py	2013-03-11 12:43:20 UTC (rev 55313)
+++ grass/branches/develbranch_6/gui/wxpython/location_wizard/wizard.py	2013-03-11 13:27:20 UTC (rev 55314)
@@ -42,6 +42,7 @@
 from core                    import utils
 from core.gcmd               import RunCommand, GError, GMessage, GWarning
 from gui_core.ghelp          import HelpFrame
+from gui_core.widgets        import GenericValidator
 from location_wizard.base    import BaseClass
 from location_wizard.dialogs import SelectTransformDialog
 
@@ -102,6 +103,7 @@
         # text controls
         self.tgisdbase = self.MakeTextCtrl(grassdatabase, size = (300, -1))
         self.tlocation = self.MakeTextCtrl("newLocation", size = (300, -1))
+        self.tlocation.SetValidator(GenericValidator(grass.legal_name, self._nameValidationFailed))
         self.tlocTitle = self.MakeTextCtrl(size = (400, -1))
         
         # layout
@@ -153,6 +155,12 @@
         self.tgisdbase.Bind(wx.EVT_TEXT,        self.OnChangeName)
         self.tlocation.Bind(wx.EVT_TEXT,        self.OnChangeName)
         
+    def _nameValidationFailed(self, ctrl):
+        message = _("Name <%(name)s> is not a valid name for location. "
+                    "Please use only ASCII characters excluding %(chars)s "
+                    "and space.") % {'name': ctrl.GetValue(), 'chars': '/"\'@,=*~'}
+        GError(parent=self, message=message, caption=_("Invalid location name"))
+
     def OnChangeName(self, event):
         """!Name for new location was changed"""
         nextButton = wx.FindWindowById(wx.ID_FORWARD)

Modified: grass/branches/develbranch_6/lib/python/core.py
===================================================================
--- grass/branches/develbranch_6/lib/python/core.py	2013-03-11 12:43:20 UTC (rev 55313)
+++ grass/branches/develbranch_6/lib/python/core.py	2013-03-11 13:27:20 UTC (rev 55314)
@@ -1199,3 +1199,24 @@
 # get debug_level
 if find_program('g.gisenv', ['--help']):
     debug_level = int(gisenv().get('DEBUG', 0))
+
+def legal_name(s):
+    """!Checks if the string contains only allowed characters.
+
+    This is the Python implementation of G_legal_filename() function.
+
+    @note It is not clear when to use this function.
+    """
+    if not s or s[0] == '.':
+        warning(_("Illegal filename <%s>. Cannot be empty or start with '.'.") % s)
+        return False
+
+    illegal = [c
+               for c in s
+               if c in '/"\'@,=*~' or c <= ' ' or c >= '\177']
+    if illegal:
+        illegal = ''.join(sorted(set(illegal)))
+        warning(_("Illegal filename <%s>. <%s> not allowed.\n") % (s, illegal))
+        return False
+
+    return True



More information about the grass-commit mailing list