Teacup_Firmware/configtool/printerpanel.py

408 lines
11 KiB
Python

import os
import wx
import re
from sys import platform
from configtool.decoration import Decoration
from configtool.data import (defineValueFormat, defineBoolFormat, reCommDefBL,
reCommDefBoolBL, reHelpTextStart, reHelpTextEnd,
reDefine, reDefineBL, reDefQS, reDefQSm,
reDefQSm2, reDefBool, reDefBoolBL)
from configtool.mechanicalpage import MechanicalPage
from configtool.accelerationpage import AccelerationPage
from configtool.miscellaneouspage import MiscellaneousPage
from configtool.protectedfiles import protectedFiles
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, "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, 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.metadata")
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 = ""
self.parseDefineName(ln)
prevLines = ""
for ln in self.userBuffer:
if ln.rstrip().endswith("\\"):
prevLines += ln.rstrip()[:-1]
continue
if prevLines != "":
ln = prevLines + ln
prevLines = ""
self.parseDefineValue(ln)
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, None
def parseDefineName(self, ln):
m = reDefBool.search(ln)
if m:
t = m.groups()
if len(t) == 1:
self.cfgNames.append(t[0])
def parseDefineValue(self, ln):
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]
return
elif len(tt) > 1:
self.cfgValues[t[0]] = tt
return
m = reDefine.search(ln)
if m:
t = m.groups()
if len(t) == 2:
self.cfgValues[t[0]] = t[1]
return
m = reDefBool.search(ln)
if m:
t = m.groups()
if len(t) == 1:
self.cfgValues[t[0]] = True
return
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 = reDefBoolBL.match(ln)
if m:
t = m.groups()
if len(t) == 1:
if t[0] in values.keys():
v = values[t[0]]
self.cfgValues[t[0]] = v
if v == "" or v == False:
fp.write("//" + ln)
elif v == True:
fp.write(ln)
else:
fp.write(defineValueFormat % (t[0], v))
else:
fp.write(ln)
continue
fp.write(ln)
fp.close()
return True