|
GRASS Programmer's Manual
6.5.svn(2012)-r51648
|
00001 """! 00002 @package location_wizard.wizard 00003 00004 @brief Location wizard - creates a new GRASS Location. User can choose 00005 from multiple methods. 00006 00007 Classes: 00008 - wizard::TitledPage 00009 - wizard::DatabasePage 00010 - wizard::CoordinateSystemPage 00011 - wizard::ProjectionsPage 00012 - wizard::ItemList 00013 - wizard::ProjParamsPage 00014 - wizard::DatumPage 00015 - wizard::EllipsePage 00016 - wizard::GeoreferencedFilePage 00017 - wizard::WKTPage 00018 - wizard::EPSGPage 00019 - wizard::CustomPage 00020 - wizard::SummaryPage 00021 - wizard::LocationWizard 00022 00023 (C) 2007-2011 by the GRASS Development Team 00024 00025 This program is free software under the GNU General Public License 00026 (>=v2). Read the file COPYING that comes with GRASS for details. 00027 00028 @author Michael Barton 00029 @author Jachym Cepicky 00030 @author Martin Landa <landa.martin gmail.com> 00031 """ 00032 import os 00033 import locale 00034 00035 import wx 00036 import wx.lib.mixins.listctrl as listmix 00037 import wx.wizard as wiz 00038 import wx.lib.scrolledpanel as scrolled 00039 00040 from core import globalvar 00041 from core import utils 00042 from core.gcmd import RunCommand, GError, GMessage, GWarning 00043 from location_wizard.base import BaseClass 00044 from location_wizard.dialogs import RegionDef, SelectTransformDialog 00045 00046 from grass.script import core as grass 00047 00048 global coordsys 00049 global north 00050 global south 00051 global east 00052 global west 00053 global resolution 00054 global wizerror 00055 global translist 00056 00057 class TitledPage(BaseClass, wiz.WizardPageSimple): 00058 """!Class to make wizard pages. Generic methods to make labels, 00059 text entries, and buttons. 00060 """ 00061 def __init__(self, parent, title): 00062 00063 self.page = wiz.WizardPageSimple.__init__(self, parent) 00064 00065 # page title 00066 self.title = wx.StaticText(parent = self, id = wx.ID_ANY, label = title) 00067 self.title.SetFont(wx.Font(13, wx.SWISS, wx.NORMAL, wx.BOLD)) 00068 00069 # main sizers 00070 self.pagesizer = wx.BoxSizer(wx.VERTICAL) 00071 self.sizer = wx.GridBagSizer(vgap = 0, hgap = 0) 00072 00073 def DoLayout(self): 00074 """!Do page layout""" 00075 self.pagesizer.Add(item = self.title, proportion = 0, 00076 flag = wx.ALIGN_CENTRE | wx.ALL, 00077 border = 5) 00078 self.pagesizer.Add(item = wx.StaticLine(self, -1), proportion = 0, 00079 flag = wx.EXPAND | wx.ALL, 00080 border = 0) 00081 self.pagesizer.Add(item = self.sizer, proportion = 1, 00082 flag = wx.EXPAND) 00083 00084 self.SetAutoLayout(True) 00085 self.SetSizer(self.pagesizer) 00086 self.Layout() 00087 00088 class DatabasePage(TitledPage): 00089 """!Wizard page for setting GIS data directory and location name""" 00090 def __init__(self, wizard, parent, grassdatabase): 00091 TitledPage.__init__(self, wizard, _("Define GRASS Database and Location Name")) 00092 00093 self.grassdatabase = grassdatabase 00094 self.location = '' 00095 self.locTitle = '' 00096 00097 # buttons 00098 self.bbrowse = self.MakeButton(_("Browse")) 00099 00100 # text controls 00101 self.tgisdbase = self.MakeTextCtrl(grassdatabase, size = (300, -1)) 00102 self.tlocation = self.MakeTextCtrl("newLocation", size = (300, -1)) 00103 self.tlocTitle = self.MakeTextCtrl(size = (400, -1)) 00104 00105 # layout 00106 self.sizer.AddGrowableCol(3) 00107 self.sizer.Add(item = self.MakeLabel(_("GIS Data Directory:")), 00108 flag = wx.ALIGN_RIGHT | 00109 wx.ALIGN_CENTER_VERTICAL | 00110 wx.ALL, border = 5, 00111 pos = (1, 1)) 00112 self.sizer.Add(item = self.tgisdbase, 00113 flag = wx.ALIGN_LEFT | 00114 wx.ALIGN_CENTER_VERTICAL | 00115 wx.ALL, border = 5, 00116 pos = (1, 2)) 00117 self.sizer.Add(item = self.bbrowse, 00118 flag = wx.ALIGN_LEFT | 00119 wx.ALIGN_CENTER_VERTICAL | 00120 wx.ALL, border = 5, 00121 pos = (1, 3)) 00122 00123 self.sizer.Add(item = self.MakeLabel("%s:" % _("Project Location")), 00124 flag = wx.ALIGN_RIGHT | 00125 wx.ALIGN_CENTER_VERTICAL | 00126 wx.ALL, border = 5, 00127 pos = (2, 1)) 00128 self.sizer.Add(item = self.tlocation, 00129 flag = wx.ALIGN_LEFT | 00130 wx.ALIGN_CENTER_VERTICAL | 00131 wx.ALL, border = 5, 00132 pos = (2, 2)) 00133 00134 self.sizer.Add(item = self.MakeLabel("%s:" % _("Location Title")), 00135 flag = wx.ALIGN_RIGHT | 00136 wx.ALIGN_TOP | wx.ALIGN_CENTER_VERTICAL | 00137 wx.ALL, border = 5, 00138 pos = (3, 1)) 00139 self.sizer.Add(item = self.tlocTitle, 00140 flag = wx.ALIGN_LEFT | 00141 wx.ALIGN_CENTER_VERTICAL | 00142 wx.ALL, border = 5, 00143 pos = (3, 2), span = (1, 2)) 00144 00145 # bindings 00146 self.Bind(wx.EVT_BUTTON, self.OnBrowse, self.bbrowse) 00147 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging) 00148 self.tgisdbase.Bind(wx.EVT_TEXT, self.OnChangeName) 00149 self.tlocation.Bind(wx.EVT_TEXT, self.OnChangeName) 00150 00151 def OnChangeName(self, event): 00152 """!Name for new location was changed""" 00153 nextButton = wx.FindWindowById(wx.ID_FORWARD) 00154 if len(event.GetString()) > 0: 00155 if not nextButton.IsEnabled(): 00156 nextButton.Enable() 00157 else: 00158 nextButton.Disable() 00159 00160 event.Skip() 00161 00162 def OnBrowse(self, event): 00163 """!Choose GRASS data directory""" 00164 dlg = wx.DirDialog(self, _("Choose GRASS data directory:"), 00165 os.getcwd(), wx.DD_DEFAULT_STYLE) 00166 if dlg.ShowModal() == wx.ID_OK: 00167 self.grassdatabase = dlg.GetPath() 00168 self.tgisdbase.SetValue(self.grassdatabase) 00169 00170 dlg.Destroy() 00171 00172 def OnPageChanging(self, event = None): 00173 error = None 00174 if os.path.isdir(os.path.join(self.tgisdbase.GetValue(), self.tlocation.GetValue())): 00175 error = _("Location already exists in GRASS Database.") 00176 00177 if error: 00178 GError(parent = self, 00179 message="%s <%s>.%s%s" % (_("Unable to create location"), 00180 str(self.tlocation.GetValue()), 00181 os.linesep, 00182 error)) 00183 event.Veto() 00184 return 00185 00186 self.location = self.tlocation.GetValue() 00187 self.grassdatabase = self.tgisdbase.GetValue() 00188 self.locTitle = self.tlocTitle.GetValue() 00189 if os.linesep in self.locTitle or \ 00190 len(self.locTitle) > 255: 00191 GWarning(parent = self, 00192 message = _("Title of the location is limited only to one line and " 00193 "256 characters. The rest of the text will be ignored.")) 00194 self.locTitle = self.locTitle.split(os.linesep)[0][:255] 00195 00196 class CoordinateSystemPage(TitledPage): 00197 """!Wizard page for choosing method for location creation""" 00198 def __init__(self, wizard, parent): 00199 TitledPage.__init__(self, wizard, _("Choose method for creating a new location")) 00200 00201 self.parent = parent 00202 global coordsys 00203 00204 # toggles 00205 self.radio1 = wx.RadioButton(parent = self, id = wx.ID_ANY, 00206 label = _("Select coordinate system parameters from a list"), 00207 style = wx.RB_GROUP) 00208 self.radio2 = wx.RadioButton(parent = self, id = wx.ID_ANY, 00209 label = _("Select EPSG code of spatial reference system")) 00210 self.radio3 = wx.RadioButton(parent = self, id = wx.ID_ANY, 00211 label = _("Read projection and datum terms from a " 00212 "georeferenced data file")) 00213 self.radio4 = wx.RadioButton(parent = self, id = wx.ID_ANY, 00214 label = _("Read projection and datum terms from a " 00215 "WKT or PRJ file")) 00216 self.radio5 = wx.RadioButton(parent = self, id = wx.ID_ANY, 00217 label = _("Specify projection and datum terms using custom " 00218 "PROJ.4 parameters")) 00219 self.radio6 = wx.RadioButton(parent = self, id = wx.ID_ANY, 00220 label = _("Create a generic Cartesian coordinate system (XY)")) 00221 00222 # layout 00223 self.sizer.AddGrowableCol(1) 00224 self.sizer.SetVGap(10) 00225 self.sizer.Add(item = self.radio1, 00226 flag = wx.ALIGN_LEFT, pos = (1, 1)) 00227 self.sizer.Add(item = self.radio2, 00228 flag = wx.ALIGN_LEFT, pos = (2, 1)) 00229 self.sizer.Add(item = self.radio3, 00230 flag = wx.ALIGN_LEFT, pos = (3, 1)) 00231 self.sizer.Add(item = self.radio4, 00232 flag = wx.ALIGN_LEFT, pos = (4, 1)) 00233 self.sizer.Add(item = self.radio5, 00234 flag = wx.ALIGN_LEFT, pos = (5, 1)) 00235 self.sizer.Add(item = self.radio6, 00236 flag = wx.ALIGN_LEFT, pos = (6, 1)) 00237 00238 # bindings 00239 self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio1.GetId()) 00240 self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio2.GetId()) 00241 self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio3.GetId()) 00242 self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio4.GetId()) 00243 self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio5.GetId()) 00244 self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio6.GetId()) 00245 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 00246 00247 def OnEnterPage(self, event): 00248 global coordsys 00249 00250 if not coordsys: 00251 coordsys = "proj" 00252 self.radio1.SetValue(True) 00253 else: 00254 if coordsys == 'proj': 00255 self.radio1.SetValue(True) 00256 if coordsys == "epsg": 00257 self.radio2.SetValue(True) 00258 if coordsys == "file": 00259 self.radio3.SetValue(True) 00260 if coordsys == "wkt": 00261 self.radio4.SetValue(True) 00262 if coordsys == "custom": 00263 self.radio5.SetValue(True) 00264 if coordsys == "xy": 00265 self.radio6.SetValue(True) 00266 00267 if event.GetDirection(): 00268 if coordsys == 'proj': 00269 self.SetNext(self.parent.projpage) 00270 self.parent.sumpage.SetPrev(self.parent.datumpage) 00271 if coordsys == "epsg": 00272 self.SetNext(self.parent.epsgpage) 00273 self.parent.sumpage.SetPrev(self.parent.epsgpage) 00274 if coordsys == "file": 00275 self.SetNext(self.parent.filepage) 00276 self.parent.sumpage.SetPrev(self.parent.filepage) 00277 if coordsys == "wkt": 00278 self.SetNext(self.parent.wktpage) 00279 self.parent.sumpage.SetPrev(self.parent.wktpage) 00280 if coordsys == "custom": 00281 self.SetNext(self.parent.custompage) 00282 self.parent.sumpage.SetPrev(self.parent.custompage) 00283 if coordsys == "xy": 00284 self.SetNext(self.parent.sumpage) 00285 self.parent.sumpage.SetPrev(self.parent.csystemspage) 00286 00287 if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled(): 00288 wx.FindWindowById(wx.ID_FORWARD).Enable() 00289 00290 def SetVal(self, event): 00291 """!Choose method""" 00292 global coordsys 00293 if event.GetId() == self.radio1.GetId(): 00294 coordsys = "proj" 00295 self.SetNext(self.parent.projpage) 00296 self.parent.sumpage.SetPrev(self.parent.datumpage) 00297 elif event.GetId() == self.radio2.GetId(): 00298 coordsys = "epsg" 00299 self.SetNext(self.parent.epsgpage) 00300 self.parent.sumpage.SetPrev(self.parent.epsgpage) 00301 elif event.GetId() == self.radio3.GetId(): 00302 coordsys = "file" 00303 self.SetNext(self.parent.filepage) 00304 self.parent.sumpage.SetPrev(self.parent.filepage) 00305 elif event.GetId() == self.radio4.GetId(): 00306 coordsys = "wkt" 00307 self.SetNext(self.parent.wktpage) 00308 self.parent.sumpage.SetPrev(self.parent.wktpage) 00309 elif event.GetId() == self.radio5.GetId(): 00310 coordsys = "custom" 00311 self.SetNext(self.parent.custompage) 00312 self.parent.sumpage.SetPrev(self.parent.custompage) 00313 elif event.GetId() == self.radio6.GetId(): 00314 coordsys = "xy" 00315 self.SetNext(self.parent.sumpage) 00316 self.parent.sumpage.SetPrev(self.parent.csystemspage) 00317 00318 class ProjectionsPage(TitledPage): 00319 """!Wizard page for selecting projection (select coordinate system option)""" 00320 def __init__(self, wizard, parent): 00321 TitledPage.__init__(self, wizard, _("Choose projection")) 00322 00323 self.parent = parent 00324 self.proj = '' 00325 self.projdesc = '' 00326 self.p4proj = '' 00327 00328 # text input 00329 self.tproj = self.MakeTextCtrl("", size = (200,-1)) 00330 00331 # search box 00332 self.searchb = wx.SearchCtrl(self, size = (200,-1), 00333 style = wx.TE_PROCESS_ENTER) 00334 00335 # projection list 00336 self.projlist = ItemList(self, data = self.parent.projdesc.items(), 00337 columns = [_('Code'), _('Description')]) 00338 self.projlist.resizeLastColumn(30) 00339 00340 # layout 00341 self.sizer.AddGrowableCol(3) 00342 self.sizer.Add(item = self.MakeLabel(_("Projection code:")), 00343 flag = wx.ALIGN_LEFT | 00344 wx.ALIGN_CENTER_VERTICAL | 00345 wx.ALL, border = 5, pos = (1, 1)) 00346 self.sizer.Add(item = self.tproj, 00347 flag = wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL, 00348 border = 5, pos = (1, 2)) 00349 00350 self.sizer.Add(item = self.MakeLabel(_("Search in description:")), 00351 flag = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 00352 border = 5, pos = (2, 1)) 00353 self.sizer.Add(item = self.searchb, 00354 flag = wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL, 00355 border = 5, pos = (2, 2)) 00356 00357 self.sizer.AddGrowableRow(3) 00358 self.sizer.Add(item = self.projlist, 00359 flag = wx.EXPAND | 00360 wx.ALIGN_LEFT | 00361 wx.ALL, border = 5, pos = (3, 1), span = (1, 3)) 00362 00363 # events 00364 self.tproj.Bind(wx.EVT_TEXT, self.OnText) 00365 self.tproj.Bind(wx.EVT_TEXT_ENTER, self.OnText) 00366 self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnSearch) 00367 self.projlist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected) 00368 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging) 00369 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 00370 00371 def OnPageChanging(self,event): 00372 if event.GetDirection() and self.proj not in self.parent.projections.keys(): 00373 event.Veto() 00374 00375 def OnText(self, event): 00376 """!Projection name changed""" 00377 self.proj = event.GetString().lower() 00378 self.p4proj = '' 00379 nextButton = wx.FindWindowById(wx.ID_FORWARD) 00380 if self.proj not in self.parent.projections.keys() and nextButton.IsEnabled(): 00381 nextButton.Enable(False) 00382 00383 if self.proj in self.parent.projections.keys(): 00384 if self.proj == 'stp': 00385 wx.MessageBox('Currently State Plane projections must be selected using the ' 00386 'text-based setup (g.setproj), or entered by EPSG code or ' 00387 'custom PROJ.4 terms.', 00388 'Warning', wx.ICON_WARNING) 00389 self.proj = '' 00390 self.tproj.SetValue(self.proj) 00391 nextButton.Enable(False) 00392 return 00393 elif self.proj.lower() == 'll': 00394 self.p4proj = '+proj=longlat' 00395 else: 00396 self.p4proj = '+proj=' + self.proj.lower() 00397 self.projdesc = self.parent.projections[self.proj][0] 00398 nextButton.Enable() 00399 00400 def OnEnterPage(self, event): 00401 if len(self.proj) == 0: 00402 # disable 'next' button by default 00403 wx.FindWindowById(wx.ID_FORWARD).Enable(False) 00404 else: 00405 wx.FindWindowById(wx.ID_FORWARD).Enable(True) 00406 00407 event.Skip() 00408 00409 def OnSearch(self, event): 00410 """!Search projection by desc""" 00411 str = event.GetString() 00412 try: 00413 self.proj, self.projdesc = self.projlist.Search(index = [0,1], pattern = event.GetString()) 00414 except: 00415 self.proj = self.projdesc = '' 00416 00417 event.Skip() 00418 00419 def OnItemSelected(self, event): 00420 """!Projection selected""" 00421 index = event.m_itemIndex 00422 00423 # set values 00424 self.proj = self.projlist.GetItem(index, 0).GetText().lower() 00425 self.tproj.SetValue(self.proj) 00426 00427 event.Skip() 00428 00429 class ItemList(wx.ListCtrl, 00430 listmix.ListCtrlAutoWidthMixin, 00431 listmix.ColumnSorterMixin): 00432 """!Generic list (for projections, ellipsoids, etc.)""" 00433 00434 def __init__(self, parent, columns, data = None): 00435 wx.ListCtrl.__init__(self, parent = parent, id = wx.ID_ANY, 00436 style = wx.LC_REPORT | 00437 wx.LC_VIRTUAL | 00438 wx.LC_HRULES | 00439 wx.LC_VRULES | 00440 wx.LC_SINGLE_SEL | 00441 wx.LC_SORT_ASCENDING, size = (550, 125)) 00442 00443 # original data or None 00444 self.sourceData = data 00445 00446 # 00447 # insert columns 00448 # 00449 i = 0 00450 for column in columns: 00451 self.InsertColumn(i, column) 00452 i += 1 00453 00454 if self.sourceData: 00455 self.Populate() 00456 00457 for i in range(self.GetColumnCount()): 00458 self.SetColumnWidth(i, wx.LIST_AUTOSIZE_USEHEADER) 00459 if self.GetColumnWidth(i) < 80: 00460 self.SetColumnWidth(i, 80) 00461 00462 # 00463 # listmix 00464 # 00465 listmix.ListCtrlAutoWidthMixin.__init__(self) 00466 listmix.ColumnSorterMixin.__init__(self, self.GetColumnCount()) 00467 00468 # 00469 # add some attributes 00470 # 00471 self.attr1 = wx.ListItemAttr() 00472 self.attr1.SetBackgroundColour(wx.Colour(238,238,238)) 00473 self.attr2 = wx.ListItemAttr() 00474 self.attr2.SetBackgroundColour("white") 00475 self.il = wx.ImageList(16, 16) 00476 self.sm_up = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_GO_UP, wx.ART_TOOLBAR, 00477 (16,16))) 00478 self.sm_dn = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_GO_DOWN, wx.ART_TOOLBAR, 00479 (16,16))) 00480 self.SetImageList(self.il, wx.IMAGE_LIST_SMALL) 00481 00482 # 00483 # sort by first column 00484 # 00485 if self.sourceData: 00486 self.SortListItems(col = 0, ascending = True) 00487 00488 # 00489 # bindings 00490 # 00491 self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColumnClick) 00492 00493 def Populate(self, data = None, update = False): 00494 """!Populate list""" 00495 self.itemDataMap = {} 00496 self.itemIndexMap = [] 00497 00498 if data is None: 00499 data = self.sourceData 00500 elif update: 00501 self.sourceData = data 00502 00503 try: 00504 data.sort() 00505 self.DeleteAllItems() 00506 row = 0 00507 for value in data: 00508 self.itemDataMap[row] = [value[0]] 00509 for i in range(1, len(value)): 00510 self.itemDataMap[row].append(value[i]) 00511 self.itemIndexMap.append(row) 00512 row += 1 00513 00514 self.SetItemCount(row) 00515 00516 # set column width 00517 self.SetColumnWidth(0, 80) 00518 self.SetColumnWidth(1, 300) 00519 00520 self.SendSizeEvent() 00521 00522 except StandardError, e: 00523 wx.MessageBox(parent = self, 00524 message = _("Unable to read list: %s") % e, 00525 caption = _("Error"), style = wx.OK | wx.ICON_ERROR) 00526 00527 def OnColumnClick(self, event): 00528 """!Sort by column""" 00529 self._col = event.GetColumn() 00530 00531 # remove duplicated arrow symbol from column header 00532 # FIXME: should be done automatically 00533 info = wx.ListItem() 00534 info.m_mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE 00535 info.m_image = -1 00536 for column in range(self.GetColumnCount()): 00537 info.m_text = self.GetColumn(column).GetText() 00538 self.SetColumn(column, info) 00539 00540 event.Skip() 00541 00542 def GetSortImages(self): 00543 """!Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py""" 00544 return (self.sm_dn, self.sm_up) 00545 00546 def OnGetItemText(self, item, col): 00547 """!Get item text""" 00548 index = self.itemIndexMap[item] 00549 s = str(self.itemDataMap[index][col]) 00550 return s 00551 00552 def OnGetItemAttr(self, item): 00553 """!Get item attributes""" 00554 index = self.itemIndexMap[item] 00555 if ( index % 2) == 0: 00556 return self.attr2 00557 else: 00558 return self.attr1 00559 00560 def SortItems(self, sorter = cmp): 00561 """!Sort items""" 00562 items = list(self.itemDataMap.keys()) 00563 items.sort(self.Sorter) 00564 self.itemIndexMap = items 00565 00566 # redraw the list 00567 self.Refresh() 00568 00569 def Sorter(self, key1, key2): 00570 colName = self.GetColumn(self._col).GetText() 00571 ascending = self._colSortFlag[self._col] 00572 # convert always string 00573 item1 = self.itemDataMap[key1][self._col] 00574 item2 = self.itemDataMap[key2][self._col] 00575 00576 if type(item1) == type('') or type(item2) == type(''): 00577 cmpVal = locale.strcoll(str(item1), str(item2)) 00578 else: 00579 cmpVal = cmp(item1, item2) 00580 00581 00582 # If the items are equal then pick something else to make the sort value unique 00583 if cmpVal == 0: 00584 cmpVal = apply(cmp, self.GetSecondarySortValues(self._col, key1, key2)) 00585 00586 if ascending: 00587 return cmpVal 00588 else: 00589 return -cmpVal 00590 00591 def GetListCtrl(self): 00592 """!Used by listmix.ColumnSorterMixin""" 00593 return self 00594 00595 def Search (self, index, pattern): 00596 """!Search projection by description 00597 Return first found item or None 00598 """ 00599 if pattern == '': 00600 self.Populate(self.sourceData) 00601 return [] 00602 00603 data = [] 00604 pattern = pattern.lower() 00605 for i in range(len(self.sourceData)): 00606 for idx in index: 00607 try: 00608 value = str(self.sourceData[i][idx]).lower() 00609 if pattern in value: 00610 data.append(self.sourceData[i]) 00611 break 00612 except UnicodeDecodeError: 00613 # osgeo4w problem (should be fixed) 00614 pass 00615 00616 self.Populate(data) 00617 if len(data) > 0: 00618 return data[0] 00619 else: 00620 return [] 00621 00622 class ProjParamsPage(TitledPage): 00623 """!Wizard page for selecting method of setting coordinate system 00624 parameters (select coordinate system option) 00625 """ 00626 def __init__(self, wizard, parent): 00627 TitledPage.__init__(self, wizard, _("Choose projection parameters")) 00628 global coordsys 00629 00630 self.parent = parent 00631 self.panel = None 00632 self.prjParamSizer = None 00633 00634 self.pparam = dict() 00635 00636 self.p4projparams = '' 00637 self.projdesc = '' 00638 00639 self.sizer.AddGrowableCol(1) 00640 self.sizer.AddGrowableRow(1) 00641 00642 radioSBox = wx.StaticBox(parent = self, id = wx.ID_ANY, 00643 label = " %s " % _("Select datum or ellipsoid (next page)")) 00644 radioSBSizer = wx.StaticBoxSizer(radioSBox) 00645 self.sizer.Add(item = radioSBSizer, pos = (0, 1), 00646 flag = wx.EXPAND | wx.ALIGN_TOP | wx.TOP, border = 10) 00647 00648 self.radio1 = wx.RadioButton(parent = self, id = wx.ID_ANY, 00649 label = _("Datum with associated ellipsoid"), 00650 style = wx.RB_GROUP) 00651 self.radio2 = wx.RadioButton(parent = self, id = wx.ID_ANY, 00652 label = _("Ellipsoid only")) 00653 00654 # default button setting 00655 if self.radio1.GetValue() == False and self.radio2.GetValue() == False: 00656 self.radio1.SetValue(True) 00657 self.SetNext(self.parent.datumpage) 00658 # self.parent.sumpage.SetPrev(self.parent.datumpage) 00659 00660 radioSBSizer.Add(item = self.radio1, 00661 flag = wx.ALIGN_LEFT | wx.RIGHT, border = 20) 00662 radioSBSizer.Add(item = self.radio2, 00663 flag = wx.ALIGN_LEFT) 00664 00665 # bindings 00666 self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio1.GetId()) 00667 self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio2.GetId()) 00668 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChange) 00669 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 00670 00671 def OnParamEntry(self, event): 00672 """!Parameter value changed""" 00673 id = event.GetId() 00674 val = event.GetString() 00675 00676 if id not in self.pparam: 00677 event.Skip() 00678 return 00679 00680 param = self.pparam[id] 00681 win = self.FindWindowById(id) 00682 if param['type'] == 'zone': 00683 val = event.GetInt() 00684 if val < 1: 00685 win.SetValue(1) 00686 elif val > 60: 00687 win.SetValue(60) 00688 00689 if param['type'] == 'bool': 00690 param['value'] = event.GetSelection() 00691 else: 00692 param['value'] = val 00693 00694 event.Skip() 00695 00696 def OnPageChange(self,event=None): 00697 """!Go to next page""" 00698 if event.GetDirection(): 00699 self.p4projparams = '' 00700 for id, param in self.pparam.iteritems(): 00701 if param['type'] == 'bool': 00702 if param['value'] == False: 00703 continue 00704 else: 00705 self.p4projparams += (' +' + param['proj4']) 00706 else: 00707 if param['value'] is None: 00708 wx.MessageBox(parent = self, 00709 message = _('You must enter a value for %s') % param['desc'], 00710 caption = _('Error'), style = wx.ICON_ERROR | wx.CENTRE) 00711 event.Veto() 00712 else: 00713 self.p4projparams += (' +' + param['proj4'] + '=' + str(param['value'])) 00714 00715 def OnEnterPage(self,event): 00716 """!Page entered""" 00717 self.projdesc = self.parent.projections[self.parent.projpage.proj][0] 00718 if self.prjParamSizer is None: 00719 # entering page for the first time 00720 self.paramSBox = wx.StaticBox(parent = self, id = wx.ID_ANY, 00721 label = _(" Enter parameters for %s projection ") % self.projdesc) 00722 paramSBSizer = wx.StaticBoxSizer(self.paramSBox) 00723 00724 self.panel = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY) 00725 self.panel.SetupScrolling() 00726 00727 self.prjParamSizer = wx.GridBagSizer(vgap = 0, hgap = 0) 00728 00729 self.sizer.Add(item = paramSBSizer, pos = (1, 1), 00730 flag = wx.EXPAND) 00731 paramSBSizer.Add(item = self.panel, proportion = 1, 00732 flag = wx.ALIGN_CENTER | wx.EXPAND) 00733 00734 paramSBSizer.Fit(self.panel) 00735 self.panel.SetSizer(self.prjParamSizer) 00736 00737 if event.GetDirection(): 00738 self.prjParamSizer.Clear(True) 00739 self.paramSBox.SetLabel(_(" Enter parameters for %s projection ") % self.projdesc) 00740 self.pparam = dict() 00741 row = 0 00742 for paramgrp in self.parent.projections[self.parent.projpage.proj][1]: 00743 # get parameters 00744 id = wx.NewId() 00745 param = self.pparam[id] = { 'type' : self.parent.paramdesc[paramgrp[0]][0], 00746 'proj4': self.parent.paramdesc[paramgrp[0]][1], 00747 'desc' : self.parent.paramdesc[paramgrp[0]][2] } 00748 00749 # default values 00750 if param['type'] == 'bool': 00751 param['value'] = 0 00752 elif param['type'] == 'zone': 00753 param['value'] = 30 00754 param['desc'] += ' (1-60)' 00755 else: 00756 param['value'] = paramgrp[2] 00757 00758 label = wx.StaticText(parent = self.panel, id = wx.ID_ANY, label = param['desc'], 00759 style = wx.ALIGN_RIGHT | wx.ST_NO_AUTORESIZE) 00760 if param['type'] == 'bool': 00761 win = wx.Choice(parent = self.panel, id = id, size = (100,-1), 00762 choices = [_('No'), _('Yes')]) 00763 win.SetSelection(param['value']) 00764 win.Bind(wx.EVT_CHOICE, self.OnParamEntry) 00765 elif param['type'] == 'zone': 00766 win = wx.SpinCtrl(parent = self.panel, id = id, 00767 size = (100, -1), 00768 style = wx.SP_ARROW_KEYS | wx.SP_WRAP, 00769 min = 1, max = 60) 00770 win.SetValue(param['value']) 00771 win.Bind(wx.EVT_SPINCTRL, self.OnParamEntry) 00772 win.Bind(wx.EVT_TEXT, self.OnParamEntry) 00773 else: 00774 win = wx.TextCtrl(parent = self.panel, id = id, 00775 value = param['value'], 00776 size=(100, -1)) 00777 win.Bind(wx.EVT_TEXT, self.OnParamEntry) 00778 if paramgrp[1] == 'noask': 00779 win.Enable(False) 00780 00781 self.prjParamSizer.Add(item = label, pos = (row, 1), 00782 flag = wx.ALIGN_RIGHT | 00783 wx.ALIGN_CENTER_VERTICAL | 00784 wx.RIGHT, border = 5) 00785 self.prjParamSizer.Add(item = win, pos = (row, 2), 00786 flag = wx.ALIGN_LEFT | 00787 wx.ALIGN_CENTER_VERTICAL | 00788 wx.LEFT, border = 5) 00789 row += 1 00790 00791 self.panel.SetSize(self.panel.GetBestSize()) 00792 self.panel.Layout() 00793 self.Layout() 00794 self.Update() 00795 00796 if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled(): 00797 wx.FindWindowById(wx.ID_FORWARD).Enable() 00798 00799 event.Skip() 00800 00801 def SetVal(self, event): 00802 """!Set value""" 00803 if event.GetId() == self.radio1.GetId(): 00804 self.SetNext(self.parent.datumpage) 00805 self.parent.sumpage.SetPrev(self.parent.datumpage) 00806 elif event.GetId() == self.radio2.GetId(): 00807 self.SetNext(self.parent.ellipsepage) 00808 self.parent.sumpage.SetPrev(self.parent.ellipsepage) 00809 00810 class DatumPage(TitledPage): 00811 """!Wizard page for selecting datum (with associated ellipsoid) 00812 and datum transformation parameters (select coordinate system option) 00813 """ 00814 00815 def __init__(self, wizard, parent): 00816 TitledPage.__init__(self, wizard, _("Specify geodetic datum")) 00817 00818 self.parent = parent 00819 self.datum = '' 00820 self.datumdesc = '' 00821 self.ellipse = '' 00822 self.datumparams = '' 00823 self.proj4params = '' 00824 00825 # text input 00826 self.tdatum = self.MakeTextCtrl("", size = (200,-1)) 00827 00828 # search box 00829 self.searchb = wx.SearchCtrl(self, size = (200,-1), 00830 style = wx.TE_PROCESS_ENTER) 00831 00832 # create list control for datum/elipsoid list 00833 data = [] 00834 for key in self.parent.datums.keys(): 00835 data.append([key, self.parent.datums[key][0], self.parent.datums[key][1]]) 00836 self.datumlist = ItemList(self, 00837 data = data, 00838 columns = [_('Code'), _('Ellipsoid'), _('Description')]) 00839 self.datumlist.resizeLastColumn(10) 00840 00841 # layout 00842 self.sizer.AddGrowableCol(4) 00843 self.sizer.Add(item = self.MakeLabel(_("Datum code:")), 00844 flag = wx.ALIGN_LEFT | 00845 wx.ALIGN_CENTER_VERTICAL | 00846 wx.ALL, border = 5, pos = (1, 1)) 00847 self.sizer.Add(item = self.tdatum, 00848 flag = wx.ALIGN_LEFT | 00849 wx.ALIGN_CENTER_VERTICAL | 00850 wx.ALL, border = 5, pos = (1, 2)) 00851 00852 self.sizer.Add(item = self.MakeLabel(_("Search in description:")), 00853 flag = wx.ALIGN_LEFT | 00854 wx.ALIGN_CENTER_VERTICAL | 00855 wx.ALL, border = 5, pos = (2, 1)) 00856 self.sizer.Add(item = self.searchb, 00857 flag = wx.ALIGN_LEFT | 00858 wx.ALIGN_CENTER_VERTICAL | 00859 wx.ALL, border = 5, pos = (2, 2)) 00860 00861 self.sizer.AddGrowableRow(3) 00862 self.sizer.Add(item = self.datumlist, 00863 flag = wx.EXPAND | 00864 wx.ALIGN_LEFT | 00865 wx.ALL, border = 5, pos = (3, 1), span = (1, 4)) 00866 00867 # events 00868 self.datumlist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnDatumSelected) 00869 self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnDSearch) 00870 self.tdatum.Bind(wx.EVT_TEXT, self.OnDText) 00871 self.tdatum.Bind(wx.EVT_TEXT_ENTER, self.OnDText) 00872 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging) 00873 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 00874 00875 # do page layout 00876 # self.DoLayout() 00877 00878 def OnPageChanging(self, event): 00879 self.proj4params = '' 00880 proj = self.parent.projpage.p4proj 00881 00882 if event.GetDirection(): 00883 if self.datum not in self.parent.datums: 00884 event.Veto() 00885 else: 00886 # check for datum tranforms 00887 # proj4string = self.parent.CreateProj4String() + ' +datum=%s' % self.datum 00888 ret = RunCommand('g.proj', 00889 read = True, 00890 proj4 = '%s +datum=%s' % (proj, self.datum), 00891 datumtrans = '-1') 00892 if ret != '': 00893 dtrans = '' 00894 # open a dialog to select datum transform number 00895 dlg = SelectTransformDialog(self.parent.parent, transforms=ret) 00896 00897 if dlg.ShowModal() == wx.ID_OK: 00898 dtrans = dlg.GetTransform() 00899 if dtrans == '': 00900 dlg.Destroy() 00901 event.Veto() 00902 return 'Datum transform is required.' 00903 else: 00904 dlg.Destroy() 00905 event.Veto() 00906 return 'Datum transform is required.' 00907 00908 self.parent.datumtrans = dtrans 00909 00910 self.GetNext().SetPrev(self) 00911 self.parent.ellipsepage.ellipse = self.ellipse 00912 self.parent.ellipsepage.ellipseparams = self.parent.ellipsoids[self.ellipse][1] 00913 00914 def OnEnterPage(self,event): 00915 self.parent.datumtrans = None 00916 if event.GetDirection(): 00917 if len(self.datum) == 0: 00918 # disable 'next' button by default when entering from previous page 00919 wx.FindWindowById(wx.ID_FORWARD).Enable(False) 00920 else: 00921 wx.FindWindowById(wx.ID_FORWARD).Enable(True) 00922 00923 event.Skip() 00924 00925 def OnDText(self, event): 00926 """!Datum code changed""" 00927 self.datum = event.GetString() 00928 00929 nextButton = wx.FindWindowById(wx.ID_FORWARD) 00930 if len(self.datum) == 0 or self.datum not in self.parent.datums: 00931 nextButton.Enable(False) 00932 else: 00933 self.ellipse = self.parent.datums[self.datum][0] 00934 self.datumdesc = self.parent.datums[self.datum][1] 00935 self.datumparams = self.parent.datums[self.datum][2] 00936 try: 00937 self.datumparams.remove('dx=0.0') 00938 except: 00939 pass 00940 try: 00941 self.datumparams.remove('dy=0.0') 00942 except: 00943 pass 00944 try: 00945 self.datumparams.remove('dz=0.0') 00946 except: 00947 pass 00948 00949 nextButton.Enable(True) 00950 00951 self.Update() 00952 event.Skip() 00953 00954 def OnDSearch(self, event): 00955 """!Search geodetic datum by desc""" 00956 str = self.searchb.GetValue() 00957 try: 00958 self.datum, self.ellipsoid, self.datumdesc = self.datumlist.Search(index = [0,1,2], pattern = str) 00959 except: 00960 self.datum = self.datumdesc = self.ellipsoid = '' 00961 00962 event.Skip() 00963 00964 def OnDatumSelected(self, event): 00965 """!Datum selected""" 00966 index = event.m_itemIndex 00967 item = event.GetItem() 00968 00969 self.datum = self.datumlist.GetItem(index, 0).GetText() 00970 self.tdatum.SetValue(self.datum) 00971 00972 event.Skip() 00973 00974 class EllipsePage(TitledPage): 00975 """!Wizard page for selecting ellipsoid (select coordinate system option)""" 00976 00977 def __init__(self, wizard, parent): 00978 TitledPage.__init__(self, wizard, _("Specify ellipsoid")) 00979 00980 self.parent = parent 00981 00982 self.ellipse = '' 00983 self.ellipsedesc = '' 00984 self.ellipseparams = '' 00985 self.proj4params = '' 00986 00987 # text input 00988 self.tellipse = self.MakeTextCtrl("", size = (200,-1)) 00989 00990 # search box 00991 self.searchb = wx.SearchCtrl(self, size = (200,-1), 00992 style = wx.TE_PROCESS_ENTER) 00993 00994 # create list control for ellipse list 00995 data = [] 00996 # extract code, desc 00997 for key in self.parent.ellipsoids.keys(): 00998 data.append([key, self.parent.ellipsoids[key][0]]) 00999 01000 self.ellipselist = ItemList(self, data = data, 01001 columns = [_('Code'), _('Description')]) 01002 self.ellipselist.resizeLastColumn(30) 01003 01004 # layout 01005 self.sizer.AddGrowableCol(4) 01006 self.sizer.Add(item = self.MakeLabel(_("Ellipsoid code:")), 01007 flag = wx.ALIGN_RIGHT | 01008 wx.ALIGN_CENTER_VERTICAL | 01009 wx.ALL, border = 5, pos = (1, 1)) 01010 self.sizer.Add(item = self.tellipse, 01011 flag = wx.ALIGN_LEFT | 01012 wx.ALIGN_CENTER_VERTICAL | 01013 wx.ALL, border = 5, pos = (1, 2)) 01014 self.sizer.Add(item = self.MakeLabel(_("Search in description:")), 01015 flag = wx.ALIGN_RIGHT | 01016 wx.ALIGN_CENTER_VERTICAL | 01017 wx.ALL, border = 5, pos = (2, 1)) 01018 self.sizer.Add(item = self.searchb, 01019 flag = wx.ALIGN_LEFT | 01020 wx.ALIGN_CENTER_VERTICAL | 01021 wx.ALL, border = 5, pos = (2, 2)) 01022 01023 self.sizer.AddGrowableRow(3) 01024 self.sizer.Add(item = self.ellipselist, 01025 flag = wx.EXPAND | 01026 wx.ALIGN_LEFT | 01027 wx.ALL, border = 5, pos = (3, 1), span = (1, 4)) 01028 01029 # events 01030 self.ellipselist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected) 01031 self.tellipse.Bind(wx.EVT_TEXT, self.OnText) 01032 self.tellipse.Bind(wx.EVT_TEXT_ENTER, self.OnText) 01033 self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnSearch) 01034 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 01035 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging) 01036 01037 def OnEnterPage(self,event): 01038 if len(self.ellipse) == 0: 01039 # disable 'next' button by default 01040 wx.FindWindowById(wx.ID_FORWARD).Enable(False) 01041 else: 01042 wx.FindWindowById(wx.ID_FORWARD).Enable(True) 01043 01044 event.Skip() 01045 01046 def OnPageChanging(self, event): 01047 if event.GetDirection() and self.ellipse not in self.parent.ellipsoids: 01048 event.Veto() 01049 01050 self.proj4params = '' 01051 self.GetNext().SetPrev(self) 01052 self.parent.datumpage.datumparams = '' 01053 # self.GetNext().SetPrev(self) (???) 01054 01055 def OnText(self, event): 01056 """!Ellipspoid code changed""" 01057 self.ellipse = event.GetString() 01058 nextButton = wx.FindWindowById(wx.ID_FORWARD) 01059 if len(self.ellipse) == 0 or self.ellipse not in self.parent.ellipsoids: 01060 nextButton.Enable(False) 01061 self.ellipsedesc = '' 01062 self.ellipseparams = '' 01063 self.proj4params = '' 01064 elif self.ellipse in self.parent.ellipsoids: 01065 self.ellipsedesc = self.parent.ellipsoids[self.ellipse][0] 01066 self.ellipseparams = self.parent.ellipsoids[self.ellipse][1] 01067 nextButton.Enable(True) 01068 01069 def OnSearch(self, event): 01070 """!Search ellipsoid by desc""" 01071 try: 01072 self.ellipse, self.ellipsedesc = \ 01073 self.ellipselist.Search(index=[0,1], pattern=event.GetString()) 01074 self.ellipseparams = self.parent.ellipsoids[self.ellipse][1] 01075 except: 01076 self.ellipse = self.ellipsedesc = self.ellipseparams = '' 01077 01078 event.Skip() 01079 01080 def OnItemSelected(self,event): 01081 """!Ellipsoid selected""" 01082 index = event.m_itemIndex 01083 item = event.GetItem() 01084 01085 self.ellipse = self.ellipselist.GetItem(index, 0).GetText() 01086 self.tellipse.SetValue(self.ellipse) 01087 01088 event.Skip() 01089 01090 class GeoreferencedFilePage(TitledPage): 01091 """!Wizard page for selecting georeferenced file to use 01092 for setting coordinate system parameters""" 01093 01094 def __init__(self, wizard, parent): 01095 TitledPage.__init__(self, wizard, _("Select georeferenced file")) 01096 01097 self.georeffile = '' 01098 01099 # create controls 01100 self.lfile= self.MakeLabel(_("Georeferenced file:")) 01101 self.tfile = self.MakeTextCtrl(size = (300,-1)) 01102 self.bbrowse = self.MakeButton(_("Browse")) 01103 01104 # do layout 01105 self.sizer.AddGrowableCol(3) 01106 self.sizer.Add(item = self.lfile, flag = wx.ALIGN_LEFT | 01107 wx.ALIGN_CENTRE_VERTICAL | 01108 wx.ALL, border = 5, pos = (1, 1)) 01109 self.sizer.Add(item = self.tfile, flag = wx.ALIGN_LEFT | 01110 wx.ALIGN_CENTRE_VERTICAL | 01111 wx.ALL, border = 5, pos = (1, 2)) 01112 self.sizer.Add(item = self.bbrowse, flag = wx.ALIGN_LEFT | 01113 wx.ALL, border = 5, pos = (1, 3)) 01114 01115 self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse) 01116 self.tfile.Bind(wx.EVT_TEXT, self.OnText) 01117 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging) 01118 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 01119 01120 # do page layout 01121 # self.DoLayout() 01122 01123 def OnEnterPage(self, event): 01124 if len(self.georeffile) == 0: 01125 # disable 'next' button by default 01126 wx.FindWindowById(wx.ID_FORWARD).Enable(False) 01127 else: 01128 wx.FindWindowById(wx.ID_FORWARD).Enable(True) 01129 01130 event.Skip() 01131 01132 def OnPageChanging(self, event): 01133 if event.GetDirection() and not os.path.isfile(self.georeffile): 01134 event.Veto() 01135 self.GetNext().SetPrev(self) 01136 01137 event.Skip() 01138 01139 def OnText(self, event): 01140 """!File changed""" 01141 self.georeffile = event.GetString() 01142 nextButton = wx.FindWindowById(wx.ID_FORWARD) 01143 if len(self.georeffile) > 0 and os.path.isfile(self.georeffile): 01144 if not nextButton.IsEnabled(): 01145 nextButton.Enable(True) 01146 else: 01147 if nextButton.IsEnabled(): 01148 nextButton.Enable(False) 01149 01150 event.Skip() 01151 01152 def OnBrowse(self, event): 01153 """!Choose file""" 01154 dlg = wx.FileDialog(self, 01155 _("Select georeferenced file"), 01156 os.getcwd(), "", "*.*", wx.OPEN) 01157 if dlg.ShowModal() == wx.ID_OK: 01158 path = dlg.GetPath() 01159 self.tfile.SetValue(path) 01160 dlg.Destroy() 01161 01162 event.Skip() 01163 01164 class WKTPage(TitledPage): 01165 """!Wizard page for selecting WKT file to use 01166 for setting coordinate system parameters""" 01167 01168 def __init__(self, wizard, parent): 01169 TitledPage.__init__(self, wizard, _("Select WKT file")) 01170 01171 self.wktfile = '' 01172 01173 # create controls 01174 self.lfile= self.MakeLabel(_("WKT file:")) 01175 self.tfile = self.MakeTextCtrl(size = (300,-1)) 01176 self.bbrowse = self.MakeButton(_("Browse")) 01177 01178 # do layout 01179 self.sizer.AddGrowableCol(3) 01180 self.sizer.Add(item = self.lfile, flag = wx.ALIGN_LEFT | 01181 wx.ALIGN_CENTRE_VERTICAL | 01182 wx.ALL, border = 5, pos = (1, 1)) 01183 self.sizer.Add(item = self.tfile, flag = wx.ALIGN_LEFT | 01184 wx.ALIGN_CENTRE_VERTICAL | 01185 wx.ALL, border = 5, pos = (1, 2)) 01186 self.sizer.Add(item = self.bbrowse, flag = wx.ALIGN_LEFT | 01187 wx.ALL, border = 5, pos = (1, 3)) 01188 01189 self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse) 01190 self.tfile.Bind(wx.EVT_TEXT, self.OnText) 01191 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging) 01192 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 01193 01194 def OnEnterPage(self, event): 01195 if len(self.wktfile) == 0: 01196 # disable 'next' button by default 01197 wx.FindWindowById(wx.ID_FORWARD).Enable(False) 01198 else: 01199 wx.FindWindowById(wx.ID_FORWARD).Enable(True) 01200 01201 event.Skip() 01202 01203 def OnPageChanging(self, event): 01204 if event.GetDirection() and not os.path.isfile(self.wktfile): 01205 event.Veto() 01206 self.GetNext().SetPrev(self) 01207 01208 event.Skip() 01209 01210 def OnText(self, event): 01211 """!File changed""" 01212 self.wktfile = event.GetString() 01213 nextButton = wx.FindWindowById(wx.ID_FORWARD) 01214 if len(self.wktfile) > 0 and os.path.isfile(self.wktfile): 01215 if not nextButton.IsEnabled(): 01216 nextButton.Enable(True) 01217 else: 01218 if nextButton.IsEnabled(): 01219 nextButton.Enable(False) 01220 01221 event.Skip() 01222 01223 def OnBrowse(self, event): 01224 """!Choose file""" 01225 dlg = wx.FileDialog(self, 01226 _("Select WKT file"), 01227 os.getcwd(), "", "*.*", wx.OPEN) 01228 if dlg.ShowModal() == wx.ID_OK: 01229 path = dlg.GetPath() 01230 self.tfile.SetValue(path) 01231 dlg.Destroy() 01232 01233 event.Skip() 01234 01235 class EPSGPage(TitledPage): 01236 """!Wizard page for selecting EPSG code for 01237 setting coordinate system parameters""" 01238 01239 def __init__(self, wizard, parent): 01240 TitledPage.__init__(self, wizard, _("Choose EPSG Code")) 01241 self.parent = parent 01242 self.epsgCodeDict = {} 01243 self.epsgcode = None 01244 self.epsgdesc = '' 01245 self.epsgparams = '' 01246 01247 # labels 01248 self.lfile = self.MakeLabel(_("Path to the EPSG-codes file:"), 01249 style = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) 01250 self.lcode = self.MakeLabel(_("EPSG code:"), 01251 style = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) 01252 # text input 01253 epsgdir = utils.PathJoin(os.environ["GRASS_PROJSHARE"], 'epsg') 01254 self.tfile = self.MakeTextCtrl(text = epsgdir, size = (200,-1), 01255 style = wx.TE_PROCESS_ENTER) 01256 self.tcode = self.MakeTextCtrl(size = (200,-1)) 01257 01258 # buttons 01259 self.bbrowse = self.MakeButton(_("Browse")) 01260 01261 # search box 01262 self.searchb = wx.SearchCtrl(self, size = (200,-1), 01263 style = wx.TE_PROCESS_ENTER) 01264 01265 self.epsglist = ItemList(self, data = None, 01266 columns = [_('Code'), _('Description'), _('Parameters')]) 01267 01268 # layout 01269 self.sizer.AddGrowableCol(3) 01270 self.sizer.Add(item = self.lfile, 01271 flag = wx.ALIGN_LEFT | 01272 wx.ALIGN_CENTER_VERTICAL | 01273 wx.ALL, border = 5, pos = (1, 1), span = (1, 2)) 01274 self.sizer.Add(item = self.tfile, 01275 flag = wx.ALIGN_LEFT | 01276 wx.ALIGN_CENTER_VERTICAL | 01277 wx.ALL, border = 5, pos = (1, 3)) 01278 self.sizer.Add(item = self.bbrowse, 01279 flag = wx.ALIGN_LEFT | 01280 wx.ALIGN_CENTER_VERTICAL | 01281 wx.ALL, border = 5, pos = (1, 4)) 01282 self.sizer.Add(item = self.lcode, 01283 flag = wx.ALIGN_LEFT | 01284 wx.ALIGN_CENTER_VERTICAL | 01285 wx.ALL, border = 5, pos = (2, 1), span = (1, 2)) 01286 self.sizer.Add(item = self.tcode, 01287 flag = wx.ALIGN_LEFT | 01288 wx.ALIGN_CENTER_VERTICAL | 01289 wx.ALL, border = 5, pos = (2, 3)) 01290 self.sizer.Add(item = self.searchb, 01291 flag = wx.ALIGN_LEFT | 01292 wx.ALIGN_CENTER_VERTICAL | 01293 wx.ALL, border = 5, pos = (3, 3)) 01294 01295 self.sizer.AddGrowableRow(4) 01296 self.sizer.Add(item = self.epsglist, 01297 flag = wx.ALIGN_LEFT | wx.EXPAND, pos = (4, 1), 01298 span = (1, 4)) 01299 01300 # events 01301 self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse) 01302 self.tfile.Bind(wx.EVT_TEXT_ENTER, self.OnBrowseCodes) 01303 self.tcode.Bind(wx.EVT_TEXT, self.OnText) 01304 self.tcode.Bind(wx.EVT_TEXT_ENTER, self.OnText) 01305 self.epsglist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected) 01306 self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnSearch) 01307 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging) 01308 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 01309 01310 def OnEnterPage(self, event): 01311 self.parent.datumtrans = None 01312 if event.GetDirection(): 01313 if not self.epsgcode: 01314 # disable 'next' button by default 01315 wx.FindWindowById(wx.ID_FORWARD).Enable(False) 01316 else: 01317 wx.FindWindowById(wx.ID_FORWARD).Enable(True) 01318 01319 # load default epsg database file 01320 self.OnBrowseCodes(None) 01321 01322 event.Skip() 01323 01324 def OnPageChanging(self, event): 01325 if event.GetDirection(): 01326 if not self.epsgcode: 01327 event.Veto() 01328 return 01329 else: 01330 # check for datum transforms 01331 ret = RunCommand('g.proj', 01332 read = True, 01333 epsg = self.epsgcode, 01334 datumtrans = '-1') 01335 01336 if ret != '': 01337 dtrans = '' 01338 # open a dialog to select datum transform number 01339 dlg = SelectTransformDialog(self.parent.parent, transforms = ret) 01340 01341 if dlg.ShowModal() == wx.ID_OK: 01342 dtrans = dlg.GetTransform() 01343 if dtrans == '': 01344 dlg.Destroy() 01345 event.Veto() 01346 return 'Datum transform is required.' 01347 else: 01348 dlg.Destroy() 01349 event.Veto() 01350 return 'Datum transform is required.' 01351 01352 self.parent.datumtrans = dtrans 01353 self.GetNext().SetPrev(self) 01354 01355 def OnText(self, event): 01356 self.epsgcode = event.GetString() 01357 try: 01358 self.epsgcode = int(self.epsgcode) 01359 except: 01360 self.epsgcode = None 01361 01362 nextButton = wx.FindWindowById(wx.ID_FORWARD) 01363 01364 if self.epsgcode and self.epsgcode in self.epsgCodeDict.keys(): 01365 self.epsgdesc = self.epsgCodeDict[self.epsgcode][0] 01366 self.epsgparams = self.epsgCodeDict[self.epsgcode][1] 01367 if not nextButton.IsEnabled(): 01368 nextButton.Enable(True) 01369 else: 01370 self.epsgcode = None # not found 01371 if nextButton.IsEnabled(): 01372 nextButton.Enable(False) 01373 self.epsgdesc = self.epsgparams = '' 01374 01375 def OnSearch(self, event): 01376 value = self.searchb.GetValue() 01377 01378 if value == '': 01379 self.epsgcode = None 01380 self.epsgdesc = self.epsgparams = '' 01381 self.tcode.SetValue('') 01382 self.searchb.SetValue('') 01383 self.OnBrowseCodes(None) 01384 else: 01385 try: 01386 self.epsgcode, self.epsgdesc, self.epsgparams = \ 01387 self.epsglist.Search(index=[0,1,2], pattern=value) 01388 except (IndexError, ValueError): # -> no item found 01389 self.epsgcode = None 01390 self.epsgdesc = self.epsgparams = '' 01391 self.tcode.SetValue('') 01392 self.searchb.SetValue('') 01393 01394 event.Skip() 01395 01396 def OnBrowse(self, event): 01397 """!Define path for EPSG code file""" 01398 path = os.path.dirname(self.tfile.GetValue()) 01399 if not path: 01400 path = os.getcwd() 01401 01402 dlg = wx.FileDialog(parent = self, message = _("Choose EPSG codes file"), 01403 defaultDir = path, defaultFile = "", wildcard = "*", style = wx.OPEN) 01404 01405 if dlg.ShowModal() == wx.ID_OK: 01406 path = dlg.GetPath() 01407 self.tfile.SetValue(path) 01408 self.OnBrowseCodes(None) 01409 01410 dlg.Destroy() 01411 01412 event.Skip() 01413 01414 def OnItemSelected(self, event): 01415 """!EPSG code selected from the list""" 01416 index = event.m_itemIndex 01417 item = event.GetItem() 01418 01419 self.epsgcode = int(self.epsglist.GetItem(index, 0).GetText()) 01420 self.epsgdesc = self.epsglist.GetItem(index, 1).GetText() 01421 self.tcode.SetValue(str(self.epsgcode)) 01422 01423 event.Skip() 01424 01425 def OnBrowseCodes(self, event, search = None): 01426 """!Browse EPSG codes""" 01427 self.epsgCodeDict = utils.ReadEpsgCodes(self.tfile.GetValue()) 01428 01429 if type(self.epsgCodeDict) != dict: 01430 wx.MessageBox(parent = self, 01431 message = _("Unable to read EPGS codes: %s") % self.epsgCodeDict, 01432 caption = _("Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE) 01433 self.epsglist.Populate(list(), update = True) 01434 return 01435 01436 data = list() 01437 for code, val in self.epsgCodeDict.iteritems(): 01438 if code is not None: 01439 data.append((code, val[0], val[1])) 01440 01441 self.epsglist.Populate(data, update = True) 01442 01443 class CustomPage(TitledPage): 01444 """!Wizard page for entering custom PROJ.4 string 01445 for setting coordinate system parameters""" 01446 01447 def __init__(self, wizard, parent): 01448 TitledPage.__init__(self, wizard, 01449 _("Choose method of specifying georeferencing parameters")) 01450 global coordsys 01451 self.customstring = '' 01452 self.parent = parent 01453 01454 # widgets 01455 self.text_proj4string = self.MakeTextCtrl(size = (400, 200), 01456 style = wx.TE_MULTILINE) 01457 self.label_proj4string = self.MakeLabel(_("Enter PROJ.4 parameters string:")) 01458 01459 # layout 01460 self.sizer.AddGrowableCol(2) 01461 self.sizer.Add(self.label_proj4string, 01462 flag = wx.ALIGN_LEFT | wx.ALL, 01463 border = 5, pos = (1, 1)) 01464 self.sizer.AddGrowableRow(2) 01465 self.sizer.Add(self.text_proj4string, 01466 flag = wx.ALIGN_LEFT | wx.ALL | wx.EXPAND, 01467 border = 5, pos = (2, 1), span = (1, 2)) 01468 01469 self.text_proj4string.Bind(wx.EVT_TEXT, self.GetProjstring) 01470 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging) 01471 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 01472 01473 def OnEnterPage(self, event): 01474 if len(self.customstring) == 0: 01475 # disable 'next' button by default 01476 wx.FindWindowById(wx.ID_FORWARD).Enable(False) 01477 else: 01478 wx.FindWindowById(wx.ID_FORWARD).Enable(True) 01479 01480 def OnPageChanging(self, event): 01481 if event.GetDirection(): 01482 # check for datum tranforms 01483 ret, out, err = RunCommand('g.proj', 01484 read = True, getErrorMsg = True, 01485 proj4 = self.customstring, 01486 datumtrans = '-1') 01487 if ret != 0: 01488 wx.MessageBox(parent = self, 01489 message = err, 01490 caption = _("Error"), 01491 style = wx.OK | wx.ICON_ERROR | wx.CENTRE) 01492 event.Veto() 01493 return 01494 01495 if out: 01496 dtrans = '' 01497 # open a dialog to select datum transform number 01498 dlg = SelectTransformDialog(self.parent.parent, transforms = out) 01499 01500 if dlg.ShowModal() == wx.ID_OK: 01501 dtrans = dlg.GetTransform() 01502 if len(dtrans) == 0: 01503 dlg.Destroy() 01504 event.Veto() 01505 return _('Datum transform is required.') 01506 else: 01507 dlg.Destroy() 01508 event.Veto() 01509 return _('Datum transform is required.') 01510 01511 self.parent.datumtrans = dtrans 01512 01513 self.GetNext().SetPrev(self) 01514 01515 def GetProjstring(self, event): 01516 """!Change proj string""" 01517 # TODO: check PROJ.4 syntax 01518 self.customstring = event.GetString() 01519 nextButton = wx.FindWindowById(wx.ID_FORWARD) 01520 if len(self.customstring) == 0: 01521 if nextButton.IsEnabled(): 01522 nextButton.Enable(False) 01523 else: 01524 if not nextButton.IsEnabled(): 01525 nextButton.Enable() 01526 01527 class SummaryPage(TitledPage): 01528 """!Shows summary result of choosing coordinate system parameters 01529 prior to creating location""" 01530 def __init__(self, wizard, parent): 01531 TitledPage.__init__(self, wizard, _("Summary")) 01532 self.parent = parent 01533 01534 self.panelTitle = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY) 01535 self.panelProj4string = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY) 01536 self.panelProj = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY) 01537 01538 # labels 01539 self.ldatabase = self.MakeLabel() 01540 self.llocation = self.MakeLabel() 01541 self.llocTitle = self.MakeLabel(parent = self.panelTitle) 01542 self.lprojection = self.MakeLabel(parent = self.panelProj) 01543 self.lproj4string = self.MakeLabel(parent = self.panelProj4string) 01544 01545 self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage) 01546 01547 # do sub-page layout 01548 self._doLayout() 01549 01550 def _doLayout(self): 01551 """!Do page layout""" 01552 self.sizer.AddGrowableCol(1) 01553 self.sizer.AddGrowableRow(3, 1) 01554 self.sizer.AddGrowableRow(4, 1) 01555 self.sizer.AddGrowableRow(5, 5) 01556 01557 titleSizer = wx.BoxSizer(wx.VERTICAL) 01558 titleSizer.Add(item = self.llocTitle, proportion = 1, 01559 flag = wx.EXPAND | wx.ALL, border = 5) 01560 self.panelTitle.SetSizer(titleSizer) 01561 01562 projSizer = wx.BoxSizer(wx.VERTICAL) 01563 projSizer.Add(item = self.lprojection, proportion = 1, 01564 flag = wx.EXPAND | wx.ALL, border = 5) 01565 self.panelProj.SetSizer(projSizer) 01566 01567 proj4stringSizer = wx.BoxSizer(wx.VERTICAL) 01568 proj4stringSizer.Add(item = self.lproj4string, proportion = 1, 01569 flag = wx.EXPAND | wx.ALL, border = 5) 01570 self.panelProj4string.SetSizer(proj4stringSizer) 01571 01572 self.panelProj4string.SetupScrolling() 01573 self.panelProj.SetupScrolling(scroll_y = False) 01574 self.panelTitle.SetupScrolling(scroll_y = False) 01575 01576 self.sizer.Add(item = self.MakeLabel(_("GRASS Database:")), 01577 flag = wx.ALIGN_LEFT | wx.ALL, 01578 border = 5, pos = (1, 0)) 01579 self.sizer.Add(item = self.ldatabase, 01580 flag = wx.ALIGN_LEFT | wx.ALL, 01581 border = 5, pos = (1, 1)) 01582 self.sizer.Add(item = self.MakeLabel(_("Location Name:")), 01583 flag = wx.ALIGN_LEFT | wx.ALL, 01584 border = 5, pos = (2, 0)) 01585 self.sizer.Add(item = self.llocation, 01586 flag = wx.ALIGN_LEFT | wx.ALL, 01587 border = 5, pos = (2, 1)) 01588 self.sizer.Add(item = self.MakeLabel(_("Location Title:")), 01589 flag = wx.ALIGN_LEFT | wx.ALL, 01590 border = 5, pos = (3, 0)) 01591 self.sizer.Add(item = self.panelTitle, 01592 flag = wx.ALIGN_LEFT | wx.ALL | wx.EXPAND, 01593 border = 0, pos = (3, 1)) 01594 self.sizer.Add(item = self.MakeLabel(_("Projection:")), 01595 flag = wx.ALIGN_LEFT | wx.ALL, 01596 border = 5, pos = (4, 0)) 01597 self.sizer.Add(item = self.panelProj, 01598 flag = wx.ALIGN_LEFT | wx.ALL | wx.EXPAND, 01599 border = 0, pos = (4, 1)) 01600 self.sizer.Add(item = self.MakeLabel(_("PROJ.4 definition:")), 01601 flag = wx.ALIGN_LEFT | wx.ALL, 01602 border = 5, pos = (5, 0)) 01603 self.sizer.Add(item = self.panelProj4string, 01604 flag = wx.ALIGN_LEFT | wx.ALL | wx.EXPAND, 01605 border = 0, pos = (5, 1)) 01606 01607 def OnEnterPage(self, event): 01608 """!Insert values into text controls for summary of location 01609 creation options 01610 """ 01611 database = self.parent.startpage.grassdatabase 01612 location = self.parent.startpage.location 01613 proj4string = self.parent.CreateProj4String() 01614 epsgcode = self.parent.epsgpage.epsgcode 01615 dtrans = self.parent.datumtrans 01616 01617 global coordsys 01618 if coordsys in ('proj', 'epsg'): 01619 if coordsys == 'proj': 01620 ret, projlabel, err = RunCommand('g.proj', 01621 flags = 'jf', 01622 proj4 = proj4string, 01623 datumtrans = dtrans, 01624 location = location, 01625 getErrorMsg = True, 01626 read = True) 01627 elif coordsys == 'epsg': 01628 ret, projlabel, err = RunCommand('g.proj', 01629 flags = 'jf', 01630 epsg = epsgcode, 01631 datumtrans = dtrans, 01632 location = location, 01633 getErrorMsg = True, 01634 read = True) 01635 01636 finishButton = wx.FindWindowById(wx.ID_FORWARD) 01637 if ret == 0: 01638 self.lproj4string.SetLabel(projlabel.replace(' ', os.linesep)) 01639 finishButton.Enable(True) 01640 else: 01641 GError(err, parent = self) 01642 self.lproj4string.SetLabel('') 01643 finishButton.Enable(False) 01644 01645 projdesc = self.parent.projpage.projdesc 01646 ellipsedesc = self.parent.ellipsepage.ellipsedesc 01647 datumdesc = self.parent.datumpage.datumdesc 01648 self.ldatabase.SetLabel(database) 01649 self.llocation.SetLabel(location) 01650 self.llocTitle.SetLabel(self.parent.startpage.locTitle) 01651 01652 label = '' 01653 if coordsys == 'epsg': 01654 label = 'EPSG code %s (%s)' % (self.parent.epsgpage.epsgcode, self.parent.epsgpage.epsgdesc) 01655 elif coordsys == 'file': 01656 label = 'matches file %s' % self.parent.filepage.georeffile 01657 self.lproj4string.SetLabel("") 01658 elif coordsys == 'wkt': 01659 label = 'matches file %s' % self.parent.wktpage.wktfile 01660 self.lproj4string.SetLabel("") 01661 elif coordsys == 'proj': 01662 label = ('%s, %s %s' % (projdesc, datumdesc, ellipsedesc)) 01663 elif coordsys == 'xy': 01664 label = ('XY coordinate system (not projected).') 01665 self.lproj4string.SetLabel("") 01666 elif coordsys == 'custom': 01667 label = _("custom") 01668 self.lproj4string.SetLabel(('%s' % self.parent.custompage.customstring.replace(' ', os.linesep))) 01669 self.lprojection.SetLabel(label) 01670 01671 def OnFinish(self, event): 01672 dlg = wx.MessageDialog(parent = self.wizard, 01673 message = _("Do you want to create GRASS location <%s>?") % location, 01674 caption = _("Create new location?"), 01675 style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION) 01676 01677 if dlg.ShowModal() == wx.ID_NO: 01678 dlg.Destroy() 01679 event.Veto() 01680 else: 01681 dlg.Destroy() 01682 event.Skip() 01683 01684 class LocationWizard(wx.Object): 01685 """!Start wizard here and finish wizard here 01686 """ 01687 def __init__(self, parent, grassdatabase): 01688 self.__cleanUp() 01689 01690 global coordsys 01691 self.parent = parent 01692 01693 # 01694 # define wizard image 01695 # 01696 imagePath = os.path.join(globalvar.ETCIMGDIR, "loc_wizard_qgis.png") 01697 wizbmp = wx.Image(imagePath, wx.BITMAP_TYPE_PNG) 01698 wizbmp = wizbmp.ConvertToBitmap() 01699 01700 # 01701 # get georeferencing information from tables in $GISBASE/etc 01702 # 01703 self.__readData() 01704 01705 # 01706 # datum transform number and list of datum transforms 01707 # 01708 self.datumtrans = None 01709 self.proj4string = '' 01710 01711 # 01712 # define wizard pages 01713 # 01714 self.wizard = wiz.Wizard(parent, id = wx.ID_ANY, title = _("Define new GRASS Location"), 01715 bitmap = wizbmp, style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER) 01716 self.startpage = DatabasePage(self.wizard, self, grassdatabase) 01717 self.csystemspage = CoordinateSystemPage(self.wizard, self) 01718 self.projpage = ProjectionsPage(self.wizard, self) 01719 self.datumpage = DatumPage(self.wizard, self) 01720 self.paramspage = ProjParamsPage(self.wizard,self) 01721 self.epsgpage = EPSGPage(self.wizard, self) 01722 self.filepage = GeoreferencedFilePage(self.wizard, self) 01723 self.wktpage = WKTPage(self.wizard, self) 01724 self.ellipsepage = EllipsePage(self.wizard, self) 01725 self.custompage = CustomPage(self.wizard, self) 01726 self.sumpage = SummaryPage(self.wizard, self) 01727 01728 # 01729 # set the initial order of the pages 01730 # (should follow the epsg line) 01731 # 01732 self.startpage.SetNext(self.csystemspage) 01733 01734 self.csystemspage.SetPrev(self.startpage) 01735 self.csystemspage.SetNext(self.sumpage) 01736 01737 self.projpage.SetPrev(self.csystemspage) 01738 self.projpage.SetNext(self.paramspage) 01739 01740 self.paramspage.SetPrev(self.projpage) 01741 self.paramspage.SetNext(self.datumpage) 01742 01743 self.datumpage.SetPrev(self.paramspage) 01744 self.datumpage.SetNext(self.sumpage) 01745 01746 self.ellipsepage.SetPrev(self.paramspage) 01747 self.ellipsepage.SetNext(self.sumpage) 01748 01749 self.epsgpage.SetPrev(self.csystemspage) 01750 self.epsgpage.SetNext(self.sumpage) 01751 01752 self.filepage.SetPrev(self.csystemspage) 01753 self.filepage.SetNext(self.sumpage) 01754 01755 self.wktpage.SetPrev(self.csystemspage) 01756 self.wktpage.SetNext(self.sumpage) 01757 01758 self.custompage.SetPrev(self.csystemspage) 01759 self.custompage.SetNext(self.sumpage) 01760 01761 self.sumpage.SetPrev(self.csystemspage) 01762 01763 # 01764 # do pages layout 01765 # 01766 self.startpage.DoLayout() 01767 self.csystemspage.DoLayout() 01768 self.projpage.DoLayout() 01769 self.datumpage.DoLayout() 01770 self.paramspage.DoLayout() 01771 self.epsgpage.DoLayout() 01772 self.filepage.DoLayout() 01773 self.wktpage.DoLayout() 01774 self.ellipsepage.DoLayout() 01775 self.custompage.DoLayout() 01776 self.sumpage.DoLayout() 01777 self.wizard.FitToPage(self.datumpage) 01778 size = self.wizard.GetPageSize() 01779 self.wizard.SetPageSize((size[0], size[1] + 75)) 01780 01781 # new location created? 01782 self.location = None 01783 success = False 01784 01785 # location created in different GIS database? 01786 self.altdb = False 01787 01788 # 01789 # run wizard... 01790 # 01791 if self.wizard.RunWizard(self.startpage): 01792 msg = self.OnWizFinished() 01793 if not msg: 01794 self.wizard.Destroy() 01795 self.location = self.startpage.location 01796 01797 if self.altdb == False: 01798 dlg = wx.MessageDialog(parent = self.parent, 01799 message = _("Do you want to set the default " 01800 "region extents and resolution now?"), 01801 caption = _("Location <%s> created") % self.location, 01802 style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) 01803 dlg.CenterOnScreen() 01804 if dlg.ShowModal() == wx.ID_YES: 01805 dlg.Destroy() 01806 defineRegion = RegionDef(self.parent, location = self.location) 01807 defineRegion.CenterOnScreen() 01808 defineRegion.Show() 01809 else: 01810 dlg.Destroy() 01811 else: # -> error 01812 self.wizard.Destroy() 01813 GError(parent = self.parent, 01814 message = "%s" % _("Unable to create new location. " 01815 "Location <%(loc)s> not created.\n\n" 01816 "Details: %(err)s") % \ 01817 { 'loc' : self.startpage.location, 01818 'err' : msg }) 01819 else: # -> canceled 01820 self.wizard.Destroy() 01821 GMessage(parent = self.parent, 01822 message = _("Location wizard canceled. " 01823 "Location not created.")) 01824 01825 self.__cleanUp() 01826 01827 def __cleanUp(self): 01828 global coordsys 01829 global north 01830 global south 01831 global east 01832 global west 01833 global resolution 01834 global wizerror 01835 global translist 01836 01837 coordsys = None 01838 north = None 01839 south = None 01840 east = None 01841 west = None 01842 resolution = None 01843 transformlist = list() 01844 01845 def __readData(self): 01846 """!Get georeferencing information from tables in $GISBASE/etc""" 01847 01848 # read projection and parameters 01849 f = open(os.path.join(globalvar.ETCDIR, "proj-parms.table"), "r") 01850 self.projections = {} 01851 self.projdesc = {} 01852 for line in f.readlines(): 01853 line = line.strip() 01854 try: 01855 proj, projdesc, params = line.split(':') 01856 paramslist = params.split(';') 01857 plist = [] 01858 for p in paramslist: 01859 if p == '': continue 01860 p1, pdefault = p.split(',') 01861 pterm, pask = p1.split('=') 01862 p = [pterm.strip(), pask.strip(), pdefault.strip()] 01863 plist.append(p) 01864 self.projections[proj.lower().strip()] = (projdesc.strip(), plist) 01865 self.projdesc[proj.lower().strip()] = projdesc.strip() 01866 except: 01867 continue 01868 f.close() 01869 01870 # read datum definitions 01871 f = open(os.path.join(globalvar.ETCDIR, "datum.table"), "r") 01872 self.datums = {} 01873 paramslist = [] 01874 for line in f.readlines(): 01875 line = line.expandtabs(1) 01876 line = line.strip() 01877 if line == '' or line[0] == "#": 01878 continue 01879 datum, info = line.split(" ", 1) 01880 info = info.strip() 01881 datumdesc, params = info.split(" ", 1) 01882 datumdesc = datumdesc.strip('"') 01883 paramlist = params.split() 01884 ellipsoid = paramlist.pop(0) 01885 self.datums[datum] = (ellipsoid, datumdesc.replace('_', ' '), paramlist) 01886 f.close() 01887 01888 # read ellipsiod definitions 01889 f = open(os.path.join(globalvar.ETCDIR, "ellipse.table"), "r") 01890 self.ellipsoids = {} 01891 for line in f.readlines(): 01892 line = line.expandtabs(1) 01893 line = line.strip() 01894 if line == '' or line[0] == "#": 01895 continue 01896 ellipse, rest = line.split(" ", 1) 01897 rest = rest.strip('" ') 01898 desc, params = rest.split('"', 1) 01899 desc = desc.strip('" ') 01900 paramslist = params.split() 01901 self.ellipsoids[ellipse] = (desc, paramslist) 01902 f.close() 01903 01904 # read projection parameter description and parsing table 01905 f = open(os.path.join(globalvar.ETCDIR, "proj-desc.table"), "r") 01906 self.paramdesc = {} 01907 for line in f.readlines(): 01908 line = line.strip() 01909 try: 01910 pparam, datatype, proj4term, desc = line.split(':') 01911 self.paramdesc[pparam] = (datatype, proj4term, desc) 01912 except: 01913 continue 01914 f.close() 01915 01916 def OnWizFinished(self): 01917 """!Wizard finished, create new location 01918 01919 @return error message on error 01920 @return None on success 01921 """ 01922 database = self.startpage.grassdatabase 01923 location = self.startpage.location 01924 01925 # location already exists? 01926 if os.path.isdir(os.path.join(database,location)): 01927 GError(parent = self.wizard, 01928 message = "%s <%s>: %s" % \ 01929 (_("Unable to create new location"), 01930 os.path.join(database, location), 01931 _("Location already exists in GRASS Database."))) 01932 return None 01933 01934 # current GISDbase or a new one? 01935 current_gdb = grass.gisenv()['GISDBASE'] 01936 if current_gdb != database: 01937 # change to new GISDbase or create new one 01938 if os.path.isdir(database) != True: 01939 # create new directory 01940 os.mkdir(database) 01941 01942 # change to new GISDbase directory 01943 RunCommand('g.gisenv', 01944 parent = self.wizard, 01945 set = 'GISDBASE=%s' % database) 01946 01947 wx.MessageBox(parent = self.wizard, 01948 message = _("Location <%(loc)s> will be created " 01949 "in GIS data directory <%(dir)s>. " 01950 "You will need to change the default GIS " 01951 "data directory in the GRASS startup screen.") % \ 01952 { 'loc' : location, 'dir' : database}, 01953 caption = _("New GIS data directory"), 01954 style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE) 01955 01956 # location created in alternate GISDbase 01957 self.altdb = True 01958 01959 global coordsys 01960 try: 01961 if coordsys == "xy": 01962 grass.create_location(dbase = self.startpage.grassdatabase, 01963 location = self.startpage.location, 01964 desc = self.startpage.locTitle) 01965 elif coordsys == "proj": 01966 grass.create_location(dbase = self.startpage.grassdatabase, 01967 location = self.startpage.location, 01968 proj4 = self.CreateProj4String(), 01969 datum = self.datumtrans, 01970 desc = self.startpage.locTitle) 01971 elif coordsys == 'custom': 01972 grass.create_location(dbase = self.startpage.grassdatabase, 01973 location = self.startpage.location, 01974 proj4 = self.custompage.customstring, 01975 desc = self.startpage.locTitle) 01976 elif coordsys == "epsg": 01977 if not self.epsgpage.epsgcode: 01978 return _('EPSG code missing.') 01979 01980 grass.create_location(dbase = self.startpage.grassdatabase, 01981 location = self.startpage.location, 01982 epsg = self.epsgpage.epsgcode, 01983 datum = self.datumtrans, 01984 desc = self.startpage.locTitle) 01985 elif coordsys == "file": 01986 if not self.filepage.georeffile or \ 01987 not os.path.isfile(self.filepage.georeffile): 01988 return _("File <%s> not found." % self.filepage.georeffile) 01989 01990 grass.create_location(dbase = self.startpage.grassdatabase, 01991 location = self.startpage.location, 01992 filename = self.filepage.georeffile, 01993 desc = self.startpage.locTitle) 01994 elif coordsys == "wkt": 01995 if not self.wktpage.wktfile or \ 01996 not os.path.isfile(self.wktpage.wktfile): 01997 return _("File <%s> not found." % self.wktpage.wktfile) 01998 01999 grass.create_location(dbase = self.startpage.grassdatabase, 02000 location = self.startpage.location, 02001 wkt = self.wktpage.wktfile, 02002 desc = self.startpage.locTitle) 02003 02004 except grass.ScriptError, e: 02005 return e.value 02006 02007 return None 02008 02009 def CreateProj4String(self): 02010 """!Constract PROJ.4 string""" 02011 location = self.startpage.location 02012 proj = self.projpage.p4proj 02013 projdesc = self.projpage.projdesc 02014 proj4params = self.paramspage.p4projparams 02015 02016 datum = self.datumpage.datum 02017 if self.datumpage.datumdesc: 02018 datumdesc = self.datumpage.datumdesc +' - ' + self.datumpage.ellipse 02019 else: 02020 datumdesc = '' 02021 datumparams = self.datumpage.datumparams 02022 ellipse = self.ellipsepage.ellipse 02023 ellipsedesc = self.ellipsepage.ellipsedesc 02024 ellipseparams = self.ellipsepage.ellipseparams 02025 02026 # 02027 # creating PROJ.4 string 02028 # 02029 proj4string = '%s %s' % (proj, proj4params) 02030 02031 # set ellipsoid parameters 02032 if ellipse != '': 02033 proj4string = '%s +ellps=%s' % (proj4string, ellipse) 02034 for item in ellipseparams: 02035 if item[:4] == 'f=1/': 02036 item = ' +rf=' + item[4:] 02037 else: 02038 item = ' +' + item 02039 proj4string = '%s %s' % (proj4string, item) 02040 02041 # set datum and transform parameters if relevant 02042 if datum != '': 02043 proj4string = '%s +datum=%s' % (proj4string, datum) 02044 if datumparams: 02045 for item in datumparams: 02046 proj4string = '%s +%s' % (proj4string,item) 02047 02048 proj4string = '%s +no_defs' % proj4string 02049 02050 return proj4string