[GRASS-dev] [GRASS-SVN] r61032 - grass/trunk/gui/wxpython/lmgr

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@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 @@
+“”"
+@package lmgr::datacatalog
+
+@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.
+
+@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@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/grass-commit

Ciao Anna,

2014-06-28 20:05 GMT+02:00 Anna Petrášová <kratochanna@gmail.com>:

nice work, can I do some changes (mostly style) or you don't want me to mess
it now to avoid conflicts?

you can do modification directly in trunk. Thanks, Martin

--
Martin Landa * http://geo.fsv.cvut.cz/gwiki/Landa

2014-06-29 11:23 GMT+02:00 Martin Landa <landa.martin@gmail.com>:

nice work, can I do some changes (mostly style) or you don't want me to mess
it now to avoid conflicts?

you can do modification directly in trunk. Thanks, Martin

today I am planning to do some refactoring, so please wait a bit with
your modifications. Thanks, Martin

--
Martin Landa * http://geo.fsv.cvut.cz/gwiki/Landa