[GRASS-dev] [GRASS-SVN] r61032 - grass/trunk/gui/wxpython/lmgr
Anna Petrášová
kratochanna at gmail.com
Sat Jun 28 11:05:57 PDT 2014
Hi,
nice work, can I do some changes (mostly style) or you don't want me to
mess it now to avoid conflicts?
Anna
On Sat, Jun 28, 2014 at 12:46 PM, <svn_grass at osgeo.org> wrote:
> Author: martinl
> Date: 2014-06-28 09:46:15 -0700 (Sat, 28 Jun 2014)
> New Revision: 61032
>
> Added:
> grass/trunk/gui/wxpython/lmgr/datacatalog.py
> Modified:
> grass/trunk/gui/wxpython/lmgr/__init__.py
> grass/trunk/gui/wxpython/lmgr/frame.py
> Log:
> wxGUI: first experimental prototype of Data Catalog in Layer Manager
> (author: Tereza Fiedlerova)
>
> Modified: grass/trunk/gui/wxpython/lmgr/__init__.py
> ===================================================================
> --- grass/trunk/gui/wxpython/lmgr/__init__.py 2014-06-28 16:26:15 UTC
> (rev 61031)
> +++ grass/trunk/gui/wxpython/lmgr/__init__.py 2014-06-28 16:46:15 UTC
> (rev 61032)
> @@ -5,4 +5,5 @@
> 'pyshell',
> 'frame',
> 'giface',
> + 'datacatalog'
> ]
>
> Added: grass/trunk/gui/wxpython/lmgr/datacatalog.py
> ===================================================================
> --- grass/trunk/gui/wxpython/lmgr/datacatalog.py
> (rev 0)
> +++ grass/trunk/gui/wxpython/lmgr/datacatalog.py 2014-06-28
> 16:46:15 UTC (rev 61032)
> @@ -0,0 +1,477 @@
> +"""
> + at package lmgr::datacatalog
> +
> + at brief Data catalog
> +
> +Classes:
> + - datacatalog::DataCatalog
> + - datacatalog::DataCatalogTree
> +
> +(C) 2014 by Tereza Fiedlerova, and the GRASS Development Team
> +
> +This program is free software under the GNU General Public
> +License (>=v2). Read the file COPYING that comes with GRASS
> +for details.
> +
> + at author Tereza Fiedlerova
> +"""
> +
> +import os
> +import sys
> +
> +import wx
> +
> +from core.gcmd import RunCommand, GError, GMessage
> +from core.utils import GetListOfLocations
> +from core.gthread import gThread
> +from core.debug import Debug
> +from gui_core.dialogs import TextEntryDialog
> +
> +from grass.pydispatch.signal import Signal
> +
> +import grass.script as grass
> +
> +class DataCatalog(wx.Panel):
> + """Data catalog panel"""
> + def __init__(self, parent, giface=None, id = wx.ID_ANY, title=_("Data
> catalog"),
> + name='catalog', **kwargs):
> + """Panel constructor """
> + self.showNotification = Signal('DataCatalog.showNotification')
> + self.parent = parent
> + self.baseTitle = title
> + wx.Panel.__init__(self, parent = parent, id = id, **kwargs)
> + self.SetName("DataCatalog")
> +
> + Debug.msg(1, "DataCatalog.__init__()")
> +
> + # tree with layers
> + self.tree = DataCatalogTree(self)
> + self.thread = gThread()
> + self._loaded = False
> + self.tree.showNotification.connect(self.showNotification)
> +
> + # some layout
> + self._layout()
> +
> + def _layout(self):
> + """Do layout"""
> + sizer = wx.BoxSizer(wx.VERTICAL)
> +
> + sizer.Add(item = self.tree.GetControl(), proportion = 1,
> + flag = wx.EXPAND)
> +
> + self.SetAutoLayout(True)
> + self.SetSizer(sizer)
> +
> + self.Layout()
> +
> + def LoadItems(self):
> + if self._loaded:
> + return
> +
> + self.thread.Run(callable=self.tree.InitTreeItems,
> + ondone=lambda event: self.LoadItemsDone())
> +
> + def LoadItemsDone(self):
> + self._loaded = True
> +
> +class DataCatalogTree(wx.TreeCtrl):
> + def __init__(self, parent):
> + """Tree constructor."""
> + super(DataCatalogTree, self).__init__(parent, id=wx.ID_ANY, style
> = wx.TR_HIDE_ROOT | wx.TR_EDIT_LABELS |
> + wx.TR_HAS_BUTTONS |
> wx.TR_FULL_ROW_HIGHLIGHT | wx.TR_COLUMN_LINES | wx.TR_SINGLE)
> + self.showNotification = Signal('Tree.showNotification')
> + self.parent = parent
> + self.root = self.AddRoot('Catalog') # will not be displayed when
> we use TR_HIDE_ROOT flag
> +
> + self._initVariables()
> + self.MakeBackup()
> +
> + wx.EVT_TREE_ITEM_RIGHT_CLICK(self, wx.ID_ANY, self.OnRightClick)
> + wx.EVT_TREE_BEGIN_DRAG(self, wx.ID_ANY, self.OnBeginDrag)
> + wx.EVT_TREE_END_DRAG(self, wx.ID_ANY, self.OnEndDrag)
> +
> + self.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick)
> + self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
> + self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
> +
> + wx.EVT_TREE_END_LABEL_EDIT(self, wx.ID_ANY, self.OnEditLabel)
> + wx.EVT_TREE_BEGIN_LABEL_EDIT(self, wx.ID_ANY,
> self.OnStartEditLabel)
> +
> + def _initVariables(self):
> + """Init variables."""
> + self.selected_layer = None
> + self.selected_type = None
> + self.selected_mapset = None
> + self.selected_location = None
> + self.copy_layer = None
> + self.copy_type = None
> + self.copy_mapset = None
> + self.copy_location = None
> + self.gisdbase = grass.gisenv()['GISDBASE']
> + self.ctrldown = False
> +
> + def GetControl(self):
> + """Returns control itself."""
> + return self
> +
> + def DefineItems(self, item0):
> + """Set selected items."""
> + self.selected_layer = None
> + self.selected_type = None
> + self.selected_mapset = None
> + self.selected_location = None
> + items = []
> + item = item0
> + while (self.GetItemParent(item)):
> + items.insert(0,item)
> + item = self.GetItemParent(item)
> +
> + self.selected_location = items[0]
> + length = len(items)
> + if (length > 1):
> + self.selected_mapset = items[1]
> + if (length > 2):
> + self.selected_type = items[2]
> + if (length > 3):
> + self.selected_layer = items[3]
> +
> + def InitTreeItems(self):
> + """Add locations, mapsets and layers to the tree."""
> + locations = GetListOfLocations(self.gisdbase)
> + first = True
> + for loc in locations:
> + location = loc
> + if first:
> + self.ChangeEnvironment(location, 'PERMANENT')
> + first = False
> + else:
> + self.ChangeEnvironment(location)
> + varloc = self.AppendItem(self.root, loc)
> + #get list of all maps in location
> + maplist = RunCommand('g.mlist', flags='mt',
> type='rast,rast3d,vect', mapset='*', quiet=True, read=True)
> + maplist = maplist.splitlines()
> + for ml in maplist:
> + # parse
> + parts1 = ml.split('/')
> + parts2 = parts1[1].split('@')
> + mapset = parts2[1]
> + mlayer = parts2[0]
> + ltype = parts1[0]
> + if self.itemExists(mapset, varloc) == False:
> + varmapset = self.AppendItem(varloc, mapset)
> + if (self.GetItemText(varmapset) == mapset):
> + if (self.itemExists(ltype, varmapset) == False):
> + vartype = self.AppendItem(varmapset, ltype)
> + else:
> + varmapset = self.getItemByName(mapset, varloc)
> + if (self.itemExists(ltype, varmapset) == False):
> + vartype = self.AppendItem(varmapset, ltype)
> + self.AppendItem(vartype, mlayer)
> + self.RestoreBackup()
> + Debug.msg(1, "Tree filled")
> +
> + def getItemByName(self, match, root):
> + """Return match item from the root."""
> + item, cookie = self.GetFirstChild(root)
> + while item.IsOk():
> + if self.GetItemText(item) == match:
> + return item
> + item, cookie = self.GetNextChild(root, cookie)
> + return None
> +
> + def itemExists(self, match, root):
> + """Return true if match item exists in the root item."""
> + item, cookie = self.GetFirstChild(root)
> + while item.IsOk():
> + if self.GetItemText(item) == match:
> + return True
> + item, cookie = self.GetNextChild(root, cookie)
> + return False
> +
> + def UpdateTree(self):
> + """Update whole tree."""
> + self.DeleteAllItems()
> + self.root = self.AddRoot('Tree')
> + self.AddTreeItems()
> + label = "Tree updated."
> + self.showNotification.emit(message=label)
> +
> + def OnSelChanged(self, event):
> + self.selected_layer = None
> +
> + def OnRightClick(self, event):
> + """Display popup menu."""
> + self.DefineItems(event.GetItem())
> + if(self.selected_layer):
> + self._popupMenuLayer()
> + elif(self.selected_mapset and self.selected_type==None):
> + self._popupMenuMapset()
> +
> + def OnDoubleClick(self, event):
> + """Rename layer"""
> + Debug.msg(1, "Double CLICK")
> +
> + def OnCopy(self, event):
> + """Copy layer or mapset (just save it temporarily, copying is
> done by paste)"""
> + self.copy_layer = self.selected_layer
> + self.copy_type = self.selected_type
> + self.copy_mapset = self.selected_mapset
> + self.copy_location = self.selected_location
> + label = "Layer "+self.GetItemText(self.copy_layer)+" copied to
> clipboard. You can paste it to selected mapset."
> + self.showNotification.emit(message=label)
> +
> + def OnRename(self, event):
> + """Rename levent with dialog"""
> + if (self.selected_layer):
> + self.old_name = self.GetItemText(self.selected_layer)
> + self._textDialog(_('New name'), _('Rename map'),
> self.old_name)
> + self.rename()
> +
> + def OnStartEditLabel(self, event):
> + """Start label editing"""
> + item = event.GetItem()
> + self.DefineItems(item)
> + Debug.msg(1, "Start label edit "+self.GetItemText(item))
> + label = _("Editing") + " " + self.GetItemText(item)
> + self.showNotification.emit(message=label)
> + if (self.selected_layer == None):
> + event.Veto()
> +
> + def OnEditLabel(self, event):
> + """End label editing"""
> + if (self.selected_layer):
> + item = event.GetItem()
> + self.old_name = self.GetItemText(item)
> + Debug.msg(1, "End label edit "+self.old_name)
> + wx.CallAfter(self.afterEdit, self, item)
> +
> + def afterEdit(pro, self, item):
> + self.new_name = self.GetItemText(item)
> + self.rename()
> +
> + def rename(self):
> + """Rename layer"""
> + if (self.selected_layer):
> + string = self.old_name+','+self.new_name
> +
> self.ChangeEnvironment(self.GetItemText(self.selected_location),
> self.GetItemText(self.selected_mapset))
> + renamed = 0
> + label = _("Renaming") + " " + string + " ..."
> + self.showNotification.emit(message=label)
> + if (self.GetItemText(self.selected_type)=='vect'):
> + renamed = RunCommand('g.rename', vect=string)
> + elif (self.GetItemText(self.selected_type)=='rast'):
> + renamed = RunCommand('g.rename', rast=string)
> + else:
> + renamed = RunCommand('g.rename', rast3d=string)
> + if (renamed==0):
> + self.SetItemText(self.selected_layer,self.new_name)
> + label = "g.rename
> "+self.GetItemText(self.selected_type)+"="+string+" -- completed"
> + self.showNotification.emit(message=label)
> + Debug.msg(1,"LAYER RENAMED TO: "+self.new_name)
> + self.RestoreBackup()
> +
> + def OnPaste(self, event):
> + """Paste layer or mapset"""
> + # copying between mapsets of one location
> + if (self.copy_layer == None):
> + return
> + if (self.selected_location == self.copy_location and
> self.selected_mapset):
> + if (self.selected_type != None):
> + if (self.GetItemText(self.copy_type) !=
> self.GetItemText(self.selected_type)): # copy raster to vector or vice versa
> + GError(_("Failed to copy layer: invalid type."),
> parent = self)
> + return
> + self._textDialog(_('New name'), _('Copy map'),
> self.GetItemText(self.copy_layer)+'_copy')
> + if (self.GetItemText(self.copy_layer) == self.new_name):
> + GMessage(_("Layer was not copied: new layer has the same
> name"), parent=self)
> + return
> + string =
> self.GetItemText(self.copy_layer)+'@'+self.GetItemText(self.copy_mapset)+','+self.new_name
> +
> self.ChangeEnvironment(self.GetItemText(self.selected_location),
> self.GetItemText(self.selected_mapset))
> + pasted = 0
> + type = None
> + label = _("Copying") + " " + string + " ..."
> + self.showNotification.emit(message=label)
> + if (self.GetItemText(self.copy_type)=='vect'):
> + pasted = RunCommand('g.copy', vect=string)
> + node = 'vect'
> + elif (self.GetItemText(self.copy_type)=='rast'):
> + pasted = RunCommand('g.copy', rast=string)
> + node = 'rast'
> + else:
> + pasted = RunCommand('g.copy', rast3d=string)
> + node = 'rast3d'
> + if (pasted==0):
> + if (self.selected_type == None):
> + self.selected_type = self.getItemByName(node,
> self.selected_mapset)
> + self.AppendItem(self.selected_type,self.new_name)
> + self.SortChildren(self.selected_type)
> + Debug.msg(1,"COPIED TO: "+self.new_name)
> + label = "g.copy
> "+self.GetItemText(self.copy_type)+"="+string+" -- completed" # generate
> this message (command) automatically?
> + self.showNotification.emit(message=label)
> + else:
> + GError(_("Failed to copy layer: action is allowed only within
> the same location."),
> + parent=self)
> +
> + self.RestoreBackup()
> +
> +
> + def OnDelete(self, event):
> + """Delete layer or mapset"""
> + if (self.selected_layer):
> + string = self.GetItemText(self.selected_layer)
> +
> self.ChangeEnvironment(self.GetItemText(self.selected_location),
> self.GetItemText(self.selected_mapset))
> + removed = 0
> + if (self._confirmDialog(_('Do you really want to delete
> layer') +string+'?', _('Delete map')) == wx.ID_YES):
> + label = _("Deleting") + " " + string + " ..."
> + self.showNotification.emit(message=label)
> + if (self.GetItemText(self.selected_type)=='vect'):
> + removed = RunCommand('g.remove', vect=string)
> + elif (self.GetItemText(self.selected_type)=='rast'):
> + removed = RunCommand('g.remove', rast=string)
> + else:
> + removed = RunCommand('g.remove', rast3d=string)
> + if (removed==0):
> + self.Delete(self.selected_layer)
> + Debug.msg(1,"LAYER "+string+" DELETED")
> + label = "g.remove
> "+self.GetItemText(self.selected_type)+"="+string+" -- completed" #
> generate this message (command) automatically?
> + self.showNotification.emit(message=label)
> + self.RestoreBackup()
> +
> + def OnDisplayLayer(self, event):
> + """Display layer in current graphics view"""
> + layerName = []
> + if (self.GetItemText(self.selected_location) == self.glocation
> and self.selected_mapset):
> + string =
> self.GetItemText(self.selected_layer)+'@'+self.GetItemText(self.selected_mapset)
> + layerName.append(string)
> + label = _("Displaying") + " " + string + " ..."
> + self.showNotification.emit(message=label)
> + label = "d."+self.GetItemText(self.selected_type)+" --q
> map="+string+" -- completed. Go to Map layers for further operations."
> + if (self.GetItemText(self.selected_type)=='vect'):
> + self.parent.parent.AddMaps(layerName, 'vect', True)
> + elif (self.GetItemText(self.selected_type)=='rast'):
> + self.parent.parent.AddMaps(layerName, 'rast', True)
> + else:
> + self.parent.parent.AddMaps(layerName, 'rast3d', True)
> + label = "d.rast --q map="+string+" -- completed. Go to
> 'Map layers' for further operations." # generate this message (command)
> automatically?
> + self.showNotification.emit(message=label)
> + Debug.msg(1,"LAYER "+self.GetItemText(self.selected_layer)+"
> DISPLAYED")
> + else:
> + GError(_("Failed to display layer: not in current mapset or
> invalid layer"),
> + parent = self)
> +
> + def OnBeginDrag(self, event):
> + """Just copy necessary data"""
> + if (self.ctrldown):
> + #cursor = wx.StockCursor(wx.CURSOR_HAND)
> + #self.SetCursor(cursor)
> + event.Allow()
> + self.DefineItems(event.GetItem())
> + self.OnCopy(event)
> + Debug.msg(1,"DRAG")
> + else:
> + event.Veto()
> + Debug.msg(1,"DRAGGING without ctrl key does nothing")
> +
> + def OnEndDrag(self, event):
> + """Copy layer into target"""
> + #cursor = wx.StockCursor(wx.CURSOR_ARROW)
> + #self.SetCursor(cursor)
> + if (event.GetItem()):
> + self.DefineItems(event.GetItem())
> + if (self.selected_location == self.copy_location and
> self.selected_mapset):
> + event.Allow()
> + self.OnPaste(event)
> + self.ctrldown = False
> + #cursor = wx.StockCursor(wx.CURSOR_DEFAULT)
> + #self.SetCursor(cursor) # TODO: change cursor while
> dragging and then back, this is not working
> + Debug.msg(1,"DROP DONE")
> + else:
> + event.Veto()
> +
> + def OnKeyDown(self, event):
> + """Set key event and check if control key is down"""
> + keycode = event.GetKeyCode()
> + if keycode == wx.WXK_CONTROL:
> + self.ctrldown = True
> + Debug.msg(1,"CONTROL ON")
> +
> + def OnKeyUp(self, event):
> + """Check if control key is up"""
> + keycode = event.GetKeyCode()
> + if keycode == wx.WXK_CONTROL:
> + self.ctrldown = False
> + Debug.msg(1,"CONTROL OFF")
> +
> + def _textDialog(self, message, title, value):
> + """Dialog for simple text entry"""
> + dlg = TextEntryDialog(self, message, title)
> + dlg.SetValue(value)
> + res = dlg.ShowModal()
> + self.new_name = dlg.GetValue()
> + dlg.Destroy()
> +
> + def _confirmDialog(self, question, title):
> + """Confirm dialog"""
> + dlg = wx.MessageDialog(self, question, title, wx.YES_NO)
> + res = dlg.ShowModal()
> + dlg.Destroy()
> + return res
> +
> + def _popupMenuLayer(self):
> + """Create popup menu for layers"""
> + menu = wx.Menu()
> +
> + item = wx.MenuItem(menu, wx.NewId(), _("&Copy"))
> + menu.AppendItem(item)
> + self.Bind(wx.EVT_MENU, self.OnCopy, item)
> +
> + item = wx.MenuItem(menu, wx.NewId(), _("&Paste"))
> + menu.AppendItem(item)
> + self.Bind(wx.EVT_MENU, self.OnPaste, item)
> +
> + item = wx.MenuItem(menu, wx.NewId(), _("&Delete"))
> + menu.AppendItem(item)
> + self.Bind(wx.EVT_MENU, self.OnDelete, item)
> +
> + item = wx.MenuItem(menu, wx.NewId(), _("&Rename"))
> + menu.AppendItem(item)
> + self.Bind(wx.EVT_MENU, self.OnRename, item)
> +
> + item = wx.MenuItem(menu, wx.NewId(), _("&Display layer"))
> + menu.AppendItem(item)
> + self.Bind(wx.EVT_MENU, self.OnDisplayLayer, item)
> +
> + self.PopupMenu(menu)
> + menu.Destroy()
> +
> + def _popupMenuMapset(self):
> + """Create popup menu for mapsets"""
> + menu = wx.Menu()
> +
> + item = wx.MenuItem(menu, wx.NewId(), _("&Paste"))
> + menu.AppendItem(item)
> + self.Bind(wx.EVT_MENU, self.OnPaste, item)
> +
> + self.PopupMenu(menu)
> + menu.Destroy()
> +
> + def MakeBackup(self):
> + """Make backup for case of change"""
> + self.glocation = grass.gisenv()['LOCATION_NAME']
> + self.gmapset = grass.gisenv()['MAPSET']
> +
> + def RestoreBackup(self):
> + """Restore backup"""
> + stringl = 'LOCATION_NAME='+self.glocation
> + RunCommand('g.gisenv', set=stringl)
> + stringm = 'MAPSET='+self.gmapset
> + RunCommand('g.gisenv', set=stringm)
> +
> + def ChangeEnvironment(self, location, mapset=None):
> + """Change gisenv variables -> location, mapset"""
> + stringl = 'LOCATION_NAME='+location
> + RunCommand('g.gisenv', set=stringl)
> + if mapset:
> + stringm = 'MAPSET='+mapset
> + RunCommand('g.gisenv', set=stringm)
> +
>
>
> Property changes on: grass/trunk/gui/wxpython/lmgr/datacatalog.py
> ___________________________________________________________________
> Added: svn:mime-type
> + text/x-python
> Added: svn:eol-style
> + native
>
> Modified: grass/trunk/gui/wxpython/lmgr/frame.py
> ===================================================================
> --- grass/trunk/gui/wxpython/lmgr/frame.py 2014-06-28 16:26:15 UTC
> (rev 61031)
> +++ grass/trunk/gui/wxpython/lmgr/frame.py 2014-06-28 16:46:15 UTC
> (rev 61032)
> @@ -70,6 +70,7 @@
> from lmgr.toolbars import LMMiscToolbar, LMVectorToolbar,
> LMNvizToolbar
> from lmgr.pyshell import PyShellWindow
> from lmgr.giface import LayerManagerGrassInterface
> +from lmgr.datacatalog import DataCatalog
> from gui_core.forms import GUI
> from gcp.manager import GCPWizard
> from nviz.main import haveNviz
> @@ -317,6 +318,11 @@
> else:
> self.search = None
>
> + # create 'data catalog' notebook page
> + self.datacatalog = DataCatalog(parent = self, giface =
> self._giface)
> + self.datacatalog.showNotification.connect(lambda message:
> self.SetStatusText(message))
> + self.notebook.AddPage(page = self.datacatalog, text = _("Data
> catalog"), name = 'catalog')
> +
> # create 'python shell' notebook page
> if not UserSettings.Get(group = 'manager', key = 'hideTabs',
> subkey = 'pyshell'):
> self.pyshell = PyShellWindow(parent = self)
> @@ -544,6 +550,8 @@
> page = event.GetSelection()
> if page == self.notebook.GetPageIndexByName('output'):
> wx.CallAfter(self.goutput.ResetFocus)
> + elif page == self.notebook.GetPageIndexByName('catalog'):
> + wx.CallAfter(self.datacatalog.LoadItems)
> self.SetStatusText('', 0)
>
> event.Skip()
>
> _______________________________________________
> grass-commit mailing list
> grass-commit at lists.osgeo.org
> http://lists.osgeo.org/mailman/listinfo/grass-commit
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/grass-dev/attachments/20140628/2b50290b/attachment-0001.html>
More information about the grass-dev
mailing list