much better

This commit is contained in:
Stefan Kögl 2012-11-20 16:55:22 +01:00
parent 3f3d1f60b7
commit e7ade6bb92
5 changed files with 453 additions and 284 deletions

View File

@ -1,17 +0,0 @@
// include the library code:
#include <LiquidCrystal.h>
#include <DFR_Key.h>
#include <profile.h>
#include <oven_control.h>
OvenCtl oven_ctl;
void setup() {
Serial.begin(9600);
delay(300);
oven_ctl.set_config_state();
}
void loop() {
oven_ctl.handle_states();
}

View File

@ -18,40 +18,48 @@ from matplotlib.path import Path
import matplotlib.patches as patches
#from mpltools import annotation
progname = os.path.basename(sys.argv[0])
progversion = "0.1"
PSTEP_COLORS = ("lightgreen", "yellow", "orange", "red")
def calc_colors(count):
r = 0
g = 255
step = int(512. / (count-1))
colors = list()
print "step", step
for i in range(count):
colors.append(QtGui.QColor(r, g, 0))
if r < 255:
r += step
if r > 255:
g -= r - 255
r = 255
else:
g -= step
g = max(0, g)
return colors
class State(object):
def __init__(self, name, temp):
def getTemperature():
return 20.
class TempLevel(object):
def __init__(self, name, temp, is_env=False):
self.name = name
self.temp = temp
self.is_env = is_env
self.color = None
class Solder(object):
def __init__(self):
self.psteps = []
def __init__(self, name=str(), description=str()):
self.name = name
self.description = description
self.temp_levels = list()
self.durations = list()
self.rates = list()
self.name = None
#start = self.add_state("start", 25)
#ps = self.add_state("preheat start", 150)
#pe = self.add_state("preheat end", 185)
#tal = self.add_state("tal", 220)
#peak = self.add_state("peak", 250)
#end = self.add_state("end", 25)
#self.add_duration((ps, pe), 100)
#self.add_duration((tal, peak, tal), 100)
#self.add_rate((start, ps), 1)
#self.add_rate((ps, pe), 1)
#self.add_rate((pe, tal), 1)
#self.add_rate((tal, end), -2)
def __unicode__(self):
return unicode(self.name)
@ -59,26 +67,28 @@ class Solder(object):
def __str__(self):
return self.name
def color(self, index):
return PSTEP_COLORS[index]
def add_state(self, name, temp):
s = State(name, temp)
self.psteps.append(s)
def add_temp_level(self, name, temp, is_env):
s = TempLevel(name, temp, is_env)
self.temp_levels.append(s)
return s
def add_rate(self, states, rate):
self.rates.append((states, rate))
self.rates.append([states, rate])
def add_duration(self, states, duration):
self.durations.append((states, duration))
self.durations.append([states, duration])
def get_state(self, name):
for i in self.psteps:
def get_temp_level_by_name(self, name):
assert isinstance(name, basestring)
for i in self.temp_levels:
if i.name == name:
return i
return None
def get_temp_level(self, ix):
assert isinstance(ix, int)
return self.temp_levels[ix]
def calc_profile(self):
x = list()
@ -86,64 +96,55 @@ class Solder(object):
duration_points = dict()
rate_points = dict()
self.time = 0
used_steps = set()
for ix, pstep in enumerate(self.psteps):
#print "-- ", repr(pstep.name), pstep.temp, pstep.used, self.time, x, y
used_temp_levels = set()
for ix, temp_level in enumerate(self.temp_levels):
if temp_level != self.temp_levels[0] and temp_level not in used_temp_levels:
ix = self.temp_levels.index(temp_level)
raise ValueError("TempLevel %r not connected to %r" % (temp_level.name[ix-1], self.temp_levels[ix].name))
if pstep != self.psteps[0] and pstep not in used_steps:
ix = self.psteps.index(pstep)
raise Exception("step %r not connected to step %r or step %r" % (pstep.name, self.psteps[ix-1].name, self.psteps[ix+1].name))
psteps = None
temp_levels = None
duration = None
for sts, dur in self.durations:
if sts[0] == pstep:
if sts[0] == temp_level:
duration = dur
psteps = sts
temp_levels = sts
break
if pstep not in used_steps:
used_steps.add(pstep)
if temp_level not in used_temp_levels:
used_temp_levels.add(temp_level)
x.append(self.time)
y.append(pstep.temp)
y.append(temp_level.temp)
if duration is not None:
if len(psteps) == 3:
used_steps.add(psteps[1])
used_steps.add(psteps[2])
if len(temp_levels) == 3:
used_temp_levels.add(temp_levels[1])
used_temp_levels.add(temp_levels[2])
self.time += duration / 2
x.append(self.time)
y.append(psteps[1].temp)
#print "3er duration", (self.time, psteps[1].temp)
y.append(temp_levels[1].temp)
self.time += duration / 2
x.append(self.time)
y.append(psteps[2].temp)
y.append(temp_levels[2].temp)
duration_points[ix] = (x[-3:], y[-3:])
#print "3er duration", (self.time, psteps[2].temp)
else:
y.append(psteps[1].temp)
used_steps.add(psteps[1])
y.append(temp_levels[1].temp)
used_temp_levels.add(temp_levels[1])
self.time += duration
x.append(self.time)
duration_points[ix] = (x[-2:], y[-2:])
#print "2er duration", (self.time, psteps[1].temp)
else:
for ex, (sts, rate) in enumerate(self.rates):
if sts[0] == pstep:
used_steps.add(sts[1])
duration = (sts[1].temp - pstep.temp) / rate
if sts[0] == temp_level:
used_temp_levels.add(sts[1])
duration = (sts[1].temp - temp_level.temp) / rate
self.time += duration
x.append(self.time)
y.append(sts[1].temp)
#print "rate", (self.time, sts[1].temp)
rate_points[ex] = (x[-2:], y[-2:])
return array(map(float, x)), array(map(float, y)), max(x), max(y), duration_points, rate_points
@ -151,27 +152,43 @@ class Solder(object):
def unpack(filename):
xmltree = etree.parse(filename)
root = xmltree.getroot()
s = Solder()
s.name = root[0].attrib["name"]
for state in root[0].findall("state"):
s.add_state(state.attrib["name"], int(state.attrib["temperature"]))
for duration in root[0].findall("duration"):
states = list()
for state in duration:
states.append(s.get_state(state.attrib["name"]))
s.add_duration(states, int(duration.attrib["value"]))
for rate in root[0].findall("rate"):
#print rate
states = list()
for state in rate:
states.append(s.get_state(state.attrib["name"]))
s.add_rate(states, int(rate.attrib["value"]))
solder_node = root[0]
s = Solder(solder_node.attrib["name"], solder_node)
env_count = 0
for temp_level in solder_node.findall("state"):
tstr = temp_level.attrib["temperature"]
is_env = False
try:
temp = int(tstr)
except ValueError:
if tstr == "$ENV":
temp = getTemperature()
is_env = True
env_count += 1
s.add_temp_level(temp_level.attrib["name"], temp, is_env)
colors = calc_colors(len(s.temp_levels) - 1)
ix = 0
for temp_level in s.temp_levels:
if not temp_level.is_env:
temp_level.color = colors[ix]
ix += 1
else:
temp_level.color = QtGui.QColor("black")
for duration in solder_node.findall("duration"):
temp_levels = list()
for temp_level in duration:
temp_levels.append(s.get_temp_level_by_name(temp_level.attrib["name"]))
s.add_duration(temp_levels, int(duration.attrib["value"]))
for rate in solder_node.findall("rate"):
temp_levels = list()
for temp_level in rate:
temp_levels.append(s.get_temp_level_by_name(temp_level.attrib["name"]))
s.add_rate(temp_levels, int(rate.attrib["value"]))
return s
def serialize(self, pstep_list):
return ", ".join(map(attrgetter("name"), pstep_list))
class SolderListModel(QtCore.QAbstractListModel):
def __init__(self, parent=None, *args):
@ -180,14 +197,17 @@ class SolderListModel(QtCore.QAbstractListModel):
super(SolderListModel, self).__init__(parent, *args)
dirname = os.path.join(os.path.dirname(__file__), "solder_types")
dirlisting = os.listdir(dirname)
dirlisting = filter(lambda x: os.path.splitext(x)[1] == ".xml", os.listdir(dirname))
self.listdata = []
for p in dirlisting:
#try:
self.listdata.append(Solder.unpack(os.path.join(dirname, p)))
#except Exception:
#except Exception, e:
#print e
#pass
print len(self.listdata)
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.listdata)
@ -204,10 +224,11 @@ class SolderListModel(QtCore.QAbstractListModel):
return QtCore.QVariant()
class PStepModel(QtCore.QAbstractTableModel):
def __init__(self, parent=None, *args):
super(PStepModel, self).__init__(parent, *args)
self.psteps = list()
class TempLevelModel(QtCore.QAbstractTableModel):
def __init__(self, parent):
super(TempLevelModel, self).__init__(parent)
self._changed = False
self.temp_levels = list()
self.headerdata = [u"Name", u"Temperature (°C)"]
def headerData(self, col, orientation, role):
@ -216,7 +237,7 @@ class PStepModel(QtCore.QAbstractTableModel):
return QtCore.QVariant()
def rowCount(self, parent):
return len(self.psteps)
return len(self.temp_levels)
def columnCount(self, parent):
return 2
@ -228,57 +249,79 @@ class PStepModel(QtCore.QAbstractTableModel):
if role == QtCore.Qt.DisplayRole:
col = index.column()
if col == 0:
return QtCore.QVariant(self.psteps[index.row()].name)
return QtCore.QVariant(self.temp_levels[index.row()].name)
else:
return QtCore.QVariant(self.psteps[index.row()].temp)
return QtCore.QVariant(self.temp_levels[index.row()].temp)
if index.column() == 0 and role == QtCore.Qt.DecorationRole:
p = QtGui.QPixmap(10,10)
cr = row = index.row()
color = index.row() in (0, len(self.psteps)-1) and QtGui.QColor("black") or QtGui.QColor(PSTEP_COLORS[cr-1])
color = self.temp_levels[index.row()].color
p.fill(color)
return p
return QtCore.QVariant()
def remove_pstep(self, index):
del self.psteps[index]
self.reset()
def flags(self, index):
if not index.isValid():
return 0
return QtCore.Qt.ItemFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable)
def add_pstep(self, index, pstep):
self.psteps.insert(index, pstep)
self.reset()
def setData(self, index, variant, role):
if index.isValid() and role == QtCore.Qt.EditRole:
col = index.column()
if col == 0:
self.temp_levels[index.row()].name = str(variant.toString())
elif col == 1:
self.temp_levels[index.row()].temp = variant.toInt()[0]
self._changed = True
return True
return False
def setSteps(self, steps):
assert isinstance(steps, list)
self.psteps = steps
def remove_temp_level(self, index):
tmp = self.temp_levels[index]
del self.temp_levels[index]
self.reset()
self._changed = True
return tmp
def add_temp_level(self, index, temp_level):
self.beginInsertRows(QtGui.QModelIndex(), index.row(), 1)
self.temp_levels.temp_levels.insert(index.row(), temp_level)
self.endInsertRows()
self.reset()
self._changed = True
def setTempLevels(self, temp_levels):
assert isinstance(temp_levels, list)
self.temp_levels = temp_levels
self.reset()
def clear(self):
self.temp_levels = list()
self.reset()
class MyDynamicMplCanvas(FigureCanvas):
class Plotter(FigureCanvas):
"""A canvas that updates itself every second with a new plot."""
def __init__(self, parent, myapp, width, height, dpi):
self.fig = Figure(figsize=(width, height), dpi=dpi)
super(MyDynamicMplCanvas, self).__init__(self.fig)
super(Plotter, self).__init__(self.fig)
self.axes = self.fig.add_subplot(111)
## We want the axes cleared every time plot() is called
self.axes.set_axis_bgcolor('black')
self.axes.set_title(u'reflow profile', size=12)
self.axes.set_xlabel(u'time (seconds)', size=12)
self.axes.set_ylabel(u'temperature (°C)', size=12)
#pylab.setp(self.axes.get_xticklabels(), fontsize=8)
#pylab.setp(self.axes.get_yticklabels(), fontsize=8)
self.axes.set_ymargin(0)
self.axes.set_xmargin(0)
self.setParent(parent)
self.myapp = myapp
self.solder = None
self.plot_data, = self.axes.plot([], linewidth=1.0, color=(0,0,1), zorder=10)
self.selection_data, = self.axes.plot([], linewidth=1.0, color=(1,1,1), zorder=5)
#self.selection_data, = self.axes.plot([], linewidth=1.0, color=(1,1,1), zorder=5)
FigureCanvas.setSizePolicy(self,
QtGui.QSizePolicy.Expanding,
@ -290,30 +333,24 @@ class MyDynamicMplCanvas(FigureCanvas):
self.counter = list()
QtCore.QObject.connect(timer, QtCore.SIGNAL("timeout()"), self.update_figure)
timer.start(1000)
self.updated = True
def update_figure(self):
#Build a list of 4 random integers between 0 and 10 (both inclusive)
x, y, xmax, ymax, duration_points, rate_points = self.solder.calc_profile()
lines = list()
legend = list()
if self.updated:
updated = False
self.x, self.y, self.xmax, self.ymax, self.duration_points, self.rate_points = self.solder.calc_profile()
#for states, value in self.durations.iteritems():
#annotation.slope_marker((states[0])
self.fig.lines = lines
self.axes.set_xbound(lower=0, upper=self.xmax + 20)
self.axes.set_ybound(lower=0, upper=self.ymax + 20)
self.axes.set_xbound(lower=0, upper=xmax + 20)
self.axes.set_ybound(lower=0, upper=ymax + 20)
self.axes.set_ymargin(0)
self.axes.set_xmargin(0)
self.axes.set_yticks([state.temp for state in self.solder.temp_levels])
self.axes.set_xticks(self.x)
self.axes.set_yticks([state.temp for state in self.solder.psteps])
self.axes.set_xticks(x)
self.plot_data.set_xdata(x)
self.plot_data.set_ydata(y)
self.plot_data.set_xdata(self.x)
self.plot_data.set_ydata(self.y)
self.plot_data.set_zorder(20)
duration_widget = self.myapp.duration_widget
@ -321,159 +358,317 @@ class MyDynamicMplCanvas(FigureCanvas):
#self.selection_data.set_xdata(array(da))
#self.selection_data.set_ydata(array(db))
for ix, i in enumerate(self.solder.psteps[1:-1]):
line = Line2D([0, xmax + 20], [i.temp, i.temp],
transform=self.axes.transData, figure=self.fig, color=self.solder.color(ix), label="name", zorder=1)
lines.append(line)
self.fig.lines = lines = list()
for temp_level in self.solder.temp_levels:
if not temp_level.is_env:
line = Line2D([0, self.xmax + 20], [temp_level.temp, temp_level.temp],
transform=self.axes.transData, figure=self.fig, color=str(temp_level.color.name()), label="name", zorder=1)
lines.append(line)
self.axes.legend(("Estimated profile",))
self.draw()
# contraint_list | label - checkboxes
# label - value
class AddRemoveWidget(QtGui.QWidget):
def __init__(self, parent, with_upown=True):
#super(AddRemoveWidget, self).__init__(parent)
QtGui.QWidget.__init__(self, parent)
self.add_button = QtGui.QPushButton("Add")
self.remove_button = QtGui.QPushButton("Remove")
sh = "QPushButton:disabled { background-color: #555555; }"
self.remove_button.setStyleSheet(sh)
self.add_button.setStyleSheet(sh)
self._layout = QtGui.QVBoxLayout(self)
self._layout.addWidget(self.add_button)
self._layout.addWidget(self.remove_button)
if with_upown:
self.up_button = QtGui.QPushButton("Up")
self.down_button = QtGui.QPushButton("Down")
self._layout.addWidget(self.up_button)
self._layout.addWidget(self.down_button)
self._layout.addStretch(4)
class AddRemoveValueWidget(AddRemoveWidget):
def __init__(self, parent):
super(AddRemoveValueWidget, self).__init__(parent)
self.value = QtGui.QSpinBox(self)
self.value.setRange(-500, 500)
self._layout.addWidget(self.value)
class ConstraintListModel(QtCore.QAbstractListModel):
def __init__(self, parent=None, *args):
""" datain: a list where each item is a row
"""
super(ConstraintListModel, self).__init__(parent, *args)
self.constraint_list = list()
def rowCount(self, parent=QtCore.QModelIndex()):
return len(self.constraint_list)
def headerData(self, col, orientation, role):
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
return QtCore.QVariant("Solder Paste")
return QtCore.QVariant()
def data(self, index, role):
if index.isValid() and role == QtCore.Qt.DisplayRole:
return QtCore.QVariant(index.row() + 1)
else:
return QtCore.QVariant()
def append_constraint(self):
self.constraint_list.append([[], 0])
self.reset()
def remove_constraint(self):
del self.constraint_list[self.currentIndex().row()]
self.reset()
class ConstraintWidget(QtGui.QWidget):
def __init__(self, name):
def __init__(self, name, solder):
super(ConstraintWidget, self).__init__()
self.name = name
self.solder = None
#self.solder = solder
self.spinbox_block = False
self.value = QtGui.QSpinBox(self)
self.value.setRange(-300, 400)
self.constraint_model = QtGui.QStringListModel(self) # constraint selection
self.all_psteps = PStepModel(self) # pstep selection pool
self.selected_psteps = PStepModel(self) # selected psteps
self.constraint_model = ConstraintListModel(self) # constraint selection
self.all_temp_levels = TempLevelModel(self) # temp_level selection pool
self.selected_temp_levels = TempLevelModel(self) # selected temp_levels
#self.all_psteps.setSteps(self.solder.psteps)
self.controls = AddRemoveValueWidget(self)
self.constraint_controls = AddRemoveWidget(self, False)
self.add_button = QtGui.QPushButton("Add", self)
self.remove_button = QtGui.QPushButton("Remove", self)
self.controls.add_button.setText(u"Add TempLevel")
self.controls.remove_button.setText(u"Remove TempLevel")
bg = QtGui.QWidget(self)
gbl = QtGui.QVBoxLayout(bg)
self.constraint_controls.add_button.setText(u"Add Constraint")
self.constraint_controls.remove_button.setText(u"Remove Constraint")
gbl.addWidget(self.add_button)
gbl.addWidget(self.remove_button)
gbl.addStretch(5)
gbl.addWidget(self.value)
self.constraint_view = QtGui.QListView(self)
self.constraint_view.setModel(self.constraint_model)
self.all_temp_levels_view = QtGui.QListView(self)
self.all_temp_levels_view.setModel(self.all_temp_levels)
self.constraint_list_view = QtGui.QListView(self)
self.constraint_list_view.setModel(self.constraint_model)
self.all_psteps_view = QtGui.QListView(self)
self.all_psteps_view.setModel(self.all_psteps)
self.selected_psteps_view = QtGui.QListView(self)
self.selected_psteps_view.setModel(self.selected_psteps)
#self.left = QtGui.QWidget(self)
#gl = QtGui.QGridLayout(self.left)
#gl.addWidget(QtGui.QLabel(u"Steps"), 0,0)
#gl.addWidget(QtGui.QLabel(name), 1,0)
#gl.addWidget(self.checkboxes_group, 0, 1)
#gl.addWidget(self.value, 1, 1)
#self.gl = gl
self.selected_temp_levels_view = QtGui.QListView(self)
self.selected_temp_levels_view.setModel(self.selected_temp_levels)
h = QtGui.QHBoxLayout()
h.addWidget(self.constraint_list_view)
h.addWidget(self.all_psteps_view)
h.addWidget(bg)
h.addWidget(self.selected_psteps_view)
h.addWidget(self.constraint_view, 1)
h.addWidget(self.constraint_controls, 1)
h.addWidget(self.all_temp_levels_view, 3)
h.addWidget(self.controls, 1)
h.addWidget(self.selected_temp_levels_view, 3)
self.setLayout(h)
self.connect(
self.constraint_list_view,
self.constraint_view,
QtCore.SIGNAL("clicked(QModelIndex)"),
self.constraint_clicked)
self._constraint_selected)
self.connect(
self.add_button,
self.controls.add_button,
QtCore.SIGNAL("clicked()"),
self.add_constraint)
self.add_temp_level_to_constraint)
self.connect(
self.remove_button,
self.controls.remove_button,
QtCore.SIGNAL("clicked()"),
self.remove_temp_level_from_constraint)
self.connect(
self.controls.up_button,
QtCore.SIGNAL("clicked()"),
self.temp_level_up)
self.connect(
self.controls.down_button,
QtCore.SIGNAL("clicked()"),
self.temp_level_down)
self.connect(
self.constraint_controls.add_button,
QtCore.SIGNAL("clicked()"),
self.constraint_model.append_constraint)
self.connect(
self.constraint_controls.remove_button,
QtCore.SIGNAL("clicked()"),
self.remove_constraint)
self.connect(
self.controls.value,
QtCore.SIGNAL("valueChanged(int)"),
self.constraint_value_changed)
def setData(self, solder):
print self.setData, 1
self.solder = solder
self.all_psteps.setSteps(self.solder.psteps)
self.getConstraints()
print self.setData, 2
self.all_temp_levels.setTempLevels(self.solder.temp_levels)
print self.setData, 3
self._set_data()
print self.setData, 4
def constraint_clicked(self, index):
def _constraint_selected(self, index):
raise NotImplementedError()
def getConstraints(self):
def _set_data(self):
raise NotImplementedError()
def add_constraint(self):
raise NotImplementedError()
def add_temp_level_to_constraint(self):
src_row = self.all_temp_levels_view.currentIndex().row()
dst_row = self.selected_temp_levels_view.currentIndex().row()
temp_level = self.all_temp_levels.temp_levels[src_row]
self.selected_temp_levels.temp_levels.insert(dst_row, temp_level)
#tls.append(temp_level)
#tls.sort(key=attrgetter("temp"))
self.selected_temp_levels.reset()
self.selected_temp_levels_view.clearSelection()
def remove_temp_level_from_constraint(self):
del self.selected_temp_levels.temp_levels[self.selected_temp_levels_view.currentIndex().row()]
self.selected_temp_levels.reset()
self.selected_temp_levels_view.clearSelection()
def remove_constraint(self):
raise NotImplementedError()
src_row = self.all_temp_levels_view.currentIndex().row()
del self.constraint_model.constraint_list[src_row]
self.constraint_model.reset()
self.selected_temp_levels.clear()
def constraint_value_changed(self, value):
print self.constraint_value_changed
if self.spinbox_block:
self.spinbox_block = False
return
print
print
print "IIIIEK"
print
src_index = self.constraint_view.currentIndex().row()
self.constraint_model.constraint_list[src_index][1] = value
def slot_temp_level_removed(self, temp_level):
print "temp_level"
self.reset()
def temp_level_up(self):
dst_row = self.selected_temp_levels_view.currentIndex().row()
self.selected_temp_levels.temp_levels[dst_row - 1], self.selected_temp_levels.temp_levels[dst_row] = self.selected_temp_levels.temp_levels[dst_row], self.selected_temp_levels.temp_levels[dst_row - 1]
self.selected_temp_levels.reset()
def temp_level_down(self):
dst_row = self.selected_temp_levels_view.currentIndex().row()
self.selected_temp_levels.temp_levels[dst_row], self.selected_temp_levels.temp_levels[dst_row + 1] = self.selected_temp_levels.temp_levels[dst_row + 1], self.selected_temp_levels.temp_levels[dst_row]
self.selected_temp_levels.reset()
class DurationConstraintWidget(ConstraintWidget):
def getConstraints(self):
tmp = QtCore.QStringList()
for ix in xrange(len(self.solder.durations)):
tmp << unicode(ix + 1)
def _set_data(self):
self.spinbox_block = True
print self._set_data, 1
self.constraint_model.constraint_list.extend(self.solder.durations)
print self._set_data, 2
ix = self.constraint_model.index(0, 0)
print self._set_data, 3
self.constraint_view.setCurrentIndex(ix)
print self._set_data, 4
self._constraint_selected(ix)
print self._set_data, 5
self.constraint_model.setStringList(tmp)
k, t = self.solder.durations[0]
self.value.setValue(t)
self.constraint_list_view.setCurrentIndex(self.constraint_model.index(0, 0))
self.constraint_clicked(self.constraint_model.index(0, 0))
def add_constraint(self):
self.selected_psteps.psteps.append(self.all_psteps.psteps[self.all_psteps_view.currentIndex().row()])
self.selected_psteps.reset()
#self.selected_psteps_view.setCurrentIndex(QtCore.QModelIndex())
self.selected_psteps_view.clearSelection()
def remove_constraint(self):
del self.selected_psteps.psteps[self.selected_psteps_view.currentIndex().row()]
self.selected_psteps.reset()
#self.selected_psteps_view.setCurrentIndex(QtCore.QModelIndex())
self.selected_psteps_view.clearSelection()
def constraint_clicked(self, index):
psteps, value = self.solder.durations[index.row()]
self.selected_psteps.setSteps(psteps)
self.value.setValue(value)
def _constraint_selected(self, index):
print self._constraint_selected
self.spinbox_block = True
temp_levels, value = self.constraint_model.constraint_list[index.row()]
self.selected_temp_levels.setTempLevels(temp_levels)
self.controls.value.setValue(value)
class RateConstraintWidget(ConstraintWidget):
def getConstraints(self):
tmp = QtCore.QStringList()
for ix in xrange(len(self.solder.durations)):
tmp << unicode(ix + 1)
def _set_data(self):
print self._set_data
self.spinbox_block = True
self.constraint_model.constraint_list.extend(self.solder.rates)
self.constraint_model.setStringList(tmp)
k, t = self.solder.rates[0]
ix = self.constraint_model.index(0, 0)
self.constraint_view.setCurrentIndex(ix)
self._constraint_selected(ix)
self.value.setValue(t)
self.constraint_list_view.setCurrentIndex(self.constraint_model.index(0, 0))
self.constraint_clicked(self.constraint_model.index(0, 0))
def _constraint_selected(self, index):
print self._constraint_selected
self.spinbox_block = True
temp_levels, value = self.constraint_model.constraint_list[index.row()]
self.selected_temp_levels.setTempLevels(temp_levels)
self.controls.value.setValue(value)
def constraint_clicked(self, index):
psteps, value = self.solder.durations[index.row()]
self.selected_psteps.setSteps(psteps)
self.value.setValue(value)
class TempLevelWidget(QtGui.QWidget):
temp_level_removed = QtCore.pyqtSignal(TempLevel)
def __init__(self, parent, solder):
super(TempLevelWidget, self).__init__(parent)
self.temp_level_model = TempLevelModel(self)
self.temp_level_view = QtGui.QTableView()
self.temp_level_view.setModel(self.temp_level_model)
self.temp_level_view.verticalHeader().setVisible(False)
self.temp_level_view.resizeColumnsToContents()
self.temp_level_view.horizontalHeader().setStretchLastSection(True)
self.temp_level_view.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
self.controls = AddRemoveWidget(self)
h = QtGui.QHBoxLayout()
h.addWidget(self.temp_level_view)
h.addWidget(self.controls)
self.setLayout(h)
self.connect(
self.temp_level_view,
QtCore.SIGNAL("clicked(QModelIndex)"),
self.temp_level_selected)
self.connect(
self.controls.remove_button,
QtCore.SIGNAL("clicked()"),
self.remove_temp_level)
def add_temp_level(self):
index = self.temp_level_view.currentIndex()
self.temp_level_model.add_temp_level(index,TempLevel("new", 0))
def remove_temp_level(self):
self.temp_level_removed.emit(
self.temp_level_model.remove_temp_level(
self.temp_level_view.currentIndex().row()))
def temp_level_selected(self, index):
if index.isValid():
row = index.row()
is_env = self.temp_level_model.temp_levels[row].is_env
is_end = row == len(self.temp_level_model.temp_levels) - 1
self.controls.add_button.setEnabled(not is_end)
self.controls.remove_button.setEnabled(not is_env)
print "remove_button state", self.controls.remove_button.isEnabled()
class ApplicationWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.dpi = 100
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.setWindowTitle("application main window")
@ -490,70 +685,64 @@ class ApplicationWindow(QtGui.QMainWindow):
self.help_menu.addAction('&About', self.about)
self.main_widget = QtGui.QWidget(self)
self.profile_widget = QtGui.QWidget(self)
self.tab_widget = QtGui.QTabWidget(self)
self.duration_widget = DurationConstraintWidget(u"Duration (s)")
self.rate_widget = RateConstraintWidget(u"Rate (°C/s)")
self.dpi = 100
pl = QtGui.QHBoxLayout(self.profile_widget)
self.solder_model = SolderListModel(self)
self.pstep_model = PStepModel(self)
self.pstep_view = QtGui.QTableView()
self.pstep_view.setModel(self.pstep_model)
self.pstep_view.verticalHeader().setVisible(False)
self.pstep_view.resizeColumnsToContents()
self.solder_view = QtGui.QListView()
self.solder_view.setModel(self.solder_model)
self.solder_controls = AddRemoveWidget(self, False)
self.tab_widget = QtGui.QTabWidget(self)
self.temp_level_widget = TempLevelWidget(self, self.solder_model.listdata[0])
self.duration_widget = DurationConstraintWidget(u"Duration (s)", self.solder_model.listdata[0])
self.rate_widget = RateConstraintWidget(u"Rate (°C/s)", self.solder_model.listdata[0])
self.tab_widget.addTab(self.temp_level_widget, u"Temperature Levels")
self.tab_widget.addTab(self.duration_widget, u"Duration (s)")
self.tab_widget.addTab(self.rate_widget, u"Rate (°C/s)")
self.connect(
self.solder_view,
QtCore.SIGNAL("clicked(QModelIndex)"),
self.solder_selected)
self.tab_widget.addTab(self.pstep_view, u"Temperature Steps")
self.tab_widget.addTab(self.duration_widget, u"Duration (s)")
self.tab_widget.addTab(self.rate_widget, u"Rate (°C/s)")
self.settings_widget = QtGui.QWidget(self)
pl = QtGui.QHBoxLayout(self.settings_widget)
pl.addWidget(self.solder_view, 1)
pl.addWidget(self.tab_widget, 7)
#pl.addWidget(self.duration_widget)
#pl.addWidget(self.rate_widget)
pl.addWidget(self.solder_controls, 1)
pl.addWidget(self.tab_widget, 6)
l = QtGui.QVBoxLayout(self.main_widget)
self.dc = MyDynamicMplCanvas(self, self, width=5, height=4, dpi=self.dpi)
self.splitter = QtGui.QSplitter(QtCore.Qt.Vertical, self)
self.plotter = Plotter(self, self, width=5, height=4, dpi=self.dpi)
self.solder_view.setCurrentIndex(self.solder_model.index(0,0))
self.solder_selected(self.solder_model.index(0,0))
l.addWidget(self.profile_widget, 2)
l.addWidget(self.dc, 8)
self.splitter.addWidget(self.settings_widget)
self.splitter.addWidget(self.plotter)
self.splitter.setStretchFactor(0, 2)
self.splitter.setStretchFactor(1, 8)
self.main_widget.setFocus()
self.setCentralWidget(self.main_widget)
self.setCentralWidget(self.splitter)
self.statusBar().showMessage("I'm in reflow heaven", 2000)
self.temp_level_widget.temp_level_removed.connect(self.duration_widget.slot_temp_level_removed)
self.temp_level_widget.temp_level_removed.connect(self.rate_widget.slot_temp_level_removed)
def solder_selected(self, index):
if index.isValid():
self.dc.solder = self.solder_model.listdata[index.row()]
self.pstep_model.setSteps(self.dc.solder.psteps)
self.pstep_view.resizeColumnsToContents()
self.duration_widget.setData(self.dc.solder)
self.rate_widget.setData(self.dc.solder)
solder = self.plotter.solder = self.solder_model.listdata[index.row()]
self.temp_level_widget.temp_level_model.setTempLevels(solder.temp_levels)
self.temp_level_widget.temp_level_view.resizeColumnsToContents()
self.duration_widget.setData(solder)
self.rate_widget.setData(solder)
self.plotter.updated = True
def save_plot(self):
file_choices = "PNG (*.png)|*.png"
filename = QtGui.QFileDialog.getSaveFileName(self, 'Save File', 'qtplot.png')
print type(filename), dir(filename)
self.dc.print_figure(str(filename), dpi=self.dpi)
self.plotter.print_figure(str(filename), dpi=self.dpi)
def fileQuit(self):
self.close()

