class GCodeDlg(wx.Frame): def __init__(self, parent, server, gcode, filenm, pname, settings, images, cbexit): wx.Frame.__init__(self, None, wx.ID_ANY, self.formatTitle(pname, filenm)) self.SetBackgroundColour("white") self.Bind(wx.EVT_CLOSE, self.onClose) self.parent = parent self.server = server self.gcode = gcode self.filenm = filenm self.pname = pname self.settings = settings self.images = images self.exitDlg = cbexit self.nExtr = self.parent.nExtr self.layerCount = 0 if self.gcode: self.sTotalTime = " / " + formatElapsed(self.gcode.getPrintTime()) self.filament = self.gcode.getFilament() else: self.sTotalTime = "" self.filament = [[0.0, 0.0]] self.printPosition = 0 self.followPrint = True self.lx = 0 lbFont = wx.Font(10, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD) self.gcf = GcFrame(self, self.pname, self.gcode, self.settings) self.stHeight = wx.StaticText(self, wx.ID_ANY, "") self.stHeight.SetFont(lbFont) self.stTime = wx.StaticText(self, wx.ID_ANY, "") self.stTime.SetFont(lbFont) self.stFilament = wx.StaticText(self, wx.ID_ANY, "") self.stFilament.SetFont(lbFont) self.slLayer = wx.Slider(self, wx.ID_ANY, 1, 1, 10, style=wx.SL_VERTICAL+wx.SL_LABELS+wx.SL_INVERSE) self.Bind(wx.EVT_SLIDER, self.onSlLayer, self.slLayer) self.bUp = wx.BitmapButton(self, wx.ID_ANY, self.images.pngUp, size=BTNDIM, style=wx.NO_BORDER) self.bUp.SetBackgroundColour("white") self.Bind(wx.EVT_BUTTON, self.onBUp, self.bUp) self.bDown = wx.BitmapButton(self, wx.ID_ANY, self.images.pngDown, size=BTNDIM, style=wx.NO_BORDER) self.bDown.SetBackgroundColour("white") self.Bind(wx.EVT_BUTTON, self.onBDown, self.bDown) self.setSliderRange() self.cbSync = wx.CheckBox(self, wx.ID_ANY, "Sync with print") self.cbSync.SetValue(True) self.Bind(wx.EVT_CHECKBOX, self.onCbSync, self.cbSync) self.cbPrintedOnly = wx.CheckBox(self, wx.ID_ANY, "Only show printed") self.cbPrintedOnly.SetValue(self.settings.getSetting("showprintedonly", self.pname, "False")) self.Bind(wx.EVT_CHECKBOX, self.onCbShowPrintedOnly, self.cbPrintedOnly) self.cbShowPrev = wx.CheckBox(self, wx.ID_ANY, "Show previous layer") self.cbShowPrev.SetValue(self.settings.getSetting("showprevious", self.pname, "False")) self.Bind(wx.EVT_CHECKBOX, self.onCbShowPrev, self.cbShowPrev) self.cbShowMoves = wx.CheckBox(self, wx.ID_ANY, "Show moves") self.cbShowMoves.SetValue(self.settings.getSetting("showmoves", self.pname, "False")) self.Bind(wx.EVT_CHECKBOX, self.onCbShowMoves, self.cbShowMoves) self.cbShowRetr = wx.CheckBox(self, wx.ID_ANY, "Show retractions") self.cbShowRetr.SetValue(self.settings.getSetting("showretractions", self.pname, "False")) self.Bind(wx.EVT_CHECKBOX, self.onCbShowRetr, self.cbShowRetr) self.cbShowRevRetr = wx.CheckBox(self, wx.ID_ANY, "Show reverse retractions") self.cbShowRevRetr.SetValue(self.settings.getSetting("showrevretractions", self.pname, "False")) self.Bind(wx.EVT_CHECKBOX, self.onCbShowRevRetr, self.cbShowRevRetr) sznavgc = wx.BoxSizer(wx.VERTICAL) sznavgc.Add(self.bUp, 0, wx.LEFT, 12 if os.name == 'posix' else 25) sznavgc.Add(self.slLayer, 1, wx.GROW) sznavgc.Add(self.bDown, 0, wx.LEFT, 12 if os.name == 'posix' else 25) szgcf = wx.BoxSizer(wx.VERTICAL) szgcf.Add(self.gcf) szgcf.AddSpacer(5) szgcf.Add(self.stHeight, 0, wx.ALIGN_CENTER) szgcf.AddSpacer(5) szgcf.Add(self.stTime, 0, wx.ALIGN_CENTER) szgcf.AddSpacer(5) szgcf.Add(self.stFilament, 0, wx.ALIGN_CENTER) szgc = wx.BoxSizer(wx.HORIZONTAL) szgc.AddSpacer(15) szgc.Add(szgcf) if os.name == 'posix': szgc.AddSpacer(10) szgc.Add(sznavgc, 1, wx.GROW) szgc.AddSpacer(15) szopt1 = wx.BoxSizer(wx.VERTICAL) szopt1.Add(self.cbSync, 1, wx.EXPAND) szopt1.Add(self.cbPrintedOnly, 1, wx.EXPAND) szopt2 = wx.BoxSizer(wx.VERTICAL) szopt2.Add(self.cbShowPrev, 1, wx.EXPAND) szopt2.Add(self.cbShowMoves, 1, wx.EXPAND) szopt3 = wx.BoxSizer(wx.VERTICAL) szopt3.Add(self.cbShowRetr, 1, wx.EXPAND) szopt3.Add(self.cbShowRevRetr, 1, wx.EXPAND) szoptions = wx.BoxSizer(wx.HORIZONTAL) szoptions.AddSpacer(20) szoptions.Add(szopt1, 1, wx.EXPAND) szoptions.AddSpacer(5) szoptions.Add(szopt2, 1, wx.EXPAND) szoptions.AddSpacer(5) szoptions.Add(szopt3, 1, wx.EXPAND) szoptions.AddSpacer(10) sz = wx.BoxSizer(wx.VERTICAL) sz.AddSpacer(10) sz.Add(szgc) sz.AddSpacer(5) sz.Add(szoptions) sz.AddSpacer(10) self.showLayerInfo() self.SetSizer(sz) self.Fit() self.Layout() @staticmethod def formatTitle(pname, filenm): if filenm is None: return "%s - GCode Monitor - (no file loaded)" % pname else: return "%s - GCode monitor - %s" % (pname, filenm) def reloadGCode(self, gcode, filenm): self.filenm = filenm self.SetTitle(self.formatTitle(self.pname, filenm)) self.gcode = gcode if self.gcode: self.sTotalTime = " / " + formatElapsed(self.gcode.getPrintTime()) self.filament = self.gcode.getFilament() else: self.sTotalTime = "" self.filament = 0.0 self.setSliderRange() # send new gcode to gcf self.printPosition = 0 self.gcf.loadGCode(gcode) self.showLayerInfo() def setSliderRange(self): n = self.gcode.layerCount() self.slLayer.SetRange(1, 10 if n == 0 else n) self.slLayer.SetValue(1) self.slLayer.Enable(n != 0) self.bUp.Enable(n != 0) self.bDown.Enable(n != 0) self.layerCount = n def setPrintPosition(self, pos): if pos is None: return False, None, None self.printPosition = 0 if pos is None else pos self.gcf.setPrintPosition(self.printPosition) pLayer, lpct = self.gcode.findLayerByOffset(self.printPosition) cLayer = self.gcf.getCurrentLayerNum() if not self.followPrint: return cLayer != pLayer, pLayer, lpct if cLayer != pLayer: self.gcf.setLayer(pLayer) self.slLayer.SetValue(pLayer+1) self.showLayerInfo() return True, pLayer, lpct return False, pLayer, lpct def showLayerInfo(self): l = self.gcf.getCurrentLayer() if l is None: lblHt = "" lblTime = "" lblFilament = "" else: lx = self.gcf.getCurrentLayerNum() lblHt, lblTime, lblFilament = self.formatLayerInfo(l, lx) self.stHeight.SetLabel(lblHt) self.stTime.SetLabel(lblTime) self.stFilament.SetLabel(lblFilament) def formatLayerInfo(self, l, lx): sHt = "Height: {:.2f} Layer: {:d} / {:d}".format(l.getHeight(), lx+1, self.layerCount) sTm = " Print time: {:s}{:s}".format(formatElapsed(l.getLayerTime()), self.sTotalTime) o = l.getOffsets() if self.printPosition < o[0]: lyrs = self.gcode.getLayersBetweenOffsets(self.printPosition, o[0]) untilTime = 0.0 for ly in lyrs: untilTime += ly.getLayerTime() sTm += " ({:s} until)".format(formatElapsed(untilTime)) sFi = " Filament: " lf = l.getFilament() for i in range(self.nExtr): if i > 0: sFi += " / " if self.nExtr > 1: if i > 0: sFi += " - " sFi += "{:d}: ".format(i) sFi += "{:.2f}mm ({:.2f}cm3) / {:.2f}mm".format(lf[i][0], lf[i][1], self.filament[i][0]) return sHt, sTm, sFi def onSlLayer(self, _): self.followPrintOff() v = self.slLayer.GetValue()-1 self.gcf.setLayer(v) self.showLayerInfo() def onBUp(self, _): v = self.slLayer.GetValue() if v < self.gcode.layerCount(): self.followPrintOff() v += 1 self.slLayer.SetValue(v) self.gcf.setLayer(v-1) self.showLayerInfo() def onBDown(self, _): v = self.slLayer.GetValue() if v > 1: self.followPrintOff() v -= 1 self.slLayer.SetValue(v) self.gcf.setLayer(v-1) self.showLayerInfo() def followPrintOff(self): if self.followPrint: self.cbSync.SetValue(False) self.followPrint = False self.gcf.setFollowPrint(False) def onCbSync(self, _): self.followPrint = self.cbSync.GetValue() self.gcf.setFollowPrint(self.followPrint) def onCbShowPrintedOnly(self, _): v = self.cbPrintedOnly.GetValue() self.settings.setSetting("showprintedonly", str(v), self.pname) self.gcf.setShowPrintedOnly(v) def onCbShowPrev(self, _): v = self.cbShowPrev.GetValue() self.settings.setSetting("showprevious", str(v), self.pname) self.gcf.setShowPrevious(v) def onCbShowMoves(self, _): v = self.cbShowMoves.GetValue() self.settings.setSetting("showmoves", str(v), self.pname) self.gcf.setShowMoves(v) def onCbShowRetr(self, _): v = self.cbShowRetr.GetValue() self.settings.setSetting("showretractions", str(v), self.pname) self.gcf.setShowRetractions(v) def onCbShowRevRetr(self, _): v = self.cbShowRevRetr.GetValue() self.settings.setSetting("showrevretractions", str(v), self.pname) self.gcf.setShowRevRetractions(v) def onClose(self, _): self.exitDlg()
class GEditDlg(wx.Frame): def __init__(self, parent): self.parent = parent self.history = parent.history wx.Frame.__init__(self, None, wx.ID_ANY, TITLE_PREFIX, size=(600, 600)) self.Show() ico = wx.Icon(os.path.join(cmdFolder, "images", "geditico.png"), wx.BITMAP_TYPE_PNG) self.SetIcon(ico) self.Bind(wx.EVT_CLOSE, self.onClose) self.settings = Settings(cmdFolder) self.propDlg = None self.legend = None self.log = self.parent.log self.images = Images(os.path.join(cmdFolder, "images")) self.shiftX = 0 self.shiftY = 0 self.modified = False self.filename = None self.importFileName = None self.okToImport = False self.gObj = self.loadGCode(self.filename) if self.gObj is not None: self.updateTitle() self.gcFrame = GcFrame(self, self.gObj, self.settings) self.stLayerText = wx.StaticText(self, wx.ID_ANY, "Layer Height: 0.00") ht = self.gcFrame.GetSize().Get()[1] - 2*BUTTONDIM[1] - 20 if self.gObj is None: lmax = 1 else: lmax = self.gObj.layerCount()-1 self.slLayers = wx.Slider( self, wx.ID_ANY, 0, 0, 1000, size=(-1, ht), style=wx.SL_VERTICAL | wx.SL_AUTOTICKS | wx.SL_LABELS | wx.SL_INVERSE) self.Bind(wx.EVT_SCROLL, self.onLayerScroll, self.slLayers) if self.gObj is None: self.slLayers.Enable(False) self.lcGCode = GcodeListCtrl(self, self.gcode, self.images) self.lcGCode.setLineNumbers(self.settings.uselinenbrs) self.currentLayer = 0 self.setLayerText() if self.gObj is not None: self.lcGCode.setLayerBounds(self.gObj.getGCodeLines(0)) self.bShift = wx.BitmapButton(self, wx.ID_ANY, self.images.pngShift, size=BUTTONDIM) self.bShift.SetToolTip("Move model in x/y direction") self.Bind(wx.EVT_BUTTON, self.doShiftModel, self.bShift) self.bShift.Enable(False) self.bModTemp = wx.BitmapButton(self, wx.ID_ANY, self.images.pngModtemp, size=BUTTONDIM) self.bModTemp.SetToolTip("Modify Temperatures") self.Bind(wx.EVT_BUTTON, self.onModTemps, self.bModTemp) self.bModTemp.Enable(False) self.bModSpeed = wx.BitmapButton(self, wx.ID_ANY, self.images.pngModspeed, size=BUTTONDIM) self.bModSpeed.SetToolTip("Modify Speed") self.Bind(wx.EVT_BUTTON, self.onModSpeed, self.bModSpeed) self.bModSpeed.Enable(False) self.bFilChange = wx.BitmapButton(self, wx.ID_ANY, self.images.pngFilchange, size=BUTTONDIM) self.bFilChange.SetToolTip("Insert G Code to assist with changing filament") self.Bind(wx.EVT_BUTTON, self.onFilChange, self.bFilChange) self.bFilChange.Enable(False) self.bEdit = wx.BitmapButton(self, wx.ID_ANY, self.images.pngEdit, size=BUTTONDIM) self.bEdit.SetToolTip("Free edit G Code") self.Bind(wx.EVT_BUTTON, self.onEditGCode, self.bEdit) self.bEdit.Enable(False) self.bUp = wx.BitmapButton(self, wx.ID_ANY, self.images.pngUp, size=BUTTONDIM) self.bUp.SetToolTip("Move up one layer") self.Bind(wx.EVT_BUTTON, self.onUp, self.bUp) self.bUp.Enable(False) self.bDown = wx.BitmapButton(self, wx.ID_ANY, self.images.pngDown, size=BUTTONDIM) self.bDown.SetToolTip("Move down one layer") self.Bind(wx.EVT_BUTTON, self.onDown, self.bDown) self.bDown.Enable(False) self.bInfo = wx.BitmapButton(self, wx.ID_ANY, self.images.pngInfo, size=BUTTONDIM) self.bInfo.SetToolTip("Information") self.Bind(wx.EVT_BUTTON, self.onInfo, self.bInfo) self.bInfo.Enable(False) self.bLegend = wx.BitmapButton(self, wx.ID_ANY, self.images.pngLegend, size=BUTTONDIM) self.bLegend.SetToolTip("Display a color legend") self.Bind(wx.EVT_BUTTON, self.onLegend, self.bLegend) self.bLegend.Enable(True) self.bSaveLayers = wx.BitmapButton(self, wx.ID_ANY, self.images.pngSavelayers, size=BUTTONDIM) self.bSaveLayers.SetToolTip("Save specific layers to a file") self.Bind(wx.EVT_BUTTON, self.onSaveLayers, self.bSaveLayers) self.bSaveLayers.Enable(False) self.bOpen = wx.BitmapButton(self, wx.ID_ANY, self.images.pngFileopen, size=BUTTONDIM) self.bOpen.SetToolTip("Open a G Code file") self.Bind(wx.EVT_BUTTON, self.onOpen, self.bOpen) self.bImport = wx.BitmapButton(self, wx.ID_ANY, self.images.pngImport, size=BUTTONDIM) self.bImport.SetToolTip("Import the current toolbox G Code file") self.Bind(wx.EVT_BUTTON, self.onImport, self.bImport) self.bImport.Enable(False) self.bImportQ = wx.BitmapButton(self, wx.ID_ANY, self.images.pngNext, size=BUTTONDIM) self.bImportQ.SetToolTip("Import the next G Code file from the queue") self.Bind(wx.EVT_BUTTON, self.onImportFromQueue, self.bImportQ) self.bImportQ.Enable(False) self.bExport = wx.BitmapButton(self, wx.ID_ANY, self.images.pngExport, size=BUTTONDIM) self.bExport.SetToolTip("Export the current toolbox G Code file") self.Bind(wx.EVT_CHECKBOX, self.onExport, self.bExport) self.bExport.Enable(not self.settings.autoexport) self.cbExport = wx.CheckBox(self, wx.ID_ANY, "Auto-export") self.cbExport.SetToolTip("Auto-export the current G Code file when saving") self.Bind(wx.EVT_CHECKBOX, self.onCbExport, self.cbExport) self.cbEnqueue = wx.CheckBox(self, wx.ID_ANY, "Add to queue") self.cbEnqueue.SetToolTip("Enqueue the current G Code file on the end of the G Code queue when exporting") self.Bind(wx.EVT_BUTTON, self.onEnqueue, self.cbEnqueue) self.bSave = wx.BitmapButton(self, wx.ID_ANY, self.images.pngFilesave, size=BUTTONDIM) self.bSave.SetToolTip("Save G Code to the current file") self.Bind(wx.EVT_BUTTON, self.onSave, self.bSave) self.bSave.Enable(False) self.bSaveAs = wx.BitmapButton(self, wx.ID_ANY, self.images.pngFilesaveas, size=BUTTONDIM) self.bSaveAs.SetToolTip("Save G Code to a different file") self.Bind(wx.EVT_BUTTON, self.onSaveAs, self.bSaveAs) self.bSaveAs.Enable(False) self.cbShowMoves = wx.CheckBox(self, wx.ID_ANY, "Show Moves") self.cbShowMoves.SetToolTip("Show/Hide non-extrusion moves") self.cbShowMoves.SetValue(self.settings.showmoves) self.Bind(wx.EVT_CHECKBOX, self.onCbShowMoves, self.cbShowMoves) self.cbShowPrevious = wx.CheckBox(self, wx.ID_ANY, "Show Previous Layer") self.cbShowPrevious.SetToolTip("Show/Hide the previous layer") self.cbShowPrevious.SetValue(self.settings.showprevious) self.Bind(wx.EVT_CHECKBOX, self.onCbShowPrevious, self.cbShowPrevious) self.cbShowRetractions = wx.CheckBox(self, wx.ID_ANY, "Show Retractions") self.cbShowRetractions.SetToolTip("Show/Hide retractions") self.cbShowRetractions.SetValue(self.settings.showretractions) self.Bind(wx.EVT_CHECKBOX, self.onCbShowRetractions, self.cbShowRetractions) self.cbShowRevRetractions = wx.CheckBox(self, wx.ID_ANY, "Show Reverse Retractions") self.cbShowRevRetractions.SetToolTip("Show/Hide reverse retractions") self.cbShowRevRetractions.SetValue(self.settings.showrevretractions) self.Bind(wx.EVT_CHECKBOX, self.onCbShowRevRetractions, self.cbShowRevRetractions) self.cmbTool = wx.ComboBox(self, wx.ID_ANY, "None", choices = ["None", "0", "1", "2", "3"], style = wx.CB_DROPDOWN + wx.CB_READONLY) self.cmbTool.SetToolTip("Choose which tool, if any, is highlighted in the display") self.Bind(wx.EVT_COMBOBOX, self.onCmbTool, self.cmbTool) self.cbLineNbrs = wx.CheckBox(self, wx.ID_ANY, "Line Numbers") self.cbLineNbrs.SetToolTip("Use G Code line numbers") self.cbLineNbrs.SetValue(self.settings.uselinenbrs) self.Bind(wx.EVT_CHECKBOX, self.onCbLineNbrs, self.cbLineNbrs) self.bBracketStart = wx.BitmapButton(self, wx.ID_ANY, self.images.pngBracketopen, size=BUTTONDIM) self.bBracketStart.SetToolTip("Mark the beginning of a block of G code") self.Bind(wx.EVT_BUTTON, self.onBracketStart, self.bBracketStart) self.bBracketStart.Enable(False) self.bBracketEnd = wx.BitmapButton(self, wx.ID_ANY, self.images.pngBracketclose, size=BUTTONDIM) self.bBracketEnd.SetToolTip("Mark the end of a block of G code") self.Bind(wx.EVT_BUTTON, self.onBracketEnd, self.bBracketEnd) self.bBracketEnd.Enable(False) self.bBracketDel = wx.BitmapButton(self, wx.ID_ANY, self.images.pngBracketdel, size=BUTTONDIM) self.bBracketDel.SetToolTip("Delete the marked block of G code") self.Bind(wx.EVT_BUTTON, self.onBracketDel, self.bBracketDel) self.bBracketDel.Enable(False) btnszr = wx.BoxSizer(wx.HORIZONTAL) btnszr.AddSpacer(20) btnszr.Add(self.bShift) btnszr.AddSpacer(10) btnszr.Add(self.bModTemp) btnszr.AddSpacer(10) btnszr.Add(self.bModSpeed) btnszr.AddSpacer(10) btnszr.Add(self.bFilChange) btnszr.AddSpacer(10) btnszr.Add(self.bEdit) btnszr.AddSpacer(10) btnszr.Add(self.bInfo) btnszr.AddSpacer(10) btnszr.Add(self.bLegend) btnszr.AddSpacer(50) btnszr.Add(self.bSaveLayers) btnszr.AddSpacer(10) btnszr.Add(self.bOpen) btnszr.AddSpacer(10) btnszr.Add(self.bImport) btnszr.AddSpacer(10) btnszr.Add(self.bImportQ) btnszr.AddSpacer(10) btnszr.Add(self.bExport) btnszr.AddSpacer(5) optszr = wx.BoxSizer(wx.VERTICAL) optszr.AddSpacer(1) optszr.Add(self.cbExport) optszr.AddSpacer(1) optszr.Add(self.cbEnqueue) btnszr.Add(optszr) btnszr.AddSpacer(10) btnszr.Add(self.bSave) btnszr.AddSpacer(10) btnszr.Add(self.bSaveAs) btnszr.AddSpacer(10) hszr = wx.BoxSizer(wx.HORIZONTAL) hszr.AddSpacer(20) vszr = wx.BoxSizer(wx.VERTICAL) vszr.Add(self.gcFrame) vszr.Add(self.stLayerText, 1, wx.ALIGN_CENTER_HORIZONTAL, 1) vszr.AddSpacer(10) opthszr = wx.BoxSizer(wx.HORIZONTAL) optszr = wx.BoxSizer(wx.VERTICAL) optszr.AddSpacer(1) optszr.Add(self.cbShowMoves) optszr.AddSpacer(1) optszr.Add(self.cbShowPrevious) opthszr.Add(optszr) opthszr.AddSpacer(10) optszr = wx.BoxSizer(wx.VERTICAL) optszr.AddSpacer(1) optszr.Add(self.cbShowRetractions) optszr.AddSpacer(1) optszr.Add(self.cbShowRevRetractions) opthszr.Add(optszr) opthszr.AddSpacer(10) optszr = wx.BoxSizer(wx.VERTICAL) optszr.AddSpacer(1) hsz = wx.BoxSizer(wx.HORIZONTAL) hsz.Add(wx.StaticText(self, wx.ID_ANY, "Tool to Hi-light: "), 1, wx.TOP, 5) hsz.AddSpacer(5) hsz.Add(self.cmbTool) optszr.Add(hsz) opthszr.Add(optszr) vszr.Add(opthszr) hszr.Add(vszr) szNav = wx.BoxSizer(wx.VERTICAL) szNav.Add(self.bUp, 1, wx.ALIGN_CENTER_HORIZONTAL, 1) szNav.AddSpacer(10) szNav.Add(self.slLayers) szNav.AddSpacer(10) szNav.Add(self.bDown, 1, wx.ALIGN_CENTER_HORIZONTAL, 1) hszr.Add(szNav) hszr.AddSpacer(20) listszr = wx.BoxSizer(wx.VERTICAL) listszr.Add(self.lcGCode) listszr.AddSpacer(10) listszr.Add(self.cbLineNbrs, 1, wx.ALIGN_CENTER_HORIZONTAL, 1) brksz = wx.BoxSizer(wx.HORIZONTAL) brksz.Add(self.bBracketStart) brksz.AddSpacer(20) brksz.Add(self.bBracketDel) brksz.AddSpacer(20) brksz.Add(self.bBracketEnd) listszr.AddSpacer(10) listszr.Add(brksz, 0, wx.ALIGN_CENTER_HORIZONTAL, 1) hszr.Add(listszr) hszr.AddSpacer(20) vszr = wx.BoxSizer(wx.VERTICAL) vszr.AddSpacer(20) vszr.Add(btnszr) vszr.AddSpacer(10) vszr.Add(hszr) vszr.AddSpacer(20) self.SetSizer(vszr) self.Layout() self.Fit() self.slLayers.SetRange(0, lmax) self.slLayers.SetPageSize(int(lmax/10)) if self.gObj is not None: self.enableButtons() def onLegend(self, evt): if self.legend is None: self.legend = LegendDlg(self) self.legend.Show() else: self.legend.Show() self.legend.Raise() def legendClosed(self): self.legend = None def setImportFile(self, fn): self.importFileName = fn if fn is None: self.bImport.SetToolTip("") self.bImport.Enable(False) else: self.bImport.SetToolTip("Import G Code file (%s)" % fn) self.bImport.Enable(True) def onBracketStart(self, evt): b = self.lcGCode.setBracketStart() self.gcFrame.setBracket(b) self.enableBracketDel(b) def onBracketEnd(self, evt): b = self.lcGCode.setBracketEnd() self.gcFrame.setBracket(b) self.enableBracketDel(b) def enableBracketDel(self, b=None): if b is None: b = self.lcGCode.getBracket() if b[0] is None or b[1] is None: self.bBracketDel.Enable(False) else: self.bBracketDel.Enable(True) def onBracketDel(self, evt): b = self.lcGCode.getBracket() if b[0] is None or b[1] is None: return self.gcode = self.gcode[:b[0]] + self.gcode[b[1]+1:] self.setModified(True) self.gObj = self.buildModel() self.modGcSuffixTemps(self.gObj.getTemps()) l = self.gcFrame.getCurrentLayer() self.gcFrame.loadModel(self.gObj, l, self.gcFrame.getZoom()) lmax = self.gObj.layerCount()-1 self.slLayers.SetRange(0, lmax) self.slLayers.SetPageSize(int(lmax/10)) self.lcGCode.setGCode(self.gcode) self.lcGCode.setLayerBounds(self.gObj.getGCodeLines(l)) self.bBracketDel.Enable(False) self.updateInfoDlg(self.currentLayer) def updateTitle(self): if self.filename is None: self.SetTitle("%s" % TITLE_PREFIX) else: txt = TITLE_PREFIX + " - " if self.modified: txt += "* " txt += self.filename self.SetTitle(txt) def setModified(self, flag=True): self.modified = flag self.updateTitle() def onExport(self, evt): if self.modified: dlg = wx.MessageDialog(self, "You have unsaved changes.\nAre you sure you want to export?", "Confirm Export With Pending Changes", wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) rc = dlg.ShowModal() dlg.Destroy() if rc != wx.ID_YES: return self.parent.exportGcFile(self.filename, True, self.settings.autoenqueue) def onCbExport(self, evt): self.settings.autoexport = evt.IsChecked() self.bExport.Enable(not self.settings.autoexport) def onEnqueue(self, evt): self.settings.autoenqueue = evt.IsChecked() def onImport(self, evt): fn = self.parent.importGcFile() if fn is None: return self.loadGFile(fn) def onImportFromQueue(self, evt): fn = self.parent.importGcFromQueue() if fn is None: return self.loadGFile(fn) def setImportButton(self, msg): if msg is None: self.okToImport = False self.bImportQ.SetToolTip("") self.bImportQ.Enable(False) else: self.okToImport = True self.bImportQ.SetToolTip(msg) self.bImportQ.Enable(self.bOpen.IsEnabled()) def onOpen(self, evt): if self.modified: dlg = wx.MessageDialog(self, "You have unsaved changes.\nAre you sure you want to open a different file?", "Confirm Open With Pending Changes", wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) rc = dlg.ShowModal() dlg.Destroy() if rc != wx.ID_YES: return self.gcodeFileDialog() def onInfo(self, evt): if self.propDlg is not None: return self.propDlg = PropertiesDlg(self, self, None, cb=self.onInfoClose) self.showFileProperties() self.showLayerProperties(self.currentLayer) self.propDlg.Show() def onInfoClose(self): self.propDlg = None def updateInfoDlg(self, lx): if self.propDlg is None: return self.showFileProperties() self.showLayerProperties(lx) def showFileProperties(self): slCfg, filSiz, tempsHE, tempsBed = parseGCSuffix(self.gcode) ftime = time.strftime('%y/%m/%d-%H:%M:%S', time.localtime(os.path.getmtime(self.filename))) if len(self.filename) > 50: self.propDlg.setProperty(PropertyEnum.fileName, os.path.basename(self.filename)) else: self.propDlg.setProperty(PropertyEnum.fileName, self.filename) self.propDlg.setProperty(PropertyEnum.slicerCfg, slCfg) self.propDlg.setProperty(PropertyEnum.filamentSize, filSiz) self.propDlg.setProperty(PropertyEnum.temperatures, "HE:%s BED:%s" % (tempsHE, tempsBed)) self.propDlg.setProperty(PropertyEnum.sliceTime, ftime) self.propDlg.setProperty(PropertyEnum.printEstimate, self.totalTimeStr) def showLayerProperties(self, lx): if self.propDlg is None: return self.propDlg.setProperty(PropertyEnum.layerNum, "%d" % lx) x0, y0, xn, yn = self.gObj.getLayerMinMaxXY(lx) if x0 is None: self.propDlg.setProperty(PropertyEnum.minMaxXY, "") else: self.propDlg.setProperty(PropertyEnum.minMaxXY, "(%.2f, %.2f) - (%.2f, %.2f)" % (x0, y0, xn, yn)) le, prior, after = self.gObj.getLayerFilament(lx) eUsed = self.gObj.getFilament() s = [] for i in range(self.settings.nextruders): s.append("%.2f/%.2f <: %.2f >: %.2f" % (le[i], eUsed[i], prior[i], after[i])) self.propDlg.setProperty(PropertyEnum.filamentUsed, s) f, l = self.gObj.getGCodeLines(lx) if f is None: self.propDlg.setProperty(PropertyEnum.gCodeRange, "") else: self.propDlg.setProperty(PropertyEnum.gCodeRange, "%d - %d" % (f, l)) self.propDlg.setProperty(PropertyEnum.layerPrintTime, self.layerTimeStr[lx]) if lx == 0: self.propDlg.setProperty(PropertyEnum.timeUntil, "") else: t = sum(self.layerTimes[:lx]) self.propDlg.setProperty(PropertyEnum.timeUntil, formatElapsed(t)) def gcodeFileDialog(self): wildcard = "GCode (*.gcode)|*.gcode;*.GCODE|" \ "All files (*.*)|*.*" dlg = wx.FileDialog( self, message="Choose a GCode file", defaultDir=self.settings.lastdirectory, defaultFile="", wildcard=wildcard, style=wx.FD_OPEN) rc = dlg.ShowModal() if rc == wx.ID_OK: path = dlg.GetPath().encode('ascii','ignore') dlg.Destroy() if rc != wx.ID_OK: return self.loadGFile(path) def loadGFile(self, path): self.settings.lastdirectory = os.path.dirname(path) self.gObj = self.loadGCode(path) if self.gObj is None: lmax = 1 self.slLayers.Enable(False) self.bUp.Enable(False) self.bDown.Enable(False) self.filename = None else: lmax = self.gObj.layerCount()-1 self.slLayers.Enable(True) self.bUp.Enable(True) self.bDown.Enable(True) self.filename = path self.updateTitle() self.slLayers.SetRange(0, lmax) self.slLayers.SetPageSize(int(lmax/10)) self.gcFrame.loadModel(self.gObj) self.lcGCode.setGCode(self.gcode) self.currentLayer = 0 self.setLayerText() self.slLayers.SetValue(0) self.updateInfoDlg(0) self.setModified(False) if self.gObj is not None: self.lcGCode.setLayerBounds(self.gObj.getGCodeLines(0)) self.enableButtons() else: self.enableButtons(False) def enableButtons(self, flag=True, openButtons=False): self.bShift.Enable(flag) self.bModTemp.Enable(flag) self.bModSpeed.Enable(flag) self.bEdit.Enable(flag) self.bInfo.Enable(flag) self.bUp.Enable(flag) self.bDown.Enable(flag) self.bSaveLayers.Enable(flag) self.bSave.Enable(flag) self.bSaveAs.Enable(flag) self.bExport.Enable(flag and (not self.settings.autoexport)) self.bFilChange.Enable(flag) self.bBracketStart.Enable(flag) self.bBracketEnd.Enable(flag) self.enableBracketDel() if openButtons: if flag and self.importFileName is not None: self.bImport.Enable(True) else: self.bImport.Enable(False) if flag and self.okToImport: self.bImportQ.Enable(True) else: self.bImportQ.Enable(False) self.bOpen.Enable(flag) def doShiftModel(self, evt): dlg = ShiftModelDlg(self, self.gObj, self.settings.buildarea) dlg.CenterOnScreen() rc = dlg.ShowModal() dlg.Destroy() if rc == wx.ID_OK: self.applyShift() self.setModified() else: self.setShift(0, 0) def setShift(self, sx, sy): self.shiftX = sx self.shiftY = sy self.gcFrame.setShift(sx, sy) def applyShift(self): self.gcode = [self.applyAxisShift(self.applyAxisShift(l, 'y', self.shiftY), 'x', self.shiftX) for l in self.gcode] self.shiftX = 0 self.shiftY = 0 self.gObj = self.buildModel() self.gcFrame.loadModel(self.gObj, self.gcFrame.getCurrentLayer(), self.gcFrame.getZoom()) self.lcGCode.setGCode(self.gcode) self.lcGCode.refreshList() self.updateInfoDlg(self.currentLayer) def applyAxisShift(self, s, axis, shift): if "m117" in s or "M117" in s: return s if axis == 'x': m = reX.match(s) maxv = self.settings.buildarea[0] elif axis == 'y': m = reY.match(s) maxv = self.settings.buildarea[1] elif axis == 'z': m = reZ.match(s) maxv = self.settings.buildarea[1] else: return s if m is None or m.lastindex != 3: return s value = float(m.group(2)) + float(shift) if value < 0: value = 0.0 elif value > maxv: value = float(maxv) return "%s%s%s" % (m.group(1), str(value), m.group(3)) def onModTemps(self, evt): dlg = ModifyTempsDlg(self, self.gObj, self.settings.platemps, self.settings.abstemps) dlg.CenterOnScreen() rc = dlg.ShowModal() if rc == wx.ID_OK: bed, hes = dlg.getResult() dlg.Destroy() if rc != wx.ID_OK: return self.applyTempChange(bed, hes) def applyTempChange(self, bed, hes): self.currentTool = 0 self.gcode = [self.applySingleTempChange(l, bed, hes) for l in self.gcode] self.setModified(True) self.gObj = self.buildModel() self.modGcSuffixTemps(self.gObj.getTemps()) self.gcFrame.loadModel(self.gObj, self.gcFrame.getCurrentLayer(), self.gcFrame.getZoom()) self.lcGCode.setGCode(self.gcode) self.lcGCode.refreshList() self.updateInfoDlg(self.currentLayer) def modGcSuffixTemps(self, nTemps): bstr = "%.1f" % nTemps[0] h = [] nct = 0 for x in nTemps[1]: if x is None: nct += 1 else: if nct != 0: h.extend([None]*nct) nct = 0 h.append("%.1f" % x) hestr = ",".join(h) modifyGCSuffix(self.gcode, None, None, hestr, bstr) def applySingleTempChange(self, s, bed, hes): if "m104" in s.lower() or "m109" in s.lower(): m = reS.match(s) difference = hes[self.currentTool] elif "m140" in s.lower() or "m190" in s.lower(): m = reS.match(s) difference = bed elif s.startswith("T"): try: t = int(s[1:]) except: t = None if t is not None: self.currentTool = t return s else: return s if m is None or m.lastindex != 3: return s value = float(m.group(2)) if value == 0.0: return s value += float(difference) return "%s%s%s" % (m.group(1), str(value), m.group(3)) def onModSpeed(self, evt): dlg = ModifySpeedDlg(self) dlg.CenterOnScreen() val = dlg.ShowModal() if val == wx.ID_OK: modSpeeds = dlg.getResult() dlg.Destroy() if val != wx.ID_OK: return self.applySpeedChange([float(x)/100.0 for x in modSpeeds]) def applySpeedChange(self, speeds): self.gcode = [self.applySingleSpeedChange(l, speeds) for l in self.gcode] self.setModified(True) self.gObj = self.buildModel() self.gcFrame.loadModel(self.gObj, self.gcFrame.getCurrentLayer(), self.gcFrame.getZoom()) self.lcGCode.setGCode(self.gcode) self.lcGCode.refreshList() self.updateInfoDlg(self.currentLayer) def applySingleSpeedChange(self, s, speeds): if "m117" in s or "M117" in s: return s m = reF.match(s) if m is None or m.lastindex != 3: return s e = reE.match(s) if e is None: #no extrusion - must be a move factor = speeds[1] else: factor = speeds[0] value = float(m.group(2)) * float(factor) return "%s%s%s" % (m.group(1), str(value), m.group(3)) def onFilChange(self, evt): insertPoint = self.lcGCode.getSelectedLine() dlg = FilamentChangeDlg(self, self.gcode, self.gObj, insertPoint, self.gObj[self.currentLayer].printHeight()) rc = dlg.ShowModal() if rc == wx.ID_OK: ngc = dlg.getValues() dlg.Destroy() if rc != wx.ID_OK: return if insertPoint == 0: self.gcode = ngc + self.gcode else: self.gcode = self.gcode[:insertPoint] + ngc + self.gcode[insertPoint:] self.setModified(True) self.enableButtons() self.gObj = self.buildModel() lmax = self.gObj.layerCount()-1 self.slLayers.SetRange(0, lmax) self.slLayers.SetPageSize(int(lmax/10)) self.gcFrame.loadModel(self.gObj, self.currentLayer, None) self.lcGCode.setGCode(self.gcode) self.lcGCode.setLayerBounds(self.gObj.getGCodeLines(self.currentLayer)) self.updateInfoDlg(self.currentLayer) def onEditGCode(self, evt): self.editDlg = EditGCodeDlg(self, self.gcode, "<live buffer>", self.editClosed) self.editDlg.CenterOnScreen() self.editDlg.Show() self.enableButtons(flag=False, openButtons=True) def editClosed(self, rc): self.enableButtons(flag=True, openButtons=True) if rc == wx.ID_OK: data = self.editDlg.getData() self.editDlg.Destroy() if rc != wx.ID_OK: return self.gcode = data[:] self.setModified(True) self.gObj = self.buildModel() self.modGcSuffixTemps(self.gObj.getTemps()) self.gcFrame.loadModel(self.gObj, 0, 1) self.currentLayer = 0 self.setLayerText() self.slLayers.SetValue(0) lmax = self.gObj.layerCount()-1 self.slLayers.SetRange(0, lmax) self.slLayers.SetPageSize(int(lmax/10)) self.lcGCode.setGCode(self.gcode) self.lcGCode.setLayerBounds(self.gObj.getGCodeLines(0)) self.lcGCode.refreshList() self.updateInfoDlg(0) def onCbShowMoves(self, evt): self.settings.showmoves = self.cbShowMoves.GetValue() self.gcFrame.setShowMoves(self.settings.showmoves) def onCbShowPrevious(self, evt): self.settings.showprevious = self.cbShowPrevious.GetValue() self.gcFrame.setShowPrevious(self.settings.showprevious) def onCbShowRetractions(self, evt): self.settings.showretractions = self.cbShowRetractions.GetValue() self.gcFrame.setShowRetractions(self.settings.showretractions) def onCbShowRevRetractions(self, evt): self.settings.showrevretractions = self.cbShowRevRetractions.GetValue() self.gcFrame.setShowRevRetractions(self.settings.showrevretractions) def onCmbTool(self, evt): sel = self.cmbTool.GetStringSelection() if sel == "" or sel == "None": sel = None else: try: sel = int(sel) except: sel = None self.gcFrame.setHilightTool(sel) def onCbLineNbrs(self, evt): self.settings.uselinenbrs = self.cbLineNbrs.GetValue() self.lcGCode.setLineNumbers(self.settings.uselinenbrs) def onLayerScroll(self, evt): v = self.slLayers.GetValue() if v == self.currentLayer: return self.changeLayer(v) def onUp(self, evt): lmax = self.slLayers.GetRange()[1] if self.currentLayer >= lmax: return v = self.currentLayer + 1 self.changeLayer(v) def onDown(self, evt): if self.currentLayer <= 0: return v = self.currentLayer - 1 self.changeLayer(v) def changeLayer(self, v): self.currentLayer = v self.gcFrame.setLayer(v) self.slLayers.SetValue(v) self.setLayerText() self.lcGCode.setLayerBounds(self.gObj.getGCodeLines(v)) self.showLayerProperties(v) def setLayerText(self): if self.gObj is None: ht = 0.0 else: ht = self.gObj[self.currentLayer].printHeight() self.stLayerText.SetLabel("Layer Height: %0.3f" % ht) def reportSelectedLine(self, ln): self.gcFrame.reportSelectedLine(ln) def onClose(self, evt): self.settings.save() if self.modified: dlg = wx.MessageDialog(self, "You have unsaved changes.\nAre you sure you want to exit?", "Confirm Exit With Pending Changes", wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) rc = dlg.ShowModal() dlg.Destroy() if rc == wx.ID_YES: self.parent.GEditClosed() else: self.parent.GEditClosed() def loadGCode(self, fn): if fn is None: self.gcode = [] return None try: self.gcode = list(open(fn)) except: print "Error opening file %s" % fn return None return self.buildModel() def buildModel(self): rgcode = [s.rstrip() for s in self.gcode] cnc = CNC(self.settings.acceleration, self.settings.layerheight) ln = -1 for gl in rgcode: ln += 1 if ";" in gl: gl = gl.split(";")[0] if gl.strip() == "": continue p = re.split("\\s+", gl, 1) params = {} if not (p[0].strip() in ["M117", "m117"]): if len(p) >= 2: self.paramStr = p[1] if "X" in self.paramStr: params["X"] = self._get_float("X") if "Y" in self.paramStr: params["Y"] = self._get_float("Y") if "Z" in self.paramStr: params["Z"] = self._get_float("Z") if "E" in self.paramStr: params["E"] = self._get_float("E") if "F" in self.paramStr: params["F"] = self._get_float("F") if "S" in self.paramStr: params["S"] = self._get_float("S") cnc.execute(p[0], params, ln) gobj = cnc.getGObject() gobj.setMaxLine(ln) self.totalTime, self.layerTimes = cnc.getTimes() self.totalTimeStr = formatElapsed(self.totalTime) self.layerTimeStr = [formatElapsed(s) for s in self.layerTimes] return gobj def _get_float(self,which): try: return float(gcRegex.findall(self.paramStr.split(which)[1])[0]) except: print "exception: ", self.paramStr def onSaveAs(self, evt): wildcard = "GCode (*.gcode)|*.gcode;*.GCODE" dlg = wx.FileDialog( self, message="Save as ...", defaultDir=self.settings.lastdirectory, defaultFile="", wildcard=wildcard, style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) val = dlg.ShowModal() if val != wx.ID_OK: dlg.Destroy() return path = dlg.GetPath() dlg.Destroy() ext = os.path.splitext(os.path.basename(path))[1] if ext == "": path += ".gcode" self.saveFile(path) def onSave(self, evt): if self.filename is None: self.onSaveAs(evt) else: self.saveFile(self.filename) def saveFile(self, path): fp = file(path, 'w') for ln in self.gcode: fp.write("%s\n" % ln.rstrip()) self.setModified(False) fp.close() self.filename = path self.parent.exportGcFile(path, self.settings.autoexport, self.settings.autoenqueue) self.updateTitle() dlg = wx.MessageDialog(self, "G Code file\n" + path + "\nwritten.", 'Save Successful', wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def onSaveLayers(self, evt): dlg = SaveLayerDlg(self, self.gObj) rc = dlg.ShowModal() if rc == wx.ID_OK: sx, ex, ereset, zmodify, zdelta = dlg.getValues() dlg.Destroy() if rc != wx.ID_OK: return startLine = self.gObj.getGCodeLines(sx)[0] endLine = self.gObj.getGCodeLines(ex)[1] wildcard = "GCode (*.gcode)|*.gcode;*.GCODE" dlg = wx.FileDialog( self, message="Save as ...", defaultDir=self.settings.lastdirectory, defaultFile="", wildcard=wildcard, style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT) val = dlg.ShowModal() if val != wx.ID_OK: dlg.Destroy() return path = dlg.GetPath() dlg.Destroy() ext = os.path.splitext(os.path.basename(path))[1] if ext == "": path += ".gcode" fp = file(path, 'w') if ereset: fp.write("G92 E%0.5f\n" % self.gObj[sx].startingE()) if zmodify: fp.write("\n".join([self.applyAxisShift(ln, 'z', zdelta).rstrip() for ln in self.gcode[startLine:endLine+1]])) else: fp.write("\n".join([ln.rstrip() for ln in self.gcode[startLine:endLine+1]])) fp.close() dlg = wx.MessageDialog(self, "G Code file\n" + path + "\nwritten.", 'Save Layers Successful', wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def applyZMod(self, ln, modflag): if not modflag: return ln return ln
class PrintMonitorDlg(wx.Frame): def __init__(self, parent, wparent, reprap, prtName): self.parent = parent self.wparent = wparent self.log = self.parent.log self.history = wparent.history self.reprap = reprap self.settings = self.parent.settings self.images = self.parent.images self.state = PrintState.idle self.oldState = None self.gcodeLoaded = False self.gcodeFile = None self.printerName = prtName self.layerMap = [] self.okToImport = False self.importFile = None self.currentLayer = 0 self.maxTool = 0 self.eUsed = [0.0, 0.0, 0.0, 0.0] self.totalTime = 0 self.totalTimeStr = "" self.layerTimes = [] self.layerTimeStr = [] self.layerRange = (0, 0) self.gObj = None self.printLayer = 0 self.printPosition = None title = self.buildTitle() wx.Frame.__init__(self, wparent, wx.ID_ANY, title=title) self.Show() ico = wx.Icon(os.path.join(cmdFolder, "images", "printmon.png"), wx.BITMAP_TYPE_PNG) self.SetIcon(ico) if self.settings.hassdcard: self.sdcard = SDCard(self.parent, self, self.reprap, self.log) else: self.sdcard = None self.gcf = GcFrame(self, self.gObj, self.settings) self.stLayerText = wx.StaticText(self, wx.ID_ANY, "Layer Height: 0.00") ht = self.gcf.GetSize().Get()[1] - BUTTONDIM[1] * 2 - 20 self.slLayers = wx.Slider(self, wx.ID_ANY, 0, 0, 1000, size=(-1, ht), style=wx.SL_VERTICAL | wx.SL_AUTOTICKS | wx.SL_LABELS | wx.SL_INVERSE) self.Bind(wx.EVT_SCROLL, self.onLayerScroll, self.slLayers) self.slLayers.Enable(False) self.cbShowMoves = wx.CheckBox(self, wx.ID_ANY, "Show moves") self.cbShowMoves.SetValue(self.settings.showmoves) self.Bind(wx.EVT_CHECKBOX, self.onShowMoves, self.cbShowMoves) self.cbShowPrevious = wx.CheckBox(self, wx.ID_ANY, "Show previous layer") self.cbShowPrevious.SetValue(self.settings.showprevious) self.Bind(wx.EVT_CHECKBOX, self.onShowPrevious, self.cbShowPrevious) self.cbToolPathOnly = wx.CheckBox(self, wx.ID_ANY, "Show tool paths only") self.cbToolPathOnly.SetValue(self.settings.toolpathonly) self.Bind(wx.EVT_CHECKBOX, self.onToolPathOnly, self.cbToolPathOnly) self.cbSyncPrint = wx.CheckBox(self, wx.ID_ANY, "Sync with print") self.cbSyncPrint.SetValue(True) self.Bind(wx.EVT_CHECKBOX, self.onSyncPrint, self.cbSyncPrint) self.bImport = wx.BitmapButton(self, wx.ID_ANY, self.images.pngImport, size=BUTTONDIM) self.bImport.SetToolTip("Import G Code file from toolbox") self.Bind(wx.EVT_BUTTON, self.onImport, self.bImport) self.bImportQ = wx.BitmapButton(self, wx.ID_ANY, self.images.pngNext, size=BUTTONDIM) self.Bind(wx.EVT_BUTTON, self.onImportFromQueue, self.bImportQ) self.bOpen = wx.BitmapButton(self, wx.ID_ANY, self.images.pngFileopen, size=BUTTONDIM) self.bOpen.SetToolTip("Open a G Code file") self.Bind(wx.EVT_BUTTON, self.onOpenFile, self.bOpen) self.Bind(wx.EVT_CLOSE, self.onClose) self.bPrint = PrintButton(self, self.images) self.bPrint.Enable(False) self.Bind(wx.EVT_BUTTON, self.onPrint, self.bPrint) self.bPause = PauseButton(self, self.images) self.bPause.Enable(False) self.Bind(wx.EVT_BUTTON, self.onPause, self.bPause) self.bSdPrintTo = wx.BitmapButton(self, wx.ID_ANY, self.images.pngSdprintto, size=(BUTTONDIMWIDE)) self.bSdPrintTo.Enable(False) self.Bind(wx.EVT_BUTTON, self.onSdPrintTo, self.bSdPrintTo) self.bSdPrintFrom = wx.BitmapButton(self, wx.ID_ANY, self.images.pngSdprintfrom, size=(BUTTONDIMWIDE)) self.bSdPrintFrom.Enable(False) self.Bind(wx.EVT_BUTTON, self.onSdPrintFrom, self.bSdPrintFrom) self.bSdDelete = wx.BitmapButton(self, wx.ID_ANY, self.images.pngSddelete, size=(BUTTONDIM)) self.bSdDelete.Enable(False) self.Bind(wx.EVT_BUTTON, self.onSdDelete, self.bSdDelete) self.bUp = wx.BitmapButton(self, wx.ID_ANY, self.images.pngUp, size=BUTTONDIM) self.bUp.SetToolTip("Move up one layer") self.Bind(wx.EVT_BUTTON, self.onUp, self.bUp) self.bUp.Enable(False) self.bDown = wx.BitmapButton(self, wx.ID_ANY, self.images.pngDown, size=BUTTONDIM) self.bDown.SetToolTip("Move down one layer") self.Bind(wx.EVT_BUTTON, self.onDown, self.bDown) self.bDown.Enable(False) szGcf = wx.BoxSizer(wx.HORIZONTAL) szGcf.AddSpacer(10) szGcf.Add(self.gcf) szGcf.Add(self.stLayerText, 1, wx.ALIGN_CENTER_HORIZONTAL, 1) szGcf.AddSpacer(10) szNav = wx.BoxSizer(wx.VERTICAL) szNav.Add(self.bUp, 1, wx.ALIGN_CENTER_HORIZONTAL, 1) szNav.AddSpacer(10) szNav.Add(self.slLayers) szNav.AddSpacer(10) szNav.Add(self.bDown, 1, wx.ALIGN_CENTER_HORIZONTAL, 1) szGcf.Add(szNav) szGcf.AddSpacer(10) szOpts = wx.BoxSizer(wx.HORIZONTAL) szOpts.AddSpacer(10) szOpts.Add(self.cbShowMoves) szOpts.AddSpacer(10) szOpts.Add(self.cbShowPrevious) szOpts.AddSpacer(10) szOpts.Add(self.cbToolPathOnly) szOpts.AddSpacer(10) szOpts.Add(self.cbSyncPrint) szOpts.AddSpacer(10) szBtn = wx.BoxSizer(wx.HORIZONTAL) szBtn.AddSpacer(10) szBtn.Add(self.bImport) szBtn.AddSpacer(10) szBtn.Add(self.bImportQ) szBtn.AddSpacer(10) szBtn.Add(self.bOpen) szBtn.AddSpacer(20) szBtn.Add(self.bPrint) szBtn.AddSpacer(10) szBtn.Add(self.bPause) if self.sdcard: szBtn.AddSpacer(20) szBtn.Add(self.bSdPrintTo) szBtn.AddSpacer(10) szBtn.Add(self.bSdPrintFrom) szBtn.AddSpacer(10) szBtn.Add(self.bSdDelete) szBtn.AddSpacer(10) szDlg = wx.BoxSizer(wx.VERTICAL) szDlg.AddSpacer(10) szDlg.Add(szGcf) szDlg.AddSpacer(10) szDlg.Add(szOpts) szDlg.AddSpacer(10) szDlg.Add(szBtn) szDlg.AddSpacer(10) self.SetSizer(szDlg) self.Fit() self.Layout() self.propDlg = PropertiesDlg(self, wparent, self.printerName) self.propDlg.Show() if not self.settings.propposition is None: self.propDlg.SetPosition(self.settings.propposition) self.enableButtonsByState() self.reprap.registerPositionHandler(self.updatePrintPosition) self.reprap.registerEventHandler(self.reprapEvent) self.reprap.registerSdEventHandler(self.sdcard) def show(self): self.Show() self.Raise() self.propDlg.Show() self.propDlg.Raise() def setLayerText(self, ht): if ht is None: htv = 0.0 else: htv = ht self.stLayerText.SetLabel("Layer Height: %0.3f" % htv) def getStatusReport(self): r = self.propDlg.getStatusReport() r["PrintStatus"] = PrintState.label[self.state] return r def buildTitle(self): t = "%s print monitor" % self.printerName if self.gcodeLoaded: if len(self.gcodeFile) > 45: t += " - %s" % os.path.basename(self.gcodeFile) else: t += " - %s" % self.gcodeFile return t def rememberPositions(self): self.settings.propposition = self.propDlg.GetPosition() def isPrinting(self): return self.state in [ PrintState.printing, PrintState.sdprintingto, PrintState.sdprintingfrom ] def onClose(self, evt): if self.isPrinting(): dlg = wx.MessageDialog(self, 'Cannot exit with printing active', "Printer is active", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() return self.terminate() def terminate(self): self.reprap.registerPositionHandler(None) self.reprap.registerEventHandler(None) self.parent.closePrintMon() self.propDlg.Destroy() self.Destroy() def onShowMoves(self, evt): v = self.cbShowMoves.GetValue() self.settings.showmoves = v self.gcf.setShowMoves(v) def onShowPrevious(self, evt): v = self.cbShowPrevious.GetValue() self.settings.showprevious = v self.gcf.setShowPrevious(v) def onToolPathOnly(self, evt): v = self.cbToolPathOnly.GetValue() self.settings.toolpathonly = v self.gcf.setToolPathsOnly(v) def onSyncPrint(self, evt): v = self.cbSyncPrint.GetValue() self.gcf.setSyncWithPrint(v) def onLayerScroll(self, evt): v = self.slLayers.GetValue() if v == self.currentLayer: return self.gcf.setLayer(v) self.changeLayer(v) def onUp(self, evt): lmax = self.slLayers.GetRange()[1] if self.currentLayer >= lmax: return v = self.currentLayer + 1 self.gcf.setLayer(v) self.changeLayer(v) def onDown(self, evt): if self.currentLayer <= 0: return v = self.currentLayer - 1 self.gcf.setLayer(v) self.changeLayer(v) def onImport(self, evt): fn = self.wparent.importGcFile() if fn is None: return self.loadGFile(fn) def onImportFromQueue(self, evt): fn = self.wparent.importGcFromQueue() if fn is None: return self.loadGFile(fn) def setImportButton(self, msg): if msg is None: self.okToImport = False self.bImportQ.SetToolTip("") self.bImportQ.Enable(False) else: self.okToImport = True self.bImportQ.SetToolTip(msg) self.bImportQ.Enable(self.bOpen.IsEnabled()) def setImportFile(self, fn): self.importFile = fn if fn is None: self.bImport.Enable(False) self.bImport.SetToolTip("") else: self.bImport.Enable(self.bOpen.IsEnabled()) self.bImport.SetToolTip("Import G Code file (%s)" % fn) def onOpenFile(self, evt): wildcard = "GCode (*.gcode)|*.gcode;*.GCODE|" \ "All files (*.*)|*.*" dlg = wx.FileDialog(self, message="Choose a GCode file", defaultDir=self.settings.lastdirectory, defaultFile="", wildcard=wildcard, style=wx.FD_OPEN) rc = dlg.ShowModal() if rc == wx.ID_OK: path = dlg.GetPath().encode('ascii', 'ignore') dlg.Destroy() if rc != wx.ID_OK: return self.loadGFile(path) def loadGFile(self, path): self.settings.lastdirectory = os.path.dirname(path) self.loadGCode(path) if self.gObj is None: lmax = 1 self.slLayers.Enable(False) self.bUp.Enable(False) self.bDown.Enable(False) else: lmax = self.gObj.layerCount() - 1 self.slLayers.Enable(True) self.bUp.Enable(True) self.bDown.Enable(True) self.slLayers.SetRange(0, lmax) self.slLayers.SetPageSize(int(lmax / 10)) self.gcf.loadModel(self.gObj) self.changeLayer(0) self.state = PrintState.idle self.oldState = None self.enableButtonsByState() t = self.buildTitle() self.SetTitle(t) self.propDlg.setPrintStatus(PrintState.idle) def loadGCode(self, fn): def gnormal(s): if ";" in s: return s.split(";")[0].rstrip() else: return s.rstrip() self.gcodeFile = None self.gcodeLoaded = False self.gcode = [] self.gObj = None self.maxLine = 0 self.totalTime = 0 self.totalTimeStr = "" self.layerTimes = [] self.layerTimeStr = [] self.propDlg.clearAllProperties() self.reprap.clearPrint() if fn is None: return try: gc = list(open(fn)) except: self.log("Error opening file %s" % fn) self.gcode = [] self.gObj = None self.gcodeLoaded = False return self.gcode = [s for s in map(gnormal, gc) if s.strip() != ""] self.gObj = self.buildModel() self.maxLine = self.gObj.getMaxLine() self.eUsed = self.gObj.getFilament() self.gcodeLoaded = True self.gcodeFile = pfn = fn if len(pfn) > 45: pfn = os.path.basename(fn) self.propDlg.setProperty(PropertyEnum.fileName, pfn) ftime = time.strftime('%y/%m/%d-%H:%M:%S', time.localtime(os.path.getmtime(fn))) self.propDlg.setProperty(PropertyEnum.sliceTime, ftime) self.propDlg.setProperty(PropertyEnum.printEstimate, self.totalTimeStr) if self.settings.nextruders < self.maxTool + 1: self.log( "G Code file uses more tools (%d) than printer is equipped with (%d)" % (self.maxTool + 1, self.settings.nextruders)) slCfg, filSiz, tempsHE, tempsBed = parseGCSuffix(gc) if tempsBed == "??": tBed = 0 else: try: tBed = int(float(tempsBed)) except: tBed = 0 if tempsHE == "??": tHe = [0] * self.settings.nextruders else: try: x = [int(float(x)) for x in re.split(", *", tempsHE) ] + [0] * self.settings.nextruders tHe = x[:self.settings.nextruders] except: tHe = [0] * self.settings.nextruders self.parent.registerGCodeTemps(tHe, tBed) self.propDlg.setProperty(PropertyEnum.slicerCfg, slCfg) self.propDlg.setProperty(PropertyEnum.filamentSize, filSiz) self.propDlg.setProperty(PropertyEnum.temperatures, "HE:%s BED:%s" % (tempsHE, tempsBed)) def updatePrintPosition(self, position): self.printLayer = self.getLayerByPosition(position) self.printPosition = position if self.state in [PrintState.printing, PrintState.sdprintingto]: posString = "%d/%d" % (position, self.maxLine) if self.maxLine != 0: pct = float(position) / float(self.maxLine) * 100.0 posString += " (%.1f%%)" % pct self.propDlg.setProperty(PropertyEnum.position, posString) self.gcf.setPrintPosition(position) lx = self.gcf.getCurrentLayer() if lx != self.currentLayer: self.changeLayer(lx) layersSplit = self.sumLayerTimes(self.printLayer) layerSplit = self.partialPrintingLayer() self.elapsed = time.time() - self.startTime expected = layersSplit[0] + layerSplit[0] elapsedStr = "%s (expected: %s)" % (formatElapsed( self.elapsed), formatElapsed(expected)) self.propDlg.setProperty(PropertyEnum.elapsed, elapsedStr) self.remaining = layersSplit[1] + layerSplit[1] self.propDlg.setProperty(PropertyEnum.remaining, formatElapsed(self.remaining)) #TODO - probably don't need all the various time estimates when printing TO CD # BUT IT MAY BREAK LOGIC BELOW (update time until) that rely on these values newEta = time.time() + self.remaining revisedStr = time.strftime('%H:%M:%S', time.localtime(newEta)) tdiff = newEta - self.origEta if tdiff < 0: revisedStr += " (%s ahead of estimate)" % formatElapsed( -tdiff) elif tdiff > 0: revisedStr += " (%s behind estimate)" % formatElapsed(tdiff) self.propDlg.setProperty(PropertyEnum.revisedEta, revisedStr) self.updateTimeUntil() elif self.state == PrintState.sdprintingfrom: #TODO Need to convey print position when printing from SD card pass def getLayerByPosition(self, pos): for lx in range(len(self.layerMap)): if self.layerMap[lx][0] <= pos and pos <= self.layerMap[lx][1]: return lx return 0 def partialPrintingLayer(self): f, l = self.gObj.getGCodeLines(self.printLayer) if f <= self.printPosition and self.printPosition <= l: done = self.printPosition - f todo = l - self.printPosition + 1 total = l - f + 1 lt = self.layerTimes[self.printLayer] pctDone = float(done) / float(total) pctToDo = float(todo) / float(total) return (pctDone * lt, pctToDo * lt) else: return (0.0, 0.0) def sumLayerTimes(self, lx): tBefore = sum(self.layerTimes[:lx]) tAfter = sum(self.layerTimes[lx + 1:]) return (tBefore, tAfter) def sumLayerRangeTime(self, slx, elx): return sum(self.layerTimes[slx:elx]) def changeLayer(self, lx): self.currentLayer = lx self.slLayers.SetValue(lx) ht = self.gObj.getLayerHeight(lx) self.setLayerText(ht) if ht is None: self.propDlg.setProperty(PropertyEnum.layerNum, "%d / %d" % (lx, self.gObj.layerCount())) else: self.propDlg.setProperty( PropertyEnum.layerNum, "%d / %d (%.2f mm) " % (lx, self.gObj.layerCount(), ht)) f, l = self.gObj.getGCodeLines(lx) if f is None: self.propDlg.setProperty(PropertyEnum.gCodeRange, "") self.layerRange = (0, 0) else: self.propDlg.setProperty(PropertyEnum.gCodeRange, "%d - %d" % (f, l)) self.layerRange = (f, l) x0, y0, xn, yn = self.gObj.getLayerMinMaxXY(lx) if x0 is None: self.propDlg.setProperty(PropertyEnum.minMaxXY, "") else: self.propDlg.setProperty( PropertyEnum.minMaxXY, "(%.2f, %.2f) - (%.2f, %.2f)" % (x0, y0, xn, yn)) le, prior, after = self.gObj.getLayerFilament(lx) s = [] for i in range(self.settings.nextruders): s.append("%.2f/%.2f <: %.2f >: %.2f" % (le[i], self.eUsed[i], prior[i], after[i])) self.propDlg.setProperty(PropertyEnum.filamentUsed, s) self.propDlg.setProperty( PropertyEnum.layerPrintTime, "%s / %s" % (self.layerTimeStr[lx], self.totalTimeStr)) self.updateTimeUntil() def updateTimeUntil(self): if self.currentLayer <= self.printLayer: self.propDlg.setProperty(PropertyEnum.timeUntil, "") elif self.printPosition is None: t = sum(self.layerTimes[:self.currentLayer]) self.propDlg.setProperty(PropertyEnum.timeUntil, formatElapsed(t)) else: t = sum(self.layerTimes[self.printLayer + 1:self.currentLayer] ) + self.partialPrintingLayer()[1] self.propDlg.setProperty(PropertyEnum.timeUntil, formatElapsed(t)) def reprapEvent(self, evt): if evt.event == RepRapEventEnum.PRINT_COMPLETE: # TODO - do I need special consideration here for print FROM SD if self.state == PrintState.sdprintingto: self.reprap.sendNow("M29 %s" % self.sdTargetFile) self.reprap.suspendTempProbe(False) self.setSDTargetFile(None) if self.state == PrintState.printing: self.history.addEvent( PrintCompleted(self.history.addFile(self.gcodeFile), "")) self.state = PrintState.idle self.oldState = None self.propDlg.setPrintStatus(PrintState.idle) self.gcf.setPrintPosition(-1) self.printPosition = None self.printLayer = 0 self.enableButtonsByState() self.elapsed = time.time() - self.startTime cmpTime = time.time() expCmpTime = self.origEta - self.startTime cmpTimeStr = time.strftime('%H:%M:%S', time.localtime(cmpTime)) self.log("Print completed at %s" % (cmpTimeStr)) self.log("Total print time of %s - expected print time %s" % (formatElapsed(self.elapsed), formatElapsed(expCmpTime))) self.reprap.printComplete() elif evt.event == RepRapEventEnum.PRINT_STOPPED: if self.state != PrintState.paused: self.oldState = self.state self.state = PrintState.paused self.propDlg.setPrintStatus(PrintState.paused) self.enableButtonsByState() self.reprap.printStopped() elif evt.event == RepRapEventEnum.PRINT_STARTED: pass elif evt.event == RepRapEventEnum.PRINT_RESUMED: pass elif evt.event == RepRapEventEnum.PRINT_ERROR: self.log("Error communicating with printer") elif evt.event == RepRapEventEnum.PRINT_SENDGCODE: self.log(evt.msg) else: self.log("unknown reprap event: %s" % str(evt.event)) def buildModel(self): cnc = CNC(self.settings.acceleration, self.settings.layerheight) if RECORD_TIMES: self.log("recording g code times in /tmp/gcodeTimes") fp = open("/tmp/gcodeTimes", "w") ln = -1 for gl in self.gcode: ln += 1 p = re.split("\\s+", gl, 1) params = {} if not (p[0].strip() in ["M117", "m117"]): if len(p) >= 2: self.paramStr = p[1] if "X" in self.paramStr: params["X"] = self._get_float("X") if "Y" in self.paramStr: params["Y"] = self._get_float("Y") if "Z" in self.paramStr: params["Z"] = self._get_float("Z") if "E" in self.paramStr: params["E"] = self._get_float("E") if "F" in self.paramStr: params["F"] = self._get_float("F") if "S" in self.paramStr: params["S"] = self._get_float("S") if "P" in self.paramStr: params["P"] = self._get_float("P") t = cnc.execute(p[0], params, ln) if RECORD_TIMES: fp.write("(%s) (%.3f)\n" % (gl, t)) if RECORD_TIMES: fp.close() gobj = cnc.getGObject() gobj.setMaxLine(ln) self.maxTool = cnc.getMaxTool() self.totalTime, self.layerTimes = cnc.getTimes() self.layerMap = [] for lx in range(len(gobj)): self.layerMap.append(gobj.getGCodeLines(lx)) self.totalTimeStr = formatElapsed(self.totalTime) self.layerTimeStr = [formatElapsed(s) for s in self.layerTimes] return gobj def _get_float(self, which): try: return float(gcRegex.findall(self.paramStr.split(which)[1])[0]) except: self.log("unable to parse float from (%s)" % self.paramStr) def enableButtonsByState(self): if self.state == PrintState.idle: self.bOpen.Enable(True) self.setImportFile(self.importFile) self.bImportQ.Enable(self.okToImport) if self.sdcard: self.bSdPrintTo.Enable(self.gcodeLoaded) self.bSdPrintFrom.Enable() self.bSdDelete.Enable() if self.gcodeLoaded: self.bPrint.Enable(True) self.bPrint.setPrint() self.bPause.Enable(False) self.bPause.setPause() else: self.bPrint.Enable(False) self.bPause.Enable(False) elif self.state in [PrintState.printing, PrintState.sdprintingto]: self.bImport.Enable(False) self.bImportQ.Enable(False) self.bOpen.Enable(False) self.bPrint.Enable(False) self.bPrint.setPrint() self.bPause.Enable(True) self.bPause.setPause() if self.sdcard: self.bSdPrintTo.Enable(False) self.bSdPrintFrom.Enable(False) self.bSdDelete.Enable(False) elif self.state == PrintState.sdprintingfrom: #TODO - what makes sense here pass elif self.state == PrintState.paused: self.bOpen.Enable(True) self.setImportFile(self.importFile) self.bImportQ.Enable(self.okToImport) self.bPrint.Enable(True) self.bPrint.setRestart() self.bPause.Enable(True) self.bPause.setResume() if self.sdcard: self.bSdPrintTo.Enable(self.gcodeLoaded) self.bSdPrintFrom.Enable() self.bSdDelete.Enable() def emulatePrintButton(self): if self.state in [ PrintState.printing, PrintState.sdprintingto, PrintState.sdprintingfrom ]: self.log("Already printing") elif not self.bPrint.IsEnabled(): self.log("Unable to print right now") else: self.onPrint(None) def reset(self): #TODO - cleanup if was sdprintingfrom self.state = PrintState.idle self.oldState = None self.reprap.suspendTempProbe(False) self.setSDTargetFile(None) self.propDlg.setPrintStatus(PrintState.idle) self.enableButtonsByState() def onPrint(self, evt): oldState = self.state self.state = PrintState.printing self.propDlg.setPrintStatus(PrintState.printing) self.enableButtonsByState() self.printPos = 0 self.startTime = time.time() self.endTime = None self.origEta = self.startTime + self.totalTime self.elapsed = 0 self.remaining = self.totalTime if oldState == PrintState.paused: action = "restarted" self.reprap.restartPrint(self.gcode) else: action = "started" self.reprap.startPrint(self.gcode) self.history.addEvent( PrintStarted(self.history.addFile(self.gcodeFile), "")) stime = time.strftime('%H:%M:%S', time.localtime(self.startTime)) self.propDlg.setProperty(PropertyEnum.startTime, stime) self.propDlg.setProperty( PropertyEnum.origEta, time.strftime('%H:%M:%S', time.localtime(self.origEta))) self.propDlg.setProperty(PropertyEnum.elapsed, formatElapsed(self.elapsed)) self.propDlg.setProperty(PropertyEnum.remaining, formatElapsed(self.remaining)) self.propDlg.setProperty(PropertyEnum.revisedEta, "") self.log("Print %s at %s" % (action, stime)) def onSdPrintFrom(self, evt): print "sd print from" def doSDPrintFrom(self, evt): self.printing = False self.paused = False self.sdpaused = False self.sdprintingfrom = True self.sdStartTime = time.time() #self.infoPane.setSDStartTime(self.sdStartTime) self.state = PrintState.printing #self.propDlg.setPrintStatus(PrintState.printing) self.enableButtonsByState() self.sdcard.startPrintFromSD() def cancelSDPrintFrom(self): self.sdprintingfrom = False self.printing = False self.paused = False self.state = PrintState.idle #self.propDlg.setPrintStatus(PrintState.printing) self.enableButtonsByState() def resumeSDPrintFrom(self, fn): #self.clearModel() self.reprap.sendNow("M23 " + fn[1].lower()) self.reprap.sendNow("M24") self.sdprintingfrom = True #self.M27Timer.Start(M27Interval, True) self.sdpaused = False #self.infoPane.setMode(MODE_FROM_SD) self.enableButtonsByState() def onSdPrintTo(self, evt): self.sdcard.startPrintToSD() def resumeSDPrintTo(self, tfn): self.setSDTargetFile(tfn[1].lower()) self.reprap.suspendTempProbe(True) self.reprap.sendNow("M28 %s" % self.sdTargetFile) self.printPos = 0 self.startTime = time.time() self.endTime = None self.reprap.startPrint(self.gcode) self.origEta = self.startTime + self.totalTime self.elapsed = 0 self.remaining = self.totalTime self.state = PrintState.sdprintingto stime = time.strftime('%H:%M:%S', time.localtime(self.startTime)) self.propDlg.setProperty(PropertyEnum.startTime, stime) self.propDlg.setProperty( PropertyEnum.origEta, time.strftime('%H:%M:%S', time.localtime(self.origEta))) self.propDlg.setProperty(PropertyEnum.elapsed, formatElapsed(self.elapsed)) self.propDlg.setProperty(PropertyEnum.remaining, formatElapsed(self.remaining)) self.propDlg.setProperty(PropertyEnum.revisedEta, "") self.log("Print to SD: %s started at %s" % (self.sdTargetFile, stime)) self.enableButtonsByState() def setSDTargetFile(self, tfn): self.sdTargetFile = tfn self.propDlg.setSDTargetFile(tfn) def onSdDelete(self, evt): self.sdcard.startDeleteFromSD() def emulatePauseButton(self): if not self.bPause.IsEnabled(): self.log("Unable to pause right now") else: self.onPause(None) def onPause(self, evt): if self.state == PrintState.paused: self.state = self.oldState if self.state is None: self.state = PrintState.printing self.propDlg.setPrintStatus(self.state) self.enableButtonsByState() self.reprap.resumePrint() else: self.oldState = self.state self.state = PrintState.paused self.propDlg.setPrintStatus(PrintState.paused) self.enableButtonsByState() self.reprap.pausePrint()