reflow/reflowctl/edge_widget.py

244 lines
7.8 KiB
Python

# -*- coding: utf-8 -*-
from PyQt4 import QtGui, QtCore
class Edge(QtCore.QObject):
def __init__(self, from_tl, to_tl, duration=None, rate=None):
super(Edge, self).__init__(None)
self.from_tl = from_tl
self.to_tl = to_tl
self.duration = duration
self.rate = rate
def contains(self, temp_level):
return (
(self.from_tl.temp < temp_level.temp < self.to_tl.temp) or
(self.from_tl.temp > temp_level.temp > self.to_tl.temp))
def has_from_tl(self, temp_level):
return self.from_tl == temp_level
def has_to_tl(self, temp_level):
return self.to_tl == temp_level
def __repr__(self):
return "Edge(%r, %r, %r, %r)" % (self.from_tl, self.to_tl, self.duration, self.rate)
class EdgeModel(QtCore.QAbstractTableModel):
edge_changed = QtCore.pyqtSignal()
def __init__(self, parent):
super(EdgeModel, self).__init__(parent)
self.edges = list()
self.headerdata = [
u"From Temperature (°C)",
u"To Temperature (°C)",
u"Duration (s)",
u"Rate (°C/s)"]
def headerData(self, col, orientation, role):
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
return QtCore.QVariant(self.headerdata[col])
return QtCore.QVariant()
def rowCount(self, parent):
return len(self.edges)
def columnCount(self, parent):
return 4
def data(self, index, role):
if not index.isValid():
return QtCore.QVariant()
col = index.column()
if role == QtCore.Qt.DisplayRole:
if col == 0:
return QtCore.QVariant(self.edges[index.row()].from_tl.name)
elif col == 1:
return QtCore.QVariant(self.edges[index.row()].to_tl.name)
elif col == 2:
return QtCore.QVariant(self.edges[index.row()].duration)
elif col == 3:
return QtCore.QVariant(self.edges[index.row()].rate)
if index.column() < 2 and role == QtCore.Qt.DecorationRole:
p = QtGui.QPixmap(10,10)
if col == 0:
p.fill(self.edges[index.row()].from_tl.color)
elif col == 1:
p.fill(self.edges[index.row()].to_tl.color)
return p
return QtCore.QVariant()
def flags(self, index):
if not index.isValid():
return 0
return QtCore.Qt.ItemFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable)
def setData(self, index, variant, role):
if index.isValid() and role == QtCore.Qt.EditRole:
col = index.column()
if col == 2:
self.edges[index.row()].duration = variant.toFloat()[0]
elif col == 3:
self.edges[index.row()].rate = variant.toFloat()[0]
self.edge_changed.emit()
return True
return False
def remove_edge(self, index):
tmp = self.edges[index]
del self.edges[index]
self.reset()
self.edge_changed.emit()
return tmp
def add_edge(self, index, edge):
self.edges.insert(index.row() + 1, edge)
self.reset()
self.edge_changed.emit()
def setTempLevels(self, edges):
assert isinstance(edges, list)
self.edges = edges
self.reset()
def clear(self):
self.edges = list()
self.reset()
def get_edge(self, ix):
return self.edges[ix]
class EdgeWidget(QtGui.QWidget):
edge_changed = QtCore.pyqtSignal()
def __init__(self, name):
super(EdgeWidget, self).__init__()
self.name = name
self.edge_model = EdgeModel(self)
self.edge_view = QtGui.QTableView(self)
self.edge_view.setModel(self.edge_model)
self.edge_view.verticalHeader().setVisible(False)
self.edge_view.resizeColumnsToContents()
self.edge_view.horizontalHeader().setStretchLastSection(True)
self.edge_view.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
h = QtGui.QHBoxLayout(self)
h.addWidget(self.edge_view)
def edge_picked(self, ix):
self.edge_view.setCurrentIndex(self.edge_model.index(ix, 0))
def setData(self, solder):
self.solder = solder
self.edge_model.setTempLevels(solder.edges)
self.edge_view.setCurrentIndex(self.edge_model.index(0,0))
self.connect(
self.edge_model,
QtCore.SIGNAL("edge_changed()"),
self._edge_changed)
def _edge_changed(self):
self.edge_changed.emit()
def make_closed(self):
first_edge = self.edge_model.edges[0]
last_edge = self.edge_model.edges[-1]
if not first_edge.from_tl == last_edge.to_tl:
self.edge_model.edges.append(Edge(last_edge.to_tl, first_edge.from_tl, None, -1))
def temp_level_removed(self, temp_level):
from_ix = None
to_ix = None
edges = self.edge_model.edges
end = len(edges)
def helper(start, end):
for i in xrange(start, end):
edge = edges[i]
if edge.from_tl == temp_level:
return i
for ix, edge in enumerate(self.edge_model.edges):
if edge.to_tl == temp_level:
from_ix = ix
to_ix = helper(ix, end)
for i in range(to_ix, from_ix-1, -1):
self.edge_model.edges.pop(i)
self.edge_model.reset()
def temp_level_added(self, old_tl, new_tl):
new_edges = list()
ix = 0
batch = list()
#for edge in self.edge_model.edges:
#if edge.contains(new_tl):
#batch.append(edge)
#if not batch:
def find_in_to(edges):
for edge in edges:
if old_tl == edge.to_tl:
yield edge
def find_in_from(edges):
for edge in edges:
if old_tl == edge.from_tl:
yield edge
for edge in find_in_to(self.edge_model.edges):
batch.append(edge)
for return_edge in find_in_from(self.edge_model.edges[self.edge_model.edges.index(edge):]):
batch.append(return_edge)
for edge in batch:
if edge.from_tl == old_tl:
new_edge = Edge(new_tl, old_tl, None, -1)
ix = self.edge_model.edges.index(edge)
self.edge_model.edges.insert(ix, new_edge)
elif edge.to_tl == old_tl:
new_edge = Edge(old_tl, new_tl, None, 1)
ix = self.edge_model.edges.index(edge)
self.edge_model.edges.insert(ix+1, new_edge)
if not batch:
self.edge_model.edges.append(Edge(old_tl, new_tl, None, 1))
self.make_closed()
self.edge_model.reset()
self.edge_changed.emit()
#for edge in batch:
#if edge.from_tl < new_tl:
#duration = None if edge.duration is None else edge.duration / 2
#new_edge = Edge(new_tl, edge.to_tl, duration, edge.rate)
#edge.duration = duration
#edge.to_tl = new_tl
#ix = self.edge_model.edges.index(edge)
#self.edge_model.edges.insert(ix+1, new_edge)
#elif edge.from_tl > new_tl:
#duration = None if edge.duration is None else edge.duration / 2
#new_edge = Edge(new_tl, edge.to_tl, duration, edge.rate)
#edge.duration = duration
#edge.to_tl = new_tl
#ix = self.edge_model.edges.index(edge)
#self.edge_model.edges.insert(ix+1, new_edge)
#else:
#raise Exception("cannot make an edge")
#self.make_closed()
#self.edge_model.reset()
#self.edge_changed.emit()