[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