[GRASS-SVN] r54972 - in grass/trunk: gui/wxpython/gui_core gui/wxpython/mapdisp lib/python/script

svn_grass at osgeo.org svn_grass at osgeo.org
Thu Feb 7 07:09:56 PST 2013


Author: annakrat
Date: 2013-02-07 07:09:56 -0800 (Thu, 07 Feb 2013)
New Revision: 54972

Added:
   grass/trunk/gui/wxpython/gui_core/query.py
Modified:
   grass/trunk/gui/wxpython/mapdisp/frame.py
   grass/trunk/lib/python/script/raster.py
Log:
wxGUI: new dialog for query results

Added: grass/trunk/gui/wxpython/gui_core/query.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/query.py	                        (rev 0)
+++ grass/trunk/gui/wxpython/gui_core/query.py	2013-02-07 15:09:56 UTC (rev 54972)
@@ -0,0 +1,127 @@
+"""!
+ at package gui_core.query
+
+ at brief wxGUI query dialog
+
+Classes:
+ - query::QueryDialog
+
+(C) 2013 by 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 Anna Kratochvilova <kratochanna gmail.com>
+"""
+
+import wx
+import wx.gizmos as gizmos
+
+class QueryDialog(wx.Dialog):
+    def __init__(self, parent, data = None):
+        wx.Dialog.__init__(self, parent, id = wx.ID_ANY,
+                           title = _("Query results"),
+                           size = (420, 400),
+                           style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)
+        self.data = data
+
+        self.panel = wx.Panel(self, id = wx.ID_ANY)
+        self.mainSizer = wx.BoxSizer(wx.VERTICAL)
+
+        self.tree = gizmos.TreeListCtrl(self.panel, id = wx.ID_ANY,
+                                        style = wx.TR_DEFAULT_STYLE |
+                                        wx.TR_HIDE_ROOT)
+
+        self.tree.AddColumn("Feature")
+        self.tree.AddColumn("Value")
+        self.tree.SetMainColumn(0)
+        self.tree.SetColumnWidth(0, 180)
+        self.tree.SetColumnWidth(1, 200)
+
+        self.mainSizer.Add(item = self.tree, proportion = 1, flag = wx.EXPAND | wx.ALL, border = 5)
+        if self.data:
+            self._load()
+
+        close = wx.Button(self.panel, id = wx.ID_CLOSE)
+        close.Bind(wx.EVT_BUTTON, lambda evt: self.Destroy())
+        copy = wx.Button(self.panel, id = wx.ID_ANY, label = _("Copy to clipboard"))
+        copy.Bind(wx.EVT_BUTTON, self.Copy)
+
+        hbox = wx.BoxSizer(wx.HORIZONTAL)
+        hbox.AddStretchSpacer(1)
+        hbox.Add(item = copy, proportion = 0, flag = wx.EXPAND | wx.RIGHT, border = 5)
+        hbox.Add(item = close, proportion = 0, flag = wx.EXPAND | wx.ALL, border = 0)
+
+        self.mainSizer.Add(item = hbox, proportion = 0, flag = wx.EXPAND | wx.ALL, border = 5)
+        self.panel.SetSizer(self.mainSizer)
+        self.mainSizer.Fit(self.panel)
+
+    def _load(self):
+        self.tree.DeleteAllItems()
+        self.root = self.tree.AddRoot("The Root Item")
+        # TODO: move elsewhere
+        for part in self.data:
+            if 'Map' in part:
+                item = self.tree.AppendItem(self.root, text = part['Map'])
+                del part['Map']
+                self._addItem(item, part)
+            else:
+                self._addItem(self.root, part)
+        self.tree.UnselectAll()
+        self.tree.ExpandAll(self.root)
+
+    def _print(self):
+        string = []
+        for part in self.data:
+            self._printItem(string, '', part)
+            string.append('')
+        return '\n'.join(string)
+
+    def _addItem(self, parent, data):
+        for k, v in data.iteritems():
+            if isinstance(v, dict):
+                item = self.tree.AppendItem(parent, text = k)
+                self.tree.SetItemText(item, '', 1)
+                self._addItem(item, v)
+            else:
+                item = self.tree.AppendItem(parent, text = k)
+                self.tree.SetItemText(item, str(v), 1)
+
+    def _printItem(self, string, indent, data):
+        for k, v in data.iteritems():
+            if isinstance(v, dict):
+                string.append(indent + k)
+                self._printItem(string, indent + '    ', v)
+            else:
+                string.append(indent + k + ': ' + str(v))
+
+    def SetData(self, data):
+        self.data = data
+        self._load()
+
+    def Copy(self, event):
+        text = self._print()
+        if wx.TheClipboard.Open():
+            do = wx.TextDataObject()
+            do.SetText(text)
+            wx.TheClipboard.SetData(do)
+            wx.TheClipboard.Close()
+
+def test():
+    app = wx.PySimpleApp()
+    import pprint
+    from grass.script import vector as gvect
+    from grass.script import raster as grast
+    testdata1 = grast.raster_what(map = ('elevation_shade at PERMANENT','landclass96'),
+                                  coord = [(638509.051416,224742.348346)])
+
+    testdata2 = gvect.vector_what(map=('firestations','firestations'),
+                                 coord=(633177.897487,221352.921257), distance=10)
+    testdata = testdata1 + testdata2
+    frame = QueryDialog(parent = None, data = testdata)
+    frame.ShowModal()
+    frame.Destroy()
+    app.MainLoop()
+
+if __name__ == "__main__":
+    test()
\ No newline at end of file

