GRASS Programmer's Manual
6.4.2(2012)
|
00001 """! 00002 @package gis_set.py 00003 00004 GRASS start-up screen. 00005 00006 Initialization module for wxPython GRASS GUI. 00007 Location/mapset management (selection, creation, etc.). 00008 00009 Classes: 00010 - GRASSStartup 00011 - GListBox 00012 - StartUp 00013 00014 (C) 2006-2011 by the GRASS Development Team 00015 00016 This program is free software under the GNU General Public License 00017 (>=v2). Read the file COPYING that comes with GRASS for details. 00018 00019 @author Michael Barton and Jachym Cepicky (original author) 00020 @author Martin Landa <landa.martin gmail.com> (various updates) 00021 """ 00022 00023 import os 00024 import sys 00025 import glob 00026 import shutil 00027 import copy 00028 import platform 00029 import codecs 00030 00031 ### i18N 00032 import gettext 00033 gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True) 00034 00035 from gui_modules import globalvar 00036 import wx 00037 import wx.html 00038 import wx.lib.rcsizer as rcs 00039 import wx.lib.filebrowsebutton as filebrowse 00040 import wx.lib.mixins.listctrl as listmix 00041 import wx.lib.scrolledpanel as scrolled 00042 00043 from gui_modules import goutput 00044 from gui_modules.ghelp import HelpFrame 00045 from gui_modules.gcmd import GMessage, GError 00046 00047 sys.stderr = codecs.getwriter('utf8')(sys.stderr) 00048 00049 class GRASSStartup(wx.Frame): 00050 """!GRASS start-up screen""" 00051 def __init__(self, parent = None, id = wx.ID_ANY, style = wx.DEFAULT_FRAME_STYLE): 00052 00053 # 00054 # GRASS variables 00055 # 00056 self.gisbase = os.getenv("GISBASE") 00057 self.grassrc = self._readGisRC() 00058 self.gisdbase = self.GetRCValue("GISDBASE") 00059 00060 # 00061 # list of locations/mapsets 00062 # 00063 self.listOfLocations = [] 00064 self.listOfMapsets = [] 00065 self.listOfMapsetsSelectable = [] 00066 00067 wx.Frame.__init__(self, parent = parent, id = id, style = style) 00068 00069 self.locale = wx.Locale(language = wx.LANGUAGE_DEFAULT) 00070 00071 self.panel = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY) 00072 00073 # i18N 00074 import gettext 00075 gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True) 00076 00077 # 00078 # graphical elements 00079 # 00080 # image 00081 try: 00082 name = os.path.join(globalvar.ETCIMGDIR, "startup_banner.gif") 00083 self.hbitmap = wx.StaticBitmap(self.panel, wx.ID_ANY, 00084 wx.Bitmap(name = name, 00085 type = wx.BITMAP_TYPE_GIF)) 00086 except: 00087 self.hbitmap = wx.StaticBitmap(self.panel, wx.ID_ANY, wx.EmptyBitmap(530,150)) 00088 00089 # labels 00090 ### crashes when LOCATION doesn't exist 00091 versionFile = open(os.path.join(globalvar.ETCDIR, "VERSIONNUMBER")) 00092 grassVersion = versionFile.readline().split(' ')[0].rstrip('\n') 00093 versionFile.close() 00094 00095 self.select_box = wx.StaticBox (parent = self.panel, id = wx.ID_ANY, 00096 label = " %s " % _("Choose project location and mapset")) 00097 00098 self.manage_box = wx.StaticBox (parent = self.panel, id = wx.ID_ANY, 00099 label = " %s " % _("Manage")) 00100 self.lwelcome = wx.StaticText(parent = self.panel, id = wx.ID_ANY, 00101 label = _("Welcome to GRASS GIS %s\n" 00102 "The world's leading open source GIS") % grassVersion, 00103 style = wx.ALIGN_CENTRE) 00104 self.ltitle = wx.StaticText(parent = self.panel, id = wx.ID_ANY, 00105 label = _("Select an existing project location and mapset\n" 00106 "or define a new location"), 00107 style = wx.ALIGN_CENTRE) 00108 self.ldbase = wx.StaticText(parent = self.panel, id = wx.ID_ANY, 00109 label = _("GIS Data Directory:")) 00110 self.llocation = wx.StaticText(parent = self.panel, id = wx.ID_ANY, 00111 label = _("Project location\n(projection/coordinate system)"), 00112 style = wx.ALIGN_CENTRE) 00113 self.lmapset = wx.StaticText(parent = self.panel, id = wx.ID_ANY, 00114 label = _("Accessible mapsets\n(directories of GIS files)"), 00115 style = wx.ALIGN_CENTRE) 00116 self.lcreate = wx.StaticText(parent = self.panel, id = wx.ID_ANY, 00117 label = _("Create new mapset\nin selected location"), 00118 style = wx.ALIGN_CENTRE) 00119 self.ldefine = wx.StaticText(parent = self.panel, id = wx.ID_ANY, 00120 label = _("Define new location"), 00121 style = wx.ALIGN_CENTRE) 00122 self.lmanageloc = wx.StaticText(parent = self.panel, id = wx.ID_ANY, 00123 label = _("Rename/delete selected\nmapset or location"), 00124 style = wx.ALIGN_CENTRE) 00125 00126 # buttons 00127 self.bstart = wx.Button(parent = self.panel, id = wx.ID_ANY, 00128 label = _("Start &GRASS")) 00129 self.bstart.SetDefault() 00130 self.bexit = wx.Button(parent = self.panel, id = wx.ID_EXIT) 00131 self.bstart.SetMinSize((180, self.bexit.GetSize()[1])) 00132 self.bhelp = wx.Button(parent = self.panel, id = wx.ID_HELP) 00133 self.bbrowse = wx.Button(parent = self.panel, id = wx.ID_ANY, 00134 label = _("&Browse")) 00135 self.bmapset = wx.Button(parent = self.panel, id = wx.ID_ANY, 00136 label = _("&Create mapset")) 00137 self.bwizard = wx.Button(parent = self.panel, id = wx.ID_ANY, 00138 label = _("&Location wizard")) 00139 self.manageloc = wx.Choice(parent = self.panel, id = wx.ID_ANY, 00140 choices = [_('Rename mapset'), _('Rename location'), 00141 _('Delete mapset'), _('Delete location')]) 00142 self.manageloc.SetSelection(0) 00143 00144 # textinputs 00145 self.tgisdbase = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY, value = "", size = (300, -1), 00146 style = wx.TE_PROCESS_ENTER) 00147 00148 # Locations 00149 self.lpanel = wx.Panel(parent = self.panel, id = wx.ID_ANY) 00150 self.lblocations = GListBox(parent = self.lpanel, 00151 id = wx.ID_ANY, size = (180, 200), 00152 choices = self.listOfLocations) 00153 00154 self.lblocations.SetColumnWidth(0, 180) 00155 00156 # TODO: sort; but keep PERMANENT on top of list 00157 # Mapsets 00158 self.mpanel = wx.Panel(parent = self.panel, id = wx.ID_ANY) 00159 self.lbmapsets = GListBox(parent = self.mpanel, 00160 id = wx.ID_ANY, size = (180, 200), 00161 choices = self.listOfMapsets) 00162 00163 self.lbmapsets.SetColumnWidth(0, 180) 00164 00165 # layout & properties 00166 self._set_properties() 00167 self._do_layout() 00168 00169 # events 00170 self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse) 00171 self.bstart.Bind(wx.EVT_BUTTON, self.OnStart) 00172 self.bexit.Bind(wx.EVT_BUTTON, self.OnExit) 00173 self.bhelp.Bind(wx.EVT_BUTTON, self.OnHelp) 00174 self.bmapset.Bind(wx.EVT_BUTTON, self.OnCreateMapset) 00175 self.bwizard.Bind(wx.EVT_BUTTON, self.OnWizard) 00176 self.manageloc.Bind(wx.EVT_CHOICE, self.OnManageLoc) 00177 self.lblocations.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelectLocation) 00178 self.lbmapsets.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelectMapset) 00179 self.lbmapsets.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnStart) 00180 self.tgisdbase.Bind(wx.EVT_TEXT_ENTER, self.OnSetDatabase) 00181 self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) 00182 00183 def _set_properties(self): 00184 """!Set frame properties""" 00185 self.SetTitle(_("Welcome to GRASS GIS")) 00186 self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, "grass.ico"), 00187 wx.BITMAP_TYPE_ICO)) 00188 00189 self.lwelcome.SetForegroundColour(wx.Colour(35, 142, 35)) 00190 self.lwelcome.SetFont(wx.Font(13, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, "")) 00191 00192 self.bstart.SetForegroundColour(wx.Colour(35, 142, 35)) 00193 self.bstart.SetToolTipString(_("Enter GRASS session")) 00194 self.bstart.Enable(False) 00195 self.bmapset.Enable(False) 00196 self.manageloc.Enable(False) 00197 00198 # set database 00199 if not self.gisdbase: 00200 # sets an initial path for gisdbase if nothing in GISRC 00201 if os.path.isdir(os.getenv("HOME")): 00202 self.gisdbase = os.getenv("HOME") 00203 else: 00204 self.gisdbase = os.getcwd() 00205 try: 00206 self.tgisdbase.SetValue(self.gisdbase) 00207 except UnicodeDecodeError: 00208 wx.MessageBox(parent = self, caption = _("Error"), 00209 message = _("Unable to set GRASS database. " 00210 "Check your locale settings."), 00211 style = wx.OK | wx.ICON_ERROR | wx.CENTRE) 00212 00213 self.OnSetDatabase(None) 00214 location = self.GetRCValue("LOCATION_NAME") 00215 if location == "<UNKNOWN>" or \ 00216 not os.path.isdir(os.path.join(self.gisdbase, location)): 00217 location = None 00218 00219 if location: 00220 # list of locations 00221 self.UpdateLocations(self.gisdbase) 00222 try: 00223 self.lblocations.SetSelection(self.listOfLocations.index(location), 00224 force = True) 00225 self.lblocations.EnsureVisible(self.listOfLocations.index(location)) 00226 except ValueError: 00227 print >> sys.stderr, _("ERROR: Location <%s> not found") % \ 00228 (utils.UnicodeString(location)) 00229 00230 # list of mapsets 00231 self.UpdateMapsets(os.path.join(self.gisdbase, location)) 00232 mapset = self.GetRCValue("MAPSET") 00233 if mapset: 00234 try: 00235 self.lbmapsets.SetSelection(self.listOfMapsets.index(mapset), 00236 force = True) 00237 self.lbmapsets.EnsureVisible(self.listOfMapsets.index(mapset)) 00238 except ValueError: 00239 self.lbmapsets.Clear() 00240 print >> sys.stderr, _("ERROR: Mapset <%s> not found") % \ 00241 (utils.UnicodeString(mapset)) 00242 00243 def _do_layout(self): 00244 label_style = wx.ADJUST_MINSIZE | wx.ALIGN_CENTER_HORIZONTAL 00245 00246 sizer = wx.BoxSizer(wx.VERTICAL) 00247 dbase_sizer = wx.BoxSizer(wx.HORIZONTAL) 00248 location_sizer = wx.FlexGridSizer(rows = 1, cols = 2, vgap = 4, hgap = 4) 00249 select_boxsizer = wx.StaticBoxSizer(self.select_box, wx.VERTICAL) 00250 select_sizer = wx.FlexGridSizer(rows = 2, cols = 2, vgap = 4, hgap = 4) 00251 manage_boxsizer = wx.StaticBoxSizer(self.manage_box, wx.VERTICAL) 00252 manage_sizer = wx.BoxSizer(wx.VERTICAL) 00253 btns_sizer = wx.BoxSizer(wx.HORIZONTAL) 00254 00255 # gis data directory 00256 dbase_sizer.Add(item = self.ldbase, proportion = 0, 00257 flag = wx.ALIGN_CENTER_VERTICAL | 00258 wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 00259 border = 3) 00260 dbase_sizer.Add(item = self.tgisdbase, proportion = 0, 00261 flag = wx.ALIGN_CENTER_VERTICAL | 00262 wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 00263 border = 3) 00264 dbase_sizer.Add(item = self.bbrowse, proportion = 0, 00265 flag = wx.ALIGN_CENTER_VERTICAL | 00266 wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 00267 border = 3) 00268 00269 # select sizer 00270 select_sizer.Add(item = self.llocation, proportion = 0, 00271 flag = label_style | wx.ALL, 00272 border = 3) 00273 select_sizer.Add(item = self.lmapset, proportion = 0, 00274 flag = label_style | wx.ALL, 00275 border = 3) 00276 select_sizer.Add(item = self.lpanel, proportion = 0, 00277 flag = wx.ADJUST_MINSIZE | 00278 wx.ALIGN_CENTER_VERTICAL | 00279 wx.ALIGN_CENTER_HORIZONTAL) 00280 select_sizer.Add(item = self.mpanel, proportion = 0, 00281 flag = wx.ADJUST_MINSIZE | 00282 wx.ALIGN_CENTER_VERTICAL | 00283 wx.ALIGN_CENTER_HORIZONTAL) 00284 00285 select_boxsizer.Add(item = select_sizer, proportion = 0) 00286 00287 # define new location and mapset 00288 manage_sizer.Add(item = self.ldefine, proportion = 0, 00289 flag = label_style | wx.ALL, 00290 border = 3) 00291 manage_sizer.Add(item = self.bwizard, proportion = 0, 00292 flag = label_style | wx.BOTTOM, 00293 border = 5) 00294 manage_sizer.Add(item = self.lcreate, proportion = 0, 00295 flag = label_style | wx.ALL, 00296 border = 3) 00297 manage_sizer.Add(item = self.bmapset, proportion = 0, 00298 flag = label_style | wx.BOTTOM, 00299 border = 5) 00300 manage_sizer.Add(item = self.lmanageloc, proportion = 0, 00301 flag = label_style | wx.ALL, 00302 border = 3) 00303 manage_sizer.Add(item = self.manageloc, proportion = 0, 00304 flag = label_style | wx.BOTTOM, 00305 border = 5) 00306 00307 manage_boxsizer.Add(item = manage_sizer, proportion = 0) 00308 00309 # location sizer 00310 location_sizer.Add(item = select_boxsizer, proportion = 0, 00311 flag = wx.ADJUST_MINSIZE | 00312 wx.ALIGN_CENTER_VERTICAL | 00313 wx.ALIGN_CENTER_HORIZONTAL | 00314 wx.RIGHT | wx.LEFT | wx.EXPAND, 00315 border = 3) # GISDBASE setting 00316 location_sizer.Add(item = manage_boxsizer, proportion = 0, 00317 flag = wx.ADJUST_MINSIZE | 00318 wx.ALIGN_TOP | 00319 wx.ALIGN_CENTER_HORIZONTAL | 00320 wx.RIGHT | wx.EXPAND, 00321 border = 3) 00322 00323 # buttons 00324 btns_sizer.Add(item = self.bstart, proportion = 0, 00325 flag = wx.ALIGN_CENTER_HORIZONTAL | 00326 wx.ALIGN_CENTER_VERTICAL | 00327 wx.ALL, 00328 border = 5) 00329 btns_sizer.Add(item = self.bexit, proportion = 0, 00330 flag = wx.ALIGN_CENTER_HORIZONTAL | 00331 wx.ALIGN_CENTER_VERTICAL | 00332 wx.ALL, 00333 border = 5) 00334 btns_sizer.Add(item = self.bhelp, proportion = 0, 00335 flag = wx.ALIGN_CENTER_HORIZONTAL | 00336 wx.ALIGN_CENTER_VERTICAL | 00337 wx.ALL, 00338 border = 5) 00339 00340 # main sizer 00341 sizer.Add(item = self.hbitmap, 00342 proportion = 0, 00343 flag = wx.ALIGN_CENTER_VERTICAL | 00344 wx.ALIGN_CENTER_HORIZONTAL | 00345 wx.ALL, 00346 border = 3) # image 00347 sizer.Add(item = self.lwelcome, # welcome message 00348 proportion = 0, 00349 flag = wx.ALIGN_CENTER_VERTICAL | 00350 wx.ALIGN_CENTER_HORIZONTAL | 00351 wx.BOTTOM, 00352 border=1) 00353 sizer.Add(item = self.ltitle, # title 00354 proportion = 0, 00355 flag = wx.ALIGN_CENTER_VERTICAL | 00356 wx.ALIGN_CENTER_HORIZONTAL) 00357 sizer.Add(item = dbase_sizer, proportion = 0, 00358 flag = wx.ALIGN_CENTER_HORIZONTAL | 00359 wx.RIGHT | wx.LEFT, 00360 border = 1) # GISDBASE setting 00361 sizer.Add(item = location_sizer, proportion = 1, 00362 flag = wx.ALIGN_CENTER_VERTICAL | 00363 wx.ALIGN_CENTER_HORIZONTAL | 00364 wx.RIGHT | wx.LEFT, 00365 border = 1) 00366 sizer.Add(item = btns_sizer, proportion = 0, 00367 flag = wx.ALIGN_CENTER_VERTICAL | 00368 wx.ALIGN_CENTER_HORIZONTAL | 00369 wx.RIGHT | wx.LEFT, 00370 border = 1) 00371 00372 self.panel.SetAutoLayout(True) 00373 self.panel.SetSizer(sizer) 00374 sizer.Fit(self.panel) 00375 sizer.SetSizeHints(self) 00376 00377 self.Layout() 00378 00379 def _readGisRC(self): 00380 """ 00381 Read variables from $HOME/.grassrc6 file 00382 """ 00383 00384 grassrc = {} 00385 00386 gisrc = os.getenv("GISRC") 00387 00388 if gisrc and os.path.isfile(gisrc): 00389 try: 00390 rc = open(gisrc, "r") 00391 for line in rc.readlines(): 00392 key, val = line.split(":", 1) 00393 grassrc[key.strip()] = utils.DecodeString(val.strip()) 00394 finally: 00395 rc.close() 00396 00397 return grassrc 00398 00399 def GetRCValue(self, value): 00400 """!Return GRASS variable (read from GISRC) 00401 """ 00402 if self.grassrc.has_key(value): 00403 return self.grassrc[value] 00404 else: 00405 return None 00406 00407 def OnWizard(self, event): 00408 """!Location wizard started""" 00409 from gui_modules import location_wizard 00410 gWizard = location_wizard.LocationWizard(parent = self, 00411 grassdatabase = self.tgisdbase.GetValue()) 00412 if gWizard.location != None: 00413 self.OnSetDatabase(event) 00414 self.UpdateMapsets(os.path.join(self.gisdbase, gWizard.location)) 00415 self.lblocations.SetSelection(self.listOfLocations.index(gWizard.location)) 00416 self.lbmapsets.SetSelection(0) 00417 00418 def OnManageLoc(self, event): 00419 """!Location management choice control handler 00420 """ 00421 sel = event.GetSelection() 00422 if sel == 0: 00423 self.RenameMapset() 00424 elif sel == 1: 00425 self.RenameLocation() 00426 elif sel == 2: 00427 self.DeleteMapset() 00428 elif sel == 3: 00429 self.DeleteLocation() 00430 00431 event.Skip() 00432 00433 def RenameMapset(self): 00434 """!Rename selected mapset 00435 """ 00436 location = utils.UnicodeString(self.listOfLocations[self.lblocations.GetSelection()]) 00437 mapset = utils.UnicodeString(self.listOfMapsets[self.lbmapsets.GetSelection()]) 00438 if mapset == 'PERMANENT': 00439 GMessage(parent = self, 00440 message = _('Mapset <PERMANENT> is required for valid GRASS location.\n\n' 00441 'This mapset cannot be renamed.')) 00442 return 00443 00444 dlg = wx.TextEntryDialog(parent = self, 00445 message = _('Current name: %s\n\nEnter new name:') % mapset, 00446 caption = _('Rename selected mapset')) 00447 00448 if dlg.ShowModal() == wx.ID_OK: 00449 newmapset = dlg.GetValue() 00450 if newmapset == mapset: 00451 dlg.Destroy() 00452 return 00453 00454 if newmapset in self.listOfMapsets: 00455 wx.MessageBox(parent = self, 00456 caption = _('Message'), 00457 message = _('Unable to rename mapset.\n\n' 00458 'Mapset <%s> already exists in location.') % newmapset, 00459 style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE) 00460 else: 00461 try: 00462 os.rename(os.path.join(self.gisdbase, location, mapset), 00463 os.path.join(self.gisdbase, location, newmapset)) 00464 self.OnSelectLocation(None) 00465 self.lbmapsets.SetSelection(self.listOfMapsets.index(newmapset)) 00466 except StandardError, e: 00467 wx.MessageBox(parent = self, 00468 caption = _('Error'), 00469 message = _('Unable to rename mapset.\n\n%s') % e, 00470 style = wx.OK | wx.ICON_ERROR | wx.CENTRE) 00471 00472 dlg.Destroy() 00473 00474 def RenameLocation(self): 00475 """!Rename selected location 00476 """ 00477 location = utils.UnicodeString(self.listOfLocations[self.lblocations.GetSelection()]) 00478 00479 dlg = wx.TextEntryDialog(parent = self, 00480 message = _('Current name: %s\n\nEnter new name:') % location, 00481 caption = _('Rename selected location')) 00482 00483 if dlg.ShowModal() == wx.ID_OK: 00484 newlocation = dlg.GetValue() 00485 if newlocation == location: 00486 dlg.Destroy() 00487 return 00488 00489 if newlocation in self.listOfLocations: 00490 wx.MessageBox(parent = self, 00491 caption = _('Message'), 00492 message = _('Unable to rename location.\n\n' 00493 'Location <%s> already exists in GRASS database.') % newlocation, 00494 style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE) 00495 else: 00496 try: 00497 os.rename(os.path.join(self.gisdbase, location), 00498 os.path.join(self.gisdbase, newlocation)) 00499 self.UpdateLocations(self.gisdbase) 00500 self.lblocations.SetSelection(self.listOfLocations.index(newlocation)) 00501 self.UpdateMapsets(newlocation) 00502 except StandardError, e: 00503 wx.MessageBox(parent = self, 00504 caption = _('Error'), 00505 message = _('Unable to rename location.\n\n%s') % e, 00506 style = wx.OK | wx.ICON_ERROR | wx.CENTRE) 00507 00508 dlg.Destroy() 00509 00510 def DeleteMapset(self): 00511 """!Delete selected mapset 00512 """ 00513 location = self.listOfLocations[self.lblocations.GetSelection()] 00514 mapset = self.listOfMapsets[self.lbmapsets.GetSelection()] 00515 if mapset == 'PERMANENT': 00516 GMessage(parent = self, 00517 message = _('Mapset <PERMANENT> is required for valid GRASS location.\n\n' 00518 'This mapset cannot be deleted.')) 00519 return 00520 00521 dlg = wx.MessageDialog(parent = self, message = _("Do you want to continue with deleting mapset <%(mapset)s> " 00522 "from location <%(location)s>?\n\n" 00523 "ALL MAPS included in this mapset will be " 00524 "PERMANENTLY DELETED!") % {'mapset' : mapset, 00525 'location' : location}, 00526 caption = _("Delete selected mapset"), 00527 style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) 00528 00529 if dlg.ShowModal() == wx.ID_YES: 00530 try: 00531 shutil.rmtree(os.path.join(self.gisdbase, location, mapset)) 00532 self.OnSelectLocation(None) 00533 self.lbmapsets.SetSelection(0) 00534 except: 00535 wx.MessageBox(message = _('Unable to delete mapset')) 00536 00537 dlg.Destroy() 00538 00539 def DeleteLocation(self): 00540 """ 00541 Delete selected location 00542 """ 00543 00544 location = self.listOfLocations[self.lblocations.GetSelection()] 00545 00546 dlg = wx.MessageDialog(parent = self, message = _("Do you want to continue with deleting " 00547 "location <%s>?\n\n" 00548 "ALL MAPS included in this location will be " 00549 "PERMANENTLY DELETED!") % (location), 00550 caption = _("Delete selected location"), 00551 style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) 00552 00553 if dlg.ShowModal() == wx.ID_YES: 00554 try: 00555 shutil.rmtree(os.path.join(self.gisdbase, location)) 00556 self.UpdateLocations(self.gisdbase) 00557 self.lblocations.SetSelection(0) 00558 self.OnSelectLocation(None) 00559 self.lbmapsets.SetSelection(0) 00560 except: 00561 wx.MessageBox(message = _('Unable to delete location')) 00562 00563 dlg.Destroy() 00564 00565 def UpdateLocations(self, dbase): 00566 """!Update list of locations""" 00567 try: 00568 self.listOfLocations = utils.GetListOfLocations(dbase) 00569 except UnicodeEncodeError: 00570 wx.MessageBox(parent = self, caption = _("Error"), 00571 message = _("Unable to set GRASS database. " 00572 "Check your locale settings."), 00573 style = wx.OK | wx.ICON_ERROR | wx.CENTRE) 00574 00575 self.lblocations.Clear() 00576 self.lblocations.InsertItems(self.listOfLocations, 0) 00577 00578 if len(self.listOfLocations) > 0: 00579 self.lblocations.SetSelection(0) 00580 else: 00581 self.lblocations.SetSelection(wx.NOT_FOUND) 00582 00583 return self.listOfLocations 00584 00585 def UpdateMapsets(self, location): 00586 """!Update list of mapsets""" 00587 self.FormerMapsetSelection = wx.NOT_FOUND # for non-selectable item 00588 00589 self.listOfMapsetsSelectable = list() 00590 self.listOfMapsets = utils.GetListOfMapsets(self.gisdbase, location) 00591 00592 self.lbmapsets.Clear() 00593 00594 # disable mapset with denied permission 00595 locationName = os.path.basename(location) 00596 00597 ret = gcmd.RunCommand('g.mapset', 00598 read = True, 00599 flags = 'l', 00600 location = locationName, 00601 gisdbase = self.gisdbase) 00602 00603 if ret: 00604 for line in ret.splitlines(): 00605 self.listOfMapsetsSelectable += line.split(' ') 00606 else: 00607 gcmd.RunCommand("g.gisenv", 00608 set = "GISDBASE=%s" % self.gisdbase) 00609 gcmd.RunCommand("g.gisenv", 00610 set = "LOCATION_NAME=%s" % locationName) 00611 gcmd.RunCommand("g.gisenv", 00612 set = "MAPSET=PERMANENT") 00613 # first run only 00614 self.listOfMapsetsSelectable = copy.copy(self.listOfMapsets) 00615 00616 disabled = [] 00617 idx = 0 00618 for mapset in self.listOfMapsets: 00619 if mapset not in self.listOfMapsetsSelectable or \ 00620 os.path.isfile(os.path.join(self.gisdbase, 00621 locationName, 00622 mapset, ".gislock")): 00623 disabled.append(idx) 00624 idx += 1 00625 00626 self.lbmapsets.InsertItems(self.listOfMapsets, 0, disabled = disabled) 00627 00628 return self.listOfMapsets 00629 00630 def OnSelectLocation(self, event): 00631 """!Location selected""" 00632 if event: 00633 self.lblocations.SetSelection(event.GetIndex()) 00634 00635 if self.lblocations.GetSelection() != wx.NOT_FOUND: 00636 self.UpdateMapsets(os.path.join(self.gisdbase, 00637 self.listOfLocations[self.lblocations.GetSelection()])) 00638 else: 00639 self.listOfMapsets = [] 00640 00641 disabled = [] 00642 idx = 0 00643 try: 00644 locationName = self.listOfLocations[self.lblocations.GetSelection()] 00645 except IndexError: 00646 locationName = '' 00647 00648 for mapset in self.listOfMapsets: 00649 if mapset not in self.listOfMapsetsSelectable or \ 00650 os.path.isfile(os.path.join(self.gisdbase, 00651 locationName, 00652 mapset, ".gislock")): 00653 disabled.append(idx) 00654 idx += 1 00655 00656 self.lbmapsets.Clear() 00657 self.lbmapsets.InsertItems(self.listOfMapsets, 0, disabled = disabled) 00658 00659 if len(self.listOfMapsets) > 0: 00660 self.lbmapsets.SetSelection(0) 00661 if locationName: 00662 # enable start button when location and mapset is selected 00663 self.bstart.Enable() 00664 self.bmapset.Enable() 00665 self.manageloc.Enable() 00666 else: 00667 self.lbmapsets.SetSelection(wx.NOT_FOUND) 00668 self.bstart.Enable(False) 00669 self.bmapset.Enable(False) 00670 self.manageloc.Enable(False) 00671 00672 def OnSelectMapset(self, event): 00673 """!Mapset selected""" 00674 self.lbmapsets.SetSelection(event.GetIndex()) 00675 00676 if event.GetText() not in self.listOfMapsetsSelectable: 00677 self.lbmapsets.SetSelection(self.FormerMapsetSelection) 00678 else: 00679 self.FormerMapsetSelection = event.GetIndex() 00680 event.Skip() 00681 00682 def OnSetDatabase(self, event): 00683 """!Database set""" 00684 self.gisdbase = self.tgisdbase.GetValue() 00685 00686 self.UpdateLocations(self.gisdbase) 00687 00688 self.OnSelectLocation(None) 00689 00690 def OnBrowse(self, event): 00691 """'Browse' button clicked""" 00692 grassdata = None 00693 00694 dlg = wx.DirDialog(self, _("Choose GIS Data Directory:"), 00695 style = wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON) 00696 if dlg.ShowModal() == wx.ID_OK: 00697 self.gisdbase = dlg.GetPath() 00698 self.tgisdbase.SetValue(self.gisdbase) 00699 self.OnSetDatabase(event) 00700 00701 dlg.Destroy() 00702 00703 def OnCreateMapset(self,event): 00704 """!Create new mapset""" 00705 self.gisdbase = self.tgisdbase.GetValue() 00706 location = self.listOfLocations[self.lblocations.GetSelection()] 00707 00708 dlg = wx.TextEntryDialog(parent = self, 00709 message = _('Enter name for new mapset:'), 00710 caption = _('Create new mapset')) 00711 00712 if dlg.ShowModal() == wx.ID_OK: 00713 mapset = dlg.GetValue() 00714 try: 00715 os.mkdir(os.path.join(self.gisdbase, location, mapset)) 00716 # copy WIND file and its permissions from PERMANENT and set permissions to u+rw,go+r 00717 shutil.copy(os.path.join(self.gisdbase, location, 'PERMANENT', 'WIND'), 00718 os.path.join(self.gisdbase, location, mapset)) 00719 # os.chmod(os.path.join(database,location,mapset,'WIND'), 0644) 00720 self.OnSelectLocation(None) 00721 self.lbmapsets.SetSelection(self.listOfMapsets.index(mapset)) 00722 except StandardError, e: 00723 dlg = wx.MessageDialog(parent = self, message = _("Unable to create new mapset: %s") % e, 00724 caption = _("Error"), style = wx.OK | wx.ICON_ERROR) 00725 dlg.ShowModal() 00726 dlg.Destroy() 00727 return False 00728 00729 self.bstart.SetFocus() 00730 00731 return True 00732 00733 def OnStart(self, event): 00734 """'Start GRASS' button clicked""" 00735 dbase = self.tgisdbase.GetValue() 00736 location = self.listOfLocations[self.lblocations.GetSelection()] 00737 mapset = self.listOfMapsets[self.lbmapsets.GetSelection()] 00738 00739 lockfile = os.path.join(dbase, location, mapset, '.gislock') 00740 if os.path.isfile(lockfile): 00741 dlg = wx.MessageDialog(parent = self, 00742 message = _("GRASS is already running in selected mapset <%(mapset)s>\n" 00743 "(file %(lock)s found).\n\n" 00744 "Concurrent use not allowed.\n\n" 00745 "Do you want to try to remove .gislock (note that you " 00746 "need permission for this operation) and continue?") % 00747 { 'mapset' : mapset, 'lock' : lockfile }, 00748 caption = _("Lock file found"), 00749 style = wx.YES_NO | wx.NO_DEFAULT | 00750 wx.ICON_QUESTION | wx.CENTRE) 00751 00752 ret = dlg.ShowModal() 00753 dlg.Destroy() 00754 if ret == wx.ID_YES: 00755 dlg1 = wx.MessageDialog(parent = self, 00756 message = _("ARE YOU REALLY SURE?\n\n" 00757 "If you really are running another GRASS session doing this " 00758 "could corrupt your data. Have another look in the processor " 00759 "manager just to be sure..."), 00760 caption = _("Lock file found"), 00761 style = wx.YES_NO | wx.NO_DEFAULT | 00762 wx.ICON_QUESTION | wx.CENTRE) 00763 00764 ret = dlg1.ShowModal() 00765 dlg1.Destroy() 00766 00767 if ret == wx.ID_YES: 00768 try: 00769 os.remove(lockfile) 00770 except IOError, e: 00771 GError(_("Unable to remove '%(lock)s'.\n\n" 00772 "Details: %(reason)s") % { 'lock' : lockfile, 'reason' : e}) 00773 else: 00774 return 00775 else: 00776 return 00777 00778 gcmd.RunCommand("g.gisenv", 00779 set = "GISDBASE=%s" % dbase) 00780 gcmd.RunCommand("g.gisenv", 00781 set = "LOCATION_NAME=%s" % location) 00782 gcmd.RunCommand("g.gisenv", 00783 set = "MAPSET=%s" % mapset) 00784 00785 self.Destroy() 00786 sys.exit(0) 00787 00788 def OnExit(self, event): 00789 """'Exit' button clicked""" 00790 self.Destroy() 00791 sys.exit (2) 00792 00793 def OnHelp(self, event): 00794 """'Help' button clicked""" 00795 # help text in lib/init/helptext.html 00796 file = os.path.join(self.gisbase, "docs", "html", "helptext.html") 00797 00798 helpFrame = HelpFrame(parent = self, id = wx.ID_ANY, 00799 title = _("GRASS Quickstart"), 00800 size = (640, 480), 00801 file = file) 00802 helpFrame.Show(True) 00803 00804 event.Skip() 00805 00806 def OnCloseWindow(self, event): 00807 """!Close window event""" 00808 event.Skip() 00809 sys.exit(2) 00810 00811 class GListBox(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin): 00812 """!Use wx.ListCtrl instead of wx.ListBox, different style for 00813 non-selectable items (e.g. mapsets with denied permission)""" 00814 def __init__(self, parent, id, size, 00815 choices, disabled = []): 00816 wx.ListCtrl.__init__(self, parent, id, size = size, 00817 style = wx.LC_REPORT | wx.LC_NO_HEADER | wx.LC_SINGLE_SEL | 00818 wx.BORDER_SUNKEN) 00819 00820 listmix.ListCtrlAutoWidthMixin.__init__(self) 00821 00822 self.InsertColumn(0, '') 00823 00824 self.selected = wx.NOT_FOUND 00825 00826 self._LoadData(choices, disabled) 00827 00828 def _LoadData(self, choices, disabled = []): 00829 """!Load data into list 00830 00831 @param choices list of item 00832 @param disabled list of indeces of non-selectable items 00833 """ 00834 idx = 0 00835 for item in choices: 00836 index = self.InsertStringItem(sys.maxint, item) 00837 self.SetStringItem(index, 0, item) 00838 00839 if idx in disabled: 00840 self.SetItemTextColour(idx, wx.Colour(150, 150, 150)) 00841 idx += 1 00842 00843 def Clear(self): 00844 self.DeleteAllItems() 00845 00846 def InsertItems(self, choices, pos, disabled = []): 00847 self._LoadData(choices, disabled) 00848 00849 def SetSelection(self, item, force = False): 00850 if item != wx.NOT_FOUND and \ 00851 (platform.system() != 'Windows' or force): 00852 ### Windows -> FIXME 00853 self.SetItemState(item, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED) 00854 00855 self.selected = item 00856 00857 def GetSelection(self): 00858 return self.selected 00859 00860 class StartUp(wx.App): 00861 """!Start-up application""" 00862 00863 def OnInit(self): 00864 wx.InitAllImageHandlers() 00865 StartUp = GRASSStartup() 00866 StartUp.CenterOnScreen() 00867 self.SetTopWindow(StartUp) 00868 StartUp.Show() 00869 00870 if StartUp.GetRCValue("LOCATION_NAME") == "<UNKNOWN>": 00871 wx.MessageBox(parent = StartUp, 00872 caption = _('Starting GRASS for the first time'), 00873 message = _('GRASS needs a directory in which to store its data. ' 00874 'Create one now if you have not already done so. ' 00875 'A popular choice is "grassdata", located in ' 00876 'your home directory.'), 00877 style = wx.OK | wx.ICON_ERROR | wx.CENTRE) 00878 00879 StartUp.OnBrowse(None) 00880 00881 return 1 00882 00883 if __name__ == "__main__": 00884 00885 if os.getenv("GISBASE") is None: 00886 print >> sys.stderr, "Failed to start GUI, GRASS GIS is not running." 00887 else: 00888 import gettext 00889 gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True) 00890 00891 import gui_modules.gcmd as gcmd 00892 import gui_modules.utils as utils 00893 00894 GRASSStartUp = StartUp(0) 00895 GRASSStartUp.MainLoop()