GRASS Programmer's Manual  6.4.2(2012)
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gdialogs.py
Go to the documentation of this file.
1 """!
2 @package gdialogs.py
3 
4 @brief Various dialogs used in wxGUI.
5 
6 List of classes:
7  - ElementDialog
8  - LocationDialog
9  - MapsetDialog
10  - NewVectorDialog
11  - SavedRegion
12  - DecorationDialog
13  - TextLayerDialog
14  - AddMapLayersDialog
15  - ImportDialog
16  - GdalImportDialog
17  - DxfImportDialog
18  - LayersList (used by MultiImport)
19  - SetOpacityDialog
20  - StaticWrapText
21  - ImageSizeDialog
22 
23 (C) 2008-2011 by the GRASS Development Team
24 
25 This program is free software under the GNU General Public
26 License (>=v2). Read the file COPYING that comes with GRASS
27 for details.
28 
29 @author Martin Landa <landa.martin gmail.com>
30 """
31 
32 import os
33 import sys
34 import re
35 from bisect import bisect
36 
37 import wx
38 import wx.lib.filebrowsebutton as filebrowse
39 import wx.lib.mixins.listctrl as listmix
40 
41 from grass.script import core as grass
42 from grass.script import task as gtask
43 
44 import gcmd
45 import globalvar
46 import gselect
47 import menuform
48 import utils
49 from debug import Debug
50 from preferences import globalSettings as UserSettings
51 
52 class ElementDialog(wx.Dialog):
53  def __init__(self, parent, title, label, id = wx.ID_ANY,
54  etype = False, style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
55  **kwargs):
56  """!General dialog to choose given element (location, mapset, vector map, etc.)
57 
58  @param parent window
59  @param title window title
60  @param label element label
61  @param etype show also ElementSelect
62  """
63  wx.Dialog.__init__(self, parent, id, title, style = style, **kwargs)
64 
65  self.etype = etype
66  self.label = label
67 
68  self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
69 
70  self.btnCancel = wx.Button(parent = self.panel, id = wx.ID_CANCEL)
71  self.btnOK = wx.Button(parent = self.panel, id = wx.ID_OK)
72  self.btnOK.SetDefault()
73  self.btnOK.Enable(False)
74 
75  if self.etype:
76  self.typeSelect = gselect.ElementSelect(parent = self.panel,
77  size = globalvar.DIALOG_GSELECT_SIZE)
78  self.typeSelect.Bind(wx.EVT_CHOICE, self.OnType)
79 
80  self.element = None # must be defined
81 
82  self.__layout()
83 
84  def PostInit(self):
85  self.element.SetFocus()
86  self.element.Bind(wx.EVT_TEXT, self.OnElement)
87 
88  def OnType(self, event):
89  """!Select element type"""
90  if not self.etype:
91  return
92  evalue = self.typeSelect.GetValue(event.GetString())
93  self.element.SetType(evalue)
94 
95  def OnElement(self, event):
96  """!Name for vector map layer given"""
97  if len(event.GetString()) > 0:
98  self.btnOK.Enable(True)
99  else:
100  self.btnOK.Enable(False)
101 
102  def __layout(self):
103  """!Do layout"""
104  self.sizer = wx.BoxSizer(wx.VERTICAL)
105 
106  self.dataSizer = wx.BoxSizer(wx.VERTICAL)
107 
108  if self.etype:
109  self.dataSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
110  label = _("Type of element:")),
111  proportion=0, flag=wx.ALL, border=1)
112  self.dataSizer.Add(item = self.typeSelect,
113  proportion=0, flag=wx.ALL, border=1)
114 
115  self.dataSizer.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
116  label = self.label),
117  proportion=0, flag=wx.ALL, border=1)
118 
119  # buttons
120  btnSizer = wx.StdDialogButtonSizer()
121  btnSizer.AddButton(self.btnCancel)
122  btnSizer.AddButton(self.btnOK)
123  btnSizer.Realize()
124 
125  self.sizer.Add(item=self.dataSizer, proportion=1,
126  flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
127 
128  self.sizer.Add(item=btnSizer, proportion=0,
129  flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
130 
131  def GetElement(self):
132  """!Return (mapName, overwrite)"""
133  return self.element.GetValue()
134 
135  def GetType(self):
136  """!Get element type"""
137  return self.element.tcp.GetType()
138 
140  """!Dialog used to select location"""
141  def __init__(self, parent, title = _("Select GRASS location and mapset"), id = wx.ID_ANY):
142  ElementDialog.__init__(self, parent, title, label = _("Name of GRASS location:"))
143 
144  self.element = gselect.LocationSelect(parent = self.panel, id = wx.ID_ANY,
145  size = globalvar.DIALOG_GSELECT_SIZE)
146 
147  self.element1 = gselect.MapsetSelect(parent = self.panel, id = wx.ID_ANY,
148  size = globalvar.DIALOG_GSELECT_SIZE,
149  setItems = False)
150 
151  self.PostInit()
152 
153  self.__Layout()
154  self.SetMinSize(self.GetSize())
155 
156  def __Layout(self):
157  """!Do layout"""
158  self.dataSizer.Add(self.element, proportion=0,
159  flag=wx.EXPAND | wx.ALL, border=1)
160 
161  self.dataSizer.Add(wx.StaticText(parent = self.panel, id = wx.ID_ANY,
162  label = _("Name of mapset:")), proportion=0,
163  flag=wx.EXPAND | wx.ALL, border=1)
164 
165  self.dataSizer.Add(self.element1, proportion=0,
166  flag=wx.EXPAND | wx.ALL, border=1)
167 
168  self.panel.SetSizer(self.sizer)
169  self.sizer.Fit(self)
170 
171  def OnElement(self, event):
172  """!Select mapset given location name"""
173  location = event.GetString()
174 
175  if location:
176  dbase = grass.gisenv()['GISDBASE']
177  self.element1.SetItems(utils.GetListOfMapsets(dbase, location, selectable = True))
178  self.element1.SetSelection(0)
179  mapset = self.element1.GetStringSelection()
180 
181  if location and mapset:
182  self.btnOK.Enable(True)
183  else:
184  self.btnOK.Enable(False)
185 
186  def GetValues(self):
187  """!Get location, mapset"""
188  return (self.GetElement(), self.element1.GetStringSelection())
189 
191  """!Dialog used to select mapset"""
192  def __init__(self, parent, title = _("Select mapset in GRASS location"),
193  location = None, id = wx.ID_ANY):
194  ElementDialog.__init__(self, parent, title, label = _("Name of mapset:"))
195  if location:
196  self.SetTitle(self.GetTitle() + ' <%s>' % location)
197  else:
198  self.SetTitle(self.GetTitle() + ' <%s>' % grass.gisenv()['LOCATION_NAME'])
199 
200  self.element = gselect.MapsetSelect(parent = self.panel, id = wx.ID_ANY,
201  size = globalvar.DIALOG_GSELECT_SIZE)
202 
203  self.PostInit()
204 
205  self.__Layout()
206  self.SetMinSize(self.GetSize())
207 
208  def __Layout(self):
209  """!Do layout"""
210  self.dataSizer.Add(self.element, proportion=0,
211  flag=wx.EXPAND | wx.ALL, border=1)
212 
213  self.panel.SetSizer(self.sizer)
214  self.sizer.Fit(self)
215 
216  def GetMapset(self):
217  return self.GetElement()
218 
220  def __init__(self, parent, id = wx.ID_ANY, title = _('Create new vector map'),
221  disableAdd = False, disableTable = False,
222  style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, *kwargs):
223  """!Dialog for creating new vector map
224 
225  @param parent parent window
226  @param id window id
227  @param title window title
228  @param disableAdd disable 'add layer' checkbox
229  @param disableTable disable 'create table' checkbox
230  @param style window style
231  @param kwargs other argumentes for ElementDialog
232 
233  @return dialog instance
234  """
235  ElementDialog.__init__(self, parent, title, label = _("Name for new vector map:"))
236 
237  self.element = gselect.Select(parent = self.panel, id = wx.ID_ANY, size = globalvar.DIALOG_GSELECT_SIZE,
238  type = 'vector', mapsets = [grass.gisenv()['MAPSET'],])
239 
240  self.table = wx.CheckBox(parent = self.panel, id = wx.ID_ANY,
241  label = _("Create attribute table"))
242  self.table.SetValue(True)
243  if disableTable:
244  self.table.Enable(False)
245 
246  self.keycol = wx.TextCtrl(parent = self.panel, id = wx.ID_ANY,
247  size = globalvar.DIALOG_SPIN_SIZE)
248  self.keycol.SetValue(UserSettings.Get(group = 'atm', key = 'keycolumn', subkey = 'value'))
249  if disableTable:
250  self.keycol.Enable(False)
251 
252  self.addbox = wx.CheckBox(parent = self.panel,
253  label = _('Add created map into layer tree'), style = wx.NO_BORDER)
254  if disableAdd:
255  self.addbox.SetValue(True)
256  self.addbox.Enable(False)
257  else:
258  self.addbox.SetValue(UserSettings.Get(group = 'cmd', key = 'addNewLayer', subkey = 'enabled'))
259 
260  self.table.Bind(wx.EVT_CHECKBOX, self.OnTable)
261 
262  self.PostInit()
263 
264  self._layout()
265  self.SetMinSize(self.GetSize())
266 
267  def OnMapName(self, event):
268  """!Name for vector map layer given"""
269  self.OnElement(event)
270 
271  def OnTable(self, event):
272  self.keycol.Enable(event.IsChecked())
273 
274  def _layout(self):
275  """!Do layout"""
276  self.dataSizer.Add(self.element, proportion = 0,
277  flag = wx.EXPAND | wx.ALL, border = 1)
278 
279  self.dataSizer.Add(self.table, proportion = 0,
280  flag = wx.EXPAND | wx.ALL, border = 1)
281 
282  keySizer = wx.BoxSizer(wx.HORIZONTAL)
283  keySizer.Add(item = wx.StaticText(parent = self.panel, label = _("Key column:")),
284  proportion = 0,
285  flag = wx.ALIGN_CENTER_VERTICAL)
286  keySizer.AddSpacer(10)
287  keySizer.Add(item = self.keycol, proportion = 0,
288  flag = wx.ALIGN_RIGHT)
289  self.dataSizer.Add(item = keySizer, proportion = 1,
290  flag = wx.EXPAND | wx.ALL, border = 1)
291 
292  self.dataSizer.AddSpacer(5)
293 
294  self.dataSizer.Add(item = self.addbox, proportion = 0,
295  flag = wx.EXPAND | wx.ALL, border = 1)
296 
297  self.panel.SetSizer(self.sizer)
298  self.sizer.Fit(self)
299 
300  def GetName(self, full = False):
301  """!Get name of vector map to be created
302 
303  @param full True to get fully qualified name
304  """
305  name = self.GetElement()
306  if full:
307  if '@' in name:
308  return name
309  else:
310  return name + '@' + grass.gisenv()['MAPSET']
311 
312  return name.split('@', 1)[0]
313 
314  def GetKey(self):
315  """!Get key column name"""
316  return self.keycol.GetValue()
317 
318  def IsChecked(self, key):
319  """!Get dialog properties
320 
321  @param key window key ('add', 'table')
322 
323  @return True/False
324  @return None on error
325  """
326  if key == 'add':
327  return self.addbox.IsChecked()
328  elif key == 'table':
329  return self.table.IsChecked()
330 
331  return None
332 
333 def CreateNewVector(parent, cmd, title = _('Create new vector map'),
334  exceptMap = None, log = None, disableAdd = False, disableTable = False):
335  """!Create new vector map layer
336 
337  @param cmd (prog, **kwargs)
338  @param title window title
339  @param exceptMap list of maps to be excepted
340  @param log
341  @param disableAdd disable 'add layer' checkbox
342  @param disableTable disable 'create table' checkbox
343 
344  @return dialog instance
345  @return None on error
346  """
347  dlg = NewVectorDialog(parent, title = title,
348  disableAdd = disableAdd, disableTable = disableTable)
349 
350  if dlg.ShowModal() != wx.ID_OK:
351  dlg.Destroy()
352  return None
353 
354  outmap = dlg.GetName()
355  key = dlg.GetKey()
356  if outmap == exceptMap:
357  gcmd.GError(parent = parent,
358  message = _("Unable to create vector map <%s>.") % outmap)
359  dlg.Destroy()
360  return None
361  if dlg.table.IsEnabled() and not key:
362  gcmd.GError(parent = parent,
363  message = _("Invalid or empty key column.\n"
364  "Unable to create vector map <%s>.") % outmap)
365  dlg.Destroy()
366  return
367 
368  if outmap == '': # should not happen
369  dlg.Destroy()
370  return None
371 
372  # update cmd -> output name defined
373  cmd[1][cmd[2]] = outmap
374 
375  listOfVectors = grass.list_grouped('vect')[grass.gisenv()['MAPSET']]
376 
377  overwrite = False
378  if not UserSettings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled') and \
379  outmap in listOfVectors:
380  dlgOw = wx.MessageDialog(parent, message = _("Vector map <%s> already exists "
381  "in the current mapset. "
382  "Do you want to overwrite it?") % outmap,
383  caption = _("Overwrite?"),
384  style = wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION)
385  if dlgOw.ShowModal() == wx.ID_YES:
386  overwrite = True
387  else:
388  dlgOw.Destroy()
389  dlg.Destroy()
390  return None
391 
392  if UserSettings.Get(group = 'cmd', key = 'overwrite', subkey = 'enabled'):
393  overwrite = True
394 
395  ret = gcmd.RunCommand(prog = cmd[0],
396  parent = parent,
397  overwrite = overwrite,
398  **cmd[1])
399  if ret != 0:
400  dlg.Destroy()
401  return None
402 
403  # create attribute table
404  if dlg.table.IsEnabled() and dlg.table.IsChecked():
405  sql = 'CREATE TABLE %s (%s INTEGER)' % (outmap, key)
406 
407  gcmd.RunCommand('db.connect',
408  flags = 'c')
409 
410  Debug.msg(1, "SQL: %s" % sql)
411  gcmd.RunCommand('db.execute',
412  quiet = True,
413  parent = parent,
414  stdin = sql)
415 
416  gcmd.RunCommand('v.db.connect',
417  quiet = True,
418  parent = parent,
419  map = outmap,
420  table = outmap,
421  key = key,
422  layer = '1')
423 
424  # return fully qualified map name
425  if '@' not in outmap:
426  outmap += '@' + grass.gisenv()['MAPSET']
427 
428  if log:
429  log.WriteLog(_("New vector map <%s> created") % outmap)
430 
431  return dlg
432 
433 class SavedRegion(wx.Dialog):
434  def __init__(self, parent, id = wx.ID_ANY, title="", loadsave='load',
435  **kwargs):
436  """!Loading and saving of display extents to saved region file
437 
438  @param loadsave load or save region?
439  """
440  wx.Dialog.__init__(self, parent, id, title, **kwargs)
441 
442  self.loadsave = loadsave
443  self.wind = ''
444 
445  sizer = wx.BoxSizer(wx.VERTICAL)
446 
447  box = wx.BoxSizer(wx.HORIZONTAL)
448  label = wx.StaticText(parent=self, id=wx.ID_ANY)
449  box.Add(item=label, proportion=0, flag=wx.ALIGN_CENTRE | wx.ALL, border=5)
450  if loadsave == 'load':
451  label.SetLabel(_("Load region:"))
452  selection = gselect.Select(parent=self, id=wx.ID_ANY, size=globalvar.DIALOG_GSELECT_SIZE,
453  type='windows')
454  elif loadsave == 'save':
455  label.SetLabel(_("Save region:"))
456  selection = gselect.Select(parent=self, id=wx.ID_ANY, size=globalvar.DIALOG_GSELECT_SIZE,
457  type='windows', mapsets = [grass.gisenv()['MAPSET']])
458 
459  box.Add(item=selection, proportion=0, flag=wx.ALIGN_CENTRE | wx.ALL, border=5)
460  selection.SetFocus()
461  selection.Bind(wx.EVT_TEXT, self.OnRegion)
462 
463  sizer.Add(item=box, proportion=0, flag=wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL,
464  border=5)
465 
466  line = wx.StaticLine(parent=self, id=wx.ID_ANY, size=(20, -1), style=wx.LI_HORIZONTAL)
467  sizer.Add(item=line, proportion=0,
468  flag=wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, border=5)
469 
470  btnsizer = wx.StdDialogButtonSizer()
471 
472  btn = wx.Button(parent = self, id = wx.ID_OK)
473  btn.SetDefault()
474  btnsizer.AddButton(btn)
475 
476  btn = wx.Button(parent = self, id = wx.ID_CANCEL)
477  btnsizer.AddButton(btn)
478  btnsizer.Realize()
479 
480  sizer.Add(item=btnsizer, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
481 
482  self.SetSizer(sizer)
483  sizer.Fit(self)
484  self.Layout()
485 
486  def OnRegion(self, event):
487  self.wind = event.GetString()
488 
489 class DecorationDialog(wx.Dialog):
490  """
491  Controls setting options and displaying/hiding map overlay decorations
492  """
493  def __init__(self, parent, ovlId, title, cmd, name=None,
494  pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_DIALOG_STYLE,
495  checktxt='', ctrltxt=''):
496 
497  wx.Dialog.__init__(self, parent, wx.ID_ANY, title, pos, size, style)
498 
499  self.ovlId = ovlId # PseudoDC id
500  self.cmd = cmd
501  self.name = name # overlay name
502  self.parent = parent # MapFrame
503 
504  sizer = wx.BoxSizer(wx.VERTICAL)
505 
506  box = wx.BoxSizer(wx.HORIZONTAL)
507  self.chkbox = wx.CheckBox(parent=self, id=wx.ID_ANY, label=checktxt)
508  if self.parent.Map.GetOverlay(self.ovlId) is None:
509  self.chkbox.SetValue(True)
510  else:
511  self.chkbox.SetValue(self.parent.MapWindow.overlays[self.ovlId]['layer'].IsActive())
512  box.Add(item=self.chkbox, proportion=0,
513  flag=wx.ALIGN_CENTRE|wx.ALL, border=5)
514  sizer.Add(item=box, proportion=0,
515  flag=wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=5)
516 
517  box = wx.BoxSizer(wx.HORIZONTAL)
518  optnbtn = wx.Button(parent=self, id=wx.ID_ANY, label=_("Set options"))
519  box.Add(item=optnbtn, proportion=0, flag=wx.ALIGN_CENTRE|wx.ALL, border=5)
520  sizer.Add(item=box, proportion=0,
521  flag=wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=5)
522 
523  box = wx.BoxSizer(wx.HORIZONTAL)
524  label = wx.StaticText(parent=self, id=wx.ID_ANY,
525  label=_("Drag %s with mouse in pointer mode to position.\n"
526  "Double-click to change options." % ctrltxt))
527  if self.name == 'legend':
528  label.SetLabel(label.GetLabel() + _('\nDefine raster map name for legend in '
529  'properties dialog.'))
530  box.Add(item=label, proportion=0,
531  flag=wx.ALIGN_CENTRE|wx.ALL, border=5)
532  sizer.Add(item=box, proportion=0,
533  flag=wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=5)
534 
535  line = wx.StaticLine(parent=self, id=wx.ID_ANY, size=(20,-1), style=wx.LI_HORIZONTAL)
536  sizer.Add(item=line, proportion=0,
537  flag=wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, border=5)
538 
539  # buttons
540  btnsizer = wx.StdDialogButtonSizer()
541 
542  self.btnOK = wx.Button(parent=self, id=wx.ID_OK)
543  self.btnOK.SetDefault()
544  if self.name == 'legend':
545  self.btnOK.Enable(False)
546  btnsizer.AddButton(self.btnOK)
547 
548  btnCancel = wx.Button(parent=self, id=wx.ID_CANCEL)
549  btnsizer.AddButton(btnCancel)
550  btnsizer.Realize()
551 
552  sizer.Add(item=btnsizer, proportion=0,
553  flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
554 
555  #
556  # bindings
557  #
558  self.Bind(wx.EVT_BUTTON, self.OnOptions, optnbtn)
559  self.Bind(wx.EVT_BUTTON, self.OnCancel, btnCancel)
560  self.Bind(wx.EVT_BUTTON, self.OnOK, self.btnOK)
561 
562  self.SetSizer(sizer)
563  sizer.Fit(self)
564 
565  # create overlay if doesn't exist
566  self._CreateOverlay()
567 
568  if len(self.parent.MapWindow.overlays[self.ovlId]['cmd']) > 1:
569  mapName, found = utils.GetLayerNameFromCmd(self.parent.MapWindow.overlays[self.ovlId]['cmd'])
570  if self.parent.MapWindow.overlays[self.ovlId]['propwin'] is None and mapName:
571  # build properties dialog
572  menuform.GUI(parent = self.parent, show = False).ParseCommand(cmd=self.cmd,
573  completed=(self.GetOptData, self.name, ''))
574 
575  if found:
576  # enable 'OK' button
577  self.btnOK.Enable()
578  if name == 'legend':
579  # set title
580  self.SetTitle(_('Legend of raster map <%s>') % \
581  mapName)
582 
583  def _CreateOverlay(self):
584  if not self.parent.Map.GetOverlay(self.ovlId):
585  overlay = self.parent.Map.AddOverlay(id=self.ovlId, type=self.name,
586  command=self.cmd,
587  l_active=False, l_render=False, l_hidden=True)
588 
589  self.parent.MapWindow.overlays[self.ovlId] = {}
590  self.parent.MapWindow.overlays[self.ovlId] = { 'layer' : overlay,
591  'params' : None,
592  'propwin' : None,
593  'cmd' : self.cmd,
594  'coords': (10, 10),
595  'pdcType': 'image' }
596  else:
597  if self.parent.MapWindow.overlays[self.ovlId]['propwin'] == None:
598  return
599 
600  self.parent.MapWindow.overlays[self.ovlId]['propwin'].get_dcmd = self.GetOptData
601 
602 
603  def OnOptions(self, event):
604  """ self.SetSizer(sizer)
605  sizer.Fit(self)
606 
607  Sets option for decoration map overlays
608  """
609  if self.parent.MapWindow.overlays[self.ovlId]['propwin'] is None:
610  # build properties dialog
611  menuform.GUI(parent = self.parent).ParseCommand(cmd=self.cmd,
612  completed=(self.GetOptData, self.name, ''))
613 
614  else:
615  if self.parent.MapWindow.overlays[self.ovlId]['propwin'].IsShown():
616  self.parent.MapWindow.overlays[self.ovlId]['propwin'].SetFocus()
617  else:
618  self.parent.MapWindow.overlays[self.ovlId]['propwin'].Show()
619 
620  def OnCancel(self, event):
621  """!Cancel dialog"""
622  self.parent.dialogs['barscale'] = None
623 
624  self.Destroy()
625 
626  def OnOK(self, event):
627  """!Button 'OK' pressed"""
628  # enable or disable overlay
629  self.parent.Map.GetOverlay(self.ovlId).SetActive(self.chkbox.IsChecked())
630 
631  # update map
632  self.parent.MapWindow.UpdateMap()
633 
634  # close dialog
635  self.OnCancel(None)
636 
637  def GetOptData(self, dcmd, layer, params, propwin):
638  """!Process decoration layer data"""
639  # update layer data
640  if params:
641  self.parent.MapWindow.overlays[self.ovlId]['params'] = params
642  if dcmd:
643  self.parent.MapWindow.overlays[self.ovlId]['cmd'] = dcmd
644  self.parent.MapWindow.overlays[self.ovlId]['propwin'] = propwin
645 
646  # change parameters for item in layers list in render.Map
647  # "Use mouse..." (-m) flag causes GUI freeze and is pointless here, trac #119
648 
649  try:
650  self.parent.MapWindow.overlays[self.ovlId]['cmd'].remove('-m')
651  except ValueError:
652  pass
653 
654  self.parent.Map.ChangeOverlay(id=self.ovlId, type=self.name,
655  command=self.parent.MapWindow.overlays[self.ovlId]['cmd'],
656  l_active=self.parent.MapWindow.overlays[self.ovlId]['layer'].IsActive(),
657  l_render=False, l_hidden=True)
658  if self.name == 'legend':
659  if params and not self.btnOK.IsEnabled():
660  self.btnOK.Enable()
661 
662 class TextLayerDialog(wx.Dialog):
663  """
664  Controls setting options and displaying/hiding map overlay decorations
665  """
666 
667  def __init__(self, parent, ovlId, title, name='text',
668  pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_DIALOG_STYLE):
669 
670  wx.Dialog.__init__(self, parent, wx.ID_ANY, title, pos, size, style)
671  from wx.lib.expando import ExpandoTextCtrl, EVT_ETC_LAYOUT_NEEDED
672 
673  self.ovlId = ovlId
674  self.parent = parent
675 
676  if self.ovlId in self.parent.MapWindow.textdict.keys():
677  self.currText = self.parent.MapWindow.textdict[self.ovlId]['text']
678  self.currFont = self.parent.MapWindow.textdict[self.ovlId]['font']
679  self.currClr = self.parent.MapWindow.textdict[self.ovlId]['color']
680  self.currRot = self.parent.MapWindow.textdict[self.ovlId]['rotation']
681  self.currCoords = self.parent.MapWindow.textdict[self.ovlId]['coords']
682  else:
683  self.currClr = wx.BLACK
684  self.currText = ''
685  self.currFont = self.GetFont()
686  self.currRot = 0.0
687  self.currCoords = [10, 10, 10, 10]
688 
689  self.sizer = wx.BoxSizer(wx.VERTICAL)
690  box = wx.GridBagSizer(vgap=5, hgap=5)
691 
692  # show/hide
693  self.chkbox = wx.CheckBox(parent=self, id=wx.ID_ANY, \
694  label = _('Show text object'))
695  if self.parent.Map.GetOverlay(self.ovlId) is None:
696  self.chkbox.SetValue(True)
697  else:
698  self.chkbox.SetValue(self.parent.MapWindow.overlays[self.ovlId]['layer'].IsActive())
699  box.Add(item=self.chkbox, span=(1,2),
700  flag=wx.ALIGN_LEFT|wx.ALL, border=5,
701  pos=(0, 0))
702 
703  # text entry
704  label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Enter text:"))
705  box.Add(item=label,
706  flag=wx.ALIGN_CENTER_VERTICAL,
707  pos=(1, 0))
708 
709  self.textentry = ExpandoTextCtrl(parent=self, id=wx.ID_ANY, value="", size=(300,-1))
710  self.textentry.SetFont(self.currFont)
711  self.textentry.SetForegroundColour(self.currClr)
712  self.textentry.SetValue(self.currText)
713  # get rid of unneeded scrollbar when text box first opened
714  self.textentry.SetClientSize((300,-1))
715 
716  box.Add(item=self.textentry,
717  pos=(1, 1))
718 
719  # rotation
720  label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Rotation:"))
721  box.Add(item=label,
722  flag=wx.ALIGN_CENTER_VERTICAL,
723  pos=(2, 0))
724  self.rotation = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="", pos=(30, 50),
725  size=(75,-1), style=wx.SP_ARROW_KEYS)
726  self.rotation.SetRange(-360, 360)
727  self.rotation.SetValue(int(self.currRot))
728  box.Add(item=self.rotation,
729  flag=wx.ALIGN_RIGHT,
730  pos=(2, 1))
731 
732  # font
733  fontbtn = wx.Button(parent=self, id=wx.ID_ANY, label=_("Set font"))
734  box.Add(item=fontbtn,
735  flag=wx.ALIGN_RIGHT,
736  pos=(3, 1))
737 
738  self.sizer.Add(item=box, proportion=1,
739  flag=wx.ALL, border=10)
740 
741  # note
742  box = wx.BoxSizer(wx.HORIZONTAL)
743  label = wx.StaticText(parent=self, id=wx.ID_ANY,
744  label=_("Drag text with mouse in pointer mode "
745  "to position.\nDouble-click to change options"))
746  box.Add(item=label, proportion=0,
747  flag=wx.ALIGN_CENTRE | wx.ALL, border=5)
748  self.sizer.Add(item=box, proportion=0,
749  flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_CENTER | wx.ALL, border=5)
750 
751  line = wx.StaticLine(parent=self, id=wx.ID_ANY,
752  size=(20,-1), style=wx.LI_HORIZONTAL)
753  self.sizer.Add(item=line, proportion=0,
754  flag=wx.EXPAND | wx.ALIGN_CENTRE | wx.ALL, border=5)
755 
756  btnsizer = wx.StdDialogButtonSizer()
757 
758  btn = wx.Button(parent=self, id=wx.ID_OK)
759  btn.SetDefault()
760  btnsizer.AddButton(btn)
761 
762  btn = wx.Button(parent=self, id=wx.ID_CANCEL)
763  btnsizer.AddButton(btn)
764  btnsizer.Realize()
765 
766  self.sizer.Add(item=btnsizer, proportion=0,
767  flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
768 
769  self.SetSizer(self.sizer)
770  self.sizer.Fit(self)
771 
772  # bindings
773  self.Bind(EVT_ETC_LAYOUT_NEEDED, self.OnRefit, self.textentry)
774  self.Bind(wx.EVT_BUTTON, self.OnSelectFont, fontbtn)
775  self.Bind(wx.EVT_TEXT, self.OnText, self.textentry)
776  self.Bind(wx.EVT_SPINCTRL, self.OnRotation, self.rotation)
777 
778  def OnRefit(self, event):
779  """!Resize text entry to match text"""
780  self.sizer.Fit(self)
781 
782  def OnText(self, event):
783  """!Change text string"""
784  self.currText = event.GetString()
785 
786  def OnRotation(self, event):
787  """!Change rotation"""
788  self.currRot = event.GetInt()
789 
790  event.Skip()
791 
792  def OnSelectFont(self, event):
793  """!Change font"""
794  data = wx.FontData()
795  data.EnableEffects(True)
796  data.SetColour(self.currClr) # set colour
797  data.SetInitialFont(self.currFont)
798 
799  dlg = wx.FontDialog(self, data)
800 
801  if dlg.ShowModal() == wx.ID_OK:
802  data = dlg.GetFontData()
803  self.currFont = data.GetChosenFont()
804  self.currClr = data.GetColour()
805 
806  self.textentry.SetFont(self.currFont)
807  self.textentry.SetForegroundColour(self.currClr)
808 
809  self.Layout()
810 
811  dlg.Destroy()
812 
813  def GetValues(self):
814  """!Get text properties"""
815  return { 'text' : self.currText,
816  'font' : self.currFont,
817  'color' : self.currClr,
818  'rotation' : self.currRot,
819  'coords' : self.currCoords,
820  'active' : self.chkbox.IsChecked() }
821 
822 class AddMapLayersDialog(wx.Dialog):
823  """!Add selected map layers (raster, vector) into layer tree"""
824  def __init__(self, parent, title, style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
825  wx.Dialog.__init__(self, parent=parent, id=wx.ID_ANY, title=title, style=style)
826 
827  self.parent = parent # GMFrame
828 
829  #
830  # dialog body
831  #
833  # update list of layer to be loaded
834  self.map_layers = [] # list of map layers (full list type/mapset)
835  self.LoadMapLayers(self.layerType.GetStringSelection()[:4],
836  self.mapset.GetStringSelection())
837  #
838  # buttons
839  #
840  btnCancel = wx.Button(parent = self, id = wx.ID_CANCEL)
841  btnOk = wx.Button(parent = self, id = wx.ID_OK, label = _("&Add"))
842  btnOk.SetDefault()
843  btnOk.SetToolTipString(_("Add selected map layers to current display"))
844 
845  #
846  # sizers & do layout
847  #
848  btnSizer = wx.StdDialogButtonSizer()
849  btnSizer.AddButton(btnCancel)
850  btnSizer.AddButton(btnOk)
851  btnSizer.Realize()
852 
853  mainSizer = wx.BoxSizer(wx.VERTICAL)
854  mainSizer.Add(item=self.bodySizer, proportion=1,
855  flag=wx.EXPAND | wx.ALL, border=5)
856  mainSizer.Add(item=btnSizer, proportion=0,
857  flag=wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=5)
858 
859  self.SetSizer(mainSizer)
860  mainSizer.Fit(self)
861 
862  # set dialog min size
863  self.SetMinSize(self.GetSize())
864 
865  def __createDialogBody(self):
866  bodySizer = wx.GridBagSizer(vgap=3, hgap=3)
867  bodySizer.AddGrowableCol(1)
868  bodySizer.AddGrowableRow(3)
869 
870  # layer type
871  bodySizer.Add(item=wx.StaticText(parent=self, label=_("Map layer type:")),
872  flag=wx.ALIGN_CENTER_VERTICAL,
873  pos=(0,0))
874 
875  self.layerType = wx.Choice(parent=self, id=wx.ID_ANY,
876  choices=['raster', 'vector'], size=(100,-1))
877  self.layerType.SetSelection(0)
878  bodySizer.Add(item=self.layerType,
879  pos=(0,1))
880 
881  # select toggle
882  self.toggle = wx.CheckBox(parent=self, id=wx.ID_ANY,
883  label=_("Select toggle"))
884  self.toggle.SetValue(True)
885  bodySizer.Add(item=self.toggle,
886  flag=wx.ALIGN_CENTER_VERTICAL,
887  pos=(0,2))
888 
889  # mapset filter
890  bodySizer.Add(item=wx.StaticText(parent=self, label=_("Mapset:")),
891  flag=wx.ALIGN_CENTER_VERTICAL,
892  pos=(1,0))
893 
894  self.mapset = gselect.MapsetSelect(parent = self)
895  self.mapset.SetStringSelection(grass.gisenv()['MAPSET'])
896  bodySizer.Add(item=self.mapset,
897  pos=(1,1), span=(1, 2))
898 
899  # map name filter
900  bodySizer.Add(item=wx.StaticText(parent=self, label=_("Filter:")),
901  flag=wx.ALIGN_CENTER_VERTICAL,
902  pos=(2,0))
903 
904  self.filter = wx.TextCtrl(parent=self, id=wx.ID_ANY,
905  value="",
906  size=(250,-1))
907  bodySizer.Add(item=self.filter,
908  flag=wx.EXPAND,
909  pos=(2,1), span=(1, 2))
910 
911  # layer list
912  bodySizer.Add(item=wx.StaticText(parent=self, label=_("List of maps:")),
913  flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_TOP,
914  pos=(3,0))
915  self.layers = wx.CheckListBox(parent=self, id=wx.ID_ANY,
916  size=(250, 100),
917  choices=[])
918  bodySizer.Add(item=self.layers,
919  flag=wx.EXPAND,
920  pos=(3,1), span=(1, 2))
921 
922  # bindings
923  self.layerType.Bind(wx.EVT_CHOICE, self.OnChangeParams)
924  self.mapset.Bind(wx.EVT_COMBOBOX, self.OnChangeParams)
925  self.layers.Bind(wx.EVT_RIGHT_DOWN, self.OnMenu)
926  self.filter.Bind(wx.EVT_TEXT, self.OnFilter)
927  self.toggle.Bind(wx.EVT_CHECKBOX, self.OnToggle)
928  return bodySizer
929 
930  def LoadMapLayers(self, type, mapset):
931  """!Load list of map layers
932 
933  @param type layer type ('raster' or 'vector')
934  @param mapset mapset name
935  """
936  self.map_layers = grass.mlist_grouped(type = type)[mapset]
937  self.layers.Set(self.map_layers)
938 
939  # check all items by default
940  for item in range(self.layers.GetCount()):
941  self.layers.Check(item)
942 
943  def OnChangeParams(self, event):
944  """!Filter parameters changed by user"""
945  # update list of layer to be loaded
946  self.LoadMapLayers(self.layerType.GetStringSelection()[:4],
947  self.mapset.GetStringSelection())
948 
949  event.Skip()
950 
951  def OnMenu(self, event):
952  """!Table description area, context menu"""
953  if not hasattr(self, "popupID1"):
954  self.popupDataID1 = wx.NewId()
955  self.popupDataID2 = wx.NewId()
956  self.popupDataID3 = wx.NewId()
957 
958  self.Bind(wx.EVT_MENU, self.OnSelectAll, id=self.popupDataID1)
959  self.Bind(wx.EVT_MENU, self.OnSelectInvert, id=self.popupDataID2)
960  self.Bind(wx.EVT_MENU, self.OnDeselectAll, id=self.popupDataID3)
961 
962  # generate popup-menu
963  menu = wx.Menu()
964  menu.Append(self.popupDataID1, _("Select all"))
965  menu.Append(self.popupDataID2, _("Invert selection"))
966  menu.Append(self.popupDataID3, _("Deselect all"))
967 
968  self.PopupMenu(menu)
969  menu.Destroy()
970 
971  def OnSelectAll(self, event):
972  """!Select all map layer from list"""
973  for item in range(self.layers.GetCount()):
974  self.layers.Check(item, True)
975 
976  def OnSelectInvert(self, event):
977  """!Invert current selection"""
978  for item in range(self.layers.GetCount()):
979  if self.layers.IsChecked(item):
980  self.layers.Check(item, False)
981  else:
982  self.layers.Check(item, True)
983 
984  def OnDeselectAll(self, event):
985  """!Select all map layer from list"""
986  for item in range(self.layers.GetCount()):
987  self.layers.Check(item, False)
988 
989  def OnFilter(self, event):
990  """!Apply filter for map names"""
991  if len(event.GetString()) == 0:
992  self.layers.Set(self.map_layers)
993  return
994 
995  list = []
996  for layer in self.map_layers:
997  try:
998  if re.compile('^' + event.GetString()).search(layer):
999  list.append(layer)
1000  except:
1001  pass
1002 
1003  self.layers.Set(list)
1004  self.OnSelectAll(None)
1005 
1006  event.Skip()
1007 
1008  def OnToggle(self, event):
1009  """!Select toggle (check or uncheck all layers)"""
1010  check = event.Checked()
1011  for item in range(self.layers.GetCount()):
1012  self.layers.Check(item, check)
1013 
1014  event.Skip()
1015 
1016  def GetMapLayers(self):
1017  """!Return list of checked map layers"""
1018  layerNames = []
1019  for indx in self.layers.GetSelections():
1020  # layers.append(self.layers.GetStringSelec(indx))
1021  pass
1022 
1023  # return fully qualified map names
1024  mapset = self.mapset.GetStringSelection()
1025  for item in range(self.layers.GetCount()):
1026  if not self.layers.IsChecked(item):
1027  continue
1028  layerNames.append(self.layers.GetString(item) + '@' + mapset)
1029 
1030  return layerNames
1031 
1032  def GetLayerType(self):
1033  """!Get selected layer type"""
1034  return self.layerType.GetStringSelection()
1035 
1036 class ImportDialog(wx.Dialog):
1037  """!Dialog for bulk import of various data (base class)"""
1038  def __init__(self, parent, itype,
1039  id = wx.ID_ANY, title = _("Multiple import"),
1040  style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
1041  self.parent = parent # GMFrame
1042  self.importType = itype
1043  self.options = dict() # list of options
1044 
1045  self.commandId = -1 # id of running command
1046 
1047  wx.Dialog.__init__(self, parent, id, title, style=style,
1048  name = "MultiImportDialog")
1049 
1050  self.panel = wx.Panel(parent=self, id=wx.ID_ANY)
1051 
1052  self.layerBox = wx.StaticBox(parent=self.panel, id=wx.ID_ANY,
1053  label=_(" List of %s layers ") % self.importType.upper())
1054 
1055  #
1056  # list of layers
1057  #
1058  self.list = LayersList(self.panel)
1059  self.list.LoadData()
1060 
1061  self.optionBox = wx.StaticBox(parent=self.panel, id=wx.ID_ANY,
1062  label="%s" % _("Options"))
1063 
1064  cmd = self._getCommand()
1065  task = gtask.parse_interface(cmd)
1066  for f in task.get_options()['flags']:
1067  name = f.get('name', '')
1068  desc = f.get('label', '')
1069  if not desc:
1070  desc = f.get('description', '')
1071  if not name and not desc:
1072  continue
1073  if cmd == 'r.in.gdal' and name not in ('o', 'e', 'l', 'k'):
1074  continue
1075  elif cmd == 'r.external' and name not in ('o', 'e', 'r', 'h', 'v'):
1076  continue
1077  elif cmd == 'v.in.ogr' and name not in ('c', 'z', 't', 'o', 'r', 'e', 'w'):
1078  continue
1079  elif cmd == 'v.external' and name not in ('b'):
1080  continue
1081  elif cmd == 'v.in.dxf' and name not in ('e', 't', 'b', 'f', 'i'):
1082  continue
1083  self.options[name] = wx.CheckBox(parent = self.panel, id = wx.ID_ANY,
1084  label = desc)
1085 
1086 
1087  self.overwrite = wx.CheckBox(parent=self.panel, id=wx.ID_ANY,
1088  label=_("Allow output files to overwrite existing files"))
1089  self.overwrite.SetValue(UserSettings.Get(group='cmd', key='overwrite', subkey='enabled'))
1090 
1091  self.add = wx.CheckBox(parent=self.panel, id=wx.ID_ANY)
1092 
1093  #
1094  # buttons
1095  #
1096  # cancel
1097  self.btn_cancel = wx.Button(parent=self.panel, id=wx.ID_CANCEL)
1098  self.btn_cancel.SetToolTipString(_("Close dialog"))
1099  self.btn_cancel.Bind(wx.EVT_BUTTON, self.OnCancel)
1100  # run
1101  self.btn_run = wx.Button(parent=self.panel, id=wx.ID_OK, label = _("&Import"))
1102  self.btn_run.SetToolTipString(_("Import selected layers"))
1103  self.btn_run.SetDefault()
1104  self.btn_run.Enable(False)
1105  self.btn_run.Bind(wx.EVT_BUTTON, self.OnRun)
1106  # run command dialog
1107  self.btn_cmd = wx.Button(parent = self.panel, id = wx.ID_ANY,
1108  label = _("Command dialog"))
1109  self.btn_cmd.Bind(wx.EVT_BUTTON, self.OnCmdDialog)
1110 
1111  def doLayout(self):
1112  """!Do layout"""
1113  dialogSizer = wx.BoxSizer(wx.VERTICAL)
1114 
1115  # dsn input
1116  dialogSizer.Add(item = self.dsnInput, proportion = 0,
1117  flag = wx.EXPAND)
1118 
1119  #
1120  # list of DXF layers
1121  #
1122  layerSizer = wx.StaticBoxSizer(self.layerBox, wx.HORIZONTAL)
1123 
1124  layerSizer.Add(item=self.list, proportion=1,
1125  flag=wx.ALL | wx.EXPAND, border=5)
1126 
1127  dialogSizer.Add(item=layerSizer, proportion=1,
1128  flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
1129 
1130  # options
1131  optionSizer = wx.StaticBoxSizer(self.optionBox, wx.VERTICAL)
1132  for key in self.options.keys():
1133  optionSizer.Add(item=self.options[key], proportion=0)
1134 
1135  dialogSizer.Add(item=optionSizer, proportion=0,
1136  flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=5)
1137 
1138  dialogSizer.Add(item=self.overwrite, proportion=0,
1139  flag=wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)
1140 
1141  dialogSizer.Add(item=self.add, proportion=0,
1142  flag=wx.LEFT | wx.RIGHT | wx.BOTTOM, border=5)
1143 
1144  #
1145  # buttons
1146  #
1147  btnsizer = wx.BoxSizer(orient=wx.HORIZONTAL)
1148 
1149  btnsizer.Add(item=self.btn_cmd, proportion=0,
1150  flag=wx.ALL | wx.ALIGN_CENTER,
1151  border=10)
1152 
1153  btnsizer.Add(item=self.btn_run, proportion=0,
1154  flag=wx.ALL | wx.ALIGN_CENTER,
1155  border=10)
1156 
1157  btnsizer.Add(item=self.btn_cancel, proportion=0,
1158  flag=wx.ALL | wx.ALIGN_CENTER,
1159  border=10)
1160 
1161  dialogSizer.Add(item=btnsizer, proportion=0,
1162  flag=wx.ALIGN_CENTER)
1163 
1164  # dialogSizer.SetSizeHints(self.panel)
1165  self.panel.SetAutoLayout(True)
1166  self.panel.SetSizer(dialogSizer)
1167  dialogSizer.Fit(self.panel)
1168 
1169  # auto-layout seems not work here - FIXME
1170  size = wx.Size(globalvar.DIALOG_GSELECT_SIZE[0] + 225, 550)
1171  self.SetMinSize(size)
1172  self.SetSize((size.width, size.height + 100))
1173  width = self.GetSize()[0]
1174  self.list.SetColumnWidth(col=1, width=width/2 - 50)
1175  self.Layout()
1176 
1177  def _getCommand(self):
1178  """!Get command"""
1179  return ''
1180 
1181  def OnCancel(self, event=None):
1182  """!Close dialog"""
1183  self.Close()
1184 
1185  def OnRun(self, event):
1186  """!Import/Link data (each layes as separate vector map)"""
1187  pass
1188 
1189  def OnCmdDialog(self, event):
1190  """!Show command dialog"""
1191  pass
1192 
1193  def AddLayers(self, returncode, cmd = None):
1194  """!Add imported/linked layers into layer tree"""
1195  if not self.add.IsChecked() or returncode != 0:
1196  return
1197 
1198  self.commandId += 1
1199  maptree = self.parent.curr_page.maptree
1200  layer, output = self.list.GetLayers()[self.commandId]
1201 
1202  if '@' not in output:
1203  name = output + '@' + grass.gisenv()['MAPSET']
1204  else:
1205  name = output
1206 
1207  # add imported layers into layer tree
1208  if self.importType == 'gdal':
1209  cmd = ['d.rast',
1210  'map=%s' % name]
1211  if UserSettings.Get(group='cmd', key='rasterOverlay', subkey='enabled'):
1212  cmd.append('-o')
1213 
1214  item = maptree.AddLayer(ltype = 'raster',
1215  lname = name, lchecked = False,
1216  lcmd = cmd)
1217  else:
1218  item = maptree.AddLayer(ltype = 'vector',
1219  lname = name, lchecked = False,
1220  lcmd = ['d.vect',
1221  'map=%s' % name])
1222 
1223  maptree.mapdisplay.MapWindow.ZoomToMap()
1224 
1225  def OnAbort(self, event):
1226  """!Abort running import
1227 
1228  @todo not yet implemented
1229  """
1230  pass
1231 
1232 class GdalImportDialog(ImportDialog):
1233  """!Dialog for bulk import of various raster/vector data"""
1234  def __init__(self, parent, ogr = False, link = False):
1235  self.link = link
1236  self.ogr = ogr
1237 
1238  if ogr:
1239  ImportDialog.__init__(self, parent, itype = 'ogr')
1240  if link:
1241  self.SetTitle(_("Link external vector data"))
1242  else:
1243  self.SetTitle(_("Import vector data"))
1244  else:
1245  ImportDialog.__init__(self, parent, itype = 'gdal')
1246  if link:
1247  self.SetTitle(_("Link external raster data"))
1248  else:
1249  self.SetTitle(_("Import raster data"))
1250 
1251  self.dsnInput = gselect.GdalSelect(parent = self, panel = self.panel, ogr = ogr)
1252 
1253  if link:
1254  self.add.SetLabel(_("Add linked layers into layer tree"))
1255  else:
1256  self.add.SetLabel(_("Add imported layers into layer tree"))
1257 
1258  self.add.SetValue(UserSettings.Get(group='cmd', key='addNewLayer', subkey='enabled'))
1259 
1260  if link:
1261  self.btn_run.SetLabel(_("&Link"))
1262  self.btn_run.SetToolTipString(_("Link selected layers"))
1263  if ogr:
1264  self.btn_cmd.SetToolTipString(_('Open %s dialog') % 'v.external')
1265  else:
1266  self.btn_cmd.SetToolTipString(_('Open %s dialog') % 'r.external')
1267  else:
1268  self.btn_run.SetLabel(_("&Import"))
1269  self.btn_run.SetToolTipString(_("Import selected layers"))
1270  if ogr:
1271  self.btn_cmd.SetToolTipString(_('Open %s dialog') % 'v.in.ogr')
1272  else:
1273  self.btn_cmd.SetToolTipString(_('Open %s dialog') % 'r.in.gdal')
1274 
1275  self.doLayout()
1276 
1277  def OnRun(self, event):
1278  """!Import/Link data (each layes as separate vector map)"""
1279  self.commandId = -1
1280  data = self.list.GetLayers()
1281  if not data:
1282  gcmd.GMessage(parent = self,
1283  message = _("No layers marked for import.\nOperation canceled."))
1284  return
1285 
1286  dsn = self.dsnInput.GetDsn()
1287  ext = self.dsnInput.GetFormatExt()
1288 
1289  for layer, output in data:
1290  if self.importType == 'ogr':
1291  if ext and layer.rfind(ext) > -1:
1292  layer = layer.replace('.' + ext, '')
1293  if self.link:
1294  cmd = ['v.external',
1295  'dsn=%s' % dsn,
1296  'output=%s' % output,
1297  'layer=%s' % layer]
1298  else:
1299  cmd = ['v.in.ogr',
1300  'dsn=%s' % dsn,
1301  'layer=%s' % layer,
1302  'output=%s' % output]
1303  else: # gdal
1304  if self.dsnInput.GetType() == 'dir':
1305  idsn = os.path.join(dsn, layer)
1306  else:
1307  idsn = dsn
1308 
1309  if self.link:
1310  cmd = ['r.external',
1311  'input=%s' % idsn,
1312  'output=%s' % output]
1313  else:
1314  cmd = ['r.in.gdal',
1315  'input=%s' % idsn,
1316  'output=%s' % output]
1317 
1318  if self.overwrite.IsChecked():
1319  cmd.append('--overwrite')
1320 
1321  for key in self.options.keys():
1322  if self.options[key].IsChecked():
1323  cmd.append('-%s' % key)
1324 
1325  if UserSettings.Get(group='cmd', key='overwrite', subkey='enabled'):
1326  cmd.append('--overwrite')
1327 
1328  # run in Layer Manager
1329  self.parent.goutput.RunCmd(cmd, switchPage = True,
1330  onDone = self.AddLayers)
1331 
1332  def _getCommand(self):
1333  """!Get command"""
1334  if self.link:
1335  if self.ogr:
1336  return 'v.external'
1337  else:
1338  return 'r.external'
1339  else:
1340  if self.ogr:
1341  return 'v.in.ogr'
1342  else:
1343  return 'r.in.gdal'
1344 
1345  return ''
1346 
1347  def OnCmdDialog(self, event):
1348  """!Show command dialog"""
1349  name = self._getCommand()
1350  menuform.GUI(parent = self, modal = True).ParseCommand(cmd = [name])
1351 
1353  """!Dialog for bulk import of DXF layers"""
1354  def __init__(self, parent):
1355  ImportDialog.__init__(self, parent, itype = 'dxf',
1356  title = _("Import DXF layers"))
1357 
1358  self.dsnInput = filebrowse.FileBrowseButton(parent=self.panel, id=wx.ID_ANY,
1359  size=globalvar.DIALOG_GSELECT_SIZE, labelText='',
1360  dialogTitle=_('Choose DXF file to import'),
1361  buttonText=_('Browse'),
1362  startDirectory=os.getcwd(), fileMode=0,
1363  changeCallback=self.OnSetDsn,
1364  fileMask="DXF File (*.dxf)|*.dxf")
1365 
1366  self.add.SetLabel(_("Add imported layers into layer tree"))
1367 
1368  self.add.SetValue(UserSettings.Get(group='cmd', key='addNewLayer', subkey='enabled'))
1369 
1370  self.doLayout()
1371 
1372  def _getCommand(self):
1373  """!Get command"""
1374  return 'v.in.dxf'
1375 
1376  def OnRun(self, event):
1377  """!Import/Link data (each layes as separate vector map)"""
1378  data = self.list.GetLayers()
1379 
1380  # hide dialog
1381  self.Hide()
1382 
1383  inputDxf = self.dsnInput.GetValue()
1384 
1385  for layer, output in data:
1386  cmd = ['v.in.dxf',
1387  'input=%s' % inputDxf,
1388  'layers=%s' % layer,
1389  'output=%s' % output]
1390 
1391  for key in self.options.keys():
1392  if self.options[key].IsChecked():
1393  cmd.append('-%s' % key)
1394 
1395  if self.overwrite.IsChecked() or \
1396  UserSettings.Get(group='cmd', key='overwrite', subkey='enabled'):
1397  cmd.append('--overwrite')
1398 
1399  # run in Layer Manager
1400  self.parent.goutput.RunCmd(cmd, switchPage=True,
1401  onDone = self.AddLayers)
1402 
1403  self.OnCancel()
1404 
1405  def OnSetDsn(self, event):
1406  """!Input DXF file defined, update list of layer widget"""
1407  path = event.GetString()
1408  if not path:
1409  return
1410 
1411  data = list()
1412  ret = gcmd.RunCommand('v.in.dxf',
1413  quiet = True,
1414  parent = self,
1415  read = True,
1416  flags = 'l',
1417  input = path)
1418  if not ret:
1419  self.list.LoadData()
1420  self.btn_run.Enable(False)
1421  return
1422 
1423  for line in ret.splitlines():
1424  layerId = line.split(':')[0].split(' ')[1]
1425  layerName = line.split(':')[1].strip()
1426  grassName = utils.GetValidLayerName(layerName)
1427  data.append((layerId, layerName.strip(), grassName.strip()))
1428 
1429  self.list.LoadData(data)
1430  if len(data) > 0:
1431  self.btn_run.Enable(True)
1432  else:
1433  self.btn_run.Enable(False)
1434 
1435  def OnCmdDialog(self, event):
1436  """!Show command dialog"""
1437  menuform.GUI(parent = self, modal = True).ParseCommand(cmd = ['v.in.dxf'])
1438 
1439 class LayersList(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin,
1440  listmix.CheckListCtrlMixin, listmix.TextEditMixin):
1441  """!List of layers to be imported (dxf, shp...)"""
1442  def __init__(self, parent, pos = wx.DefaultPosition,
1443  log = None):
1444  self.parent = parent
1445 
1446  wx.ListCtrl.__init__(self, parent, wx.ID_ANY,
1447  style=wx.LC_REPORT)
1448  listmix.CheckListCtrlMixin.__init__(self)
1449  self.log = log
1450 
1451  # setup mixins
1452  listmix.ListCtrlAutoWidthMixin.__init__(self)
1453  listmix.TextEditMixin.__init__(self)
1454 
1455  self.InsertColumn(0, _('Layer id'))
1456  self.InsertColumn(1, _('Layer name'))
1457  self.InsertColumn(2, _('Name for GRASS map (editable)'))
1458 
1459  self.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnPopupMenu) #wxMSW
1460  self.Bind(wx.EVT_RIGHT_UP, self.OnPopupMenu) #wxGTK
1461 
1462  def LoadData(self, data=None):
1463  """!Load data into list"""
1464  if data is None:
1465  return
1466 
1467  self.DeleteAllItems()
1468 
1469  for id, name, grassName in data:
1470  index = self.InsertStringItem(sys.maxint, str(id))
1471  self.SetStringItem(index, 1, "%s" % str(name))
1472  self.SetStringItem(index, 2, "%s" % str(grassName))
1473 
1474  if len(data) == 1:
1475  self.CheckItem(0, True)
1476 
1477  self.SetColumnWidth(col = 0, width = wx.LIST_AUTOSIZE_USEHEADER)
1478 
1479  def OnPopupMenu(self, event):
1480  """!Show popup menu"""
1481  if self.GetItemCount() < 1:
1482  return
1483 
1484  if not hasattr(self, "popupDataID1"):
1485  self.popupDataID1 = wx.NewId()
1486  self.popupDataID2 = wx.NewId()
1487 
1488  self.Bind(wx.EVT_MENU, self.OnSelectAll, id=self.popupDataID1)
1489  self.Bind(wx.EVT_MENU, self.OnSelectNone, id=self.popupDataID2)
1490 
1491  # generate popup-menu
1492  menu = wx.Menu()
1493  menu.Append(self.popupDataID1, _("Select all"))
1494  menu.Append(self.popupDataID2, _("Deselect all"))
1495 
1496  self.PopupMenu(menu)
1497  menu.Destroy()
1498 
1499  def OnSelectAll(self, event):
1500  """!Select all items"""
1501  item = -1
1502 
1503  while True:
1504  item = self.GetNextItem(item)
1505  if item == -1:
1506  break
1507  self.CheckItem(item, True)
1508 
1509  event.Skip()
1510 
1511  def OnSelectNone(self, event):
1512  """!Deselect items"""
1513  item = -1
1514 
1515  while True:
1516  item = self.GetNextItem(item, wx.LIST_STATE_SELECTED)
1517  if item == -1:
1518  break
1519  self.CheckItem(item, False)
1520 
1521  event.Skip()
1522 
1523  def OnLeftDown(self, event):
1524  """!Allow editing only output name
1525 
1526  Code taken from TextEditMixin class.
1527  """
1528  x, y = event.GetPosition()
1529 
1530  colLocs = [0]
1531  loc = 0
1532  for n in range(self.GetColumnCount()):
1533  loc = loc + self.GetColumnWidth(n)
1534  colLocs.append(loc)
1535 
1536  col = bisect(colLocs, x + self.GetScrollPos(wx.HORIZONTAL)) - 1
1537 
1538  if col == 2:
1539  listmix.TextEditMixin.OnLeftDown(self, event)
1540  else:
1541  event.Skip()
1542 
1543  def GetLayers(self):
1544  """!Get list of layers (layer name, output name)"""
1545  data = []
1546  item = -1
1547  while True:
1548  item = self.GetNextItem(item)
1549  if item == -1:
1550  break
1551  if self.IsChecked(item):
1552  # layer / output name
1553  data.append((self.GetItem(item, 1).GetText(),
1554  self.GetItem(item, 2).GetText()))
1555 
1556  return data
1557 
1558 class SetOpacityDialog(wx.Dialog):
1559  """!Set opacity of map layers"""
1560  def __init__(self, parent, id=wx.ID_ANY, title=_("Set Map Layer Opacity"),
1561  size=wx.DefaultSize, pos=wx.DefaultPosition,
1562  style=wx.DEFAULT_DIALOG_STYLE, opacity=100):
1563 
1564  self.parent = parent # GMFrame
1565  self.opacity = opacity # current opacity
1566 
1567  super(SetOpacityDialog, self).__init__(parent, id=id, pos=pos,
1568  size=size, style=style, title=title)
1569 
1570  panel = wx.Panel(parent=self, id=wx.ID_ANY)
1571 
1572  sizer = wx.BoxSizer(wx.VERTICAL)
1573 
1574  box = wx.GridBagSizer(vgap=5, hgap=5)
1575  self.value = wx.Slider(panel, id=wx.ID_ANY, value=self.opacity,
1576  style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | \
1577  wx.SL_TOP | wx.SL_LABELS,
1578  minValue=0, maxValue=100,
1579  size=(350, -1))
1580 
1581  box.Add(item=self.value,
1582  flag=wx.ALIGN_CENTRE, pos=(0, 0), span=(1, 2))
1583  box.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
1584  label=_("transparent")),
1585  pos=(1, 0))
1586  box.Add(item=wx.StaticText(parent=panel, id=wx.ID_ANY,
1587  label=_("opaque")),
1588  flag=wx.ALIGN_RIGHT,
1589  pos=(1, 1))
1590 
1591  sizer.Add(item=box, proportion=0,
1592  flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
1593 
1594  line = wx.StaticLine(parent=panel, id=wx.ID_ANY,
1595  style=wx.LI_HORIZONTAL)
1596  sizer.Add(item=line, proportion=0,
1597  flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
1598 
1599  # buttons
1600  btnsizer = wx.StdDialogButtonSizer()
1601 
1602  btnOK = wx.Button(parent=panel, id=wx.ID_OK)
1603  btnOK.SetDefault()
1604  btnsizer.AddButton(btnOK)
1605 
1606  btnCancel = wx.Button(parent=panel, id=wx.ID_CANCEL)
1607  btnsizer.AddButton(btnCancel)
1608  btnsizer.Realize()
1609 
1610  sizer.Add(item=btnsizer, proportion=0,
1611  flag=wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, border=5)
1612 
1613  panel.SetSizer(sizer)
1614  sizer.Fit(panel)
1615 
1616  self.SetSize(self.GetBestSize())
1617 
1618  self.Layout()
1619 
1620  def GetOpacity(self):
1621  """!Button 'OK' pressed"""
1622  # return opacity value
1623  opacity = float(self.value.GetValue()) / 100
1624  return opacity
1625 
1626 def GetImageHandlers(image):
1627  """!Get list of supported image handlers"""
1628  lext = list()
1629  ltype = list()
1630  for h in image.GetHandlers():
1631  lext.append(h.GetExtension())
1632 
1633  filetype = ''
1634  if 'png' in lext:
1635  filetype += "PNG file (*.png)|*.png|"
1636  ltype.append({ 'type' : wx.BITMAP_TYPE_PNG,
1637  'ext' : 'png' })
1638  filetype += "BMP file (*.bmp)|*.bmp|"
1639  ltype.append({ 'type' : wx.BITMAP_TYPE_BMP,
1640  'ext' : 'bmp' })
1641  if 'gif' in lext:
1642  filetype += "GIF file (*.gif)|*.gif|"
1643  ltype.append({ 'type' : wx.BITMAP_TYPE_GIF,
1644  'ext' : 'gif' })
1645 
1646  if 'jpg' in lext:
1647  filetype += "JPG file (*.jpg)|*.jpg|"
1648  ltype.append({ 'type' : wx.BITMAP_TYPE_JPEG,
1649  'ext' : 'jpg' })
1650 
1651  if 'pcx' in lext:
1652  filetype += "PCX file (*.pcx)|*.pcx|"
1653  ltype.append({ 'type' : wx.BITMAP_TYPE_PCX,
1654  'ext' : 'pcx' })
1655 
1656  if 'pnm' in lext:
1657  filetype += "PNM file (*.pnm)|*.pnm|"
1658  ltype.append({ 'type' : wx.BITMAP_TYPE_PNM,
1659  'ext' : 'pnm' })
1660 
1661  if 'tif' in lext:
1662  filetype += "TIF file (*.tif)|*.tif|"
1663  ltype.append({ 'type' : wx.BITMAP_TYPE_TIF,
1664  'ext' : 'tif' })
1665 
1666  if 'xpm' in lext:
1667  filetype += "XPM file (*.xpm)|*.xpm"
1668  ltype.append({ 'type' : wx.BITMAP_TYPE_XPM,
1669  'ext' : 'xpm' })
1670 
1671  return filetype, ltype
1672 
1673 class StaticWrapText(wx.StaticText):
1674  """!A Static Text field that wraps its text to fit its width,
1675  enlarging its height if necessary.
1676  """
1677  def __init__(self, parent, id = wx.ID_ANY, label = '', *args, **kwds):
1678  self.parent = parent
1679  self.originalLabel = label
1680 
1681  wx.StaticText.__init__(self, parent, id, label = '', *args, **kwds)
1682 
1683  self.SetLabel(label)
1684  self.Bind(wx.EVT_SIZE, self.OnResize)
1685 
1686  def SetLabel(self, label):
1687  self.originalLabel = label
1688  self.wrappedSize = None
1689  self.OnResize(None)
1690 
1691  def OnResize(self, event):
1692  if not getattr(self, "resizing", False):
1693  self.resizing = True
1694  newSize = wx.Size(self.parent.GetSize().width - 50,
1695  self.GetSize().height)
1696  if self.wrappedSize != newSize:
1697  wx.StaticText.SetLabel(self, self.originalLabel)
1698  self.Wrap(newSize.width)
1699  self.wrappedSize = newSize
1700 
1701  self.SetSize(self.wrappedSize)
1702  del self.resizing
1703 
1704 class ImageSizeDialog(wx.Dialog):
1705  """!Set size for saved graphic file"""
1706  def __init__(self, parent, id = wx.ID_ANY, title=_("Set image size"),
1707  style = wx.DEFAULT_DIALOG_STYLE, **kwargs):
1708  self.parent = parent
1709 
1710  wx.Dialog.__init__(self, parent, id = id, style=style, title=title, **kwargs)
1711 
1712  self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
1713 
1714  self.box = wx.StaticBox(parent = self.panel, id = wx.ID_ANY,
1715  label = ' % s' % _("Image size"))
1716 
1717  size = self.parent.GetWindow().GetClientSize()
1718  self.width = wx.SpinCtrl(parent = self.panel, id = wx.ID_ANY,
1719  style = wx.SP_ARROW_KEYS)
1720  self.width.SetRange(20, 1e6)
1721  self.width.SetValue(size.width)
1722  wx.CallAfter(self.width.SetFocus)
1723  self.height = wx.SpinCtrl(parent = self.panel, id = wx.ID_ANY,
1724  style = wx.SP_ARROW_KEYS)
1725  self.height.SetRange(20, 1e6)
1726  self.height.SetValue(size.height)
1727  self.template = wx.Choice(parent = self.panel, id = wx.ID_ANY,
1728  size = (125, -1),
1729  choices = [ "",
1730  "640x480",
1731  "800x600",
1732  "1024x768",
1733  "1280x960",
1734  "1600x1200",
1735  "1920x1440" ])
1736 
1737  self.btnOK = wx.Button(parent = self.panel, id = wx.ID_OK)
1738  self.btnOK.SetDefault()
1739  self.btnCancel = wx.Button(parent = self.panel, id = wx.ID_CANCEL)
1740 
1741  self.template.Bind(wx.EVT_CHOICE, self.OnTemplate)
1742 
1743  self._layout()
1744  self.SetSize(self.GetBestSize())
1745 
1746  def _layout(self):
1747  """!Do layout"""
1748  sizer = wx.BoxSizer(wx.VERTICAL)
1749 
1750  # body
1751  box = wx.StaticBoxSizer(self.box, wx.HORIZONTAL)
1752  fbox = wx.FlexGridSizer(cols = 2, vgap = 5, hgap = 5)
1753  fbox.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
1754  label = _("Width:")),
1755  flag = wx.ALIGN_CENTER_VERTICAL)
1756  fbox.Add(item = self.width)
1757  fbox.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
1758  label = _("Height:")),
1759  flag = wx.ALIGN_CENTER_VERTICAL)
1760  fbox.Add(item = self.height)
1761  fbox.Add(item = wx.StaticText(parent = self.panel, id = wx.ID_ANY,
1762  label = _("Template:")),
1763  flag = wx.ALIGN_CENTER_VERTICAL)
1764  fbox.Add(item = self.template)
1765 
1766  box.Add(item = fbox, proportion = 1,
1767  flag = wx.EXPAND | wx.ALL, border = 5)
1768  sizer.Add(item = box, proportion = 1,
1769  flag=wx.EXPAND | wx.ALL, border = 3)
1770 
1771  # buttons
1772  btnsizer = wx.StdDialogButtonSizer()
1773  btnsizer.AddButton(self.btnOK)
1774  btnsizer.AddButton(self.btnCancel)
1775  btnsizer.Realize()
1776 
1777  sizer.Add(item = btnsizer, proportion = 0,
1778  flag = wx.EXPAND | wx.ALIGN_RIGHT | wx.ALL, border=5)
1779 
1780  self.panel.SetSizer(sizer)
1781  sizer.Fit(self.panel)
1782  self.Layout()
1783 
1784  def GetValues(self):
1785  """!Get width/height values"""
1786  return self.width.GetValue(), self.height.GetValue()
1787 
1788  def OnTemplate(self, event):
1789  """!Template selected"""
1790  sel = event.GetString()
1791  if not sel:
1792  width, height = self.parent.GetWindow().GetClientSize()
1793  else:
1794  width, height = map(int, sel.split('x'))
1795  self.width.SetValue(width)
1796  self.height.SetValue(height)
1797