[GRASS-SVN] r32450 - in grass/trunk/gui/wxpython: . gui_modules
svn_grass at osgeo.org
svn_grass at osgeo.org
Fri Aug 1 11:28:45 EDT 2008
Author: martinl
Date: 2008-08-01 11:28:45 -0400 (Fri, 01 Aug 2008)
New Revision: 32450
Modified:
grass/trunk/gui/wxpython/gui_modules/gcmd.py
grass/trunk/gui/wxpython/gui_modules/gdialogs.py
grass/trunk/gui/wxpython/gui_modules/goutput.py
grass/trunk/gui/wxpython/gui_modules/menudata.py
grass/trunk/gui/wxpython/wxgui.py
Log:
wxGUI: initial version of dialog for multiple dxf file import (each layer is imported as separate vector map)
Modified: grass/trunk/gui/wxpython/gui_modules/gcmd.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/gcmd.py 2008-08-01 15:08:28 UTC (rev 32449)
+++ grass/trunk/gui/wxpython/gui_modules/gcmd.py 2008-08-01 15:28:45 UTC (rev 32450)
@@ -349,11 +349,11 @@
os.linesep, os.linesep,
_("Details:"),
os.linesep,
- self.PrintModuleOutput()))
+ _("Error: ") + self.GetError()))
elif rerr == sys.stderr: # redirect message to sys
stderr.write("Execution failed: '%s'" % (' '.join(self.cmd)))
stderr.write("%sDetails:%s%s" % (os.linesep,
- self.PrintModuleOutput(),
+ _("Error: ") + self.GetError(),
os.linesep))
else:
pass # nop
@@ -408,7 +408,7 @@
if self.stderr is None:
lines = self.ReadErrOutput()
else:
- lines = self.cmdThread.rerr.strip('%s' % os.linesep). \
+ lines = self.cmdThread.error.strip('%s' % os.linesep). \
split('%s' % os.linesep)
msg = []
@@ -435,6 +435,14 @@
return msg
+ def GetError(self):
+ """Get error message or ''"""
+ for type, msg in self.__ProcessStdErr():
+ if type == 'ERROR':
+ return msg
+
+ return ''
+
def PrintModuleOutput(self, error=True, warning=False, message=False):
"""Print module errors, warnings, messages to output
@@ -544,7 +552,8 @@
if self.stderr:
line = recv_some(self.module, e=0, stderr=1)
self.stderr.write(line)
- self.rerr = line
+ if len(line) > 0:
+ self.error = line
# get the last output
if self.stdout:
@@ -554,8 +563,8 @@
line = recv_some(self.module, e=0, stderr=1)
self.stderr.write(line)
if len(line) > 0:
- self.rerr = line
-
+ self.error = line
+
def abort(self):
"""Abort running process, used by main thread to signal an abort"""
self._want_abort = True
Modified: grass/trunk/gui/wxpython/gui_modules/gdialogs.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/gdialogs.py 2008-08-01 15:08:28 UTC (rev 32449)
+++ grass/trunk/gui/wxpython/gui_modules/gdialogs.py 2008-08-01 15:28:45 UTC (rev 32450)
@@ -9,7 +9,9 @@
- DecorationDialog
- TextLayerDialog
- LoadMapLayersDialog
-
+ - ImportDxfDialog
+ - LayerList (used by ImportDxfMulti)
+
(C) 2008 by the GRASS Development Team
This program is free software under the GNU General Public
@@ -19,10 +21,13 @@
@author Martin Landa <landa.martin gmail.com>
"""
+import os
import sys
import re
import wx
+import wx.lib.filebrowsebutton as filebrowse
+import wx.lib.mixins.listctrl as listmix
import gcmd
import grassenv
@@ -702,3 +707,217 @@
"""Get selected layer type"""
return self.layerType.GetStringSelection()
+class ImportDxfDialog(wx.Dialog):
+ """Import dxf layers"""
+ def __init__(self, parent, id=wx.ID_ANY, title=_("Import DXF layers"),
+ style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER):
+
+ self.parent = parent # GMFrame
+
+ wx.Dialog.__init__(self, parent, id, title, style=style)
+
+ self.panel = wx.Panel(parent=self, id=wx.ID_ANY)
+
+ #
+ # input
+ #
+ self.input = filebrowse.FileBrowseButton(parent=self.panel, id=wx.ID_ANY,
+ size=globalvar.DIALOG_GSELECT_SIZE, labelText='',
+ dialogTitle=_('Choose DXF file to import'),
+ buttonText=_('Browse'),
+ startDirectory=os.getcwd(), fileMode=0,
+ changeCallback=self.OnSetInput) # TODO: wildcard
+
+
+ #
+ # list of layers
+ #
+ self.list = LayersList(self)
+ self.list.LoadData()
+
+ #
+ # buttons
+ #
+ # cancel
+ self.btn_cancel = wx.Button(parent=self.panel, id=wx.ID_CANCEL)
+ self.btn_cancel.SetToolTipString(_("Close dialog"))
+ self.btn_cancel.Bind(wx.EVT_BUTTON, self.OnCancel)
+ # run
+ self.btn_run = wx.Button(parent=self.panel, id=wx.ID_OK, label= _("&Run"))
+ self.btn_run.SetToolTipString(_("Import selected layers"))
+ self.btn_run.SetDefault()
+ self.btn_run.Enable(False)
+ self.btn_run.Bind(wx.EVT_BUTTON, self.OnRun)
+ # abort
+ self.btn_abort = wx.Button(parent=self.panel, id=wx.ID_STOP)
+ self.btn_abort.SetToolTipString(_("Abort the running command"))
+ self.btn_abort.Enable(False)
+ self.btn_abort.Bind(wx.EVT_BUTTON, self.OnAbort)
+
+ self.__doLayout()
+ self.Layout()
+
+ def __doLayout(self):
+ dialogSizer = wx.BoxSizer(wx.VERTICAL)
+ #
+ # input
+ #
+ inputBox = wx.StaticBox(parent=self.panel, id=wx.ID_ANY,
+ label=" %s " % _("Input DXF file"))
+ inputSizer = wx.StaticBoxSizer(inputBox, wx.HORIZONTAL)
+
+ inputSizer.Add(item=wx.StaticText(self.panel, id=wx.ID_ANY, label=_("Choose DXF file:")),
+ proportion=0,
+ flag=wx.ALIGN_CENTER_VERTICAL)
+
+ inputSizer.Add(item=self.input, proportion=1,
+ flag=wx.EXPAND, border=1)
+
+ dialogSizer.Add(item=inputSizer, proportion=0,
+ flag=wx.ALL | wx.EXPAND, border=5)
+
+ #
+ # list of DXF layers
+ #
+ layerBox = wx.StaticBox(parent=self.panel, id=wx.ID_ANY,
+ label=" %s " % _("List of DXF layers"))
+ layerSizer = wx.StaticBoxSizer(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_cancel, proportion=0,
+ flag=wx.ALL | wx.ALIGN_CENTER,
+ border=10)
+
+ btnsizer.Add(item=self.btn_abort, proportion=0,
+ flag=wx.ALL | wx.ALIGN_CENTER,
+ border=10)
+
+ btnsizer.Add(item=self.btn_run, proportion=0,
+ flag=wx.ALL | wx.ALIGN_CENTER,
+ border=10)
+
+ dialogSizer.Add(item=btnsizer, proportion=0,
+ flag=wx.ALIGN_CENTER)
+
+ # dialogSizer.SetSizeHints(self.panel)
+ # self.panel.SetAutoLayout(True)
+ self.panel.SetSizer(dialogSizer)
+ dialogSizer.Fit(self.panel)
+
+ self.Layout()
+ # auto-layout seems not work here - FIXME
+ self.SetMinSize((globalvar.DIALOG_GSELECT_SIZE[0] + 125, 200))
+ width = self.GetSize()[0]
+ self.list.SetColumnWidth(col=1, width=width/2)
+
+ def OnCancel(self, event=None):
+ """Close dialog"""
+ self.Close()
+
+ def OnRun(self, event):
+ """Import data (each layes as separate vector map)"""
+ data = self.list.GetLayers()
+
+ # hide dialog
+ self.Hide()
+
+ for layer, output in data:
+ cmd = ['v.in.dxf',
+ 'input=%s' % self.input.GetValue(),
+ 'layers=%s' % layer,
+ 'output=%s' % output]
+ if UserSettings.Get(group='cmd', key='overwrite', subkey='enabled'):
+ cmd.append('--overwrite')
+
+ # run in Layer Manager
+ self.parent.goutput.RunCmd(cmd)
+
+ self.OnCancel()
+
+ def OnAbort(self, event):
+ """Abort running import"""
+ pass
+
+ def OnSetInput(self, event):
+ """Input DXF file/OGR dsn defined, update list of layer widget"""
+ filePath = event.GetString()
+
+ try:
+ cmd = gcmd.Command(['v.in.dxf',
+ 'input=%s' % filePath,
+ '-l', '--q'], stderr=None)
+ except gcmd.CmdError, e:
+ wx.MessageBox(parent=self, message=_("File <%(file)s>: Unable to get list of DXF layers.\n\n%(details)s") % \
+ { 'file' : filePath, 'details' : e.message },
+ caption=_("Error"), style=wx.ID_OK | wx.ICON_ERROR | wx.CENTRE)
+ self.list.LoadData()
+ self.btn_run.Enable(False)
+ return
+
+ data = []
+ for line in cmd.ReadStdOutput():
+ layerId = line.split(':')[0].split(' ')[1]
+ layer = line.split(':')[1]
+ layerName, grassName = layer.split('/')
+ data.append((layerId, layerName.strip(), grassName.strip()))
+
+ self.list.LoadData(data)
+ self.btn_run.Enable(True)
+
+class LayersList(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin,
+ listmix.CheckListCtrlMixin, listmix.TextEditMixin):
+ """List of layers to be imported (dxf, shp...)"""
+ def __init__(self, parent, pos=wx.DefaultPosition,
+ log=None):
+ self.parent = parent
+
+ wx.ListCtrl.__init__(self, parent, wx.ID_ANY,
+ style=wx.LC_REPORT)
+ listmix.CheckListCtrlMixin.__init__(self)
+ self.log = log
+
+ # setup mixins
+ listmix.ListCtrlAutoWidthMixin.__init__(self)
+ listmix.TextEditMixin.__init__(self)
+
+ self.InsertColumn(0, _('Layer'))
+ self.InsertColumn(1, _('Layer name'))
+ self.InsertColumn(2, _('Output vector map name (editable)'))
+
+ def LoadData(self, data=None):
+ """Load data into list"""
+ if data is None:
+ return
+
+ for id, name, grassName in data:
+ index = self.InsertStringItem(sys.maxint, str(id))
+ self.SetStringItem(index, 1, "%s" % str(name))
+ self.SetStringItem(index, 2, "%s" % str(grassName))
+ # check by default
+ self.CheckItem(index, True)
+
+ self.SetColumnWidth(col=0, width=wx.LIST_AUTOSIZE_USEHEADER)
+
+ def GetLayers(self):
+ """Get list of layers (layer name, output name)"""
+ data = []
+ item = -1
+ while True:
+ item = self.GetNextItem(item)
+ if item == -1:
+ break
+ # layer / output name
+ data.append((self.GetItem(item, 1).GetText(),
+ self.GetItem(item, 2).GetText()))
+
+ return data
Modified: grass/trunk/gui/wxpython/gui_modules/goutput.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/goutput.py 2008-08-01 15:08:28 UTC (rev 32449)
+++ grass/trunk/gui/wxpython/gui_modules/goutput.py 2008-08-01 15:28:45 UTC (rev 32450)
@@ -35,6 +35,7 @@
wxCmdOutput, EVT_CMD_OUTPUT = NewEvent()
wxCmdProgress, EVT_CMD_PROGRESS = NewEvent()
+wxCmdRun, EVT_CMD_RUN = NewEvent()
wxCmdDone, EVT_CMD_DONE = NewEvent()
wxCmdAbort, EVT_CMD_ABORT = NewEvent()
@@ -61,7 +62,6 @@
def RunCmd(self, callable, *args, **kwds):
CmdThread.requestId += 1
- self.requestTime = time.time()
self.requestCmd = None
self.requestQ.put((CmdThread.requestId, callable, args, kwds))
@@ -70,13 +70,24 @@
def run(self):
while True:
requestId, callable, args, kwds = self.requestQ.get()
+
+ requestTime = time.time()
+ event = wxCmdRun(cmd=args[0],
+ pid=requestId)
+ wx.PostEvent(self.parent, event)
+
self.requestCmd = callable(*args, **kwds)
+
+ time.sleep(.1)
+
self.resultQ.put((requestId, self.requestCmd.run()))
event = wxCmdDone(aborted=self.requestCmd.aborted,
- time=self.requestTime,
+ time=requestTime,
pid=requestId)
+
time.sleep(.1)
+
wx.PostEvent(self.parent, event)
def abort(self):
@@ -120,6 +131,7 @@
self.cmd_output_timer = wx.Timer(self.cmd_output, id=wx.ID_ANY)
self.cmd_output.Bind(EVT_CMD_OUTPUT, self.OnCmdOutput)
self.cmd_output.Bind(wx.EVT_TIMER, self.OnProcessPendingOutputWindowEvents)
+ self.Bind(EVT_CMD_RUN, self.OnCmdRun)
self.Bind(EVT_CMD_DONE, self.OnCmdDone)
#
@@ -240,15 +252,12 @@
except:
curr_disp = None
- if not self.requestQ.empty():
- # only one running command enabled (per GMConsole instance)
- busy = wx.BusyInfo(message=_("Unable to run the command, another command is running..."),
- parent=self)
- wx.Yield()
- time.sleep(3)
- busy.Destroy()
- return None
-
+ # switch to 'Command output'
+ if hasattr(self.parent, "curr_page"):
+ # change notebook page only for Layer Manager
+ if self.parent.notebook.GetSelection() != 1:
+ self.parent.notebook.SetSelection(1)
+
# command given as a string ?
try:
cmdlist = command.strip().split(' ')
@@ -299,9 +308,6 @@
menuform.GUI().ParseCommand(cmdlist, parentframe=self)
else:
# process GRASS command with argument
- cmdPID = self.cmdThread.requestId + 1
- self.WriteCmdLog('%s' % ' '.join(cmdlist), pid=cmdPID)
-
self.cmdThread.RunCmd(GrassCmd,
cmdlist, self.cmd_stdout, self.cmd_stderr)
@@ -314,10 +320,6 @@
else:
# Send any other command to the shell. Send output to
# console output window
- if hasattr(self.parent, "curr_page"):
- # change notebook page only for Layer Manager
- if self.parent.notebook.GetSelection() != 1:
- self.parent.notebook.SetSelection(1)
# if command is not a GRASS command, treat it like a shell command
try:
@@ -369,7 +371,6 @@
"""Print command output"""
message = event.text
type = event.type
-
# message prefix
if type == 'warning':
messege = 'WARNING: ' + message
@@ -425,7 +426,11 @@
def OnCmdAbort(self, event):
"""Abort running command"""
self.cmdThread.abort()
-
+
+ def OnCmdRun(self, event):
+ """Run command"""
+ self.WriteCmdLog('%s' % ' '.join(event.cmd), pid=event.pid)
+
def OnCmdDone(self, event):
"""Command done (or aborted)"""
if event.aborted:
@@ -606,7 +611,7 @@
self.StyleMessageSpec = "face:Courier New,size:10,fore:#000000,back:#FFFFFF"
# unknown
self.StyleUnknown = 6
- self.StyleUnknownSpec = "face:Courier New,size:10,fore:#7F0000,back:#FFFFFF"
+ self.StyleUnknownSpec = "face:Courier New,size:10,fore:#000000,back:#FFFFFF"
# default and clear => init
self.StyleSetSpec(wx.stc.STC_STYLE_DEFAULT, self.StyleDefaultSpec)
Modified: grass/trunk/gui/wxpython/gui_modules/menudata.py
===================================================================
--- grass/trunk/gui/wxpython/gui_modules/menudata.py 2008-08-01 15:08:28 UTC (rev 32449)
+++ grass/trunk/gui/wxpython/gui_modules/menudata.py 2008-08-01 15:28:45 UTC (rev 32450)
@@ -153,6 +153,12 @@
"self.OnMenuCmd",
"v.in.dxf"),
+ (_("Multiple DXF import"),
+ _("Converts selected DXF layers to GRASS vector maps."),
+ "self.OnImportDxfFile",
+ ""),
+ ("","","", ""),
+
(_("ESRI e00 import"),
_("Import E00 file into a vector map."),
"self.OnMenuCmd",
Modified: grass/trunk/gui/wxpython/wxgui.py
===================================================================
--- grass/trunk/gui/wxpython/wxgui.py 2008-08-01 15:08:28 UTC (rev 32449)
+++ grass/trunk/gui/wxpython/wxgui.py 2008-08-01 15:28:45 UTC (rev 32450)
@@ -1027,6 +1027,9 @@
Icons["attrtable"].GetLabel(), self.OnShowAttributeTable)
)
+ def OnImportDxfFile(self, event):
+ gdialogs.ImportDxfDialog(parent=self).ShowModal()
+
def OnShowAttributeTable(self, event):
"""
Show attribute table of the given vector map layer
More information about the grass-commit
mailing list