From: daid Date: Fri, 20 Apr 2012 15:06:50 +0000 (+0200) Subject: Add progress window to project planner. X-Git-Tag: RC3~39 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=861610f376fed8ef0354f7761db2e61512cfb734;p=cura.git Add progress window to project planner. --- diff --git a/Cura/gui/projectPlanner.py b/Cura/gui/projectPlanner.py index 02de4e2e..f664d53d 100644 --- a/Cura/gui/projectPlanner.py +++ b/Cura/gui/projectPlanner.py @@ -1,7 +1,7 @@ from __future__ import absolute_import import __init__ -import wx, os, platform, types, webbrowser, math, subprocess +import wx, os, platform, types, webbrowser, math, subprocess, threading, time import ConfigParser from wx import glcanvas @@ -24,6 +24,9 @@ from util import util3d from util import stl from util import sliceRun +class Action(): + pass + class projectPlanner(wx.Frame): "Main user interface window" def __init__(self): @@ -223,6 +226,8 @@ class projectPlanner(wx.Frame): put('add_start_end_gcode', 'False') put('gcode_extension', 'project_tmp') + clearZ = 0 + actionList = [] for item in self.list: put('machine_center_x', item.centerX) put('machine_center_y', item.centerY) @@ -234,7 +239,14 @@ class projectPlanner(wx.Frame): put('swap_xz', item.swapXZ) put('swap_yz', item.swapYZ) - item.sliceCmd = sliceRun.getSliceCommand(item.filename) + action = Action() + action.sliceCmd = sliceRun.getSliceCommand(item.filename) + action.centerX = item.centerX + action.centerY = item.centerY + action.filename = item.filename + clearZ = max(clearZ, item.getMaximum().z * item.scale) + action.clearZ = clearZ + actionList.append(action) #Restore the old profile. profile.loadGlobalProfileFromString(oldProfile) @@ -244,44 +256,12 @@ class projectPlanner(wx.Frame): if dlg.ShowModal() != wx.ID_OK: dlg.Destroy() return - resultFile = open(dlg.GetPath(), "w") + resultFilename = dlg.GetPath() dlg.Destroy() - i = 1 - maxZ = 0 - prevItem = None - for item in self.list: - subprocess.call(item.sliceCmd) - - maxZ = max(maxZ, item.getMaximum().z * item.scale) - put('machine_center_x', item.centerX) - put('machine_center_y', item.centerY) - put('clear_z', maxZ) - - if prevItem == None: - resultFile.write(';TYPE:CUSTOM\n') - resultFile.write(profile.getAlterationFileContents('start.gcode')) - else: - #reset the extrusion length, and move to the next object center. - resultFile.write(';TYPE:CUSTOM\n') - resultFile.write(profile.getAlterationFileContents('nextobject.gcode')) - resultFile.write(';PRINTNR:%d\n' % (i)) - profile.loadGlobalProfileFromString(oldProfile) - - f = open(item.filename[: item.filename.rfind('.')] + "_export.project_tmp", "r") - data = f.read(4096) - while data != '': - resultFile.write(data) - data = f.read(4096) - f.close() - os.remove(item.filename[: item.filename.rfind('.')] + "_export.project_tmp") - i += 1 - - prevItem = item - - resultFile.write(';TYPE:CUSTOM\n') - resultFile.write(profile.getAlterationFileContents('end.gcode')) - resultFile.close() + pspw = ProjectSliceProgressWindow(actionList, resultFilename) + pspw.Centre() + pspw.Show(True) def loadModelFile(self, item): item.load(item.filename) @@ -561,6 +541,129 @@ class PreviewGLCanvas(glcanvas.GLCanvas): glFlush() +class ProjectSliceProgressWindow(wx.Frame): + def __init__(self, actionList, resultFilename): + super(ProjectSliceProgressWindow, self).__init__(None, title='Cura') + self.actionList = actionList + self.resultFilename = resultFilename + self.abort = False + self.prevStep = 'start' + self.totalDoneFactor = 0.0 + self.startTime = time.time() + + #How long does each step take compared to the others. This is used to make a better scaled progress bar, and guess time left. + # TODO: Duplicate with sliceProgressPanel, move to sliceRun. + self.sliceStepTimeFactor = { + 'start': 3.3713991642, + 'slice': 15.4984838963, + 'preface': 5.17178297043, + 'inset': 116.362634182, + 'fill': 215.702672005, + 'multiply': 21.9536788464, + 'speed': 12.759510994, + 'raft': 31.4580039978, + 'skirt': 19.3436040878, + 'skin': 1.0, + 'joris': 1.0, + 'comb': 23.7805759907, + 'cool': 27.148763895, + 'dimension': 90.4914340973 + } + self.totalRunTimeFactor = 0 + for v in self.sliceStepTimeFactor.itervalues(): + self.totalRunTimeFactor += v + + self.sizer = wx.GridBagSizer(2, 2) + self.statusText = wx.StaticText(self, -1, "Building: %s" % (resultFilename)) + self.progressGauge = wx.Gauge(self, -1) + self.progressGauge.SetRange(10000) + self.progressGauge2 = wx.Gauge(self, -1) + self.progressGauge2.SetRange(len(self.actionList)) + self.abortButton = wx.Button(self, -1, "Abort") + self.sizer.Add(self.statusText, (0,0), flag=wx.ALIGN_CENTER) + self.sizer.Add(self.progressGauge, (1, 0), flag=wx.EXPAND) + self.sizer.Add(self.progressGauge2, (2, 0), flag=wx.EXPAND) + self.sizer.Add(self.abortButton, (3,0), flag=wx.ALIGN_CENTER) + + 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): + self.abort = True + + def SetProgress(self, stepName, layer, maxLayer): + if self.prevStep != stepName: + self.totalDoneFactor += self.sliceStepTimeFactor[self.prevStep] + newTime = time.time() + #print "#####" + str(newTime-self.startTime) + " " + self.prevStep + " -> " + stepName + self.startTime = newTime + self.prevStep = stepName + + progresValue = ((self.totalDoneFactor + self.sliceStepTimeFactor[stepName] * layer / maxLayer) / self.totalRunTimeFactor) * 10000 + self.progressGauge.SetValue(int(progresValue)) + self.statusText.SetLabel(stepName + " [" + str(layer) + "/" + str(maxLayer) + "]") + + def OnRun(self): + resultFile = open(self.resultFilename, "w") + put = profile.putProfileSetting + for action in self.actionList: + p = subprocess.Popen(action.sliceCmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + line = p.stdout.readline() + + maxValue = 1 + self.progressLog = [] + 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 + self.progressLog.append(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() + + oldProfile = profile.getGlobalProfileString() + put('machine_center_x', action.centerX) + put('machine_center_y', action.centerY) + put('clear_z', action.clearZ) + + if action == self.actionList[0]: + resultFile.write(';TYPE:CUSTOM\n') + resultFile.write(profile.getAlterationFileContents('start.gcode')) + else: + #reset the extrusion length, and move to the next object center. + resultFile.write(';TYPE:CUSTOM\n') + resultFile.write(profile.getAlterationFileContents('nextobject.gcode')) + resultFile.write(';PRINTNR:%d\n' % self.actionList.index(action)) + profile.loadGlobalProfileFromString(oldProfile) + + f = open(action.filename[: action.filename.rfind('.')] + "_export.project_tmp", "r") + data = f.read(4096) + while data != '': + resultFile.write(data) + data = f.read(4096) + f.close() + os.remove(action.filename[: action.filename.rfind('.')] + "_export.project_tmp") + + wx.CallAfter(self.progressGauge.SetValue, 10000) + wx.CallAfter(self.progressGauge2.SetValue, self.actionList.index(action) + 1) + + resultFile.write(';TYPE:CUSTOM\n') + resultFile.write(profile.getAlterationFileContents('end.gcode')) + resultFile.close() + def main(): app = wx.App(False) projectPlanner().Show(True) diff --git a/Cura/util/profile.py b/Cura/util/profile.py index 66dc8ea9..55fc7f18 100644 --- a/Cura/util/profile.py +++ b/Cura/util/profile.py @@ -115,17 +115,16 @@ def getGlobalProfileString(): return '#'.join(ret) def getProfileSetting(name): - if name in profileDefaultSettings: - default = profileDefaultSettings[name] - else: - print "Missing default setting for: '" + name + "'" - profileDefaultSettings[name] = '' - default = '' - #Check if we have a configuration file loaded, else load the default. if not globals().has_key('globalProfileParser'): loadGlobalProfile(getDefaultProfilePath()) if not globalProfileParser.has_option('profile', name): + if name in profileDefaultSettings: + default = profileDefaultSettings[name] + else: + print "Missing default setting for: '" + name + "'" + profileDefaultSettings[name] = '' + default = '' if not globalProfileParser.has_section('profile'): globalProfileParser.add_section('profile') globalProfileParser.set('profile', name, str(default))