Modified: grass/trunk/gui/wxpython/mapdisp/frame.py
===================================================================
--- grass/trunk/gui/wxpython/mapdisp/frame.py	2013-02-07 14:22:28 UTC (rev 54971)
+++ grass/trunk/gui/wxpython/mapdisp/frame.py	2013-02-07 15:09:56 UTC (rev 54972)
@@ -48,6 +48,7 @@
 from core.debug         import Debug
 from core.settings      import UserSettings
 from gui_core.mapdisp   import SingleMapFrame
+from gui_core.query     import QueryDialog
 from mapdisp.mapwindow  import BufferedWindow
 from mapdisp.overlays   import LegendController, BarscaleController
 from modules.histogram  import HistogramFrame
@@ -193,6 +194,7 @@
         self.dialogs['barscale'] = None
         self.dialogs['legend'] = None
         self.dialogs['vnet'] = None
+        self.dialogs['query'] = None
 
         self.decorationDialog = None # decoration/overlays
         
@@ -651,26 +653,40 @@
     def Query(self, x, y):
         """!Query selected layers. 
 
-        Calls QueryMap in case of raster or more vectors,
-        or QueryVector in case of one vector with db connection.
-
         @param x,y coordinates
         @param layers selected tree item layers
         """
         layers = self._giface.GetLayerList().GetSelectedLayers(checkedOnly = True)
-        filteredLayers = []
+        rast = []
+        vect = []
         for layer in layers:
+            name, found = GetLayerNameFromCmd(layer.cmd)
+            if not found:
+                continue
             ltype = layer.maplayer.GetType()
-            if ltype in ('raster', 'rgb', 'his',
-                         'vector', 'thememap', 'themechart'):
-                filteredLayers.append(layer)
+            if ltype == 'raster':
+                rast.append(name)
+            elif ltype in ('rgb', 'his'):
+                for iname in name.split('\n'):
+                    rast.append(iname)
+            elif ltype in ('vector', 'thememap', 'themechart'):
+                vect.append(name)
+        if vect:
+            # check for vector maps open to be edited
+            digitToolbar = self.GetToolbar('vdigit')
+            if digitToolbar:
+                lmap = digitToolbar.GetLayer().GetName()
+                for name in vect:
+                    if lmap == name:
+                        self._giface.WriteWarning(_("Vector map <%s> "
+                                                                  "opened for editing - skipped.") % lmap)
+                        vect.remove(name)
 
