# -*- 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()