GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
wizard.py
Go to the documentation of this file.
1 """!
2 @package location_wizard.wizard
3 
4 @brief Location wizard - creates a new GRASS Location. User can choose
5 from multiple methods.
6 
7 Classes:
8  - wizard::TitledPage
9  - wizard::DatabasePage
10  - wizard::CoordinateSystemPage
11  - wizard::ProjectionsPage
12  - wizard::ItemList
13  - wizard::ProjParamsPage
14  - wizard::DatumPage
15  - wizard::EllipsePage
16  - wizard::GeoreferencedFilePage
17  - wizard::WKTPage
18  - wizard::EPSGPage
19  - wizard::CustomPage
20  - wizard::SummaryPage
21  - wizard::LocationWizard
22  - wizard::WizardWithHelpButton
23 
24 (C) 2007-2013 by the GRASS Development Team
25 
26 This program is free software under the GNU General Public License
27 (>=v2). Read the file COPYING that comes with GRASS for details.
28 
29 @author Michael Barton
30 @author Jachym Cepicky
31 @author Martin Landa <landa.martin gmail.com>
32 """
33 import os
34 import locale
35 
36 import wx
37 import wx.lib.mixins.listctrl as listmix
38 import wx.wizard as wiz
39 import wx.lib.scrolledpanel as scrolled
40 
41 from core import globalvar
42 from core import utils
43 from core.gcmd import RunCommand, GError, GMessage, GWarning
44 from gui_core.ghelp import HelpFrame
45 from gui_core.widgets import GenericValidator
46 from location_wizard.base import BaseClass
47 from location_wizard.dialogs import SelectTransformDialog
48 
49 from grass.script import core as grass
50 
51 global coordsys
52 global north
53 global south
54 global east
55 global west
56 global resolution
57 global wizerror
58 global translist
59 
60 class TitledPage(BaseClass, wiz.WizardPageSimple):
61  """!Class to make wizard pages. Generic methods to make labels,
62  text entries, and buttons.
63  """
64  def __init__(self, parent, title):
65 
66  self.page = wiz.WizardPageSimple.__init__(self, parent)
67 
68  # page title
69  self.title = wx.StaticText(parent = self, id = wx.ID_ANY, label = title)
70  self.title.SetFont(wx.Font(13, wx.SWISS, wx.NORMAL, wx.BOLD))
71 
72  # main sizers
73  self.pagesizer = wx.BoxSizer(wx.VERTICAL)
74  self.sizer = wx.GridBagSizer(vgap = 0, hgap = 0)
75 
76  def DoLayout(self):
77  """!Do page layout"""
78  self.pagesizer.Add(item = self.title, proportion = 0,
79  flag = wx.ALIGN_CENTRE | wx.ALL,
80  border = 5)
81  self.pagesizer.Add(item = wx.StaticLine(self, -1), proportion = 0,
82  flag = wx.EXPAND | wx.ALL,
83  border = 0)
84  self.pagesizer.Add(item = self.sizer, proportion = 1,
85  flag = wx.EXPAND)
86 
87  self.SetAutoLayout(True)
88  self.SetSizer(self.pagesizer)
89  self.Layout()
90 
92  """!Wizard page for setting GIS data directory and location name"""
93  def __init__(self, wizard, parent, grassdatabase):
94  TitledPage.__init__(self, wizard, _("Define GRASS Database and Location Name"))
95 
96  self.grassdatabase = grassdatabase
97  self.location = ''
98  self.locTitle = ''
99 
100  # buttons
101  self.bbrowse = self.MakeButton(_("Browse"))
102 
103  # text controls
104  self.tgisdbase = self.MakeTextCtrl(grassdatabase, size = (300, -1))
105  self.tlocation = self.MakeTextCtrl("newLocation", size = (300, -1))
106  self.tlocation.SetValidator(GenericValidator(grass.legal_name, self._nameValidationFailed))
107  self.tlocTitle = self.MakeTextCtrl(size = (400, -1))
108 
109  # layout
110  self.sizer.Add(item = self.MakeLabel(_("GIS Data Directory:")),
111  flag = wx.ALIGN_RIGHT |
112  wx.ALIGN_CENTER_VERTICAL |
113  wx.ALL, border = 5,
114  pos = (1, 1))
115  self.sizer.Add(item = self.tgisdbase,
116  flag = wx.ALIGN_LEFT |
117  wx.ALIGN_CENTER_VERTICAL |
118  wx.ALL, border = 5,
119  pos = (1, 2))
120  self.sizer.Add(item = self.bbrowse,
121  flag = wx.ALIGN_LEFT |
122  wx.ALIGN_CENTER_VERTICAL |
123  wx.ALL, border = 5,
124  pos = (1, 3))
125 
126  self.sizer.Add(item = self.MakeLabel("%s:" % _("Project Location"),
127  tooltip = _("Name of location directory in GIS Data Directory")),
128  flag = wx.ALIGN_RIGHT |
129  wx.ALIGN_CENTER_VERTICAL |
130  wx.ALL, border = 5,
131  pos = (2, 1))
132  self.sizer.Add(item = self.tlocation,
133  flag = wx.ALIGN_LEFT |
134  wx.ALIGN_CENTER_VERTICAL |
135  wx.ALL, border = 5,
136  pos = (2, 2))
137 
138  self.sizer.Add(item = self.MakeLabel("%s:" % _("Location Title"),
139  tooltip = _("Optional location title, "
140  "you can leave this field blank.")),
141  flag = wx.ALIGN_RIGHT |
142  wx.ALIGN_TOP | wx.ALIGN_CENTER_VERTICAL |
143  wx.ALL, border = 5,
144  pos = (3, 1))
145  self.sizer.Add(item = self.tlocTitle,
146  flag = wx.ALIGN_LEFT |
147  wx.ALIGN_CENTER_VERTICAL |
148  wx.ALL, border = 5,
149  pos = (3, 2), span = (1, 2))
150  self.sizer.AddGrowableCol(3)
151 
152  # bindings
153  self.Bind(wx.EVT_BUTTON, self.OnBrowse, self.bbrowse)
154  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
155  self.tgisdbase.Bind(wx.EVT_TEXT, self.OnChangeName)
156  self.tlocation.Bind(wx.EVT_TEXT, self.OnChangeName)
157 
158  def _nameValidationFailed(self, ctrl):
159  message = _("Name <%(name)s> is not a valid name for location. "
160  "Please use only ASCII characters excluding %(chars)s "
161  "and space.") % {'name': ctrl.GetValue(), 'chars': '/"\'@,=*~'}
162  GError(parent=self, message=message, caption=_("Invalid location name"))
163 
164  def OnChangeName(self, event):
165  """!Name for new location was changed"""
166  nextButton = wx.FindWindowById(wx.ID_FORWARD)
167  if len(event.GetString()) > 0:
168  if not nextButton.IsEnabled():
169  nextButton.Enable()
170  else:
171  nextButton.Disable()
172 
173  event.Skip()
174 
175  def OnBrowse(self, event):
176  """!Choose GRASS data directory"""
177  dlg = wx.DirDialog(self, _("Choose GRASS data directory:"),
178  os.getcwd(), wx.DD_DEFAULT_STYLE)
179  if dlg.ShowModal() == wx.ID_OK:
180  self.grassdatabase = dlg.GetPath()
181  self.tgisdbase.SetValue(self.grassdatabase)
182 
183  dlg.Destroy()
184 
185  def OnPageChanging(self, event = None):
186  error = None
187  if os.path.isdir(os.path.join(self.tgisdbase.GetValue(), self.tlocation.GetValue())):
188  error = _("Location already exists in GRASS Database.")
189 
190  if error:
191  GError(parent = self,
192  message="%s <%s>.%s%s" % (_("Unable to create location"),
193  str(self.tlocation.GetValue()),
194  os.linesep,
195  error))
196  event.Veto()
197  return
198 
199  self.location = self.tlocation.GetValue()
200  self.grassdatabase = self.tgisdbase.GetValue()
201  self.locTitle = self.tlocTitle.GetValue()
202  if os.linesep in self.locTitle or \
203  len(self.locTitle) > 255:
204  GWarning(parent = self,
205  message = _("Title of the location is limited only to one line and "
206  "256 characters. The rest of the text will be ignored."))
207  self.locTitle = self.locTitle.split(os.linesep)[0][:255]
208 
210  """!Wizard page for choosing method for location creation"""
211  def __init__(self, wizard, parent):
212  TitledPage.__init__(self, wizard, _("Choose method for creating a new location"))
213 
214  self.parent = parent
215  global coordsys
216 
217  # toggles
218  self.radio1 = wx.RadioButton(parent = self, id = wx.ID_ANY,
219  label = _("Select coordinate system parameters from a list"),
220  style = wx.RB_GROUP)
221  self.radio2 = wx.RadioButton(parent = self, id = wx.ID_ANY,
222  label = _("Select EPSG code of spatial reference system"))
223  self.radio3 = wx.RadioButton(parent = self, id = wx.ID_ANY,
224  label = _("Read projection and datum terms from a "
225  "georeferenced data file"))
226  self.radio4 = wx.RadioButton(parent = self, id = wx.ID_ANY,
227  label = _("Read projection and datum terms from a "
228  "Well Known Text (WKT) .prj file"))
229  self.radio5 = wx.RadioButton(parent = self, id = wx.ID_ANY,
230  label = _("Specify projection and datum terms using custom "
231  "PROJ.4 parameters"))
232  self.radio6 = wx.RadioButton(parent = self, id = wx.ID_ANY,
233  label = _("Create a generic Cartesian coordinate system (XY)"))
234 
235  # layout
236  self.sizer.SetVGap(10)
237  self.sizer.Add(item = self.radio1,
238  flag = wx.ALIGN_LEFT, pos = (1, 1))
239  self.sizer.Add(item = self.radio2,
240  flag = wx.ALIGN_LEFT, pos = (2, 1))
241  self.sizer.Add(item = self.radio3,
242  flag = wx.ALIGN_LEFT, pos = (3, 1))
243  self.sizer.Add(item = self.radio4,
244  flag = wx.ALIGN_LEFT, pos = (4, 1))
245  self.sizer.Add(item = self.radio5,
246  flag = wx.ALIGN_LEFT, pos = (5, 1))
247  self.sizer.Add(item = self.radio6,
248  flag = wx.ALIGN_LEFT, pos = (6, 1))
249  self.sizer.AddGrowableCol(1)
250 
251  # bindings
252  self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio1.GetId())
253  self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio2.GetId())
254  self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio3.GetId())
255  self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio4.GetId())
256  self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio5.GetId())
257  self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio6.GetId())
258  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
259 
260  def OnEnterPage(self, event):
261  global coordsys
262 
263  if not coordsys:
264  coordsys = "proj"
265  self.radio1.SetValue(True)
266  else:
267  if coordsys == 'proj':
268  self.radio1.SetValue(True)
269  if coordsys == "epsg":
270  self.radio2.SetValue(True)
271  if coordsys == "file":
272  self.radio3.SetValue(True)
273  if coordsys == "wkt":
274  self.radio4.SetValue(True)
275  if coordsys == "custom":
276  self.radio5.SetValue(True)
277  if coordsys == "xy":
278  self.radio6.SetValue(True)
279 
280  if event.GetDirection():
281  if coordsys == 'proj':
282  self.SetNext(self.parent.projpage)
283  self.parent.sumpage.SetPrev(self.parent.datumpage)
284  if coordsys == "epsg":
285  self.SetNext(self.parent.epsgpage)
286  self.parent.sumpage.SetPrev(self.parent.epsgpage)
287  if coordsys == "file":
288  self.SetNext(self.parent.filepage)
289  self.parent.sumpage.SetPrev(self.parent.filepage)
290  if coordsys == "wkt":
291  self.SetNext(self.parent.wktpage)
292  self.parent.sumpage.SetPrev(self.parent.wktpage)
293  if coordsys == "custom":
294  self.SetNext(self.parent.custompage)
295  self.parent.sumpage.SetPrev(self.parent.custompage)
296  if coordsys == "xy":
297  self.SetNext(self.parent.sumpage)
298  self.parent.sumpage.SetPrev(self.parent.csystemspage)
299 
300  if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled():
301  wx.FindWindowById(wx.ID_FORWARD).Enable()
302 
303  def SetVal(self, event):
304  """!Choose method"""
305  global coordsys
306  if event.GetId() == self.radio1.GetId():
307  coordsys = "proj"
308  self.SetNext(self.parent.projpage)
309  self.parent.sumpage.SetPrev(self.parent.datumpage)
310  elif event.GetId() == self.radio2.GetId():
311  coordsys = "epsg"
312  self.SetNext(self.parent.epsgpage)
313  self.parent.sumpage.SetPrev(self.parent.epsgpage)
314  elif event.GetId() == self.radio3.GetId():
315  coordsys = "file"
316  self.SetNext(self.parent.filepage)
317  self.parent.sumpage.SetPrev(self.parent.filepage)
318  elif event.GetId() == self.radio4.GetId():
319  coordsys = "wkt"
320  self.SetNext(self.parent.wktpage)
321  self.parent.sumpage.SetPrev(self.parent.wktpage)
322  elif event.GetId() == self.radio5.GetId():
323  coordsys = "custom"
324  self.SetNext(self.parent.custompage)
325  self.parent.sumpage.SetPrev(self.parent.custompage)
326  elif event.GetId() == self.radio6.GetId():
327  coordsys = "xy"
328  self.SetNext(self.parent.sumpage)
329  self.parent.sumpage.SetPrev(self.parent.csystemspage)
330 
332  """!Wizard page for selecting projection (select coordinate system option)"""
333  def __init__(self, wizard, parent):
334  TitledPage.__init__(self, wizard, _("Choose projection"))
335 
336  self.parent = parent
337  self.proj = ''
338  self.projdesc = ''
339  self.p4proj = ''
340 
341  # text input
342  self.tproj = self.MakeTextCtrl("", size = (200,-1))
343 
344  # search box
345  self.searchb = wx.SearchCtrl(self, size = (200,-1),
346  style = wx.TE_PROCESS_ENTER)
347 
348  # projection list
349  self.projlist = ItemList(self, data = self.parent.projdesc.items(),
350  columns = [_('Code'), _('Description')])
351  self.projlist.resizeLastColumn(30)
352 
353  # layout
354  self.sizer.Add(item = self.MakeLabel(_("Projection code:")),
355  flag = wx.ALIGN_LEFT |
356  wx.ALIGN_CENTER_VERTICAL |
357  wx.ALL, border = 5, pos = (1, 1))
358  self.sizer.Add(item = self.tproj,
359  flag = wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL,
360  border = 5, pos = (1, 2))
361 
362  self.sizer.Add(item = self.MakeLabel(_("Search in description:")),
363  flag = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
364  border = 5, pos = (2, 1))
365  self.sizer.Add(item = self.searchb,
366  flag = wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL,
367  border = 5, pos = (2, 2))
368 
369  self.sizer.Add(item = self.projlist,
370  flag = wx.EXPAND |
371  wx.ALIGN_LEFT |
372  wx.ALL, border = 5, pos = (3, 1), span = (1, 3))
373  self.sizer.AddGrowableCol(3)
374  self.sizer.AddGrowableRow(3)
375 
376  # events
377  self.tproj.Bind(wx.EVT_TEXT, self.OnText)
378  self.tproj.Bind(wx.EVT_TEXT_ENTER, self.OnText)
379  self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnSearch)
380  self.projlist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
381  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
382  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
383 
384  def OnPageChanging(self,event):
385  if event.GetDirection() and self.proj not in self.parent.projections.keys():
386  event.Veto()
387 
388  def OnText(self, event):
389  """!Projection name changed"""
390  self.proj = event.GetString().lower()
391  self.p4proj = ''
392  nextButton = wx.FindWindowById(wx.ID_FORWARD)
393  if self.proj not in self.parent.projections.keys() and nextButton.IsEnabled():
394  nextButton.Enable(False)
395 
396  if self.proj in self.parent.projections.keys():
397  if self.proj == 'stp':
398  wx.MessageBox('Currently State Plane projections must be selected using the '
399  'text-based setup (g.setproj), or entered by EPSG code or '
400  'custom PROJ.4 terms.',
401  'Warning', wx.ICON_WARNING)
402  self.proj = ''
403  self.tproj.SetValue(self.proj)
404  nextButton.Enable(False)
405  return
406  elif self.proj.lower() == 'll':
407  self.p4proj = '+proj=longlat'
408  else:
409  self.p4proj = '+proj=' + self.proj.lower()
410  self.projdesc = self.parent.projections[self.proj][0]
411  nextButton.Enable()
412 
413  def OnEnterPage(self, event):
414  if len(self.proj) == 0:
415  # disable 'next' button by default
416  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
417  else:
418  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
419 
420  event.Skip()
421 
422  def OnSearch(self, event):
423  """!Search projection by desc"""
424  str = event.GetString()
425  try:
426  self.proj, self.projdesc = self.projlist.Search(index = [0,1], pattern = event.GetString())
427  except:
428  self.proj = self.projdesc = ''
429 
430  event.Skip()
431 
432  def OnItemSelected(self, event):
433  """!Projection selected"""
434  index = event.m_itemIndex
435 
436  # set values
437  self.proj = self.projlist.GetItem(index, 0).GetText().lower()
438  self.tproj.SetValue(self.proj)
439 
440  event.Skip()
441 
442 class ItemList(wx.ListCtrl,
443  listmix.ListCtrlAutoWidthMixin,
444  listmix.ColumnSorterMixin):
445  """!Generic list (for projections, ellipsoids, etc.)"""
446 
447  def __init__(self, parent, columns, data = None):
448  wx.ListCtrl.__init__(self, parent = parent, id = wx.ID_ANY,
449  style = wx.LC_REPORT |
450  wx.LC_VIRTUAL |
451  wx.LC_HRULES |
452  wx.LC_VRULES |
453  wx.LC_SINGLE_SEL |
454  wx.LC_SORT_ASCENDING, size = (550, 125))
455 
456  # original data or None
457  self.sourceData = data
458 
459  #
460  # insert columns
461  #
462  i = 0
463  for column in columns:
464  self.InsertColumn(i, column)
465  i += 1
466  #
467  # add some attributes
468  #
469  self.attr1 = wx.ListItemAttr()
470  self.attr1.SetBackgroundColour(wx.Colour(238,238,238))
471  self.attr2 = wx.ListItemAttr()
472  self.attr2.SetBackgroundColour("white")
473 
474  if self.sourceData:
475  self.Populate()
476 
477  for i in range(self.GetColumnCount()):
478  self.SetColumnWidth(i, wx.LIST_AUTOSIZE_USEHEADER)
479  if self.GetColumnWidth(i) < 80:
480  self.SetColumnWidth(i, 80)
481 
482  #
483  # listmix
484  #
485  listmix.ListCtrlAutoWidthMixin.__init__(self)
486  listmix.ColumnSorterMixin.__init__(self, self.GetColumnCount())
487 
488  self.il = wx.ImageList(16, 16)
489  self.sm_up = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_GO_UP, wx.ART_TOOLBAR,
490  (16,16)))
491  self.sm_dn = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_GO_DOWN, wx.ART_TOOLBAR,
492  (16,16)))
493  self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
494 
495  #
496  # sort by first column
497  #
498  if self.sourceData:
499  self.SortListItems(col = 0, ascending = True)
500 
501  #
502  # bindings
503  #
504  self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColumnClick)
505 
506  def Populate(self, data = None, update = False):
507  """!Populate list"""
508  self.itemDataMap = {}
509  self.itemIndexMap = []
510 
511  if data is None:
512  data = self.sourceData
513  elif update:
514  self.sourceData = data
515 
516  try:
517  data.sort()
518  self.DeleteAllItems()
519  row = 0
520  for value in data:
521  self.itemDataMap[row] = [value[0]]
522  for i in range(1, len(value)):
523  self.itemDataMap[row].append(value[i])
524  self.itemIndexMap.append(row)
525  row += 1
526 
527  self.SetItemCount(row)
528 
529  # set column width
530  self.SetColumnWidth(0, 80)
531  self.SetColumnWidth(1, 300)
532 
533  self.SendSizeEvent()
534 
535  except StandardError, e:
536  wx.MessageBox(parent = self,
537  message = _("Unable to read list: %s") % e,
538  caption = _("Error"), style = wx.OK | wx.ICON_ERROR)
539 
540  def OnColumnClick(self, event):
541  """!Sort by column"""
542  self._col = event.GetColumn()
543 
544  # remove duplicated arrow symbol from column header
545  # FIXME: should be done automatically
546  info = wx.ListItem()
547  info.m_mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE
548  info.m_image = -1
549  for column in range(self.GetColumnCount()):
550  info.m_text = self.GetColumn(column).GetText()
551  self.SetColumn(column, info)
552 
553  event.Skip()
554 
555  def GetSortImages(self):
556  """!Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py"""
557  return (self.sm_dn, self.sm_up)
558 
559  def OnGetItemText(self, item, col):
560  """!Get item text"""
561  index = self.itemIndexMap[item]
562  s = str(self.itemDataMap[index][col])
563  return s
564 
565  def OnGetItemAttr(self, item):
566  """!Get item attributes"""
567  index = self.itemIndexMap[item]
568  if ( index % 2) == 0:
569  return self.attr2
570  else:
571  return self.attr1
572 
573  def SortItems(self, sorter = cmp):
574  """!Sort items"""
575  items = list(self.itemDataMap.keys())
576  items.sort(self.Sorter)
577  self.itemIndexMap = items
578 
579  # redraw the list
580  self.Refresh()
581 
582  def Sorter(self, key1, key2):
583  colName = self.GetColumn(self._col).GetText()
584  ascending = self._colSortFlag[self._col]
585  # convert always string
586  item1 = self.itemDataMap[key1][self._col]
587  item2 = self.itemDataMap[key2][self._col]
588 
589  if type(item1) == type('') or type(item2) == type(''):
590  cmpVal = locale.strcoll(str(item1), str(item2))
591  else:
592  cmpVal = cmp(item1, item2)
593 
594 
595  # If the items are equal then pick something else to make the sort value unique
596  if cmpVal == 0:
597  cmpVal = apply(cmp, self.GetSecondarySortValues(self._col, key1, key2))
598 
599  if ascending:
600  return cmpVal
601  else:
602  return -cmpVal
603 
604  def GetListCtrl(self):
605  """!Used by listmix.ColumnSorterMixin"""
606  return self
607 
608  def Search (self, index, pattern):
609  """!Search projection by description
610  Return first found item or None
611  """
612  if pattern == '':
613  self.Populate(self.sourceData)
614  return []
615 
616  data = []
617  pattern = pattern.lower()
618  for i in range(len(self.sourceData)):
619  for idx in index:
620  try:
621  value = str(self.sourceData[i][idx]).lower()
622  if pattern in value:
623  data.append(self.sourceData[i])
624  break
625  except UnicodeDecodeError:
626  # osgeo4w problem (should be fixed)
627  pass
628 
629  self.Populate(data)
630  if len(data) > 0:
631  return data[0]
632  else:
633  return []
634 
636  """!Wizard page for selecting method of setting coordinate system
637  parameters (select coordinate system option)
638  """
639  def __init__(self, wizard, parent):
640  TitledPage.__init__(self, wizard, _("Choose projection parameters"))
641  global coordsys
642 
643  self.parent = parent
644  self.panel = None
645  self.prjParamSizer = None
646 
647  self.pparam = dict()
648 
649  self.p4projparams = ''
650  self.projdesc = ''
651 
652 
653  radioSBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
654  label = " %s " % _("Select datum or ellipsoid (next page)"))
655  radioSBSizer = wx.StaticBoxSizer(radioSBox)
656  self.sizer.Add(item = radioSBSizer, pos = (0, 1),
657  flag = wx.EXPAND | wx.ALIGN_TOP | wx.TOP, border = 10)
658  self.sizer.AddGrowableCol(1)
659 
660  self.radio1 = wx.RadioButton(parent = self, id = wx.ID_ANY,
661  label = _("Datum with associated ellipsoid"),
662  style = wx.RB_GROUP)
663  self.radio2 = wx.RadioButton(parent = self, id = wx.ID_ANY,
664  label = _("Ellipsoid only"))
665 
666  # default button setting
667  if self.radio1.GetValue() == False and self.radio2.GetValue() == False:
668  self.radio1.SetValue(True)
669  self.SetNext(self.parent.datumpage)
670  # self.parent.sumpage.SetPrev(self.parent.datumpage)
671 
672  radioSBSizer.Add(item = self.radio1,
673  flag = wx.ALIGN_LEFT | wx.RIGHT, border = 20)
674  radioSBSizer.Add(item = self.radio2,
675  flag = wx.ALIGN_LEFT)
676 
677  # bindings
678  self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio1.GetId())
679  self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio2.GetId())
680  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChange)
681  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
682 
683  def OnParamEntry(self, event):
684  """!Parameter value changed"""
685  id = event.GetId()
686  val = event.GetString()
687 
688  if id not in self.pparam:
689  event.Skip()
690  return
691 
692  param = self.pparam[id]
693  win = self.FindWindowById(id)
694  if param['type'] == 'zone':
695  val = event.GetInt()
696  if val < 1:
697  win.SetValue(1)
698  elif val > 60:
699  win.SetValue(60)
700 
701  if param['type'] == 'bool':
702  param['value'] = event.GetSelection()
703  else:
704  param['value'] = val
705 
706  event.Skip()
707 
708  def OnPageChange(self,event=None):
709  """!Go to next page"""
710  if event.GetDirection():
711  self.p4projparams = ''
712  for id, param in self.pparam.iteritems():
713  if param['type'] == 'bool':
714  if param['value'] == False:
715  continue
716  else:
717  self.p4projparams += (' +' + param['proj4'])
718  else:
719  if param['value'] is None:
720  wx.MessageBox(parent = self,
721  message = _('You must enter a value for %s') % param['desc'],
722  caption = _('Error'), style = wx.ICON_ERROR | wx.CENTRE)
723  event.Veto()
724  else:
725  self.p4projparams += (' +' + param['proj4'] + '=' + str(param['value']))
726 
727  def OnEnterPage(self,event):
728  """!Page entered"""
729  self.projdesc = self.parent.projections[self.parent.projpage.proj][0]
730  if self.prjParamSizer is None:
731  # entering page for the first time
732  self.paramSBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
733  label = _(" Enter parameters for %s projection ") % self.projdesc)
734  paramSBSizer = wx.StaticBoxSizer(self.paramSBox)
735 
736  self.panel = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY)
737  self.panel.SetupScrolling()
738 
739  self.prjParamSizer = wx.GridBagSizer(vgap = 0, hgap = 0)
740 
741  self.sizer.Add(item = paramSBSizer, pos = (1, 1),
742  flag = wx.EXPAND)
743  paramSBSizer.Add(item = self.panel, proportion = 1,
744  flag = wx.ALIGN_CENTER | wx.EXPAND)
745 
746  paramSBSizer.Fit(self.panel)
747  self.panel.SetSizer(self.prjParamSizer)
748 
749  if event.GetDirection():
750  self.prjParamSizer.Clear(True)
751  self.paramSBox.SetLabel(_(" Enter parameters for %s projection ") % self.projdesc)
752  self.pparam = dict()
753  row = 0
754  for paramgrp in self.parent.projections[self.parent.projpage.proj][1]:
755  # get parameters
756  id = wx.NewId()
757  param = self.pparam[id] = { 'type' : self.parent.paramdesc[paramgrp[0]][0],
758  'proj4': self.parent.paramdesc[paramgrp[0]][1],
759  'desc' : self.parent.paramdesc[paramgrp[0]][2] }
760 
761  # default values
762  if param['type'] == 'bool':
763  param['value'] = 0
764  elif param['type'] == 'zone':
765  param['value'] = 30
766  param['desc'] += ' (1-60)'
767  else:
768  param['value'] = paramgrp[2]
769 
770  label = wx.StaticText(parent = self.panel, id = wx.ID_ANY, label = param['desc'],
771  style = wx.ALIGN_RIGHT | wx.ST_NO_AUTORESIZE)
772  if param['type'] == 'bool':
773  win = wx.Choice(parent = self.panel, id = id, size = (100,-1),
774  choices = [_('No'), _('Yes')])
775  win.SetSelection(param['value'])
776  win.Bind(wx.EVT_CHOICE, self.OnParamEntry)
777  elif param['type'] == 'zone':
778  win = wx.SpinCtrl(parent = self.panel, id = id,
779  size = (100, -1),
780  style = wx.SP_ARROW_KEYS | wx.SP_WRAP,
781  min = 1, max = 60)
782  win.SetValue(param['value'])
783  win.Bind(wx.EVT_SPINCTRL, self.OnParamEntry)
784  win.Bind(wx.EVT_TEXT, self.OnParamEntry)
785  else:
786  win = wx.TextCtrl(parent = self.panel, id = id,
787  value = param['value'],
788  size=(100, -1))
789  win.Bind(wx.EVT_TEXT, self.OnParamEntry)
790  if paramgrp[1] == 'noask':
791  win.Enable(False)
792 
793  self.prjParamSizer.Add(item = label, pos = (row, 1),
794  flag = wx.ALIGN_RIGHT |
795  wx.ALIGN_CENTER_VERTICAL |
796  wx.RIGHT, border = 5)
797  self.prjParamSizer.Add(item = win, pos = (row, 2),
798  flag = wx.ALIGN_LEFT |
799  wx.ALIGN_CENTER_VERTICAL |
800  wx.LEFT, border = 5)
801  row += 1
802  self.sizer.AddGrowableRow(1)
803  self.panel.SetSize(self.panel.GetBestSize())
804  self.panel.Layout()
805  self.Layout()
806  self.Update()
807 
808  if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled():
809  wx.FindWindowById(wx.ID_FORWARD).Enable()
810 
811  event.Skip()
812 
813  def SetVal(self, event):
814  """!Set value"""
815  if event.GetId() == self.radio1.GetId():
816  self.SetNext(self.parent.datumpage)
817  self.parent.sumpage.SetPrev(self.parent.datumpage)
818  elif event.GetId() == self.radio2.GetId():
819  self.SetNext(self.parent.ellipsepage)
820  self.parent.sumpage.SetPrev(self.parent.ellipsepage)
821 
823  """!Wizard page for selecting datum (with associated ellipsoid)
824  and datum transformation parameters (select coordinate system option)
825  """
826 
827  def __init__(self, wizard, parent):
828  TitledPage.__init__(self, wizard, _("Specify geodetic datum"))
829 
830  self.parent = parent
831  self.datum = ''
832  self.datumdesc = ''
833  self.ellipse = ''
834  self.datumparams = ''
835  self.proj4params = ''
836 
837  # text input
838  self.tdatum = self.MakeTextCtrl("", size = (200,-1))
839 
840  # search box
841  self.searchb = wx.SearchCtrl(self, size = (200,-1),
842  style = wx.TE_PROCESS_ENTER)
843 
844  # create list control for datum/elipsoid list
845  data = []
846  for key in self.parent.datums.keys():
847  data.append([key, self.parent.datums[key][0], self.parent.datums[key][1]])
848  self.datumlist = ItemList(self,
849  data = data,
850  columns = [_('Code'), _('Ellipsoid'), _('Description')])
851  self.datumlist.resizeLastColumn(10)
852 
853  # layout
854  self.sizer.Add(item = self.MakeLabel(_("Datum code:")),
855  flag = wx.ALIGN_LEFT |
856  wx.ALIGN_CENTER_VERTICAL |
857  wx.ALL, border = 5, pos = (1, 1))
858  self.sizer.Add(item = self.tdatum,
859  flag = wx.ALIGN_LEFT |
860  wx.ALIGN_CENTER_VERTICAL |
861  wx.ALL, border = 5, pos = (1, 2))
862 
863  self.sizer.Add(item = self.MakeLabel(_("Search in description:")),
864  flag = wx.ALIGN_LEFT |
865  wx.ALIGN_CENTER_VERTICAL |
866  wx.ALL, border = 5, pos = (2, 1))
867  self.sizer.Add(item = self.searchb,
868  flag = wx.ALIGN_LEFT |
869  wx.ALIGN_CENTER_VERTICAL |
870  wx.ALL, border = 5, pos = (2, 2))
871 
872  self.sizer.Add(item = self.datumlist,
873  flag = wx.EXPAND |
874  wx.ALIGN_LEFT |
875  wx.ALL, border = 5, pos = (3, 1), span = (1, 4))
876  self.sizer.AddGrowableCol(4)
877  self.sizer.AddGrowableRow(3)
878 
879  # events
880  self.datumlist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnDatumSelected)
881  self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnDSearch)
882  self.tdatum.Bind(wx.EVT_TEXT, self.OnDText)
883  self.tdatum.Bind(wx.EVT_TEXT_ENTER, self.OnDText)
884  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
885  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
886 
887  # do page layout
888  # self.DoLayout()
889 
890  def OnPageChanging(self, event):
891  self.proj4params = ''
892  proj = self.parent.projpage.p4proj
893 
894  if event.GetDirection():
895  if self.datum not in self.parent.datums:
896  event.Veto()
897  else:
898  # check for datum tranforms
899 # proj4string = self.parent.CreateProj4String() + ' +datum=%s' % self.datum
900  ret = RunCommand('g.proj',
901  read = True,
902  proj4 = '%s' % proj,
903  datum = '%s' % self.datum,
904  datumtrans = '-1',
905  flags = 't')
906 # wx.Messagebox('here')
907  if ret != '':
908  dtrans = ''
909  # open a dialog to select datum transform number
910  dlg = SelectTransformDialog(self.parent.parent, transforms=ret)
911 
912  if dlg.ShowModal() == wx.ID_OK:
913  dtrans = dlg.GetTransform()
914  if dtrans == '':
915  dlg.Destroy()
916  event.Veto()
917  return 'Datum transform is required.'
918  else:
919  dlg.Destroy()
920  event.Veto()
921  return 'Datum transform is required.'
922 
923  self.parent.datumtrans = dtrans
924 
925  self.GetNext().SetPrev(self)
926  self.parent.ellipsepage.ellipse = self.ellipse
927  self.parent.ellipsepage.ellipseparams = self.parent.ellipsoids[self.ellipse][1]
928 
929  def OnEnterPage(self,event):
930  self.parent.datumtrans = None
931  if event.GetDirection():
932  if len(self.datum) == 0:
933  # disable 'next' button by default when entering from previous page
934  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
935  else:
936  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
937 
938  event.Skip()
939 
940  def OnDText(self, event):
941  """!Datum code changed"""
942  self.datum = event.GetString()
943 
944  nextButton = wx.FindWindowById(wx.ID_FORWARD)
945  if len(self.datum) == 0 or self.datum not in self.parent.datums:
946  nextButton.Enable(False)
947  else:
948  self.ellipse = self.parent.datums[self.datum][0]
949  self.datumdesc = self.parent.datums[self.datum][1]
950  self.datumparams = self.parent.datums[self.datum][2]
951  try:
952  self.datumparams.remove('dx=0.0')
953  except:
954  pass
955  try:
956  self.datumparams.remove('dy=0.0')
957  except:
958  pass
959  try:
960  self.datumparams.remove('dz=0.0')
961  except:
962  pass
963 
964  nextButton.Enable(True)
965 
966  self.Update()
967  event.Skip()
968 
969  def OnDSearch(self, event):
970  """!Search geodetic datum by desc"""
971  str = self.searchb.GetValue()
972  try:
973  self.datum, self.ellipsoid, self.datumdesc = self.datumlist.Search(index = [0,1,2], pattern = str)
974  except:
975  self.datum = self.datumdesc = self.ellipsoid = ''
976 
977  event.Skip()
978 
979  def OnDatumSelected(self, event):
980  """!Datum selected"""
981  index = event.m_itemIndex
982  item = event.GetItem()
983 
984  self.datum = self.datumlist.GetItem(index, 0).GetText()
985  self.tdatum.SetValue(self.datum)
986 
987  event.Skip()
988 
990  """!Wizard page for selecting ellipsoid (select coordinate system option)"""
991 
992  def __init__(self, wizard, parent):
993  TitledPage.__init__(self, wizard, _("Specify ellipsoid"))
994 
995  self.parent = parent
996 
997  self.ellipse = ''
998  self.ellipsedesc = ''
999  self.ellipseparams = ''
1000  self.proj4params = ''
1001 
1002  # text input
1003  self.tellipse = self.MakeTextCtrl("", size = (200,-1))
1004 
1005  # search box
1006  self.searchb = wx.SearchCtrl(self, size = (200,-1),
1007  style = wx.TE_PROCESS_ENTER)
1008 
1009  # create list control for ellipse list
1010  data = []
1011  # extract code, desc
1012  for key in self.parent.ellipsoids.keys():
1013  data.append([key, self.parent.ellipsoids[key][0]])
1014 
1015  self.ellipselist = ItemList(self, data = data,
1016  columns = [_('Code'), _('Description')])
1017  self.ellipselist.resizeLastColumn(30)
1018 
1019  # layout
1020  self.sizer.Add(item = self.MakeLabel(_("Ellipsoid code:")),
1021  flag = wx.ALIGN_RIGHT |
1022  wx.ALIGN_CENTER_VERTICAL |
1023  wx.ALL, border = 5, pos = (1, 1))
1024  self.sizer.Add(item = self.tellipse,
1025  flag = wx.ALIGN_LEFT |
1026  wx.ALIGN_CENTER_VERTICAL |
1027  wx.ALL, border = 5, pos = (1, 2))
1028  self.sizer.Add(item = self.MakeLabel(_("Search in description:")),
1029  flag = wx.ALIGN_RIGHT |
1030  wx.ALIGN_CENTER_VERTICAL |
1031  wx.ALL, border = 5, pos = (2, 1))
1032  self.sizer.Add(item = self.searchb,
1033  flag = wx.ALIGN_LEFT |
1034  wx.ALIGN_CENTER_VERTICAL |
1035  wx.ALL, border = 5, pos = (2, 2))
1036 
1037  self.sizer.Add(item = self.ellipselist,
1038  flag = wx.EXPAND |
1039  wx.ALIGN_LEFT |
1040  wx.ALL, border = 5, pos = (3, 1), span = (1, 4))
1041  self.sizer.AddGrowableCol(4)
1042  self.sizer.AddGrowableRow(3)
1043 
1044  # events
1045  self.ellipselist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
1046  self.tellipse.Bind(wx.EVT_TEXT, self.OnText)
1047  self.tellipse.Bind(wx.EVT_TEXT_ENTER, self.OnText)
1048  self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnSearch)
1049  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
1050  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1051 
1052  def OnEnterPage(self,event):
1053  if len(self.ellipse) == 0:
1054  # disable 'next' button by default
1055  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
1056  else:
1057  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
1058 
1059  event.Skip()
1060 
1061  def OnPageChanging(self, event):
1062  if event.GetDirection() and self.ellipse not in self.parent.ellipsoids:
1063  event.Veto()
1064 
1065  self.proj4params = ''
1066  self.GetNext().SetPrev(self)
1067  self.parent.datumpage.datumparams = ''
1068  # self.GetNext().SetPrev(self) (???)
1069 
1070  def OnText(self, event):
1071  """!Ellipspoid code changed"""
1072  self.ellipse = event.GetString()
1073  nextButton = wx.FindWindowById(wx.ID_FORWARD)
1074  if len(self.ellipse) == 0 or self.ellipse not in self.parent.ellipsoids:
1075  nextButton.Enable(False)
1076  self.ellipsedesc = ''
1077  self.ellipseparams = ''
1078  self.proj4params = ''
1079  elif self.ellipse in self.parent.ellipsoids:
1080  self.ellipsedesc = self.parent.ellipsoids[self.ellipse][0]
1081  self.ellipseparams = self.parent.ellipsoids[self.ellipse][1]
1082  nextButton.Enable(True)
1083 
1084  def OnSearch(self, event):
1085  """!Search ellipsoid by desc"""
1086  try:
1087  self.ellipse, self.ellipsedesc = \
1088  self.ellipselist.Search(index=[0,1], pattern=event.GetString())
1089  self.ellipseparams = self.parent.ellipsoids[self.ellipse][1]
1090  except:
1091  self.ellipse = self.ellipsedesc = self.ellipseparams = ''
1092 
1093  event.Skip()
1094 
1095  def OnItemSelected(self,event):
1096  """!Ellipsoid selected"""
1097  index = event.m_itemIndex
1098  item = event.GetItem()
1099 
1100  self.ellipse = self.ellipselist.GetItem(index, 0).GetText()
1101  self.tellipse.SetValue(self.ellipse)
1102 
1103  event.Skip()
1104 
1106  """!Wizard page for selecting georeferenced file to use
1107  for setting coordinate system parameters"""
1108 
1109  def __init__(self, wizard, parent):
1110  TitledPage.__init__(self, wizard, _("Select georeferenced file"))
1111 
1112  self.georeffile = ''
1113 
1114  # create controls
1115  self.lfile= self.MakeLabel(_("Georeferenced file:"))
1116  self.tfile = self.MakeTextCtrl(size = (300,-1))
1117  self.bbrowse = self.MakeButton(_("Browse"))
1118 
1119  # do layout
1120  self.sizer.Add(item = self.lfile, flag = wx.ALIGN_LEFT |
1121  wx.ALIGN_CENTRE_VERTICAL |
1122  wx.ALL, border = 5, pos = (1, 1))
1123  self.sizer.Add(item = self.tfile, flag = wx.ALIGN_LEFT |
1124  wx.ALIGN_CENTRE_VERTICAL |
1125  wx.ALL, border = 5, pos = (1, 2))
1126  self.sizer.Add(item = self.bbrowse, flag = wx.ALIGN_LEFT |
1127  wx.ALL, border = 5, pos = (1, 3))
1128  self.sizer.AddGrowableCol(3)
1129 
1130  self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse)
1131  self.tfile.Bind(wx.EVT_TEXT, self.OnText)
1132  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1133  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
1134 
1135  # do page layout
1136  # self.DoLayout()
1137 
1138  def OnEnterPage(self, event):
1139  if len(self.georeffile) == 0:
1140  # disable 'next' button by default
1141  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
1142  else:
1143  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
1144 
1145  event.Skip()
1146 
1147  def OnPageChanging(self, event):
1148  if event.GetDirection() and not os.path.isfile(self.georeffile):
1149  event.Veto()
1150  self.GetNext().SetPrev(self)
1151 
1152  event.Skip()
1153 
1154  def OnText(self, event):
1155  """!File changed"""
1156  self.georeffile = event.GetString()
1157  nextButton = wx.FindWindowById(wx.ID_FORWARD)
1158  if len(self.georeffile) > 0 and os.path.isfile(self.georeffile):
1159  if not nextButton.IsEnabled():
1160  nextButton.Enable(True)
1161  else:
1162  if nextButton.IsEnabled():
1163  nextButton.Enable(False)
1164 
1165  event.Skip()
1166 
1167  def OnBrowse(self, event):
1168  """!Choose file"""
1169  dlg = wx.FileDialog(self,
1170  _("Select georeferenced file"),
1171  os.getcwd(), "", "*.*", wx.OPEN)
1172  if dlg.ShowModal() == wx.ID_OK:
1173  path = dlg.GetPath()
1174  self.tfile.SetValue(path)
1175  dlg.Destroy()
1176 
1177  event.Skip()
1178 
1180  """!Wizard page for selecting WKT file to use
1181  for setting coordinate system parameters"""
1182 
1183  def __init__(self, wizard, parent):
1184  TitledPage.__init__(self, wizard, _("Select Well Known Text (WKT) .prj file"))
1185 
1186  self.wktfile = ''
1187 
1188  # create controls
1189  self.lfile= self.MakeLabel(_("WKT .prj file:"))
1190  self.tfile = self.MakeTextCtrl(size = (300,-1))
1191  self.bbrowse = self.MakeButton(_("Browse"))
1192 
1193  # do layout
1194  self.sizer.Add(item = self.lfile, flag = wx.ALIGN_LEFT |
1195  wx.ALIGN_CENTRE_VERTICAL |
1196  wx.ALL, border = 5, pos = (1, 1))
1197  self.sizer.Add(item = self.tfile, flag = wx.ALIGN_LEFT |
1198  wx.ALIGN_CENTRE_VERTICAL |
1199  wx.ALL, border = 5, pos = (1, 2))
1200  self.sizer.Add(item = self.bbrowse, flag = wx.ALIGN_LEFT |
1201  wx.ALL, border = 5, pos = (1, 3))
1202  self.sizer.AddGrowableCol(3)
1203 
1204  self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse)
1205  self.tfile.Bind(wx.EVT_TEXT, self.OnText)
1206  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1207  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
1208 
1209  def OnEnterPage(self, event):
1210  if len(self.wktfile) == 0:
1211  # disable 'next' button by default
1212  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
1213  else:
1214  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
1215 
1216  event.Skip()
1217 
1218  def OnPageChanging(self, event):
1219  if event.GetDirection() and not os.path.isfile(self.wktfile):
1220  event.Veto()
1221  self.GetNext().SetPrev(self)
1222 
1223  event.Skip()
1224 
1225  def OnText(self, event):
1226  """!File changed"""
1227  self.wktfile = event.GetString()
1228  nextButton = wx.FindWindowById(wx.ID_FORWARD)
1229  if len(self.wktfile) > 0 and os.path.isfile(self.wktfile):
1230  if not nextButton.IsEnabled():
1231  nextButton.Enable(True)
1232  else:
1233  if nextButton.IsEnabled():
1234  nextButton.Enable(False)
1235 
1236  event.Skip()
1237 
1238  def OnBrowse(self, event):
1239  """!Choose file"""
1240  dlg = wx.FileDialog(self,
1241  message = _("Select Well Known Text (WKT) .prj file"),
1242  defaultDir = os.getcwd(),
1243  wildcard = "PRJ files (*.prj)|*.prj|Files (*.*)|*.*",
1244  style = wx.OPEN)
1245 
1246  if dlg.ShowModal() == wx.ID_OK:
1247  path = dlg.GetPath()
1248  self.tfile.SetValue(path)
1249  dlg.Destroy()
1250 
1251  event.Skip()
1252 
1254  """!Wizard page for selecting EPSG code for
1255  setting coordinate system parameters"""
1256 
1257  def __init__(self, wizard, parent):
1258  TitledPage.__init__(self, wizard, _("Choose EPSG Code"))
1259  self.parent = parent
1260  self.epsgCodeDict = {}
1261  self.epsgcode = None
1262  self.epsgdesc = ''
1263  self.epsgparams = ''
1264 
1265  # labels
1266  self.lfile = self.MakeLabel(_("Path to the EPSG-codes file:"),
1267  style = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
1268  self.lcode = self.MakeLabel(_("EPSG code:"),
1269  style = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
1270  # text input
1271  epsgdir = utils.PathJoin(os.environ["GRASS_PROJSHARE"], 'epsg')
1272  self.tfile = self.MakeTextCtrl(text = epsgdir, size = (200,-1),
1273  style = wx.TE_PROCESS_ENTER)
1274  self.tcode = self.MakeTextCtrl(size = (200,-1))
1275 
1276  # buttons
1277  self.bbrowse = self.MakeButton(_("Browse"))
1278 
1279  # search box
1280  self.searchb = wx.SearchCtrl(self, size = (200,-1),
1281  style = wx.TE_PROCESS_ENTER)
1282 
1283  self.epsglist = ItemList(self, data = None,
1284  columns = [_('Code'), _('Description'), _('Parameters')])
1285 
1286  # layout
1287  self.sizer.Add(item = self.lfile,
1288  flag = wx.ALIGN_LEFT |
1289  wx.ALIGN_CENTER_VERTICAL |
1290  wx.ALL, border = 5, pos = (1, 1), span = (1, 2))
1291  self.sizer.Add(item = self.tfile,
1292  flag = wx.ALIGN_LEFT |
1293  wx.ALIGN_CENTER_VERTICAL |
1294  wx.ALL, border = 5, pos = (1, 3))
1295  self.sizer.Add(item = self.bbrowse,
1296  flag = wx.ALIGN_LEFT |
1297  wx.ALIGN_CENTER_VERTICAL |
1298  wx.ALL, border = 5, pos = (1, 4))
1299  self.sizer.Add(item = self.lcode,
1300  flag = wx.ALIGN_LEFT |
1301  wx.ALIGN_CENTER_VERTICAL |
1302  wx.ALL, border = 5, pos = (2, 1), span = (1, 2))
1303  self.sizer.Add(item = self.tcode,
1304  flag = wx.ALIGN_LEFT |
1305  wx.ALIGN_CENTER_VERTICAL |
1306  wx.ALL, border = 5, pos = (2, 3))
1307  self.sizer.Add(item = self.searchb,
1308  flag = wx.ALIGN_LEFT |
1309  wx.ALIGN_CENTER_VERTICAL |
1310  wx.ALL, border = 5, pos = (3, 3))
1311 
1312  self.sizer.Add(item = self.epsglist,
1313  flag = wx.ALIGN_LEFT | wx.EXPAND, pos = (4, 1),
1314  span = (1, 4))
1315  self.sizer.AddGrowableCol(3)
1316  self.sizer.AddGrowableRow(4)
1317 
1318  # events
1319  self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse)
1320  self.tfile.Bind(wx.EVT_TEXT_ENTER, self.OnBrowseCodes)
1321  self.tcode.Bind(wx.EVT_TEXT, self.OnText)
1322  self.tcode.Bind(wx.EVT_TEXT_ENTER, self.OnText)
1323  self.epsglist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
1324  self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnSearch)
1325  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1326  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
1327 
1328  def OnEnterPage(self, event):
1329  self.parent.datumtrans = None
1330  if event.GetDirection():
1331  if not self.epsgcode:
1332  # disable 'next' button by default
1333  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
1334  else:
1335  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
1336 
1337  # load default epsg database file
1338  self.OnBrowseCodes(None)
1339 
1340  event.Skip()
1341 
1342  def OnPageChanging(self, event):
1343  if event.GetDirection():
1344  if not self.epsgcode:
1345  event.Veto()
1346  return
1347  else:
1348  # check for datum transforms
1349  ret = RunCommand('g.proj',
1350  read = True,
1351  epsg = self.epsgcode,
1352  datumtrans = '-1',
1353  flags = 't')
1354 
1355  if ret != '':
1356  dtrans = ''
1357  # open a dialog to select datum transform number
1358  dlg = SelectTransformDialog(self.parent.parent, transforms = ret)
1359 
1360  if dlg.ShowModal() == wx.ID_OK:
1361  dtrans = dlg.GetTransform()
1362  if dtrans == '':
1363  dlg.Destroy()
1364  event.Veto()
1365  return 'Datum transform is required.'
1366  else:
1367  dlg.Destroy()
1368  event.Veto()
1369  return 'Datum transform is required.'
1370 
1371  self.parent.datumtrans = dtrans
1372  self.GetNext().SetPrev(self)
1373 
1374  def OnText(self, event):
1375  self.epsgcode = event.GetString()
1376  try:
1377  self.epsgcode = int(self.epsgcode)
1378  except:
1379  self.epsgcode = None
1380 
1381  nextButton = wx.FindWindowById(wx.ID_FORWARD)
1382 
1383  if self.epsgcode and self.epsgcode in self.epsgCodeDict.keys():
1384  self.epsgdesc = self.epsgCodeDict[self.epsgcode][0]
1385  self.epsgparams = self.epsgCodeDict[self.epsgcode][1]
1386  if not nextButton.IsEnabled():
1387  nextButton.Enable(True)
1388  else:
1389  self.epsgcode = None # not found
1390  if nextButton.IsEnabled():
1391  nextButton.Enable(False)
1392  self.epsgdesc = self.epsgparams = ''
1393 
1394  def OnSearch(self, event):
1395  value = self.searchb.GetValue()
1396 
1397  if value == '':
1398  self.epsgcode = None
1399  self.epsgdesc = self.epsgparams = ''
1400  self.tcode.SetValue('')
1401  self.searchb.SetValue('')
1402  self.OnBrowseCodes(None)
1403  else:
1404  try:
1405  self.epsgcode, self.epsgdesc, self.epsgparams = \
1406  self.epsglist.Search(index=[0,1,2], pattern=value)
1407  except (IndexError, ValueError): # -> no item found
1408  self.epsgcode = None
1409  self.epsgdesc = self.epsgparams = ''
1410  self.tcode.SetValue('')
1411  self.searchb.SetValue('')
1412 
1413  event.Skip()
1414 
1415  def OnBrowse(self, event):
1416  """!Define path for EPSG code file"""
1417  path = os.path.dirname(self.tfile.GetValue())
1418  if not path:
1419  path = os.getcwd()
1420 
1421  dlg = wx.FileDialog(parent = self, message = _("Choose EPSG codes file"),
1422  defaultDir = path, defaultFile = "", wildcard = "*", style = wx.OPEN)
1423 
1424  if dlg.ShowModal() == wx.ID_OK:
1425  path = dlg.GetPath()
1426  self.tfile.SetValue(path)
1427  self.OnBrowseCodes(None)
1428 
1429  dlg.Destroy()
1430 
1431  event.Skip()
1432 
1433  def OnItemSelected(self, event):
1434  """!EPSG code selected from the list"""
1435  index = event.m_itemIndex
1436  item = event.GetItem()
1437 
1438  self.epsgcode = int(self.epsglist.GetItem(index, 0).GetText())
1439  self.epsgdesc = self.epsglist.GetItem(index, 1).GetText()
1440  self.tcode.SetValue(str(self.epsgcode))
1441 
1442  event.Skip()
1443 
1444  def OnBrowseCodes(self, event, search = None):
1445  """!Browse EPSG codes"""
1446  self.epsgCodeDict = utils.ReadEpsgCodes(self.tfile.GetValue())
1447 
1448  if type(self.epsgCodeDict) != dict:
1449  wx.MessageBox(parent = self,
1450  message = _("Unable to read EPGS codes: %s") % self.epsgCodeDict,
1451  caption = _("Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
1452  self.epsglist.Populate(list(), update = True)
1453  return
1454 
1455  data = list()
1456  for code, val in self.epsgCodeDict.iteritems():
1457  if code is not None:
1458  data.append((code, val[0], val[1]))
1459 
1460  self.epsglist.Populate(data, update = True)
1461 
1463  """!Wizard page for entering custom PROJ.4 string
1464  for setting coordinate system parameters"""
1465 
1466  def __init__(self, wizard, parent):
1467  TitledPage.__init__(self, wizard,
1468  _("Choose method of specifying georeferencing parameters"))
1469  global coordsys
1470  self.customstring = ''
1471  self.parent = parent
1472 
1473  # widgets
1474  self.text_proj4string = self.MakeTextCtrl(size = (400, 200),
1475  style = wx.TE_MULTILINE)
1476  self.label_proj4string = self.MakeLabel(_("Enter PROJ.4 parameters string:"))
1477 
1478  # layout
1479  self.sizer.Add(self.label_proj4string,
1480  flag = wx.ALIGN_LEFT | wx.ALL,
1481  border = 5, pos = (1, 1))
1482  self.sizer.Add(self.text_proj4string,
1483  flag = wx.ALIGN_LEFT | wx.ALL | wx.EXPAND,
1484  border = 5, pos = (2, 1), span = (1, 2))
1485  self.sizer.AddGrowableRow(2)
1486  self.sizer.AddGrowableCol(2)
1487 
1488  self.text_proj4string.Bind(wx.EVT_TEXT, self.GetProjstring)
1489  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1490  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
1491 
1492  def OnEnterPage(self, event):
1493  if len(self.customstring) == 0:
1494  # disable 'next' button by default
1495  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
1496  else:
1497  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
1498 
1499  def OnPageChanging(self, event):
1500  if event.GetDirection():
1502 
1503  if self.customstring.find('+datum=') < 0:
1504  self.GetNext().SetPrev(self)
1505  return
1506 
1507  # check for datum tranforms
1508  # FIXME: -t flag is a hack-around for trac bug #1849
1509  ret, out, err = RunCommand('g.proj',
1510  read = True, getErrorMsg = True,
1511  proj4 = self.customstring,
1512  datumtrans = '-1',
1513  flags = 't')
1514  if ret != 0:
1515  wx.MessageBox(parent = self,
1516  message = err,
1517  caption = _("Error"),
1518  style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
1519  event.Veto()
1520  return
1521 
1522  if out:
1523  dtrans = ''
1524  # open a dialog to select datum transform number
1525  dlg = SelectTransformDialog(self.parent.parent, transforms = out)
1526  if dlg.ShowModal() == wx.ID_OK:
1527  dtrans = dlg.GetTransform()
1528  if dtrans == '':
1529  dlg.Destroy()
1530  event.Veto()
1531  return _('Datum transform is required.')
1532  else:
1533  dlg.Destroy()
1534  event.Veto()
1535  return _('Datum transform is required.')
1536 
1537  self.parent.datumtrans = dtrans
1538 
1539  # prepare +nadgrids or +towgs84 terms for Summary page. first convert them:
1540  ret, projlabel, err = RunCommand('g.proj',
1541  flags = 'jft',
1542  proj4 = self.customstring,
1543  datumtrans = dtrans,
1544  getErrorMsg = True,
1545  read = True)
1546  # splitting on space alone would break for grid files with space in pathname
1547  for projterm in projlabel.split(' +'):
1548  if projterm.find("towgs84=") != -1 or projterm.find("nadgrids=") != -1:
1549  self.custom_dtrans_string = ' +%s' % projterm
1550  break
1551 
1552  self.GetNext().SetPrev(self)
1553 
1554  def GetProjstring(self, event):
1555  """!Change proj string"""
1556  # TODO: check PROJ.4 syntax
1557  self.customstring = event.GetString()
1558  nextButton = wx.FindWindowById(wx.ID_FORWARD)
1559  if len(self.customstring) == 0:
1560  if nextButton.IsEnabled():
1561  nextButton.Enable(False)
1562  else:
1563  if not nextButton.IsEnabled():
1564  nextButton.Enable()
1565 
1567  """!Shows summary result of choosing coordinate system parameters
1568  prior to creating location"""
1569  def __init__(self, wizard, parent):
1570  TitledPage.__init__(self, wizard, _("Summary"))
1571  self.parent = parent
1572 
1573  self.panelTitle = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY)
1574  self.panelProj4string = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY)
1575  self.panelProj = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY)
1576 
1577  # labels
1578  self.ldatabase = self.MakeLabel()
1579  self.llocation = self.MakeLabel()
1580  self.llocTitle = self.MakeLabel(parent = self.panelTitle)
1581  self.lprojection = self.MakeLabel(parent = self.panelProj)
1582  self.lproj4string = self.MakeLabel(parent = self.panelProj4string)
1583 
1584  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
1585 
1586  # do sub-page layout
1587  self._doLayout()
1588 
1589  def _doLayout(self):
1590  """!Do page layout"""
1591 
1592  titleSizer = wx.BoxSizer(wx.VERTICAL)
1593  titleSizer.Add(item = self.llocTitle, proportion = 1,
1594  flag = wx.EXPAND | wx.ALL, border = 5)
1595  self.panelTitle.SetSizer(titleSizer)
1596 
1597  projSizer = wx.BoxSizer(wx.VERTICAL)
1598  projSizer.Add(item = self.lprojection, proportion = 1,
1599  flag = wx.EXPAND | wx.ALL, border = 5)
1600  self.panelProj.SetSizer(projSizer)
1601 
1602  proj4stringSizer = wx.BoxSizer(wx.VERTICAL)
1603  proj4stringSizer.Add(item = self.lproj4string, proportion = 1,
1604  flag = wx.EXPAND | wx.ALL, border = 5)
1605  self.panelProj4string.SetSizer(proj4stringSizer)
1606 
1607  self.panelProj4string.SetupScrolling()
1608  self.panelProj.SetupScrolling(scroll_y = False)
1609  self.panelTitle.SetupScrolling(scroll_y = False)
1610 
1611  self.sizer.Add(item = self.MakeLabel(_("GRASS Database:")),
1612  flag = wx.ALIGN_LEFT | wx.ALL,
1613  border = 5, pos = (1, 0))
1614  self.sizer.Add(item = self.ldatabase,
1615  flag = wx.ALIGN_LEFT | wx.ALL,
1616  border = 5, pos = (1, 1))
1617  self.sizer.Add(item = self.MakeLabel(_("Location Name:")),
1618  flag = wx.ALIGN_LEFT | wx.ALL,
1619  border = 5, pos = (2, 0))
1620  self.sizer.Add(item = self.llocation,
1621  flag = wx.ALIGN_LEFT | wx.ALL,
1622  border = 5, pos = (2, 1))
1623  self.sizer.Add(item = self.MakeLabel(_("Location Title:")),
1624  flag = wx.ALIGN_LEFT | wx.ALL,
1625  border = 5, pos = (3, 0))
1626  self.sizer.Add(item = self.panelTitle,
1627  flag = wx.ALIGN_LEFT | wx.ALL | wx.EXPAND,
1628  border = 0, pos = (3, 1))
1629  self.sizer.Add(item = self.MakeLabel(_("Projection:")),
1630  flag = wx.ALIGN_LEFT | wx.ALL,
1631  border = 5, pos = (4, 0))
1632  self.sizer.Add(item = self.panelProj,
1633  flag = wx.ALIGN_LEFT | wx.ALL | wx.EXPAND,
1634  border = 0, pos = (4, 1))
1635  self.sizer.Add(item = self.MakeLabel(_("PROJ.4 definition:\n (non-definitive)")),
1636  flag = wx.ALIGN_LEFT | wx.ALL,
1637  border = 5, pos = (5, 0))
1638  self.sizer.Add(item = self.panelProj4string,
1639  flag = wx.ALIGN_LEFT | wx.ALL | wx.EXPAND,
1640  border = 0, pos = (5, 1))
1641  self.sizer.AddGrowableCol(1)
1642  self.sizer.AddGrowableRow(3, 1)
1643  self.sizer.AddGrowableRow(4, 1)
1644  self.sizer.AddGrowableRow(5, 5)
1645 
1646  def OnEnterPage(self, event):
1647  """!Insert values into text controls for summary of location
1648  creation options
1649  """
1650  database = self.parent.startpage.grassdatabase
1651  location = self.parent.startpage.location
1652  proj4string = self.parent.CreateProj4String()
1653  epsgcode = self.parent.epsgpage.epsgcode
1654  datum = self.parent.datumpage.datum
1655  dtrans = self.parent.datumtrans
1656 
1657  global coordsys
1658 
1659  if coordsys in ('proj', 'epsg', 'wkt', 'file'):
1660  extra_opts = {}
1661  extra_opts['location'] = 'location'
1662  extra_opts['getErrorMsg'] = True
1663  extra_opts['read'] = True
1664 
1665  if coordsys == 'proj':
1666  addl_opts = {}
1667  if len(datum) > 0:
1668  extra_opts['datum'] = '%s' % datum
1669  extra_opts['datumtrans'] = dtrans
1670 
1671  ret, projlabel, err = RunCommand('g.proj',
1672  flags = 'jf',
1673  proj4 = proj4string,
1674  **extra_opts)
1675  elif coordsys == 'epsg':
1676  ret, projlabel, err = RunCommand('g.proj',
1677  flags = 'jft',
1678  epsg = epsgcode,
1679  datumtrans = dtrans,
1680  **extra_opts)
1681  elif coordsys == 'file':
1682  ret, projlabel, err = RunCommand('g.proj',
1683  flags = 'jft',
1684  georef = self.parent.filepage.georeffile,
1685  **extra_opts)
1686  elif coordsys == 'wkt':
1687  ret, projlabel, err = RunCommand('g.proj',
1688  flags = 'jft',
1689  wkt = self.parent.wktpage.wktfile,
1690  **extra_opts)
1691 
1692  finishButton = wx.FindWindowById(wx.ID_FORWARD)
1693  if ret == 0:
1694  if datum != '':
1695  projlabel = projlabel + '+datum=%s' % datum
1696  self.lproj4string.SetLabel(projlabel.replace(' +', os.linesep + '+'))
1697  finishButton.Enable(True)
1698  else:
1699  GError(err, parent = self)
1700  self.lproj4string.SetLabel('')
1701  finishButton.Enable(False)
1702 
1703  projdesc = self.parent.projpage.projdesc
1704  ellipsedesc = self.parent.ellipsepage.ellipsedesc
1705  datumdesc = self.parent.datumpage.datumdesc
1706  self.ldatabase.SetLabel(database)
1707  self.llocation.SetLabel(location)
1708  self.llocTitle.SetLabel(self.parent.startpage.locTitle)
1709 
1710  label = ''
1711  if coordsys == 'epsg':
1712  label = 'EPSG code %s (%s)' % (self.parent.epsgpage.epsgcode,
1713  self.parent.epsgpage.epsgdesc)
1714 
1715  elif coordsys == 'file':
1716  label = 'matches file %s' % self.parent.filepage.georeffile
1717 
1718  elif coordsys == 'wkt':
1719  label = 'matches file %s' % self.parent.wktpage.wktfile
1720 
1721  elif coordsys == 'proj':
1722  label = ('%s, %s %s' % (projdesc, datumdesc, ellipsedesc))
1723 
1724  elif coordsys == 'xy':
1725  label = ('XY coordinate system (not projected).')
1726  self.lproj4string.SetLabel("")
1727 
1728  elif coordsys == 'custom':
1729  label = _("custom")
1730  combo_str = self.parent.custompage.customstring + \
1731  self.parent.custompage.custom_dtrans_string
1732  self.lproj4string.SetLabel(('%s' % combo_str.replace(' +', os.linesep + '+')))
1733 
1734  self.lprojection.SetLabel(label)
1735 
1736 
1737  def OnFinish(self, event):
1738  dlg = wx.MessageDialog(parent = self.wizard,
1739  message = _("Do you want to create GRASS location <%s>?") % location,
1740  caption = _("Create new location?"),
1741  style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
1742 
1743  if dlg.ShowModal() == wx.ID_NO:
1744  dlg.Destroy()
1745  event.Veto()
1746  else:
1747  dlg.Destroy()
1748  event.Skip()
1749 
1750 class LocationWizard(wx.Object):
1751  """!Start wizard here and finish wizard here
1752  """
1753  def __init__(self, parent, grassdatabase):
1754  self.__cleanUp()
1755 
1756  global coordsys
1757  self.parent = parent
1758 
1759  #
1760  # define wizard image
1761  #
1762  imagePath = os.path.join(globalvar.ETCIMGDIR, "loc_wizard_qgis.png")
1763  wizbmp = wx.Image(imagePath, wx.BITMAP_TYPE_PNG)
1764  wizbmp = wizbmp.ConvertToBitmap()
1765 
1766  #
1767  # get georeferencing information from tables in $GISBASE/etc
1768  #
1769  self.__readData()
1770 
1771  #
1772  # datum transform number and list of datum transforms
1773  #
1774  self.datumtrans = None
1775  self.proj4string = ''
1776 
1777  # file from which new location is created
1778  self.georeffile = None
1779 
1780  #
1781  # define wizard pages
1782  #
1783  self.wizard = WizardWithHelpButton(parent, id = wx.ID_ANY,
1784  title = _("Define new GRASS Location"),
1785  bitmap = wizbmp)
1786  self.wizard.Bind(wiz.EVT_WIZARD_HELP, self.OnHelp)
1787 
1788  self.startpage = DatabasePage(self.wizard, self, grassdatabase)
1790  self.projpage = ProjectionsPage(self.wizard, self)
1791  self.datumpage = DatumPage(self.wizard, self)
1793  self.epsgpage = EPSGPage(self.wizard, self)
1795  self.wktpage = WKTPage(self.wizard, self)
1796  self.ellipsepage = EllipsePage(self.wizard, self)
1797  self.custompage = CustomPage(self.wizard, self)
1798  self.sumpage = SummaryPage(self.wizard, self)
1799 
1800  #
1801  # set the initial order of the pages
1802  # (should follow the epsg line)
1803  #
1804  self.startpage.SetNext(self.csystemspage)
1805 
1806  self.csystemspage.SetPrev(self.startpage)
1807  self.csystemspage.SetNext(self.sumpage)
1808 
1809  self.projpage.SetPrev(self.csystemspage)
1810  self.projpage.SetNext(self.paramspage)
1811 
1812  self.paramspage.SetPrev(self.projpage)
1813  self.paramspage.SetNext(self.datumpage)
1814 
1815  self.datumpage.SetPrev(self.paramspage)
1816  self.datumpage.SetNext(self.sumpage)
1817 
1818  self.ellipsepage.SetPrev(self.paramspage)
1819  self.ellipsepage.SetNext(self.sumpage)
1820 
1821  self.epsgpage.SetPrev(self.csystemspage)
1822  self.epsgpage.SetNext(self.sumpage)
1823 
1824  self.filepage.SetPrev(self.csystemspage)
1825  self.filepage.SetNext(self.sumpage)
1826 
1827  self.wktpage.SetPrev(self.csystemspage)
1828  self.wktpage.SetNext(self.sumpage)
1829 
1830  self.custompage.SetPrev(self.csystemspage)
1831  self.custompage.SetNext(self.sumpage)
1832 
1833  self.sumpage.SetPrev(self.csystemspage)
1834 
1835  #
1836  # do pages layout
1837  #
1838  self.startpage.DoLayout()
1839  self.csystemspage.DoLayout()
1840  self.projpage.DoLayout()
1841  self.datumpage.DoLayout()
1842  self.paramspage.DoLayout()
1843  self.epsgpage.DoLayout()
1844  self.filepage.DoLayout()
1845  self.wktpage.DoLayout()
1846  self.ellipsepage.DoLayout()
1847  self.custompage.DoLayout()
1848  self.sumpage.DoLayout()
1849  self.wizard.FitToPage(self.datumpage)
1850  size = self.wizard.GetPageSize()
1851  self.wizard.SetPageSize((size[0], size[1] + 75))
1852 
1853  # new location created?
1854  self.location = None
1855  success = False
1856 
1857  # location created in different GIS database?
1858  self.altdb = False
1859 
1860  #
1861  # run wizard...
1862  #
1863  if self.wizard.RunWizard(self.startpage):
1864  msg = self.OnWizFinished()
1865  if not msg:
1866  self.wizard.Destroy()
1867  self.location = self.startpage.location
1868  self.grassdatabase = self.startpage.grassdatabase
1869  self.georeffile = self.filepage.georeffile
1870  # FIXME here was code for setting default region, what for is this if:
1871  # if self.altdb == False:
1872 
1873  else: # -> error
1874  self.wizard.Destroy()
1875  GError(parent = self.parent,
1876  message = "%s" % _("Unable to create new location. "
1877  "Location <%(loc)s> not created.\n\n"
1878  "Details: %(err)s") % \
1879  { 'loc' : self.startpage.location,
1880  'err' : msg })
1881  else: # -> canceled
1882  self.wizard.Destroy()
1883  GMessage(parent = self.parent,
1884  message = _("Location wizard canceled. "
1885  "Location not created."))
1886 
1887  self.__cleanUp()
1888 
1889  def __cleanUp(self):
1890  global coordsys
1891  global north
1892  global south
1893  global east
1894  global west
1895  global resolution
1896  global wizerror
1897  global translist
1898 
1899  coordsys = None
1900  north = None
1901  south = None
1902  east = None
1903  west = None
1904  resolution = None
1905  transformlist = list()
1906 
1907  def __readData(self):
1908  """!Get georeferencing information from tables in $GISBASE/etc"""
1909 
1910  # read projection and parameters
1911  f = open(os.path.join(globalvar.ETCDIR, "proj-parms.table"), "r")
1912  self.projections = {}
1913  self.projdesc = {}
1914  for line in f.readlines():
1915  line = line.strip()
1916  try:
1917  proj, projdesc, params = line.split(':')
1918  paramslist = params.split(';')
1919  plist = []
1920  for p in paramslist:
1921  if p == '': continue
1922  p1, pdefault = p.split(',')
1923  pterm, pask = p1.split('=')
1924  p = [pterm.strip(), pask.strip(), pdefault.strip()]
1925  plist.append(p)
1926  self.projections[proj.lower().strip()] = (projdesc.strip(), plist)
1927  self.projdesc[proj.lower().strip()] = projdesc.strip()
1928  except:
1929  continue
1930  f.close()
1931 
1932  # read datum definitions
1933  f = open(os.path.join(globalvar.ETCDIR, "datum.table"), "r")
1934  self.datums = {}
1935  paramslist = []
1936  for line in f.readlines():
1937  line = line.expandtabs(1)
1938  line = line.strip()
1939  if line == '' or line[0] == "#":
1940  continue
1941  datum, info = line.split(" ", 1)
1942  info = info.strip()
1943  datumdesc, params = info.split(" ", 1)
1944  datumdesc = datumdesc.strip('"')
1945  paramlist = params.split()
1946  ellipsoid = paramlist.pop(0)
1947  self.datums[datum] = (ellipsoid, datumdesc.replace('_', ' '), paramlist)
1948  f.close()
1949 
1950  # read ellipsiod definitions
1951  f = open(os.path.join(globalvar.ETCDIR, "ellipse.table"), "r")
1952  self.ellipsoids = {}
1953  for line in f.readlines():
1954  line = line.expandtabs(1)
1955  line = line.strip()
1956  if line == '' or line[0] == "#":
1957  continue
1958  ellipse, rest = line.split(" ", 1)
1959  rest = rest.strip('" ')
1960  desc, params = rest.split('"', 1)
1961  desc = desc.strip('" ')
1962  paramslist = params.split()
1963  self.ellipsoids[ellipse] = (desc, paramslist)
1964  f.close()
1965 
1966  # read projection parameter description and parsing table
1967  f = open(os.path.join(globalvar.ETCDIR, "proj-desc.table"), "r")
1968  self.paramdesc = {}
1969  for line in f.readlines():
1970  line = line.strip()
1971  try:
1972  pparam, datatype, proj4term, desc = line.split(':')
1973  self.paramdesc[pparam] = (datatype, proj4term, desc)
1974  except:
1975  continue
1976  f.close()
1977 
1978  def OnWizFinished(self):
1979  """!Wizard finished, create new location
1980 
1981  @return error message on error
1982  @return None on success
1983  """
1984  database = self.startpage.grassdatabase
1985  location = self.startpage.location
1986 
1987  # location already exists?
1988  if os.path.isdir(os.path.join(database,location)):
1989  GError(parent = self.wizard,
1990  message = "%s <%s>: %s" % \
1991  (_("Unable to create new location"),
1992  os.path.join(database, location),
1993  _("Location already exists in GRASS Database.")))
1994  return None
1995 
1996  # current GISDbase or a new one?
1997  current_gdb = grass.gisenv()['GISDBASE']
1998  if current_gdb != database:
1999  # change to new GISDbase or create new one
2000  if os.path.isdir(database) != True:
2001  # create new directory
2002  os.mkdir(database)
2003 
2004  # change to new GISDbase directory
2005  RunCommand('g.gisenv',
2006  parent = self.wizard,
2007  set = 'GISDBASE=%s' % database)
2008 
2009  wx.MessageBox(parent = self.wizard,
2010  message = _("Location <%(loc)s> will be created "
2011  "in GIS data directory <%(dir)s>. "
2012  "You will need to change the default GIS "
2013  "data directory in the GRASS startup screen.") % \
2014  { 'loc' : location, 'dir' : database},
2015  caption = _("New GIS data directory"),
2016  style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
2017 
2018  # location created in alternate GISDbase
2019  self.altdb = True
2020 
2021  global coordsys
2022  try:
2023  if coordsys == "xy":
2024  grass.create_location(dbase = self.startpage.grassdatabase,
2025  location = self.startpage.location,
2026  desc = self.startpage.locTitle)
2027  elif coordsys == "proj":
2028  grass.create_location(dbase = self.startpage.grassdatabase,
2029  location = self.startpage.location,
2030  proj4 = self.CreateProj4String(),
2031  datum = self.datumpage.datum,
2032  datumtrans = self.datumtrans,
2033  desc = self.startpage.locTitle)
2034  elif coordsys == 'custom':
2035  addl_opts = {}
2036  if self.datumtrans is not None:
2037  addl_opts['datumtrans'] = self.datumtrans
2038 
2039  grass.create_location(dbase = self.startpage.grassdatabase,
2040  location = self.startpage.location,
2041  proj4 = self.custompage.customstring,
2042  desc = self.startpage.locTitle,
2043  **addl_opts)
2044  elif coordsys == "epsg":
2045  if not self.epsgpage.epsgcode:
2046  return _('EPSG code missing.')
2047 
2048  grass.create_location(dbase = self.startpage.grassdatabase,
2049  location = self.startpage.location,
2050  epsg = self.epsgpage.epsgcode,
2051  datum = self.datumpage.datum,
2052  datumtrans = self.datumtrans,
2053  desc = self.startpage.locTitle)
2054  elif coordsys == "file":
2055  if not self.filepage.georeffile or \
2056  not os.path.isfile(self.filepage.georeffile):
2057  return _("File <%s> not found." % self.filepage.georeffile)
2058 
2059  grass.create_location(dbase = self.startpage.grassdatabase,
2060  location = self.startpage.location,
2061  filename = self.filepage.georeffile,
2062  desc = self.startpage.locTitle)
2063  elif coordsys == "wkt":
2064  if not self.wktpage.wktfile or \
2065  not os.path.isfile(self.wktpage.wktfile):
2066  return _("File <%s> not found." % self.wktpage.wktfile)
2067 
2068  grass.create_location(dbase = self.startpage.grassdatabase,
2069  location = self.startpage.location,
2070  wkt = self.wktpage.wktfile,
2071  desc = self.startpage.locTitle)
2072 
2073  except grass.ScriptError, e:
2074  return e.value
2075 
2076  return None
2077 
2079  """!Constract PROJ.4 string"""
2080  location = self.startpage.location
2081  proj = self.projpage.p4proj
2082  projdesc = self.projpage.projdesc
2083  proj4params = self.paramspage.p4projparams
2084 
2085 # datum = self.datumpage.datum
2086  if self.datumpage.datumdesc:
2087  datumdesc = self.datumpage.datumdesc +' - ' + self.datumpage.ellipse
2088  else:
2089  datumdesc = ''
2090  datumparams = self.datumpage.datumparams
2091  ellipse = self.ellipsepage.ellipse
2092  ellipsedesc = self.ellipsepage.ellipsedesc
2093  ellipseparams = self.ellipsepage.ellipseparams
2094 
2095  #
2096  # creating PROJ.4 string
2097  #
2098  proj4string = '%s %s' % (proj, proj4params)
2099 
2100  # set ellipsoid parameters
2101  if ellipse != '':
2102  proj4string = '%s +ellps=%s' % (proj4string, ellipse)
2103  for item in ellipseparams:
2104  if item[:4] == 'f=1/':
2105  item = ' +rf=' + item[4:]
2106  else:
2107  item = ' +' + item
2108  proj4string = '%s %s' % (proj4string, item)
2109 
2110  # set datum transform parameters if relevant
2111  if datumparams:
2112  for item in datumparams:
2113  proj4string = '%s +%s' % (proj4string,item)
2114 
2115  proj4string = '%s +no_defs' % proj4string
2116 
2117  return proj4string
2118 
2119  def OnHelp(self, event):
2120  """'Help' button clicked"""
2121  # help text in lib/init/helptext.html
2122  import webbrowser
2123  filePath = os.path.join(os.getenv('GISBASE'), "docs", "html", "helptext.html")
2124  webbrowser.open(filePath)
2125 
2126 
2127 class WizardWithHelpButton(wiz.Wizard):
2128  def __init__(self, parent, id, title, bitmap):
2129  pre = wiz.PreWizard()
2130  pre.SetExtraStyle(wx.wizard.WIZARD_EX_HELPBUTTON)
2131  pre.Create(parent = parent, id = id, title = title, bitmap = bitmap)
2132  self.PostCreate(pre)
Wizard page for selecting ellipsoid (select coordinate system option)
Definition: wizard.py:989
wxGUI command interface
Wizard page for selecting projection (select coordinate system option)
Definition: wizard.py:331
def SetVal
Choose method.
Definition: wizard.py:303
Wizard page for setting GIS data directory and location name.
Definition: wizard.py:91
Location wizard - dialogs.
def OnPageChanging
Definition: wizard.py:1342
Generic list (for projections, ellipsoids, etc.)
Definition: wizard.py:444
def OnItemSelected
Projection selected.
Definition: wizard.py:432
def OnEnterPage
Definition: wizard.py:1209
Core GUI widgets.
def OnChangeName
Name for new location was changed.
Definition: wizard.py:164
def _nameValidationFailed
Definition: wizard.py:158
Wizard page for selecting datum (with associated ellipsoid) and datum transformation parameters (sele...
Definition: wizard.py:822
def CreateProj4String
Constract PROJ.4 string.
Definition: wizard.py:2078
def OnPageChange
Go to next page.
Definition: wizard.py:708
def SortItems
Sort items.
Definition: wizard.py:573
Wizard page for selecting georeferenced file to use for setting coordinate system parameters...
Definition: wizard.py:1105
def OnWizFinished
Wizard finished, create new location.
Definition: wizard.py:1978
def OnBrowse
Choose file.
Definition: wizard.py:1167
Wizard page for selecting EPSG code for setting coordinate system parameters.
Definition: wizard.py:1253
Location wizard - base classes.
def OnText
File changed.
Definition: wizard.py:1154
def OnPageChanging
Definition: wizard.py:1218
def OnBrowse
Choose file.
Definition: wizard.py:1238
Shows summary result of choosing coordinate system parameters prior to creating location.
Definition: wizard.py:1566
def OnEnterPage
Insert values into text controls for summary of location creation options.
Definition: wizard.py:1646
def OnItemSelected
EPSG code selected from the list.
Definition: wizard.py:1433
def OnSearch
Search ellipsoid by desc.
Definition: wizard.py:1084
def OnEnterPage
Page entered.
Definition: wizard.py:727
def SetVal
Set value.
Definition: wizard.py:813
def OnDSearch
Search geodetic datum by desc.
Definition: wizard.py:969
Start wizard here and finish wizard here.
Definition: wizard.py:1750
def GetSortImages
Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py.
Definition: wizard.py:555
def OnText
Projection name changed.
Definition: wizard.py:388
Wizard page for entering custom PROJ.4 string for setting coordinate system parameters.
Definition: wizard.py:1462
def OnBrowse
Define path for EPSG code file.
Definition: wizard.py:1415
def ReadEpsgCodes
Read EPSG code from the file.
Definition: core/utils.py:560
def OnItemSelected
Ellipsoid selected.
Definition: wizard.py:1095
def OnText
Ellipspoid code changed.
Definition: wizard.py:1070
def OnDatumSelected
Datum selected.
Definition: wizard.py:979
def OnParamEntry
Parameter value changed.
Definition: wizard.py:683
Help window.
def OnPageChanging
Definition: wizard.py:890
def GetProjstring
Change proj string.
Definition: wizard.py:1554
Class to make wizard pages.
Definition: wizard.py:60
Wizard page for selecting WKT file to use for setting coordinate system parameters.
Definition: wizard.py:1179
def GetListCtrl
Used by listmix.ColumnSorterMixin.
Definition: wizard.py:604
def OnGetItemText
Get item text.
Definition: wizard.py:559
def OnGetItemAttr
Get item attributes.
Definition: wizard.py:565
def PathJoin
Check path created by os.path.join.
Definition: core/utils.py:551
def OnSearch
Search projection by desc.
Definition: wizard.py:422
Wizard page for selecting method of setting coordinate system parameters (select coordinate system op...
Definition: wizard.py:635
Wizard page for choosing method for location creation.
Definition: wizard.py:209
def OnBrowse
Choose GRASS data directory.
Definition: wizard.py:175
def OnBrowseCodes
Browse EPSG codes.
Definition: wizard.py:1444
tuple range
Definition: tools.py:1406
def Populate
Populate list.
Definition: wizard.py:506
def Search
Search projection by description Return first found item or None.
Definition: wizard.py:608
def OnText
File changed.
Definition: wizard.py:1225
def _doLayout
Do page layout.
Definition: wizard.py:1589
def OnColumnClick
Sort by column.
Definition: wizard.py:540
def OnDText
Datum code changed.
Definition: wizard.py:940
def __readData
Get georeferencing information from tables in $GISBASE/etc.
Definition: wizard.py:1907
def DoLayout
Do page layout.
Definition: wizard.py:76
def RunCommand
Run GRASS command.
Definition: gcmd.py:625