[GRASS-SVN] r55312 - in grass/trunk: gui/wxpython gui/wxpython/gui_core gui/wxpython/location_wizard lib/python/script

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Mar 11 05:30:47 PDT 2013


Author: annakrat
Date: 2013-03-11 05:30:46 -0700 (Mon, 11 Mar 2013)
New Revision: 55312

Modified:
   grass/trunk/gui/wxpython/gis_set.py
   grass/trunk/gui/wxpython/gui_core/dialogs.py
   grass/trunk/gui/wxpython/gui_core/widgets.py
   grass/trunk/gui/wxpython/location_wizard/wizard.py
   grass/trunk/lib/python/script/core.py
Log:
wxGUI/startup: merge changes from release branch (r55185,r55278,r55297)

Modified: grass/trunk/gui/wxpython/gis_set.py
===================================================================
--- grass/trunk/gui/wxpython/gis_set.py	2013-03-11 09:47:07 UTC (rev 55311)
+++ grass/trunk/gui/wxpython/gis_set.py	2013-03-11 12:30:46 UTC (rev 55312)
@@ -26,6 +26,7 @@
 import copy
 import platform
 import codecs
+import getpass
 
 ### i18N
 import gettext
@@ -44,6 +45,8 @@
 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
 
 sys.stderr = codecs.getwriter('utf8')(sys.stderr)
 
@@ -426,7 +429,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."""
@@ -509,9 +522,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()
@@ -544,9 +558,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()
@@ -778,54 +793,56 @@
         
         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,
-                                 message = _('Enter name for new mapset:'),
-                                 caption = _('Create new mapset'))
-        
-        if dlg.ShowModal() ==  wx.ID_OK:
+        dlg = TextEntryDialog(parent = self,
+                              message = _('Enter name for new mapset:'),
+                              caption = _('Create new mapset'),
+                              defaultValue = self._getDefaultMapsetName(),
+                              validator = GenericValidator(grass.legal_name, self._nameValidationFailed))
+        if dlg.ShowModal() == wx.ID_OK:
             mapset = dlg.GetValue()
-            if mapset in self.listOfMapsets:
-                GMessage(parent = self,
-                         message = _("Mapset <%s> already exists.") % mapset)
-                return
-            
-            if mapset.lower() == 'ogr':
-                dlg1 = wx.MessageDialog(parent = self,
-                                        message = _("Mapset <%s> is reserved for direct "
-                                                    "read access to OGR layers. Please consider to use "
-                                                    "another name for your mapset.\n\n"
-                                                    "Are you really sure that you want to create this mapset?") % mapset,
-                                        caption = _("Reserved mapset name"),
-                                        style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
-                ret = dlg1.ShowModal()
-                dlg1.Destroy()
-                if ret == wx.ID_NO:
-                    dlg.Destroy()
-                    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 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
+
+        if mapset.lower() == 'ogr':
+            dlg1 = wx.MessageDialog(parent = self,
+                                    message = _("Mapset <%s> is reserved for direct "
+                                                "read access to OGR layers. Please consider to use "
+                                                "another name for your mapset.\n\n"
+                                                "Are you really sure that you want to create this mapset?") % mapset,
+                                    caption = _("Reserved mapset name"),
+                                    style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
+            ret = dlg1.ShowModal()
+            dlg1.Destroy()
+            if ret == wx.ID_NO:
+                dlg.Destroy()
                 return False
         
-        dlg.Destroy()
-        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"""
@@ -881,8 +898,17 @@
                    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)
@@ -903,6 +929,13 @@
         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/trunk/gui/wxpython/gui_core/dialogs.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/dialogs.py	2013-03-11 09:47:07 UTC (rev 55311)
+++ grass/trunk/gui/wxpython/gui_core/dialogs.py	2013-03-11 12:30:46 UTC (rev 55312)
@@ -2516,3 +2516,35 @@
         """!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/trunk/gui/wxpython/gui_core/widgets.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/widgets.py	2013-03-11 09:47:07 UTC (rev 55311)
+++ grass/trunk/gui/wxpython/gui_core/widgets.py	2013-03-11 12:30:46 UTC (rev 55312)
@@ -601,6 +601,51 @@
         """
         return True # Prevent wxDialog from complaining.
 
+
+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/trunk/gui/wxpython/location_wizard/wizard.py
===================================================================
--- grass/trunk/gui/wxpython/location_wizard/wizard.py	2013-03-11 09:47:07 UTC (rev 55311)
+++ grass/trunk/gui/wxpython/location_wizard/wizard.py	2013-03-11 12:30:46 UTC (rev 55312)
@@ -41,6 +41,7 @@
 from core                    import globalvar
 from core                    import utils
 from core.gcmd               import RunCommand, GError, GMessage, GWarning
+from gui_core.widgets        import GenericValidator
 from location_wizard.base    import BaseClass
 from location_wizard.dialogs import SelectTransformDialog
 
@@ -101,6 +102,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
@@ -151,7 +153,13 @@
         self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
         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/trunk/lib/python/script/core.py
===================================================================
--- grass/trunk/lib/python/script/core.py	2013-03-11 09:47:07 UTC (rev 55311)
+++ grass/trunk/lib/python/script/core.py	2013-03-11 12:30:46 UTC (rev 55312)
@@ -1415,7 +1415,7 @@
                if c in '/"\'@,=*~' or c <= ' ' or c >= '\177']
     if illegal:
         illegal = ''.join(sorted(set(illegal)))
-        warning(_("Illegal filename <%s>. <%s> not allowed.\n") % (s, repr(illegal)[1:-1]))
+        warning(_("Illegal filename <%s>. <%s> not allowed.\n") % (s, illegal))
         return False
 
     return True



More information about the grass-commit mailing list