GRASS Programmer's Manual  6.4.2(2012)
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
location_wizard.py
Go to the documentation of this file.
1 """!
2 @package location_wizard.py
3 
4 @brief Location wizard - creates a new GRASS Location. User can choose
5 from multiple methods.
6 
7 Classes:
8  - BaseClass
9  - TitledPage
10  - DatabasePage
11  - CoordinateSystemPage
12  - ProjectionsPage
13  - ItemList
14  - ProjParamsPage
15  - DatumPage
16  - EllipsePage
17  - GeoreferencedFilePage
18  - EPSGPage
19  - CustomPage
20  - SummaryPage
21  - RegionDef
22  - LocationWizard
23  - SelectTransformDialog
24 
25 (C) 2007-2011 by the GRASS Development Team
26 
27 This program is free software under the GNU General Public License
28 (>=v2). Read the file COPYING that comes with GRASS for details.
29 
30 @author Michael Barton
31 @author Jachym Cepicky
32 @author Martin Landa <landa.martin gmail.com>
33 """
34 import os
35 import shutil
36 import string
37 import sys
38 import locale
39 import platform
40 
41 import wx
42 import wx.lib.mixins.listctrl as listmix
43 import wx.wizard as wiz
44 import wx.lib.scrolledpanel as scrolled
45 import time
46 
47 import gcmd
48 import globalvar
49 import utils
50 from grass.script import core as grass
51 try:
52  import subprocess
53 except:
54  CompatPath = os.path.join(globalvar.ETCWXDIR)
55  sys.path.append(CompatPath)
56  from compat import subprocess
57 
58 global coordsys
59 global north
60 global south
61 global east
62 global west
63 global resolution
64 global wizerror
65 global translist
66 
67 class BaseClass(wx.Object):
68  """!Base class providing basic methods"""
69  def __init__(self):
70  pass
71 
72  def MakeLabel(self, text = "", style = wx.ALIGN_LEFT, parent = None):
73  """!Make aligned label"""
74  if not parent:
75  parent = self
76  return wx.StaticText(parent = parent, id = wx.ID_ANY, label = text,
77  style = style)
78 
79  def MakeTextCtrl(self, text = '', size = (100,-1), style = 0, parent = None):
80  """!Generic text control"""
81  if not parent:
82  parent = self
83  return wx.TextCtrl(parent = parent, id = wx.ID_ANY, value = text,
84  size = size, style = style)
85 
86  def MakeButton(self, text, id = wx.ID_ANY, size = (-1,-1), parent = None):
87  """!Generic button"""
88  if not parent:
89  parent = self
90  return wx.Button(parent = parent, id = id, label = text,
91  size = size)
92 
93 class TitledPage(BaseClass, wiz.WizardPageSimple):
94  """!Class to make wizard pages. Generic methods to make labels,
95  text entries, and buttons.
96  """
97  def __init__(self, parent, title):
98 
99  self.page = wiz.WizardPageSimple.__init__(self, parent)
100 
101  # page title
102  self.title = wx.StaticText(parent = self, id = wx.ID_ANY, label = title)
103  self.title.SetFont(wx.Font(13, wx.SWISS, wx.NORMAL, wx.BOLD))
104 
105  # main sizers
106  self.pagesizer = wx.BoxSizer(wx.VERTICAL)
107  self.sizer = wx.GridBagSizer(vgap = 0, hgap = 0)
108 
109  def DoLayout(self):
110  """!Do page layout"""
111  self.pagesizer.Add(item = self.title, proportion = 0,
112  flag = wx.ALIGN_CENTRE | wx.ALL,
113  border = 5)
114  self.pagesizer.Add(item = wx.StaticLine(self, -1), proportion = 0,
115  flag = wx.EXPAND | wx.ALL,
116  border = 0)
117  self.pagesizer.Add(item = self.sizer, proportion = 1,
118  flag = wx.EXPAND)
119 
120  self.SetAutoLayout(True)
121  self.SetSizer(self.pagesizer)
122  self.Layout()
123 
125  """!Wizard page for setting GIS data directory and location name"""
126  def __init__(self, wizard, parent, grassdatabase):
127  TitledPage.__init__(self, wizard, _("Define GRASS Database and Location Name"))
128 
129  self.grassdatabase = grassdatabase
130  self.location = ''
131  self.locTitle = ''
132 
133  # buttons
134  self.bbrowse = self.MakeButton(_("Browse"))
135 
136  # text controls
137  self.tgisdbase = self.MakeTextCtrl(grassdatabase, size = (300, -1))
138  self.tlocation = self.MakeTextCtrl("newLocation", size = (300, -1))
139  self.tlocTitle = self.MakeTextCtrl(size = (400, -1))
140 
141  # layout
142  self.sizer.AddGrowableCol(3)
143  self.sizer.Add(item = self.MakeLabel(_("GIS Data Directory:")),
144  flag = wx.ALIGN_RIGHT |
145  wx.ALIGN_CENTER_VERTICAL |
146  wx.ALL, border = 5,
147  pos = (1, 1))
148  self.sizer.Add(item = self.tgisdbase,
149  flag = wx.ALIGN_LEFT |
150  wx.ALIGN_CENTER_VERTICAL |
151  wx.ALL, border = 5,
152  pos = (1, 2))
153  self.sizer.Add(item = self.bbrowse,
154  flag = wx.ALIGN_LEFT |
155  wx.ALIGN_CENTER_VERTICAL |
156  wx.ALL, border = 5,
157  pos = (1, 3))
158 
159  self.sizer.Add(item = self.MakeLabel("%s:" % _("Project Location")),
160  flag = wx.ALIGN_RIGHT |
161  wx.ALIGN_CENTER_VERTICAL |
162  wx.ALL, border = 5,
163  pos = (2, 1))
164  self.sizer.Add(item = self.tlocation,
165  flag = wx.ALIGN_LEFT |
166  wx.ALIGN_CENTER_VERTICAL |
167  wx.ALL, border = 5,
168  pos = (2, 2))
169 
170  self.sizer.Add(item = self.MakeLabel("%s:" % _("Location Title")),
171  flag = wx.ALIGN_RIGHT |
172  wx.ALIGN_TOP | wx.ALIGN_CENTER_VERTICAL |
173  wx.ALL, border = 5,
174  pos = (3, 1))
175  self.sizer.Add(item = self.tlocTitle,
176  flag = wx.ALIGN_LEFT |
177  wx.ALIGN_CENTER_VERTICAL |
178  wx.ALL, border = 5,
179  pos = (3, 2), span = (1, 2))
180 
181  # bindings
182  self.Bind(wx.EVT_BUTTON, self.OnBrowse, self.bbrowse)
183  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
184  self.tgisdbase.Bind(wx.EVT_TEXT, self.OnChangeName)
185  self.tlocation.Bind(wx.EVT_TEXT, self.OnChangeName)
186 
187  def OnChangeName(self, event):
188  """!Name for new location was changed"""
189  nextButton = wx.FindWindowById(wx.ID_FORWARD)
190  if len(event.GetString()) > 0:
191  if not nextButton.IsEnabled():
192  nextButton.Enable()
193  else:
194  nextButton.Disable()
195 
196  event.Skip()
197 
198  def OnBrowse(self, event):
199  """!Choose GRASS data directory"""
200  dlg = wx.DirDialog(self, _("Choose GRASS data directory:"),
201  os.getcwd(), wx.DD_DEFAULT_STYLE)
202  if dlg.ShowModal() == wx.ID_OK:
203  self.grassdatabase = dlg.GetPath()
204  self.tgisdbase.SetValue(self.grassdatabase)
205 
206  dlg.Destroy()
207 
208  def OnPageChanging(self, event = None):
209  error = None
210  if os.path.isdir(os.path.join(self.tgisdbase.GetValue(), self.tlocation.GetValue())):
211  error = _("Location already exists in GRASS Database.")
212 
213  if error:
214  gcmd.GError(parent = self,
215  message="%s <%s>.%s%s" % (_("Unable to create location"),
216  str(self.tlocation.GetValue()),
217  os.linesep,
218  error))
219  event.Veto()
220  return
221 
222  self.location = self.tlocation.GetValue()
223  self.grassdatabase = self.tgisdbase.GetValue()
224  self.locTitle = self.tlocTitle.GetValue()
225  if os.linesep in self.locTitle or \
226  len(self.locTitle) > 255:
227  gcmd.GWarning(parent = self,
228  message = _("Title of the location is limited only to one line and "
229  "256 characters. The rest of the text will be ignored."))
230  self.locTitle = self.locTitle.split(os.linesep)[0][:255]
231 
233  """!Wizard page for choosing method for location creation"""
234  def __init__(self, wizard, parent):
235  TitledPage.__init__(self, wizard, _("Choose method for creating a new location"))
236 
237  self.parent = parent
238  global coordsys
239 
240  # toggles
241  self.radio1 = wx.RadioButton(parent = self, id = wx.ID_ANY,
242  label = _("Select coordinate system parameters from a list"),
243  style = wx.RB_GROUP)
244  self.radio2 = wx.RadioButton(parent = self, id = wx.ID_ANY,
245  label = _("Select EPSG code of spatial reference system"))
246  self.radio3 = wx.RadioButton(parent = self, id = wx.ID_ANY,
247  label = _("Read projection and datum terms from a "
248  "georeferenced data file"))
249  self.radio4 = wx.RadioButton(parent = self, id = wx.ID_ANY,
250  label = _("Read projection and datum terms from a "
251  "WKT or PRJ file"))
252  self.radio5 = wx.RadioButton(parent = self, id = wx.ID_ANY,
253  label = _("Specify projection and datum terms using custom "
254  "PROJ.4 parameters"))
255  self.radio6 = wx.RadioButton(parent = self, id = wx.ID_ANY,
256  label = _("Create an arbitrary non-earth coordinate system (XY)"))
257 
258  # layout
259  self.sizer.AddGrowableCol(1)
260  self.sizer.SetVGap(10)
261  self.sizer.Add(item = self.radio1,
262  flag = wx.ALIGN_LEFT, pos = (1, 1))
263  self.sizer.Add(item = self.radio2,
264  flag = wx.ALIGN_LEFT, pos = (2, 1))
265  self.sizer.Add(item = self.radio3,
266  flag = wx.ALIGN_LEFT, pos = (3, 1))
267  self.sizer.Add(item = self.radio4,
268  flag = wx.ALIGN_LEFT, pos = (4, 1))
269  self.sizer.Add(item = self.radio5,
270  flag = wx.ALIGN_LEFT, pos = (5, 1))
271  self.sizer.Add(item = self.radio6,
272  flag = wx.ALIGN_LEFT, pos = (6, 1))
273 
274  # bindings
275  self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio1.GetId())
276  self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio2.GetId())
277  self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio3.GetId())
278  self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio4.GetId())
279  self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio5.GetId())
280  self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio6.GetId())
281  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
282 
283  def OnEnterPage(self, event):
284  global coordsys
285 
286  if not coordsys:
287  coordsys = "proj"
288  self.radio1.SetValue(True)
289  else:
290  if coordsys == 'proj':
291  self.radio1.SetValue(True)
292  if coordsys == "epsg":
293  self.radio2.SetValue(True)
294  if coordsys == "file":
295  self.radio3.SetValue(True)
296  if coordsys == "wkt":
297  self.radio4.SetValue(True)
298  if coordsys == "custom":
299  self.radio5.SetValue(True)
300  if coordsys == "xy":
301  self.radio6.SetValue(True)
302 
303  if event.GetDirection():
304  if coordsys == 'proj':
305  self.SetNext(self.parent.projpage)
306  self.parent.sumpage.SetPrev(self.parent.datumpage)
307  if coordsys == "epsg":
308  self.SetNext(self.parent.epsgpage)
309  self.parent.sumpage.SetPrev(self.parent.epsgpage)
310  if coordsys == "file":
311  self.SetNext(self.parent.filepage)
312  self.parent.sumpage.SetPrev(self.parent.filepage)
313  if coordsys == "wkt":
314  self.SetNext(self.parent.wktpage)
315  self.parent.sumpage.SetPrev(self.parent.wktpage)
316  if coordsys == "custom":
317  self.SetNext(self.parent.custompage)
318  self.parent.sumpage.SetPrev(self.parent.custompage)
319  if coordsys == "xy":
320  self.SetNext(self.parent.sumpage)
321  self.parent.sumpage.SetPrev(self.parent.csystemspage)
322 
323  if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled():
324  wx.FindWindowById(wx.ID_FORWARD).Enable()
325 
326  def SetVal(self, event):
327  """!Choose method"""
328  global coordsys
329  if event.GetId() == self.radio1.GetId():
330  coordsys = "proj"
331  self.SetNext(self.parent.projpage)
332  self.parent.sumpage.SetPrev(self.parent.datumpage)
333  elif event.GetId() == self.radio2.GetId():
334  coordsys = "epsg"
335  self.SetNext(self.parent.epsgpage)
336  self.parent.sumpage.SetPrev(self.parent.epsgpage)
337  elif event.GetId() == self.radio3.GetId():
338  coordsys = "file"
339  self.SetNext(self.parent.filepage)
340  self.parent.sumpage.SetPrev(self.parent.filepage)
341  elif event.GetId() == self.radio4.GetId():
342  coordsys = "wkt"
343  self.SetNext(self.parent.wktpage)
344  self.parent.sumpage.SetPrev(self.parent.wktpage)
345  elif event.GetId() == self.radio5.GetId():
346  coordsys = "custom"
347  self.SetNext(self.parent.custompage)
348  self.parent.sumpage.SetPrev(self.parent.custompage)
349  elif event.GetId() == self.radio6.GetId():
350  coordsys = "xy"
351  self.SetNext(self.parent.sumpage)
352  self.parent.sumpage.SetPrev(self.parent.csystemspage)
353 
355  """!Wizard page for selecting projection (select coordinate system option)"""
356  def __init__(self, wizard, parent):
357  TitledPage.__init__(self, wizard, _("Choose projection"))
358 
359  self.parent = parent
360  self.proj = ''
361  self.projdesc = ''
362  self.p4proj = ''
363 
364  # text input
365  self.tproj = self.MakeTextCtrl("", size = (200,-1))
366 
367  # search box
368  self.searchb = wx.SearchCtrl(self, size = (200,-1),
369  style = wx.TE_PROCESS_ENTER)
370 
371  # projection list
372  self.projlist = ItemList(self, data = self.parent.projdesc.items(),
373  columns = [_('Code'), _('Description')])
374  self.projlist.resizeLastColumn(30)
375 
376  # layout
377  self.sizer.AddGrowableCol(3)
378  self.sizer.Add(item = self.MakeLabel(_("Projection code:")),
379  flag = wx.ALIGN_LEFT |
380  wx.ALIGN_CENTER_VERTICAL |
381  wx.ALL, border = 5, pos = (1, 1))
382  self.sizer.Add(item = self.tproj,
383  flag = wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL,
384  border = 5, pos = (1, 2))
385 
386  self.sizer.Add(item = self.MakeLabel(_("Search in description:")),
387  flag = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.ALL,
388  border = 5, pos = (2, 1))
389  self.sizer.Add(item = self.searchb,
390  flag = wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL,
391  border = 5, pos = (2, 2))
392 
393  self.sizer.AddGrowableRow(3)
394  self.sizer.Add(item = self.projlist,
395  flag = wx.EXPAND |
396  wx.ALIGN_LEFT |
397  wx.ALL, border = 5, pos = (3, 1), span = (1, 3))
398 
399  # events
400  self.tproj.Bind(wx.EVT_TEXT, self.OnText)
401  self.tproj.Bind(wx.EVT_TEXT_ENTER, self.OnText)
402  self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnSearch)
403  self.projlist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
404  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
405  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
406 
407  def OnPageChanging(self,event):
408  if event.GetDirection() and self.proj not in self.parent.projections.keys():
409  event.Veto()
410 
411  def OnText(self, event):
412  """!Projection name changed"""
413  self.proj = event.GetString().lower()
414  self.p4proj = ''
415  nextButton = wx.FindWindowById(wx.ID_FORWARD)
416  if self.proj not in self.parent.projections.keys() and nextButton.IsEnabled():
417  nextButton.Enable(False)
418 
419  if self.proj in self.parent.projections.keys():
420  if self.proj == 'stp':
421  wx.MessageBox('Currently State Plane projections must be selected using the '
422  'text-based setup (g.setproj), or entered by EPSG code or '
423  'custom PROJ.4 terms.',
424  'Warning', wx.ICON_WARNING)
425  self.proj = ''
426  self.tproj.SetValue(self.proj)
427  nextButton.Enable(False)
428  return
429  elif self.proj.lower() == 'll':
430  self.p4proj = '+proj=longlat'
431  else:
432  self.p4proj = '+proj=' + self.proj.lower()
433  self.projdesc = self.parent.projections[self.proj][0]
434  nextButton.Enable()
435 
436  def OnEnterPage(self, event):
437  if len(self.proj) == 0:
438  # disable 'next' button by default
439  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
440  else:
441  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
442 
443  event.Skip()
444 
445  def OnSearch(self, event):
446  """!Search projection by desc"""
447  str = event.GetString()
448  try:
449  self.proj, self.projdesc = self.projlist.Search(index = [0,1], pattern = event.GetString())
450  except:
451  self.proj = self.projdesc = ''
452 
453  event.Skip()
454 
455  def OnItemSelected(self, event):
456  """!Projection selected"""
457  index = event.m_itemIndex
458 
459  # set values
460  self.proj = self.projlist.GetItem(index, 0).GetText().lower()
461  self.tproj.SetValue(self.proj)
462 
463  event.Skip()
464 
465 class ItemList(wx.ListCtrl,
466  listmix.ListCtrlAutoWidthMixin,
467  listmix.ColumnSorterMixin):
468  """!Generic list (for projections, ellipsoids, etc.)"""
469 
470  def __init__(self, parent, columns, data = None):
471  wx.ListCtrl.__init__(self, parent = parent, id = wx.ID_ANY,
472  style = wx.LC_REPORT |
473  wx.LC_VIRTUAL |
474  wx.LC_HRULES |
475  wx.LC_VRULES |
476  wx.LC_SINGLE_SEL |
477  wx.LC_SORT_ASCENDING, size = (550, 125))
478 
479  # original data or None
480  self.sourceData = data
481 
482  #
483  # insert columns
484  #
485  i = 0
486  for column in columns:
487  self.InsertColumn(i, column)
488  i += 1
489 
490  if self.sourceData:
491  self.Populate()
492 
493  for i in range(self.GetColumnCount()):
494  self.SetColumnWidth(i, wx.LIST_AUTOSIZE_USEHEADER)
495  if self.GetColumnWidth(i) < 80:
496  self.SetColumnWidth(i, 80)
497 
498  #
499  # listmix
500  #
501  listmix.ListCtrlAutoWidthMixin.__init__(self)
502  listmix.ColumnSorterMixin.__init__(self, self.GetColumnCount())
503 
504  #
505  # add some attributes
506  #
507  self.attr1 = wx.ListItemAttr()
508  self.attr1.SetBackgroundColour(wx.Colour(238,238,238))
509  self.attr2 = wx.ListItemAttr()
510  self.attr2.SetBackgroundColour("white")
511  self.il = wx.ImageList(16, 16)
512  self.sm_up = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_GO_UP, wx.ART_TOOLBAR,
513  (16,16)))
514  self.sm_dn = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_GO_DOWN, wx.ART_TOOLBAR,
515  (16,16)))
516  self.SetImageList(self.il, wx.IMAGE_LIST_SMALL)
517 
518  #
519  # sort by first column
520  #
521  if self.sourceData:
522  self.SortListItems(col = 0, ascending = True)
523 
524  #
525  # bindings
526  #
527  self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColumnClick)
528 
529  def Populate(self, data = None, update = False):
530  """!Populate list"""
531  self.itemDataMap = {}
532  self.itemIndexMap = []
533 
534  if data is None:
535  data = self.sourceData
536  elif update:
537  self.sourceData = data
538 
539  try:
540  data.sort()
541  self.DeleteAllItems()
542  row = 0
543  for value in data:
544  self.itemDataMap[row] = [value[0]]
545  for i in range(1, len(value)):
546  self.itemDataMap[row].append(value[i])
547  self.itemIndexMap.append(row)
548  row += 1
549 
550  self.SetItemCount(row)
551 
552  # set column width
553  self.SetColumnWidth(0, 80)
554  self.SetColumnWidth(1, 300)
555 
556  self.SendSizeEvent()
557 
558  except StandardError, e:
559  wx.MessageBox(parent = self,
560  message = _("Unable to read list: %s") % e,
561  caption = _("Error"), style = wx.OK | wx.ICON_ERROR)
562 
563  def OnColumnClick(self, event):
564  """!Sort by column"""
565  self._col = event.GetColumn()
566 
567  # remove duplicated arrow symbol from column header
568  # FIXME: should be done automatically
569  info = wx.ListItem()
570  info.m_mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE
571  info.m_image = -1
572  for column in range(self.GetColumnCount()):
573  info.m_text = self.GetColumn(column).GetText()
574  self.SetColumn(column, info)
575 
576  event.Skip()
577 
578  def GetSortImages(self):
579  """!Used by the ColumnSorterMixin, see wx/lib/mixins/listctrl.py"""
580  return (self.sm_dn, self.sm_up)
581 
582  def OnGetItemText(self, item, col):
583  """!Get item text"""
584  index = self.itemIndexMap[item]
585  s = str(self.itemDataMap[index][col])
586  return s
587 
588  def OnGetItemAttr(self, item):
589  """!Get item attributes"""
590  index = self.itemIndexMap[item]
591  if ( index % 2) == 0:
592  return self.attr2
593  else:
594  return self.attr1
595 
596  def SortItems(self, sorter = cmp):
597  """!Sort items"""
598  items = list(self.itemDataMap.keys())
599  items.sort(self.Sorter)
600  self.itemIndexMap = items
601 
602  # redraw the list
603  self.Refresh()
604 
605  def Sorter(self, key1, key2):
606  colName = self.GetColumn(self._col).GetText()
607  ascending = self._colSortFlag[self._col]
608  # convert always string
609  item1 = self.itemDataMap[key1][self._col]
610  item2 = self.itemDataMap[key2][self._col]
611 
612  if type(item1) == type('') or type(item2) == type(''):
613  cmpVal = locale.strcoll(str(item1), str(item2))
614  else:
615  cmpVal = cmp(item1, item2)
616 
617 
618  # If the items are equal then pick something else to make the sort value unique
619  if cmpVal == 0:
620  cmpVal = apply(cmp, self.GetSecondarySortValues(self._col, key1, key2))
621 
622  if ascending:
623  return cmpVal
624  else:
625  return -cmpVal
626 
627  def GetListCtrl(self):
628  """!Used by listmix.ColumnSorterMixin"""
629  return self
630 
631  def Search (self, index, pattern):
632  """!Search projection by description
633  Return first found item or None
634  """
635  if pattern == '':
636  self.Populate(self.sourceData)
637  return []
638 
639  data = []
640  pattern = pattern.lower()
641  for i in range(len(self.sourceData)):
642  for idx in index:
643  try:
644  value = str(self.sourceData[i][idx]).lower()
645  if pattern in value:
646  data.append(self.sourceData[i])
647  break
648  except UnicodeDecodeError:
649  # osgeo4w problem (should be fixed)
650  pass
651 
652  self.Populate(data)
653  if len(data) > 0:
654  return data[0]
655  else:
656  return []
657 
659  """!Wizard page for selecting method of setting coordinate system
660  parameters (select coordinate system option)
661  """
662  def __init__(self, wizard, parent):
663  TitledPage.__init__(self, wizard, _("Choose projection parameters"))
664  global coordsys
665 
666  self.parent = parent
667  self.panel = None
668  self.prjParamSizer = None
669 
670  self.pparam = dict()
671 
672  self.p4projparams = ''
673  self.projdesc = ''
674 
675  self.sizer.AddGrowableCol(1)
676  self.sizer.AddGrowableRow(1)
677 
678  radioSBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
679  label = " %s " % _("Select datum or ellipsoid (next page)"))
680  radioSBSizer = wx.StaticBoxSizer(radioSBox)
681  self.sizer.Add(item = radioSBSizer, pos = (0, 1),
682  flag = wx.EXPAND | wx.ALIGN_TOP | wx.TOP, border = 10)
683 
684  self.radio1 = wx.RadioButton(parent = self, id = wx.ID_ANY,
685  label = _("Datum with associated ellipsoid"),
686  style = wx.RB_GROUP)
687  self.radio2 = wx.RadioButton(parent = self, id = wx.ID_ANY,
688  label = _("Ellipsoid only"))
689 
690  # default button setting
691  if self.radio1.GetValue() == False and self.radio2.GetValue() == False:
692  self.radio1.SetValue(True)
693  self.SetNext(self.parent.datumpage)
694  # self.parent.sumpage.SetPrev(self.parent.datumpage)
695 
696  radioSBSizer.Add(item = self.radio1,
697  flag = wx.ALIGN_LEFT | wx.RIGHT, border = 20)
698  radioSBSizer.Add(item = self.radio2,
699  flag = wx.ALIGN_LEFT)
700 
701  # bindings
702  self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio1.GetId())
703  self.Bind(wx.EVT_RADIOBUTTON, self.SetVal, id = self.radio2.GetId())
704  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChange)
705  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
706 
707  def OnParamEntry(self, event):
708  """!Parameter value changed"""
709  id = event.GetId()
710  val = event.GetString()
711 
712  if id not in self.pparam:
713  event.Skip()
714  return
715 
716  param = self.pparam[id]
717  win = self.FindWindowById(id)
718  if param['type'] == 'zone':
719  val = event.GetInt()
720  if val < 1:
721  win.SetValue(1)
722  elif val > 60:
723  win.SetValue(60)
724 
725  if param['type'] == 'bool':
726  param['value'] = event.GetSelection()
727  else:
728  param['value'] = val
729 
730  event.Skip()
731 
732  def OnPageChange(self,event=None):
733  """!Go to next page"""
734  if event.GetDirection():
735  self.p4projparams = ''
736  for id, param in self.pparam.iteritems():
737  if param['type'] == 'bool':
738  if param['value'] == False:
739  continue
740  else:
741  self.p4projparams += (' +' + param['proj4'])
742  else:
743  if param['value'] is None:
744  wx.MessageBox(parent = self,
745  message = _('You must enter a value for %s') % param['desc'],
746  caption = _('Error'), style = wx.ICON_ERROR | wx.CENTRE)
747  event.Veto()
748  else:
749  self.p4projparams += (' +' + param['proj4'] + '=' + str(param['value']))
750 
751  def OnEnterPage(self,event):
752  """!Page entered"""
753  self.projdesc = self.parent.projections[self.parent.projpage.proj][0]
754  if self.prjParamSizer is None:
755  # entering page for the first time
756  self.paramSBox = wx.StaticBox(parent = self, id = wx.ID_ANY,
757  label = _(" Enter parameters for %s projection ") % self.projdesc)
758  paramSBSizer = wx.StaticBoxSizer(self.paramSBox)
759 
760  self.panel = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY)
761  self.panel.SetupScrolling()
762 
763  self.prjParamSizer = wx.GridBagSizer(vgap = 0, hgap = 0)
764 
765  self.sizer.Add(item = paramSBSizer, pos = (1, 1),
766  flag = wx.EXPAND)
767  paramSBSizer.Add(item = self.panel, proportion = 1,
768  flag = wx.ALIGN_CENTER | wx.EXPAND)
769 
770  paramSBSizer.Fit(self.panel)
771  self.panel.SetSizer(self.prjParamSizer)
772 
773  if event.GetDirection():
774  self.prjParamSizer.Clear(True)
775  self.paramSBox.SetLabel(_(" Enter parameters for %s projection ") % self.projdesc)
776  self.pparam = dict()
777  row = 0
778  for paramgrp in self.parent.projections[self.parent.projpage.proj][1]:
779  # get parameters
780  id = wx.NewId()
781  param = self.pparam[id] = { 'type' : self.parent.paramdesc[paramgrp[0]][0],
782  'proj4': self.parent.paramdesc[paramgrp[0]][1],
783  'desc' : self.parent.paramdesc[paramgrp[0]][2] }
784 
785  # default values
786  if param['type'] == 'bool':
787  param['value'] = 0
788  elif param['type'] == 'zone':
789  param['value'] = 30
790  param['desc'] += ' (1-60)'
791  else:
792  param['value'] = paramgrp[2]
793 
794  label = wx.StaticText(parent = self.panel, id = wx.ID_ANY, label = param['desc'],
795  style = wx.ALIGN_RIGHT | wx.ST_NO_AUTORESIZE)
796  if param['type'] == 'bool':
797  win = wx.Choice(parent = self.panel, id = id, size = (100,-1),
798  choices = [_('No'), _('Yes')])
799  win.SetSelection(param['value'])
800  win.Bind(wx.EVT_CHOICE, self.OnParamEntry)
801  elif param['type'] == 'zone':
802  win = wx.SpinCtrl(parent = self.panel, id = id,
803  size = (100, -1),
804  style = wx.SP_ARROW_KEYS | wx.SP_WRAP,
805  min = 1, max = 60)
806  win.SetValue(param['value'])
807  win.Bind(wx.EVT_SPINCTRL, self.OnParamEntry)
808  win.Bind(wx.EVT_TEXT, self.OnParamEntry)
809  else:
810  win = wx.TextCtrl(parent = self.panel, id = id,
811  value = param['value'],
812  size=(100, -1))
813  win.Bind(wx.EVT_TEXT, self.OnParamEntry)
814  if paramgrp[1] == 'noask':
815  win.Enable(False)
816 
817  self.prjParamSizer.Add(item = label, pos = (row, 1),
818  flag = wx.ALIGN_RIGHT |
819  wx.ALIGN_CENTER_VERTICAL |
820  wx.RIGHT, border = 5)
821  self.prjParamSizer.Add(item = win, pos = (row, 2),
822  flag = wx.ALIGN_LEFT |
823  wx.ALIGN_CENTER_VERTICAL |
824  wx.LEFT, border = 5)
825  row += 1
826 
827  self.panel.SetSize(self.panel.GetBestSize())
828  self.panel.Layout()
829  self.Layout()
830  self.Update()
831 
832  if not wx.FindWindowById(wx.ID_FORWARD).IsEnabled():
833  wx.FindWindowById(wx.ID_FORWARD).Enable()
834 
835  event.Skip()
836 
837  def SetVal(self, event):
838  """!Set value"""
839  if event.GetId() == self.radio1.GetId():
840  self.SetNext(self.parent.datumpage)
841  self.parent.sumpage.SetPrev(self.parent.datumpage)
842  elif event.GetId() == self.radio2.GetId():
843  self.SetNext(self.parent.ellipsepage)
844  self.parent.sumpage.SetPrev(self.parent.ellipsepage)
845 
847  """!Wizard page for selecting datum (with associated ellipsoid)
848  and datum transformation parameters (select coordinate system option)
849  """
850 
851  def __init__(self, wizard, parent):
852  TitledPage.__init__(self, wizard, _("Specify geodetic datum"))
853 
854  self.parent = parent
855  self.datum = ''
856  self.datumdesc = ''
857  self.ellipse = ''
858  self.datumparams = ''
859  self.proj4params = ''
860 
861  # text input
862  self.tdatum = self.MakeTextCtrl("", size = (200,-1))
863 
864  # search box
865  self.searchb = wx.SearchCtrl(self, size = (200,-1),
866  style = wx.TE_PROCESS_ENTER)
867 
868  # create list control for datum/elipsoid list
869  data = []
870  for key in self.parent.datums.keys():
871  data.append([key, self.parent.datums[key][0], self.parent.datums[key][1]])
872  self.datumlist = ItemList(self,
873  data = data,
874  columns = [_('Code'), _('Ellipsoid'), _('Description')])
875  self.datumlist.resizeLastColumn(10)
876 
877  # layout
878  self.sizer.AddGrowableCol(4)
879  self.sizer.Add(item = self.MakeLabel(_("Datum code:")),
880  flag = wx.ALIGN_LEFT |
881  wx.ALIGN_CENTER_VERTICAL |
882  wx.ALL, border = 5, pos = (1, 1))
883  self.sizer.Add(item = self.tdatum,
884  flag = wx.ALIGN_LEFT |
885  wx.ALIGN_CENTER_VERTICAL |
886  wx.ALL, border = 5, pos = (1, 2))
887 
888  self.sizer.Add(item = self.MakeLabel(_("Search in description:")),
889  flag = wx.ALIGN_LEFT |
890  wx.ALIGN_CENTER_VERTICAL |
891  wx.ALL, border = 5, pos = (2, 1))
892  self.sizer.Add(item = self.searchb,
893  flag = wx.ALIGN_LEFT |
894  wx.ALIGN_CENTER_VERTICAL |
895  wx.ALL, border = 5, pos = (2, 2))
896 
897  self.sizer.AddGrowableRow(3)
898  self.sizer.Add(item = self.datumlist,
899  flag = wx.EXPAND |
900  wx.ALIGN_LEFT |
901  wx.ALL, border = 5, pos = (3, 1), span = (1, 4))
902 
903  # events
904  self.datumlist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnDatumSelected)
905  self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnDSearch)
906  self.tdatum.Bind(wx.EVT_TEXT, self.OnDText)
907  self.tdatum.Bind(wx.EVT_TEXT_ENTER, self.OnDText)
908  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
909  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
910 
911  # do page layout
912  # self.DoLayout()
913 
914  def OnPageChanging(self, event):
915  self.proj4params = ''
916  proj = self.parent.projpage.p4proj
917 
918  if event.GetDirection():
919  if self.datum not in self.parent.datums:
920  event.Veto()
921  else:
922  # check for datum tranforms
923 # proj4string = self.parent.CreateProj4String() + ' +datum=%s' % self.datum
924  ret = gcmd.RunCommand('g.proj',
925  read = True,
926  proj4 = '%s +datum=%s' % (proj, self.datum),
927  datumtrans = '-1')
928  if ret != '':
929  dtrans = ''
930  # open a dialog to select datum transform number
931  dlg = SelectTransformDialog(self.parent.parent, transforms=ret)
932 
933  if dlg.ShowModal() == wx.ID_OK:
934  dtrans = dlg.GetTransform()
935  if dtrans == '':
936  dlg.Destroy()
937  event.Veto()
938  return 'Datum transform is required.'
939  else:
940  dlg.Destroy()
941  event.Veto()
942  return 'Datum transform is required.'
943 
944  self.parent.datumtrans = dtrans
945 
946  self.GetNext().SetPrev(self)
947  self.parent.ellipsepage.ellipse = self.ellipse
948  self.parent.ellipsepage.ellipseparams = self.parent.ellipsoids[self.ellipse][1]
949 
950  def OnEnterPage(self,event):
951  self.parent.datumtrans = None
952  if event.GetDirection():
953  if len(self.datum) == 0:
954  # disable 'next' button by default when entering from previous page
955  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
956  else:
957  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
958 
959  event.Skip()
960 
961  def OnDText(self, event):
962  """!Datum code changed"""
963  self.datum = event.GetString()
964 
965  nextButton = wx.FindWindowById(wx.ID_FORWARD)
966  if len(self.datum) == 0 or self.datum not in self.parent.datums:
967  nextButton.Enable(False)
968  else:
969  self.ellipse = self.parent.datums[self.datum][0]
970  self.datumdesc = self.parent.datums[self.datum][1]
971  self.datumparams = self.parent.datums[self.datum][2]
972  try:
973  self.datumparams.remove('dx=0.0')
974  except:
975  pass
976  try:
977  self.datumparams.remove('dy=0.0')
978  except:
979  pass
980  try:
981  self.datumparams.remove('dz=0.0')
982  except:
983  pass
984 
985  nextButton.Enable(True)
986 
987  self.Update()
988  event.Skip()
989 
990  def OnDSearch(self, event):
991  """!Search geodetic datum by desc"""
992  str = self.searchb.GetValue()
993  try:
994  self.datum, self.ellipsoid, self.datumdesc = self.datumlist.Search(index = [0,1,2], pattern = str)
995  except:
996  self.datum = self.datumdesc = self.ellipsoid = ''
997 
998  event.Skip()
999 
1000  def OnDatumSelected(self, event):
1001  """!Datum selected"""
1002  index = event.m_itemIndex
1003  item = event.GetItem()
1004 
1005  self.datum = self.datumlist.GetItem(index, 0).GetText()
1006  self.tdatum.SetValue(self.datum)
1007 
1008  event.Skip()
1009 
1011  """!Wizard page for selecting ellipsoid (select coordinate system option)"""
1012 
1013  def __init__(self, wizard, parent):
1014  TitledPage.__init__(self, wizard, _("Specify ellipsoid"))
1015 
1016  self.parent = parent
1017 
1018  self.ellipse = ''
1019  self.ellipsedesc = ''
1020  self.ellipseparams = ''
1021  self.proj4params = ''
1022 
1023  # text input
1024  self.tellipse = self.MakeTextCtrl("", size = (200,-1))
1025 
1026  # search box
1027  self.searchb = wx.SearchCtrl(self, size = (200,-1),
1028  style = wx.TE_PROCESS_ENTER)
1029 
1030  # create list control for ellipse list
1031  data = []
1032  # extract code, desc
1033  for key in self.parent.ellipsoids.keys():
1034  data.append([key, self.parent.ellipsoids[key][0]])
1035 
1036  self.ellipselist = ItemList(self, data = data,
1037  columns = [_('Code'), _('Description')])
1038  self.ellipselist.resizeLastColumn(30)
1039 
1040  # layout
1041  self.sizer.AddGrowableCol(4)
1042  self.sizer.Add(item = self.MakeLabel(_("Ellipsoid code:")),
1043  flag = wx.ALIGN_RIGHT |
1044  wx.ALIGN_CENTER_VERTICAL |
1045  wx.ALL, border = 5, pos = (1, 1))
1046  self.sizer.Add(item = self.tellipse,
1047  flag = wx.ALIGN_LEFT |
1048  wx.ALIGN_CENTER_VERTICAL |
1049  wx.ALL, border = 5, pos = (1, 2))
1050  self.sizer.Add(item = self.MakeLabel(_("Search in description:")),
1051  flag = wx.ALIGN_RIGHT |
1052  wx.ALIGN_CENTER_VERTICAL |
1053  wx.ALL, border = 5, pos = (2, 1))
1054  self.sizer.Add(item = self.searchb,
1055  flag = wx.ALIGN_LEFT |
1056  wx.ALIGN_CENTER_VERTICAL |
1057  wx.ALL, border = 5, pos = (2, 2))
1058 
1059  self.sizer.AddGrowableRow(3)
1060  self.sizer.Add(item = self.ellipselist,
1061  flag = wx.EXPAND |
1062  wx.ALIGN_LEFT |
1063  wx.ALL, border = 5, pos = (3, 1), span = (1, 4))
1064 
1065  # events
1066  self.ellipselist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
1067  self.tellipse.Bind(wx.EVT_TEXT, self.OnText)
1068  self.tellipse.Bind(wx.EVT_TEXT_ENTER, self.OnText)
1069  self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnSearch)
1070  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
1071  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1072 
1073  def OnEnterPage(self,event):
1074  if len(self.ellipse) == 0:
1075  # disable 'next' button by default
1076  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
1077  else:
1078  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
1079 
1080  event.Skip()
1081 
1082  def OnPageChanging(self, event):
1083  if event.GetDirection() and self.ellipse not in self.parent.ellipsoids:
1084  event.Veto()
1085 
1086  self.proj4params = ''
1087  self.GetNext().SetPrev(self)
1088  self.parent.datumpage.datumparams = ''
1089  # self.GetNext().SetPrev(self) (???)
1090 
1091  def OnText(self, event):
1092  """!Ellipspoid code changed"""
1093  self.ellipse = event.GetString()
1094  nextButton = wx.FindWindowById(wx.ID_FORWARD)
1095  if len(self.ellipse) == 0 or self.ellipse not in self.parent.ellipsoids:
1096  nextButton.Enable(False)
1097  self.ellipsedesc = ''
1098  self.ellipseparams = ''
1099  self.proj4params = ''
1100  elif self.ellipse in self.parent.ellipsoids:
1101  self.ellipsedesc = self.parent.ellipsoids[self.ellipse][0]
1102  self.ellipseparams = self.parent.ellipsoids[self.ellipse][1]
1103  nextButton.Enable(True)
1104 
1105  def OnSearch(self, event):
1106  """!Search ellipsoid by desc"""
1107  try:
1108  self.ellipse, self.ellipsedesc = \
1109  self.ellipselist.Search(index=[0,1], pattern=event.GetString())
1110  self.ellipseparams = self.parent.ellipsoids[self.ellipse][1]
1111  except:
1112  self.ellipse = self.ellipsedesc = self.ellipseparams = ''
1113 
1114  event.Skip()
1115 
1116  def OnItemSelected(self,event):
1117  """!Ellipsoid selected"""
1118  index = event.m_itemIndex
1119  item = event.GetItem()
1120 
1121  self.ellipse = self.ellipselist.GetItem(index, 0).GetText()
1122  self.tellipse.SetValue(self.ellipse)
1123 
1124  event.Skip()
1125 
1127  """!Wizard page for selecting georeferenced file to use
1128  for setting coordinate system parameters"""
1129 
1130  def __init__(self, wizard, parent):
1131  TitledPage.__init__(self, wizard, _("Select georeferenced file"))
1132 
1133  self.georeffile = ''
1134 
1135  # create controls
1136  self.lfile= self.MakeLabel(_("Georeferenced file:"))
1137  self.tfile = self.MakeTextCtrl(size = (300,-1))
1138  self.bbrowse = self.MakeButton(_("Browse"))
1139 
1140  # do layout
1141  self.sizer.AddGrowableCol(3)
1142  self.sizer.Add(item = self.lfile, flag = wx.ALIGN_LEFT |
1143  wx.ALIGN_CENTRE_VERTICAL |
1144  wx.ALL, border = 5, pos = (1, 1))
1145  self.sizer.Add(item = self.tfile, flag = wx.ALIGN_LEFT |
1146  wx.ALIGN_CENTRE_VERTICAL |
1147  wx.ALL, border = 5, pos = (1, 2))
1148  self.sizer.Add(item = self.bbrowse, flag = wx.ALIGN_LEFT |
1149  wx.ALL, border = 5, pos = (1, 3))
1150 
1151  self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse)
1152  self.tfile.Bind(wx.EVT_TEXT, self.OnText)
1153  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1154  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
1155 
1156  # do page layout
1157  # self.DoLayout()
1158 
1159  def OnEnterPage(self, event):
1160  if len(self.georeffile) == 0:
1161  # disable 'next' button by default
1162  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
1163  else:
1164  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
1165 
1166  event.Skip()
1167 
1168  def OnPageChanging(self, event):
1169  if event.GetDirection() and not os.path.isfile(self.georeffile):
1170  event.Veto()
1171  self.GetNext().SetPrev(self)
1172 
1173  event.Skip()
1174 
1175  def OnText(self, event):
1176  """!File changed"""
1177  self.georeffile = event.GetString()
1178  nextButton = wx.FindWindowById(wx.ID_FORWARD)
1179  if len(self.georeffile) > 0 and os.path.isfile(self.georeffile):
1180  if not nextButton.IsEnabled():
1181  nextButton.Enable(True)
1182  else:
1183  if nextButton.IsEnabled():
1184  nextButton.Enable(False)
1185 
1186  event.Skip()
1187 
1188  def OnBrowse(self, event):
1189  """!Choose file"""
1190  dlg = wx.FileDialog(self,
1191  _("Select georeferenced file"),
1192  os.getcwd(), "", "*.*", wx.OPEN)
1193  if dlg.ShowModal() == wx.ID_OK:
1194  path = dlg.GetPath()
1195  self.tfile.SetValue(path)
1196  dlg.Destroy()
1197 
1198  event.Skip()
1199 
1201  """!Wizard page for selecting WKT file to use
1202  for setting coordinate system parameters"""
1203 
1204  def __init__(self, wizard, parent):
1205  TitledPage.__init__(self, wizard, _("Select WKT file"))
1206 
1207  self.wktfile = ''
1208 
1209  # create controls
1210  self.lfile= self.MakeLabel(_("WKT file:"))
1211  self.tfile = self.MakeTextCtrl(size = (300,-1))
1212  self.bbrowse = self.MakeButton(_("Browse"))
1213 
1214  # do layout
1215  self.sizer.AddGrowableCol(3)
1216  self.sizer.Add(item = self.lfile, flag = wx.ALIGN_LEFT |
1217  wx.ALIGN_CENTRE_VERTICAL |
1218  wx.ALL, border = 5, pos = (1, 1))
1219  self.sizer.Add(item = self.tfile, flag = wx.ALIGN_LEFT |
1220  wx.ALIGN_CENTRE_VERTICAL |
1221  wx.ALL, border = 5, pos = (1, 2))
1222  self.sizer.Add(item = self.bbrowse, flag = wx.ALIGN_LEFT |
1223  wx.ALL, border = 5, pos = (1, 3))
1224 
1225  self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse)
1226  self.tfile.Bind(wx.EVT_TEXT, self.OnText)
1227  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1228  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
1229 
1230  def OnEnterPage(self, event):
1231  if len(self.wktfile) == 0:
1232  # disable 'next' button by default
1233  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
1234  else:
1235  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
1236 
1237  event.Skip()
1238 
1239  def OnPageChanging(self, event):
1240  if event.GetDirection() and not os.path.isfile(self.wktfile):
1241  event.Veto()
1242  self.GetNext().SetPrev(self)
1243 
1244  event.Skip()
1245 
1246  def OnText(self, event):
1247  """!File changed"""
1248  self.wktfile = event.GetString()
1249  nextButton = wx.FindWindowById(wx.ID_FORWARD)
1250  if len(self.wktfile) > 0 and os.path.isfile(self.wktfile):
1251  if not nextButton.IsEnabled():
1252  nextButton.Enable(True)
1253  else:
1254  if nextButton.IsEnabled():
1255  nextButton.Enable(False)
1256 
1257  event.Skip()
1258 
1259  def OnBrowse(self, event):
1260  """!Choose file"""
1261  dlg = wx.FileDialog(self,
1262  _("Select WKT file"),
1263  os.getcwd(), "", "*.*", wx.OPEN)
1264  if dlg.ShowModal() == wx.ID_OK:
1265  path = dlg.GetPath()
1266  self.tfile.SetValue(path)
1267  dlg.Destroy()
1268 
1269  event.Skip()
1270 
1272  """!Wizard page for selecting EPSG code for
1273  setting coordinate system parameters"""
1274 
1275  def __init__(self, wizard, parent):
1276  TitledPage.__init__(self, wizard, _("Choose EPSG Code"))
1277  self.parent = parent
1278  self.epsgCodeDict = {}
1279  self.epsgcode = None
1280  self.epsgdesc = ''
1281  self.epsgparams = ''
1282 
1283  # labels
1284  self.lfile = self.MakeLabel(_("Path to the EPSG-codes file:"),
1285  style = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
1286  self.lcode = self.MakeLabel(_("EPSG code:"),
1287  style = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
1288  # text input
1289  epsgdir = utils.PathJoin(os.environ["GRASS_PROJSHARE"], 'epsg')
1290  self.tfile = self.MakeTextCtrl(text = epsgdir, size = (200,-1),
1291  style = wx.TE_PROCESS_ENTER)
1292  self.tcode = self.MakeTextCtrl(size = (200,-1))
1293 
1294  # buttons
1295  self.bbrowse = self.MakeButton(_("Browse"))
1296 
1297  # search box
1298  self.searchb = wx.SearchCtrl(self, size = (200,-1),
1299  style = wx.TE_PROCESS_ENTER)
1300 
1301  self.epsglist = ItemList(self, data = None,
1302  columns = [_('Code'), _('Description'), _('Parameters')])
1303 
1304  # layout
1305  self.sizer.AddGrowableCol(3)
1306  self.sizer.Add(item = self.lfile,
1307  flag = wx.ALIGN_LEFT |
1308  wx.ALIGN_CENTER_VERTICAL |
1309  wx.ALL, border = 5, pos = (1, 1), span = (1, 2))
1310  self.sizer.Add(item = self.tfile,
1311  flag = wx.ALIGN_LEFT |
1312  wx.ALIGN_CENTER_VERTICAL |
1313  wx.ALL, border = 5, pos = (1, 3))
1314  self.sizer.Add(item = self.bbrowse,
1315  flag = wx.ALIGN_LEFT |
1316  wx.ALIGN_CENTER_VERTICAL |
1317  wx.ALL, border = 5, pos = (1, 4))
1318  self.sizer.Add(item = self.lcode,
1319  flag = wx.ALIGN_LEFT |
1320  wx.ALIGN_CENTER_VERTICAL |
1321  wx.ALL, border = 5, pos = (2, 1), span = (1, 2))
1322  self.sizer.Add(item = self.tcode,
1323  flag = wx.ALIGN_LEFT |
1324  wx.ALIGN_CENTER_VERTICAL |
1325  wx.ALL, border = 5, pos = (2, 3))
1326  self.sizer.Add(item = self.searchb,
1327  flag = wx.ALIGN_LEFT |
1328  wx.ALIGN_CENTER_VERTICAL |
1329  wx.ALL, border = 5, pos = (3, 3))
1330 
1331  self.sizer.AddGrowableRow(4)
1332  self.sizer.Add(item = self.epsglist,
1333  flag = wx.ALIGN_LEFT | wx.EXPAND, pos = (4, 1),
1334  span = (1, 4))
1335 
1336  # events
1337  self.bbrowse.Bind(wx.EVT_BUTTON, self.OnBrowse)
1338  self.tfile.Bind(wx.EVT_TEXT_ENTER, self.OnBrowseCodes)
1339  self.tcode.Bind(wx.EVT_TEXT, self.OnText)
1340  self.tcode.Bind(wx.EVT_TEXT_ENTER, self.OnText)
1341  self.epsglist.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnItemSelected)
1342  self.searchb.Bind(wx.EVT_TEXT_ENTER, self.OnSearch)
1343  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1344  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
1345 
1346  def OnEnterPage(self, event):
1347  self.parent.datumtrans = None
1348  if event.GetDirection():
1349  if not self.epsgcode:
1350  # disable 'next' button by default
1351  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
1352  else:
1353  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
1354 
1355  # load default epsg database file
1356  self.OnBrowseCodes(None)
1357 
1358  event.Skip()
1359 
1360  def OnPageChanging(self, event):
1361  if event.GetDirection():
1362  if not self.epsgcode:
1363  event.Veto()
1364  return
1365  else:
1366  # check for datum transforms
1367  ret = gcmd.RunCommand('g.proj',
1368  read = True,
1369  epsg = self.epsgcode,
1370  datumtrans = '-1')
1371 
1372  if ret != '':
1373  dtrans = ''
1374  # open a dialog to select datum transform number
1375  dlg = SelectTransformDialog(self.parent.parent, transforms = ret)
1376 
1377  if dlg.ShowModal() == wx.ID_OK:
1378  dtrans = dlg.GetTransform()
1379  if dtrans == '':
1380  dlg.Destroy()
1381  event.Veto()
1382  return 'Datum transform is required.'
1383  else:
1384  dlg.Destroy()
1385  event.Veto()
1386  return 'Datum transform is required.'
1387 
1388  self.parent.datumtrans = dtrans
1389  self.GetNext().SetPrev(self)
1390 
1391  def OnText(self, event):
1392  self.epsgcode = event.GetString()
1393  try:
1394  self.epsgcode = int(self.epsgcode)
1395  except:
1396  self.epsgcode = None
1397 
1398  nextButton = wx.FindWindowById(wx.ID_FORWARD)
1399 
1400  if self.epsgcode and self.epsgcode in self.epsgCodeDict.keys():
1401  self.epsgdesc = self.epsgCodeDict[self.epsgcode][0]
1402  self.epsgparams = self.epsgCodeDict[self.epsgcode][1]
1403  if not nextButton.IsEnabled():
1404  nextButton.Enable(True)
1405  else:
1406  self.epsgcode = None # not found
1407  if nextButton.IsEnabled():
1408  nextButton.Enable(False)
1409  self.epsgdesc = self.epsgparams = ''
1410 
1411  def OnSearch(self, event):
1412  value = self.searchb.GetValue()
1413 
1414  if value == '':
1415  self.epsgcode = None
1416  self.epsgdesc = self.epsgparams = ''
1417  self.tcode.SetValue('')
1418  self.searchb.SetValue('')
1419  self.OnBrowseCodes(None)
1420  else:
1421  try:
1422  self.epsgcode, self.epsgdesc, self.epsgparams = \
1423  self.epsglist.Search(index=[0,1,2], pattern=value)
1424  except (IndexError, ValueError): # -> no item found
1425  self.epsgcode = None
1426  self.epsgdesc = self.epsgparams = ''
1427  self.tcode.SetValue('')
1428  self.searchb.SetValue('')
1429 
1430  event.Skip()
1431 
1432  def OnBrowse(self, event):
1433  """!Define path for EPSG code file"""
1434  path = os.path.dirname(self.tfile.GetValue())
1435  if not path:
1436  path = os.getcwd()
1437 
1438  dlg = wx.FileDialog(parent = self, message = _("Choose EPSG codes file"),
1439  defaultDir = path, defaultFile = "", wildcard = "*", style = wx.OPEN)
1440 
1441  if dlg.ShowModal() == wx.ID_OK:
1442  path = dlg.GetPath()
1443  self.tfile.SetValue(path)
1444  self.OnBrowseCodes(None)
1445 
1446  dlg.Destroy()
1447 
1448  event.Skip()
1449 
1450  def OnItemSelected(self, event):
1451  """!EPSG code selected from the list"""
1452  index = event.m_itemIndex
1453  item = event.GetItem()
1454 
1455  self.epsgcode = int(self.epsglist.GetItem(index, 0).GetText())
1456  self.epsgdesc = self.epsglist.GetItem(index, 1).GetText()
1457  self.tcode.SetValue(str(self.epsgcode))
1458 
1459  event.Skip()
1460 
1461  def OnBrowseCodes(self, event, search = None):
1462  """!Browse EPSG codes"""
1463  self.epsgCodeDict = utils.ReadEpsgCodes(self.tfile.GetValue())
1464 
1465  if type(self.epsgCodeDict) != dict:
1466  wx.MessageBox(parent = self,
1467  message = _("Unable to read EPGS codes: %s") % self.epsgCodeDict,
1468  caption = _("Error"), style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
1469  self.epsglist.Populate(list(), update = True)
1470  return
1471 
1472  data = list()
1473  for code, val in self.epsgCodeDict.iteritems():
1474  if code is not None:
1475  data.append((code, val[0], val[1]))
1476 
1477  self.epsglist.Populate(data, update = True)
1478 
1480  """!Wizard page for entering custom PROJ.4 string
1481  for setting coordinate system parameters"""
1482 
1483  def __init__(self, wizard, parent):
1484  TitledPage.__init__(self, wizard,
1485  _("Choose method of specifying georeferencing parameters"))
1486  global coordsys
1487  self.customstring = ''
1488  self.parent = parent
1489 
1490  # widgets
1491  self.text_proj4string = self.MakeTextCtrl(size = (400, 200),
1492  style = wx.TE_MULTILINE)
1493  self.label_proj4string = self.MakeLabel(_("Enter PROJ.4 parameters string:"))
1494 
1495  # layout
1496  self.sizer.AddGrowableCol(2)
1497  self.sizer.Add(self.label_proj4string,
1498  flag = wx.ALIGN_LEFT | wx.ALL,
1499  border = 5, pos = (1, 1))
1500  self.sizer.AddGrowableRow(2)
1501  self.sizer.Add(self.text_proj4string,
1502  flag = wx.ALIGN_LEFT | wx.ALL | wx.EXPAND,
1503  border = 5, pos = (2, 1), span = (1, 2))
1504 
1505  self.text_proj4string.Bind(wx.EVT_TEXT, self.GetProjstring)
1506  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnPageChanging)
1507  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
1508 
1509  def OnEnterPage(self, event):
1510  if len(self.customstring) == 0:
1511  # disable 'next' button by default
1512  wx.FindWindowById(wx.ID_FORWARD).Enable(False)
1513  else:
1514  wx.FindWindowById(wx.ID_FORWARD).Enable(True)
1515 
1516  def OnPageChanging(self, event):
1517  if event.GetDirection():
1518  # check for datum tranforms
1519  ret, out, err = gcmd.RunCommand('g.proj',
1520  read = True, getErrorMsg = True,
1521  proj4 = self.customstring,
1522  datumtrans = '-1')
1523  if ret != 0:
1524  wx.MessageBox(parent = self,
1525  message = err,
1526  caption = _("Error"),
1527  style = wx.OK | wx.ICON_ERROR | wx.CENTRE)
1528  event.Veto()
1529  return
1530 
1531  if out:
1532  dtrans = ''
1533  # open a dialog to select datum transform number
1534  dlg = SelectTransformDialog(self.parent.parent, transforms = out)
1535 
1536  if dlg.ShowModal() == wx.ID_OK:
1537  dtrans = dlg.GetTransform()
1538  if len(dtrans) == 0:
1539  dlg.Destroy()
1540  event.Veto()
1541  return _('Datum transform is required.')
1542  else:
1543  dlg.Destroy()
1544  event.Veto()
1545  return _('Datum transform is required.')
1546 
1547  self.parent.datumtrans = dtrans
1548 
1549  self.GetNext().SetPrev(self)
1550 
1551  def GetProjstring(self, event):
1552  """!Change proj string"""
1553  # TODO: check PROJ.4 syntax
1554  self.customstring = event.GetString()
1555  nextButton = wx.FindWindowById(wx.ID_FORWARD)
1556  if len(self.customstring) == 0:
1557  if nextButton.IsEnabled():
1558  nextButton.Enable(False)
1559  else:
1560  if not nextButton.IsEnabled():
1561  nextButton.Enable()
1562 
1564  """!Shows summary result of choosing coordinate system parameters
1565  prior to creating location"""
1566  def __init__(self, wizard, parent):
1567  TitledPage.__init__(self, wizard, _("Summary"))
1568  self.parent = parent
1569 
1570  self.panelTitle = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY)
1571  self.panelProj4string = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY)
1572  self.panelProj = scrolled.ScrolledPanel(parent = self, id = wx.ID_ANY)
1573 
1574  # labels
1575  self.ldatabase = self.MakeLabel()
1576  self.llocation = self.MakeLabel()
1577  self.llocTitle = self.MakeLabel(parent = self.panelTitle)
1578  self.lprojection = self.MakeLabel(parent = self.panelProj)
1579  self.lproj4string = self.MakeLabel(parent = self.panelProj4string)
1580 
1581  self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnEnterPage)
1582 
1583  # do sub-page layout
1584  self._doLayout()
1585 
1586  def _doLayout(self):
1587  """!Do page layout"""
1588  self.sizer.AddGrowableCol(1)
1589  self.sizer.AddGrowableRow(3, 1)
1590  self.sizer.AddGrowableRow(4, 1)
1591  self.sizer.AddGrowableRow(5, 5)
1592 
1593  titleSizer = wx.BoxSizer(wx.VERTICAL)
1594  titleSizer.Add(item = self.llocTitle, proportion = 1,
1595  flag = wx.EXPAND | wx.ALL, border = 5)
1596  self.panelTitle.SetSizer(titleSizer)
1597 
1598  projSizer = wx.BoxSizer(wx.VERTICAL)
1599  projSizer.Add(item = self.lprojection, proportion = 1,
1600  flag = wx.EXPAND | wx.ALL, border = 5)
1601  self.panelProj.SetSizer(projSizer)
1602 
1603  proj4stringSizer = wx.BoxSizer(wx.VERTICAL)
1604  proj4stringSizer.Add(item = self.lproj4string, proportion = 1,
1605  flag = wx.EXPAND | wx.ALL, border = 5)
1606  self.panelProj4string.SetSizer(proj4stringSizer)
1607 
1608  self.panelProj4string.SetupScrolling()
1609  self.panelProj.SetupScrolling(scroll_y = False)
1610  self.panelTitle.SetupScrolling(scroll_y = False)
1611 
1612  self.sizer.Add(item = self.MakeLabel(_("GRASS Database:")),
1613  flag = wx.ALIGN_LEFT | wx.ALL,
1614  border = 5, pos = (1, 0))
1615  self.sizer.Add(item = self.ldatabase,
1616  flag = wx.ALIGN_LEFT | wx.ALL,
1617  border = 5, pos = (1, 1))
1618  self.sizer.Add(item = self.MakeLabel(_("Location Name:")),
1619  flag = wx.ALIGN_LEFT | wx.ALL,
1620  border = 5, pos = (2, 0))
1621  self.sizer.Add(item = self.llocation,
1622  flag = wx.ALIGN_LEFT | wx.ALL,
1623  border = 5, pos = (2, 1))
1624  self.sizer.Add(item = self.MakeLabel(_("Location Title:")),
1625  flag = wx.ALIGN_LEFT | wx.ALL,
1626  border = 5, pos = (3, 0))
1627  self.sizer.Add(item = self.panelTitle,
1628  flag = wx.ALIGN_LEFT | wx.ALL | wx.EXPAND,
1629  border = 0, pos = (3, 1))
1630  self.sizer.Add(item = self.MakeLabel(_("Projection:")),
1631  flag = wx.ALIGN_LEFT | wx.ALL,
1632  border = 5, pos = (4, 0))
1633  self.sizer.Add(item = self.panelProj,
1634  flag = wx.ALIGN_LEFT | wx.ALL | wx.EXPAND,
1635  border = 0, pos = (4, 1))
1636  self.sizer.Add(item = self.MakeLabel(_("PROJ.4 definition:")),
1637  flag = wx.ALIGN_LEFT | wx.ALL,
1638  border = 5, pos = (5, 0))
1639  self.sizer.Add(item = self.panelProj4string,
1640  flag = wx.ALIGN_LEFT | wx.ALL | wx.EXPAND,
1641  border = 0, pos = (5, 1))
1642 
1643  def OnEnterPage(self, event):
1644  """!Insert values into text controls for summary of location
1645  creation options
1646  """
1647  database = self.parent.startpage.grassdatabase
1648  location = self.parent.startpage.location
1649  proj4string = self.parent.CreateProj4String()
1650  epsgcode = self.parent.epsgpage.epsgcode
1651  dtrans = self.parent.datumtrans
1652 
1653  global coordsys
1654  if coordsys in ('proj', 'epsg'):
1655  if coordsys == 'proj':
1656  ret, projlabel, err = gcmd.RunCommand('g.proj',
1657  flags = 'jf',
1658  proj4 = proj4string,
1659  datumtrans = dtrans,
1660  location = location,
1661  getErrorMsg = True,
1662  read = True)
1663  elif coordsys == 'epsg':
1664  ret, projlabel, err = gcmd.RunCommand('g.proj',
1665  flags = 'jf',
1666  epsg = epsgcode,
1667  datumtrans = dtrans,
1668  location = location,
1669  getErrorMsg = True,
1670  read = True)
1671 
1672  finishButton = wx.FindWindowById(wx.ID_FORWARD)
1673  if ret == 0:
1674  self.lproj4string.SetLabel(projlabel.replace(' ', os.linesep))
1675  finishButton.Enable(True)
1676  else:
1677  gcmd.GError(err, parent = self)
1678  self.lproj4string.SetLabel('')
1679  finishButton.Enable(False)
1680 
1681  projdesc = self.parent.projpage.projdesc
1682  ellipsedesc = self.parent.ellipsepage.ellipsedesc
1683  datumdesc = self.parent.datumpage.datumdesc
1684  self.ldatabase.SetLabel(database)
1685  self.llocation.SetLabel(location)
1686  self.llocTitle.SetLabel(self.parent.startpage.locTitle)
1687 
1688  label = ''
1689  if coordsys == 'epsg':
1690  label = 'EPSG code %s (%s)' % (self.parent.epsgpage.epsgcode, self.parent.epsgpage.epsgdesc)
1691  elif coordsys == 'file':
1692  label = 'matches file %s' % self.parent.filepage.georeffile
1693  self.lproj4string.SetLabel("")
1694  elif coordsys == 'wkt':
1695  label = 'matches file %s' % self.parent.wktpage.wktfile
1696  self.lproj4string.SetLabel("")
1697  elif coordsys == 'proj':
1698  label = ('%s, %s %s' % (projdesc, datumdesc, ellipsedesc))
1699  elif coordsys == 'xy':
1700  label = ('XY coordinate system (not projected).')
1701  self.lproj4string.SetLabel("")
1702  elif coordsys == 'custom':
1703  label = _("custom")
1704  self.lproj4string.SetLabel(('%s' % self.parent.custompage.customstring.replace(' ', os.linesep)))
1705  self.lprojection.SetLabel(label)
1706 
1707  def OnFinish(self, event):
1708  dlg = wx.MessageDialog(parent = self.wizard,
1709  message = _("Do you want to create GRASS location <%s>?") % location,
1710  caption = _("Create new location?"),
1711  style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
1712 
1713  if dlg.ShowModal() == wx.ID_NO:
1714  dlg.Destroy()
1715  event.Veto()
1716  else:
1717  dlg.Destroy()
1718  event.Skip()
1719 
1720 class LocationWizard(wx.Object):
1721  """!Start wizard here and finish wizard here
1722  """
1723  def __init__(self, parent, grassdatabase):
1724  self.__cleanUp()
1725 
1726  global coordsys
1727  self.parent = parent
1728 
1729  #
1730  # define wizard image
1731  #
1732  imagePath = os.path.join(globalvar.ETCIMGDIR, "loc_wizard_qgis.png")
1733  wizbmp = wx.Image(imagePath, wx.BITMAP_TYPE_PNG)
1734  wizbmp = wizbmp.ConvertToBitmap()
1735 
1736  #
1737  # get georeferencing information from tables in $GISBASE/etc
1738  #
1739  self.__readData()
1740 
1741  #
1742  # datum transform number and list of datum transforms
1743  #
1744  self.datumtrans = None
1745  self.proj4string = ''
1746 
1747  #
1748  # define wizard pages
1749  #
1750  self.wizard = wiz.Wizard(parent, id = wx.ID_ANY, title = _("Define new GRASS Location"),
1751  bitmap = wizbmp, style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
1752  self.startpage = DatabasePage(self.wizard, self, grassdatabase)
1754  self.projpage = ProjectionsPage(self.wizard, self)
1755  self.datumpage = DatumPage(self.wizard, self)
1757  self.epsgpage = EPSGPage(self.wizard, self)
1759  self.wktpage = WKTPage(self.wizard, self)
1760  self.ellipsepage = EllipsePage(self.wizard, self)
1761  self.custompage = CustomPage(self.wizard, self)
1762  self.sumpage = SummaryPage(self.wizard, self)
1763 
1764  #
1765  # set the initial order of the pages
1766  # (should follow the epsg line)
1767  #
1768  self.startpage.SetNext(self.csystemspage)
1769 
1770  self.csystemspage.SetPrev(self.startpage)
1771  self.csystemspage.SetNext(self.sumpage)
1772 
1773  self.projpage.SetPrev(self.csystemspage)
1774  self.projpage.SetNext(self.paramspage)
1775 
1776  self.paramspage.SetPrev(self.projpage)
1777  self.paramspage.SetNext(self.datumpage)
1778 
1779  self.datumpage.SetPrev(self.paramspage)
1780  self.datumpage.SetNext(self.sumpage)
1781 
1782  self.ellipsepage.SetPrev(self.paramspage)
1783  self.ellipsepage.SetNext(self.sumpage)
1784 
1785  self.epsgpage.SetPrev(self.csystemspage)
1786  self.epsgpage.SetNext(self.sumpage)
1787 
1788  self.filepage.SetPrev(self.csystemspage)
1789  self.filepage.SetNext(self.sumpage)
1790 
1791  self.wktpage.SetPrev(self.csystemspage)
1792  self.wktpage.SetNext(self.sumpage)
1793 
1794  self.custompage.SetPrev(self.csystemspage)
1795  self.custompage.SetNext(self.sumpage)
1796 
1797  self.sumpage.SetPrev(self.csystemspage)
1798 
1799  #
1800  # do pages layout
1801  #
1802  self.startpage.DoLayout()
1803  self.csystemspage.DoLayout()
1804  self.projpage.DoLayout()
1805  self.datumpage.DoLayout()
1806  self.paramspage.DoLayout()
1807  self.epsgpage.DoLayout()
1808  self.filepage.DoLayout()
1809  self.wktpage.DoLayout()
1810  self.ellipsepage.DoLayout()
1811  self.custompage.DoLayout()
1812  self.sumpage.DoLayout()
1813  self.wizard.FitToPage(self.datumpage)
1814  size = self.wizard.GetPageSize()
1815  self.wizard.SetPageSize((size[0], size[1] + 75))
1816 
1817  # new location created?
1818  self.location = None
1819  success = False
1820 
1821  # location created in different GIS database?
1822  self.altdb = False
1823 
1824  #
1825  # run wizard...
1826  #
1827  if self.wizard.RunWizard(self.startpage):
1828  msg = self.OnWizFinished()
1829  if not msg:
1830  self.wizard.Destroy()
1831  self.location = self.startpage.location
1832 
1833  if self.altdb == False:
1834  dlg = wx.MessageDialog(parent = self.parent,
1835  message = _("Do you want to set the default "
1836  "region extents and resolution now?"),
1837  caption = _("Location <%s> created") % self.location,
1838  style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
1839  dlg.CenterOnScreen()
1840  if dlg.ShowModal() == wx.ID_YES:
1841  dlg.Destroy()
1842  defineRegion = RegionDef(self.parent, location = self.location)
1843  defineRegion.CenterOnScreen()
1844  defineRegion.Show()
1845  else:
1846  dlg.Destroy()
1847  else: # -> error
1848  self.wizard.Destroy()
1849  gcmd.GError(parent = self.parent,
1850  message = "%s" % _("Unable to create new location. "
1851  "Location <%(loc)s> not created.\n\n"
1852  "Details: %(err)s") % \
1853  { 'loc' : self.startpage.location,
1854  'err' : msg })
1855  else: # -> cancelled
1856  self.wizard.Destroy()
1857  gcmd.GMessage(parent = self.parent,
1858  message = _("Location wizard canceled. "
1859  "Location not created."))
1860 
1861  self.__cleanUp()
1862 
1863  def __cleanUp(self):
1864  global coordsys
1865  global north
1866  global south
1867  global east
1868  global west
1869  global resolution
1870  global wizerror
1871  global translist
1872 
1873  coordsys = None
1874  north = None
1875  south = None
1876  east = None
1877  west = None
1878  resolution = None
1879  transformlist = list()
1880 
1881  def __readData(self):
1882  """!Get georeferencing information from tables in $GISBASE/etc"""
1883 
1884  # read projection and parameters
1885  f = open(os.path.join(globalvar.ETCDIR, "proj-parms.table"), "r")
1886  self.projections = {}
1887  self.projdesc = {}
1888  for line in f.readlines():
1889  line = line.strip()
1890  try:
1891  proj, projdesc, params = line.split(':')
1892  paramslist = params.split(';')
1893  plist = []
1894  for p in paramslist:
1895  if p == '': continue
1896  p1, pdefault = p.split(',')
1897  pterm, pask = p1.split('=')
1898  p = [pterm.strip(), pask.strip(), pdefault.strip()]
1899  plist.append(p)
1900  self.projections[proj.lower().strip()] = (projdesc.strip(), plist)
1901  self.projdesc[proj.lower().strip()] = projdesc.strip()
1902  except:
1903  continue
1904  f.close()
1905 
1906  # read datum definitions
1907  f = open(os.path.join(globalvar.ETCDIR, "datum.table"), "r")
1908  self.datums = {}
1909  paramslist = []
1910  for line in f.readlines():
1911  line = line.expandtabs(1)
1912  line = line.strip()
1913  if line == '' or line[0] == "#":
1914  continue
1915  datum, info = line.split(" ", 1)
1916  info = info.strip()
1917  datumdesc, params = info.split(" ", 1)
1918  datumdesc = datumdesc.strip('"')
1919  paramlist = params.split()
1920  ellipsoid = paramlist.pop(0)
1921  self.datums[datum] = (ellipsoid, datumdesc.replace('_', ' '), paramlist)
1922  f.close()
1923 
1924  # read ellipsiod definitions
1925  f = open(os.path.join(globalvar.ETCDIR, "ellipse.table"), "r")
1926  self.ellipsoids = {}
1927  for line in f.readlines():
1928  line = line.expandtabs(1)
1929  line = line.strip()
1930  if line == '' or line[0] == "#":
1931  continue
1932  ellipse, rest = line.split(" ", 1)
1933  rest = rest.strip('" ')
1934  desc, params = rest.split('"', 1)
1935  desc = desc.strip('" ')
1936  paramslist = params.split()
1937  self.ellipsoids[ellipse] = (desc, paramslist)
1938  f.close()
1939 
1940  # read projection parameter description and parsing table
1941  f = open(os.path.join(globalvar.ETCDIR, "proj-desc.table"), "r")
1942  self.paramdesc = {}
1943  for line in f.readlines():
1944  line = line.strip()
1945  try:
1946  pparam, datatype, proj4term, desc = line.split(':')
1947  self.paramdesc[pparam] = (datatype, proj4term, desc)
1948  except:
1949  continue
1950  f.close()
1951 
1952  def OnWizFinished(self):
1953  """!Wizard finished, create new location
1954 
1955  @return error message on error
1956  @return None on success
1957  """
1958  database = self.startpage.grassdatabase
1959  location = self.startpage.location
1960 
1961  # location already exists?
1962  if os.path.isdir(os.path.join(database,location)):
1963  gcmd.GError(parent = self.wizard,
1964  message = "%s <%s>: %s" % \
1965  (_("Unable to create new location"),
1966  os.path.join(database, location),
1967  _("Location already exists in GRASS Database.")))
1968  return None
1969 
1970  # current GISDbase or a new one?
1971  current_gdb = grass.gisenv()['GISDBASE']
1972  if current_gdb != database:
1973  # change to new GISDbase or create new one
1974  if os.path.isdir(database) != True:
1975  # create new directory
1976  os.mkdir(database)
1977 
1978  # change to new GISDbase directory
1979  gcmd.RunCommand('g.gisenv',
1980  parent = self.wizard,
1981  set = 'GISDBASE=%s' % database)
1982 
1983  wx.MessageBox(parent = self.wizard,
1984  message = _("Location <%(loc)s> will be created "
1985  "in GIS data directory <%(dir)s>. "
1986  "You will need to change the default GIS "
1987  "data directory in the GRASS startup screen.") % \
1988  { 'loc' : location, 'dir' : database},
1989  caption = _("New GIS data directory"),
1990  style = wx.OK | wx.ICON_INFORMATION | wx.CENTRE)
1991 
1992  # location created in alternate GISDbase
1993  self.altdb = True
1994 
1995  global coordsys
1996  try:
1997  if coordsys == "xy":
1998  grass.create_location(dbase = self.startpage.grassdatabase,
1999  location = self.startpage.location,
2000  desc = self.startpage.locTitle)
2001  elif coordsys == "proj":
2002  grass.create_location(dbase = self.startpage.grassdatabase,
2003  location = self.startpage.location,
2004  proj4 = self.CreateProj4String(),
2005  datum = self.datumtrans,
2006  desc = self.startpage.locTitle)
2007  elif coordsys == 'custom':
2008  grass.create_location(dbase = self.startpage.grassdatabase,
2009  location = self.startpage.location,
2010  proj4 = self.custompage.customstring,
2011  desc = self.startpage.locTitle)
2012  elif coordsys == "epsg":
2013  if not self.epsgpage.epsgcode:
2014  return _('EPSG code missing.')
2015 
2016  grass.create_location(dbase = self.startpage.grassdatabase,
2017  location = self.startpage.location,
2018  epsg = self.epsgpage.epsgcode,
2019  datum = self.datumtrans,
2020  desc = self.startpage.locTitle)
2021  elif coordsys == "file":
2022  if not self.filepage.georeffile or \
2023  not os.path.isfile(self.filepage.georeffile):
2024  return _("File <%s> not found." % self.filepage.georeffile)
2025 
2026  grass.create_location(dbase = self.startpage.grassdatabase,
2027  location = self.startpage.location,
2028  filename = self.filepage.georeffile,
2029  desc = self.startpage.locTitle)
2030  elif coordsys == "wkt":
2031  if not self.wktpage.wktfile or \
2032  not os.path.isfile(self.wktpage.wktfile):
2033  return _("File <%s> not found." % self.wktpage.wktfile)
2034 
2035  grass.create_location(dbase = self.startpage.grassdatabase,
2036  location = self.startpage.location,
2037  wkt = self.wktpage.wktfile,
2038  desc = self.startpage.locTitle)
2039 
2040  except grass.ScriptError, e:
2041  return e.value
2042 
2043  return None
2044 
2046  """!Constract PROJ.4 string"""
2047  location = self.startpage.location
2048  proj = self.projpage.p4proj
2049  projdesc = self.projpage.projdesc
2050  proj4params = self.paramspage.p4projparams
2051 
2052  datum = self.datumpage.datum
2053  if self.datumpage.datumdesc:
2054  datumdesc = self.datumpage.datumdesc +' - ' + self.datumpage.ellipse
2055  else:
2056  datumdesc = ''
2057  datumparams = self.datumpage.datumparams
2058  ellipse = self.ellipsepage.ellipse
2059  ellipsedesc = self.ellipsepage.ellipsedesc
2060  ellipseparams = self.ellipsepage.ellipseparams
2061 
2062  #
2063  # creating PROJ.4 string
2064  #
2065  proj4string = '%s %s' % (proj, proj4params)
2066 
2067  # set ellipsoid parameters
2068  if ellipse != '':
2069  proj4string = '%s +ellps=%s' % (proj4string, ellipse)
2070  for item in ellipseparams:
2071  if item[:4] == 'f=1/':
2072  item = ' +rf=' + item[4:]
2073  else:
2074  item = ' +' + item
2075  proj4string = '%s %s' % (proj4string, item)
2076 
2077  # set datum and transform parameters if relevant
2078  if datum != '':
2079  proj4string = '%s +datum=%s' % (proj4string, datum)
2080  if datumparams:
2081  for item in datumparams:
2082  proj4string = '%s +%s' % (proj4string,item)
2083 
2084  proj4string = '%s +no_defs' % proj4string
2085 
2086  return proj4string
2087 
2088 class RegionDef(BaseClass, wx.Frame):
2089  """!Page for setting default region extents and resolution
2090  """
2091  def __init__(self, parent, id = wx.ID_ANY,
2092  title = _("Set default region extent and resolution"), location = None):
2093  wx.Frame.__init__(self, parent, id, title, size = (650,300))
2094  panel = wx.Panel(self, id = wx.ID_ANY)
2095 
2096  self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
2097 
2098  self.parent = parent
2099  self.location = location
2100 
2101  #
2102  # default values
2103  #
2104  # 2D
2105  self.north = 1.0
2106  self.south = 0.0
2107  self.east = 1.0
2108  self.west = 0.0
2109  self.nsres = 1.0
2110  self.ewres = 1.0
2111  # 3D
2112  self.top = 1.0
2113  self.bottom = 0.0
2114  # self.nsres3 = 1.0
2115  # self.ewres3 = 1.0
2116  self.tbres = 1.0
2117 
2118  #
2119  # inputs
2120  #
2121  # 2D
2122  self.tnorth = self.MakeTextCtrl(text = str(self.north), size = (150, -1), parent = panel)
2123  self.tsouth = self.MakeTextCtrl(str(self.south), size = (150, -1), parent = panel)
2124  self.twest = self.MakeTextCtrl(str(self.west), size = (150, -1), parent = panel)
2125  self.teast = self.MakeTextCtrl(str(self.east), size = (150, -1), parent = panel)
2126  self.tnsres = self.MakeTextCtrl(str(self.nsres), size = (150, -1), parent = panel)
2127  self.tewres = self.MakeTextCtrl(str(self.ewres), size = (150, -1), parent = panel)
2128 
2129  #
2130  # labels
2131  #
2132  self.lrows = self.MakeLabel(parent = panel)
2133  self.lcols = self.MakeLabel(parent = panel)
2134  self.lcells = self.MakeLabel(parent = panel)
2135 
2136  #
2137  # buttons
2138  #
2139  self.bset = self.MakeButton(text = _("&Set region"), id = wx.ID_OK, parent = panel)
2140  self.bcancel = wx.Button(panel, id = wx.ID_CANCEL)
2141  self.bset.SetDefault()
2142 
2143  #
2144  # image
2145  #
2146  self.img = wx.Image(os.path.join(globalvar.ETCIMGDIR, "qgis_world.png"),
2147  wx.BITMAP_TYPE_PNG).ConvertToBitmap()
2148 
2149  #
2150  # set current working environment to PERMANENT mapset
2151  # in selected location in order to set default region (WIND)
2152  #
2153  envval = {}
2154  ret = gcmd.RunCommand('g.gisenv',
2155  read = True)
2156  if ret:
2157  for line in ret.splitlines():
2158  key, val = line.split('=')
2159  envval[key] = val
2160  self.currlocation = envval['LOCATION_NAME'].strip("';")
2161  self.currmapset = envval['MAPSET'].strip("';")
2162  if self.currlocation != self.location or self.currmapset != 'PERMANENT':
2163  gcmd.RunCommand('g.gisenv',
2164  set = 'LOCATION_NAME=%s' % self.location)
2165  gcmd.RunCommand('g.gisenv',
2166  set = 'MAPSET=PERMANENT')
2167  else:
2168  dlg = wx.MessageBox(parent = self,
2169  message = _('Invalid location selected.'),
2170  caption = _("Error"), style = wx.ID_OK | wx.ICON_ERROR)
2171  return
2172 
2173  #
2174  # get current region settings
2175  #
2176  region = {}
2177  ret = gcmd.RunCommand('g.region',
2178  read = True,
2179  flags = 'gp3')
2180  if ret:
2181  for line in ret.splitlines():
2182  key, val = line.split('=')
2183  region[key] = float(val)
2184  else:
2185  dlg = wx.MessageBox(parent = self,
2186  message = _("Invalid region"),
2187  caption = _("Error"), style = wx.ID_OK | wx.ICON_ERROR)
2188  dlg.ShowModal()
2189  dlg.Destroy()
2190  return
2191 
2192  #
2193  # update values
2194  # 2D
2195  self.north = float(region['n'])
2196  self.south = float(region['s'])
2197  self.east = float(region['e'])
2198  self.west = float(region['w'])
2199  self.nsres = float(region['nsres'])
2200  self.ewres = float(region['ewres'])
2201  self.rows = int(region['rows'])
2202  self.cols = int(region['cols'])
2203  self.cells = int(region['cells'])
2204  # 3D
2205  self.top = float(region['t'])
2206  self.bottom = float(region['b'])
2207  # self.nsres3 = float(region['nsres3'])
2208  # self.ewres3 = float(region['ewres3'])
2209  self.tbres = float(region['tbres'])
2210  self.depth = int(region['depths'])
2211  self.cells3 = int(region['cells3'])
2212 
2213  #
2214  # 3D box collapsable
2215  #
2216  self.infoCollapseLabelExp = _("Click here to show 3D settings")
2217  self.infoCollapseLabelCol = _("Click here to hide 3D settings")
2218  self.settings3D = wx.CollapsiblePane(parent = panel,
2219  label = self.infoCollapseLabelExp,
2220  style = wx.CP_DEFAULT_STYLE |
2221  wx.CP_NO_TLW_RESIZE | wx.EXPAND)
2222  self.MakeSettings3DPaneContent(self.settings3D.GetPane())
2223  self.settings3D.Collapse(False) # FIXME
2224  self.Bind(wx.EVT_COLLAPSIBLEPANE_CHANGED, self.OnSettings3DPaneChanged, self.settings3D)
2225 
2226  #
2227  # set current region settings
2228  #
2229  self.tnorth.SetValue(str(self.north))
2230  self.tsouth.SetValue(str(self.south))
2231  self.twest.SetValue(str(self.west))
2232  self.teast.SetValue(str(self.east))
2233  self.tnsres.SetValue(str(self.nsres))
2234  self.tewres.SetValue(str(self.ewres))
2235  self.ttop.SetValue(str(self.top))
2236  self.tbottom.SetValue(str(self.bottom))
2237  # self.tnsres3.SetValue(str(self.nsres3))
2238  # self.tewres3.SetValue(str(self.ewres3))
2239  self.ttbres.SetValue(str(self.tbres))
2240  self.lrows.SetLabel(_("Rows: %d") % self.rows)
2241  self.lcols.SetLabel(_("Cols: %d") % self.cols)
2242  self.lcells.SetLabel(_("Cells: %d") % self.cells)
2243 
2244  #
2245  # bindings
2246  #
2247  self.Bind(wx.EVT_BUTTON, self.OnSetButton, self.bset)
2248  self.Bind(wx.EVT_BUTTON, self.OnCancel, self.bcancel)
2249  self.tnorth.Bind(wx.EVT_TEXT, self.OnValue)
2250  self.tsouth.Bind(wx.EVT_TEXT, self.OnValue)
2251  self.teast.Bind(wx.EVT_TEXT, self.OnValue)
2252  self.twest.Bind(wx.EVT_TEXT, self.OnValue)
2253  self.tnsres.Bind(wx.EVT_TEXT, self.OnValue)
2254  self.tewres.Bind(wx.EVT_TEXT, self.OnValue)
2255  self.ttop.Bind(wx.EVT_TEXT, self.OnValue)
2256  self.tbottom.Bind(wx.EVT_TEXT, self.OnValue)
2257  # self.tnsres3.Bind(wx.EVT_TEXT, self.OnValue)
2258  # self.tewres3.Bind(wx.EVT_TEXT, self.OnValue)
2259  self.ttbres.Bind(wx.EVT_TEXT, self.OnValue)
2260 
2261  self.__DoLayout(panel)
2262  self.SetMinSize(self.GetBestSize())
2263  self.minWindowSize = self.GetMinSize()
2264 
2265  def MakeSettings3DPaneContent(self, pane):
2266  """!Create 3D region settings pane"""
2267  border = wx.BoxSizer(wx.VERTICAL)
2268  gridSizer = wx.GridBagSizer(vgap = 0, hgap = 0)
2269 
2270  # inputs
2271  self.ttop = wx.TextCtrl(parent = pane, id = wx.ID_ANY, value = str(self.top),
2272  size = (150, -1))
2273  self.tbottom = wx.TextCtrl(parent = pane, id = wx.ID_ANY, value = str(self.bottom),
2274  size = (150, -1))
2275  self.ttbres = wx.TextCtrl(parent = pane, id = wx.ID_ANY, value = str(self.tbres),
2276  size = (150, -1))
2277  # self.tnsres3 = wx.TextCtrl(parent = pane, id = wx.ID_ANY, value = str(self.nsres3),
2278  # size = (150, -1))
2279  # self.tewres3 = wx.TextCtrl(parent = pane, id = wx.ID_ANY, value = str(self.ewres3),
2280  # size = (150, -1))
2281 
2282  #labels
2283  self.ldepth = wx.StaticText(parent = pane, label = _("Depth: %d") % self.depth)
2284  self.lcells3 = wx.StaticText(parent = pane, label = _("3D Cells: %d") % self.cells3)
2285 
2286  # top
2287  gridSizer.Add(item = wx.StaticText(parent = pane, label = _("Top")),
2288  flag = wx.ALIGN_CENTER |
2289  wx.LEFT | wx.RIGHT | wx.TOP, border = 5,
2290  pos = (0, 1))
2291  gridSizer.Add(item = self.ttop,
2292  flag = wx.ALIGN_CENTER_HORIZONTAL |
2293  wx.ALL, border = 5, pos = (1, 1))
2294  # bottom
2295  gridSizer.Add(item = wx.StaticText(parent = pane, label = _("Bottom")),
2296  flag = wx.ALIGN_CENTER |
2297  wx.LEFT | wx.RIGHT | wx.TOP, border = 5,
2298  pos = (0, 2))
2299  gridSizer.Add(item = self.tbottom,
2300  flag = wx.ALIGN_CENTER_HORIZONTAL |
2301  wx.ALL, border = 5, pos = (1, 2))
2302  # tbres
2303  gridSizer.Add(item = wx.StaticText(parent = pane, label = _("T-B resolution")),
2304  flag = wx.ALIGN_CENTER |
2305  wx.LEFT | wx.RIGHT | wx.TOP, border = 5,
2306  pos = (0, 3))
2307  gridSizer.Add(item = self.ttbres,
2308  flag = wx.ALIGN_CENTER_HORIZONTAL |
2309  wx.ALL, border = 5, pos = (1, 3))
2310 
2311  # res
2312  # gridSizer.Add(item = wx.StaticText(parent = pane, label = _("3D N-S resolution")),
2313  # flag = wx.ALIGN_CENTER |
2314  # wx.LEFT | wx.RIGHT | wx.TOP, border = 5,
2315  # pos = (2, 1))
2316  # gridSizer.Add(item = self.tnsres3,
2317  # flag = wx.ALIGN_CENTER_HORIZONTAL |
2318  # wx.ALL, border = 5, pos = (3, 1))
2319  # gridSizer.Add(item = wx.StaticText(parent = pane, label = _("3D E-W resolution")),
2320  # flag = wx.ALIGN_CENTER |
2321  # wx.LEFT | wx.RIGHT | wx.TOP, border = 5,
2322  # pos = (2, 3))
2323  # gridSizer.Add(item = self.tewres3,
2324  # flag = wx.ALIGN_CENTER_HORIZONTAL |
2325  # wx.ALL, border = 5, pos = (3, 3))
2326 
2327  # rows/cols/cells
2328  gridSizer.Add(item = self.ldepth,
2329  flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER |
2330  wx.ALL, border = 5, pos = (2, 1))
2331 
2332  gridSizer.Add(item = self.lcells3,
2333  flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER |
2334  wx.ALL, border = 5, pos = (2, 2))
2335 
2336  border.Add(item = gridSizer, proportion = 1,
2337  flag = wx.ALL | wx.ALIGN_CENTER | wx.EXPAND, border = 5)
2338 
2339  pane.SetSizer(border)
2340  border.Fit(pane)
2341 
2342  def OnSettings3DPaneChanged(self, event):
2343  """!Collapse 3D settings box"""
2344 
2345  if self.settings3D.IsExpanded():
2346  self.settings3D.SetLabel(self.infoCollapseLabelCol)
2347  self.Layout()
2348  self.SetSize(self.GetBestSize())
2349  self.SetMinSize(self.GetSize())
2350  else:
2351  self.settings3D.SetLabel(self.infoCollapseLabelExp)
2352  self.Layout()
2353  self.SetSize(self.minWindowSize)
2354  self.SetMinSize(self.minWindowSize)
2355 
2356  self.SendSizeEvent()
2357 
2358  def __DoLayout(self, panel):
2359  """!Window layout"""
2360  frameSizer = wx.BoxSizer(wx.VERTICAL)
2361  gridSizer = wx.GridBagSizer(vgap = 0, hgap = 0)
2362  settings3DSizer = wx.BoxSizer(wx.VERTICAL)
2363  buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
2364 
2365  # north
2366  gridSizer.Add(item = self.MakeLabel(text = _("North"), parent = panel),
2367  flag = wx.ALIGN_BOTTOM | wx.ALIGN_CENTER_HORIZONTAL |
2368  wx.TOP | wx.LEFT | wx.RIGHT, border = 5, pos = (0, 2))
2369  gridSizer.Add(item = self.tnorth,
2370  flag = wx.ALIGN_CENTER_HORIZONTAL |
2371  wx.ALIGN_CENTER_VERTICAL |
2372  wx.ALL, border = 5, pos = (1, 2))
2373  # west
2374  gridSizer.Add(item = self.MakeLabel(text = _("West"), parent = panel),
2375  flag = wx.ALIGN_RIGHT |
2376  wx.ALIGN_CENTER_VERTICAL |
2377  wx.LEFT | wx.TOP | wx.BOTTOM, border = 5, pos = (2, 0))
2378  gridSizer.Add(item = self.twest,
2379  flag = wx.ALIGN_RIGHT |
2380  wx.ALIGN_CENTER_VERTICAL |
2381  wx.ALL, border = 5, pos = (2, 1))
2382 
2383  gridSizer.Add(item = wx.StaticBitmap(panel, wx.ID_ANY, self.img, (-1, -1),
2384  (self.img.GetWidth(), self.img.GetHeight())),
2385  flag = wx.ALIGN_CENTER |
2386  wx.ALIGN_CENTER_VERTICAL |
2387  wx.ALL, border = 5, pos = (2, 2))
2388 
2389  # east
2390  gridSizer.Add(item = self.teast,
2391  flag = wx.ALIGN_CENTER_HORIZONTAL |
2392  wx.ALIGN_CENTER_VERTICAL |
2393  wx.ALL, border = 5, pos = (2, 3))
2394  gridSizer.Add(item = self.MakeLabel(text = _("East"), parent = panel),
2395  flag = wx.ALIGN_LEFT |
2396  wx.ALIGN_CENTER_VERTICAL |
2397  wx.RIGHT | wx.TOP | wx.BOTTOM, border = 5, pos = (2, 4))
2398  # south
2399  gridSizer.Add(item = self.tsouth,
2400  flag = wx.ALIGN_CENTER_HORIZONTAL |
2401  wx.ALIGN_CENTER_VERTICAL |
2402  wx.ALL, border = 5, pos = (3, 2))
2403  gridSizer.Add(item = self.MakeLabel(text = _("South"), parent = panel),
2404  flag = wx.ALIGN_TOP | wx.ALIGN_CENTER_HORIZONTAL |
2405  wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5, pos = (4, 2))
2406  # ns-res
2407  gridSizer.Add(item = self.MakeLabel(text = _("N-S resolution"), parent = panel),
2408  flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER |
2409  wx.TOP | wx.LEFT | wx.RIGHT, border = 5, pos = (5, 1))
2410  gridSizer.Add(item = self.tnsres,
2411  flag = wx.ALIGN_RIGHT |
2412  wx.ALIGN_CENTER_VERTICAL |
2413  wx.ALL, border = 5, pos = (6, 1))
2414  # ew-res
2415  gridSizer.Add(item = self.MakeLabel(text = _("E-W resolution"), parent = panel),
2416  flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER |
2417  wx.TOP | wx.LEFT | wx.RIGHT, border = 5, pos = (5, 3))
2418  gridSizer.Add(item = self.tewres,
2419  flag = wx.ALIGN_RIGHT |
2420  wx.ALIGN_CENTER_VERTICAL |
2421  wx.ALL, border = 5, pos = (6, 3))
2422  # rows/cols/cells
2423  gridSizer.Add(item = self.lrows,
2424  flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER |
2425  wx.ALL, border = 5, pos = (7, 1))
2426 
2427  gridSizer.Add(item = self.lcells,
2428  flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER |
2429  wx.ALL, border = 5, pos = (7, 2))
2430 
2431  gridSizer.Add(item = self.lcols,
2432  flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER |
2433  wx.ALL, border = 5, pos = (7, 3))
2434 
2435  # 3D
2436  settings3DSizer.Add(item = self.settings3D,
2437  flag = wx.ALL,
2438  border = 5)
2439 
2440  # buttons
2441  buttonSizer.Add(item = self.bcancel, proportion = 1,
2442  flag = wx.ALIGN_RIGHT |
2443  wx.ALIGN_CENTER_VERTICAL |
2444  wx.ALL, border = 10)
2445  buttonSizer.Add(item = self.bset, proportion = 1,
2446  flag = wx.ALIGN_CENTER |
2447  wx.ALIGN_CENTER_VERTICAL |
2448  wx.ALL, border = 10)
2449 
2450  frameSizer.Add(item = gridSizer, proportion = 1,
2451  flag = wx.ALL | wx.ALIGN_CENTER, border = 5)
2452  frameSizer.Add(item = settings3DSizer, proportion = 0,
2453  flag = wx.ALL | wx.ALIGN_CENTER, border = 5)
2454  frameSizer.Add(item = buttonSizer, proportion = 0,
2455  flag = wx.ALL | wx.ALIGN_RIGHT, border = 5)
2456 
2457  self.SetAutoLayout(True)
2458  panel.SetSizer(frameSizer)
2459  frameSizer.Fit(panel)
2460  self.Layout()
2461 
2462  def OnValue(self, event):
2463  """!Set given value"""
2464  try:
2465  if event.GetId() == self.tnorth.GetId():
2466  self.north = float(event.GetString())
2467  elif event.GetId() == self.tsouth.GetId():
2468  self.south = float(event.GetString())
2469  elif event.GetId() == self.teast.GetId():
2470  self.east = float(event.GetString())
2471  elif event.GetId() == self.twest.GetId():
2472  self.west = float(event.GetString())
2473  elif event.GetId() == self.tnsres.GetId():
2474  self.nsres = float(event.GetString())
2475  elif event.GetId() == self.tewres.GetId():
2476  self.ewres = float(event.GetString())
2477  elif event.GetId() == self.ttop.GetId():
2478  self.top = float(event.GetString())
2479  elif event.GetId() == self.tbottom.GetId():
2480  self.bottom = float(event.GetString())
2481  # elif event.GetId() == self.tnsres3.GetId():
2482  # self.nsres3 = float(event.GetString())
2483  # elif event.GetId() == self.tewres3.GetId():
2484  # self.ewres3 = float(event.GetString())
2485  elif event.GetId() == self.ttbres.GetId():
2486  self.tbres = float(event.GetString())
2487 
2488  self.__UpdateInfo()
2489 
2490  except ValueError, e:
2491  if len(event.GetString()) > 0 and event.GetString() != '-':
2492  dlg = wx.MessageBox(parent = self,
2493  message = _("Invalid value: %s") % e,
2494  caption = _("Error"),
2495  style = wx.OK | wx.ICON_ERROR)
2496  # reset values
2497  self.tnorth.SetValue(str(self.north))
2498  self.tsouth.SetValue(str(self.south))
2499  self.teast.SetValue(str(self.east))
2500  self.twest.SetValue(str(self.west))
2501  self.tnsres.SetValue(str(self.nsres))
2502  self.tewres.SetValue(str(self.ewres))
2503  self.ttop.SetValue(str(self.top))
2504  self.tbottom.SetValue(str(self.bottom))
2505  self.ttbres.SetValue(str(self.tbres))
2506  # self.tnsres3.SetValue(str(self.nsres3))
2507  # self.tewres3.SetValue(str(self.ewres3))
2508 
2509  event.Skip()
2510 
2511  def __UpdateInfo(self):
2512  """!Update number of rows/cols/cells"""
2513  self.rows = int((self.north - self.south) / self.nsres)
2514  self.cols = int((self.east - self.west) / self.ewres)
2515  self.cells = self.rows * self.cols
2516 
2517  self.depth = int((self.top - self.bottom) / self.tbres)
2518  self.cells3 = self.rows * self.cols * self.depth
2519 
2520  # 2D
2521  self.lrows.SetLabel(_("Rows: %d") % self.rows)
2522  self.lcols.SetLabel(_("Cols: %d") % self.cols)
2523  self.lcells.SetLabel(_("Cells: %d") % self.cells)
2524  # 3D
2525  self.ldepth.SetLabel(_("Depth: %d" % self.depth))
2526  self.lcells3.SetLabel(_("3D Cells: %d" % self.cells3))
2527 
2528  def OnSetButton(self, event = None):
2529  """!Set default region"""
2530  ret = gcmd.RunCommand('g.region',
2531  flags = 'sgpa',
2532  n = self.north,
2533  s = self.south,
2534  e = self.east,
2535  w = self.west,
2536  nsres = self.nsres,
2537  ewres = self.ewres,
2538  t = self.top,
2539  b = self.bottom,
2540  tbres = self.tbres)
2541  if ret == 0:
2542  self.Destroy()
2543 
2544  def OnCancel(self, event):
2545  self.Destroy()
2546 
2547 class TransList(wx.VListBox):
2548  """!Creates a multiline listbox for selecting datum transforms"""
2549 
2550  def OnDrawItem(self, dc, rect, n):
2551  if self.GetSelection() == n:
2552  c = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
2553  else:
2554  c = self.GetForegroundColour()
2555  dc.SetFont(self.GetFont())
2556  dc.SetTextForeground(c)
2557  dc.DrawLabel(self._getItemText(n), rect,
2558  wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
2559 
2560  def OnMeasureItem(self, n):
2561  height = 0
2562  if self._getItemText(n) == None:
2563  return
2564  for line in self._getItemText(n).splitlines():
2565  w, h = self.GetTextExtent(line)
2566  height += h
2567  return height + 5
2568 
2569  def _getItemText(self, item):
2570  global transformlist
2571  transitem = transformlist[item]
2572  if transitem.strip() !='':
2573  return transitem
2574 
2575 
2576 class SelectTransformDialog(wx.Dialog):
2577  """!Dialog for selecting datum transformations"""
2578  def __init__(self, parent, transforms, title = _("Select datum transformation"),
2579  pos = wx.DefaultPosition, size = wx.DefaultSize,
2580  style = wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER):
2581 
2582  wx.Dialog.__init__(self, parent, wx.ID_ANY, title, pos, size, style)
2583 
2584  global transformlist
2585  self.CentreOnParent()
2586 
2587  # default transform number
2588  self.transnum = 0
2589 
2590  panel = scrolled.ScrolledPanel(self, wx.ID_ANY)
2591  sizer = wx.BoxSizer(wx.VERTICAL)
2592 
2593  #
2594  # set panel sizer
2595  #
2596  panel.SetSizer(sizer)
2597  panel.SetupScrolling()
2598 
2599  #
2600  # dialog body
2601  #
2602  bodyBox = wx.StaticBox(parent = panel, id = wx.ID_ANY,
2603  label = " %s " % _("Select from list of datum transformations"))
2604  bodySizer = wx.StaticBoxSizer(bodyBox)
2605 
2606  # add no transform option
2607  transforms = '---\n\n0\nDo not apply any datum transformations\n\n' + transforms
2608 
2609  transformlist = transforms.split('---')
2610  tlistlen = len(transformlist)
2611 
2612  # calculate size for transform list
2613  height = 0
2614  width = 0
2615  for line in transforms.splitlines():
2616  w, h = self.GetTextExtent(line)
2617  height += h
2618  width = max(width, w)
2619 
2620  height = height + 5
2621  if height > 400: height = 400
2622  width = width + 5
2623  if width > 400: width = 400
2624 
2625  #
2626  # VListBox for displaying and selecting transformations
2627  #
2628  self.translist = TransList(panel, id = -1, size = (width, height), style = wx.SUNKEN_BORDER)
2629  self.translist.SetItemCount(tlistlen)
2630  self.translist.SetSelection(2)
2631  self.translist.SetFocus()
2632 
2633  self.Bind(wx.EVT_LISTBOX, self.ClickTrans, self.translist)
2634 
2635  bodySizer.Add(item = self.translist, proportion = 1, flag = wx.ALIGN_CENTER|wx.ALL|wx.EXPAND)
2636 
2637  #
2638  # buttons
2639  #
2640  btnsizer = wx.StdDialogButtonSizer()
2641 
2642  btn = wx.Button(parent = panel, id = wx.ID_OK)
2643  btn.SetDefault()
2644  btnsizer.AddButton(btn)
2645 
2646  btn = wx.Button(parent = panel, id = wx.ID_CANCEL)
2647  btnsizer.AddButton(btn)
2648  btnsizer.Realize()
2649 
2650  sizer.Add(item = bodySizer, proportion = 1,
2651  flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
2652 
2653  sizer.Add(item = btnsizer, proportion = 0,
2654  flag = wx.ALL | wx.ALIGN_RIGHT, border = 5)
2655 
2656  sizer.Fit(panel)
2657 
2658  self.SetSize(self.GetBestSize())
2659  self.Layout()
2660 
2661  def ClickTrans(self, event):
2662  """!Get the number of the datum transform to use in g.proj"""
2663  self.transnum = event.GetSelection()
2664  self.transnum = self.transnum - 1
2665 
2666  def GetTransform(self):
2667  """!Get the number of the datum transform to use in g.proj"""
2668  self.transnum = self.translist.GetSelection()
2669  self.transnum = self.transnum - 1
2670  return self.transnum
2671 
2672 if __name__ == "__main__":
2673  import gettext
2674  gettext.install('grasswxpy', os.path.join(os.getenv("GISBASE"), 'locale'), unicode = True)
2675  app = wx.PySimpleApp()
2676  gWizard = RegionDef(None)
2677  gWizzard.Show()
2678  app.MainLoop()