[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