[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