-        if not filteredLayers:
+        if not (rast + vect):
             GMessage(parent = self,
                      message = _('No raster or vector map layer selected for querying.'))
             return
-            
-        layers = filteredLayers
+
         # set query snap distance for v.what at map unit equivalent of 10 pixels
         qdist = 10.0 * ((self.Map.region['e'] - self.Map.region['w']) / self.Map.width)
 
@@ -680,108 +696,81 @@
         except TypeError:
             return
 
-        posWindow = self.ClientToScreen((x + self.MapWindow.dialogOffset,
-                                         y + self.MapWindow.dialogOffset))
-
-        isRaster = False
-        nVectors = 0
-        isDbConnection = False
-        for l in layers:
-            maplayer = l.maplayer
-            if maplayer.GetType() == 'raster':
-                isRaster = True
-                break
-            if maplayer.GetType() == 'vector':
-                nVectors += 1
-                isDbConnection = grass.vector_db(maplayer.GetName())
-
         if not self.IsPaneShown('3d'):
-            if isRaster or nVectors > 1 or not isDbConnection:
-                self.QueryMap(east, north, qdist, layers)
-            else:
-                self.QueryVector(east, north, qdist, posWindow, layers[0])
+            self.QueryMap(east, north, qdist, rast, vect)
         else:
-            if isRaster:
+            if rast:
                 self.MapWindow.QuerySurface(x, y)
-            if nVectors > 1 or not isDbConnection:
-                self.QueryMap(east, north, qdist, layers)
-            elif nVectors == 1:
-                self.QueryVector(east, north, qdist, posWindow, layers[0])
+            if vect:
+                self.QueryMap(east, north, qdist, rast = [], vect = vect)
 
-    def QueryMap(self, east, north, qdist, layers):
+    def QueryMap(self, east, north, qdist, rast, vect):
         """!Query raster or vector map layers by r/v.what
         
         @param east,north coordinates
         @param qdist query distance
-        @param layers selected tree items
+        @param rast raster map names
+        @param vect vector map names
         """
-        rast = list()
-        vect = list()
-        rcmd = ['r.what', '--v']
-        vcmd = ['v.what', '--v']
-        
-        for layer in layers:
-            ltype = layer.maplayer.GetType()
-            dcmd = layer.cmd
-            name, found = GetLayerNameFromCmd(dcmd)
-            
-            if not found:
-                continue
-            if ltype == 'raster':
-                rast.append(name)
-            elif ltype in ('rgb', 'his'):
-                for iname in name.split('\n'):
-                    rast.append(iname)
-            elif ltype in ('vector', 'thememap', 'themechart'):
-                vect.append(name)
+        Debug.msg(1, "QueryMap(): raster=%s vector=%s" % (','.join(rast),
+                                                          ','.join(vect)))
 
         # use display region settings instead of computation region settings
         self.tmpreg = os.getenv("GRASS_REGION")
         os.environ["GRASS_REGION"] = self.Map.SetRegion(windres = False)
-        
-        # build query commands for any selected rasters and vectors
+
+        rastQuery = []
+        vectQuery = []
         if rast:
-            rcmd.append('-f')
-            rcmd.append('-n')
-            rcmd.append('map=%s' % ','.join(rast))
-            rcmd.append('coordinates=%f,%f' % (float(east), float(north)))
-        
+            rastQuery = grass.raster_what(map=rast, coord=(east, north))
         if vect:
