[GRASS-SVN] r33041 - grass/trunk/gui/wxpython/gui_modules
svn_grass at osgeo.org
svn_grass at osgeo.org
Sat Aug 23 19:03:00 EDT 2008
Author: martinl
Date: 2008-08-23 19:03:00 -0400 (Sat, 23 Aug 2008)
New Revision: 33041
Modified:
grass/trunk/gui/wxpython/gui_modules/dbm.py
grass/trunk/gui/wxpython/gui_modules/mapdisp.py
grass/trunk/gui/wxpython/gui_modules/render.py
Log:
wxGUI: fix attribute table manager "highlight selected and zoom" (v.db.select -r)
(merge from devbr6, r33040)
Modified: grass/trunk/gui/wxpython/gui_modules/dbm.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/dbm.py 2008-08-23 22:59:24 UTC (rev 33040)
+++ grass/trunk/gui/wxpython/gui_modules/dbm.py 2008-08-23 23:03:00 UTC (rev 33041)
@@ -87,8 +87,8 @@
self.mapDBInfo = mapDBInfo
self.layer = layer
- self.columns = {} # <- LoadData()
-
+ self.columns = {} # <- LoadData()
+
# self.selectedCats = []
# self.lastTurnSelectedCats = [] # just temporary, for comparation
@@ -137,94 +137,110 @@
self.mapDBInfo = mapDBInfo
self.LoadData(self.layer)
- def LoadData(self, layer, sql=None):
+ def LoadData(self, layer, columns=None, where=None):
"""Load data into list
@param layer layer number
- @param sql SQL select statement (if None 'SELECT * FROM table)
-
+ @param columns list of columns for output
+ @param where where statement
+
@return id of key column
@return -1 if key column is not displayed
"""
-
self.log.write(_("Loading data..."))
+
+ tableName = self.mapDBInfo.layers[layer]['table']
+ keyColumn = self.mapDBInfo.layers[layer]['key']
+ self.columns = self.mapDBInfo.tables[tableName]
+
+ cmd = ["v.db.select",
+ "-c", "--q",
+ "map=%s" % self.mapDBInfo.map,
+ "layer=%d" % layer]
+
+ if not columns:
+ columns = self.mapDBInfo.GetColumns(tableName)
+ else:
+ all = self.mapDBInfo.GetColumns(tableName)
+ cmd.append("columns=%s" % ','.join(columns))
+ for col in columns:
+ if col not in all:
+ wx.MessageBox(parent=self,
+ message=_("Column <%(column)s> not found in "
+ "in the table <%(table)s>.") % \
+ { 'column' : col, 'table' : tableName },
+ caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+ return
+
+ if where:
+ cmd.append("where=%s" % where)
+
+ try:
+ # for maps connected via v.external
+ keyId = columns.index(keyColumn)
+ except:
+ keyId = -1
+
+ #
+ # read data
+ #
+ # FIXME: Max. number of rows, while the GUI is still usable
+
+ # stdout can be very large, do not use PIPE, redirect to temp file
+ # TODO: more effective way should be implemented...
+ outFile = tempfile.NamedTemporaryFile(mode='w+b')
+
+ selectCommand = gcmd.Command(cmd,
+ stdout=outFile)
+
# These two should probably be passed to init more cleanly
# setting the numbers of items = number of elements in the dictionary
self.itemDataMap = {}
self.itemIndexMap = []
self.itemCatsMap = {}
-
+
self.DeleteAllItems()
-
+
# self.ClearAll()
for i in range(self.GetColumnCount()):
self.DeleteColumn(0)
-
- tableName = self.mapDBInfo.layers[layer]['table']
- keyColumn = self.mapDBInfo.layers[layer]['key']
- self.columns = self.mapDBInfo.tables[tableName]
-
- if sql is None:
- sql = "SELECT * FROM %s" % tableName
-
- if sql[7] != '*':
- columnNames = sql[7:].split(' ')[0].split(',')
- else:
- columnNames = self.mapDBInfo.GetColumns(tableName)
-
- try:
- # for maps connected via v.external
- keyId = columnNames.index(keyColumn)
- except:
- keyId = -1
-
+
i = 0
info = wx.ListItem()
info.m_mask = wx.LIST_MASK_TEXT | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT
info.m_image = -1
info.m_format = 0
- for column in columnNames:
+ for column in columns:
info.m_text = column
self.InsertColumnInfo(i, info)
i += 1
-
+
if i >= 256:
self.log.write(_("Can display only 256 columns."))
-
- #
- # read data
- #
- # FIXME: Max. number of rows, while the GUI is still usable
-
- # stdout can be very large, do not use PIPE, redirect to temp file
- # TODO: more effective way should be implemented...
- outFile = tempfile.NamedTemporaryFile(mode='w+b')
- selectCommand = gcmd.Command(["db.select", "-c", "--q",
- "sql=%s" % sql,
- "database=%s" % self.mapDBInfo.layers[layer]["database"],
- "driver=%s" % self.mapDBInfo.layers[layer]["driver"],
- "fs=|"],
- stdout=outFile)
+
i = 0
outFile.seek(0)
+
while True:
# os.linesep doesn't work here (MSYS)
record = outFile.readline().replace('\n', '')
if not record:
break
+
self.itemDataMap[i] = []
j = 0
+
for value in record.split('|'):
# casting ...
try:
- self.itemDataMap[i].append(self.columns[columnNames[j]]['ctype'] (value))
+ self.itemDataMap[i].append(self.columns[columns[j]]['ctype'] (value))
except:
self.itemDataMap[i].append('')
if keyId > -1 and keyId == j:
try:
- cat = self.columns[columnNames[j]]['ctype'] (value)
+ cat = self.columns[columns[j]]['ctype'] (value)
except ValueError, e:
cat = -1
wx.MessageBox(parent=self,
@@ -255,9 +271,9 @@
break
self.SetItemCount(i)
-
+
i = 0
- for col in columnNames:
+ for col in columns:
width = self.columns[col]['length'] * 6 # FIXME
if width < 60:
width = 60
@@ -1032,27 +1048,57 @@
"""Highlight selected features"""
if not self.map or not self.mapdisplay:
return
+
+ list = self.FindWindowById(self.layerPage[self.layer]['data'])
+ cats = map(int, list.GetSelectedItems())
digitToolbar = self.mapdisplay.toolbars['vdigit']
if digitToolbar and \
digitToolbar.GetLayer().GetName() == self.vectmap:
- list = self.FindWindowById(self.layerPage[self.layer]['data'])
- cats = map(int, list.GetSelectedItems())
+
self.mapdisplay.digit.driver.SetSelected(cats, cats=True)
if zoom:
n, s, w, e = self.mapdisplay.digit.driver.GetRegionSelected()
self.mapdisplay.Map.GetRegion(n=n, s=s, w=w, e=e,
update=True)
- self.mapdisplay.Map.AdjustRegion() # resolution
- self.mapdisplay.MapWindow.UpdateMap(render=True, renderVector=True)
- else:
- self.mapdisplay.MapWindow.UpdateMap(render=False, renderVector=True)
else:
# add map layer with higlighted vector features
self.AddQueryMapLayer()
- self.mapdisplay.MapWindow.UpdateMap(render=False, renderVector=False,
- zoom=zoom)
+ if zoom:
+ keyColumn = self.mapDBInfo.layers[self.layer]['key']
+ where = ''
+ for range in utils.ListOfCatsToRange(cats).split(','):
+ if '-' in range:
+ min, max = range.split('-')
+ where += '%s >= %d and %s <= %d or ' % \
+ (keyColumn, int(min),
+ keyColumn, int(max))
+ else:
+ where += '%s = %d or ' % (keyColumn, int(range))
+ where = where.rstrip('or ')
+
+ cmd = gcmd.Command(["v.db.select",
+ "-r", "--q",
+ "map=%s" % self.mapDBInfo.map,
+ "layer=%d" % self.layer,
+ "where=%s" % where])
+
+ region = {}
+ for line in cmd.ReadStdOutput():
+ key, value = line.split('=')
+ region[key] = float(value)
+
+ self.mapdisplay.Map.GetRegion(n=region['n'], s=region['s'],
+ w=region['w'], e=region['e'],
+ update=True)
+ if zoom:
+ self.mapdisplay.Map.AdjustRegion() # adjust resolution
+ self.mapdisplay.Map.AlignExtentFromDisplay() # adjust extent
+ self.mapdisplay.MapWindow.UpdateMap(render=True, renderVector=True)
+ else:
+ self.mapdisplay.MapWindow.UpdateMap(render=False, renderVector=True)
+
def OnDataDrawSelected(self, event):
"""Reload table description"""
self._drawSelected(zoom=False)
@@ -1576,44 +1622,38 @@
where = self.FindWindowById(self.layerPage[self.layer]['where']).GetValue().strip()
try:
if len(where) > 0:
- sql = "SELECT * FROM %s WHERE %s" % (self.mapDBInfo.layers[self.layer]['table'],
- where)
- keyColumn = listWin.LoadData(self.layer, sql=sql)
+ keyColumn = listWin.LoadData(self.layer, where=where)
else:
keyColumn = listWin.LoadData(self.layer)
- except gcmd.CmdError:
+ except gcmd.CmdError, e:
wx.MessageBox(parent=self,
- message=_("Loading attribute data failed. "
- "Invalid SQL 'select' statement.\n\n"
- "'%s'") % sql,
+ message=_("Loading attribute data failed.\n\n%s") % e.message,
caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
- keyColumn = listWin.LoadData(self.layer)
self.FindWindowById(self.layerPage[self.layer]['where']).SetValue('')
else:
# advanced sql statement
- # valid, cols, where = \
- # self.ValidateSelectStatement( \
- # self.FindWindowById(self.layerPage[self.layer]['statement']).GetValue().strip())
- #
- #Debug.msg(4, "AttributeManager.OnApplySqlStatament(): valid=%s, cols=%s, where=%s" %
- # (valid, cols, where))
- sql = self.FindWindowById(self.layerPage[self.layer]['statement']).GetValue()
+ win = self.FindWindowById(self.layerPage[self.layer]['statement'])
try:
- # if valid is True:
- keyColumn = listWin.LoadData(self.layer,
- sql=sql)
- # else:
- # raise gcmd.GException('')
- except gcmd.CmdError:
+ cols, where = self.ValidateSelectStatement(win.GetValue())
+ except TypeError:
wx.MessageBox(parent=self,
- message=_("Loading attribute data failed. "
- "Invalid SQL 'select' statement.\n\n"
- "'%s'") % sql,
+ message=_("Loading attribute data failed.\n"
+ "Invalid SQL select statement.\n\n%s") % win.GetValue(),
caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
- keyColumn = listWin.LoadData(self.layer)
- self.FindWindowById(self.layerPage[self.layer]['statement']).\
- SetValue("SELECT * FROM %s" % self.mapDBInfo.layers[self.layer]['table'])
-
+ win.SetValue("SELECT * FROM %s" % self.mapDBInfo.layers[self.layer]['table'])
+ cols = None
+ where = None
+ print cols, where
+ if cols or where:
+ try:
+ keyColumn = listWin.LoadData(self.layer, columns=cols,
+ where=where)
+ except gcmd.CmdError, e:
+ wx.MessageBox(parent=self,
+ message=_("Loading attribute data failed.\n\n%s") % e.message,
+ caption=_("Error"), style=wx.OK | wx.ICON_ERROR | wx.CENTRE)
+ win.SetValue("SELECT * FROM %s" % self.mapDBInfo.layers[self.layer]['table'])
+
# sort by key column
if keyColumn > -1:
listWin.SortListItems(col=keyColumn, ascending=True)
@@ -1625,18 +1665,14 @@
self.FindWindowById(self.layerPage[self.layer]['data']).GetItemCount())
def ValidateSelectStatement(self, statement):
- """Validate Select SQL statement
+ """Validate SQL select statement
- TODO: check list of columns and where statement
-
- Return True if valid, False if not
- Return list of columns (or '*' for all columns)
- Return where statement
+ @return (columns, where)
+ @return None on error
"""
-
if statement[0:7].lower() != 'select ':
- return (False, '', '')
-
+ return None
+
cols = ''
index = 7
for c in statement[index:]:
@@ -1644,25 +1680,29 @@
break
cols += c
index += 1
-
+ if cols == '*':
+ cols = None
+ else:
+ cols = cols.split(',')
+
tablelen = len(self.mapDBInfo.layers[self.layer]['table'])
-
+
if statement[index+1:index+6].lower() != 'from ' or \
statement[index+6:index+6+tablelen] != '%s' % \
(self.mapDBInfo.layers[self.layer]['table']):
- return (False, '', '')
-
+ return None
+
if len(statement[index+7+tablelen:]) > 0:
index = statement.lower().find('where ')
if index > -1:
where = statement[index+6:]
else:
- where = ''
+ return None
else:
- where = ''
-
- return (True, cols, where)
-
+ where = None
+
+ return (cols, where)
+
def OnInfoPaneChanged(self, event):
"""Collapse database connection info box"""
Modified: grass/trunk/gui/wxpython/gui_modules/mapdisp.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/mapdisp.py 2008-08-23 22:59:24 UTC (rev 33040)
+++ grass/trunk/gui/wxpython/gui_modules/mapdisp.py 2008-08-23 23:03:00 UTC (rev 33041)
@@ -612,14 +612,13 @@
return img
- def UpdateMap(self, render=True, renderVector=True, zoom=False):
+ def UpdateMap(self, render=True, renderVector=True):
"""
Updates the canvas anytime there is a change to the
underlaying images or to the geometry of the canvas.
@param render re-render map composition
@param renderVector re-render vector map layer enabled for editing (used for digitizer)
- @param zoom zoom to region given by 'd.vect -r'
"""
start = time.clock()
@@ -658,10 +657,9 @@
# use computation region resolution for rendering
windres = True
self.mapfile = self.Map.Render(force=True, mapWindow=self.parent,
- windres=windres, zoom=zoom)
+ windres=windres)
else:
- self.mapfile = self.Map.Render(force=False, mapWindow=self.parent,
- zoom=zoom)
+ self.mapfile = self.Map.Render(force=False, mapWindow=self.parent)
self.img = self.GetImage() # id=99
@@ -2188,7 +2186,7 @@
# selected layer must be a valid map
if layer.type in ('raster', 'rgb', 'his', 'shaded', 'arrow'):
if layer.type == 'raster':
- self.Map.region = self.Map.GetRegion(rast="%s" % layer.name, zoom=zoom)
+ self.Map.region = self.Map.GetRegion(rast="%s" % layer.name)
else:
self.Map.region = self.Map.GetRegion(rast="%s" % layer.name)
elif layer.type in ('vector', 'thememap', 'themechart'):
@@ -3416,7 +3414,6 @@
str(color[2])
cmd = ["d.vect",
- # "-r", # print minimal region extent
"map=%s" % name,
"color=%s" % colorStr,
"fcolor=%s" % colorStr,
Modified: grass/trunk/gui/wxpython/gui_modules/render.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/render.py 2008-08-23 22:59:24 UTC (rev 33040)
+++ grass/trunk/gui/wxpython/gui_modules/render.py 2008-08-23 23:03:00 UTC (rev 33041)
@@ -97,11 +97,9 @@
Debug.msg (3, "Layer.__del__(): layer=%s, cmd='%s'" %
(self.name, self.GetCmd(string=True)))
- def Render(self, zoom):
+ def Render(self):
"""Render layer to image
- @param zoom if True zoom to extent given by 'd.vect -r'
-
@return rendered image filename
@return None on error
"""
@@ -150,12 +148,6 @@
runcmd = gcmd.Command(cmd=self.cmdlist + ['--q'],
stderr=None)
- if zoom:
- self._region = {}
- for line in runcmd.ReadStdOutput():
- key, value = line.split('=')
- self._region[key] = float(value)
-
if runcmd.returncode != 0:
#clean up after probley
try:
@@ -809,7 +801,7 @@
return selected
- def _renderLayers(self, force, zoom, mapWindow, maps, masks, opacities):
+ def _renderLayers(self, force, mapWindow, maps, masks, opacities):
# render map layers
ilayer = 1
for layer in self.layers + self.overlays:
@@ -822,18 +814,9 @@
layer.force_render or \
layer.mapfile == None or \
(not os.path.isfile(layer.mapfile) or not os.path.getsize(layer.mapfile)):
- if not layer.Render(zoom):
+ if not layer.Render():
continue
- zoomToRegion = layer.GetRegion()
- if zoomToRegion:
- self.GetRegion(n=zoomToRegion['n'], s=zoomToRegion['s'],
- w=zoomToRegion['w'], e=zoomToRegion['e'],
- update=True)
- self.AdjustRegion() # resolution
- print self.region
- return False
-
# update progress bar
wx.SafeYield(mapWindow)
event = wxUpdateProgressBar(value=ilayer)
@@ -850,7 +833,7 @@
return True
- def Render(self, force=False, mapWindow=None, windres=False, zoom=False):
+ def Render(self, force=False, mapWindow=None, windres=False):
"""
Creates final image composite
@@ -860,7 +843,6 @@
@param force force rendering
@param reference for MapFrame instance (for progress bar)
@param windres use region resolution (True) otherwise display resolution
- @param zoom zoom to region given by 'd.vect -r'
@return name of file with rendered image or None
"""
@@ -886,7 +868,7 @@
os.environ["GRASS_TRUECOLOR"] = "TRUE"
os.environ["GRASS_RENDER_IMMEDIATE"] = "TRUE"
- if not self._renderLayers(force, zoom, mapWindow, maps, masks, opacities):
+ if not self._renderLayers(force, mapWindow, maps, masks, opacities):
os.environ["GRASS_REGION"] = self.SetRegion(windres)
self._renderLayers(True, False, mapWindow, maps, masks, opacities)
More information about the grass-commit
mailing list