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