GRASS Programmer's Manual
6.4.2(2012)
|
00001 """! 00002 @package location_wizard.py 00003 00004 @brief Location wizard - creates a new GRASS Location. User can choose 00005 from multiple methods. 00006 00007 Classes: 00008 - BaseClass 00009 - TitledPage 00010 - DatabasePage 00011 - CoordinateSystemPage 00012 - ProjectionsPage 00013 - ItemList 00014 - ProjParamsPage 00015 - DatumPage 00016 - EllipsePage 00017 - GeoreferencedFilePage 00018 - EPSGPage 00019 - CustomPage 00020 - SummaryPage 00021 - RegionDef 00022 - LocationWizard 00023 - SelectTransformDialog 00024 00025 (C) 2007-2011 by the GRASS Development Team 00026 00027 This program is free software under the GNU General Public License 00028 (>=v2). Read the file COPYING that comes with GRASS for details. 00029 00030 @author Michael Barton 00031 @author Jachym Cepicky 00032 @author Martin Landa <landa.martin gmail.com> 00033 """ 00034 import os 00035 import shutil 00036 import string 00037 import sys 00038 import locale 00039 import platform 00040 00041 import wx 00042 import wx.lib.mixins.listctrl as listmix 00043 import wx.wizard as wiz 00044 import wx.lib.scrolledpanel as scrolled 00045 import time 00046 00047 import gcmd 00048 import globalvar 00049 import utils 00050 from grass.script import core as grass 00051 try: 00052 import subprocess 00053 except: 00054 CompatPath = os.path.join(globalvar.ETCWXDIR) 00055 sys.path.append(CompatPath) 00056 from compat import subprocess 00057 00058 global coordsys 00059 global north 00060 global south 00061 global east 00062 global west 00063 global resolution 00064 global wizerror 00065 global translist 00066 00067 class BaseClass(wx.Object): 00068 """!Base class providing basic methods""" 00069 def __init__(self): 00070 pass 00071 00072 def MakeLabel(self, text = "", style = wx.ALIGN_LEFT, parent = None): 00073 """!Make aligned label""" 00074 if not parent: 00075 parent = self 00076 return wx.StaticText(parent = parent, id = wx.ID_ANY, label = text, 00077 style = style) 00078 00079 def MakeTextCtrl(self, text = '', size = (100,-1), style = 0, parent = None): 00080 """!Generic text control""" 00081 if not parent: 00082 parent = self 00083 return wx.TextCtrl(parent = parent, id = wx.ID_ANY, value = text, 00084 size = size, style = style) 00085 00086 def MakeButton(self, text, id = wx.ID_ANY, size = (-1,-1), parent = None): 00087 """!Generic button""" 00088 if not parent: 00089 parent = self 00090 return wx.Button(parent = parent, id = id, label = text, 00091 size = size) 00092 00093 class TitledPage(BaseClass, wiz.WizardPageSimple): 00094 """!Class to make wizard pages. Generic methods to make labels, 00095 text entries, and buttons. 00096 """ 00097 def __init__(self, parent, title): 00098 00099 self.page = wiz.WizardPageSimple.__init__(self, parent) 00100 00101 # page title 00102 self.title = wx.StaticText(parent = self, id = wx.ID_ANY, label = title) 00103 self.title.SetFont(wx.Font(13, wx.SWISS, wx.NORMAL, wx.BOLD)) 00104 00105 # main sizers 00106 self.pagesizer = wx.BoxSizer(wx.VERTICAL) 00107 self.sizer = wx.GridBagSizer(vgap = 0, hgap = 0) 00108 00109 def DoLayout(self): 00110 """!Do page layout""" 00111 self.pagesizer.Add(item = self.title, proportion = 0, 00112 flag = wx.ALIGN_CENTRE | wx.ALL, 00113 border = 5) 00114 self.pagesizer.Add(item = wx.StaticLine(self, -1), proportion = 0, 00115 flag = wx.EXPAND | wx.ALL, 00116 border = 0) 00117 self.pagesizer.Add(item = self.sizer, proportion = 1, 00118 flag = wx.EXPAND) 00119 00120 self.SetAutoLayout(True) 00121 self.SetSizer(self.pagesizer) 00122 self.Layout() 00123 00124 class DatabasePage(TitledPage): 00125 """!Wizard page for setting GIS data directory and location name""" 00126 def __init__(self, wizard, parent, grassdatabase): 00127 TitledPage.__init__(self, wizard, _("Define GRASS Database and Location Name")) 00128 00129 self.grassdatabase = grassdatabase 00130 self.location = '' 00131 self.locTitle = '' 00132 00133 # buttons 00134 self.bbrowse = self.MakeButton(_("Browse")) 00135 00136 # text controls 00137 self.tgisdbase = self.MakeTextCtrl(grassdatabase, size = (300, -1)) 00138 self.tlocation = self.MakeTextCtrl("newLocation", size = (300, -1)) 00139 self.tlocTitle = self.MakeTextCtrl(size = (400, -1)) 00140 00141 # layout 00142 self.sizer.AddGrowableCol(3) 00143 self.sizer.Add(item = self.MakeLabel(_("GIS Data Directory:")), 00144 flag = wx.ALIGN_RIGHT | 00145 wx.ALIGN_CENTER_VERTICAL | 00146 wx.ALL, border = 5, 00147 pos = (1, 1)) 00148 self.sizer.Add(item = self.tgisdbase, 00149 flag = wx.ALIGN_LEFT | 00150 wx.ALIGN_CENTER_VERTICAL | 00151 wx.ALL, border = 5, 00152 pos = (1, 2)) 00153 self.sizer.Add(item = self.bbrowse, 00154 flag = wx.ALIGN_LEFT | 00155 wx.ALIGN_CENTER_VERTICAL | 00156 wx.ALL, border = 5, 00157 pos = (1, 3)) 00158 00159 self.sizer.Add(item = self.MakeLabel("%s:" % _("Project Location")), 00160 flag = wx.ALIGN_RIGHT | 00161 wx.ALIGN_CENTER_VERTICAL | 00162 wx.ALL, border = 5, 00163 pos = (2, 1)) 00164 self.sizer.Add(item = self.tlocation, 00165 flag = wx.ALIGN_LEFT | 00166 wx.ALIGN_CENTER_VERTICAL | 00167 wx.ALL, border = 5, 00168 pos = (2, 2)) 00169 00170 self.sizer.Add(item = self.MakeLabel("%s:" % _("Location Title")), 00171 flag = wx.ALIGN_RIGHT | 00172 wx.ALIGN_TOP | wx.ALIGN_CENTER_VERTICAL | 00173 wx.ALL, border = 5, 00174 pos = (3, 1)) 00175 self.sizer.Add(item = self.tlocTitle, 00176 flag = wx.ALIGN_LEFT | 00177 wx.ALIGN_CENTER_VERTICAL | 00178 wx.ALL, border = 5, 00179 pos = (3, 2), span = (1, 2)) 00180 00181 # bindings 00182 self.Bind(wx.EVT_BUTTON, self.OnBrowse, self.bbrowse) 00183 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging) 00184 self.tgisdbase.Bind(wx.EVT_TEXT, self.OnChangeName) 00185 self.tlocation.Bind(wx.EVT_TEXT, self.OnChangeName) 00186 00187 def OnChangeName(self, event): 00188 """!Name for new location was changed""" 00189 nextButton = wx.FindWindowById(wx.ID_FORWARD) 00190 if len(event.GetString()) > 0: 00191 if not nextButton.IsEnabled(): 00192 nextButton.Enable() 00193 else: 00194 nextButton.Disable() 00195 00196 event.Skip() 00197 00198 def OnBrowse(self, event): 00199 """!Choose GRASS data directory""" 00200 dlg = wx.DirDialog(self, _("Choose GRASS data directory:"), 00201 os.getcwd(), wx.DD_DEFAULT_STYLE) 00202 if dlg.ShowModal() == wx.ID_OK: 00203 self.grassdatabase = dlg.GetPath() 00204 self.tgisdbase.SetValue(self.grassdatabase) 00205 00206 dlg.Destroy() 00207 00208 def OnPageChanging(self, event = None): 00209 error = None 00210 if os.path.isdir(os.path.join(self.tgisdbase.GetValue(), self.tlocation.GetValue())): 00211 error = _("Location already exists in GRASS Database.") 00212 00213 if error: 00214 gcmd.GError(parent = self, 00215 message="%s <%s>.%s%s" % (_("Unable to create location"), 00216 str(self.tlocation.GetValue()), 00217 os.linesep, 00218 error)) 00219 event.Veto() 00220 return 00221 00222 self.location = self.tlocation.GetValue() 00223 self.grassdatabase = self.tgisdbase.GetValue() 00224 self.locTitle = self.tlocTitle.GetValue() 00225 if os.linesep in self.locTitle or \ 00226 len(self.locTitle) > 255: 00227 gcmd.GWarning(parent = self, 00228 message = _("Title of the location is limited only to one line and " 00229 "256 characters. The rest of the text will be ignored.")) 00230 self.locTitle = self.locTitle.split(os.linesep)[0][:255] 00231 00232 class CoordinateSystemPage(TitledPage): 00233 """!Wizard page for choosing method for location creation""" 00234 def __init__(self, wizard, parent): 00235 TitledPage.__init__(self, wizard, _("Choose method for creating a new location")) 00236 00237 self.parent = parent 00238 global coordsys 00239 00240 # toggles 00241 self.radio1 = wx.RadioButton(parent = self, id = wx.ID_ANY, 00242 label = _("Select coordinate system parameters from a list"), 00243 style = wx.RB_GROUP) 00244 self.radio2 = wx.RadioButton(parent = self, id = wx.ID_ANY, 00245 label = _("Select EPSG code of spatial reference system")) 00246 self.radio3 = wx.RadioButton(parent = self, id = wx.ID_ANY, 00247 label = _("Read projection and datum terms from a " 00248 "georeferenced data file")) 00249 self.radio4 = wx.RadioButton(parent = self, id = wx.ID_ANY, 00250 label = _("Read projection and datum terms from a " 00251 "WKT or PRJ file")) 00252 self.radio5 = wx.RadioButton(parent = self, id = wx.ID_ANY, 00253 label = _("Specify projection and datum terms using custom " 00254 "PROJ.4 parameters")) 00255 self.radio6 = wx.RadioButton(parent = self, id = wx.ID_ANY, 00256 label = _("Create an arbitrary non-earth coordinate system (XY)")) 00257 00258 # layout 00259 self.sizer.AddGrowableCol(1) 00260 self.sizer.SetVGap(10) 00261 self.sizer.Add(item = self.radio1, 00262 flag = wx.ALIGN_LEFT, pos = (1, 1)) 00263 self.sizer.Add(item = self.radio2, 00264 flag = wx.ALIGN_LEFT, pos = (2, 1)) 00265 self.sizer.Add(item = self.radio3, 00266 flag = wx.ALIGN_LEFT, pos = (3, 1)) 00267 self.sizer.Add(item = self.radio4, 00268 flag = wx.ALIGN_LEFT, pos = (4, 1)) 00269 self.sizer.Add(item = self.radio5, 00270 flag = wx.ALIGN_LEFT, pos = (5, 1)) 00271 self.sizer.Add(item = self.radio6, 00272 flag = wx.ALIGN_LEFT, pos = (6, 1)) 00273 00274 # bindings 00275 self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio1.GetId()) 00276 self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio2.GetId()) 00277 self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio3.GetId()) 00278 self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio4.GetId()) 00279 self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio5.GetId()) 00280 self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio6.GetId()) 00281 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 00282 00283 def OnEnterPage(self, event): 00284 global coordsys 00285 00286 if not coordsys: 00287 coordsys = "proj" 00288 self.radio1.SetValue(True) 00289 else: 00290 if coordsys == 'proj': 00291 self.radio1.SetValue(True) 00292 if coordsys == "epsg": 00293 self.radio2.SetValue(True) 00294 if coordsys == "file": 00295 self.radio3.SetValue(True) 00296 if coordsys == "wkt": 00297 self.radio4.SetValue(True) 00298 if coordsys == "custom": 00299 self.radio5.SetValue(True) 00300 if coordsys == "xy": 00301 self.radio6.SetValue(True) 00302 00303 if event.GetDirection(): 00304 if coordsys == 'proj': 00305 self.SetNext(self.parent.projpage) 00306 self.parent.sumpage.SetPrev(self.parent.datumpage) 00307 if coordsys == "epsg": 00308 self.SetNext(self.parent.epsgpage) 00309 self.parent.sumpage.SetPrev(self.parent.epsgpage) 00310 if coordsys == "file": 00311 self.SetNext(self.parent.filepage) 00312 self.parent.sumpage.SetPrev(self.parent.filepage) 00313 if coordsys == "wkt": 00314 self.SetNext(self.parent.wktpage) 00315 self.parent.sumpage.SetPrev(self.parent.wktpage) 00316 if coordsys == "custom": 00317 self.SetNext(self.parent.custompage) 00318 self.parent.sumpage.SetPrev(self.parent.custompage) 00319 if coordsys == "xy": 00320 self.SetNext(self.parent.sumpage) 00321 self.parent.sumpage.SetPrev(self.parent.csystemspage) 00322 00323 if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled(): 00324 wx.FindWindowById(wx.ID_FORWARD).Enable() 00325 00326 def SetVal(self, event): 00327 """!Choose method""" 00328 global coordsys 00329 if event.GetId() == self.radio1.GetId(): 00330 coordsys = "proj" 00331 self.SetNext(self.parent.projpage) 00332 self.parent.sumpage.SetPrev(self.parent.datumpage) 00333 elif event.GetId() == self.radio2.GetId(): 00334 coordsys = "epsg" 00335 self.SetNext(self.parent.epsgpage) 00336 self.parent.sumpage.SetPrev(self.parent.epsgpage) 00337 elif event.GetId() == self.radio3.GetId(): 00338 coordsys = "file" 00339 self.SetNext(self.parent.filepage) 00340 self.parent.sumpage.SetPrev(self.parent.filepage) 00341 elif event.GetId() == self.radio4.GetId(): 00342 coordsys = "wkt" 00343 self.SetNext(self.parent.wktpage) 00344 self.parent.sumpage.SetPrev(self.parent.wktpage) 00345 elif event.GetId() == self.radio5.GetId(): 00346 coordsys = "custom" 00347 self.SetNext(self.parent.custompage) 00348 self.parent.sumpage.SetPrev(self.parent.custompage) 00349 elif event.GetId() == self.radio6.GetId(): 00350 coordsys = "xy" 00351 self.SetNext(self.parent.sumpage) 00352 self.parent.sumpage.SetPrev(self.parent.csystemspage) 00353 00354 class ProjectionsPage(TitledPage): 00355 """!Wizard page for selecting projection (select coordinate system option)""" 00356 def __init__(self, wizard, parent): 00357 TitledPage.__init__(self, wizard, _("Choose projection")) 00358 00359 self.parent = parent 00360 self.proj = '' 00361 self.projdesc = '' 00362 self.p4proj = '' 00363 00364 # text input 00365 self.tproj = self.MakeTextCtrl("", size = (200,-1)) 00366 00367 # search box 00368 self.searchb = wx.SearchCtrl(self, size = (200,-1), 00369 style = wx.TE_PROCESS_ENTER) 00370 00371 # projection list 00372 self.projlist = ItemList(self, data = self.parent.projdesc.items(), 00373 columns = [_('Code'), _('Description')]) 00374 self.projlist.resizeLastColumn(30) 00375 00376 # layout 00377 self.sizer.AddGrowableCol(3) 00378 self.sizer.Add(item = self.MakeLabel(_("Projection code:")), 00379 flag = wx.ALIGN_LEFT | 00380 wx.ALIGN_CENTER_VERTICAL | 00381 wx.ALL, border = 5, pos = (1, 1)) 00382 self.sizer.Add(item = self.tproj, 00383 flag = wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL, 00384 border = 5, pos = (1, 2)) 00385 00386 self.sizer.Add(item = self.MakeLabel(_("Search in description:")), 00387 flag = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 00388 border = 5, pos = (2, 1)) 00389 self.sizer.Add(item = self.searchb, 00390 flag = wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL, 00391 border = 5, pos = (2, 2)) 00392 00393 self.sizer.AddGrowableRow(3) 00394 self.sizer.Add(item = self.projlist, 00395 flag = wx.EXPAND | 00396 wx.ALIGN_LEFT | 00397 wx.ALL, border = 5, pos = (3, 1), span = (1, 3)) 00398 00399 # events 00400 self.tproj.Bind(wx.EVT_TEXT, self.OnText) 00401 self.tproj.Bind(wx.EVT_TEXT_ENTER, self.OnText) 00402 self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnSearch) 00403 self.projlist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected) 00404 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging) 00405 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 00406 00407 def OnPageChanging(self,event): 00408 if event.GetDirection() and self.proj not in self.parent.projections.keys(): 00409 event.Veto() 00410 00411 def OnText(self, event): 00412 """!Projection name changed""" 00413 self.proj = event.GetString().lower() 00414 self.p4proj = '' 00415 nextButton = wx.FindWindowById(wx.ID_FORWARD) 00416 if self.proj not in self.parent.projections.keys() and nextButton.IsEnabled(): 00417 nextButton.Enable(False) 00418 00419 if self.proj in self.parent.projections.keys(): 00420 if self.proj == 'stp': 00421 wx.MessageBox('Currently State Plane projections must be selected using the ' 00422 'text-based setup (g.setproj), or entered by EPSG code or ' 00423 'custom PROJ.4 terms.', 00424 'Warning', wx.ICON_WARNING) 00425 self.proj = '' 00426 self.tproj.SetValue(self.proj) 00427 nextButton.Enable(False) 00428 return 00429 elif self.proj.lower() == 'll': 00430 self.p4proj = '+proj=longlat' 00431 else: 00432 self.p4proj = '+proj=' + self.proj.lower() 00433 self.projdesc = self.parent.projections[self.proj][0] 00434 nextButton.Enable() 00435 00436 def OnEnterPage(self, event): 00437 if len(self.proj) == 0: 00438 # disable 'next' button by default 00439 wx.FindWindowById(wx.ID_FORWARD).Enable(False) 00440 else: 00441 wx.FindWindowById(wx.ID_FORWARD).Enable(True) 00442 00443 event.Skip() 00444 00445 def OnSearch(self, event): 00446 """!Search projection by desc""" 00447 str = event.GetString() 00448 try: 00449 self.proj, self.projdesc = self.projlist.Search(index = [0,1], pattern = event.GetString()) 00450 except: 00451 self.proj = self.projdesc = '' 00452 00453 event.Skip() 00454 00455 def OnItemSelected(self, event): 00456 """!Projection selected""" 00457 index = event.m_itemIndex 00458 00459 # set values 00460 self.proj = self.projlist.GetItem(index, 0).GetText().lower() 00461 self.tproj.SetValue(self.proj) 00462 00463 event.Skip() 00464 00465 class ItemList(wx.ListCtrl, 00466 listmix.ListCtrlAutoWidthMixin, 00467 listmix.ColumnSorterMixin): 00468 """!Generic list (for projections, ellipsoids, etc.)""" 00469 00470 def __init__(self, parent, columns, data = None): 00471 wx.ListCtrl.__init__(self, parent = parent, id = wx.ID_ANY, 00472 style = wx.LC_REPORT | 00473 wx.LC_VIRTUAL | 00474 wx.LC_HRULES | 00475 wx.LC_VRULES | 00476 wx.LC_SINGLE_SEL | 00477 wx.LC_SORT_ASCENDING, size = (550, 125)) 00478 00479 # original data or None 00480 self.sourceData = data 00481 00482 # 00483 # insert columns 00484 # 00485 i = 0 00486 for column in columns: 00487 self.InsertColumn(i, column) 00488 i += 1 00489 00490 if self.sourceData: 00491 self.Populate() 00492 00493 for i in range(self.GetColumnCount()): 00494 self.SetColumnWidth(i, wx.LIST_AUTOSIZE_USEHEADER) 00495 if self.GetColumnWidth(i) < 80: 00496 self.SetColumnWidth(i, 80) 00497 00498 # 00499 # listmix 00500 # 00501 listmix.ListCtrlAutoWidthMixin.__init__(self) 00502 listmix.ColumnSorterMixin.__init__(self, self.GetColumnCount()) 00503 00504 # 00505 # add some attributes 00506 # 00507 self.attr1 = wx.ListItemAttr() 00508 self.attr1.SetBackgroundColour(wx.Colour(238,238,238)) 00509 self.attr2 = wx.ListItemAttr() 00510 self.attr2.SetBackgroundColour("white") 00511 self.il = wx.ImageList(16, 16) 00512 self.sm_up = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_GO_UP, wx.ART_TOOLBAR, 00513 (16,16))) 00514 self.sm_dn = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_GO_DOWN, wx.ART_TOOLBAR, 00515 (16,16))) 00516 self.SetImageList(self.il, wx.IMAGE_LIST_SMALL) 00517 00518 # 00519 # sort by first column 00520 # 00521 if self.sourceData: 00522 self.SortListItems(col = 0, ascending = True) 00523 00524 # 00525 # bindings 00526 # 00527 self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColumnClick) 00528 00529 def Populate(self, data = None, update = False): 00530 """!Populate list""" 00531 self.itemDataMap = {} 00532 self.itemIndexMap = [] 00533 00534 if data is None: 00535 data = self.sourceData 00536 elif update: 00537 self.sourceData = data 00538 00539 try: 00540 data.sort() 00541 self.DeleteAllItems() 00542 row = 0 00543 for value in data: 00544 self.itemDataMap[row] = [value[0]] 00545 for i in range(1, len(value)): 00546 self.itemDataMap[row].append(value[i]) 00547 self.itemIndexMap.append(row) 00548 row += 1 00549 00550 self.SetItemCount(row) 00551 00552 # set column width 00553 self.SetColumnWidth(0, 80) 00554 self.SetColumnWidth(1, 300) 00555 00556 self.SendSizeEvent() 00557 00558 except StandardError, e: 00559 wx.MessageBox(parent = self, 00560 message = _("Unable to read list: %s") % e, 00561 caption = _("Error"), style = wx.OK | wx.ICON_ERROR) 00562 00563 def OnColumnClick(self, event): 00564 """!Sort by column""" 00565 self._col = event.GetColumn() 00566 00567 # remove duplicated arrow symbol from column header 00568 # FIXME: should be done automatically 00569 info = wx.ListItem() 00570 info.m_mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE 00571 info.m_image = -1 00572 for column in range(self.GetColumnCount()): 00573 info.m_text = self.GetColumn(column).GetText() 00574 self.SetColumn(column, info) 00575 00576 event.Skip() 00577 00578 def GetSortImages(self): 00579 """!Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py""" 00580 return (self.sm_dn, self.sm_up) 00581 00582 def OnGetItemText(self, item, col): 00583 """!Get item text""" 00584 index = self.itemIndexMap[item] 00585 s = str(self.itemDataMap[index][col]) 00586 return s 00587 00588 def OnGetItemAttr(self, item): 00589 """!Get item attributes""" 00590 index = self.itemIndexMap[item] 00591 if ( index % 2) == 0: 00592 return self.attr2 00593 else: 00594 return self.attr1 00595 00596 def SortItems(self, sorter = cmp): 00597 """!Sort items""" 00598 items = list(self.itemDataMap.keys()) 00599 items.sort(self.Sorter) 00600 self.itemIndexMap = items 00601 00602 # redraw the list 00603 self.Refresh() 00604 00605 def Sorter(self, key1, key2): 00606 colName = self.GetColumn(self._col).GetText() 00607 ascending = self._colSortFlag[self._col] 00608 # convert always string 00609 item1 = self.itemDataMap[key1][self._col] 00610 item2 = self.itemDataMap[key2][self._col] 00611 00612 if type(item1) == type('') or type(item2) == type(''): 00613 cmpVal = locale.strcoll(str(item1), str(item2)) 00614 else: 00615 cmpVal = cmp(item1, item2) 00616 00617 00618 # If the items are equal then pick something else to make the sort value unique 00619 if cmpVal == 0: 00620 cmpVal = apply(cmp, self.GetSecondarySortValues(self._col, key1, key2)) 00621 00622 if ascending: 00623 return cmpVal 00624 else: 00625 return -cmpVal 00626 00627 def GetListCtrl(self): 00628 """!Used by listmix.ColumnSorterMixin""" 00629 return self 00630 00631 def Search (self, index, pattern): 00632 """!Search projection by description 00633 Return first found item or None 00634 """ 00635 if pattern == '': 00636 self.Populate(self.sourceData) 00637 return [] 00638 00639 data = [] 00640 pattern = pattern.lower() 00641 for i in range(len(self.sourceData)): 00642 for idx in index: 00643 try: 00644 value = str(self.sourceData[i][idx]).lower() 00645 if pattern in value: 00646 data.append(self.sourceData[i]) 00647 break 00648 except UnicodeDecodeError: 00649 # osgeo4w problem (should be fixed) 00650 pass 00651 00652 self.Populate(data) 00653 if len(data) > 0: 00654 return data[0] 00655 else: 00656 return [] 00657 00658 class ProjParamsPage(TitledPage): 00659 """!Wizard page for selecting method of setting coordinate system 00660 parameters (select coordinate system option) 00661 """ 00662 def __init__(self, wizard, parent): 00663 TitledPage.__init__(self, wizard, _("Choose projection parameters")) 00664 global coordsys 00665 00666 self.parent = parent 00667 self.panel = None 00668 self.prjParamSizer = None 00669 00670 self.pparam = dict() 00671 00672 self.p4projparams = '' 00673 self.projdesc = '' 00674 00675 self.sizer.AddGrowableCol(1) 00676 self.sizer.AddGrowableRow(1) 00677 00678 radioSBox = wx.StaticBox(parent = self, id = wx.ID_ANY, 00679 label = " %s " % _("Select datum or ellipsoid (next page)")) 00680 radioSBSizer = wx.StaticBoxSizer(radioSBox) 00681 self.sizer.Add(item = radioSBSizer, pos = (0, 1), 00682 flag = wx.EXPAND | wx.ALIGN_TOP | wx.TOP, border = 10) 00683 00684 self.radio1 = wx.RadioButton(parent = self, id = wx.ID_ANY, 00685 label = _("Datum with associated ellipsoid"), 00686 style = wx.RB_GROUP) 00687 self.radio2 = wx.RadioButton(parent = self, id = wx.ID_ANY, 00688 label = _("Ellipsoid only")) 00689 00690 # default button setting 00691 if self.radio1.GetValue() == False and self.radio2.GetValue() == False: 00692 self.radio1.SetValue(True) 00693 self.SetNext(self.parent.datumpage) 00694 # self.parent.sumpage.SetPrev(self.parent.datumpage) 00695 00696 radioSBSizer.Add(item = self.radio1, 00697 flag = wx.ALIGN_LEFT | wx.RIGHT, border = 20) 00698 radioSBSizer.Add(item = self.radio2, 00699 flag = wx.ALIGN_LEFT) 00700 00701 # bindings 00702 self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio1.GetId()) 00703 self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio2.GetId()) 00704 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChange) 00705 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 00706 00707 def OnParamEntry(self, event): 00708 """!Parameter value changed""" 00709 id = event.GetId() 00710 val = event.GetString() 00711 00712 if id not in self.pparam: 00713 event.Skip() 00714 return 00715 00716 param = self.pparam[id] 00717 win = self.FindWindowById(id) 00718 if param['type'] == 'zone': 00719 val = event.GetInt() 00720 if val < 1: 00721 win.SetValue(1) 00722 elif val > 60: 00723 win.SetValue(60) 00724 00725 if param['type'] == 'bool': 00726 param['value'] = event.GetSelection() 00727 else: 00728 param['value'] = val 00729 00730 event.Skip() 00731 00732 def OnPageChange(self,event=None): 00733 """!Go to next page""" 00734 if event.GetDirection(): 00735 self.p4projparams = '' 00736 for id, param in self.pparam.iteritems(): 00737 if param['type'] == 'bool': 00738 if param['value'] == False: 00739 continue 00740 else: 00741 self.p4projparams += (' +' + param['proj4']) 00742 else: 00743 if param['value'] is None: 00744 wx.MessageBox(parent = self, 00745 message = _('You must enter a value for %s') % param['desc'], 00746 caption = _('Error'), style = wx.ICON_ERROR | wx.CENTRE) 00747 event.Veto() 00748 else: 00749 self.p4projparams += (' +' + param['proj4'] + '=' + str(param['value'])) 00750 00751 def OnEnterPage(self,event): 00752 """!Page entered""" 00753 self.projdesc = self.parent.projections[self.parent.projpage.proj][0] 00754 if self.prjParamSizer is None: 00755 # entering page for the first time 00756 self.paramSBox = wx.StaticBox(parent = self, id = wx.ID_ANY, 00757 label = _(" Enter parameters for %s projection ") % self.projdesc) 00758 paramSBSizer = wx.StaticBoxSizer(self.paramSBox) 00759 00760 self.panel = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY) 00761 self.panel.SetupScrolling() 00762 00763 self.prjParamSizer = wx.GridBagSizer(vgap = 0, hgap = 0) 00764 00765 self.sizer.Add(item = paramSBSizer, pos = (1, 1), 00766 flag = wx.EXPAND) 00767 paramSBSizer.Add(item = self.panel, proportion = 1, 00768 flag = wx.ALIGN_CENTER | wx.EXPAND) 00769 00770 paramSBSizer.Fit(self.panel) 00771 self.panel.SetSizer(self.prjParamSizer) 00772 00773 if event.GetDirection(): 00774 self.prjParamSizer.Clear(True) 00775 self.paramSBox.SetLabel(_(" Enter parameters for %s projection ") % self.projdesc) 00776 self.pparam = dict() 00777 row = 0 00778 for paramgrp in self.parent.projections[self.parent.projpage.proj][1]: 00779 # get parameters 00780 id = wx.NewId() 00781 param = self.pparam[id] = { 'type' : self.parent.paramdesc[paramgrp[0]][0], 00782 'proj4': self.parent.paramdesc[paramgrp[0]][1], 00783 'desc' : self.parent.paramdesc[paramgrp[0]][2] } 00784 00785 # default values 00786 if param['type'] == 'bool': 00787 param['value'] = 0 00788 elif param['type'] == 'zone': 00789 param['value'] = 30 00790 param['desc'] += ' (1-60)' 00791 else: 00792 param['value'] = paramgrp[2] 00793 00794 label = wx.StaticText(parent = self.panel, id = wx.ID_ANY, label = param['desc'], 00795 style = wx.ALIGN_RIGHT | wx.ST_NO_AUTORESIZE) 00796 if param['type'] == 'bool': 00797 win = wx.Choice(parent = self.panel, id = id, size = (100,-1), 00798 choices = [_('No'), _('Yes')]) 00799 win.SetSelection(param['value']) 00800 win.Bind(wx.EVT_CHOICE, self.OnParamEntry) 00801 elif param['type'] == 'zone': 00802 win = wx.SpinCtrl(parent = self.panel, id = id, 00803 size = (100, -1), 00804 style = wx.SP_ARROW_KEYS | wx.SP_WRAP, 00805 min = 1, max = 60) 00806 win.SetValue(param['value']) 00807 win.Bind(wx.EVT_SPINCTRL, self.OnParamEntry) 00808 win.Bind(wx.EVT_TEXT, self.OnParamEntry) 00809 else: 00810 win = wx.TextCtrl(parent = self.panel, id = id, 00811 value = param['value'], 00812 size=(100, -1)) 00813 win.Bind(wx.EVT_TEXT, self.OnParamEntry) 00814 if paramgrp[1] == 'noask': 00815 win.Enable(False) 00816 00817 self.prjParamSizer.Add(item = label, pos = (row, 1), 00818 flag = wx.ALIGN_RIGHT | 00819 wx.ALIGN_CENTER_VERTICAL | 00820 wx.RIGHT, border = 5) 00821 self.prjParamSizer.Add(item = win, pos = (row, 2), 00822 flag = wx.ALIGN_LEFT | 00823 wx.ALIGN_CENTER_VERTICAL | 00824 wx.LEFT, border = 5) 00825 row += 1 00826 00827 self.panel.SetSize(self.panel.GetBestSize()) 00828 self.panel.Layout() 00829 self.Layout() 00830 self.Update() 00831 00832 if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled(): 00833 wx.FindWindowById(wx.ID_FORWARD).Enable() 00834 00835 event.Skip() 00836 00837 def SetVal(self, event): 00838 """!Set value""" 00839 if event.GetId() == self.radio1.GetId(): 00840 self.SetNext(self.parent.datumpage) 00841 self.parent.sumpage.SetPrev(self.parent.datumpage) 00842 elif event.GetId() == self.radio2.GetId(): 00843 self.SetNext(self.parent.ellipsepage) 00844 self.parent.sumpage.SetPrev(self.parent.ellipsepage) 00845 00846 class DatumPage(TitledPage): 00847 """!Wizard page for selecting datum (with associated ellipsoid) 00848 and datum transformation parameters (select coordinate system option) 00849 """ 00850 00851 def __init__(self, wizard, parent): 00852 TitledPage.__init__(self, wizard, _("Specify geodetic datum")) 00853 00854 self.parent = parent 00855 self.datum = '' 00856 self.datumdesc = '' 00857 self.ellipse = '' 00858 self.datumparams = '' 00859 self.proj4params = '' 00860 00861 # text input 00862 self.tdatum = self.MakeTextCtrl("", size = (200,-1)) 00863 00864 # search box 00865 self.searchb = wx.SearchCtrl(self, size = (200,-1), 00866 style = wx.TE_PROCESS_ENTER) 00867 00868 # create list control for datum/elipsoid list 00869 data = [] 00870 for key in self.parent.datums.keys(): 00871 data.append([key, self.parent.datums[key][0], self.parent.datums[key][1]]) 00872 self.datumlist = ItemList(self, 00873 data = data, 00874 columns = [_('Code'), _('Ellipsoid'), _('Description')]) 00875 self.datumlist.resizeLastColumn(10) 00876 00877 # layout 00878 self.sizer.AddGrowableCol(4) 00879 self.sizer.Add(item = self.MakeLabel(_("Datum code:")), 00880 flag = wx.ALIGN_LEFT | 00881 wx.ALIGN_CENTER_VERTICAL | 00882 wx.ALL, border = 5, pos = (1, 1)) 00883 self.sizer.Add(item = self.tdatum, 00884 flag = wx.ALIGN_LEFT | 00885 wx.ALIGN_CENTER_VERTICAL | 00886 wx.ALL, border = 5, pos = (1, 2)) 00887 00888 self.sizer.Add(item = self.MakeLabel(_("Search in description:")), 00889 flag = wx.ALIGN_LEFT | 00890 wx.ALIGN_CENTER_VERTICAL | 00891 wx.ALL, border = 5, pos = (2, 1)) 00892 self.sizer.Add(item = self.searchb, 00893 flag = wx.ALIGN_LEFT | 00894 wx.ALIGN_CENTER_VERTICAL | 00895 wx.ALL, border = 5, pos = (2, 2)) 00896 00897 self.sizer.AddGrowableRow(3) 00898 self.sizer.Add(item = self.datumlist, 00899 flag = wx.EXPAND | 00900 wx.ALIGN_LEFT | 00901 wx.ALL, border = 5, pos = (3, 1), span = (1, 4)) 00902 00903 # events 00904 self.datumlist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnDatumSelected) 00905 self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnDSearch) 00906 self.tdatum.Bind(wx.EVT_TEXT, self.OnDText) 00907 self.tdatum.Bind(wx.EVT_TEXT_ENTER, self.OnDText) 00908 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging) 00909 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 00910 00911 # do page layout 00912 # self.DoLayout() 00913 00914 def OnPageChanging(self, event): 00915 self.proj4params = '' 00916 proj = self.parent.projpage.p4proj 00917 00918 if event.GetDirection(): 00919 if self.datum not in self.parent.datums: 00920 event.Veto() 00921 else: 00922 # check for datum tranforms 00923 # proj4string = self.parent.CreateProj4String() + ' +datum=%s' % self.datum 00924 ret = gcmd.RunCommand('g.proj', 00925 read = True, 00926 proj4 = '%s +datum=%s' % (proj, self.datum), 00927 datumtrans = '-1') 00928 if ret != '': 00929 dtrans = '' 00930 # open a dialog to select datum transform number 00931 dlg = SelectTransformDialog(self.parent.parent, transforms=ret) 00932 00933 if dlg.ShowModal() == wx.ID_OK: 00934 dtrans = dlg.GetTransform() 00935 if dtrans == '': 00936 dlg.Destroy() 00937 event.Veto() 00938 return 'Datum transform is required.' 00939 else: 00940 dlg.Destroy() 00941 event.Veto() 00942 return 'Datum transform is required.' 00943 00944 self.parent.datumtrans = dtrans 00945 00946 self.GetNext().SetPrev(self) 00947 self.parent.ellipsepage.ellipse = self.ellipse 00948 self.parent.ellipsepage.ellipseparams = self.parent.ellipsoids[self.ellipse][1] 00949 00950 def OnEnterPage(self,event): 00951 self.parent.datumtrans = None 00952 if event.GetDirection(): 00953 if len(self.datum) == 0: 00954 # disable 'next' button by default when entering from previous page 00955 wx.FindWindowById(wx.ID_FORWARD).Enable(False) 00956 else: 00957 wx.FindWindowById(wx.ID_FORWARD).Enable(True) 00958 00959 event.Skip() 00960 00961 def OnDText(self, event): 00962 """!Datum code changed""" 00963 self.datum = event.GetString() 00964 00965 nextButton = wx.FindWindowById(wx.ID_FORWARD) 00966 if len(self.datum) == 0 or self.datum not in self.parent.datums: 00967 nextButton.Enable(False) 00968 else: 00969 self.ellipse = self.parent.datums[self.datum][0] 00970 self.datumdesc = self.parent.datums[self.datum][1] 00971 self.datumparams = self.parent.datums[self.datum][2] 00972 try: 00973 self.datumparams.remove('dx=0.0') 00974 except: 00975 pass 00976 try: 00977 self.datumparams.remove('dy=0.0') 00978 except: 00979 pass 00980 try: 00981 self.datumparams.remove('dz=0.0') 00982 except: 00983 pass 00984 00985 nextButton.Enable(True) 00986 00987 self.Update() 00988 event.Skip() 00989 00990 def OnDSearch(self, event): 00991 """!Search geodetic datum by desc""" 00992 str = self.searchb.GetValue() 00993 try: 00994 self.datum, self.ellipsoid, self.datumdesc = self.datumlist.Search(index = [0,1,2], pattern = str) 00995 except: 00996 self.datum = self.datumdesc = self.ellipsoid = '' 00997 00998 event.Skip() 00999 01000 def OnDatumSelected(self, event): 01001 """!Datum selected""" 01002 index = event.m_itemIndex 01003 item = event.GetItem() 01004 01005 self.datum = self.datumlist.GetItem(index, 0).GetText() 01006 self.tdatum.SetValue(self.datum) 01007 01008 event.Skip() 01009 01010 class EllipsePage(TitledPage): 01011 """!Wizard page for selecting ellipsoid (select coordinate system option)""" 01012 01013 def __init__(self, wizard, parent): 01014 TitledPage.__init__(self, wizard, _("Specify ellipsoid")) 01015 01016 self.parent = parent 01017 01018 self.ellipse = '' 01019 self.ellipsedesc = '' 01020 self.ellipseparams = '' 01021 self.proj4params = '' 01022 01023 # text input 01024 self.tellipse = self.MakeTextCtrl("", size = (200,-1)) 01025 01026 # search box 01027 self.searchb = wx.SearchCtrl(self, size = (200,-1), 01028 style = wx.TE_PROCESS_ENTER) 01029 01030 # create list control for ellipse list 01031 data = [] 01032 # extract code, desc 01033 for key in self.parent.ellipsoids.keys(): 01034 data.append([key, self.parent.ellipsoids[key][0]]) 01035 01036 self.ellipselist = ItemList(self, data = data, 01037 columns = [_('Code'), _('Description')]) 01038 self.ellipselist.resizeLastColumn(30) 01039 01040 # layout 01041 self.sizer.AddGrowableCol(4) 01042 self.sizer.Add(item = self.MakeLabel(_("Ellipsoid code:")), 01043 flag = wx.ALIGN_RIGHT | 01044 wx.ALIGN_CENTER_VERTICAL | 01045 wx.ALL, border = 5, pos = (1, 1)) 01046 self.sizer.Add(item = self.tellipse, 01047 flag = wx.ALIGN_LEFT | 01048 wx.ALIGN_CENTER_VERTICAL | 01049 wx.ALL, border = 5, pos = (1, 2)) 01050 self.sizer.Add(item = self.MakeLabel(_("Search in description:")), 01051 flag = wx.ALIGN_RIGHT | 01052 wx.ALIGN_CENTER_VERTICAL | 01053 wx.ALL, border = 5, pos = (2, 1)) 01054 self.sizer.Add(item = self.searchb, 01055 flag = wx.ALIGN_LEFT | 01056 wx.ALIGN_CENTER_VERTICAL | 01057 wx.ALL, border = 5, pos = (2, 2)) 01058 01059 self.sizer.AddGrowableRow(3) 01060 self.sizer.Add(item = self.ellipselist, 01061 flag = wx.EXPAND | 01062 wx.ALIGN_LEFT | 01063 wx.ALL, border = 5, pos = (3, 1), span = (1, 4)) 01064 01065 # events 01066 self.ellipselist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected) 01067 self.tellipse.Bind(wx.EVT_TEXT, self.OnText) 01068 self.tellipse.Bind(wx.EVT_TEXT_ENTER, self.OnText) 01069 self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnSearch) 01070 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 01071 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging) 01072 01073 def OnEnterPage(self,event): 01074 if len(self.ellipse) == 0: 01075 # disable 'next' button by default 01076 wx.FindWindowById(wx.ID_FORWARD).Enable(False) 01077 else: 01078 wx.FindWindowById(wx.ID_FORWARD).Enable(True) 01079 01080 event.Skip() 01081 01082 def OnPageChanging(self, event): 01083 if event.GetDirection() and self.ellipse not in self.parent.ellipsoids: 01084 event.Veto() 01085 01086 self.proj4params = '' 01087 self.GetNext().SetPrev(self) 01088 self.parent.datumpage.datumparams = '' 01089 # self.GetNext().SetPrev(self) (???) 01090 01091 def OnText(self, event): 01092 """!Ellipspoid code changed""" 01093 self.ellipse = event.GetString() 01094 nextButton = wx.FindWindowById(wx.ID_FORWARD) 01095 if len(self.ellipse) == 0 or self.ellipse not in self.parent.ellipsoids: 01096 nextButton.Enable(False) 01097 self.ellipsedesc = '' 01098 self.ellipseparams = '' 01099 self.proj4params = '' 01100 elif self.ellipse in self.parent.ellipsoids: 01101 self.ellipsedesc = self.parent.ellipsoids[self.ellipse][0] 01102 self.ellipseparams = self.parent.ellipsoids[self.ellipse][1] 01103 nextButton.Enable(True) 01104 01105 def OnSearch(self, event): 01106 """!Search ellipsoid by desc""" 01107 try: 01108 self.ellipse, self.ellipsedesc = \ 01109 self.ellipselist.Search(index=[0,1], pattern=event.GetString()) 01110 self.ellipseparams = self.parent.ellipsoids[self.ellipse][1] 01111 except: 01112 self.ellipse = self.ellipsedesc = self.ellipseparams = '' 01113 01114 event.Skip() 01115 01116 def OnItemSelected(self,event): 01117 """!Ellipsoid selected""" 01118 index = event.m_itemIndex 01119 item = event.GetItem() 01120 01121 self.ellipse = self.ellipselist.GetItem(index, 0).GetText() 01122 self.tellipse.SetValue(self.ellipse) 01123 01124 event.Skip() 01125 01126 class GeoreferencedFilePage(TitledPage): 01127 """!Wizard page for selecting georeferenced file to use 01128 for setting coordinate system parameters""" 01129 01130 def __init__(self, wizard, parent): 01131 TitledPage.__init__(self, wizard, _("Select georeferenced file")) 01132 01133 self.georeffile = '' 01134 01135 # create controls 01136 self.lfile= self.MakeLabel(_("Georeferenced file:")) 01137 self.tfile = self.MakeTextCtrl(size = (300,-1)) 01138 self.bbrowse = self.MakeButton(_("Browse")) 01139 01140 # do layout 01141 self.sizer.AddGrowableCol(3) 01142 self.sizer.Add(item = self.lfile, flag = wx.ALIGN_LEFT | 01143 wx.ALIGN_CENTRE_VERTICAL | 01144 wx.ALL, border = 5, pos = (1, 1)) 01145 self.sizer.Add(item = self.tfile, flag = wx.ALIGN_LEFT | 01146 wx.ALIGN_CENTRE_VERTICAL | 01147 wx.ALL, border = 5, pos = (1, 2)) 01148 self.sizer.Add(item = self.bbrowse, flag = wx.ALIGN_LEFT | 01149 wx.ALL, border = 5, pos = (1, 3)) 01150 01151 self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse) 01152 self.tfile.Bind(wx.EVT_TEXT, self.OnText) 01153 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging) 01154 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 01155 01156 # do page layout 01157 # self.DoLayout() 01158 01159 def OnEnterPage(self, event): 01160 if len(self.georeffile) == 0: 01161 # disable 'next' button by default 01162 wx.FindWindowById(wx.ID_FORWARD).Enable(False) 01163 else: 01164 wx.FindWindowById(wx.ID_FORWARD).Enable(True) 01165 01166 event.Skip() 01167 01168 def OnPageChanging(self, event): 01169 if event.GetDirection() and not os.path.isfile(self.georeffile): 01170 event.Veto() 01171 self.GetNext().SetPrev(self) 01172 01173 event.Skip() 01174 01175 def OnText(self, event): 01176 """!File changed""" 01177 self.georeffile = event.GetString() 01178 nextButton = wx.FindWindowById(wx.ID_FORWARD) 01179 if len(self.georeffile) > 0 and os.path.isfile(self.georeffile): 01180 if not nextButton.IsEnabled(): 01181 nextButton.Enable(True) 01182 else: 01183 if nextButton.IsEnabled(): 01184 nextButton.Enable(False) 01185 01186 event.Skip() 01187 01188 def OnBrowse(self, event): 01189 """!Choose file""" 01190 dlg = wx.FileDialog(self, 01191 _("Select georeferenced file"), 01192 os.getcwd(), "", "*.*", wx.OPEN) 01193 if dlg.ShowModal() == wx.ID_OK: 01194 path = dlg.GetPath() 01195 self.tfile.SetValue(path) 01196 dlg.Destroy() 01197 01198 event.Skip() 01199 01200 class WKTPage(TitledPage): 01201 """!Wizard page for selecting WKT file to use 01202 for setting coordinate system parameters""" 01203 01204 def __init__(self, wizard, parent): 01205 TitledPage.__init__(self, wizard, _("Select WKT file")) 01206 01207 self.wktfile = '' 01208 01209 # create controls 01210 self.lfile= self.MakeLabel(_("WKT file:")) 01211 self.tfile = self.MakeTextCtrl(size = (300,-1)) 01212 self.bbrowse = self.MakeButton(_("Browse")) 01213 01214 # do layout 01215 self.sizer.AddGrowableCol(3) 01216 self.sizer.Add(item = self.lfile, flag = wx.ALIGN_LEFT | 01217 wx.ALIGN_CENTRE_VERTICAL | 01218 wx.ALL, border = 5, pos = (1, 1)) 01219 self.sizer.Add(item = self.tfile, flag = wx.ALIGN_LEFT | 01220 wx.ALIGN_CENTRE_VERTICAL | 01221 wx.ALL, border = 5, pos = (1, 2)) 01222 self.sizer.Add(item = self.bbrowse, flag = wx.ALIGN_LEFT | 01223 wx.ALL, border = 5, pos = (1, 3)) 01224 01225 self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse) 01226 self.tfile.Bind(wx.EVT_TEXT, self.OnText) 01227 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging) 01228 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 01229 01230 def OnEnterPage(self, event): 01231 if len(self.wktfile) == 0: 01232 # disable 'next' button by default 01233 wx.FindWindowById(wx.ID_FORWARD).Enable(False) 01234 else: 01235 wx.FindWindowById(wx.ID_FORWARD).Enable(True) 01236 01237 event.Skip() 01238 01239 def OnPageChanging(self, event): 01240 if event.GetDirection() and not os.path.isfile(self.wktfile): 01241 event.Veto() 01242 self.GetNext().SetPrev(self) 01243 01244 event.Skip() 01245 01246 def OnText(self, event): 01247 """!File changed""" 01248 self.wktfile = event.GetString() 01249 nextButton = wx.FindWindowById(wx.ID_FORWARD) 01250 if len(self.wktfile) > 0 and os.path.isfile(self.wktfile): 01251 if not nextButton.IsEnabled(): 01252 nextButton.Enable(True) 01253 else: 01254 if nextButton.IsEnabled(): 01255 nextButton.Enable(False) 01256 01257 event.Skip() 01258 01259 def OnBrowse(self, event): 01260 """!Choose file""" 01261 dlg = wx.FileDialog(self, 01262 _("Select WKT file"), 01263 os.getcwd(), "", "*.*", wx.OPEN) 01264 if dlg.ShowModal() == wx.ID_OK: 01265 path = dlg.GetPath() 01266 self.tfile.SetValue(path) 01267 dlg.Destroy() 01268 01269 event.Skip() 01270 01271 class EPSGPage(TitledPage): 01272 """!Wizard page for selecting EPSG code for 01273 setting coordinate system parameters""" 01274 01275 def __init__(self, wizard, parent): 01276 TitledPage.__init__(self, wizard, _("Choose EPSG Code")) 01277 self.parent = parent 01278 self.epsgCodeDict = {} 01279 self.epsgcode = None 01280 self.epsgdesc = '' 01281 self.epsgparams = '' 01282 01283 # labels 01284 self.lfile = self.MakeLabel(_("Path to the EPSG-codes file:"), 01285 style = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) 01286 self.lcode = self.MakeLabel(_("EPSG code:"), 01287 style = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) 01288 # text input 01289 epsgdir = utils.PathJoin(os.environ["GRASS_PROJSHARE"], 'epsg') 01290 self.tfile = self.MakeTextCtrl(text = epsgdir, size = (200,-1), 01291 style = wx.TE_PROCESS_ENTER) 01292 self.tcode = self.MakeTextCtrl(size = (200,-1)) 01293 01294 # buttons 01295 self.bbrowse = self.MakeButton(_("Browse")) 01296 01297 # search box 01298 self.searchb = wx.SearchCtrl(self, size = (200,-1), 01299 style = wx.TE_PROCESS_ENTER) 01300 01301 self.epsglist = ItemList(self, data = None, 01302 columns = [_('Code'), _('Description'), _('Parameters')]) 01303 01304 # layout 01305 self.sizer.AddGrowableCol(3) 01306 self.sizer.Add(item = self.lfile, 01307 flag = wx.ALIGN_LEFT | 01308 wx.ALIGN_CENTER_VERTICAL | 01309 wx.ALL, border = 5, pos = (1, 1), span = (1, 2)) 01310 self.sizer.Add(item = self.tfile, 01311 flag = wx.ALIGN_LEFT | 01312 wx.ALIGN_CENTER_VERTICAL | 01313 wx.ALL, border = 5, pos = (1, 3)) 01314 self.sizer.Add(item = self.bbrowse, 01315 flag = wx.ALIGN_LEFT | 01316 wx.ALIGN_CENTER_VERTICAL | 01317 wx.ALL, border = 5, pos = (1, 4)) 01318 self.sizer.Add(item = self.lcode, 01319 flag = wx.ALIGN_LEFT | 01320 wx.ALIGN_CENTER_VERTICAL | 01321 wx.ALL, border = 5, pos = (2, 1), span = (1, 2)) 01322 self.sizer.Add(item = self.tcode, 01323 flag = wx.ALIGN_LEFT | 01324 wx.ALIGN_CENTER_VERTICAL | 01325 wx.ALL, border = 5, pos = (2, 3)) 01326 self.sizer.Add(item = self.searchb, 01327 flag = wx.ALIGN_LEFT | 01328 wx.ALIGN_CENTER_VERTICAL | 01329 wx.ALL, border = 5, pos = (3, 3)) 01330 01331 self.sizer.AddGrowableRow(4) 01332 self.sizer.Add(item = self.epsglist, 01333 flag = wx.ALIGN_LEFT | wx.EXPAND, pos = (4, 1), 01334 span = (1, 4)) 01335 01336 # events 01337 self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse) 01338 self.tfile.Bind(wx.EVT_TEXT_ENTER, self.OnBrowseCodes) 01339 self.tcode.Bind(wx.EVT_TEXT, self.OnText) 01340 self.tcode.Bind(wx.EVT_TEXT_ENTER, self.OnText) 01341 self.epsglist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected) 01342 self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnSearch) 01343 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging) 01344 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 01345 01346 def OnEnterPage(self, event): 01347 self.parent.datumtrans = None 01348 if event.GetDirection(): 01349 if not self.epsgcode: 01350 # disable 'next' button by default 01351 wx.FindWindowById(wx.ID_FORWARD).Enable(False) 01352 else: 01353 wx.FindWindowById(wx.ID_FORWARD).Enable(True) 01354 01355 # load default epsg database file 01356 self.OnBrowseCodes(None) 01357 01358 event.Skip() 01359 01360 def OnPageChanging(self, event): 01361 if event.GetDirection(): 01362 if not self.epsgcode: 01363 event.Veto() 01364 return 01365 else: 01366 # check for datum transforms 01367 ret = gcmd.RunCommand('g.proj', 01368 read = True, 01369 epsg = self.epsgcode, 01370 datumtrans = '-1') 01371 01372 if ret != '': 01373 dtrans = '' 01374 # open a dialog to select datum transform number 01375 dlg = SelectTransformDialog(self.parent.parent, transforms = ret) 01376 01377 if dlg.ShowModal() == wx.ID_OK: 01378 dtrans = dlg.GetTransform() 01379 if dtrans == '': 01380 dlg.Destroy() 01381 event.Veto() 01382 return 'Datum transform is required.' 01383 else: 01384 dlg.Destroy() 01385 event.Veto() 01386 return 'Datum transform is required.' 01387 01388 self.parent.datumtrans = dtrans 01389 self.GetNext().SetPrev(self) 01390 01391 def OnText(self, event): 01392 self.epsgcode = event.GetString() 01393 try: 01394 self.epsgcode = int(self.epsgcode) 01395 except: 01396 self.epsgcode = None 01397 01398 nextButton = wx.FindWindowById(wx.ID_FORWARD) 01399 01400 if self.epsgcode and self.epsgcode in self.epsgCodeDict.keys(): 01401 self.epsgdesc = self.epsgCodeDict[self.epsgcode][0] 01402 self.epsgparams = self.epsgCodeDict[self.epsgcode][1] 01403 if not nextButton.IsEnabled(): 01404 nextButton.Enable(True) 01405 else: 01406 self.epsgcode = None # not found 01407 if nextButton.IsEnabled(): 01408 nextButton.Enable(False) 01409 self.epsgdesc = self.epsgparams = '' 01410 01411 def OnSearch(self, event): 01412 value = self.searchb.GetValue() 01413 01414 if value == '': 01415 self.epsgcode = None 01416 self.epsgdesc = self.epsgparams = '' 01417 self.tcode.SetValue('') 01418 self.searchb.SetValue('') 01419 self.OnBrowseCodes(None) 01420 else: 01421 try: 01422 self.epsgcode, self.epsgdesc, self.epsgparams = \ 01423 self.epsglist.Search(index=[0,1,2], pattern=value) 01424 except (IndexError, ValueError): # -> no item found 01425 self.epsgcode = None 01426 self.epsgdesc = self.epsgparams = '' 01427 self.tcode.SetValue('') 01428 self.searchb.SetValue('') 01429 01430 event.Skip() 01431 01432 def OnBrowse(self, event): 01433 """!Define path for EPSG code file""" 01434 path = os.path.dirname(self.tfile.GetValue()) 01435 if not path: 01436 path = os.getcwd() 01437 01438 dlg = wx.FileDialog(parent = self, message = _("Choose EPSG codes file"), 01439 defaultDir = path, defaultFile = "", wildcard = "*", style = wx.OPEN) 01440 01441 if dlg.ShowModal() == wx.ID_OK: 01442 path = dlg.GetPath() 01443 self.tfile.SetValue(path) 01444 self.OnBrowseCodes(None) 01445 01446 dlg.Destroy() 01447 01448 event.Skip() 01449 01450 def OnItemSelected(self, event): 01451 """!EPSG code selected from the list""" 01452 index = event.m_itemIndex 01453 item = event.GetItem() 01454 01455 self.epsgcode = int(self.epsglist.GetItem(index, 0).GetText()) 01456 self.epsgdesc = self.epsglist.GetItem(index, 1).GetText() 01457 self.tcode.SetValue(str(self.epsgcode)) 01458 01459 event.Skip() 01460 01461 def OnBrowseCodes(self, event, search = None): 01462 """!Browse EPSG codes""" 01463 self.epsgCodeDict = utils.ReadEpsgCodes(self.tfile.GetValue()) 01464 01465 if type(self.epsgCodeDict) != dict: 01466 wx.MessageBox(parent = self, 01467 message = _("Unable to read EPGS codes: %s") % self.epsgCodeDict, 01468 caption = _("Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE) 01469 self.epsglist.Populate(list(), update = True) 01470 return 01471 01472 data = list() 01473 for code, val in self.epsgCodeDict.iteritems(): 01474 if code is not None: 01475 data.append((code, val[0], val[1])) 01476 01477 self.epsglist.Populate(data, update = True) 01478 01479 class CustomPage(TitledPage): 01480 """!Wizard page for entering custom PROJ.4 string 01481 for setting coordinate system parameters""" 01482 01483 def __init__(self, wizard, parent): 01484 TitledPage.__init__(self, wizard, 01485 _("Choose method of specifying georeferencing parameters")) 01486 global coordsys 01487 self.customstring = '' 01488 self.parent = parent 01489 01490 # widgets 01491 self.text_proj4string = self.MakeTextCtrl(size = (400, 200), 01492 style = wx.TE_MULTILINE) 01493 self.label_proj4string = self.MakeLabel(_("Enter PROJ.4 parameters string:")) 01494 01495 # layout 01496 self.sizer.AddGrowableCol(2) 01497 self.sizer.Add(self.label_proj4string, 01498 flag = wx.ALIGN_LEFT | wx.ALL, 01499 border = 5, pos = (1, 1)) 01500 self.sizer.AddGrowableRow(2) 01501 self.sizer.Add(self.text_proj4string, 01502 flag = wx.ALIGN_LEFT | wx.ALL | wx.EXPAND, 01503 border = 5, pos = (2, 1), span = (1, 2)) 01504 01505 self.text_proj4string.Bind(wx.EVT_TEXT, self.GetProjstring) 01506 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging) 01507 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 01508 01509 def OnEnterPage(self, event): 01510 if len(self.customstring) == 0: 01511 # disable 'next' button by default 01512 wx.FindWindowById(wx.ID_FORWARD).Enable(False) 01513 else: 01514 wx.FindWindowById(wx.ID_FORWARD).Enable(True) 01515 01516 def OnPageChanging(self, event): 01517 if event.GetDirection(): 01518 # check for datum tranforms 01519 ret, out, err = gcmd.RunCommand('g.proj', 01520 read = True, getErrorMsg = True, 01521 proj4 = self.customstring, 01522 datumtrans = '-1') 01523 if ret != 0: 01524 wx.MessageBox(parent = self, 01525 message = err, 01526 caption = _("Error"), 01527 style = wx.OK | wx.ICON_ERROR | wx.CENTRE) 01528 event.Veto() 01529 return 01530 01531 if out: 01532 dtrans = '' 01533 # open a dialog to select datum transform number 01534 dlg = SelectTransformDialog(self.parent.parent, transforms = out) 01535 01536 if dlg.ShowModal() == wx.ID_OK: 01537 dtrans = dlg.GetTransform() 01538 if len(dtrans) == 0: 01539 dlg.Destroy() 01540 event.Veto() 01541 return _('Datum transform is required.') 01542 else: 01543 dlg.Destroy() 01544 event.Veto() 01545 return _('Datum transform is required.') 01546 01547 self.parent.datumtrans = dtrans 01548 01549 self.GetNext().SetPrev(self) 01550 01551 def GetProjstring(self, event): 01552 """!Change proj string""" 01553 # TODO: check PROJ.4 syntax 01554 self.customstring = event.GetString() 01555 nextButton = wx.FindWindowById(wx.ID_FORWARD) 01556 if len(self.customstring) == 0: 01557 if nextButton.IsEnabled(): 01558 nextButton.Enable(False) 01559 else: 01560 if not nextButton.IsEnabled(): 01561 nextButton.Enable() 01562 01563 class SummaryPage(TitledPage): 01564 """!Shows summary result of choosing coordinate system parameters 01565 prior to creating location""" 01566 def __init__(self, wizard, parent): 01567 TitledPage.__init__(self, wizard, _("Summary")) 01568 self.parent = parent 01569 01570 self.panelTitle = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY) 01571 self.panelProj4string = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY) 01572 self.panelProj = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY) 01573 01574 # labels 01575 self.ldatabase = self.MakeLabel() 01576 self.llocation = self.MakeLabel() 01577 self.llocTitle = self.MakeLabel(parent = self.panelTitle) 01578 self.lprojection = self.MakeLabel(parent = self.panelProj) 01579 self.lproj4string = self.MakeLabel(parent = self.panelProj4string) 01580 01581 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 01582 01583 # do sub-page layout 01584 self._doLayout() 01585 01586 def _doLayout(self): 01587 """!Do page layout""" 01588 self.sizer.AddGrowableCol(1) 01589 self.sizer.AddGrowableRow(3, 1) 01590 self.sizer.AddGrowableRow(4, 1) 01591 self.sizer.AddGrowableRow(5, 5) 01592 01593 titleSizer = wx.BoxSizer(wx.VERTICAL) 01594 titleSizer.Add(item = self.llocTitle, proportion = 1, 01595 flag = wx.EXPAND | wx.ALL, border = 5) 01596 self.panelTitle.SetSizer(titleSizer) 01597 01598 projSizer = wx.BoxSizer(wx.VERTICAL) 01599 projSizer.Add(item = self.lprojection, proportion = 1, 01600 flag = wx.EXPAND | wx.ALL, border = 5) 01601 self.panelProj.SetSizer(projSizer) 01602 01603 proj4stringSizer = wx.BoxSizer(wx.VERTICAL) 01604 proj4stringSizer.Add(item = self.lproj4string, proportion = 1, 01605 flag = wx.EXPAND | wx.ALL, border = 5) 01606 self.panelProj4string.SetSizer(proj4stringSizer) 01607 01608 self.panelProj4string.SetupScrolling() 01609 self.panelProj.SetupScrolling(scroll_y = False) 01610 self.panelTitle.SetupScrolling(scroll_y = False) 01611 01612 self.sizer.Add(item = self.MakeLabel(_("GRASS Database:")), 01613 flag = wx.ALIGN_LEFT | wx.ALL, 01614 border = 5, pos = (1, 0)) 01615 self.sizer.Add(item = self.ldatabase, 01616 flag = wx.ALIGN_LEFT | wx.ALL, 01617 border = 5, pos = (1, 1)) 01618 self.sizer.Add(item = self.MakeLabel(_("Location Name:")), 01619 flag = wx.ALIGN_LEFT | wx.ALL, 01620 border = 5, pos = (2, 0)) 01621 self.sizer.Add(item = self.llocation, 01622 flag = wx.ALIGN_LEFT | wx.ALL, 01623 border = 5, pos = (2, 1)) 01624 self.sizer.Add(item = self.MakeLabel(_("Location Title:")), 01625 flag = wx.ALIGN_LEFT | wx.ALL, 01626 border = 5, pos = (3, 0)) 01627 self.sizer.Add(item = self.panelTitle, 01628 flag = wx.ALIGN_LEFT | wx.ALL | wx.EXPAND, 01629 border = 0, pos = (3, 1)) 01630 self.sizer.Add(item = self.MakeLabel(_("Projection:")), 01631 flag = wx.ALIGN_LEFT | wx.ALL, 01632 border = 5, pos = (4, 0)) 01633 self.sizer.Add(item = self.panelProj, 01634 flag = wx.ALIGN_LEFT | wx.ALL | wx.EXPAND, 01635 border = 0, pos = (4, 1)) 01636 self.sizer.Add(item = self.MakeLabel(_("PROJ.4 definition:")), 01637 flag = wx.ALIGN_LEFT | wx.ALL, 01638 border = 5, pos = (5, 0)) 01639 self.sizer.Add(item = self.panelProj4string, 01640 flag = wx.ALIGN_LEFT | wx.ALL | wx.EXPAND, 01641 border = 0, pos = (5, 1)) 01642 01643 def OnEnterPage(self, event): 01644 """!Insert values into text controls for summary of location 01645 creation options 01646 """ 01647 database = self.parent.startpage.grassdatabase 01648 location = self.parent.startpage.location 01649 proj4string = self.parent.CreateProj4String() 01650 epsgcode = self.parent.epsgpage.epsgcode 01651 dtrans = self.parent.datumtrans 01652 01653 global coordsys 01654 if coordsys in ('proj', 'epsg'): 01655 if coordsys == 'proj': 01656 ret, projlabel, err = gcmd.RunCommand('g.proj', 01657 flags = 'jf', 01658 proj4 = proj4string, 01659 datumtrans = dtrans, 01660 location = location, 01661 getErrorMsg = True, 01662 read = True) 01663 elif coordsys == 'epsg': 01664 ret, projlabel, err = gcmd.RunCommand('g.proj', 01665 flags = 'jf', 01666 epsg = epsgcode, 01667 datumtrans = dtrans, 01668 location = location, 01669 getErrorMsg = True, 01670 read = True) 01671 01672 finishButton = wx.FindWindowById(wx.ID_FORWARD) 01673 if ret == 0: 01674 self.lproj4string.SetLabel(projlabel.replace(' ', os.linesep)) 01675 finishButton.Enable(True) 01676 else: 01677 gcmd.GError(err, parent = self) 01678 self.lproj4string.SetLabel('') 01679 finishButton.Enable(False) 01680 01681 projdesc = self.parent.projpage.projdesc 01682 ellipsedesc = self.parent.ellipsepage.ellipsedesc 01683 datumdesc = self.parent.datumpage.datumdesc 01684 self.ldatabase.SetLabel(database) 01685 self.llocation.SetLabel(location) 01686 self.llocTitle.SetLabel(self.parent.startpage.locTitle) 01687 01688 label = '' 01689 if coordsys == 'epsg': 01690 label = 'EPSG code %s (%s)' % (self.parent.epsgpage.epsgcode, self.parent.epsgpage.epsgdesc) 01691 elif coordsys == 'file': 01692 label = 'matches file %s' % self.parent.filepage.georeffile 01693 self.lproj4string.SetLabel("") 01694 elif coordsys == 'wkt': 01695 label = 'matches file %s' % self.parent.wktpage.wktfile 01696 self.lproj4string.SetLabel("") 01697 elif coordsys == 'proj': 01698 label = ('%s, %s %s' % (projdesc, datumdesc, ellipsedesc)) 01699 elif coordsys == 'xy': 01700 label = ('XY coordinate system (not projected).') 01701 self.lproj4string.SetLabel("") 01702 elif coordsys == 'custom': 01703 label = _("custom") 01704 self.lproj4string.SetLabel(('%s' % self.parent.custompage.customstring.replace(' ', os.linesep))) 01705 self.lprojection.SetLabel(label) 01706 01707 def OnFinish(self, event): 01708 dlg = wx.MessageDialog(parent = self.wizard, 01709 message = _("Do you want to create GRASS location <%s>?") % location, 01710 caption = _("Create new location?"), 01711 style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION) 01712 01713 if dlg.ShowModal() == wx.ID_NO: 01714 dlg.Destroy() 01715 event.Veto() 01716 else: 01717 dlg.Destroy() 01718 event.Skip() 01719 01720 class LocationWizard(wx.Object): 01721 """!Start wizard here and finish wizard here 01722 """ 01723 def __init__(self, parent, grassdatabase): 01724 self.__cleanUp() 01725 01726 global coordsys 01727 self.parent = parent 01728 01729 # 01730 # define wizard image 01731 # 01732 imagePath = os.path.join(globalvar.ETCIMGDIR, "loc_wizard_qgis.png") 01733 wizbmp = wx.Image(imagePath, wx.BITMAP_TYPE_PNG) 01734 wizbmp = wizbmp.ConvertToBitmap() 01735 01736 # 01737 # get georeferencing information from tables in $GISBASE/etc 01738 # 01739 self.__readData() 01740 01741 # 01742 # datum transform number and list of datum transforms 01743 # 01744 self.datumtrans = None 01745 self.proj4string = '' 01746 01747 # 01748 # define wizard pages 01749 # 01750 self.wizard = wiz.Wizard(parent, id = wx.ID_ANY, title = _("Define new GRASS Location"), 01751 bitmap = wizbmp, style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER) 01752 self.startpage = DatabasePage(self.wizard, self, grassdatabase) 01753 self.csystemspage = CoordinateSystemPage(self.wizard, self) 01754 self.projpage = ProjectionsPage(self.wizard, self) 01755 self.datumpage = DatumPage(self.wizard, self) 01756 self.paramspage = ProjParamsPage(self.wizard,self) 01757 self.epsgpage = EPSGPage(self.wizard, self) 01758 self.filepage = GeoreferencedFilePage(self.wizard, self) 01759 self.wktpage = WKTPage(self.wizard, self) 01760 self.ellipsepage = EllipsePage(self.wizard, self) 01761 self.custompage = CustomPage(self.wizard, self) 01762 self.sumpage = SummaryPage(self.wizard, self) 01763 01764 # 01765 # set the initial order of the pages 01766 # (should follow the epsg line) 01767 # 01768 self.startpage.SetNext(self.csystemspage) 01769 01770 self.csystemspage.SetPrev(self.startpage) 01771 self.csystemspage.SetNext(self.sumpage) 01772 01773 self.projpage.SetPrev(self.csystemspage) 01774 self.projpage.SetNext(self.paramspage) 01775 01776 self.paramspage.SetPrev(self.projpage) 01777 self.paramspage.SetNext(self.datumpage) 01778 01779 self.datumpage.SetPrev(self.paramspage) 01780 self.datumpage.SetNext(self.sumpage) 01781 01782 self.ellipsepage.SetPrev(self.paramspage) 01783 self.ellipsepage.SetNext(self.sumpage) 01784 01785 self.epsgpage.SetPrev(self.csystemspage) 01786 self.epsgpage.SetNext(self.sumpage) 01787 01788 self.filepage.SetPrev(self.csystemspage) 01789 self.filepage.SetNext(self.sumpage) 01790 01791 self.wktpage.SetPrev(self.csystemspage) 01792 self.wktpage.SetNext(self.sumpage) 01793 01794 self.custompage.SetPrev(self.csystemspage) 01795 self.custompage.SetNext(self.sumpage) 01796 01797 self.sumpage.SetPrev(self.csystemspage) 01798 01799 # 01800 # do pages layout 01801 # 01802 self.startpage.DoLayout() 01803 self.csystemspage.DoLayout() 01804 self.projpage.DoLayout() 01805 self.datumpage.DoLayout() 01806 self.paramspage.DoLayout() 01807 self.epsgpage.DoLayout() 01808 self.filepage.DoLayout() 01809 self.wktpage.DoLayout() 01810 self.ellipsepage.DoLayout() 01811 self.custompage.DoLayout() 01812 self.sumpage.DoLayout() 01813 self.wizard.FitToPage(self.datumpage) 01814 size = self.wizard.GetPageSize() 01815 self.wizard.SetPageSize((size[0], size[1] + 75)) 01816 01817 # new location created? 01818 self.location = None 01819 success = False 01820 01821 # location created in different GIS database? 01822 self.altdb = False 01823 01824 # 01825 # run wizard... 01826 # 01827 if self.wizard.RunWizard(self.startpage): 01828 msg = self.OnWizFinished() 01829 if not msg: 01830 self.wizard.Destroy() 01831 self.location = self.startpage.location 01832 01833 if self.altdb == False: 01834 dlg = wx.MessageDialog(parent = self.parent, 01835 message = _("Do you want to set the default " 01836 "region extents and resolution now?"), 01837 caption = _("Location <%s> created") % self.location, 01838 style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) 01839 dlg.CenterOnScreen() 01840 if dlg.ShowModal() == wx.ID_YES: 01841 dlg.Destroy() 01842 defineRegion = RegionDef(self.parent, location = self.location) 01843 defineRegion.CenterOnScreen() 01844 defineRegion.Show() 01845 else: 01846 dlg.Destroy() 01847 else: # -> error 01848 self.wizard.Destroy() 01849 gcmd.GError(parent = self.parent, 01850 message = "%s" % _("Unable to create new location. " 01851 "Location <%(loc)s> not created.\n\n" 01852 "Details: %(err)s") % \ 01853 { 'loc' : self.startpage.location, 01854 'err' : msg }) 01855 else: # -> cancelled 01856 self.wizard.Destroy() 01857 gcmd.GMessage(parent = self.parent, 01858 message = _("Location wizard canceled. " 01859 "Location not created.")) 01860 01861 self.__cleanUp() 01862 01863 def __cleanUp(self): 01864 global coordsys 01865 global north 01866 global south 01867 global east 01868 global west 01869 global resolution 01870 global wizerror 01871 global translist 01872 01873 coordsys = None 01874 north = None 01875 south = None 01876 east = None 01877 west = None 01878 resolution = None 01879 transformlist = list() 01880 01881 def __readData(self): 01882 """!Get georeferencing information from tables in $GISBASE/etc""" 01883 01884 # read projection and parameters 01885 f = open(os.path.join(globalvar.ETCDIR, "proj-parms.table"), "r") 01886 self.projections = {} 01887 self.projdesc = {} 01888 for line in f.readlines(): 01889 line = line.strip() 01890 try: 01891 proj, projdesc, params = line.split(':') 01892 paramslist = params.split(';') 01893 plist = [] 01894 for p in paramslist: 01895 if p == '': continue 01896 p1, pdefault = p.split(',') 01897 pterm, pask = p1.split('=') 01898 p = [pterm.strip(), pask.strip(), pdefault.strip()] 01899 plist.append(p) 01900 self.projections[proj.lower().strip()] = (projdesc.strip(), plist) 01901 self.projdesc[proj.lower().strip()] = projdesc.strip() 01902 except: 01903 continue 01904 f.close() 01905 01906 # read datum definitions 01907 f = open(os.path.join(globalvar.ETCDIR, "datum.table"), "r") 01908 self.datums = {} 01909 paramslist = [] 01910 for line in f.readlines(): 01911 line = line.expandtabs(1) 01912 line = line.strip() 01913 if line == '' or line[0] == "#": 01914 continue 01915 datum, info = line.split(" ", 1) 01916 info = info.strip() 01917 datumdesc, params = info.split(" ", 1) 01918 datumdesc = datumdesc.strip('"') 01919 paramlist = params.split() 01920 ellipsoid = paramlist.pop(0) 01921 self.datums[datum] = (ellipsoid, datumdesc.replace('_', ' '), paramlist) 01922 f.close() 01923 01924 # read ellipsiod definitions 01925 f = open(os.path.join(globalvar.ETCDIR, "ellipse.table"), "r") 01926 self.ellipsoids = {} 01927 for line in f.readlines(): 01928 line = line.expandtabs(1) 01929 line = line.strip() 01930 if line == '' or line[0] == "#": 01931 continue 01932 ellipse, rest = line.split(" ", 1) 01933 rest = rest.strip('" ') 01934 desc, params = rest.split('"', 1) 01935 desc = desc.strip('" ') 01936 paramslist = params.split() 01937 self.ellipsoids[ellipse] = (desc, paramslist) 01938 f.close() 01939 01940 # read projection parameter description and parsing table 01941 f = open(os.path.join(globalvar.ETCDIR, "proj-desc.table"), "r") 01942 self.paramdesc = {} 01943 for line in f.readlines(): 01944 line = line.strip() 01945 try: 01946 pparam, datatype, proj4term, desc = line.split(':') 01947 self.paramdesc[pparam] = (datatype, proj4term, desc) 01948 except: 01949 continue 01950 f.close() 01951 01952 def OnWizFinished(self): 01953 """!Wizard finished, create new location 01954 01955 @return error message on error 01956 @return None on success 01957 """ 01958 database = self.startpage.grassdatabase 01959 location = self.startpage.location 01960 01961 # location already exists? 01962 if os.path.isdir(os.path.join(database,location)): 01963 gcmd.GError(parent = self.wizard, 01964 message = "%s <%s>: %s" % \ 01965 (_("Unable to create new location"), 01966 os.path.join(database, location), 01967 _("Location already exists in GRASS Database."))) 01968 return None 01969 01970 # current GISDbase or a new one? 01971 current_gdb = grass.gisenv()['GISDBASE'] 01972 if current_gdb != database: 01973 # change to new GISDbase or create new one 01974 if os.path.isdir(database) != True: 01975 # create new directory 01976 os.mkdir(database) 01977 01978 # change to new GISDbase directory 01979 gcmd.RunCommand('g.gisenv', 01980 parent = self.wizard, 01981 set = 'GISDBASE=%s' % database) 01982 01983 wx.MessageBox(parent = self.wizard, 01984 message = _("Location <%(loc)s> will be created " 01985 "in GIS data directory <%(dir)s>. " 01986 "You will need to change the default GIS " 01987 "data directory in the GRASS startup screen.") % \ 01988 { 'loc' : location, 'dir' : database}, 01989 caption = _("New GIS data directory"), 01990 style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE) 01991 01992 # location created in alternate GISDbase 01993 self.altdb = True 01994 01995 global coordsys 01996 try: 01997 if coordsys == "xy": 01998 grass.create_location(dbase = self.startpage.grassdatabase, 01999 location = self.startpage.location, 02000 desc = self.startpage.locTitle) 02001 elif coordsys == "proj": 02002 grass.create_location(dbase = self.startpage.grassdatabase, 02003 location = self.startpage.location, 02004 proj4 = self.CreateProj4String(), 02005 datum = self.datumtrans, 02006 desc = self.startpage.locTitle) 02007 elif coordsys == 'custom': 02008 grass.create_location(dbase = self.startpage.grassdatabase, 02009 location = self.startpage.location, 02010 proj4 = self.custompage.customstring, 02011 desc = self.startpage.locTitle) 02012 elif coordsys == "epsg": 02013 if not self.epsgpage.epsgcode: 02014 return _('EPSG code missing.') 02015 02016 grass.create_location(dbase = self.startpage.grassdatabase, 02017 location = self.startpage.location, 02018 epsg = self.epsgpage.epsgcode, 02019 datum = self.datumtrans, 02020 desc = self.startpage.locTitle) 02021 elif coordsys == "file": 02022 if not self.filepage.georeffile or \ 02023 not os.path.isfile(self.filepage.georeffile): 02024 return _("File <%s> not found." % self.filepage.georeffile) 02025 02026 grass.create_location(dbase = self.startpage.grassdatabase, 02027 location = self.startpage.location, 02028 filename = self.filepage.georeffile, 02029 desc = self.startpage.locTitle) 02030 elif coordsys == "wkt": 02031 if not self.wktpage.wktfile or \ 02032 not os.path.isfile(self.wktpage.wktfile): 02033 return _("File <%s> not found." % self.wktpage.wktfile) 02034 02035 grass.create_location(dbase = self.startpage.grassdatabase, 02036 location = self.startpage.location, 02037 wkt = self.wktpage.wktfile, 02038 desc = self.startpage.locTitle) 02039 02040 except grass.ScriptError, e: 02041 return e.value 02042 02043 return None 02044 02045 def CreateProj4String(self): 02046 """!Constract PROJ.4 string""" 02047 location = self.startpage.location 02048 proj = self.projpage.p4proj 02049 projdesc = self.projpage.projdesc 02050 proj4params = self.paramspage.p4projparams 02051 02052 datum = self.datumpage.datum 02053 if self.datumpage.datumdesc: 02054 datumdesc = self.datumpage.datumdesc +' - ' + self.datumpage.ellipse 02055 else: 02056 datumdesc = '' 02057 datumparams = self.datumpage.datumparams 02058 ellipse = self.ellipsepage.ellipse 02059 ellipsedesc = self.ellipsepage.ellipsedesc 02060 ellipseparams = self.ellipsepage.ellipseparams 02061 02062 # 02063 # creating PROJ.4 string 02064 # 02065 proj4string = '%s %s' % (proj, proj4params) 02066 02067 # set ellipsoid parameters 02068 if ellipse != '': 02069 proj4string = '%s +ellps=%s' % (proj4string, ellipse) 02070 for item in ellipseparams: 02071 if item[:4] == 'f=1/': 02072 item = ' +rf=' + item[4:] 02073 else: 02074 item = ' +' + item 02075 proj4string = '%s %s' % (proj4string, item) 02076 02077 # set datum and transform parameters if relevant 02078 if datum != '': 02079 proj4string = '%s +datum=%s' % (proj4string, datum) 02080 if datumparams: 02081 for item in datumparams: 02082 proj4string = '%s +%s' % (proj4string,item) 02083 02084 proj4string = '%s +no_defs' % proj4string 02085 02086 return proj4string 02087 02088 class RegionDef(BaseClass, wx.Frame): 02089 """!Page for setting default region extents and resolution 02090 """ 02091 def __init__(self, parent, id = wx.ID_ANY, 02092 title = _("Set default region extent and resolution"), location = None): 02093 wx.Frame.__init__(self, parent, id, title, size = (650,300)) 02094 panel = wx.Panel(self, id = wx.ID_ANY) 02095 02096 self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO)) 02097 02098 self.parent = parent 02099 self.location = location 02100 02101 # 02102 # default values 02103 # 02104 # 2D 02105 self.north = 1.0 02106 self.south = 0.0 02107 self.east = 1.0 02108 self.west = 0.0 02109 self.nsres = 1.0 02110 self.ewres = 1.0 02111 # 3D 02112 self.top = 1.0 02113 self.bottom = 0.0 02114 # self.nsres3 = 1.0 02115 # self.ewres3 = 1.0 02116 self.tbres = 1.0 02117 02118 # 02119 # inputs 02120 # 02121 # 2D 02122 self.tnorth = self.MakeTextCtrl(text = str(self.north), size = (150, -1), parent = panel) 02123 self.tsouth = self.MakeTextCtrl(str(self.south), size = (150, -1), parent = panel) 02124 self.twest = self.MakeTextCtrl(str(self.west), size = (150, -1), parent = panel) 02125 self.teast = self.MakeTextCtrl(str(self.east), size = (150, -1), parent = panel) 02126 self.tnsres = self.MakeTextCtrl(str(self.nsres), size = (150, -1), parent = panel) 02127 self.tewres = self.MakeTextCtrl(str(self.ewres), size = (150, -1), parent = panel) 02128 02129 # 02130 # labels 02131 # 02132 self.lrows = self.MakeLabel(parent = panel) 02133 self.lcols = self.MakeLabel(parent = panel) 02134 self.lcells = self.MakeLabel(parent = panel) 02135 02136 # 02137 # buttons 02138 # 02139 self.bset = self.MakeButton(text = _("&Set region"), id = wx.ID_OK, parent = panel) 02140 self.bcancel = wx.Button(panel, id = wx.ID_CANCEL) 02141 self.bset.SetDefault() 02142 02143 # 02144 # image 02145 # 02146 self.img = wx.Image(os.path.join(globalvar.ETCIMGDIR, "qgis_world.png"), 02147 wx.BITMAP_TYPE_PNG).ConvertToBitmap() 02148 02149 # 02150 # set current working environment to PERMANENT mapset 02151 # in selected location in order to set default region (WIND) 02152 # 02153 envval = {} 02154 ret = gcmd.RunCommand('g.gisenv', 02155 read = True) 02156 if ret: 02157 for line in ret.splitlines(): 02158 key, val = line.split('=') 02159 envval[key] = val 02160 self.currlocation = envval['LOCATION_NAME'].strip("';") 02161 self.currmapset = envval['MAPSET'].strip("';") 02162 if self.currlocation != self.location or self.currmapset != 'PERMANENT': 02163 gcmd.RunCommand('g.gisenv', 02164 set = 'LOCATION_NAME=%s' % self.location) 02165 gcmd.RunCommand('g.gisenv', 02166 set = 'MAPSET=PERMANENT') 02167 else: 02168 dlg = wx.MessageBox(parent = self, 02169 message = _('Invalid location selected.'), 02170 caption = _("Error"), style = wx.ID_OK | wx.ICON_ERROR) 02171 return 02172 02173 # 02174 # get current region settings 02175 # 02176 region = {} 02177 ret = gcmd.RunCommand('g.region', 02178 read = True, 02179 flags = 'gp3') 02180 if ret: 02181 for line in ret.splitlines(): 02182 key, val = line.split('=') 02183 region[key] = float(val) 02184 else: 02185 dlg = wx.MessageBox(parent = self, 02186 message = _("Invalid region"), 02187 caption = _("Error"), style = wx.ID_OK | wx.ICON_ERROR) 02188 dlg.ShowModal() 02189 dlg.Destroy() 02190 return 02191 02192 # 02193 # update values 02194 # 2D 02195 self.north = float(region['n']) 02196 self.south = float(region['s']) 02197 self.east = float(region['e']) 02198 self.west = float(region['w']) 02199 self.nsres = float(region['nsres']) 02200 self.ewres = float(region['ewres']) 02201 self.rows = int(region['rows']) 02202 self.cols = int(region['cols']) 02203 self.cells = int(region['cells']) 02204 # 3D 02205 self.top = float(region['t']) 02206 self.bottom = float(region['b']) 02207 # self.nsres3 = float(region['nsres3']) 02208 # self.ewres3 = float(region['ewres3']) 02209 self.tbres = float(region['tbres']) 02210 self.depth = int(region['depths']) 02211 self.cells3 = int(region['cells3']) 02212 02213 # 02214 # 3D box collapsable 02215 # 02216 self.infoCollapseLabelExp = _("Click here to show 3D settings") 02217 self.infoCollapseLabelCol = _("Click here to hide 3D settings") 02218 self.settings3D = wx.CollapsiblePane(parent = panel, 02219 label = self.infoCollapseLabelExp, 02220 style = wx.CP_DEFAULT_STYLE | 02221 wx.CP_NO_TLW_RESIZE | wx.EXPAND) 02222 self.MakeSettings3DPaneContent(self.settings3D.GetPane()) 02223 self.settings3D.Collapse(False) # FIXME 02224 self.Bind(wx.EVT_COLLAPSIBLEPANE_CHANGED, self.OnSettings3DPaneChanged, self.settings3D) 02225 02226 # 02227 # set current region settings 02228 # 02229 self.tnorth.SetValue(str(self.north)) 02230 self.tsouth.SetValue(str(self.south)) 02231 self.twest.SetValue(str(self.west)) 02232 self.teast.SetValue(str(self.east)) 02233 self.tnsres.SetValue(str(self.nsres)) 02234 self.tewres.SetValue(str(self.ewres)) 02235 self.ttop.SetValue(str(self.top)) 02236 self.tbottom.SetValue(str(self.bottom)) 02237 # self.tnsres3.SetValue(str(self.nsres3)) 02238 # self.tewres3.SetValue(str(self.ewres3)) 02239 self.ttbres.SetValue(str(self.tbres)) 02240 self.lrows.SetLabel(_("Rows: %d") % self.rows) 02241 self.lcols.SetLabel(_("Cols: %d") % self.cols) 02242 self.lcells.SetLabel(_("Cells: %d") % self.cells) 02243 02244 # 02245 # bindings 02246 # 02247 self.Bind(wx.EVT_BUTTON, self.OnSetButton, self.bset) 02248 self.Bind(wx.EVT_BUTTON, self.OnCancel, self.bcancel) 02249 self.tnorth.Bind(wx.EVT_TEXT, self.OnValue) 02250 self.tsouth.Bind(wx.EVT_TEXT, self.OnValue) 02251 self.teast.Bind(wx.EVT_TEXT, self.OnValue) 02252 self.twest.Bind(wx.EVT_TEXT, self.OnValue) 02253 self.tnsres.Bind(wx.EVT_TEXT, self.OnValue) 02254 self.tewres.Bind(wx.EVT_TEXT, self.OnValue) 02255 self.ttop.Bind(wx.EVT_TEXT, self.OnValue) 02256 self.tbottom.Bind(wx.EVT_TEXT, self.OnValue) 02257 # self.tnsres3.Bind(wx.EVT_TEXT, self.OnValue) 02258 # self.tewres3.Bind(wx.EVT_TEXT, self.OnValue) 02259 self.ttbres.Bind(wx.EVT_TEXT, self.OnValue) 02260 02261 self.__DoLayout(panel) 02262 self.SetMinSize(self.GetBestSize()) 02263 self.minWindowSize = self.GetMinSize() 02264 02265 def MakeSettings3DPaneContent(self, pane): 02266 """!Create 3D region settings pane""" 02267 border = wx.BoxSizer(wx.VERTICAL) 02268 gridSizer = wx.GridBagSizer(vgap = 0, hgap = 0) 02269 02270 # inputs 02271 self.ttop = wx.TextCtrl(parent = pane, id = wx.ID_ANY, value = str(self.top), 02272 size = (150, -1)) 02273 self.tbottom = wx.TextCtrl(parent = pane, id = wx.ID_ANY, value = str(self.bottom), 02274 size = (150, -1)) 02275 self.ttbres = wx.TextCtrl(parent = pane, id = wx.ID_ANY, value = str(self.tbres), 02276 size = (150, -1)) 02277 # self.tnsres3 = wx.TextCtrl(parent = pane, id = wx.ID_ANY, value = str(self.nsres3), 02278 # size = (150, -1)) 02279 # self.tewres3 = wx.TextCtrl(parent = pane, id = wx.ID_ANY, value = str(self.ewres3), 02280 # size = (150, -1)) 02281 02282 #labels 02283 self.ldepth = wx.StaticText(parent = pane, label = _("Depth: %d") % self.depth) 02284 self.lcells3 = wx.StaticText(parent = pane, label = _("3D Cells: %d") % self.cells3) 02285 02286 # top 02287 gridSizer.Add(item = wx.StaticText(parent = pane, label = _("Top")), 02288 flag = wx.ALIGN_CENTER | 02289 wx.LEFT | wx.RIGHT | wx.TOP, border = 5, 02290 pos = (0, 1)) 02291 gridSizer.Add(item = self.ttop, 02292 flag = wx.ALIGN_CENTER_HORIZONTAL | 02293 wx.ALL, border = 5, pos = (1, 1)) 02294 # bottom 02295 gridSizer.Add(item = wx.StaticText(parent = pane, label = _("Bottom")), 02296 flag = wx.ALIGN_CENTER | 02297 wx.LEFT | wx.RIGHT | wx.TOP, border = 5, 02298 pos = (0, 2)) 02299 gridSizer.Add(item = self.tbottom, 02300 flag = wx.ALIGN_CENTER_HORIZONTAL | 02301 wx.ALL, border = 5, pos = (1, 2)) 02302 # tbres 02303 gridSizer.Add(item = wx.StaticText(parent = pane, label = _("T-B resolution")), 02304 flag = wx.ALIGN_CENTER | 02305 wx.LEFT | wx.RIGHT | wx.TOP, border = 5, 02306 pos = (0, 3)) 02307 gridSizer.Add(item = self.ttbres, 02308 flag = wx.ALIGN_CENTER_HORIZONTAL | 02309 wx.ALL, border = 5, pos = (1, 3)) 02310 02311 # res 02312 # gridSizer.Add(item = wx.StaticText(parent = pane, label = _("3D N-S resolution")), 02313 # flag = wx.ALIGN_CENTER | 02314 # wx.LEFT | wx.RIGHT | wx.TOP, border = 5, 02315 # pos = (2, 1)) 02316 # gridSizer.Add(item = self.tnsres3, 02317 # flag = wx.ALIGN_CENTER_HORIZONTAL | 02318 # wx.ALL, border = 5, pos = (3, 1)) 02319 # gridSizer.Add(item = wx.StaticText(parent = pane, label = _("3D E-W resolution")), 02320 # flag = wx.ALIGN_CENTER | 02321 # wx.LEFT | wx.RIGHT | wx.TOP, border = 5, 02322 # pos = (2, 3)) 02323 # gridSizer.Add(item = self.tewres3, 02324 # flag = wx.ALIGN_CENTER_HORIZONTAL | 02325 # wx.ALL, border = 5, pos = (3, 3)) 02326 02327 # rows/cols/cells 02328 gridSizer.Add(item = self.ldepth, 02329 flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER | 02330 wx.ALL, border = 5, pos = (2, 1)) 02331 02332 gridSizer.Add(item = self.lcells3, 02333 flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER | 02334 wx.ALL, border = 5, pos = (2, 2)) 02335 02336 border.Add(item = gridSizer, proportion = 1, 02337 flag = wx.ALL | wx.ALIGN_CENTER | wx.EXPAND, border = 5) 02338 02339 pane.SetSizer(border) 02340 border.Fit(pane) 02341 02342 def OnSettings3DPaneChanged(self, event): 02343 """!Collapse 3D settings box""" 02344 02345 if self.settings3D.IsExpanded(): 02346 self.settings3D.SetLabel(self.infoCollapseLabelCol) 02347 self.Layout() 02348 self.SetSize(self.GetBestSize()) 02349 self.SetMinSize(self.GetSize()) 02350 else: 02351 self.settings3D.SetLabel(self.infoCollapseLabelExp) 02352 self.Layout() 02353 self.SetSize(self.minWindowSize) 02354 self.SetMinSize(self.minWindowSize) 02355 02356 self.SendSizeEvent() 02357 02358 def __DoLayout(self, panel): 02359 """!Window layout""" 02360 frameSizer = wx.BoxSizer(wx.VERTICAL) 02361 gridSizer = wx.GridBagSizer(vgap = 0, hgap = 0) 02362 settings3DSizer = wx.BoxSizer(wx.VERTICAL) 02363 buttonSizer = wx.BoxSizer(wx.HORIZONTAL) 02364 02365 # north 02366 gridSizer.Add(item = self.MakeLabel(text = _("North"), parent = panel), 02367 flag = wx.ALIGN_BOTTOM | wx.ALIGN_CENTER_HORIZONTAL | 02368 wx.TOP | wx.LEFT | wx.RIGHT, border = 5, pos = (0, 2)) 02369 gridSizer.Add(item = self.tnorth, 02370 flag = wx.ALIGN_CENTER_HORIZONTAL | 02371 wx.ALIGN_CENTER_VERTICAL | 02372 wx.ALL, border = 5, pos = (1, 2)) 02373 # west 02374 gridSizer.Add(item = self.MakeLabel(text = _("West"), parent = panel), 02375 flag = wx.ALIGN_RIGHT | 02376 wx.ALIGN_CENTER_VERTICAL | 02377 wx.LEFT | wx.TOP | wx.BOTTOM, border = 5, pos = (2, 0)) 02378 gridSizer.Add(item = self.twest, 02379 flag = wx.ALIGN_RIGHT | 02380 wx.ALIGN_CENTER_VERTICAL | 02381 wx.ALL, border = 5, pos = (2, 1)) 02382 02383 gridSizer.Add(item = wx.StaticBitmap(panel, wx.ID_ANY, self.img, (-1, -1), 02384 (self.img.GetWidth(), self.img.GetHeight())), 02385 flag = wx.ALIGN_CENTER | 02386 wx.ALIGN_CENTER_VERTICAL | 02387 wx.ALL, border = 5, pos = (2, 2)) 02388 02389 # east 02390 gridSizer.Add(item = self.teast, 02391 flag = wx.ALIGN_CENTER_HORIZONTAL | 02392 wx.ALIGN_CENTER_VERTICAL | 02393 wx.ALL, border = 5, pos = (2, 3)) 02394 gridSizer.Add(item = self.MakeLabel(text = _("East"), parent = panel), 02395 flag = wx.ALIGN_LEFT | 02396 wx.ALIGN_CENTER_VERTICAL | 02397 wx.RIGHT | wx.TOP | wx.BOTTOM, border = 5, pos = (2, 4)) 02398 # south 02399 gridSizer.Add(item = self.tsouth, 02400 flag = wx.ALIGN_CENTER_HORIZONTAL | 02401 wx.ALIGN_CENTER_VERTICAL | 02402 wx.ALL, border = 5, pos = (3, 2)) 02403 gridSizer.Add(item = self.MakeLabel(text = _("South"), parent = panel), 02404 flag = wx.ALIGN_TOP | wx.ALIGN_CENTER_HORIZONTAL | 02405 wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5, pos = (4, 2)) 02406 # ns-res 02407 gridSizer.Add(item = self.MakeLabel(text = _("N-S resolution"), parent = panel), 02408 flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER | 02409 wx.TOP | wx.LEFT | wx.RIGHT, border = 5, pos = (5, 1)) 02410 gridSizer.Add(item = self.tnsres, 02411 flag = wx.ALIGN_RIGHT | 02412 wx.ALIGN_CENTER_VERTICAL | 02413 wx.ALL, border = 5, pos = (6, 1)) 02414 # ew-res 02415 gridSizer.Add(item = self.MakeLabel(text = _("E-W resolution"), parent = panel), 02416 flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER | 02417 wx.TOP | wx.LEFT | wx.RIGHT, border = 5, pos = (5, 3)) 02418 gridSizer.Add(item = self.tewres, 02419 flag = wx.ALIGN_RIGHT | 02420 wx.ALIGN_CENTER_VERTICAL | 02421 wx.ALL, border = 5, pos = (6, 3)) 02422 # rows/cols/cells 02423 gridSizer.Add(item = self.lrows, 02424 flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER | 02425 wx.ALL, border = 5, pos = (7, 1)) 02426 02427 gridSizer.Add(item = self.lcells, 02428 flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER | 02429 wx.ALL, border = 5, pos = (7, 2)) 02430 02431 gridSizer.Add(item = self.lcols, 02432 flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER | 02433 wx.ALL, border = 5, pos = (7, 3)) 02434 02435 # 3D 02436 settings3DSizer.Add(item = self.settings3D, 02437 flag = wx.ALL, 02438 border = 5) 02439 02440 # buttons 02441 buttonSizer.Add(item = self.bcancel, proportion = 1, 02442 flag = wx.ALIGN_RIGHT | 02443 wx.ALIGN_CENTER_VERTICAL | 02444 wx.ALL, border = 10) 02445 buttonSizer.Add(item = self.bset, proportion = 1, 02446 flag = wx.ALIGN_CENTER | 02447 wx.ALIGN_CENTER_VERTICAL | 02448 wx.ALL, border = 10) 02449 02450 frameSizer.Add(item = gridSizer, proportion = 1, 02451 flag = wx.ALL | wx.ALIGN_CENTER, border = 5) 02452 frameSizer.Add(item = settings3DSizer, proportion = 0, 02453 flag = wx.ALL | wx.ALIGN_CENTER, border = 5) 02454 frameSizer.Add(item = buttonSizer, proportion = 0, 02455 flag = wx.ALL | wx.ALIGN_RIGHT, border = 5) 02456 02457 self.SetAutoLayout(True) 02458 panel.SetSizer(frameSizer) 02459 frameSizer.Fit(panel) 02460 self.Layout() 02461 02462 def OnValue(self, event): 02463 """!Set given value""" 02464 try: 02465 if event.GetId() == self.tnorth.GetId(): 02466 self.north = float(event.GetString()) 02467 elif event.GetId() == self.tsouth.GetId(): 02468 self.south = float(event.GetString()) 02469 elif event.GetId() == self.teast.GetId(): 02470 self.east = float(event.GetString()) 02471 elif event.GetId() == self.twest.GetId(): 02472 self.west = float(event.GetString()) 02473 elif event.GetId() == self.tnsres.GetId(): 02474 self.nsres = float(event.GetString()) 02475 elif event.GetId() == self.tewres.GetId(): 02476 self.ewres = float(event.GetString()) 02477 elif event.GetId() == self.ttop.GetId(): 02478 self.top = float(event.GetString()) 02479 elif event.GetId() == self.tbottom.GetId(): 02480 self.bottom = float(event.GetString()) 02481 # elif event.GetId() == self.tnsres3.GetId(): 02482 # self.nsres3 = float(event.GetString()) 02483 # elif event.GetId() == self.tewres3.GetId(): 02484 # self.ewres3 = float(event.GetString()) 02485 elif event.GetId() == self.ttbres.GetId(): 02486 self.tbres = float(event.GetString()) 02487 02488 self.__UpdateInfo() 02489 02490 except ValueError, e: 02491 if len(event.GetString()) > 0 and event.GetString() != '-': 02492 dlg = wx.MessageBox(parent = self, 02493 message = _("Invalid value: %s") % e, 02494 caption = _("Error"), 02495 style = wx.OK | wx.ICON_ERROR) 02496 # reset values 02497 self.tnorth.SetValue(str(self.north)) 02498 self.tsouth.SetValue(str(self.south)) 02499 self.teast.SetValue(str(self.east)) 02500 self.twest.SetValue(str(self.west)) 02501 self.tnsres.SetValue(str(self.nsres)) 02502 self.tewres.SetValue(str(self.ewres)) 02503 self.ttop.SetValue(str(self.top)) 02504 self.tbottom.SetValue(str(self.bottom)) 02505 self.ttbres.SetValue(str(self.tbres)) 02506 # self.tnsres3.SetValue(str(self.nsres3)) 02507 # self.tewres3.SetValue(str(self.ewres3)) 02508 02509 event.Skip() 02510 02511 def __UpdateInfo(self): 02512 """!Update number of rows/cols/cells""" 02513 self.rows = int((self.north - self.south) / self.nsres) 02514 self.cols = int((self.east - self.west) / self.ewres) 02515 self.cells = self.rows * self.cols 02516 02517 self.depth = int((self.top - self.bottom) / self.tbres) 02518 self.cells3 = self.rows * self.cols * self.depth 02519 02520 # 2D 02521 self.lrows.SetLabel(_("Rows: %d") % self.rows) 02522 self.lcols.SetLabel(_("Cols: %d") % self.cols) 02523 self.lcells.SetLabel(_("Cells: %d") % self.cells) 02524 # 3D 02525 self.ldepth.SetLabel(_("Depth: %d" % self.depth)) 02526 self.lcells3.SetLabel(_("3D Cells: %d" % self.cells3)) 02527 02528 def OnSetButton(self, event = None): 02529 """!Set default region""" 02530 ret = gcmd.RunCommand('g.region', 02531 flags = 'sgpa', 02532 n = self.north, 02533 s = self.south, 02534 e = self.east, 02535 w = self.west, 02536 nsres = self.nsres, 02537 ewres = self.ewres, 02538 t = self.top, 02539 b = self.bottom, 02540 tbres = self.tbres) 02541 if ret == 0: 02542 self.Destroy() 02543 02544 def OnCancel(self, event): 02545 self.Destroy() 02546 02547 class TransList(wx.VListBox): 02548 """!Creates a multiline listbox for selecting datum transforms""" 02549 02550 def OnDrawItem(self, dc, rect, n): 02551 if self.GetSelection() == n: 02552 c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT) 02553 else: 02554 c = self.GetForegroundColour() 02555 dc.SetFont(self.GetFont()) 02556 dc.SetTextForeground(c) 02557 dc.DrawLabel(self._getItemText(n), rect, 02558 wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) 02559 02560 def OnMeasureItem(self, n): 02561 height = 0 02562 if self._getItemText(n) == None: 02563 return 02564 for line in self._getItemText(n).splitlines(): 02565 w, h = self.GetTextExtent(line) 02566 height += h 02567 return height + 5 02568 02569 def _getItemText(self, item): 02570 global transformlist 02571 transitem = transformlist[item] 02572 if transitem.strip() !='': 02573 return transitem 02574 02575 02576 class SelectTransformDialog(wx.Dialog): 02577 """!Dialog for selecting datum transformations""" 02578 def __init__(self, parent, transforms, title = _("Select datum transformation"), 02579 pos = wx.DefaultPosition, size = wx.DefaultSize, 02580 style = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER): 02581 02582 wx.Dialog.__init__(self, parent, wx.ID_ANY, title, pos, size, style) 02583 02584 global transformlist 02585 self.CentreOnParent() 02586 02587 # default transform number 02588 self.transnum = 0 02589 02590 panel = scrolled.ScrolledPanel(self, wx.ID_ANY) 02591 sizer = wx.BoxSizer(wx.VERTICAL) 02592 02593 # 02594 # set panel sizer 02595 # 02596 panel.SetSizer(sizer) 02597 panel.SetupScrolling() 02598 02599 # 02600 # dialog body 02601 # 02602 bodyBox = wx.StaticBox(parent = panel, id = wx.ID_ANY, 02603 label = " %s " % _("Select from list of datum transformations")) 02604 bodySizer = wx.StaticBoxSizer(bodyBox) 02605 02606 # add no transform option 02607 transforms = '---\n\n0\nDo not apply any datum transformations\n\n' + transforms 02608 02609 transformlist = transforms.split('---') 02610 tlistlen = len(transformlist) 02611 02612 # calculate size for transform list 02613 height = 0 02614 width = 0 02615 for line in transforms.splitlines(): 02616 w, h = self.GetTextExtent(line) 02617 height += h 02618 width = max(width, w) 02619 02620 height = height + 5 02621 if height > 400: height = 400 02622 width = width + 5 02623 if width > 400: width = 400 02624 02625 # 02626 # VListBox for displaying and selecting transformations 02627 # 02628 self.translist = TransList(panel, id = -1, size = (width, height), style = wx.SUNKEN_BORDER) 02629 self.translist.SetItemCount(tlistlen) 02630 self.translist.SetSelection(2) 02631 self.translist.SetFocus() 02632 02633 self.Bind(wx.EVT_LISTBOX, self.ClickTrans, self.translist) 02634 02635 bodySizer.Add(item = self.translist, proportion = 1, flag = wx.ALIGN_CENTER|wx.ALL|wx.EXPAND) 02636 02637 # 02638 # buttons 02639 # 02640 btnsizer = wx.StdDialogButtonSizer() 02641 02642 btn = wx.Button(parent = panel, id = wx.ID_OK) 02643 btn.SetDefault() 02644 btnsizer.AddButton(btn) 02645 02646 btn = wx.Button(parent = panel, id = wx.ID_CANCEL) 02647 btnsizer.AddButton(btn) 02648 btnsizer.Realize() 02649 02650 sizer.Add(item = bodySizer, proportion = 1, 02651 flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5) 02652 02653 sizer.Add(item = btnsizer, proportion = 0, 02654 flag = wx.ALL | wx.ALIGN_RIGHT, border = 5) 02655 02656 sizer.Fit(panel) 02657 02658 self.SetSize(self.GetBestSize()) 02659 self.Layout() 02660 02661 def ClickTrans(self, event): 02662 """!Get the number of the datum transform to use in g.proj""" 02663 self.transnum = event.GetSelection() 02664 self.transnum = self.transnum - 1 02665 02666 def GetTransform(self): 02667 """!Get the number of the datum transform to use in g.proj""" 02668 self.transnum = self.translist.GetSelection() 02669 self.transnum = self.transnum - 1 02670 return self.transnum 02671 02672 if __name__ == "__main__": 02673 import gettext 02674 gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True) 02675 app = wx.PySimpleApp() 02676 gWizard = RegionDef(None) 02677 gWizzard.Show() 02678 app.MainLoop()