manager.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. """
  2. @package dbmgr.manager
  3. @brief GRASS Attribute Table Manager
  4. This program is based on FileHunter, published in 'The wxPython Linux
  5. Tutorial' on wxPython WIKI pages.
  6. It also uses some functions at
  7. http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/426407
  8. List of classes:
  9. - manager::AttributeManager
  10. (C) 2007-2014 by the GRASS Development Team
  11. This program is free software under the GNU General Public License
  12. (>=v2). Read the file COPYING that comes with GRASS for details.
  13. @author Jachym Cepicky <jachym.cepicky gmail.com>
  14. @author Martin Landa <landa.martin gmail.com>
  15. @author Refactoring by Stepan Turek <stepan.turek seznam.cz> (GSoC 2012, mentor: Martin Landa)
  16. """
  17. import os
  18. import wx
  19. from core import globalvar
  20. if globalvar.wxPythonPhoenix:
  21. try:
  22. import agw.flatnotebook as FN
  23. except ImportError: # if it's not there locally, try the wxPython lib.
  24. import wx.lib.agw.flatnotebook as FN
  25. else:
  26. import wx.lib.flatnotebook as FN
  27. from core.gcmd import GMessage
  28. from dbmgr.base import DbMgrBase
  29. from gui_core.widgets import GNotebook
  30. from gui_core.wrap import Button, ClearButton, CloseButton
  31. class AttributeManager(wx.Frame, DbMgrBase):
  32. def __init__(
  33. self,
  34. parent,
  35. id=wx.ID_ANY,
  36. title=None,
  37. base_title=None,
  38. vectorName=None,
  39. item=None,
  40. log=None,
  41. selection=None,
  42. **kwargs,
  43. ):
  44. """GRASS Attribute Table Manager window
  45. :param parent: parent window
  46. :param id: window id
  47. :param title: full window title or None for default title
  48. :param base_title: the document independent part of title or None for default
  49. :param vectorName: name of vector map
  50. :param item: item from Layer Tree
  51. :param log: log window
  52. :param selection: name of page to be selected
  53. :param kwagrs: other wx.Frame's arguments
  54. """
  55. self.parent = parent
  56. try:
  57. mapdisplay = self.parent.GetMapDisplay()
  58. except:
  59. mapdisplay = None
  60. DbMgrBase.__init__(
  61. self,
  62. id=id,
  63. mapdisplay=mapdisplay,
  64. vectorName=vectorName,
  65. item=item,
  66. log=log,
  67. statusbar=self,
  68. **kwargs,
  69. )
  70. wx.Frame.__init__(self, parent, id, *kwargs)
  71. # title
  72. if not title:
  73. if not base_title:
  74. base_title = _("Attribute Table Manager")
  75. document = self.dbMgrData["vectName"]
  76. if not self.dbMgrData["editable"]:
  77. document = _("{document} (read-only)").format(document=document)
  78. title = "{document} - {tool_name}".format(
  79. document=document, tool_name=base_title
  80. )
  81. self.SetTitle(title)
  82. # icon
  83. self.SetIcon(
  84. wx.Icon(
  85. os.path.join(globalvar.ICONDIR, "grass_sql.ico"), wx.BITMAP_TYPE_ICO
  86. )
  87. )
  88. self.panel = wx.Panel(parent=self, id=wx.ID_ANY)
  89. if len(self.dbMgrData["mapDBInfo"].layers.keys()) == 0:
  90. GMessage(
  91. parent=self.parent,
  92. message=_(
  93. "Database connection for vector map <%s> "
  94. "is not defined in DB file. "
  95. "You can define new connection in "
  96. "'Manage layers' tab."
  97. )
  98. % self.dbMgrData["vectName"],
  99. )
  100. busy = wx.BusyInfo(
  101. _("Please wait, loading attribute data..."), parent=self.parent
  102. )
  103. wx.SafeYield()
  104. self.CreateStatusBar(number=1)
  105. self.notebook = GNotebook(self.panel, style=globalvar.FNPageDStyle)
  106. self.CreateDbMgrPage(parent=self, pageName="browse")
  107. self.notebook.AddPage(
  108. page=self.pages["browse"], text=_("Browse data"), name="browse"
  109. )
  110. self.pages["browse"].SetTabAreaColour(globalvar.FNPageColor)
  111. self.CreateDbMgrPage(parent=self, pageName="manageTable")
  112. self.notebook.AddPage(
  113. page=self.pages["manageTable"], text=_("Manage tables"), name="table"
  114. )
  115. self.pages["manageTable"].SetTabAreaColour(globalvar.FNPageColor)
  116. self.CreateDbMgrPage(parent=self, pageName="manageLayer")
  117. self.notebook.AddPage(
  118. page=self.pages["manageLayer"], text=_("Manage layers"), name="layers"
  119. )
  120. del busy
  121. if selection:
  122. wx.CallAfter(self.notebook.SetSelectionByName, selection)
  123. else:
  124. wx.CallAfter(self.notebook.SetSelection, 0) # select browse tab
  125. # buttons
  126. self.btnClose = CloseButton(parent=self.panel)
  127. self.btnClose.SetToolTip(_("Close Attribute Table Manager"))
  128. self.btnReload = Button(parent=self.panel, id=wx.ID_REFRESH)
  129. self.btnReload.SetToolTip(_("Reload currently selected attribute data"))
  130. self.btnReset = ClearButton(parent=self.panel)
  131. self.btnReset.SetToolTip(
  132. _("Reload all attribute data (drop current selection)")
  133. )
  134. # bind closing to ESC
  135. self.Bind(wx.EVT_MENU, self.OnCloseWindow, id=wx.ID_CANCEL)
  136. accelTableList = [(wx.ACCEL_NORMAL, wx.WXK_ESCAPE, wx.ID_CANCEL)]
  137. accelTable = wx.AcceleratorTable(accelTableList)
  138. self.SetAcceleratorTable(accelTable)
  139. # events
  140. self.btnClose.Bind(wx.EVT_BUTTON, self.OnCloseWindow)
  141. self.btnReload.Bind(wx.EVT_BUTTON, self.OnReloadData)
  142. self.btnReset.Bind(wx.EVT_BUTTON, self.OnReloadDataAll)
  143. self.notebook.Bind(FN.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
  144. self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
  145. # do layout
  146. self._layout()
  147. # self.SetMinSize(self.GetBestSize())
  148. self.SetSize((700, 550)) # FIXME hard-coded size
  149. self.SetMinSize(self.GetSize())
  150. def _layout(self):
  151. """Do layout"""
  152. # frame body
  153. mainSizer = wx.BoxSizer(wx.VERTICAL)
  154. # buttons
  155. btnSizer = wx.BoxSizer(wx.HORIZONTAL)
  156. btnSizer.Add(self.btnReset, proportion=1, flag=wx.ALL, border=5)
  157. btnSizer.Add(self.btnReload, proportion=1, flag=wx.ALL, border=5)
  158. btnSizer.Add(self.btnClose, proportion=1, flag=wx.ALL, border=5)
  159. mainSizer.Add(self.notebook, proportion=1, flag=wx.EXPAND)
  160. mainSizer.Add(btnSizer, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
  161. self.panel.SetAutoLayout(True)
  162. self.panel.SetSizer(mainSizer)
  163. mainSizer.Fit(self.panel)
  164. self.Layout()
  165. def OnCloseWindow(self, event):
  166. """Cancel button pressed"""
  167. if self.parent and self.parent.GetName() == "LayerManager":
  168. # deregister ATM
  169. self.parent.dialogs["atm"].remove(self)
  170. if not isinstance(event, wx.CloseEvent):
  171. self.Destroy()
  172. event.Skip()
  173. def OnReloadData(self, event):
  174. """Reload data"""
  175. if self.pages["browse"]:
  176. self.pages["browse"].OnDataReload(event) # TODO replace by signal
  177. def OnReloadDataAll(self, event):
  178. """Reload all data"""
  179. if self.pages["browse"]:
  180. self.pages["browse"].ResetPage()
  181. def OnPageChanged(self, event):
  182. """On page in ATM is changed"""
  183. try:
  184. if self.pages["browse"]:
  185. selPage = self.pages["browse"].selLayer
  186. id = self.pages["browse"].layerPage[selPage]["data"]
  187. else:
  188. id = None
  189. except KeyError:
  190. id = None
  191. if event.GetSelection() == self.notebook.GetPageIndexByName("browse") and id:
  192. win = self.FindWindowById(id)
  193. if win:
  194. self.log.write(_("Number of loaded records: %d") % win.GetItemCount())
  195. else:
  196. self.log.write("")
  197. self.btnReload.Enable()
  198. self.btnReset.Enable()
  199. else:
  200. self.log.write("")
  201. self.btnReload.Enable(False)
  202. self.btnReset.Enable(False)
  203. event.Skip()
  204. def OnTextEnter(self, event):
  205. pass
  206. def UpdateDialog(self, layer):
  207. """Updates dialog layout for given layer"""
  208. DbMgrBase.UpdateDialog(self, layer=layer)
  209. # set current page selection
  210. self.notebook.SetSelectionByName("layers")