chiark / gitweb /
Added basic batch run tool. Still needs some more enhancements.
authordaid <daid303@gmail.com>
Thu, 28 Jun 2012 12:13:03 +0000 (14:13 +0200)
committerdaid <daid303@gmail.com>
Thu, 28 Jun 2012 12:13:03 +0000 (14:13 +0200)
Cura/gui/batchRun.py [new file with mode: 0644]
Cura/gui/mainWindow.py

diff --git a/Cura/gui/batchRun.py b/Cura/gui/batchRun.py
new file mode 100644 (file)
index 0000000..67792d9
--- /dev/null
@@ -0,0 +1,185 @@
+from __future__ import absolute_import
+import __init__
+
+import wx, os, platform, types, webbrowser, math, subprocess, threading, time, re
+
+from util import profile
+from util import sliceRun
+
+class batchRunWindow(wx.Frame):
+       def __init__(self, parent):
+               super(batchRunWindow, self).__init__(parent, title='Cura - Batch run')
+               
+               self.list = []
+               
+               wx.EVT_CLOSE(self, self.OnClose)
+               self.panel = wx.Panel(self, -1)
+               self.SetSizer(wx.BoxSizer(wx.VERTICAL))
+               self.GetSizer().Add(self.panel, 1, flag=wx.EXPAND)
+               #self.SetIcon(icon.getMainIcon())
+
+               self.sizer = wx.GridBagSizer(2,2)
+               self.panel.SetSizer(self.sizer)
+
+               self.listbox = wx.ListBox(self.panel, -1, choices=[])
+               self.addButton = wx.Button(self.panel, -1, "Add")
+               self.remButton = wx.Button(self.panel, -1, "Remove")
+               self.sliceButton = wx.Button(self.panel, -1, "Slice")
+
+               self.addButton.Bind(wx.EVT_BUTTON, self.OnAddModel)
+               self.remButton.Bind(wx.EVT_BUTTON, self.OnRemModel)
+               self.sliceButton.Bind(wx.EVT_BUTTON, self.OnSlice)
+               self.listbox.Bind(wx.EVT_LISTBOX, self.OnListSelect)
+
+               self.sizer.Add(self.listbox, (0,0), span=(1,3), flag=wx.EXPAND)
+               self.sizer.Add(self.addButton, (1,0), span=(1,1))
+               self.sizer.Add(self.remButton, (1,1), span=(1,1))
+               self.sizer.Add(self.sliceButton, (1,2), span=(1,1))
+
+               self.sizer.AddGrowableCol(2)
+               self.sizer.AddGrowableRow(0)
+
+       def OnAddModel(self, e):
+               dlg=wx.FileDialog(self, "Open file to batch slice", os.path.split(profile.getPreference('lastFile'))[0], style=wx.FD_OPEN|wx.FD_FILE_MUST_EXIST|wx.FD_MULTIPLE)
+               dlg.SetWildcard("STL files (*.stl)|*.stl;*.STL")
+               if dlg.ShowModal() == wx.ID_OK:
+                       for filename in dlg.GetPaths():
+                               profile.putPreference('lastFile', filename)
+                               self.list.append(filename)
+                               self.selection = filename
+                               self._updateListbox()
+               dlg.Destroy()
+       
+       def OnRemModel(self, e):
+               if self.selection == None:
+                       return
+               self.list.remove(self.selection)
+               self._updateListbox()
+
+       def OnListSelect(self, e):
+               if self.listbox.GetSelection() == -1:
+                       return
+               self.selection = self.list[self.listbox.GetSelection()]
+
+       def _updateListbox(self):
+               self.listbox.Clear()
+               for item in self.list:
+                       self.listbox.AppendAndEnsureVisible(os.path.split(item)[1])
+               if self.selection in self.list:
+                       self.listbox.SetSelection(self.list.index(self.selection))
+               elif len(self.list) > 0:
+                       self.selection = self.list[0]
+                       self.listbox.SetSelection(0)
+               else:
+                       self.selection = None
+                       self.listbox.SetSelection(-1)
+
+       def OnClose(self, e):
+               self.Destroy()
+
+       def OnSlice(self, e):
+               sliceCmdList = []
+               for filename in self.list:
+                       sliceCmdList.append(sliceRun.getSliceCommand(filename))
+               bspw = BatchSliceProgressWindow(self.list[:], sliceCmdList)
+               bspw.Centre()
+               bspw.Show(True)
+       
+class BatchSliceProgressWindow(wx.Frame):
+       def __init__(self, filenameList, sliceCmdList):
+               super(BatchSliceProgressWindow, self).__init__(None, title='Cura')
+               self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
+               
+               self.filenameList = filenameList
+               self.sliceCmdList = sliceCmdList
+               self.abort = False
+               self.prevStep = 'start'
+               self.totalDoneFactor = 0.0
+               self.startTime = time.time()
+               self.sliceStartTime = time.time()
+               
+               self.sizer = wx.GridBagSizer(2, 2) 
+               self.statusText = wx.StaticText(self, -1, "Building: %d XXXXXXXXXXXXXXXXXXXXX" % (len(self.sliceCmdList)))
+               self.progressGauge = wx.Gauge(self, -1)
+               self.progressGauge.SetRange(10000)
+               self.progressGauge2 = wx.Gauge(self, -1)
+               self.progressGauge2.SetRange(len(self.sliceCmdList))
+               self.abortButton = wx.Button(self, -1, "Abort")
+               self.sizer.Add(self.statusText, (0,0), span=(1,4))
+               self.sizer.Add(self.progressGauge, (1, 0), span=(1,4), flag=wx.EXPAND)
+               self.sizer.Add(self.progressGauge2, (2, 0), span=(1,4), flag=wx.EXPAND)
+
+               self.sizer.Add(self.abortButton, (3,0), span=(1,4), flag=wx.ALIGN_CENTER)
+               self.sizer.AddGrowableCol(0)
+               self.sizer.AddGrowableRow(0)
+
+               self.Bind(wx.EVT_BUTTON, self.OnAbort, self.abortButton)
+               self.SetSizer(self.sizer)
+               self.Layout()
+               self.Fit()
+               
+               threading.Thread(target=self.OnRun).start()
+
+       def OnAbort(self, e):
+               if self.abort:
+                       self.Close()
+               else:
+                       self.abort = True
+                       self.abortButton.SetLabel('Close')
+
+       def SetProgress(self, stepName, layer, maxLayer):
+               if self.prevStep != stepName:
+                       self.totalDoneFactor += sliceRun.sliceStepTimeFactor[self.prevStep]
+                       newTime = time.time()
+                       #print "#####" + str(newTime-self.startTime) + " " + self.prevStep + " -> " + stepName
+                       self.startTime = newTime
+                       self.prevStep = stepName
+               
+               progresValue = ((self.totalDoneFactor + sliceRun.sliceStepTimeFactor[stepName] * layer / maxLayer) / sliceRun.totalRunTimeFactor) * 10000
+               self.progressGauge.SetValue(int(progresValue))
+               self.statusText.SetLabel(stepName + " [" + str(layer) + "/" + str(maxLayer) + "]")
+       
+       def OnRun(self):
+               for action in self.sliceCmdList:
+                       wx.CallAfter(self.SetTitle, "Building: [%d/%d]"  % (self.sliceCmdList.index(action) + 1, len(self.sliceCmdList)))
+
+                       p = subprocess.Popen(action, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+                       line = p.stdout.readline()
+                       maxValue = 1
+                       while(len(line) > 0):
+                               line = line.rstrip()
+                               if line[0:9] == "Progress[" and line[-1:] == "]":
+                                       progress = line[9:-1].split(":")
+                                       if len(progress) > 2:
+                                               maxValue = int(progress[2])
+                                       wx.CallAfter(self.SetProgress, progress[0], int(progress[1]), maxValue)
+                               else:
+                                       print line
+                                       wx.CallAfter(self.statusText.SetLabel, line)
+                               if self.abort:
+                                       p.terminate()
+                                       wx.CallAfter(self.statusText.SetLabel, "Aborted by user.")
+                                       return
+                               line = p.stdout.readline()
+                       self.returnCode = p.wait()
+                       
+                       wx.CallAfter(self.progressGauge.SetValue, 10000)
+                       self.totalDoneFactor = 0.0
+                       wx.CallAfter(self.progressGauge2.SetValue, self.sliceCmdList.index(action) + 1)
+               
+               self.abort = True
+               sliceTime = time.time() - self.sliceStartTime
+               status = "Build: %d" % (len(self.sliceCmdList))
+               status += "\nSlicing took: %02d:%02d" % (sliceTime / 60, sliceTime % 60)
+
+               wx.CallAfter(self.statusText.SetLabel, status)
+               wx.CallAfter(self.OnSliceDone)
+       
+       def OnSliceDone(self):
+               self.abortButton.Destroy()
+               self.closeButton = wx.Button(self, -1, "Close")
+               self.sizer.Add(self.closeButton, (3,0), span=(1,1))
+               self.Bind(wx.EVT_BUTTON, self.OnAbort, self.closeButton)
+               self.Layout()
+               self.Fit()
+
index 036d5746610feae034ade4465fdc0853345651ec..453bd63c108f663e050312ce78c0d32893e2dee3 100644 (file)
@@ -15,6 +15,7 @@ from gui import firmwareInstall
 from gui import printWindow
 from gui import simpleMode
 from gui import projectPlanner
+from gui import batchRun
 from gui import flatSlicerWindow
 from gui import icon
 from util import profile
@@ -53,6 +54,8 @@ class mainWindow(configBase.configWindowBase):
                i = fileMenu.Append(-1, 'Reset Profile to default')
                self.Bind(wx.EVT_MENU, self.OnResetProfile, i)
                fileMenu.AppendSeparator()
+               i = fileMenu.Append(-1, 'Batch run...')
+               self.Bind(wx.EVT_MENU, self.OnBatchRun, i)
                i = fileMenu.Append(-1, 'Preferences...')
                self.Bind(wx.EVT_MENU, self.OnPreferences, i)
                fileMenu.AppendSeparator()
@@ -267,6 +270,11 @@ class mainWindow(configBase.configWindowBase):
                        profile.resetGlobalProfile()
                        self.updateProfileToControls()
        
+       def OnBatchRun(self, e):
+               br = batchRun.batchRunWindow(self)
+               br.Centre()
+               br.Show(True)
+       
        def OnPreferences(self, e):
                prefDialog = preferencesDialog.preferencesDialog(self)
                prefDialog.Centre()