GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
vdigit/dialogs.py
Go to the documentation of this file.
1 """!
2 @package vdigit.dialogs
3 
4 @brief wxGUI vector digitizer dialogs
5 
6 Classes:
7  - dialogs::VDigitCategoryDialog
8  - dialogs::CategoryListCtrl
9  - dialogs::VDigitZBulkDialog
10  - dialogs::VDigitDuplicatesDialog
11  - dialogs::CheckListFeature
12 
13 (C) 2007-2011 by the GRASS Development Team
14 
15 This program is free software under the GNU General Public License
16 (>=v2). Read the file COPYING that comes with GRASS for details.
17 
18 @author Martin Landa <landa.martin gmail.com>
19 """
20 
21 import sys
22 import copy
23 
24 import wx
25 import wx.lib.mixins.listctrl as listmix
26 
27 from core.gcmd import RunCommand, GError
28 from core.debug import Debug
29 from core.settings import UserSettings
30 
31 class VDigitCategoryDialog(wx.Dialog, listmix.ColumnSorterMixin):
32  def __init__(self, parent, title,
33  vectorName, query = None, cats = None,
34  style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER, **kwargs):
35  """!Dialog used to display/modify categories of vector objects
36 
37  @param parent
38  @param title dialog title
39  @param query {coordinates, qdist} - used by v.edit/v.what
40  @param cats directory of lines (layer/categories) - used by vdigit
41  @param style dialog style
42  """
43  self.parent = parent # mapdisplay.BufferedWindow class instance
44  self.digit = parent.digit
45 
46  # map name
47  self.vectorName = vectorName
48 
49  # line : {layer: [categories]}
50  self.cats = {}
51 
52  # do not display dialog if no line is found (-> self.cats)
53  if cats is None:
54  if self._getCategories(query[0], query[1]) == 0 or not self.line:
55  Debug.msg(3, "VDigitCategoryDialog(): nothing found!")
56  else:
57  self.cats = cats
58  for line in cats.keys():
59  for layer in cats[line].keys():
60  self.cats[line][layer] = list(cats[line][layer])
61 
62  layers = []
63  for layer in self.digit.GetLayers():
64  layers.append(str(layer))
65 
66  # make copy of cats (used for 'reload')
67  self.cats_orig = copy.deepcopy(self.cats)
68 
69  wx.Dialog.__init__(self, parent = self.parent, id = wx.ID_ANY, title = title,
70  style = style, **kwargs)
71 
72  # list of categories
73  box = wx.StaticBox(parent = self, id = wx.ID_ANY,
74  label = " %s " % _("List of categories - right-click to delete"))
75  listSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
76  self.list = CategoryListCtrl(parent = self, id = wx.ID_ANY,
77  style = wx.LC_REPORT |
78  wx.BORDER_NONE |
79  wx.LC_SORT_ASCENDING |
80  wx.LC_HRULES |
81  wx.LC_VRULES)
82  # sorter
83  self.fid = self.cats.keys()[0]
84  self.itemDataMap = self.list.Populate(self.cats[self.fid])
85  listmix.ColumnSorterMixin.__init__(self, 2)
86  self.fidMulti = wx.Choice(parent = self, id = wx.ID_ANY,
87  size = (150, -1))
88  self.fidMulti.Bind(wx.EVT_CHOICE, self.OnFeature)
89  self.fidText = wx.StaticText(parent = self, id = wx.ID_ANY)
90  if len(self.cats.keys()) == 1:
91  self.fidMulti.Show(False)
92  self.fidText.SetLabel(str(self.fid))
93  else:
94  self.fidText.Show(False)
95  choices = []
96  for fid in self.cats.keys():
97  choices.append(str(fid))
98  self.fidMulti.SetItems(choices)
99  self.fidMulti.SetSelection(0)
100 
101  listSizer.Add(item = self.list, proportion = 1, flag = wx.EXPAND)
102 
103  # add new category
104  box = wx.StaticBox(parent = self, id = wx.ID_ANY,
105  label = " %s " % _("Add new category"))
106  addSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
107  flexSizer = wx.FlexGridSizer (cols = 5, hgap = 5, vgap = 5)
108  flexSizer.AddGrowableCol(3)
109 
110  layerNewTxt = wx.StaticText(parent = self, id = wx.ID_ANY,
111  label = "%s:" % _("Layer"))
112  self.layerNew = wx.Choice(parent = self, id = wx.ID_ANY, size = (75, -1),
113  choices = layers)
114  if len(layers) > 0:
115  self.layerNew.SetSelection(0)
116 
117  catNewTxt = wx.StaticText(parent = self, id = wx.ID_ANY,
118  label = "%s:" % _("Category"))
119 
120  try:
121  newCat = max(self.cats[self.fid][1]) + 1
122  except KeyError:
123  newCat = 1
124  self.catNew = wx.SpinCtrl(parent = self, id = wx.ID_ANY, size = (75, -1),
125  initial = newCat, min = 0, max = 1e9)
126  btnAddCat = wx.Button(self, wx.ID_ADD)
127  flexSizer.Add(item = layerNewTxt, proportion = 0,
128  flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
129  flexSizer.Add(item = self.layerNew, proportion = 0,
130  flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
131  flexSizer.Add(item = catNewTxt, proportion = 0,
132  flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_RIGHT | wx.LEFT,
133  border = 10)
134  flexSizer.Add(item = self.catNew, proportion = 0,
135  flag = wx.FIXED_MINSIZE | wx.ALIGN_CENTER_VERTICAL)
136  flexSizer.Add(item = btnAddCat, proportion = 0,
137  flag = wx.EXPAND | wx.ALIGN_RIGHT | wx.FIXED_MINSIZE)
138  addSizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 5)
139 
140  # buttons
141  btnApply = wx.Button(self, wx.ID_APPLY)
142  btnApply.SetToolTipString(_("Apply changes"))
143  btnCancel = wx.Button(self, wx.ID_CANCEL)
144  btnCancel.SetToolTipString(_("Ignore changes and close dialog"))
145  btnOk = wx.Button(self, wx.ID_OK)
146  btnOk.SetToolTipString(_("Apply changes and close dialog"))
147  btnOk.SetDefault()
148 
149  # sizers
150  btnSizer = wx.StdDialogButtonSizer()
151  btnSizer.AddButton(btnCancel)
152  #btnSizer.AddButton(btnReload)
153  #btnSizer.SetNegativeButton(btnReload)
154  btnSizer.AddButton(btnApply)
155  btnSizer.AddButton(btnOk)
156  btnSizer.Realize()
157 
158  mainSizer = wx.BoxSizer(wx.VERTICAL)
159  mainSizer.Add(item = listSizer, proportion = 1,
160  flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
161  mainSizer.Add(item = addSizer, proportion = 0,
162  flag = wx.EXPAND | wx.ALIGN_CENTER |
163  wx.LEFT | wx.RIGHT | wx.BOTTOM, border = 5)
164  fidSizer = wx.BoxSizer(wx.HORIZONTAL)
165  fidSizer.Add(item = wx.StaticText(parent = self, id = wx.ID_ANY,
166  label = _("Feature id:")),
167  proportion = 0, border = 5,
168  flag = wx.ALIGN_CENTER_VERTICAL)
169  fidSizer.Add(item = self.fidMulti, proportion = 0,
170  flag = wx.EXPAND | wx.ALL, border = 5)
171  fidSizer.Add(item = self.fidText, proportion = 0,
172  flag = wx.EXPAND | wx.ALL, border = 5)
173  mainSizer.Add(item = fidSizer, proportion = 0,
174  flag = wx.EXPAND | wx.ALL, border = 5)
175  mainSizer.Add(item = btnSizer, proportion = 0,
176  flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
177 
178  self.SetSizer(mainSizer)
179  mainSizer.Fit(self)
180  self.SetAutoLayout(True)
181 
182  # set min size for dialog
183  self.SetMinSize(self.GetBestSize())
184 
185  # bindings
186  btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
187  btnOk.Bind(wx.EVT_BUTTON, self.OnOK)
188  btnAddCat.Bind(wx.EVT_BUTTON, self.OnAddCat)
189  btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
190 
191  # list
192  self.list.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.OnRightUp) #wxMSW
193  self.list.Bind(wx.EVT_RIGHT_UP, self.OnRightUp) #wxGTK
194  self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.OnBeginEdit, self.list)
195  self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnEndEdit, self.list)
196  self.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick, self.list)
197 
198  def GetListCtrl(self):
199  """!Used by ColumnSorterMixin
200  """
201  return self.list
202 
203  def OnColClick(self, event):
204  """!Click on column header (order by)
205  """
206  event.Skip()
207 
208  def OnBeginEdit(self, event):
209  """!Editing of item started
210  """
211  event.Allow()
212 
213  def OnEndEdit(self, event):
214  """!Finish editing of item
215  """
216  itemIndex = event.GetIndex()
217  layerOld = int (self.list.GetItem(itemIndex, 0).GetText())
218  catOld = int (self.list.GetItem(itemIndex, 1).GetText())
219 
220  if event.GetColumn() == 0:
221  layerNew = int(event.GetLabel())
222  catNew = catOld
223  else:
224  layerNew = layerOld
225  catNew = int(event.GetLabel())
226 
227  try:
228  if layerNew not in self.cats[self.fid].keys():
229  self.cats[self.fid][layerNew] = []
230  self.cats[self.fid][layerNew].append(catNew)
231  self.cats[self.fid][layerOld].remove(catOld)
232  except:
233  event.Veto()
234  self.list.SetStringItem(itemIndex, 0, str(layerNew))
235  self.list.SetStringItem(itemIndex, 1, str(catNew))
236  dlg = wx.MessageDialog(self, _("Unable to add new layer/category <%(layer)s/%(category)s>.\n"
237  "Layer and category number must be integer.\n"
238  "Layer number must be greater than zero.") %
239  { 'layer': self.layerNew.GetStringSelection(),
240  'category' : str(self.catNew.GetValue()) },
241  _("Error"), wx.OK | wx.ICON_ERROR)
242  dlg.ShowModal()
243  dlg.Destroy()
244  return False
245 
246  def OnRightDown(self, event):
247  """!Mouse right button down
248  """
249  x = event.GetX()
250  y = event.GetY()
251  item, flags = self.list.HitTest((x, y))
252 
253  if item != wx.NOT_FOUND and \
254  flags & wx.LIST_HITTEST_ONITEM:
255  self.list.Select(item)
256 
257  event.Skip()
258 
259  def OnRightUp(self, event):
260  """!Mouse right button up
261  """
262  if not hasattr(self, "popupID1"):
263  self.popupID1 = wx.NewId()
264  self.popupID2 = wx.NewId()
265  self.popupID3 = wx.NewId()
266  self.Bind(wx.EVT_MENU, self.OnItemDelete, id = self.popupID1)
267  self.Bind(wx.EVT_MENU, self.OnItemDeleteAll, id = self.popupID2)
268  self.Bind(wx.EVT_MENU, self.OnReload, id = self.popupID3)
269 
270  # generate popup-menu
271  menu = wx.Menu()
272  menu.Append(self.popupID1, _("Delete selected"))
273  if self.list.GetFirstSelected() == -1:
274  menu.Enable(self.popupID1, False)
275 
276  menu.Append(self.popupID2, _("Delete all"))
277  menu.AppendSeparator()
278  menu.Append(self.popupID3, _("Reload"))
279 
280  self.PopupMenu(menu)
281  menu.Destroy()
282 
283  def OnItemSelected(self, event):
284  """!Item selected
285  """
286  event.Skip()
287 
288  def OnItemDelete(self, event):
289  """!Delete selected item(s) from the list (layer/category pair)
290  """
291  item = self.list.GetFirstSelected()
292  while item != -1:
293  layer = int (self.list.GetItem(item, 0).GetText())
294  cat = int (self.list.GetItem(item, 1).GetText())
295  self.list.DeleteItem(item)
296  self.cats[self.fid][layer].remove(cat)
297 
298  item = self.list.GetFirstSelected()
299 
300  event.Skip()
301 
302  def OnItemDeleteAll(self, event):
303  """!Delete all items from the list
304  """
305  self.list.DeleteAllItems()
306  self.cats[self.fid] = {}
307 
308  event.Skip()
309 
310  def OnFeature(self, event):
311  """!Feature id changed (on duplicates)
312  """
313  self.fid = int(event.GetString())
314 
315  self.itemDataMap = self.list.Populate(self.cats[self.fid],
316  update = True)
317 
318  try:
319  newCat = max(self.cats[self.fid][1]) + 1
320  except KeyError:
321  newCat = 1
322 
323  self.catNew.SetValue(newCat)
324 
325  event.Skip()
326 
327  def _getCategories(self, coords, qdist):
328  """!Get layer/category pairs for all available
329  layers
330 
331  Return True line found or False if not found
332  """
333  ret = RunCommand('v.what',
334  parent = self,
335  quiet = True,
336  map = self.vectorName,
337  east_north = '%f,%f' % \
338  (float(coords[0]), float(coords[1])),
339  distance = qdist)
340 
341  if not ret:
342  return False
343 
344  for item in ret.splitlines():
345  litem = item.lower()
346  if "id:" in litem: # get line id
347  self.line = int(item.split(':')[1].strip())
348  elif "layer:" in litem: # add layer
349  layer = int(item.split(':')[1].strip())
350  if layer not in self.cats.keys():
351  self.cats[layer] = []
352  elif "category:" in litem: # add category
353  self.cats[layer].append(int(item.split(':')[1].strip()))
354 
355  return True
356 
357  def OnReload(self, event):
358  """!Reload button pressed
359  """
360  # restore original list
361  self.cats = copy.deepcopy(self.cats_orig)
362 
363  # polulate list
364  self.itemDataMap = self.list.Populate(self.cats[self.fid],
365  update = True)
366 
367  event.Skip()
368 
369  def OnCancel(self, event):
370  """!Cancel button pressed
371  """
372  self.parent.parent.dialogs['category'] = None
373  if self.digit:
374  self.digit.GetDisplay().SetSelected([])
375  self.parent.UpdateMap(render = False)
376  else:
377  self.parent.parent.OnRender(None)
378 
379  self.Close()
380 
381  def OnApply(self, event):
382  """!Apply button pressed
383  """
384  for fid in self.cats.keys():
385  newfid = self.ApplyChanges(fid)
386  if fid == self.fid and newfid > 0:
387  self.fid = newfid
388 
389  def ApplyChanges(self, fid):
390  """!Apply changes
391 
392  @param fid feature id
393  """
394  cats = self.cats[fid]
395  cats_orig = self.cats_orig[fid]
396 
397  # action : (catsFrom, catsTo)
398  check = {'catadd': (cats, cats_orig),
399  'catdel': (cats_orig, cats)}
400 
401  newfid = -1
402 
403  # add/delete new category
404  for action, catsCurr in check.iteritems():
405  for layer in catsCurr[0].keys():
406  catList = []
407  for cat in catsCurr[0][layer]:
408  if layer not in catsCurr[1].keys() or \
409  cat not in catsCurr[1][layer]:
410  catList.append(cat)
411  if catList != []:
412  if action == 'catadd':
413  add = True
414  else:
415  add = False
416 
417  newfid = self.digit.SetLineCats(fid, layer,
418  catList, add)
419  if len(self.cats.keys()) == 1:
420  self.fidText.SetLabel("%d" % newfid)
421  else:
422  choices = self.fidMulti.GetItems()
423  choices[choices.index(str(fid))] = str(newfid)
424  self.fidMulti.SetItems(choices)
425  self.fidMulti.SetStringSelection(str(newfid))
426 
427  self.cats[newfid] = self.cats[fid]
428  del self.cats[fid]
429 
430  fid = newfid
431  if self.fid < 0:
432  wx.MessageBox(parent = self, message = _("Unable to update vector map."),
433  caption = _("Error"), style = wx.OK | wx.ICON_ERROR)
434 
435  self.cats_orig[fid] = copy.deepcopy(cats)
436 
437  return newfid
438 
439  def OnOK(self, event):
440  """!OK button pressed
441  """
442  self.OnApply(event)
443  self.OnCancel(event)
444 
445  def OnAddCat(self, event):
446  """!Button 'Add' new category pressed
447  """
448  try:
449  layer = int(self.layerNew.GetStringSelection())
450  cat = int(self.catNew.GetValue())
451  if layer <= 0:
452  raise ValueError
453  except ValueError:
454  GError(parent = self,
455  message = _("Unable to add new layer/category <%(layer)s/%(category)s>.\n"
456  "Layer and category number must be integer.\n"
457  "Layer number must be greater than zero.") %
458  {'layer' : str(self.layerNew.GetValue()),
459  'category' : str(self.catNew.GetValue())})
460  return False
461 
462  if layer not in self.cats[self.fid].keys():
463  self.cats[self.fid][layer] = []
464 
465  self.cats[self.fid][layer].append(cat)
466 
467  # reload list
468  self.itemDataMap = self.list.Populate(self.cats[self.fid],
469  update = True)
470 
471  # update category number for add
472  self.catNew.SetValue(cat + 1)
473 
474  event.Skip()
475 
476  return True
477 
478  def GetLine(self):
479  """!Get id of selected line of 'None' if no line is selected
480  """
481  return self.cats.keys()
482 
483  def UpdateDialog(self, query = None, cats = None):
484  """!Update dialog
485 
486  @param query {coordinates, distance} - v.what
487  @param cats directory layer/cats - vdigit
488  Return True if updated otherwise False
489  """
490  # line: {layer: [categories]}
491  self.cats = {}
492  # do not display dialog if no line is found (-> self.cats)
493  if cats is None:
494  ret = self._getCategories(query[0], query[1])
495  else:
496  self.cats = cats
497  for line in cats.keys():
498  for layer in cats[line].keys():
499  self.cats[line][layer] = list(cats[line][layer])
500  ret = 1
501  if ret == 0 or len(self.cats.keys()) < 1:
502  Debug.msg(3, "VDigitCategoryDialog(): nothing found!")
503  return False
504 
505  # make copy of cats (used for 'reload')
506  self.cats_orig = copy.deepcopy(self.cats)
507 
508  # polulate list
509  self.fid = self.cats.keys()[0]
510  self.itemDataMap = self.list.Populate(self.cats[self.fid],
511  update = True)
512 
513  try:
514  newCat = max(self.cats[self.fid][1]) + 1
515  except KeyError:
516  newCat = 1
517  self.catNew.SetValue(newCat)
518 
519  if len(self.cats.keys()) == 1:
520  self.fidText.Show(True)
521  self.fidMulti.Show(False)
522  self.fidText.SetLabel("%d" % self.fid)
523  else:
524  self.fidText.Show(False)
525  self.fidMulti.Show(True)
526  choices = []
527  for fid in self.cats.keys():
528  choices.append(str(fid))
529  self.fidMulti.SetItems(choices)
530  self.fidMulti.SetSelection(0)
531 
532  self.Layout()
533 
534  return True
535 
536 class CategoryListCtrl(wx.ListCtrl,
537  listmix.ListCtrlAutoWidthMixin,
538  listmix.TextEditMixin):
539  def __init__(self, parent, id, pos = wx.DefaultPosition,
540  size = wx.DefaultSize, style = 0):
541  """!List of layers/categories"""
542  self.parent = parent
543 
544  wx.ListCtrl.__init__(self, parent, id, pos, size, style)
545 
546  listmix.ListCtrlAutoWidthMixin.__init__(self)
547  listmix.TextEditMixin.__init__(self)
548 
549  def Populate(self, cats, update = False):
550  """!Populate the list
551  """
552  itemData = {} # requested by sorter
553 
554  if not update:
555  self.InsertColumn(0, _("Layer"))
556  self.InsertColumn(1, _("Category"))
557  else:
558  self.DeleteAllItems()
559 
560  i = 1
561  for layer in cats.keys():
562  catsList = cats[layer]
563  for cat in catsList:
564  index = self.InsertStringItem(sys.maxint, str(catsList[0]))
565  self.SetStringItem(index, 0, str(layer))
566  self.SetStringItem(index, 1, str(cat))
567  self.SetItemData(index, i)
568  itemData[i] = (str(layer), str(cat))
569  i = i + 1
570 
571  if not update:
572  self.SetColumnWidth(0, 100)
573  self.SetColumnWidth(1, wx.LIST_AUTOSIZE)
574 
575  self.currentItem = 0
576 
577  return itemData
578 
579 class VDigitZBulkDialog(wx.Dialog):
580  def __init__(self, parent, title, nselected, style = wx.DEFAULT_DIALOG_STYLE):
581  """!Dialog used for Z bulk-labeling tool
582  """
583  wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title, style = style)
584 
585  self.parent = parent # mapdisplay.BufferedWindow class instance
586 
587  # panel = wx.Panel(parent=self, id=wx.ID_ANY)
588 
589  border = wx.BoxSizer(wx.VERTICAL)
590 
591  txt = wx.StaticText(parent = self,
592  label = _("%d lines selected for z bulk-labeling") % nselected);
593  border.Add(item = txt, proportion = 0, flag = wx.ALL | wx.EXPAND, border = 5)
594 
595  box = wx.StaticBox (parent = self, id = wx.ID_ANY, label = " %s " % _("Set value"))
596  sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
597  flexSizer = wx.FlexGridSizer (cols = 2, hgap = 5, vgap = 5)
598  flexSizer.AddGrowableCol(0)
599 
600  # starting value
601  txt = wx.StaticText(parent = self,
602  label = _("Starting value"));
603  self.value = wx.SpinCtrl(parent = self, id = wx.ID_ANY, size = (150, -1),
604  initial = 0,
605  min = -1e6, max = 1e6)
606  flexSizer.Add(txt, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
607  flexSizer.Add(self.value, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
608 
609  # step
610  txt = wx.StaticText(parent = self,
611  label = _("Step"))
612  self.step = wx.SpinCtrl(parent = self, id = wx.ID_ANY, size = (150, -1),
613  initial = 0,
614  min = 0, max = 1e6)
615  flexSizer.Add(txt, proportion = 0, flag = wx.ALIGN_CENTER_VERTICAL)
616  flexSizer.Add(self.step, proportion = 0, flag = wx.ALIGN_CENTER | wx.FIXED_MINSIZE)
617 
618  sizer.Add(item = flexSizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 1)
619  border.Add(item = sizer, proportion = 1, flag = wx.ALL | wx.EXPAND, border = 0)
620 
621  # buttons
622  btnCancel = wx.Button(self, wx.ID_CANCEL)
623  btnOk = wx.Button(self, wx.ID_OK)
624  btnOk.SetDefault()
625 
626  # sizers
627  btnSizer = wx.StdDialogButtonSizer()
628  btnSizer.AddButton(btnCancel)
629  btnSizer.AddButton(btnOk)
630  btnSizer.Realize()
631 
632  mainSizer = wx.BoxSizer(wx.VERTICAL)
633  mainSizer.Add(item = border, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
634  mainSizer.Add(item = btnSizer, proportion = 0,
635  flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
636 
637  self.SetSizer(mainSizer)
638  mainSizer.Fit(self)
639 
640 class VDigitDuplicatesDialog(wx.Dialog):
641  def __init__(self, parent, data, title = _("List of duplicates"),
642  style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
643  pos = wx.DefaultPosition):
644  """!Show duplicated feature ids
645  """
646  wx.Dialog.__init__(self, parent = parent, id = wx.ID_ANY, title = title, style = style,
647  pos = pos)
648 
649  self.parent = parent # BufferedWindow
650  self.data = data
651  self.winList = []
652 
653  # panel = wx.Panel(parent=self, id=wx.ID_ANY)
654 
655  # notebook
656  self.notebook = wx.Notebook(parent = self, id = wx.ID_ANY, style = wx.BK_DEFAULT)
657 
658  id = 1
659  for key in self.data.keys():
660  panel = wx.Panel(parent = self.notebook, id = wx.ID_ANY)
661  self.notebook.AddPage(page = panel, text = " %d " % (id))
662 
663  # notebook body
664  border = wx.BoxSizer(wx.VERTICAL)
665 
666  win = CheckListFeature(parent = panel, data = list(self.data[key]))
667  self.winList.append(win.GetId())
668 
669  border.Add(item = win, proportion = 1,
670  flag = wx.ALL | wx.EXPAND, border = 5)
671 
672  panel.SetSizer(border)
673 
674  id += 1
675 
676  # buttons
677  btnCancel = wx.Button(self, wx.ID_CANCEL)
678  btnOk = wx.Button(self, wx.ID_OK)
679  btnOk.SetDefault()
680 
681  # sizers
682  btnSizer = wx.StdDialogButtonSizer()
683  btnSizer.AddButton(btnCancel)
684  btnSizer.AddButton(btnOk)
685  btnSizer.Realize()
686 
687  mainSizer = wx.BoxSizer(wx.VERTICAL)
688  mainSizer.Add(item = self.notebook, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
689  mainSizer.Add(item = btnSizer, proportion = 0,
690  flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border = 5)
691 
692  self.SetSizer(mainSizer)
693  mainSizer.Fit(self)
694  self.SetAutoLayout(True)
695 
696  # set min size for dialog
697  self.SetMinSize((250, 180))
698 
699  def GetUnSelected(self):
700  """!Get unselected items (feature id)
701 
702  @return list of ids
703  """
704  ids = []
705  for id in self.winList:
706  wlist = self.FindWindowById(id)
707 
708  for item in range(wlist.GetItemCount()):
709  if not wlist.IsChecked(item):
710  ids.append(int(wlist.GetItem(item, 0).GetText()))
711 
712  return ids
713 
714 class CheckListFeature(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin, listmix.CheckListCtrlMixin):
715  def __init__(self, parent, data,
716  pos = wx.DefaultPosition, log = None):
717  """!List of mapset/owner/group
718  """
719  self.parent = parent
720  self.data = data
721 
722  wx.ListCtrl.__init__(self, parent, wx.ID_ANY,
723  style = wx.LC_REPORT)
724 
725  listmix.CheckListCtrlMixin.__init__(self)
726 
727  self.log = log
728 
729  # setup mixins
730  listmix.ListCtrlAutoWidthMixin.__init__(self)
731 
732  self.LoadData(self.data)
733 
734  def LoadData(self, data):
735  """!Load data into list
736  """
737  self.InsertColumn(0, _('Feature id'))
738  self.InsertColumn(1, _('Layer (Categories)'))
739 
740  for item in data:
741  index = self.InsertStringItem(sys.maxint, str(item[0]))
742  self.SetStringItem(index, 1, str(item[1]))
743 
744  # enable all items by default
745  for item in range(self.GetItemCount()):
746  self.CheckItem(item, True)
747 
748  self.SetColumnWidth(col = 0, width = wx.LIST_AUTOSIZE_USEHEADER)
749  self.SetColumnWidth(col = 1, width = wx.LIST_AUTOSIZE_USEHEADER)
750 
751  def OnCheckItem(self, index, flag):
752  """!Mapset checked/unchecked
753  """
754  pass
def OnItemSelected
Item selected.
def GetLine
Get id of selected line of &#39;None&#39; if no line is selected.
def __init__
List of layers/categories.
wxGUI command interface
def OnApply
Apply button pressed.
def UpdateDialog
Update dialog.
def OnCancel
Cancel button pressed.
def OnReload
Reload button pressed.
wxGUI debugging
def OnItemDeleteAll
Delete all items from the list.
def GetUnSelected
Get unselected items (feature id)
def OnBeginEdit
Editing of item started.
def OnColClick
Click on column header (order by)
#define max(x, y)
Definition: draw2.c:69
def LoadData
Load data into list.
def OnRightUp
Mouse right button up.
def __init__
Dialog used to display/modify categories of vector objects.
def Populate
Populate the list.
def __init__
Dialog used for Z bulk-labeling tool.
def __init__
Show duplicated feature ids.
def _getCategories
Get layer/category pairs for all available layers.
def GetListCtrl
Used by ColumnSorterMixin.
def ApplyChanges
Apply changes.
def __init__
List of mapset/owner/group.
def OnFeature
Feature id changed (on duplicates)
def OnItemDelete
Delete selected item(s) from the list (layer/category pair)
Default GUI settings.
tuple range
Definition: tools.py:1406
def OnEndEdit
Finish editing of item.
def OnRightDown
Mouse right button down.
def OnAddCat
Button &#39;Add&#39; new category pressed.
def OnOK
OK button pressed.
def OnCheckItem
Mapset checked/unchecked.
def RunCommand
Run GRASS command.
Definition: gcmd.py:625