dialogs.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. """!
  2. @package iclass::toolbars
  3. @brief wxIClass dialogs
  4. Classes:
  5. - dialogs::IClassGroupDialog
  6. - dialogs::IClassMapDialog
  7. - dialogs::IClassCategoryManagerDialog
  8. - dialogs::CategoryListCtrl
  9. (C) 2006-2011 by the GRASS Development Team
  10. This program is free software under the GNU General Public
  11. License (>=v2). Read the file COPYING that comes with GRASS
  12. for details.
  13. @author Vaclav Petras <wenzeslaus gmail.com>
  14. @author Anna Kratochvilova <kratochanna gmail.com>
  15. """
  16. import wx
  17. import wx.lib.mixins.listctrl as listmix
  18. from core import globalvar
  19. from gui_core.dialogs import ElementDialog, GroupDialog
  20. from gui_core import gselect
  21. from iclass.statistics import Statistics, BandStatistics
  22. import grass.script as grass
  23. class IClassGroupDialog(ElementDialog):
  24. """!Dialog for imagery group selection"""
  25. def __init__(self, parent, group = None, title = _("Select imagery group"), id = wx.ID_ANY):
  26. """!
  27. Does post init and layout.
  28. @param gui parent
  29. @param title dialog window title
  30. @param id wx id
  31. """
  32. ElementDialog.__init__(self, parent, title, label = _("Name of imagery group:"))
  33. self.element = gselect.Select(parent = self.panel, type = 'group',
  34. mapsets = [grass.gisenv()['MAPSET']],
  35. size = globalvar.DIALOG_GSELECT_SIZE)
  36. if group:
  37. self.element.SetValue(group)
  38. self.editGroup = wx.Button(parent = self.panel, id = wx.ID_ANY,
  39. label = _("Create/edit group..."))
  40. self.editGroup.Bind(wx.EVT_BUTTON, self.OnEditGroup)
  41. self.PostInit()
  42. self.__Layout()
  43. self.SetMinSize(self.GetSize())
  44. def __Layout(self):
  45. """!Do layout"""
  46. self.dataSizer.Add(self.element, proportion = 0,
  47. flag = wx.EXPAND | wx.ALL, border = 5)
  48. self.dataSizer.Add(self.editGroup, proportion = 0,
  49. flag = wx.ALL, border = 5)
  50. self.panel.SetSizer(self.sizer)
  51. self.sizer.Fit(self)
  52. def GetGroup(self):
  53. """!Returns selected group"""
  54. return self.GetElement()
  55. def OnEditGroup(self, event):
  56. """!Launch edit group dialog"""
  57. dlg = GroupDialog(parent = self, defaultGroup = self.element.GetValue())
  58. dlg.ShowModal()
  59. gr = dlg.GetSelectedGroup()
  60. if gr in dlg.GetExistGroups():
  61. self.element.SetValue(gr)
  62. dlg.Destroy()
  63. class IClassMapDialog(ElementDialog):
  64. """!Dialog for adding raster map"""
  65. def __init__(self, parent, title = _("Add raster map"), id = wx.ID_ANY):
  66. """!
  67. Does post init and layout.
  68. @param gui parent
  69. @param title dialog window title
  70. @param id wx id
  71. """
  72. ElementDialog.__init__(self, parent, title, label = _("Name of raster map:"))
  73. self.element = gselect.Select(parent = self.panel, type = 'raster',
  74. size = globalvar.DIALOG_GSELECT_SIZE)
  75. #self.firstMapCheck = wx.CheckBox(parent = self.panel, id = wx.ID_ANY,
  76. #label = _("Add raster map to Training display"))
  77. #self.secondMapCheck = wx.CheckBox(parent = self.panel, id = wx.ID_ANY,
  78. #label = _("Add raster map to Preview display"))
  79. # in user settings
  80. #self.firstMapCheck.SetValue(True)
  81. #self.secondMapCheck.SetValue(True)
  82. self.PostInit()
  83. self.__Layout()
  84. self.SetMinSize(self.GetSize())
  85. def __Layout(self):
  86. """!Do layout"""
  87. self.dataSizer.Add(self.element, proportion = 0,
  88. flag = wx.EXPAND | wx.ALL, border = 5)
  89. #self.dataSizer.Add(self.firstMapCheck, proportion = 0,
  90. #flag = wx.ALL, border = 5)
  91. #self.dataSizer.Add(self.secondMapCheck, proportion = 0,
  92. #flag = wx.ALL, border = 5)
  93. self.panel.SetSizer(self.sizer)
  94. self.sizer.Fit(self)
  95. def GetRasterMap(self):
  96. """!Returns selected raster map"""
  97. return self.GetElement()
  98. #def IfAddToFirstMap(self):
  99. #return self.firstMapCheck.IsChecked()
  100. #def IfAddToSecondMap(self):
  101. #return self.secondMapCheck.IsChecked()
  102. class IClassCategoryManagerDialog(wx.Dialog):
  103. """!Dialog for managing categories (classes).
  104. Alows adding, deleting class and changing its name and color.
  105. """
  106. def __init__(self, parent, title = _("Class manager"), id = wx.ID_ANY):
  107. """!
  108. Does post init and layout.
  109. @param gui parent
  110. @param title dialog window title
  111. @param id wx id
  112. """
  113. wx.Dialog.__init__(self, parent = parent, title = title, id = id)
  114. panel = wx.Panel(parent = self, id = wx.ID_ANY)
  115. mainSizer = wx.BoxSizer(wx.VERTICAL)
  116. box = wx.StaticBox(panel, id = wx.ID_ANY,
  117. label = " %s " % _("Classes"))
  118. sizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  119. gridSizer = wx.GridBagSizer(hgap = 5, vgap = 5)
  120. gridSizer.AddGrowableCol(0)
  121. gridSizer.AddGrowableRow(2)
  122. self.catList = CategoryListCtrl(panel, mapwindow = parent, statistics = parent.statisticsDict,
  123. statisticsList = parent.statisticsList)
  124. addButton = wx.Button(panel, id = wx.ID_ADD)
  125. deleteButton = wx.Button(panel, id = wx.ID_DELETE)
  126. gridSizer.Add(item = self.catList, pos = (0, 0), span = (3, 1), flag = wx.EXPAND)
  127. gridSizer.Add(item = addButton, pos = (0, 1), flag = wx.EXPAND)
  128. gridSizer.Add(item = deleteButton, pos = (1, 1), flag = wx.EXPAND)
  129. sizer.Add(item = gridSizer, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
  130. mainSizer.Add(item = sizer, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
  131. btnSizer = wx.BoxSizer(wx.HORIZONTAL)
  132. closeButton = wx.Button(panel, id = wx.ID_CLOSE)
  133. btnSizer.Add(item = wx.Size(-1, -1), proportion = 1, flag = wx.EXPAND)
  134. btnSizer.Add(item = closeButton, proportion = 0, flag = wx.ALIGN_RIGHT)
  135. mainSizer.Add(item = btnSizer, proportion = 0, flag = wx.EXPAND | wx.ALL, border = 5)
  136. addButton.Bind(wx.EVT_BUTTON, self.OnAddCategory)
  137. deleteButton.Bind(wx.EVT_BUTTON, self.OnDeleteCategory)
  138. closeButton.Bind(wx.EVT_BUTTON, self.OnClose)
  139. self.Bind(wx.EVT_CLOSE, self.OnClose)
  140. panel.SetSizer(mainSizer)
  141. mainSizer.Fit(panel)
  142. self.SetSize((-1, 250))
  143. self.Layout()
  144. def OnAddCategory(self, event):
  145. self.catList.AddCategory()
  146. def OnDeleteCategory(self, event):
  147. self.catList.DeleteCategory()
  148. def OnClose(self, event):
  149. self.catList.UpdateChoice()
  150. if not isinstance(event, wx.CloseEvent):
  151. self.Destroy()
  152. event.Skip()
  153. class CategoryListCtrl(wx.ListCtrl,
  154. listmix.ListCtrlAutoWidthMixin,
  155. listmix.TextEditMixin):
  156. """! Widget for controling list of classes (categories).
  157. CategoryListCtrl updates choice in mapwindow and removes raster map
  158. when deleting class (category).
  159. It uses virtual data in the terms of @c wx.ListCtrl.
  160. @todo statistics and categories are managed here directly,
  161. it could be better to use some interface
  162. @todo delete vector features after deleting class
  163. """
  164. def __init__(self, parent, mapwindow, statistics, statisticsList, id = wx.ID_ANY):
  165. """!
  166. @param parent gui parent
  167. @param mapwindow mapwindow instance with iclass toolbar and remove raster method
  168. @param statistics dictionary of statistics (defined in statistics.py)
  169. @param statisticsList list of statistics
  170. @param id wx id
  171. """
  172. wx.ListCtrl.__init__(self, parent, id,
  173. style = wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES)
  174. self.columns = ((_('Class name'), 'name'),
  175. (_('Color'), 'color'))
  176. self.Populate(columns = self.columns)
  177. self.mapWindow = mapwindow
  178. self.statisticsDict = statistics
  179. self.statisticsList = statisticsList
  180. self.SetItemCount(len(statisticsList))
  181. listmix.ListCtrlAutoWidthMixin.__init__(self)
  182. listmix.TextEditMixin.__init__(self)
  183. self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.OnEdit)
  184. def SetVirtualData(self, row, column, text):
  185. attr = self.columns[column][1]
  186. setattr(self.statisticsDict[self.statisticsList[row]], attr, text)
  187. self.UpdateChoice()
  188. toolbar = self.mapWindow.toolbars['iClass']
  189. toolbar.choice.SetSelection(row)
  190. if attr == 'name':
  191. self.mapWindow.UpdateRasterName(text, toolbar.GetSelectedCategoryIdx())
  192. def Populate(self, columns):
  193. for i, col in enumerate(columns):
  194. self.InsertColumn(i, col[0])#wx.LIST_FORMAT_RIGHT
  195. self.SetColumnWidth(0, 100)
  196. self.SetColumnWidth(1, 100)
  197. def AddCategory(self):
  198. st = Statistics()
  199. if self.statisticsList:
  200. cat = max(self.statisticsList) + 1
  201. else:
  202. cat = 1
  203. defaultName = 'class' + '_' + str(cat) # intentionally not translatable
  204. defaultColor = '0:0:0'
  205. st.SetBaseStatistics(cat = cat, name = defaultName, color = defaultColor)
  206. self.statisticsDict[cat] = st
  207. self.statisticsList.append(cat)
  208. self.SetItemCount(len(self.statisticsList))
  209. self.UpdateChoice()
  210. def DeleteCategory(self):
  211. indexList = sorted(self.GetSelectedIndices(), reverse = True)
  212. for i in indexList:
  213. # remove temporary raster
  214. name = self.statisticsDict[self.statisticsList[i]].rasterName
  215. self.mapWindow.RemoveTempRaster(name)
  216. del self.statisticsDict[self.statisticsList[i]]
  217. del self.statisticsList[i]
  218. self.SetItemCount(len(self.statisticsList))
  219. self.UpdateChoice()
  220. # delete vector items!
  221. def UpdateChoice(self):
  222. toolbar = self.mapWindow.toolbars['iClass']
  223. name = toolbar.GetSelectedCategoryName()
  224. catNames = []
  225. for cat in self.statisticsList:
  226. catNames.append(self.statisticsDict[cat].name)
  227. toolbar.SetCategories(catNames = catNames, catIdx = self.statisticsList)
  228. if name in catNames:
  229. toolbar.choice.SetStringSelection(name)
  230. elif catNames:
  231. toolbar.choice.SetSelection(0)
  232. if toolbar.choice.IsEmpty():
  233. toolbar.EnableControls(False)
  234. else:
  235. toolbar.EnableControls(True)
  236. # don't forget to update maps, histo, ...
  237. def GetSelectedIndices(self, state = wx.LIST_STATE_SELECTED):
  238. indices = []
  239. lastFound = -1
  240. while True:
  241. index = self.GetNextItem(lastFound, wx.LIST_NEXT_ALL, state)
  242. if index == -1:
  243. break
  244. else:
  245. lastFound = index
  246. indices.append(index)
  247. return indices
  248. def OnEdit(self, event):
  249. currentItem = event.m_itemIndex
  250. currentCol = event.m_col
  251. if currentCol == 1:
  252. dlg = wx.ColourDialog(self)
  253. dlg.GetColourData().SetChooseFull(True)
  254. if dlg.ShowModal() == wx.ID_OK:
  255. color = dlg.GetColourData().GetColour().Get()
  256. color = ':'.join(map(str, color))
  257. self.SetVirtualData(currentItem, currentCol, color)
  258. dlg.Destroy()
  259. event.Skip()
  260. def OnGetItemText(self, item, col):
  261. cat = self.statisticsList[item]
  262. return getattr(self.statisticsDict[cat], self.columns[col][1])
  263. def OnGetItemImage(self, item):
  264. return -1
  265. def OnGetItemAttr(self, item):
  266. return None