[GRASS-SVN] r67285 - in grass/trunk/gui/wxpython: gui_core modules
svn_grass at osgeo.org
svn_grass at osgeo.org
Sun Dec 20 10:13:18 PST 2015
Author: turek
Date: 2015-12-20 10:13:18 -0800 (Sun, 20 Dec 2015)
New Revision: 67285
Modified:
grass/trunk/gui/wxpython/gui_core/forms.py
grass/trunk/gui/wxpython/gui_core/gselect.py
grass/trunk/gui/wxpython/gui_core/widgets.py
grass/trunk/gui/wxpython/modules/import_export.py
Log:
wx.gui data import: show reprojection dialog
Modified: grass/trunk/gui/wxpython/gui_core/forms.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/forms.py 2015-12-20 16:35:37 UTC (rev 67284)
+++ grass/trunk/gui/wxpython/gui_core/forms.py 2015-12-20 18:13:18 UTC (rev 67285)
@@ -1710,11 +1710,11 @@
flag = wx.EXPAND | wx.ALL, border = 3)
porf = self.task.get_param('input', element = 'name', raiseError = False)
winDataSource = self.FindWindowById(porf['wxId'][0])
- winDataSource.reloadDataRequired.connect(lambda data: self.win1.LoadData(data, False))
+ winDataSource.reloadDataRequired.connect(lambda listData: self.win1.LoadData(listData, False))
p['wxId'] = [self.win1.GetId()]
def OnCheckItem(index, flag):
layers = list()
- for layer, match in self.win1.GetLayers():
+ for layer, match, listId in self.win1.GetLayers():
layers.append(layer)
porf = self.task.get_param('layer', element = 'name', raiseError = False)
porf['value'] = ','.join(layers)
Modified: grass/trunk/gui/wxpython/gui_core/gselect.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/gselect.py 2015-12-20 16:35:37 UTC (rev 67284)
+++ grass/trunk/gui/wxpython/gui_core/gselect.py 2015-12-20 18:13:18 UTC (rev 67285)
@@ -1738,7 +1738,7 @@
self.SetDatabase(db)
if not self.dest:
- self.reloadDataRequired.emit(data=None)
+ self.reloadDataRequired.emit(listData=None, data=None)
self._reloadLayers()
def OnSettingsChanged(self, data):
@@ -1778,7 +1778,7 @@
self.dbWidgets['options'].SetValue(data[3])
if not self.dest:
- self.reloadDataRequired.emit(data=None)
+ self.reloadDataRequired.emit(listData=None, data=None)
self._reloadLayers()
def AttachSettings(self):
@@ -1913,11 +1913,40 @@
def _reloadLayers(self):
"""Reload list of layers"""
+
+ def hasRastSameProjAsLocation(dsn):
+
+ ret = RunCommand('r.external',
+ quiet = True,
+ read = True,
+ flags = 't',
+ input = dsn)
+
+ # v.external returns info for individual bands, however projection is shared by all bands ->
+ # (it is possible to take first line)
+
+ lines = ret.splitlines()
+ projectionMatch = '0'
+ if lines:
+ bandNumber, bandType, projectionMatch = map(lambda x: x.strip(), lines[0].split(','))
+
+ return projectionMatch
+
+ def getProjMatchCaption(projectionMatch):
+
+ if projectionMatch == '0':
+ projectionMatchCaption = _("No")
+ else:
+ projectionMatchCaption = _("Yes")
+
+ return projectionMatchCaption
+
dsn = self.GetDsn()
if not dsn:
return
data = list()
+ listData = list()
layerId = 1
if self.ogr:
@@ -1927,37 +1956,40 @@
flags = 't',
input = dsn)
if not ret:
- self.reloadDataRequired.emit(data=None)
+ self.reloadDataRequired.emit(listData=None, data=None)
return
layerId = 1
for line in ret.splitlines():
- layerName, featureType, projection, geometryColumn = map(lambda x: x.strip(), line.split(','))
- if projection == '0':
- projectionMatch = _("No")
- else:
- projectionMatch = _("Yes")
+ layerName, featureType, projectionMatch, geometryColumn = map(lambda x: x.strip(), line.split(','))
+ projectionMatchCaption = getProjMatchCaption(projectionMatch)
grassName = GetValidLayerName(layerName)
if geometryColumn:
featureType = geometryColumn + '/' + featureType
- data.append((layerId, layerName, featureType, projectionMatch, grassName))
+ listData.append((layerId, layerName, featureType, projectionMatchCaption, grassName))
+ data.append((layerId, layerName, featureType, int(projectionMatch), grassName))
layerId += 1
else:
if self._sourceType == 'file':
baseName = os.path.basename(dsn)
grassName = GetValidLayerName(baseName.split('.', -1)[0])
- data.append((layerId, baseName, grassName))
+ projectionMatch = hasRastSameProjAsLocation(dsn)
+ projectionMatchCaption = getProjMatchCaption(projectionMatch)
+ listData.append((layerId, baseName, projectionMatchCaption, grassName))
+ data.append((layerId, baseName, int(projectionMatch), grassName))
elif self._sourceType == 'dir':
ext = self.dirWidgets['extension'].GetValue()
for filename in glob.glob(os.path.join(dsn, "%s") % self._getExtPatternGlob(ext)):
baseName = os.path.basename(filename)
-
grassName = GetValidLayerName(baseName.split('.', -1)[0])
- data.append((layerId, baseName, grassName))
+ projectionMatch = hasRastSameProjAsLocation(dsn)
+ projectionMatchCaption = getProjMatchCaption(projectionMatch)
+ listData.append((layerId, baseName, projectionMatchCaption, grassName))
+ data.append((layerId, baseName, int(projectionMatch), grassName))
layerId += 1
# emit signal
- self.reloadDataRequired.emit(data=data)
+ self.reloadDataRequired.emit(listData=listData, data=data)
def ExtensionChanged(self, event):
if not self.dest:
Modified: grass/trunk/gui/wxpython/gui_core/widgets.py
===================================================================
--- grass/trunk/gui/wxpython/gui_core/widgets.py 2015-12-20 16:35:37 UTC (rev 67284)
+++ grass/trunk/gui/wxpython/gui_core/widgets.py 2015-12-20 18:13:18 UTC (rev 67285)
@@ -921,7 +921,51 @@
event.Skip()
+ def GetData(self, checked=None):
+ """Get list data"""
+ data = []
+ checkedList = []
+
+ item = -1
+ while True:
+
+ row = []
+ item = self.GetNextItem(item)
+ if item == -1:
+ break
+ isChecked = self.IsChecked(item)
+ if checked is not None and checked != isChecked:
+ continue
+
+ checkedList.append(isChecked)
+
+ for i in range(self.GetColumnCount()):
+ row.append(self.GetItem(item, i).GetText())
+
+ row.append(item)
+ data.append(tuple(row))
+
+ if checked is not None:
+ return tuple(data)
+ else:
+ return (tuple(data), tuple(checkedList))
+
+ def LoadData(self, data=None, selectOne=True):
+ """Load data into list"""
+ self.DeleteAllItems()
+ if data is None:
+ return
+
+ for item in data:
+ index = self.InsertStringItem(sys.maxint, str(item[0]))
+ for i in range(1, self.GetColumnCount()):
+ self.SetStringItem(index, i, item[i])
+
+ # check by default only on one item
+ if len(data) == 1 and selectOne:
+ self.CheckItem(index, True)
+
class SearchModuleWidget(wx.Panel):
"""Search module widget (used e.g. in SearchModuleWindow)
@@ -1465,29 +1509,14 @@
for i in range(len(columns)):
self.InsertColumn(i, columns[i])
- if len(columns) == 3:
- width = (65, 200)
+ if len(columns) == 4:
+ width = (65, 200, 90)
else:
width = (65, 180, 90, 70)
for i in range(len(width)):
self.SetColumnWidth(col = i, width = width[i])
-
- def LoadData(self, data = None, selectOne = True):
- """Load data into list"""
- self.DeleteAllItems()
- if data is None:
- return
-
- for item in data:
- index = self.InsertStringItem(sys.maxint, str(item[0]))
- for i in range(1, self.GetColumnCount()):
- self.SetStringItem(index, i, item[i])
-
- # check by default only on one item
- if len(data) == 1 and selectOne:
- self.CheckItem(index, True)
-
+
def OnLeftDown(self, event):
"""Allow editing only output name
@@ -1509,21 +1538,19 @@
event.Skip()
def GetLayers(self):
- """Get list of layers (layer name, output name)"""
- data = []
- item = -1
- while True:
- item = self.GetNextItem(item)
- if item == -1:
- break
- if not self.IsChecked(item):
- continue
- # layer / output name
- layer = self.GetItem(item, 1).GetText()
- ftype = self.GetItem(item, 2).GetText()
+ """Get list of layers (layer name, output name, list id)"""
+ layers = []
+
+ data = self.GetData(checked=True);
+
+ for itm in data:
+
+ layer = itm[1]
+ ftype = itm[2]
if '/' in ftype:
layer += '|%s' % ftype.split('/', 1)[0]
- output = self.GetItem(item, self.GetColumnCount() - 1).GetText()
- data.append((layer, output))
-
- return data
+ output = itm[self.GetColumnCount() - 1]
+ layers.append((layer, output, itm[-1]))
+
+ return layers
+
Modified: grass/trunk/gui/wxpython/modules/import_export.py
===================================================================
--- grass/trunk/gui/wxpython/modules/import_export.py 2015-12-20 16:35:37 UTC (rev 67284)
+++ grass/trunk/gui/wxpython/modules/import_export.py 2015-12-20 18:13:18 UTC (rev 67285)
@@ -8,6 +8,7 @@
- :class:`GdalImportDialog`
- :class:`GdalOutputDialog`
- :class:`DxfImportDialog`
+ - :class:`ReprojectionDialog`
(C) 2008-2015 by the GRASS Development Team
@@ -29,7 +30,7 @@
from core import globalvar
from core.gcmd import RunCommand, GMessage, GWarning
from gui_core.gselect import OgrTypeSelect, GdalSelect, SubGroupSelect
-from gui_core.widgets import LayersList
+from gui_core.widgets import LayersList, GListCtrl
from core.utils import GetValidLayerName, _
from core.settings import UserSettings, GetDisplayVectSettings
@@ -67,6 +68,8 @@
if itype == 'ogr':
columns.insert(2, _('Feature type'))
columns.insert(3, _('Projection match'))
+ elif itype == 'gdal':
+ columns.insert(2, _('Projection match'))
self.list = LayersList(parent = self.panel, columns = columns)
self.list.LoadData()
@@ -231,7 +234,7 @@
# * try to determine names using regexp or
# * persuade import tools to report map names
self.commandId += 1
- layer, output = self.list.GetLayers()[self.commandId]
+ layer, output = self.list.GetLayers()[self.commandId][:2]
if '@' not in output:
name = output + '@' + grass.gisenv()['MAPSET']
@@ -295,7 +298,7 @@
"""Dialog for bulk import of various raster/vector data
.. todo::
- Split into GdalImportDialog and OgrImportDialog
+ Split into GdalImportDialog and OgrImportDialog, split importing logic from gui code
:param parent: parent window
:param ogr: True for OGR (vector) otherwise GDAL (raster)
@@ -304,7 +307,9 @@
self._giface = giface
self.link = link
self.ogr = ogr
-
+
+ self.layersData = []
+
if ogr:
ImportDialog.__init__(self, parent, giface=giface, itype='ogr')
if link:
@@ -321,7 +326,7 @@
self.dsnInput = GdalSelect(parent = self, panel = self.panel,
ogr = ogr, link = link)
self.dsnInput.AttachSettings()
- self.dsnInput.reloadDataRequired.connect(lambda data: self.list.LoadData(data))
+ self.dsnInput.reloadDataRequired.connect(self.reload)
if link:
self.add.SetLabel(_("Add linked layers into layer tree"))
@@ -339,10 +344,22 @@
self.doLayout()
+ def reload(self, data, listData):
+
+ self.list.LoadData(listData);
+ self.layersData = data;
+
def OnRun(self, event):
"""Import/Link data (each layes as separate vector map)"""
self.commandId = -1
data = self.list.GetLayers()
+
+
+ data = self._getLayersToReprojetion()
+
+ if data is None:
+ return;
+
if not data:
GMessage(_("No layers selected. Operation canceled."),
parent = self)
@@ -360,9 +377,10 @@
self.popOGR = True
os.environ['GRASS_VECTOR_OGR'] = '1'
- for layer, output in data:
+ for layer, output, listId in data:
userData = {}
if self.importType == 'ogr':
+
if ext and layer.rfind(ext) > -1:
layer = layer.replace('.' + ext, '')
if '|' in layer:
@@ -374,6 +392,12 @@
'input=%s' % dsn,
'output=%s' % output,
'layer=%s' % layer]
+
+ elif self.layersData[listId][3] == 0:
+ cmd = ['v.import',
+ 'input=%s' % dsn,
+ 'layer=%s' % layer,
+ 'output=%s' % output]
else:
cmd = ['v.in.ogr',
'input=%s' % dsn,
@@ -430,6 +454,49 @@
# run in Layer Manager
self._giface.RunCmd(cmd, onDone = self.OnCmdDone, userData = userData)
+
+ def _getLayersToReprojetion(self):
+ """If there are layers with different projection from loation projection,
+ show dialog to user to explicitly select layers which will be reprojected..."""
+ differentProjLayers = []
+ data = self.list.GetData(checked=True)
+
+ if self.importType == 'ogr':
+ projMatch_idx = 3
+ grassName_idx = 4
+ else:#gdal
+ projMatch_idx = 2
+ grassName_idx = 3
+
+ for itm in data:
+
+ layerId = itm[-1]
+
+ # select only layers with different projetion
+ if self.layersData[layerId][projMatch_idx] == 0:
+ dt = [itm[0], itm[grassName_idx]]
+ differentProjLayers.append(tuple(dt))
+
+ layers = self.list.GetLayers()
+
+ if differentProjLayers:
+
+ dlg = RerojectionDialog(
+ parent=self, giface=self._giface, data=differentProjLayers)
+
+ ret = dlg.ShowModal()
+
+ if ret == wx.ID_OK:
+
+ # do not import unchecked layers
+ for itm in reversed(list(dlg.GetData(checked=False))):
+ idx = itm[-1]
+ layers.pop(idx)
+ else:
+ return None;
+
+ return layers
+
def OnCmdDone(self, event):
"""Load layers and close if required"""
if not hasattr(self, 'AddLayers'):
@@ -635,3 +702,95 @@
data.append((layerId, layerName.strip(), grassName.strip()))
self.list.LoadData(data)
+
+class RerojectionDialog(wx.Dialog):
+ """ """
+ def __init__(self, parent, giface, data,
+ id = wx.ID_ANY, title = _("Reprojection"),
+ style = wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
+ self.parent = parent # GMFrame
+ self._giface = giface # used to add layers
+
+ wx.Dialog.__init__(self, parent, id, title, style = style,
+ name = "MultiImportDialog")
+
+
+ self.panel = wx.Panel(parent = self, id = wx.ID_ANY)
+
+ # list of layers
+ columns = [_('Layer id'),
+ _('Name for output GRASS map')]
+
+ self.list = GListCtrl(parent = self.panel)
+
+ for i in range(len(columns)):
+ self.list.InsertColumn(i, columns[i])
+
+ width = (65, 180)
+
+ for i in range(len(width)):
+ self.list.SetColumnWidth(col=i, width=width[i])
+
+ self.list.LoadData(data)
+
+ self.layerBox = wx.StaticBox(parent=self.panel, id=wx.ID_ANY)
+
+ self.labelText = wx.StaticText(parent=self.panel, id=wx.ID_ANY, label=_("Projection of following layers do not match with projection of current location. "))
+
+ label = _("Layers to be reprojected")
+ self.layerBox.SetLabel(" %s - %s " % (label, _("right click to (un)select all")))
+
+ #
+ # buttons
+ #
+ # cancel
+ self.btn_close = wx.Button(parent = self.panel, id = wx.ID_CANCEL)
+
+ # run
+ self.btn_run = wx.Button(parent = self.panel, id = wx.ID_OK, label = _("&Import && reproject"))
+ self.btn_run.SetToolTipString(_("Reproject selected layers"))
+ self.btn_run.SetDefault()
+
+ self.doLayout()
+
+ def doLayout(self):
+ """Do layout"""
+ dialogSizer = wx.BoxSizer(wx.VERTICAL)
+
+ dialogSizer.Add(item = self.labelText,
+ flag = wx.ALL | wx.EXPAND, border = 5)
+
+ layerSizer = wx.StaticBoxSizer(self.layerBox, wx.HORIZONTAL)
+
+
+ layerSizer.Add(item = self.list, proportion = 1,
+ flag = wx.ALL | wx.EXPAND, border = 5)
+
+ dialogSizer.Add(item = layerSizer, proportion = 1,
+ flag = wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border = 5)
+
+ #
+ # buttons
+ #
+ btnsizer = wx.BoxSizer(orient = wx.HORIZONTAL)
+
+ btnsizer.Add(item = self.btn_close, proportion = 0,
+ flag = wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER,
+ border = 10)
+
+ btnsizer.Add(item = self.btn_run, proportion = 0,
+ flag = wx.RIGHT | wx.ALIGN_CENTER,
+ border = 10)
+
+ dialogSizer.Add(item = btnsizer, proportion = 0,
+ flag = wx.ALIGN_CENTER_VERTICAL | wx.BOTTOM | wx.ALIGN_RIGHT,
+ border = 10)
+
+ self.panel.SetSizer(dialogSizer)
+ dialogSizer.Fit(self.panel)
+
+ self.Layout()
+
+ def GetData(self, checked):
+
+ return self.list.GetData(checked)
More information about the grass-commit
mailing list