import os import re from sys import platform from configtool.data import (defineValueFormat, defineBoolFormat, reHelpTextStart, reHelpTextEnd, reDefine, reDefineBL, reDefQS, reDefQSm, reDefQSm2, reDefBool, reDefBoolBL) class Printer: def __init__(self, settings): self.configFile = None self.cfgValues = {} self.settings = settings self.cfgDir = os.path.join(self.settings.folder, "configtool") def getValues(self): vars = [(x, self.cfgValues[x]) for x in self.cfgValues] return dict(vars) def hasData(self): return (self.configFile != None) def getFileName(self): return self.configFile 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 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 = "" self.parseDefineName(ln) self.parseDefineValue(ln) # Set all boolean generic configuration items to False, so items not yet # existing in the user configuration default to disabled. for k in self.cfgValues.keys(): if isinstance(self.cfgValues[k], bool): self.cfgValues[k] = False # Read the user configuration. This usually overwrites all of the items # read above, but not those missing in the user configuration, e.g. # when reading an older config. 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 = "" self.parseDefineValue(ln) # Parsing done. All parsed stuff is now in these array and dicts. if self.settings.verbose >= 2: print self.cfgValues # #defines with a value. print self.cfgNames # Names found in the generic file. if self.settings.verbose >= 3: print self.helpText 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 = reDefBool.search(ln) if m: t = m.groups() # Accept booleans, but not those for which a value exists already. # Booleans already existing as values are most likely misconfigured # manual edits (or result of a bug). if len(t) == 1 and t[0] in self.cfgNames \ and not (t[0] in self.cfgValues \ and isinstance(self.cfgValues[t[0]], tuple)): if reDefBoolBL.search(ln): self.cfgValues[t[0]] = True else: self.cfgValues[t[0]] = False return True return False def saveConfigFile(self, path, values): if not values: values = self.cfgValues if self.settings.verbose >= 1: print("Saving printer: %s." % path) if self.settings.verbose >= 2: print values fp = file(path, 'w') self.configFile = path 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