X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=Cura%2Fgui%2FprintWindow.py;h=1a0e2cbe116c63a3b67bb6a8ac49c121a8a23609;hb=6208201bafdeaf82883181471c6da3a41283cfe7;hp=e79d5c2e2f89d5b25b75d5a94aaa7218b786111f;hpb=40e86b2883139bb3de3ca97ae551c1f51483c0c0;p=cura.git diff --git a/Cura/gui/printWindow.py b/Cura/gui/printWindow.py index e79d5c2e..1a0e2cbe 100644 --- a/Cura/gui/printWindow.py +++ b/Cura/gui/printWindow.py @@ -1,5 +1,5 @@ -# coding=utf-8 from __future__ import absolute_import +__copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License" import threading import re @@ -7,7 +7,9 @@ import subprocess import sys import time import platform +import os import power +import datetime import wx from wx.lib import buttons @@ -16,63 +18,98 @@ from Cura.gui.util import webcam from Cura.gui.util import taskbar from Cura.util import machineCom from Cura.util import gcodeInterpreter -from Cura.util.resources import getPathForImage - -printWindowMonitorHandle = None - -def printFile(filename): - global printWindowMonitorHandle - if printWindowMonitorHandle == None: - printWindowMonitorHandle = printProcessMonitor() - printWindowMonitorHandle.loadFile(filename) - - -def startPrintInterface(filename): - #startPrintInterface is called from the main script when we want the printer interface to run in a seperate process. - # It needs to run in a seperate process, as any running python code blocks the GCode sender pyton code (http://wiki.python.org/moin/GlobalInterpreterLock). - app = wx.App(False) - printWindowHandle = printWindow() - printWindowHandle.Show(True) - printWindowHandle.Raise() - printWindowHandle.OnConnect(None) - t = threading.Thread(target=printWindowHandle.LoadGCodeFile, args=(filename,)) - t.daemon = True - t.start() - app.MainLoop() - +from Cura.util import resources +from Cura.util import profile +#The printProcessMonitor is used from the main GUI python process. This monitors the printing python process. +# This class also handles starting of the 2nd process for printing and all communications with it. class printProcessMonitor(): - def __init__(self): + def __init__(self, callback = None): self.handle = None - - def loadFile(self, filename): - if self.handle == None: - cmdList = [sys.executable, sys.argv[0], '-r', filename] + self._state = 'CLOSED' + self._z = 0.0 + self._callback = callback + self._id = -1 + + def loadFile(self, filename, id): + if self.handle is None: + if platform.system() == "Darwin" and hasattr(sys, 'frozen'): + cmdList = [os.path.join(os.path.dirname(sys.executable), 'Cura')] + else: + cmdList = [sys.executable, '-m', 'Cura.cura'] + cmdList.append('-r') + cmdList.append(filename) if platform.system() == "Darwin": if platform.machine() == 'i386': cmdList.insert(0, 'arch') cmdList.insert(1, '-i386') - self.handle = subprocess.Popen(cmdList, stdin=subprocess.PIPE, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + #Save the preferences before starting the print window so we use the proper machine settings. + profile.savePreferences(profile.getPreferencePath()) + self.handle = subprocess.Popen(cmdList, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.thread = threading.Thread(target=self.Monitor) self.thread.start() else: - self.handle.stdin.write(filename + '\n') + self.handle.stdin.write('LOAD:%s\n' % filename) + self._id = id def Monitor(self): p = self.handle line = p.stdout.readline() - while(len(line) > 0): - #print line.rstrip() + while len(line) > 0: + line = line.rstrip() + try: + if line.startswith('Z:'): + self._z = float(line[2:]) + self._callCallback() + elif line.startswith('STATE:'): + self._state = line[6:] + self._callCallback() + else: + print '>' + line.rstrip() + except: + print sys.exc_info() line = p.stdout.readline() + line = p.stderr.readline() + while len(line) > 0: + print '>>' + line.rstrip() + line = p.stderr.readline() p.communicate() self.handle = None self.thread = None + def getID(self): + return self._id + + def getZ(self): + return self._z + + def getState(self): + return self._state + + def _callCallback(self): + if self._callback is not None: + self._callback() + +def startPrintInterface(filename): + #startPrintInterface is called from the main script when we want the printer interface to run in a separate process. + # It needs to run in a separate process, as any running python code blocks the GCode sender python code (http://wiki.python.org/moin/GlobalInterpreterLock). + + sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) + + app = wx.App(False) + resources.setupLocalization(profile.getPreference('language')) + printWindowHandle = printWindow() + printWindowHandle.Show(True) + printWindowHandle.Raise() + printWindowHandle.OnConnect(None) + t = threading.Thread(target=printWindowHandle.LoadGCodeFile, args=(filename,)) + t.daemon = True + t.start() + app.MainLoop() class PrintCommandButton(buttons.GenBitmapButton): def __init__(self, parent, commandList, bitmapFilename, size=(20, 20)): - self.bitmap = wx.Bitmap(getPathForImage(bitmapFilename)) + self.bitmap = wx.Bitmap(resources.getPathForImage(bitmapFilename)) super(PrintCommandButton, self).__init__(parent.directControlPanel, -1, self.bitmap, size=size) self.commandList = commandList @@ -84,7 +121,7 @@ class PrintCommandButton(buttons.GenBitmapButton): self.Bind(wx.EVT_BUTTON, self.OnClick) def OnClick(self, e): - if self.parent.machineCom == None or self.parent.machineCom.isPrinting(): + if self.parent.machineCom is None or self.parent.machineCom.isPrinting(): return; for cmd in self.commandList: self.parent.machineCom.sendCommand(cmd) @@ -95,7 +132,8 @@ class printWindow(wx.Frame): "Main user interface window" def __init__(self): - super(printWindow, self).__init__(None, -1, title='Printing') + super(printWindow, self).__init__(None, -1, title=_("Printing")) + t = time.time() self.machineCom = None self.gcode = None self.gcodeList = None @@ -113,10 +151,6 @@ class printWindow(wx.Frame): self.termHistoryIdx = 0 self.cam = None - if webcam.hasWebcamSupport(): - self.cam = webcam.webcam() - if not self.cam.hasCamera(): - self.cam = None self.SetSizer(wx.BoxSizer()) self.panel = wx.Panel(self) @@ -124,12 +158,12 @@ class printWindow(wx.Frame): self.sizer = wx.GridBagSizer(2, 2) self.panel.SetSizer(self.sizer) - sb = wx.StaticBox(self.panel, label="Statistics") + sb = wx.StaticBox(self.panel, label=_("Statistics")) boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL) self.powerWarningText = wx.StaticText(parent=self.panel, id=-1, - label="Your computer is running on battery power.\nConnect your computer to AC power or your print might not finish.", + label=_("Your computer is running on battery power.\nConnect your computer to AC power or your print might not finish."), style=wx.ALIGN_CENTER) self.powerWarningText.SetBackgroundColour('red') self.powerWarningText.SetForegroundColour('white') @@ -140,18 +174,17 @@ class printWindow(wx.Frame): self.OnPowerWarningChange(None) self.powerWarningTimer.Start(10000) - self.statsText = wx.StaticText(self.panel, -1, - "Filament: ####.##m #.##g\nEstimated print time: #####:##\nMachine state:\nDetecting baudrateXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") + self.statsText = wx.StaticText(self.panel, -1, _("Filament: ####.##m #.##g\nEstimated print time: #####:##\nMachine state:\nDetecting baudrateXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")) boxsizer.Add(self.statsText, flag=wx.LEFT, border=5) self.sizer.Add(boxsizer, pos=(0, 0), span=(7, 1), flag=wx.EXPAND) - self.connectButton = wx.Button(self.panel, -1, 'Connect') + self.connectButton = wx.Button(self.panel, -1, _("Connect")) #self.loadButton = wx.Button(self.panel, -1, 'Load') - self.printButton = wx.Button(self.panel, -1, 'Print') - self.pauseButton = wx.Button(self.panel, -1, 'Pause') - self.cancelButton = wx.Button(self.panel, -1, 'Cancel print') - self.machineLogButton = wx.Button(self.panel, -1, 'Error log') + self.printButton = wx.Button(self.panel, -1, _("Print")) + self.pauseButton = wx.Button(self.panel, -1, _("Pause")) + self.cancelButton = wx.Button(self.panel, -1, _("Cancel print")) + self.machineLogButton = wx.Button(self.panel, -1, _("Error log")) self.progress = wx.Gauge(self.panel, -1) self.sizer.Add(self.connectButton, pos=(1, 1), flag=wx.EXPAND) @@ -163,6 +196,7 @@ class printWindow(wx.Frame): self.sizer.Add(self.progress, pos=(7, 0), span=(1, 7), flag=wx.EXPAND) nb = wx.Notebook(self.panel) + self.tabs = nb self.sizer.Add(nb, pos=(0, 2), span=(7, 4), flag=wx.EXPAND) self.temperaturePanel = wx.Panel(nb) @@ -171,22 +205,23 @@ class printWindow(wx.Frame): self.temperatureSelect = wx.SpinCtrl(self.temperaturePanel, -1, '0', size=(21 * 3, 21), style=wx.SP_ARROW_KEYS) self.temperatureSelect.SetRange(0, 400) - self.bedTemperatureLabel = wx.StaticText(self.temperaturePanel, -1, "BedTemp:") - self.bedTemperatureSelect = wx.SpinCtrl(self.temperaturePanel, -1, '0', size=(21 * 3, 21), - style=wx.SP_ARROW_KEYS) + self.temperatureHeatUp = wx.Button(self.temperaturePanel, -1, str(int(profile.getProfileSettingFloat('print_temperature'))) + 'C') + self.bedTemperatureLabel = wx.StaticText(self.temperaturePanel, -1, _("BedTemp:")) + self.bedTemperatureSelect = wx.SpinCtrl(self.temperaturePanel, -1, '0', size=(21 * 3, 21), style=wx.SP_ARROW_KEYS) self.bedTemperatureSelect.SetRange(0, 400) self.bedTemperatureLabel.Show(False) self.bedTemperatureSelect.Show(False) self.temperatureGraph = temperatureGraph(self.temperaturePanel) - sizer.Add(wx.StaticText(self.temperaturePanel, -1, "Temp:"), pos=(0, 0)) + sizer.Add(wx.StaticText(self.temperaturePanel, -1, _("Temp:")), pos=(0, 0)) sizer.Add(self.temperatureSelect, pos=(0, 1)) + sizer.Add(self.temperatureHeatUp, pos=(0, 2)) sizer.Add(self.bedTemperatureLabel, pos=(1, 0)) sizer.Add(self.bedTemperatureSelect, pos=(1, 1)) - sizer.Add(self.temperatureGraph, pos=(2, 0), span=(1, 2), flag=wx.EXPAND) + sizer.Add(self.temperatureGraph, pos=(2, 0), span=(1, 3), flag=wx.EXPAND) sizer.AddGrowableRow(2) - sizer.AddGrowableCol(1) + sizer.AddGrowableCol(2) nb.AddPage(self.temperaturePanel, 'Temp') @@ -227,7 +262,7 @@ class printWindow(wx.Frame): sizer.Add(PrintCommandButton(self, ['G92 E0', 'G1 E-2 F120'], 'retract.png', size=(60, 20)), pos=(2, 10), span=(1, 3), flag=wx.EXPAND) - nb.AddPage(self.directControlPanel, 'Jog') + nb.AddPage(self.directControlPanel, _("Jog")) self.speedPanel = wx.Panel(nb) sizer = wx.GridBagSizer(2, 2) @@ -242,20 +277,20 @@ class printWindow(wx.Frame): self.supportSpeedSelect = wx.SpinCtrl(self.speedPanel, -1, '100', size=(21 * 3, 21), style=wx.SP_ARROW_KEYS) self.supportSpeedSelect.SetRange(5, 1000) - sizer.Add(wx.StaticText(self.speedPanel, -1, "Outer wall:"), pos=(0, 0)) + sizer.Add(wx.StaticText(self.speedPanel, -1, _("Outer wall:")), pos=(0, 0)) sizer.Add(self.outerWallSpeedSelect, pos=(0, 1)) sizer.Add(wx.StaticText(self.speedPanel, -1, "%"), pos=(0, 2)) - sizer.Add(wx.StaticText(self.speedPanel, -1, "Inner wall:"), pos=(1, 0)) + sizer.Add(wx.StaticText(self.speedPanel, -1, _("Inner wall:")), pos=(1, 0)) sizer.Add(self.innerWallSpeedSelect, pos=(1, 1)) sizer.Add(wx.StaticText(self.speedPanel, -1, "%"), pos=(1, 2)) - sizer.Add(wx.StaticText(self.speedPanel, -1, "Fill:"), pos=(2, 0)) + sizer.Add(wx.StaticText(self.speedPanel, -1, _("Fill:")), pos=(2, 0)) sizer.Add(self.fillSpeedSelect, pos=(2, 1)) sizer.Add(wx.StaticText(self.speedPanel, -1, "%"), pos=(2, 2)) - sizer.Add(wx.StaticText(self.speedPanel, -1, "Support:"), pos=(3, 0)) + sizer.Add(wx.StaticText(self.speedPanel, -1, _("Support:")), pos=(3, 0)) sizer.Add(self.supportSpeedSelect, pos=(3, 1)) sizer.Add(wx.StaticText(self.speedPanel, -1, "%"), pos=(3, 2)) - nb.AddPage(self.speedPanel, 'Speed') + nb.AddPage(self.speedPanel, _("Speed")) self.termPanel = wx.Panel(nb) sizer = wx.GridBagSizer(2, 2) @@ -273,36 +308,7 @@ class printWindow(wx.Frame): sizer.AddGrowableCol(0) sizer.AddGrowableRow(0) - nb.AddPage(self.termPanel, 'Term') - - if self.cam != None: - self.camPage = wx.Panel(nb) - sizer = wx.GridBagSizer(2, 2) - self.camPage.SetSizer(sizer) - - self.timelapsEnable = wx.CheckBox(self.camPage, -1, 'Enable timelaps movie recording') - sizer.Add(self.timelapsEnable, pos=(0, 0), span=(1, 2), flag=wx.EXPAND) - - pages = self.cam.propertyPages() - self.cam.buttons = [self.timelapsEnable] - for page in pages: - button = wx.Button(self.camPage, -1, page) - button.index = pages.index(page) - sizer.Add(button, pos=(1, pages.index(page))) - button.Bind(wx.EVT_BUTTON, self.OnPropertyPageButton) - self.cam.buttons.append(button) - - self.campreviewEnable = wx.CheckBox(self.camPage, -1, 'Show preview') - sizer.Add(self.campreviewEnable, pos=(2, 0), span=(1, 2), flag=wx.EXPAND) - - self.camPreview = wx.Panel(self.camPage) - sizer.Add(self.camPreview, pos=(3, 0), span=(1, 2), flag=wx.EXPAND) - - nb.AddPage(self.camPage, 'Camera') - self.camPreview.timer = wx.Timer(self) - self.Bind(wx.EVT_TIMER, self.OnCameraTimer, self.camPreview.timer) - self.camPreview.timer.Start(500) - self.camPreview.Bind(wx.EVT_ERASE_BACKGROUND, self.OnCameraEraseBackground) + nb.AddPage(self.termPanel, _("Term")) self.sizer.AddGrowableRow(6) self.sizer.AddGrowableCol(3) @@ -315,6 +321,7 @@ class printWindow(wx.Frame): self.cancelButton.Bind(wx.EVT_BUTTON, self.OnCancel) self.machineLogButton.Bind(wx.EVT_BUTTON, self.OnMachineLog) + self.Bind(wx.EVT_BUTTON, lambda e: (self.temperatureSelect.SetValue(int(profile.getProfileSettingFloat('print_temperature'))), self.machineCom.sendCommand("M104 S%d" % (int(profile.getProfileSettingFloat('print_temperature'))))), self.temperatureHeatUp) self.Bind(wx.EVT_SPINCTRL, self.OnTempChange, self.temperatureSelect) self.Bind(wx.EVT_SPINCTRL, self.OnBedTempChange, self.bedTemperatureSelect) @@ -333,12 +340,61 @@ class printWindow(wx.Frame): self.UpdateButtonStates() - #self.UpdateProgress() + #self.UpdateProgress() + self._thread = threading.Thread(target=self._stdinMonitor) + self._thread.daemon = True + self._thread.start() + + if webcam.hasWebcamSupport(): + #Need to call the camera class on the GUI thread, or else it won't work. Shame as it hangs the GUI for about 2 seconds. + wx.CallAfter(self._webcamCheck) + + def _stdinMonitor(self): + while True: + line = sys.stdin.readline().rstrip() + if line.startswith('LOAD:'): + if not self.LoadGCodeFile(line[5:]): + print 'LOADFAILED\n' + + def _webcamCheck(self): + self.cam = webcam.webcam() + if self.cam.hasCamera(): + self.camPage = wx.Panel(self.tabs) + sizer = wx.GridBagSizer(2, 2) + self.camPage.SetSizer(sizer) + + self.timelapsEnable = wx.CheckBox(self.camPage, -1, _("Enable timelapse movie recording")) + self.timelapsSavePath = wx.TextCtrl(self.camPage, -1, os.path.expanduser('~/timelaps_' + datetime.datetime.now().strftime('%Y-%m-%d_%H-%M') + '.mpg')) + sizer.Add(self.timelapsEnable, pos=(0, 0), span=(1, 2), flag=wx.EXPAND) + sizer.Add(self.timelapsSavePath, pos=(1, 0), span=(1, 2), flag=wx.EXPAND) + + pages = self.cam.propertyPages() + self.cam.buttons = [self.timelapsEnable, self.timelapsSavePath] + for page in pages: + button = wx.Button(self.camPage, -1, page) + button.index = pages.index(page) + sizer.Add(button, pos=(2, pages.index(page))) + button.Bind(wx.EVT_BUTTON, self.OnPropertyPageButton) + self.cam.buttons.append(button) + + self.campreviewEnable = wx.CheckBox(self.camPage, -1, _("Show preview")) + sizer.Add(self.campreviewEnable, pos=(3, 0), span=(1, 2), flag=wx.EXPAND) + + self.camPreview = wx.Panel(self.camPage) + sizer.Add(self.camPreview, pos=(4, 0), span=(1, 2), flag=wx.EXPAND) + + self.tabs.AddPage(self.camPage, _("Camera")) + self.camPreview.timer = wx.Timer(self) + self.Bind(wx.EVT_TIMER, self.OnCameraTimer, self.camPreview.timer) + self.camPreview.timer.Start(500) + self.camPreview.Bind(wx.EVT_ERASE_BACKGROUND, self.OnCameraEraseBackground) + else: + self.cam = None def OnCameraTimer(self, e): if not self.campreviewEnable.GetValue(): return - if self.machineCom != None and self.machineCom.isPrinting(): + if self.machineCom is not None and self.machineCom.isPrinting(): return self.cam.takeNewImage() self.camPreview.Refresh() @@ -350,7 +406,7 @@ class printWindow(wx.Frame): rect = self.GetUpdateRegion().GetBox() dc.SetClippingRect(rect) dc.SetBackground(wx.Brush(self.camPreview.GetBackgroundColour(), wx.SOLID)) - if self.cam.getLastImage() != None: + if self.cam.getLastImage() is not None: self.camPreview.SetMinSize((self.cam.getLastImage().GetWidth(), self.cam.getLastImage().GetHeight())) self.camPage.Fit() dc.DrawBitmap(self.cam.getLastImage(), 0, 0) @@ -361,42 +417,42 @@ class printWindow(wx.Frame): self.cam.openPropertyPage(e.GetEventObject().index) def UpdateButtonStates(self): - self.connectButton.Enable(self.machineCom == None or self.machineCom.isClosedOrError()) + self.connectButton.Enable(self.machineCom is None or self.machineCom.isClosedOrError()) #self.loadButton.Enable(self.machineCom == None or not (self.machineCom.isPrinting() or self.machineCom.isPaused())) - self.printButton.Enable(self.machineCom != None and self.machineCom.isOperational() and not ( + self.printButton.Enable(self.machineCom is not None and self.machineCom.isOperational() and not ( + self.machineCom.isPrinting() or self.machineCom.isPaused())) + self.temperatureHeatUp.Enable(self.machineCom is not None and self.machineCom.isOperational() and not ( self.machineCom.isPrinting() or self.machineCom.isPaused())) self.pauseButton.Enable( - self.machineCom != None and (self.machineCom.isPrinting() or self.machineCom.isPaused())) - if self.machineCom != None and self.machineCom.isPaused(): - self.pauseButton.SetLabel('Resume') + self.machineCom is not None and (self.machineCom.isPrinting() or self.machineCom.isPaused())) + if self.machineCom is not None and self.machineCom.isPaused(): + self.pauseButton.SetLabel(_("Resume")) else: - self.pauseButton.SetLabel('Pause') + self.pauseButton.SetLabel(_("Pause")) self.cancelButton.Enable( - self.machineCom != None and (self.machineCom.isPrinting() or self.machineCom.isPaused())) - self.temperatureSelect.Enable(self.machineCom != None and self.machineCom.isOperational()) - self.bedTemperatureSelect.Enable(self.machineCom != None and self.machineCom.isOperational()) + self.machineCom is not None and (self.machineCom.isPrinting() or self.machineCom.isPaused())) + self.temperatureSelect.Enable(self.machineCom is not None and self.machineCom.isOperational()) + self.bedTemperatureSelect.Enable(self.machineCom is not None and self.machineCom.isOperational()) self.directControlPanel.Enable( - self.machineCom != None and self.machineCom.isOperational() and not self.machineCom.isPrinting()) - self.machineLogButton.Show(self.machineCom != None and self.machineCom.isClosedOrError()) - if self.cam != None: + self.machineCom is not None and self.machineCom.isOperational() and not self.machineCom.isPrinting()) + self.machineLogButton.Show(self.machineCom is not None and self.machineCom.isClosedOrError()) + if self.cam is not None: for button in self.cam.buttons: - button.Enable(self.machineCom == None or not self.machineCom.isPrinting()) + button.Enable(self.machineCom is None or not self.machineCom.isPrinting()) def UpdateProgress(self): status = "" - if self.gcode == None: - status += "Loading gcode...\n" + if self.gcode is None: + status += _("Loading gcode...\n") else: - status += "Filament: %.2fm %.2fg\n" % ( - self.gcode.extrusionAmount / 1000, self.gcode.calculateWeight() * 1000) + status += _("Filament: %(amount).2fm %(weight).2fg\n") % {'amount': self.gcode.extrusionAmount / 1000, 'weight': self.gcode.calculateWeight() * 1000} cost = self.gcode.calculateCost() - if cost != False: - status += "Filament cost: %s\n" % (cost) - status += "Estimated print time: %02d:%02d\n" % ( - int(self.gcode.totalMoveTimeMinute / 60), int(self.gcode.totalMoveTimeMinute % 60)) - if self.machineCom == None or not self.machineCom.isPrinting(): + if cost is not None: + status += _("Filament cost: %s\n") % (cost) + #status += "Estimated print time: %02d:%02d\n" % (int(self.gcode.totalMoveTimeMinute / 60), int(self.gcode.totalMoveTimeMinute % 60)) + if self.machineCom is None or not self.machineCom.isPrinting(): self.progress.SetValue(0) - if self.gcodeList != None: + if self.gcodeList is not None: status += 'Line: -/%d\n' % (len(self.gcodeList)) else: printTime = self.machineCom.getPrintTime() / 60 @@ -406,15 +462,15 @@ class printWindow(wx.Frame): if self.currentZ > 0: status += 'Height: %0.1f\n' % (self.currentZ) status += 'Print time: %02d:%02d\n' % (int(printTime / 60), int(printTime % 60)) - if printTimeLeft == None: + if printTimeLeft is None: status += 'Print time left: Unknown\n' else: status += 'Print time left: %02d:%02d\n' % (int(printTimeLeft / 60), int(printTimeLeft % 60)) self.progress.SetValue(self.machineCom.getPrintPos()) taskbar.setProgress(self, self.machineCom.getPrintPos(), len(self.gcodeList)) - if self.machineCom != None: + if self.machineCom is not None: if self.machineCom.getTemp() > 0: - status += 'Temp: %d\n' % (self.machineCom.getTemp()) + status += 'Temp: %s\n' % (' ,'.join(map(str, self.machineCom.getTemp()))) if self.machineCom.getBedTemp() > 0: status += 'Bed Temp: %d\n' % (self.machineCom.getBedTemp()) self.bedTemperatureLabel.Show(True) @@ -425,7 +481,7 @@ class printWindow(wx.Frame): self.statsText.SetLabel(status.strip()) def OnConnect(self, e): - if self.machineCom != None: + if self.machineCom is not None: self.machineCom.close() self.machineCom = machineCom.MachineCom(callbackObject=self) self.UpdateButtonStates() @@ -435,15 +491,15 @@ class printWindow(wx.Frame): pass def OnPrint(self, e): - if self.machineCom == None or not self.machineCom.isOperational(): + if self.machineCom is None or not self.machineCom.isOperational(): return - if self.gcodeList == None: + if self.gcodeList is None: return if self.machineCom.isPrinting(): return self.currentZ = -1 - if self.cam != None and self.timelapsEnable.GetValue(): - self.cam.startTimelaps(self.filename[: self.filename.rfind('.')] + ".mpg") + if self.cam is not None and self.timelapsEnable.GetValue(): + self.cam.startTimelapse(self.timelapsSavePath.GetValue()) self.machineCom.printGCode(self.gcodeList) self.UpdateButtonStates() @@ -451,6 +507,7 @@ class printWindow(wx.Frame): self.pauseButton.SetLabel('Pause') self.machineCom.cancelPrint() self.machineCom.sendCommand("M84") + self.machineCom.sendCommand("M104 S0") self.UpdateButtonStates() def OnPause(self, e): @@ -465,7 +522,7 @@ class printWindow(wx.Frame): def OnClose(self, e): global printWindowHandle printWindowHandle = None - if self.machineCom != None: + if self.machineCom is not None: self.machineCom.close() self.Destroy() @@ -476,7 +533,7 @@ class printWindow(wx.Frame): self.machineCom.sendCommand("M140 S%d" % (self.bedTemperatureSelect.GetValue())) def OnSpeedChange(self, e): - if self.machineCom == None: + if self.machineCom is None: return self.machineCom.setFeedrateModifier('WALL-OUTER', self.outerWallSpeedSelect.GetValue() / 100.0) self.machineCom.setFeedrateModifier('WALL-INNER', self.innerWallSpeedSelect.GetValue() / 100.0) @@ -484,9 +541,12 @@ class printWindow(wx.Frame): self.machineCom.setFeedrateModifier('SUPPORT', self.supportSpeedSelect.GetValue() / 100.0) def AddTermLog(self, line): + if len(self.termLog.GetValue()) > 10000: + self.termLog.SetValue(self.termLog.GetValue()[-10000:]) + self.termLog.SetInsertionPointEnd() self.termLog.AppendText(unicode(line, 'utf-8', 'replace')) - l = len(self.termLog.GetValue()) - self.termLog.SetCaret(wx.Caret(self.termLog, (l, l))) + #l = self.termLog.GetLastPosition() # if needed (windows? mac?) + #self.termLog.ShowPosition(l) def OnTermEnterLine(self, e): line = self.termInput.GetValue() @@ -501,12 +561,12 @@ class printWindow(wx.Frame): def OnTermKey(self, e): if len(self.termHistory) > 0: if e.GetKeyCode() == wx.WXK_UP: - self.termHistoryIdx = self.termHistoryIdx - 1 + self.termHistoryIdx -= 1 if self.termHistoryIdx < 0: self.termHistoryIdx = len(self.termHistory) - 1 self.termInput.SetValue(self.termHistory[self.termHistoryIdx]) if e.GetKeyCode() == wx.WXK_DOWN: - self.termHistoryIdx = self.termHistoryIdx - 1 + self.termHistoryIdx -= 1 if self.termHistoryIdx >= len(self.termHistory): self.termHistoryIdx = 0 self.termInput.SetValue(self.termHistory[self.termHistoryIdx]) @@ -524,8 +584,8 @@ class printWindow(wx.Frame): self.Layout() def LoadGCodeFile(self, filename): - if self.machineCom != None and self.machineCom.isPrinting(): - return + if self.machineCom is not None and self.machineCom.isPrinting(): + return False #Send an initial M110 to reset the line counter to zero. prevLineType = lineType = 'CUSTOM' gcodeList = ["M110"] @@ -542,7 +602,7 @@ class printWindow(wx.Frame): gcodeList.append(line) prevLineType = lineType gcode = gcodeInterpreter.gcode() - gcode.loadList(gcodeList) + gcode.load(gcodeList) #print "Loaded: %s (%d)" % (filename, len(gcodeList)) self.filename = filename self.gcode = gcode @@ -551,7 +611,7 @@ class printWindow(wx.Frame): wx.CallAfter(self.progress.SetRange, len(gcodeList)) wx.CallAfter(self.UpdateButtonStates) wx.CallAfter(self.UpdateProgress) - wx.CallAfter(self.SetTitle, 'Printing: %s' % (filename)) + return True def sendLine(self, lineNr): if lineNr >= len(self.gcodeList): @@ -576,22 +636,30 @@ class printWindow(wx.Frame): def mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp): self.temperatureGraph.addPoint(temp, targetTemp, bedTemp, bedTargetTemp) -# ToFix, this causes problems with setting the temperature with the keyboard -# if self.temperatureSelect.GetValue() != targetTemp: -# wx.CallAfter(self.temperatureSelect.SetValue, targetTemp) -# if self.bedTemperatureSelect.GetValue() != bedTargetTemp: -# wx.CallAfter(self.bedTemperatureSelect.SetValue, bedTargetTemp) + wx.CallAfter(self._mcTempUpdate, temp, bedTemp, targetTemp, bedTargetTemp) + + def _mcTempUpdate(self, temp, bedTemp, targetTemp, bedTargetTemp): + if self.temperatureSelect.GetValue() != targetTemp[0] and wx.Window.FindFocus() != self.temperatureSelect: + self.temperatureSelect.SetValue(targetTemp[0]) + if self.bedTemperatureSelect.GetValue() != bedTargetTemp and wx.Window.FindFocus() != self.bedTemperatureSelect: + self.bedTemperatureSelect.SetValue(bedTargetTemp) def mcStateChange(self, state): - if self.machineCom != None: - if state == self.machineCom.STATE_OPERATIONAL and self.cam != None: - self.cam.endTimelaps() + if self.machineCom is not None: + if state == self.machineCom.STATE_OPERATIONAL and self.cam is not None: + self.cam.endTimelapse() if state == self.machineCom.STATE_OPERATIONAL: taskbar.setBusy(self, False) if self.machineCom.isClosedOrError(): taskbar.setBusy(self, False) if self.machineCom.isPaused(): taskbar.setPause(self, True) + if self.machineCom.isClosedOrError(): + print 'STATE:CLOSED' + elif self.machineCom.isPrinting(): + print 'STATE:PRINTING' + else: + print 'STATE:IDLE' wx.CallAfter(self.UpdateButtonStates) wx.CallAfter(self.UpdateProgress) @@ -603,7 +671,8 @@ class printWindow(wx.Frame): def mcZChange(self, newZ): self.currentZ = newZ - if self.cam != None: + print 'Z:%f' % newZ + if self.cam is not None: wx.CallAfter(self.cam.takeNewImage) wx.CallAfter(self.camPreview.Refresh) @@ -619,14 +688,14 @@ class temperatureGraph(wx.Panel): self.lastDraw = time.time() - 1.0 self.points = [] self.backBuffer = None - self.addPoint(0, 0, 0, 0) + self.addPoint([0]*16, [0]*16, 0, 0) self.SetMinSize((320, 200)) def OnEraseBackground(self, e): pass def OnSize(self, e): - if self.backBuffer == None or self.GetSize() != self.backBuffer.GetSize(): + if self.backBuffer is None or self.GetSize() != self.backBuffer.GetSize(): self.backBuffer = wx.EmptyBitmap(*self.GetSizeTuple()) self.UpdateDrawing(True) @@ -653,17 +722,18 @@ class temperatureGraph(wx.Panel): #Draw the background up to the current temperatures. x0 = 0 - t0 = 0 + t0 = [0] * len(self.points[0][0]) bt0 = 0 tSP0 = 0 btSP0 = 0 for temp, tempSP, bedTemp, bedTempSP, t in self.points: x1 = int(w - (now - t)) for x in xrange(x0, x1 + 1): - t = float(x - x0) / float(x1 - x0 + 1) * (temp - t0) + t0 + for n in xrange(0, len(temp)): + t = float(x - x0) / float(x1 - x0 + 1) * (temp[n] - t0[n]) + t0[n] + dc.SetPen(tempPenBG) + dc.DrawLine(x, h, x, h - (t * h / 300)) bt = float(x - x0) / float(x1 - x0 + 1) * (bedTemp - bt0) + bt0 - dc.SetPen(tempPenBG) - dc.DrawLine(x, h, x, h - (t * h / 300)) dc.SetPen(bedTempPenBG) dc.DrawLine(x, h, x, h - (bt * h / 300)) t0 = temp @@ -687,23 +757,24 @@ class temperatureGraph(wx.Panel): #Draw the main lines x0 = 0 - t0 = 0 + t0 = [0] * len(self.points[0][0]) bt0 = 0 - tSP0 = 0 + tSP0 = [0] * len(self.points[0][0]) btSP0 = 0 for temp, tempSP, bedTemp, bedTempSP, t in self.points: x1 = int(w - (now - t)) for x in xrange(x0, x1 + 1): - t = float(x - x0) / float(x1 - x0 + 1) * (temp - t0) + t0 + for n in xrange(0, len(temp)): + t = float(x - x0) / float(x1 - x0 + 1) * (temp[n] - t0[n]) + t0[n] + tSP = float(x - x0) / float(x1 - x0 + 1) * (tempSP[n] - tSP0[n]) + tSP0[n] + dc.SetPen(tempSPPen) + dc.DrawPoint(x, h - (tSP * h / 300)) + dc.SetPen(tempPen) + dc.DrawPoint(x, h - (t * h / 300)) bt = float(x - x0) / float(x1 - x0 + 1) * (bedTemp - bt0) + bt0 - tSP = float(x - x0) / float(x1 - x0 + 1) * (tempSP - tSP0) + tSP0 btSP = float(x - x0) / float(x1 - x0 + 1) * (bedTempSP - btSP0) + btSP0 - dc.SetPen(tempSPPen) - dc.DrawPoint(x, h - (tSP * h / 300)) dc.SetPen(bedTempSPPen) dc.DrawPoint(x, h - (btSP * h / 300)) - dc.SetPen(tempPen) - dc.DrawPoint(x, h - (t * h / 300)) dc.SetPen(bedTempPen) dc.DrawPoint(x, h - (bt * h / 300)) t0 = temp @@ -720,11 +791,11 @@ class temperatureGraph(wx.Panel): self.points.pop(0) def addPoint(self, temp, tempSP, bedTemp, bedTempSP): - if bedTemp == None: + if bedTemp is None: bedTemp = 0 - if bedTempSP == None: + if bedTempSP is None: bedTempSP = 0 - self.points.append((temp, tempSP, bedTemp, bedTempSP, time.time())) + self.points.append((temp[:], tempSP[:], bedTemp, bedTempSP, time.time())) wx.CallAfter(self.UpdateDrawing)