View File

@ -1,11 +1,10 @@
<xml>
<solder_type name="lead noclean" description="">
<state name="start" temperature="25" />
<state name="environment temp" temperature="$ENV" />
<state name="preheat start" temperature="150" />
<state name="preheat end" temperature="185" />
<state name="tal" temperature="220" />
<state name="peak" temperature="260" />
<state name="end" temperature="25" />
<duration value="100" >
<state name="preheat start" />
<state name="preheat end" />
@ -16,7 +15,7 @@
<state name="tal" />
</duration>
<rate value="1">
<state name="start" />
<state name="environment temp" />
<state name="preheat start" />
</rate>
<rate value="1">
@ -29,7 +28,7 @@
</rate>
<rate value="-2">
<state name="peak" />
<state name="end" />
<state name="environment temp" />
</rate>
</solder_type>
</xml>

View File

@ -1,11 +1,10 @@
<xml>
<solder_type name="leadfree noclean" description="">
<state name="start" temperature="25" />
<state name="environment temp" temperature="$ENV" />
<state name="preheat start" temperature="150" />
<state name="preheat end" temperature="185" />
<state name="tal" temperature="220" />
<state name="peak" temperature="250" />
<state name="end" temperature="25" />
<duration value="100" >
<state name="preheat start" />
<state name="preheat end" />
@ -16,7 +15,7 @@
<state name="tal" />
</duration>
<rate value="1">
<state name="start" />
<state name="environment temp" />
<state name="preheat start" />
</rate>
<rate value="1">
@ -29,7 +28,7 @@
</rate>
<rate value="-2">
<state name="peak" />
<state name="end" />
<state name="environment temp" />
</rate>
</solder_type>
</xml>

View File

@ -9,8 +9,7 @@ from setuptools import find_packages, setup
if sys.version_info >= (3,):
extras['use_2to3'] = True
extras['convert_2to3_doctests'] = ['src/your/module/README.txt']
#extra['use_2to3_fixers'] = ['your.fixers']
setup(
name='reflowctl_gui',