-            # check for vector maps open to be edited
-            digitToolbar = self.GetToolbar('vdigit')
-            if digitToolbar:
-                lmap = digitToolbar.GetLayer().GetName()
-                for name in vect:
-                    if lmap == name:
-                        self._giface.WriteWarning(_("Vector map <%s> "
-                                                                  "opened for editing - skipped.") % lmap)
-                        vect.remove(name)
+            vectQuery = grass.vector_what(map=vect, coord=(east, north), distance=qdist)
+        self._QueryMapDone()
+        self._queryHighlight(vectQuery)
+
+        result = rastQuery + vectQuery
+        if self.dialogs['query']:
+            self.dialogs['query'].Raise()
+            self.dialogs['query'].SetData(result)
+        else:
+            self.dialogs['query'] = QueryDialog(parent = self, data = result)
+            self.dialogs['query'].Show()
+
+    def _queryHighlight(self, vectQuery):
+        """!Highlight category from query."""
+        cats = name = None
+        for res in vectQuery:
+            cats = {res['Layer']: [res['Category']]}
+            name = res['Map']
+        try:
+            qlayer = self.Map.GetListOfLayers(name = globalvar.QUERYLAYER)[0]
+        except IndexError:
+            qlayer = None
+
+        if not (cats and name):
+            if qlayer:
+                self.Map.DeleteLayer(qlayer)
+                self.MapWindow.UpdateMap(render = False, renderVector = False)
+            return
+
+        if not self.IsPaneShown('3d') and self.IsAutoRendered():
+            # highlight feature & re-draw map
+            if qlayer:
+                qlayer.SetCmd(self.AddTmpVectorMapLayer(name, cats,
+                                                        useId = False,
+                                                        addLayer = False))
+            else:
+                qlayer = self.AddTmpVectorMapLayer(name, cats, useId = False)
             
-            if len(vect) < 1:
-                self._giface.WriteCmdLog(_("Nothing to query."))
-                return
+            # set opacity based on queried layer
+            # TODO fix
+            # opacity = layer.maplayer.GetOpacity(float = True)
+            # qlayer.SetOpacity(opacity)
             
-            vcmd.append('-a')
-            vcmd.append('map=%s' % ','.join(vect))
-            vcmd.append('layer=%s' % ','.join(['-1'] * len(vect)))
-            vcmd.append('coordinates=%f,%f' % (float(east), float(north)))
-            vcmd.append('distance=%f' % float(qdist))
-        
-        Debug.msg(1, "QueryMap(): raster=%s vector=%s" % (','.join(rast),
-                                                          ','.join(vect)))
-        # parse query command(s)
+            self.MapWindow.UpdateMap(render = False, renderVector = False)
 
-        if rast and not self.IsPaneShown('3d'):
-            self._giface.RunCmd(rcmd,
-                                compReg = False,
-                                onDone  =  self._QueryMapDone)
-        if vect:
-            self._giface.RunCmd(vcmd, onDone = self._QueryMapDone)
-        
-    def _QueryMapDone(self, cmd, returncode):
+    def _QueryMapDone(self):
         """!Restore settings after querying (restore GRASS_REGION)
-        
-        @param returncode command return code
         """
         if hasattr(self, "tmpreg"):
             if self.tmpreg:
@@ -794,73 +783,6 @@
         if hasattr(self, "tmpreg"):
             del self.tmpreg
         
