Configtool: many changes.

1) If variables are missing from .h files, they are added.
2) Settings file now modifiable from within the program.
3) A few cosmetic fixes.
This commit is contained in:
jbernardis 2015-01-25 20:17:32 -05:00 committed by Markus Hitter
parent b9f524d256
commit 9985c3936d
9 changed files with 353 additions and 19 deletions

View File

@ -7,7 +7,7 @@ import inspect
cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile(
inspect.currentframe()))[0]))
from configtool.settings import Settings
from configtool.settings import Settings, SettingsDlg
from configtool.printerpanel import PrinterPanel
from configtool.boardpanel import BoardPanel
from configtool.build import Build, Upload
@ -24,6 +24,7 @@ ID_LOAD_DEFAULT = 1021
ID_SAVE_CONFIG = 1022
ID_BUILD = 1030
ID_UPLOAD = 1031
ID_SETTINGS = 1040
class ConfigFrame(wx.Frame):
@ -180,6 +181,15 @@ class ConfigFrame(wx.Frame):
menu_bar.Append(build_menu, "&Build")
edit_menu = wx.Menu()
edit_menu.Append(ID_SETTINGS, "Settings", "Change settings.")
self.Bind(wx.EVT_MENU, self.onEditSettings, id = ID_SETTINGS)
self.editMenu = edit_menu
menu_bar.Append(edit_menu, "&Edit")
self.SetMenuBar(menu_bar)
self.checkEnableLoadConfig()
self.checkEnableUpload()
@ -260,16 +270,18 @@ class ConfigFrame(wx.Frame):
if not pfile:
self.message("Config file did not contain a printer file "
"include statement.", "Config error")
return
else:
if not self.pgPrinter.loadConfigFile(pfile):
self.message("There was a problem loading the printer config file:\n%s"
% pfile, "Config error")
if not bfile:
self.message("Config file did not contain a board file "
"include statement.", "Config error")
return
self.pgPrinter.loadConfigFile(pfile)
self.pgBoard.loadConfigFile(bfile)
else:
if not self.pgBoard.loadConfigFile(bfile):
self.message("There was a problem loading the board config file:\n%s"
% bfile, "Config error")
def getConfigFileNames(self, fn):
pfile = None
@ -454,6 +466,16 @@ class ConfigFrame(wx.Frame):
return ((pfile == lpfile) and (bfile == lbfile))
def onEditSettings(self, evt):
dlg = SettingsDlg(self, self.settings)
rc = dlg.ShowModal()
dlg.Destroy()
if rc != wx.ID_OK:
return
m = "configtool.default.ini successfully saved.\n"
self.message(m, "Save settings success", wx.OK + wx.ICON_INFORMATION)
def message(self, text, title, style = wx.OK + wx.ICON_ERROR):
dlg = wx.MessageDialog(self, text, title, style)
dlg.ShowModal()

View File

@ -4,7 +4,8 @@
# Where to find the arduino tools (avr-gcc, avrdude, etc). This is only used
# for windows. For linux it is assumed that the tools are available through
# the normal PATH.
arduinodir = C:/Program Files (x86)/Arduino/hardware/tools/avr/bin
#arduinodir = C:/Program Files (x86)/Arduino/hardware/tools/avr/bin
arduinodir =
# Flags passed into the avr-gcc compiler. These flags can have 3 different
# variabled embedded within them:

View File

