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