-    def QueryVector(self, east, north, qdist, posWindow, layer):
-        """!Query vector map layer features
-
-        Attribute data of selected vector object are displayed in GUI dialog.
-        Data can be modified (On Submit)
-        """
-        mapName = layer.maplayer.name
-        
-        if layer.maplayer.GetMapset() != \
-                grass.gisenv()['MAPSET']:
-            mode = 'display'
-        else:
-            mode = 'update'
-        
-        if self.dialogs['attributes'] is None:
-            dlg = DisplayAttributesDialog(parent = self.MapWindow,
-                                                      map = mapName,
-                                                      query = ((east, north), qdist),
-                                                      pos = posWindow,
-                                                      action = mode)
-            self.dialogs['attributes'] = dlg
-        
-        else:
-            # selection changed?
-            if not self.dialogs['attributes'].mapDBInfo or \
-                    self.dialogs['attributes'].mapDBInfo.map != mapName:
-                self.dialogs['attributes'].UpdateDialog(map = mapName, query = ((east, north), qdist),
-                                                        action = mode)
-            else:
-                self.dialogs['attributes'].UpdateDialog(query = ((east, north), qdist),
-                                                        action = mode)
-        if not self.dialogs['attributes'].IsFound():
-            self._giface.WriteLog(_('Nothing found.'))
-        
-        cats = self.dialogs['attributes'].GetCats()
-        
-        qlayer = None
-        if not self.IsPaneShown('3d') and self.IsAutoRendered():
-            try:
-                qlayer = self.Map.GetListOfLayers(name = globalvar.QUERYLAYER)[0]
-            except IndexError:
-                pass
-        
-        if self.dialogs['attributes'].mapDBInfo and cats:
-            if not self.IsPaneShown('3d') and self.IsAutoRendered():
-                # highlight feature & re-draw map
-                if qlayer:
-                    qlayer.SetCmd(self.AddTmpVectorMapLayer(mapName, cats,
-                                                            useId = False,
-                                                            addLayer = False))
-                else:
-                    qlayer = self.AddTmpVectorMapLayer(mapName, cats, useId = False)
-                
-                # set opacity based on queried layer
-                opacity = layer.maplayer.GetOpacity(float = True)
-                qlayer.SetOpacity(opacity)
-                
-                self.MapWindow.UpdateMap(render = False, renderVector = False)
-            if not self.dialogs['attributes'].IsShown():
-                self.dialogs['attributes'].Show()
-        else:
-            if qlayer:
-                self.Map.DeleteLayer(qlayer)
-                self.MapWindow.UpdateMap(render = False, renderVector = False)
-            if self.dialogs['attributes'].IsShown():
-                self.dialogs['attributes'].Hide()
-        
     def OnQuery(self, event):
         """!Query tools menu"""
         if self.GetMapToolbar():
@@ -923,7 +845,7 @@
                 lcats = cats[layer]
                 cmd[-1].append("layer=%d" % layer)
                 cmd[-1].append("cats=%s" % ListOfCatsToRange(lcats))
-        
+
         if addLayer:
             if useId:
                 return self.Map.AddLayer(ltype = 'vector', name = globalvar.QUERYLAYER, command = cmd,

Modified: grass/trunk/lib/python/script/raster.py
===================================================================
--- grass/trunk/lib/python/script/raster.py	2013-02-07 14:22:28 UTC (rev 54971)
+++ grass/trunk/lib/python/script/raster.py	2013-02-07 15:09:56 UTC (rev 54972)
@@ -24,6 +24,7 @@
 
 import os
 import string
+import types
 
 from core import *
 
@@ -135,3 +136,43 @@
                         verbose = verbose,
                         overwrite = overwrite)
 
+# interface to r.what
+def raster_what(map, coord):
+    """!TODO"""
+    if type(map) in (types.StringType, types.UnicodeType):
+        map_list = [map]
+    else:
+        map_list = map
+
+    coord_list = list()
+    if type(coord) is types.TupleType:
+        coord_list.append('%f,%f' % (coord[0], coord[1]))
+    else:
+        for e, n in coord:
+            coord_list.append('%f,%f' % (e, n))
+    
+    sep = '|'
+    cmdParams = dict(quiet = True,
+                     flags = 'rf',
+                     separator = sep,
+                     map = ','.join(map_list),
+                     coordinates = ','.join(coord_list))
+
+    ret = read_command('r.what',
+                       **cmdParams)
+    data = list()
+    if not ret:
+        return data
+
+    labels = (_("value"), _("label"), _("color"))
+    for item in ret.splitlines():
+        line = item.split(sep)[3:]
+        for i, map_name in enumerate(map_list):
+            tmp_dict = {}
+            tmp_dict[map_name] = {}
+            for j in range(len(labels)):
+                tmp_dict[map_name][labels[j]] = line[i*len(labels)+j]
+
+            data.append(tmp_dict)
+
+    return data



More information about the grass-commit mailing list