@ -410,6 +410,8 @@ class BoardPanel(wx.Panel):
if self.saveConfigFile(path):
dlg = wx.MessageDialog(self, "File %s successfully written." % path,
"Save successful", wx.OK + wx.ICON_INFORMATION)
self.parent.setBoardTabFile(os.path.basename(path))
else:
dlg = wx.MessageDialog(self, "Unable to write to file %s." % path,
"File error", wx.OK + wx.ICON_ERROR)
@ -431,6 +433,7 @@ class BoardPanel(wx.Panel):
self.configFile = path
values = {}
labelFound = []
for pg in self.pages:
v1 = pg.getValues()
@ -482,8 +485,10 @@ class BoardPanel(wx.Panel):
if len(t) == 2:
if t[0] in values.keys() and values[t[0]] != "":
fp.write(defineValueFormat % (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
@ -494,8 +499,10 @@ class BoardPanel(wx.Panel):
if len(t) == 1:
if t[0] in values.keys() and values[t[0]]:
fp.write(defineBoolFormat % t[0])
labelFound.append(t[0])
elif t[0] in values.keys():
fp.write("//" + ln)
labelFound.append(t[0])
else:
fp.write(ln)
continue
@ -506,6 +513,10 @@ class BoardPanel(wx.Panel):
if len(t) == 2:
if t[0] in values.keys() and values[t[0]] != "":
fp.write(defineValueFormat % (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
@ -516,14 +527,48 @@ class BoardPanel(wx.Panel):
if len(t) == 1:
if t[0] in values.keys() and values[t[0]]:
fp.write(defineBoolFormat % t[0])
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 board config:\n" +
newLabels, "New Defines",
wx.OK + wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
fp.close()
self.parent.setBoardTabFile(os.path.basename(path))
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))

View File

@ -1,8 +1,7 @@
import wx
import wx.lib.newevent
import thread, shlex, subprocess
import os
import os, re
from os.path import isfile, join
from sys import platform
@ -115,6 +114,9 @@ class Build(wx.Dialog):
tc = wx.TextCtrl(self, wx.ID_ANY, size = (900, 300),
style = wx.TE_READONLY + wx.TE_MULTILINE)
sz.Add(tc, 1, wx.EXPAND)
f = wx.Font(8, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL,
wx.FONTWEIGHT_BOLD)
tc.SetFont(f)
self.log = tc
sz.AddSpacer((10, 10))
@ -153,6 +155,21 @@ class Build(wx.Dialog):
self.active = True
t.Start()
def report(self):
self.script = []
self.reportLines = []
if platform == "win32":
cmdpath = "\"" + join(self.settings.arduinodir, "avr-objdump") + "\""
else:
cmdpath = "avr-objdump"
elfpath = "\"" + join(self.root, "build", "teacup.elf") + "\""
cmd = cmdpath + " -h " + elfpath
self.script.append(cmd)
self.Bind(EVT_SCRIPT_UPDATE, self.reportUpdate)
t = ScriptThread(self, self.script)
self.active = True
t.Start()
def generateCompileScript(self):
self.script = []
if platform == "win32":
@ -189,6 +206,7 @@ class Build(wx.Dialog):
if isfile(join(self.root, "build", f)) and f.endswith(".o")]
opath = " ".join(ofiles)
elfpath = "\"" + join(self.root, "build", "teacup.elf") + "\""
hexpath = "\"" + join(self.root, "teacup.hex") + "\""
opts = self.settings.cflags
opts = opts.replace("%ALNAME%", "teacup.elf")
opts = opts.replace("%F_CPU%", self.f_cpu)
@ -202,7 +220,7 @@ class Build(wx.Dialog):
else:
cmdpath = "avr-objcopy"
cmd = cmdpath + " " + self.settings.objcopyflags + " " + elfpath + \
" teacup.hex"
" " + hexpath
self.script.append(cmd)
def compileUpdate(self, evt):
@ -229,7 +247,50 @@ class Build(wx.Dialog):
self.active = False
if evt.state == SCRIPT_FINISHED:
self.log.AppendText("Link completed normally.\n")
self.report()
def reportUpdate(self, evt):
if evt.state == SCRIPT_RUNNING:
if evt.msg is not None:
self.reportLines.append(evt.msg)
if evt.state == SCRIPT_CANCELLED:
self.log.AppendText(evt.msg + "\n")
self.log.AppendText("Report terminated abnormally.\n")
self.active = False
if evt.state == SCRIPT_FINISHED:
self.formatReport()
self.log.AppendText("\nBuild completed normally.\n")
self.active = False
def formatReportLine(self, m, name, v168, v328, v644, v1280):
t = m.groups()
v = int(t[0], 16)
self.log.AppendText(("%12s : %6d bytes %6.2f%% %6.2f%%"
" %6.2f%% %6.2f%%\n") %
(name, v, v / float(v168 * 1024) * 100.0,
v / float(v328 * 1024) * 100.0,
v / float(v644 * 1024) * 100.0,
v / float(v1280 * 1024) * 100.0))
def formatReport(self):
reText = re.compile("\.text\s+([0-9a-f]+)")
reBss = re.compile("\.bss\s+([0-9a-f]+)")
reEEProm = re.compile("\.eeprom\s+([0-9a-f]+)")
self.log.AppendText("\n ATmega... '168 '328(P)"
" '644(P) '1280\n")
for l in self.reportLines:
m = reText.search(l)
if m:
self.formatReportLine(m, "FLASH", 14, 30, 62, 126)
else:
m = reBss.search(l)
if m:
self.formatReportLine(m, "RAM", 1, 2, 4, 8)
else:
m = reEEProm.search(l)
if m:
self.formatReportLine(m, "EEPROM", 1, 2, 2, 4)
def onExit(self, evt):
if self.active:
@ -259,6 +320,9 @@ class Upload(wx.Dialog):
tc = wx.TextCtrl(self, wx.ID_ANY, size = (900, 300),
style = wx.TE_READONLY + wx.TE_MULTILINE)
sz.Add(tc, 1, wx.EXPAND)
f = wx.Font(8, wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL,
wx.FONTWEIGHT_BOLD)
tc.SetFont(f)
self.log = tc
sz.AddSpacer((10, 10))

View File

@ -18,12 +18,13 @@ class CpuPage(wx.Panel, Page):
sz.AddSpacer((20, 40), pos = (0, 0))
k = 'F_CPU'
ch = self.addChoice(k, self.clocks, 0, 100, self.onChoice)
ch = self.addChoice(k, self.clocks, 0, 100, self.onChoice, size = (140, -1))
sz.Add(ch, pos = (1, 1))
sz.AddSpacer((100, 10), pos = (1, 2))
k = 'CPU'
ch = self.addChoice(k, self.processors, 0, 100, self.onChoice)
ch = self.addChoice(k, self.processors, 0, 100, self.onChoice,
size = (140, -1))
sz.Add(ch, pos = (1, 3))
self.SetSizer(sz)

View File

@ -216,4 +216,10 @@ class MechanicalPage(wx.Panel, Page):
result['KINEMATICS'] = tag
break
for tag in self.kinematicsKeys:
try:
del result[tag]
except:
pass
return result

View File

@ -62,14 +62,15 @@ class Page:
return rb
def addChoice(self, name, choices, selection, labelWidth, validator):
def addChoice(self, name, choices, selection, labelWidth, validator,
size = (-1, -1)):
lsz = wx.BoxSizer(wx.HORIZONTAL)
st = wx.StaticText(self, wx.ID_ANY, self.labels[name],
size = (labelWidth, -1), style = wx.ALIGN_RIGHT)
st.SetFont(self.font)
lsz.Add(st)
ch = wx.Choice(self, wx.ID_ANY, choices = choices, name = name)
ch = wx.Choice(self, wx.ID_ANY, choices = choices, size = size, name = name)
ch.SetFont(self.font)
ch.Bind(wx.EVT_CHOICE, validator)
ch.SetSelection(selection)

View File

@ -6,8 +6,7 @@ import re
from configtool.data import (defineValueFormat, defineBoolFormat, reCommDefBL,
reCommDefBoolBL, reHelpTextStart, reHelpTextEnd,
reDefine, reDefineBL, reDefQS, reDefQSm,
reDefQSm2, reDefBool, reDefBoolBL, reFloatAttr,
TYPE_FLOAT, TYPE_GENERAL)
reDefQSm2, reDefBool, reDefBoolBL)
from configtool.mechanicalpage import MechanicalPage
from configtool.accelerationpage import AccelerationPage
from configtool.miscellaneouspage import MiscellaneousPage
@ -313,6 +312,7 @@ class PrinterPanel(wx.Panel):
self.configFile = path
values = {}
labelFound = []
for pg in self.pages:
v1 = pg.getValues()
@ -326,8 +326,10 @@ class PrinterPanel(wx.Panel):
if len(t) == 2:
if t[0] in values.keys() and values[t[0]] != "":
fp.write(defineValueFormat % (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
@ -338,8 +340,10 @@ class PrinterPanel(wx.Panel):
if len(t) == 1:
if t[0] in values.keys() and values[t[0]]:
fp.write(defineBoolFormat % t[0])
labelFound.append(t[0])
elif t[0] in values.keys():
fp.write("//" + ln)
labelFound.append(t[0])
else:
fp.write(ln)
continue
@ -350,6 +354,10 @@ class PrinterPanel(wx.Panel):
if len(t) == 2:
if t[0] in values.keys() and values[t[0]] != "":
fp.write(defineValueFormat % (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
@ -360,12 +368,48 @@ class PrinterPanel(wx.Panel):
if len(t) == 1:
if t[0] in values.keys() and values[t[0]]:
fp.write(defineBoolFormat % t[0])
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))

View File

@ -1,6 +1,8 @@
import ConfigParser
import os
import wx
from configtool.data import BSIZESMALL
INIFILE = "configtool.default.ini"
@ -45,3 +47,151 @@ class Settings:
print "Unknown %s option: %s - ignoring." % (self.section, opt)
else:
print "Missing %s section - assuming defaults." % self.section
def saveSettings(self):
self.section = "configtool"
try:
self.cfg.add_section(self.section)
except ConfigParser.DuplicateSectionError:
pass
self.cfg.set(self.section, "arduinodir", str(self.arduinodir))
self.cfg.set(self.section, "cflags", str(self.cflags))
self.cfg.set(self.section, "ldflags", str(self.ldflags))
self.cfg.set(self.section, "objcopyflags", str(self.objcopyflags))
self.cfg.set(self.section, "programmer", str(self.programmer))
self.cfg.set(self.section, "port", str(self.port))
try:
cfp = open(self.inifile, 'wb')
except:
print "Unable to open settings file %s for writing." % self.inifile
return
self.cfg.write(cfp)
cfp.close()
ARDUINODIR = 0
CFLAGS = 1
LDFLAGS = 2
OBJCOPYFLAGS= 3
PROGRAMMER = 4
PORT = 5
class SettingsDlg(wx.Dialog):
def __init__(self, parent, settings):
wx.Dialog.__init__(self, parent, wx.ID_ANY, "Modify settings",
size = (500, 300))
self.SetFont(settings.font)
self.settings = settings
self.modified = False
self.Bind(wx.EVT_CLOSE, self.onExit)
self.fields = [["Arduino Directory", settings.arduinodir, None],
["C Compiler Flags", settings.cflags, None],
["LD Flags", settings.ldflags, None],
["Object Copy Flags", settings.objcopyflags, None],
["AVR Programmer", settings.programmer, None],
["Port", settings.port, None]]
hsz = wx.BoxSizer(wx.HORIZONTAL)
hsz.AddSpacer((10, 10))
sz = wx.BoxSizer(wx.VERTICAL)
sz.AddSpacer((10, 10))
labelWidth = 140
for f in self.fields:
lsz = wx.BoxSizer(wx.HORIZONTAL)
t = wx.StaticText(self, wx.ID_ANY, f[0], size = (labelWidth, -1),
style = wx.ALIGN_RIGHT)
t.SetFont(settings.font)
lsz.Add(t)
lsz.AddSpacer((8, 8))
te = wx.TextCtrl(self, wx.ID_ANY, f[1], size = (600, -1))
te.Bind(wx.EVT_TEXT, self.onTextCtrl)
lsz.Add(te)
f[2] = te
sz.Add(lsz)
sz.AddSpacer((10, 10))
sz.AddSpacer((20, 20))
bsz = wx.BoxSizer(wx.HORIZONTAL)
b = wx.Button(self, wx.ID_ANY, "Save", size = BSIZESMALL)
b.SetFont(settings.font)
self.Bind(wx.EVT_BUTTON, self.onSave, b)
bsz.Add(b)
self.bSave = b
bsz.AddSpacer((5, 5))
b = wx.Button(self, wx.ID_ANY, "Exit", size = BSIZESMALL)
b.SetFont(settings.font)
self.Bind(wx.EVT_BUTTON, self.onExit, b)
bsz.Add(b)
self.bExit = b
sz.Add(bsz, 1, wx.ALIGN_CENTER_HORIZONTAL)
sz.AddSpacer((10, 10))
hsz.Add(sz)
hsz.AddSpacer((10, 10))
self.SetSizer(hsz)
self.setModified(False)
self.Fit()
def setModified(self, flag):
self.modified = flag
if flag:
self.bSave.Enable(True)
self.bExit.SetLabel("Cancel")
else:
self.bSave.Enable(False)
self.bExit.SetLabel("Exit")
def onTextCtrl(self, evt):
self.setModified(True)
evt.Skip()
def onSave(self, evt):
self.saveValues()
self.EndModal(wx.ID_OK)
def saveValues(self):
self.settings.arduinodir = self.fields[ARDUINODIR][2].GetValue()
self.settings.cflags = self.fields[CFLAGS][2].GetValue()
self.settings.ldflags = self.fields[LDFLAGS][2].GetValue()
self.settings.objcopyflags = self.fields[OBJCOPYFLAGS][2].GetValue()
self.settings.programmer = self.fields[PROGRAMMER][2].GetValue()
self.settings.port = self.fields[PORT][2].GetValue()
self.settings.saveSettings()
def onExit(self, evt):
if not self.confirmLoseChanges("exit"):
return
self.EndModal(wx.ID_EXIT)
def confirmLoseChanges(self, msg):
if not self.modified:
return True
dlg = wx.MessageDialog(self, "Are you sure you want to " + msg + "?\n"
"There are changes to your settings 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