def __init__(self, parent, nb, settings): wx.Panel.__init__(self, nb, wx.ID_ANY) self.parent = parent self.deco = Decoration() self.configFile = None self.protFileLoaded = False self.settings = settings self.cfgValues = {} self.heaters = [] self.dir = os.path.join(self.settings.folder, "config") self.cfgDir = os.path.join(self.settings.folder, "configtool") self.SetBackgroundColour(self.deco.getBackgroundColour()) self.Bind(wx.EVT_PAINT, self.deco.onPaintBackground) sz = wx.BoxSizer(wx.HORIZONTAL) self.nb = wx.Notebook(self, wx.ID_ANY, size = (21, 21), style = wx.BK_DEFAULT) self.nb.SetBackgroundColour(self.deco.getBackgroundColour()) self.nb.SetFont(self.settings.font) self.pages = [] self.titles = [] self.pageModified = [] self.pageValid = [] self.pgMech = MechanicalPage(self, self.nb, len(self.pages), self.settings.font) text = "Mechanical" self.nb.AddPage(self.pgMech, text) self.pages.append(self.pgMech) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) self.pgAcc = AccelerationPage(self, self.nb, len(self.pages), self.settings.font) text = "Acceleration" self.nb.AddPage(self.pgAcc, text) self.pages.append(self.pgAcc) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) self.pgMiscellaneous = MiscellaneousPage(self, self.nb, len(self.pages), self.settings.font) text = "Miscellaneous" self.nb.AddPage(self.pgMiscellaneous, text) self.pages.append(self.pgMiscellaneous) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) sz.Add(self.nb, 1, wx.EXPAND + wx.ALL, 5) self.SetSizer(sz) self.Fit()
def __init__(self, parent, nb, settings): wx.Panel.__init__(self, nb, wx.ID_ANY) self.parent = parent self.deco = Decoration() self.configFile = None self.protFileLoaded = False self.settings = settings self.cfgValues = {} self.heaters = [] self.dir = os.path.join(self.settings.folder, "config") self.SetBackgroundColour(self.deco.getBackgroundColour()) self.Bind(wx.EVT_PAINT, self.deco.onPaintBackground) sz = wx.BoxSizer(wx.HORIZONTAL) self.nb = wx.Notebook(self, wx.ID_ANY, size=(21, 21), style=wx.BK_DEFAULT) self.nb.SetBackgroundColour(self.deco.getBackgroundColour()) self.nb.SetFont(self.settings.font) self.pages = [] self.titles = [] self.pageModified = [] self.pageValid = [] self.pgMech = MechanicalPage(self, self.nb, len(self.pages), self.settings.font) text = "Mechanical" self.nb.AddPage(self.pgMech, text) self.pages.append(self.pgMech) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) self.pgAcc = AccelerationPage(self, self.nb, len(self.pages), self.settings.font) text = "Acceleration" self.nb.AddPage(self.pgAcc, text) self.pages.append(self.pgAcc) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) self.pgMiscellaneous = MiscellaneousPage(self, self.nb, len(self.pages), self.settings.font) text = "Miscellaneous" self.nb.AddPage(self.pgMiscellaneous, text) self.pages.append(self.pgMiscellaneous) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) sz.Add(self.nb, 1, wx.EXPAND + wx.ALL, 5) self.SetSizer(sz) self.Fit()
class PrinterPanel(wx.Panel): def __init__(self, parent, nb, settings): wx.Panel.__init__(self, nb, wx.ID_ANY) self.parent = parent self.deco = Decoration() self.configFile = None self.protFileLoaded = False self.settings = settings self.cfgValues = {} self.heaters = [] self.dir = os.path.join(self.settings.folder, "config") self.SetBackgroundColour(self.deco.getBackgroundColour()) self.Bind(wx.EVT_PAINT, self.deco.onPaintBackground) sz = wx.BoxSizer(wx.HORIZONTAL) self.nb = wx.Notebook(self, wx.ID_ANY, size=(21, 21), style=wx.BK_DEFAULT) self.nb.SetBackgroundColour(self.deco.getBackgroundColour()) self.nb.SetFont(self.settings.font) self.pages = [] self.titles = [] self.pageModified = [] self.pageValid = [] self.pgMech = MechanicalPage(self, self.nb, len(self.pages), self.settings.font) text = "Mechanical" self.nb.AddPage(self.pgMech, text) self.pages.append(self.pgMech) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) self.pgAcc = AccelerationPage(self, self.nb, len(self.pages), self.settings.font) text = "Acceleration" self.nb.AddPage(self.pgAcc, text) self.pages.append(self.pgAcc) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) self.pgMiscellaneous = MiscellaneousPage(self, self.nb, len(self.pages), self.settings.font) text = "Miscellaneous" self.nb.AddPage(self.pgMiscellaneous, text) self.pages.append(self.pgMiscellaneous) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) sz.Add(self.nb, 1, wx.EXPAND + wx.ALL, 5) self.SetSizer(sz) self.Fit() def getFileName(self): return self.configFile def assertModified(self, pg, flag=True): self.pageModified[pg] = flag self.modifyTab(pg) def isModified(self): return (True in self.pageModified) def isValid(self): return not (False in self.pageValid) def hasData(self): return (self.configFile != None) def assertValid(self, pg, flag=True): self.pageValid[pg] = flag self.modifyTab(pg) if False in self.pageValid: self.parent.enableSavePrinter(False, False) else: self.parent.enableSavePrinter(not self.protFileLoaded, True) def modifyTab(self, pg): if self.pageModified[pg] and not self.pageValid[pg]: pfx = "?* " elif self.pageModified[pg]: pfx = "* " elif not self.pageValid[pg]: pfx = "? " else: pfx = "" self.nb.SetPageText(pg, pfx + self.titles[pg]) if True in self.pageModified and False in self.pageValid: pfx = "?* " elif True in self.pageModified: pfx = "* " elif False in self.pageValid: pfx = "? " else: pfx = "" self.parent.setPrinterTabDecor(pfx) def setHeaters(self, ht): return self.pgMiscellaneous.setHeaters(ht) def onClose(self, evt): if not self.confirmLoseChanges("exit"): return self.Destroy() def confirmLoseChanges(self, msg): if True not in self.pageModified: return True dlg = wx.MessageDialog( self, "Are you sure you want to " + msg + "?\n" "There are changes to your printer " "configuration that will be lost.", "Changes pending", wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION) rc = dlg.ShowModal() dlg.Destroy() if rc != wx.ID_YES: return False return True def onLoadConfig(self, evt): if not self.confirmLoseChanges("load a new printer configuration"): return if platform == "darwin": # Mac OS X appears to be a bit limited on wildcards. wildcard = "Printer configuration (printer.*.h)|*.h" else: wildcard = "Printer configuration (printer.*.h)|printer.*.h" dlg = wx.FileDialog(self, message="Choose a printer config file", defaultDir=self.dir, defaultFile="", wildcard=wildcard, style=wx.OPEN | wx.CHANGE_DIR) path = None if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() dlg.Destroy() if path is None: return self.dir = os.path.dirname(path) rc = self.loadConfigFile(path) if not rc: dlg = wx.MessageDialog(self, "Unable to process file %s." % path, "File error", wx.OK + wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return def loadConfigFile(self, fn): try: self.cfgBuffer = list(open(fn)) except: return False self.configFile = fn self.processors = [] gatheringHelpText = False helpTextString = "" helpKey = None self.cfgValues = {} self.helpText = {} prevLines = "" for ln in self.cfgBuffer: if gatheringHelpText: if reHelpTextEnd.match(ln): gatheringHelpText = False helpTextString = helpTextString.strip() # Keep paragraphs with double-newline. helpTextString = helpTextString.replace("\n\n ", "\n\n") # Keep indented lines, typically a list. helpTextString = helpTextString.replace( "\n\n ", "\n\n ") helpTextString = helpTextString.replace( "\n ", "\n\n ") # Remove all other newlines and indents. helpTextString = helpTextString.replace("\n ", " ") hk = helpKey.split() for k in hk: self.helpText[k] = helpTextString helpTextString = "" helpKey = None continue else: helpTextString += ln continue m = reHelpTextStart.match(ln) if m: t = m.groups() gatheringHelpText = True helpKey = t[0] continue if ln.rstrip().endswith("\\"): prevLines += ln.rstrip()[:-1] continue if prevLines != "": ln = prevLines + ln prevLines = "" if ln.lstrip().startswith("//"): continue if ln.lstrip().startswith("#define"): m = reDefQS.search(ln) if m: t = m.groups() if len(t) == 2: m = reDefQSm.search(ln) if m: t = m.groups() tt = re.findall(reDefQSm2, t[1]) if len(tt) == 1: self.cfgValues[t[0]] = tt[0] continue elif len(tt) > 1: self.cfgValues[t[0]] = tt continue m = reDefine.search(ln) if m: t = m.groups() if len(t) == 2: self.cfgValues[t[0]] = t[1] continue m = reDefBool.search(ln) if m: t = m.groups() if len(t) == 1: self.cfgValues[t[0]] = True if os.path.basename(fn) in protectedFiles: self.parent.enableSavePrinter(False, True) self.protFileLoaded = True else: self.protFileLoaded = False self.parent.enableSavePrinter(True, True) self.parent.setPrinterTabFile(os.path.basename(fn)) for pg in self.pages: pg.insertValues(self.cfgValues) pg.setHelpText(self.helpText) k = 'DC_EXTRUDER' if k in self.cfgValues.keys(): self.pgMiscellaneous.setOriginalHeater(self.cfgValues[k]) else: self.pgMiscellaneous.setOriginalHeater(None) return True def onSaveConfig(self, evt): path = self.configFile return self.saveConfigFile(path) def onSaveConfigAs(self, evt): wildcard = "Printer configuration (printer.*.h)|printer.*.h" dlg = wx.FileDialog(self, message="Save as ...", defaultDir=self.dir, 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() rc = self.saveConfigFile(path) if rc: self.parent.setPrinterTabFile(os.path.basename(path)) self.protFileLoaded = False self.parent.enableSavePrinter(True, True) return rc def saveConfigFile(self, path): if os.path.basename(path) in protectedFiles: dlg = wx.MessageDialog(self, "Unable to overwrite %s." % path, "Protected file error", wx.OK + wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return False if not os.path.basename(path).startswith("printer."): dlg = wx.MessageDialog( self, "Illegal file name: %s.\n" "File name must begin with \"printer.\"" % path, "Illegal file name", wx.OK + wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return False ext = os.path.splitext(os.path.basename(path))[1] self.dir = os.path.dirname(path) if ext == "": path += ".h" try: fp = file(path, 'w') except: dlg = wx.MessageDialog(self, "Unable to write to file %s." % path, "File error", wx.OK + wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return False self.configFile = path values = {} labelFound = [] for pg in self.pages: v1 = pg.getValues() for k in v1.keys(): values[k] = v1[k] for ln in self.cfgBuffer: m = reDefineBL.match(ln) if m: t = m.groups() if len(t) == 2: if t[0] in values.keys() and values[t[0]] != "": fp.write(defineValueFormat % (t[0], values[t[0]])) self.cfgValues[t[0]] = values[t[0]] labelFound.append(t[0]) elif t[0] in values.keys(): fp.write("//" + ln) if t[0] in self.cfgValues.keys(): del self.cfgValues[t[0]] labelFound.append(t[0]) else: fp.write(ln) continue m = reDefBoolBL.match(ln) if m: t = m.groups() if len(t) == 1: if t[0] in values.keys() and values[t[0]]: fp.write(defineBoolFormat % t[0]) self.cfgValues[t[0]] = True labelFound.append(t[0]) elif t[0] in values.keys(): fp.write("//" + ln) if t[0] in self.cfgValues.keys(): del self.cfgValues[t[0]] labelFound.append(t[0]) else: fp.write(ln) continue m = reCommDefBL.match(ln) if m: t = m.groups() if len(t) == 2: if t[0] in values.keys() and values[t[0]] != "": fp.write(defineValueFormat % (t[0], values[t[0]])) self.cfgValues[t[0]] = values[t[0]] labelFound.append(t[0]) elif t[0] in values.keys(): fp.write(ln) labelFound.append(t[0]) else: fp.write(ln) continue m = reCommDefBoolBL.match(ln) if m: t = m.groups() if len(t) == 1: if t[0] in values.keys() and values[t[0]]: fp.write(defineBoolFormat % t[0]) self.cfgValues[t[0]] = True labelFound.append(t[0]) elif t[0] in values.keys(): fp.write(ln) labelFound.append(t[0]) else: fp.write(ln) continue fp.write(ln) for k in labelFound: del values[k] newLabels = "" for k in values.keys(): if newLabels == "": newLabels = k else: newLabels += ", " + k self.addNewDefine(fp, k, values[k]) if newLabels != "": dlg = wx.MessageDialog( self, "New defines added to printer config:\n" + newLabels, "New defines", wx.OK + wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() fp.close() return True def addNewDefine(self, fp, key, val): fp.write("\n") fp.write("/** \\def %s\n" % key) fp.write(" Add help text here.\n") fp.write("*/\n") if val == True: fp.write(defineBoolFormat % key) elif val == False: fp.write("//#define %s\n" % key) elif val == "": fp.write("//#define %s\n" % key) else: fp.write(defineValueFormat % (key, val))
class PrinterPanel(wx.Panel): def __init__(self, parent, nb, settings): wx.Panel.__init__(self, nb, wx.ID_ANY) self.parent = parent self.deco = Decoration() self.configFile = None self.protFileLoaded = False self.settings = settings self.cfgValues = {} self.heaters = [] self.dir = os.path.join(self.settings.folder, "config") self.cfgDir = os.path.join(self.settings.folder, "configtool") self.SetBackgroundColour(self.deco.getBackgroundColour()) self.Bind(wx.EVT_PAINT, self.deco.onPaintBackground) sz = wx.BoxSizer(wx.HORIZONTAL) self.nb = wx.Notebook(self, wx.ID_ANY, size=(21, 21), style=wx.BK_DEFAULT) self.nb.SetBackgroundColour(self.deco.getBackgroundColour()) self.nb.SetFont(self.settings.font) self.pages = [] self.titles = [] self.pageModified = [] self.pageValid = [] self.pgMech = MechanicalPage(self, self.nb, len(self.pages), self.settings.font) text = "Mechanical" self.nb.AddPage(self.pgMech, text) self.pages.append(self.pgMech) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) self.pgAcc = AccelerationPage(self, self.nb, len(self.pages), self.settings.font) text = "Acceleration" self.nb.AddPage(self.pgAcc, text) self.pages.append(self.pgAcc) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) self.pgMiscellaneous = MiscellaneousPage(self, self.nb, len(self.pages), self.settings.font) text = "Miscellaneous" self.nb.AddPage(self.pgMiscellaneous, text) self.pages.append(self.pgMiscellaneous) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) sz.Add(self.nb, 1, wx.EXPAND + wx.ALL, 5) self.SetSizer(sz) self.Fit() def getFileName(self): return self.configFile def assertModified(self, pg, flag=True): self.pageModified[pg] = flag self.modifyTab(pg) def isModified(self): return (True in self.pageModified) def isValid(self): return not (False in self.pageValid) def hasData(self): return (self.configFile != None) def assertValid(self, pg, flag=True): self.pageValid[pg] = flag self.modifyTab(pg) if False in self.pageValid: self.parent.enableSavePrinter(False, False) else: self.parent.enableSavePrinter(not self.protFileLoaded, True) def modifyTab(self, pg): if self.pageModified[pg] and not self.pageValid[pg]: pfx = "?* " elif self.pageModified[pg]: pfx = "* " elif not self.pageValid[pg]: pfx = "? " else: pfx = "" self.nb.SetPageText(pg, pfx + self.titles[pg]) if True in self.pageModified and False in self.pageValid: pfx = "?* " elif True in self.pageModified: pfx = "* " elif False in self.pageValid: pfx = "? " else: pfx = "" self.parent.setPrinterTabDecor(pfx) def setHeaters(self, ht): return self.pgMiscellaneous.setHeaters(ht) def onClose(self, evt): if not self.confirmLoseChanges("exit"): return self.Destroy() def confirmLoseChanges(self, msg): if True not in self.pageModified: return True dlg = wx.MessageDialog( self, "Are you sure you want to " + msg + "?\n" "There are changes to your printer " "configuration that will be lost.", "Changes pending", wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION) rc = dlg.ShowModal() dlg.Destroy() if rc != wx.ID_YES: return False return True def onLoadConfig(self, evt): if not self.confirmLoseChanges("load a new printer configuration"): return if platform == "darwin": # Mac OS X appears to be a bit limited on wildcards. wildcard = "Printer configuration (printer.*.h)|*.h" else: wildcard = "Printer configuration (printer.*.h)|printer.*.h" dlg = wx.FileDialog(self, message="Choose a printer config file", defaultDir=self.dir, defaultFile="", wildcard=wildcard, style=wx.OPEN | wx.CHANGE_DIR) path = None if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() dlg.Destroy() if path is None: return self.dir = os.path.dirname(path) rc, efn = self.loadConfigFile(path) if not rc: dlg = wx.MessageDialog(self, "Unable to process file %s." % efn, "File error", wx.OK + wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return def loadConfigFile(self, fn): cfgFn = os.path.join(self.cfgDir, "printer.generic.h") try: self.cfgBuffer = list(open(cfgFn)) except: return False, cfgFn try: self.userBuffer = list(open(fn)) except: return False, fn self.configFile = fn self.processors = [] gatheringHelpText = False helpTextString = "" helpKey = None self.cfgValues = {} self.cfgNames = [] self.helpText = {} prevLines = "" for ln in self.cfgBuffer: if gatheringHelpText: if reHelpTextEnd.match(ln): gatheringHelpText = False helpTextString = helpTextString.strip() # Keep paragraphs with double-newline. helpTextString = helpTextString.replace("\n\n ", "\n\n") # Keep indented lines, typically a list. helpTextString = helpTextString.replace( "\n\n ", "\n\n ") helpTextString = helpTextString.replace( "\n ", "\n\n ") # Remove all other newlines and indents. helpTextString = helpTextString.replace("\n ", " ") hk = helpKey.split() for k in hk: self.helpText[k] = helpTextString helpTextString = "" helpKey = None continue else: helpTextString += ln continue m = reHelpTextStart.match(ln) if m: t = m.groups() gatheringHelpText = True helpKey = t[0] continue if ln.rstrip().endswith("\\"): prevLines += ln.rstrip()[:-1] continue if prevLines != "": ln = prevLines + ln prevLines = "" if self.parseDefineName(ln): continue gatheringHelpText = False prevLines = "" for ln in self.userBuffer: if gatheringHelpText: if reHelpTextEnd.match(ln): gatheringHelpText = False continue if reHelpTextStart.match(ln): gatheringHelpText = True continue if ln.rstrip().endswith("\\"): prevLines += ln.rstrip()[:-1] continue if prevLines != "": ln = prevLines + ln prevLines = "" if self.parseDefineValue(ln): continue if os.path.basename(fn) in protectedFiles: self.parent.enableSavePrinter(False, True) self.protFileLoaded = True else: self.protFileLoaded = False self.parent.enableSavePrinter(True, True) self.parent.setPrinterTabFile(os.path.basename(fn)) for pg in self.pages: pg.insertValues(self.cfgValues) pg.setHelpText(self.helpText) k = 'DC_EXTRUDER' if k in self.cfgValues.keys() and self.cfgValues[k][1] == True: self.pgMiscellaneous.setOriginalHeater(self.cfgValues[k][0]) else: self.pgMiscellaneous.setOriginalHeater(None) return True, None def parseDefineName(self, ln): m = reDefBool.search(ln) if m: t = m.groups() if len(t) == 1: self.cfgNames.append(t[0]) return True return False def parseDefineValue(self, ln): m = reDefQS.search(ln) if m: t = m.groups() if len(t) == 2: m = reDefQSm.search(ln) if m: t = m.groups() tt = re.findall(reDefQSm2, t[1]) if len(tt) == 1 and (t[0] in self.cfgNames): self.cfgValues[t[0]] = tt[0], True return True elif len(tt) > 1 and (t[0] in self.cfgNames): self.cfgValues[t[0]] = tt, True return True m = reDefine.search(ln) if m: t = m.groups() if len(t) == 2 and (t[0] in self.cfgNames): if reDefineBL.search(ln): self.cfgValues[t[0]] = t[1], True else: self.cfgValues[t[0]] = t[1], False return True m = reDefBoolBL.search(ln) if m: t = m.groups() if len(t) == 1 and (t[0] in self.cfgNames): self.cfgValues[t[0]] = True return True return False def onSaveConfig(self, evt): path = self.configFile return self.saveConfigFile(path) def onSaveConfigAs(self, evt): wildcard = "Printer configuration (printer.*.h)|printer.*.h" dlg = wx.FileDialog(self, message="Save as ...", defaultDir=self.dir, 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() rc = self.saveConfigFile(path) if rc: self.parent.setPrinterTabFile(os.path.basename(path)) self.protFileLoaded = False self.parent.enableSavePrinter(True, True) return rc def saveConfigFile(self, path): if os.path.basename(path) in protectedFiles: dlg = wx.MessageDialog( self, "It's not allowed to overwrite files " "distributed by Teacup. Choose another name.", "Protected file error", wx.OK + wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return False if not os.path.basename(path).startswith("printer."): dlg = wx.MessageDialog( self, "Illegal file name: %s.\n" "File name must begin with \"printer.\"" % path, "Illegal file name", wx.OK + wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return False ext = os.path.splitext(os.path.basename(path))[1] self.dir = os.path.dirname(path) if ext == "": path += ".h" try: fp = file(path, 'w') except: dlg = wx.MessageDialog(self, "Unable to write to file %s." % path, "File error", wx.OK + wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return False self.configFile = path values = {} for pg in self.pages: v1 = pg.getValues() for k in v1.keys(): values[k] = v1[k] for ln in self.cfgBuffer: m = reDefine.match(ln) if m: t = m.groups() if len(t) == 2 and t[0] in values.keys(): v = values[t[0]] self.cfgValues[t[0]] = v if v[1] == False: fp.write("//") fp.write(defineValueFormat % (t[0], v[0])) else: if t[0] == 'CANNED_CYCLE': # Known to be absent in the GUI. Worse, this value is replaced # by the one in the metadata file. # # TODO: make value reading above recognize wether this value is # commented out or not. Reading the value its self works # already. Hint: it's the rule using reDefQS, reDefQSm, etc. # # TODO: add a multiline text field in the GUI to deal with this. # # TODO: write this value out properly. In /* comments */, if # disabled. # # TODO: currently, the lines beyond the ones with the #define are # treated like arbitrary comments. Having the former TODOs # done, this will lead to duplicates. fp.write(ln) else: print "Value key " + t[0] + " not found in GUI." continue m = reDefBoolBL.match(ln) if m: t = m.groups() if len(t) == 1 and t[0] in values.keys(): v = values[t[0]] self.cfgValues[t[0]] = v if v == "" or v == False: fp.write("//") fp.write(defineBoolFormat % t[0]) else: print "Boolean key " + t[0] + " not found in GUI." continue fp.write(ln) fp.close() return True
class PrinterPanel(wx.Panel): def __init__(self, parent, nb, settings): wx.Panel.__init__(self, nb, wx.ID_ANY) self.parent = parent self.deco = Decoration() self.configFile = None self.protFileLoaded = False self.settings = settings self.cfgValues = {} self.heaters = [] self.dir = os.path.join(self.settings.folder, "config") self.SetBackgroundColour(self.deco.getBackgroundColour()) self.Bind(wx.EVT_PAINT, self.deco.onPaintBackground) sz = wx.BoxSizer(wx.HORIZONTAL) self.nb = wx.Notebook(self, wx.ID_ANY, size = (21, 21), style = wx.BK_DEFAULT) self.nb.SetBackgroundColour(self.deco.getBackgroundColour()) self.nb.SetFont(self.settings.font) self.pages = [] self.titles = [] self.pageModified = [] self.pageValid = [] self.pgMech = MechanicalPage(self, self.nb, len(self.pages), self.settings.font) text = "Mechanical" self.nb.AddPage(self.pgMech, text) self.pages.append(self.pgMech) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) self.pgAcc = AccelerationPage(self, self.nb, len(self.pages), self.settings.font) text = "Acceleration" self.nb.AddPage(self.pgAcc, text) self.pages.append(self.pgAcc) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) self.pgMiscellaneous = MiscellaneousPage(self, self.nb, len(self.pages), self.settings.font) text = "Miscellaneous" self.nb.AddPage(self.pgMiscellaneous, text) self.pages.append(self.pgMiscellaneous) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) sz.Add(self.nb, 1, wx.EXPAND + wx.ALL, 5) self.SetSizer(sz) self.Fit() def getFileName(self): return self.configFile def assertModified(self, pg, flag = True): self.pageModified[pg] = flag self.modifyTab(pg) def isModified(self): return (True in self.pageModified) def isValid(self): return not (False in self.pageValid) def hasData(self): return (self.configFile != None) def assertValid(self, pg, flag = True): self.pageValid[pg] = flag self.modifyTab(pg) if False in self.pageValid: self.parent.enableSavePrinter(False, False) else: self.parent.enableSavePrinter(not self.protFileLoaded, True) def modifyTab(self, pg): if self.pageModified[pg] and not self.pageValid[pg]: pfx = "?* " elif self.pageModified[pg]: pfx = "* " elif not self.pageValid[pg]: pfx = "? " else: pfx = "" self.nb.SetPageText(pg, pfx + self.titles[pg]) if True in self.pageModified and False in self.pageValid: pfx = "?* " elif True in self.pageModified: pfx = "* " elif False in self.pageValid: pfx = "? " else: pfx = "" self.parent.setPrinterTabDecor(pfx) def setHeaters(self, ht): return self.pgMiscellaneous.setHeaters(ht) def onClose(self, evt): if not self.confirmLoseChanges("exit"): return self.Destroy() def confirmLoseChanges(self, msg): if True not in self.pageModified: return True dlg = wx.MessageDialog(self, "Are you sure you want to " + msg + "?\n" "There are changes to your printer " "configuration that will be lost.", "Changes pending", wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION) rc = dlg.ShowModal() dlg.Destroy() if rc != wx.ID_YES: return False return True def onLoadConfig(self, evt): if not self.confirmLoseChanges("load a new printer configuration"): return if platform == "darwin": # Mac OS X appears to be a bit limited on wildcards. wildcard = "Printer configuration (printer.*.h)|*.h" else: wildcard = "Printer configuration (printer.*.h)|printer.*.h" dlg = wx.FileDialog(self, message = "Choose a printer config file", defaultDir = self.dir, defaultFile = "", wildcard = wildcard, style = wx.OPEN | wx.CHANGE_DIR) path = None if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() dlg.Destroy() if path is None: return self.dir = os.path.dirname(path) rc = self.loadConfigFile(path) if not rc: dlg = wx.MessageDialog(self, "Unable to process file %s." % path, "File error", wx.OK + wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return def loadConfigFile(self, fn): try: self.cfgBuffer = list(open(fn)) except: return False self.configFile = fn self.processors = [] gatheringHelpText = False helpTextString = "" helpKey = None self.cfgValues = {} self.helpText = {} prevLines = "" for ln in self.cfgBuffer: if gatheringHelpText: if reHelpTextEnd.match(ln): gatheringHelpText = False helpTextString = helpTextString.strip() # Keep paragraphs with double-newline. helpTextString = helpTextString.replace("\n\n ", "\n\n") # Keep indented lines, typically a list. helpTextString = helpTextString.replace("\n\n ", "\n\n ") helpTextString = helpTextString.replace("\n ", "\n\n ") # Remove all other newlines and indents. helpTextString = helpTextString.replace("\n ", " ") hk = helpKey.split() for k in hk: self.helpText[k] = helpTextString helpTextString = "" helpKey = None continue else: helpTextString += ln continue m = reHelpTextStart.match(ln) if m: t = m.groups() gatheringHelpText = True helpKey = t[0] continue if ln.rstrip().endswith("\\"): prevLines += ln.rstrip()[:-1] continue if prevLines != "": ln = prevLines + ln prevLines = "" if ln.lstrip().startswith("//"): continue if ln.lstrip().startswith("#define"): m = reDefQS.search(ln) if m: t = m.groups() if len(t) == 2: m = reDefQSm.search(ln) if m: t = m.groups() tt = re.findall(reDefQSm2, t[1]) if len(tt) == 1: self.cfgValues[t[0]] = tt[0] continue elif len(tt) > 1: self.cfgValues[t[0]] = tt continue m = reDefine.search(ln) if m: t = m.groups() if len(t) == 2: self.cfgValues[t[0]] = t[1] continue m = reDefBool.search(ln) if m: t = m.groups() if len(t) == 1: self.cfgValues[t[0]] = True if os.path.basename(fn) in protectedFiles: self.parent.enableSavePrinter(False, True) self.protFileLoaded = True else: self.protFileLoaded = False self.parent.enableSavePrinter(True, True) self.parent.setPrinterTabFile(os.path.basename(fn)) for pg in self.pages: pg.insertValues(self.cfgValues) pg.setHelpText(self.helpText) k = 'DC_EXTRUDER' if k in self.cfgValues.keys(): self.pgMiscellaneous.setOriginalHeater(self.cfgValues[k]) else: self.pgMiscellaneous.setOriginalHeater(None) return True def onSaveConfig(self, evt): path = self.configFile return self.saveConfigFile(path) def onSaveConfigAs(self, evt): wildcard = "Printer configuration (printer.*.h)|printer.*.h" dlg = wx.FileDialog(self, message = "Save as ...", defaultDir = self.dir, 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() rc = self.saveConfigFile(path) if rc: self.parent.setPrinterTabFile(os.path.basename(path)) self.protFileLoaded = False self.parent.enableSavePrinter(True, True) return rc def saveConfigFile(self, path): if os.path.basename(path) in protectedFiles: dlg = wx.MessageDialog(self, "Unable to overwrite %s." % path, "Protected file error", wx.OK + wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return False if not os.path.basename(path).startswith("printer."): dlg = wx.MessageDialog(self, "Illegal file name: %s.\n" "File name must begin with \"printer.\"" % path, "Illegal file name", wx.OK + wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return False ext = os.path.splitext(os.path.basename(path))[1] self.dir = os.path.dirname(path) if ext == "": path += ".h" try: fp = file(path, 'w') except: dlg = wx.MessageDialog(self, "Unable to write to file %s." % path, "File error", wx.OK + wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return False self.configFile = path values = {} labelFound = [] for pg in self.pages: v1 = pg.getValues() for k in v1.keys(): values[k] = v1[k] for ln in self.cfgBuffer: m = reDefineBL.match(ln) if m: t = m.groups() if len(t) == 2: if t[0] in values.keys() and values[t[0]] != "": fp.write(defineValueFormat % (t[0], values[t[0]])) self.cfgValues[t[0]] = values[t[0]] labelFound.append(t[0]) elif t[0] in values.keys(): fp.write("//" + ln) if t[0] in self.cfgValues.keys(): del self.cfgValues[t[0]] labelFound.append(t[0]) else: fp.write(ln) continue m = reDefBoolBL.match(ln) if m: t = m.groups() if len(t) == 1: if t[0] in values.keys() and values[t[0]]: fp.write(defineBoolFormat % t[0]) self.cfgValues[t[0]] = True labelFound.append(t[0]) elif t[0] in values.keys(): fp.write("//" + ln) if t[0] in self.cfgValues.keys(): del self.cfgValues[t[0]] labelFound.append(t[0]) else: fp.write(ln) continue m = reCommDefBL.match(ln) if m: t = m.groups() if len(t) == 2: if t[0] in values.keys() and values[t[0]] != "": fp.write(defineValueFormat % (t[0], values[t[0]])) self.cfgValues[t[0]] = values[t[0]] labelFound.append(t[0]) elif t[0] in values.keys(): fp.write(ln) labelFound.append(t[0]) else: fp.write(ln) continue m = reCommDefBoolBL.match(ln) if m: t = m.groups() if len(t) == 1: if t[0] in values.keys() and values[t[0]]: fp.write(defineBoolFormat % t[0]) self.cfgValues[t[0]] = True labelFound.append(t[0]) elif t[0] in values.keys(): fp.write(ln) labelFound.append(t[0]) else: fp.write(ln) continue fp.write(ln) for k in labelFound: del values[k] newLabels = "" for k in values.keys(): if newLabels == "": newLabels = k else: newLabels += ", " + k self.addNewDefine(fp, k, values[k]) if newLabels != "": dlg = wx.MessageDialog(self, "New defines added to printer config:\n" + newLabels, "New defines", wx.OK + wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() fp.close() return True def addNewDefine(self, fp, key, val): fp.write("\n") fp.write("/** \\def %s\n" % key) fp.write(" Add help text here.\n") fp.write("*/\n") if val == True: fp.write(defineBoolFormat % key) elif val == False: fp.write("//#define %s\n" % key) elif val == "": fp.write("//#define %s\n" % key) else: fp.write(defineValueFormat % (key, val))
class PrinterPanel(wx.Panel): def __init__(self, parent, nb, settings): wx.Panel.__init__(self, nb, wx.ID_ANY) self.parent = parent self.deco = Decoration() self.configFile = None self.protFileLoaded = False self.settings = settings self.cfgValues = {} self.heaters = [] self.dir = os.path.join(self.settings.folder, "config") self.cfgDir = os.path.join(self.settings.folder, "configtool") self.SetBackgroundColour(self.deco.getBackgroundColour()) self.Bind(wx.EVT_PAINT, self.deco.onPaintBackground) sz = wx.BoxSizer(wx.HORIZONTAL) self.nb = wx.Notebook(self, wx.ID_ANY, size = (21, 21), style = wx.BK_DEFAULT) self.nb.SetBackgroundColour(self.deco.getBackgroundColour()) self.nb.SetFont(self.settings.font) self.pages = [] self.titles = [] self.pageModified = [] self.pageValid = [] self.pgMech = MechanicalPage(self, self.nb, len(self.pages), self.settings.font) text = "Mechanical" self.nb.AddPage(self.pgMech, text) self.pages.append(self.pgMech) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) self.pgAcc = AccelerationPage(self, self.nb, len(self.pages), self.settings.font) text = "Acceleration" self.nb.AddPage(self.pgAcc, text) self.pages.append(self.pgAcc) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) self.pgMiscellaneous = MiscellaneousPage(self, self.nb, len(self.pages), self.settings.font) text = "Miscellaneous" self.nb.AddPage(self.pgMiscellaneous, text) self.pages.append(self.pgMiscellaneous) self.titles.append(text) self.pageModified.append(False) self.pageValid.append(True) sz.Add(self.nb, 1, wx.EXPAND + wx.ALL, 5) self.SetSizer(sz) self.Fit() def getFileName(self): return self.configFile def assertModified(self, pg, flag = True): self.pageModified[pg] = flag self.modifyTab(pg) def isModified(self): return (True in self.pageModified) def isValid(self): return not (False in self.pageValid) def hasData(self): return (self.configFile != None) def assertValid(self, pg, flag = True): self.pageValid[pg] = flag self.modifyTab(pg) if False in self.pageValid: self.parent.enableSavePrinter(False, False) else: self.parent.enableSavePrinter(not self.protFileLoaded, True) def modifyTab(self, pg): if self.pageModified[pg] and not self.pageValid[pg]: pfx = "?* " elif self.pageModified[pg]: pfx = "* " elif not self.pageValid[pg]: pfx = "? " else: pfx = "" self.nb.SetPageText(pg, pfx + self.titles[pg]) if True in self.pageModified and False in self.pageValid: pfx = "?* " elif True in self.pageModified: pfx = "* " elif False in self.pageValid: pfx = "? " else: pfx = "" self.parent.setPrinterTabDecor(pfx) def setHeaters(self, ht): return self.pgMiscellaneous.setHeaters(ht) def onClose(self, evt): if not self.confirmLoseChanges("exit"): return self.Destroy() def confirmLoseChanges(self, msg): if True not in self.pageModified: return True dlg = wx.MessageDialog(self, "Are you sure you want to " + msg + "?\n" "There are changes to your printer " "configuration that will be lost.", "Changes pending", wx.YES_NO | wx.NO_DEFAULT | wx.ICON_INFORMATION) rc = dlg.ShowModal() dlg.Destroy() if rc != wx.ID_YES: return False return True def onLoadConfig(self, evt): if not self.confirmLoseChanges("load a new printer configuration"): return if platform == "darwin": # Mac OS X appears to be a bit limited on wildcards. wildcard = "Printer configuration (printer.*.h)|*.h" else: wildcard = "Printer configuration (printer.*.h)|printer.*.h" dlg = wx.FileDialog(self, message = "Choose a printer config file", defaultDir = self.dir, defaultFile = "", wildcard = wildcard, style = wx.OPEN | wx.CHANGE_DIR) path = None if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() dlg.Destroy() if path is None: return self.dir = os.path.dirname(path) rc, efn = self.loadConfigFile(path) if not rc: dlg = wx.MessageDialog(self, "Unable to process file %s." % efn, "File error", wx.OK + wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return def loadConfigFile(self, fn): cfgFn = os.path.join(self.cfgDir, "printer.generic.h") try: self.cfgBuffer = list(open(cfgFn)) except: return False, cfgFn try: self.userBuffer = list(open(fn)) except: return False, fn self.configFile = fn self.processors = [] gatheringHelpText = False helpTextString = "" helpKey = None self.cfgValues = {} self.cfgNames = [] self.helpText = {} prevLines = "" for ln in self.cfgBuffer: if gatheringHelpText: if reHelpTextEnd.match(ln): gatheringHelpText = False helpTextString = helpTextString.strip() # Keep paragraphs with double-newline. helpTextString = helpTextString.replace("\n\n ", "\n\n") # Keep indented lines, typically a list. helpTextString = helpTextString.replace("\n\n ", "\n\n ") helpTextString = helpTextString.replace("\n ", "\n\n ") # Remove all other newlines and indents. helpTextString = helpTextString.replace("\n ", " ") hk = helpKey.split() for k in hk: self.helpText[k] = helpTextString helpTextString = "" helpKey = None continue else: helpTextString += ln continue m = reHelpTextStart.match(ln) if m: t = m.groups() gatheringHelpText = True helpKey = t[0] continue if ln.rstrip().endswith("\\"): prevLines += ln.rstrip()[:-1] continue if prevLines != "": ln = prevLines + ln prevLines = "" if self.parseDefineName(ln): continue gatheringHelpText = False prevLines = "" for ln in self.userBuffer: if gatheringHelpText: if reHelpTextEnd.match(ln): gatheringHelpText = False continue if reHelpTextStart.match(ln): gatheringHelpText = True continue if ln.rstrip().endswith("\\"): prevLines += ln.rstrip()[:-1] continue if prevLines != "": ln = prevLines + ln prevLines = "" if self.parseDefineValue(ln): continue if os.path.basename(fn) in protectedFiles: self.parent.enableSavePrinter(False, True) self.protFileLoaded = True else: self.protFileLoaded = False self.parent.enableSavePrinter(True, True) self.parent.setPrinterTabFile(os.path.basename(fn)) for pg in self.pages: pg.insertValues(self.cfgValues) pg.setHelpText(self.helpText) k = 'DC_EXTRUDER' if k in self.cfgValues.keys() and self.cfgValues[k][1] == True: self.pgMiscellaneous.setOriginalHeater(self.cfgValues[k][0]) else: self.pgMiscellaneous.setOriginalHeater(None) return True, None def parseDefineName(self, ln): m = reDefBool.search(ln) if m: t = m.groups() if len(t) == 1: self.cfgNames.append(t[0]) return True return False def parseDefineValue(self, ln): m = reDefQS.search(ln) if m: t = m.groups() if len(t) == 2: m = reDefQSm.search(ln) if m: t = m.groups() tt = re.findall(reDefQSm2, t[1]) if len(tt) == 1 and (t[0] in self.cfgNames): self.cfgValues[t[0]] = tt[0], True return True elif len(tt) > 1 and (t[0] in self.cfgNames): self.cfgValues[t[0]] = tt, True return True m = reDefine.search(ln) if m: t = m.groups() if len(t) == 2 and (t[0] in self.cfgNames): if reDefineBL.search(ln): self.cfgValues[t[0]] = t[1], True else: self.cfgValues[t[0]] = t[1], False return True m = reDefBoolBL.search(ln) if m: t = m.groups() if len(t) == 1 and (t[0] in self.cfgNames): self.cfgValues[t[0]] = True return True return False def onSaveConfig(self, evt): path = self.configFile return self.saveConfigFile(path) def onSaveConfigAs(self, evt): wildcard = "Printer configuration (printer.*.h)|printer.*.h" dlg = wx.FileDialog(self, message = "Save as ...", defaultDir = self.dir, 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() rc = self.saveConfigFile(path) if rc: self.parent.setPrinterTabFile(os.path.basename(path)) self.protFileLoaded = False self.parent.enableSavePrinter(True, True) return rc def saveConfigFile(self, path): if os.path.basename(path) in protectedFiles: dlg = wx.MessageDialog(self, "It's not allowed to overwrite files " "distributed by Teacup. Choose another name.", "Protected file error", wx.OK + wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return False if not os.path.basename(path).startswith("printer."): dlg = wx.MessageDialog(self, "Illegal file name: %s.\n" "File name must begin with \"printer.\"" % path, "Illegal file name", wx.OK + wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return False ext = os.path.splitext(os.path.basename(path))[1] self.dir = os.path.dirname(path) if ext == "": path += ".h" try: fp = file(path, 'w') except: dlg = wx.MessageDialog(self, "Unable to write to file %s." % path, "File error", wx.OK + wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() return False self.configFile = path values = {} for pg in self.pages: v1 = pg.getValues() for k in v1.keys(): values[k] = v1[k] for ln in self.cfgBuffer: m = reDefine.match(ln) if m: t = m.groups() if len(t) == 2 and t[0] in values.keys(): v = values[t[0]] self.cfgValues[t[0]] = v if v[1] == False: fp.write("//") fp.write(defineValueFormat % (t[0], v[0])) else: if t[0] == 'CANNED_CYCLE': # Known to be absent in the GUI. Worse, this value is replaced # by the one in the metadata file. # # TODO: make value reading above recognize wether this value is # commented out or not. Reading the value its self works # already. Hint: it's the rule using reDefQS, reDefQSm, etc. # # TODO: add a multiline text field in the GUI to deal with this. # # TODO: write this value out properly. In /* comments */, if # disabled. # # TODO: currently, the lines beyond the ones with the #define are # treated like arbitrary comments. Having the former TODOs # done, this will lead to duplicates. fp.write(ln) else: print "Value key " + t[0] + " not found in GUI." continue m = reDefBoolBL.match(ln) if m: t = m.groups() if len(t) == 1 and t[0] in values.keys(): v = values[t[0]] self.cfgValues[t[0]] = v if v == "" or v == False: fp.write("//") fp.write(defineBoolFormat % t[0]) else: print "Boolean key " + t[0] + " not found in GUI." continue fp.write(ln) fp.close() return True