# -*- coding: utf-8 -*- from PyQt4 import QtGui, QtCore from control_widgets import AddRemoveWidget def calc_colors(count): if count == 1: return [QtGui.QColor(0, 255, 0),] r = 0 g = 255 step = int(512. / (count-1)) colors = list() for i in range(count): colors.append(QtGui.QColor(r, g, 0)) if r < 255: r += step if r > 255: g -= (r - 256) r = 255 g = max(0, g) else: g -= step g = max(0, g) return colors def set_colors(temp_levels): colors = calc_colors(len(temp_levels) - 1) ix = 0 for temp_level in temp_levels: if not temp_level.is_env: temp_level.color = colors[ix] ix += 1 else: temp_level.color = QtGui.QColor("black") class TempLevel(QtCore.QObject): def __init__(self, name, temp, is_env=False): super(TempLevel, self).__init__() self.name = name self.temp = temp self.is_env = is_env self.color = None def __str__(self): return "" % (self.name, self.temp) def __lt__(self, other): return self.temp < other.temp def __le__(self, other): return self.temp <= other.temp def __eq__(self, other): return self.temp == other.temp def is_between(self, tl1, tl2): tmp = [tl1, tl2, self] tmp.sort() return self == tmp[1] def set_next(self, temp_level): if temp_level is self: raise ValueError("same temp_level") self.next = temp_level def __repr__(self): return "TempLevel(%r, %r, %r)" % (self.name, self.temp, self.is_env) class TempLevelModel(QtCore.QAbstractTableModel): solder_changed = QtCore.pyqtSignal() status_message = QtCore.pyqtSignal(QtCore.QString, int) 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): 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.temp_levels) def columnCount(self, parent): return 2 def data(self, index, role): if not index.isValid(): return QtCore.QVariant() if role == QtCore.Qt.DisplayRole: col = index.column() if col == 0: return QtCore.QVariant(self.temp_levels[index.row()].name) else: return QtCore.QVariant(self.temp_levels[index.row()].temp) if index.column() == 0 and role == QtCore.Qt.DecorationRole: p = QtGui.QPixmap(10, 10) color = self.temp_levels[index.row()].color p.fill(color) return p return QtCore.QVariant() def flags(self, index): if not index.isValid(): return 0 if index.row() != 0: return QtCore.Qt.ItemFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable) else: return QtCore.Qt.ItemFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable) def neigbors(self, temp_level): ix = self.temp_levels.index(temp_level) return self.temp_levels[ix-1], self.temp_levels[ix+1] 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 = unicode(variant.toString()) elif col == 1: temp, res = variant.toInt() tl = self.temp_levels[index.row()] try: tl0 = self.temp_levels[index.row() - 1] if tl0.temp >= temp: self.status_message.emit(QtCore.QString(u"Error: TempLevel %r cannot be moved across TempLevel %r!" % (tl.name, tl0.name)), 10000) return False except Exception, e: pass try: tl1 = self.temp_levels[index.row() + 1] if tl1.temp <= temp: self.status_message.emit(QtCore.QString(u"Error: TempLevel %r cannot be moved across TempLevel %r!" % (tl.name, tl1.name)), 10000) return False except Exception, e: pass tl.temp = temp self.solder_changed.emit() return True return False def remove_temp_level(self, index): tmp = self.temp_levels[index] del self.temp_levels[index] self.reset() self.solder_changed.emit() return tmp def add_temp_level(self, index, temp_level): self.temp_levels.insert(index.row() + 1, temp_level) set_colors(self.temp_levels) self.reset() self.solder_changed.emit() def append_temp_level(self, temp_level): self.temp_levels.append(temp_level) set_colors(self.temp_levels) self.reset() self.solder_changed.emit() 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() def get_temp_level(self, ix): return self.temp_levels[ix] class TempLevelWidget(QtGui.QWidget): temp_level_removed = QtCore.pyqtSignal(TempLevel) temp_level_added = QtCore.pyqtSignal(TempLevel, TempLevel) solder_changed = QtCore.pyqtSignal() def __init__(self, parent, readonly=False): super(TempLevelWidget, self).__init__(parent) self.readonly = readonly 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) h = QtGui.QHBoxLayout() h.addWidget(self.temp_level_view) self.setLayout(h) self.connect( self.temp_level_view, QtCore.SIGNAL("clicked(QModelIndex)"), self.temp_level_selected) if not readonly: self.controls = AddRemoveWidget(self) h.addWidget(self.controls) self.connect( self.controls.add_button, QtCore.SIGNAL("clicked()"), self.append_temp_level) self.connect( self.controls.remove_button, QtCore.SIGNAL("clicked()"), self.remove_temp_level) self.connect( self.temp_level_model, QtCore.SIGNAL("solder_changed()"), self._solder_changed) def _solder_changed(self): self.solder_changed.emit() def setData(self, solder): self.temp_level_model.setTempLevels(solder.temp_levels) self.temp_level_view.resizeColumnsToContents() self.temp_level_view.setCurrentIndex(self.temp_level_model.index(0, 0)) def add_temp_level(self): pass #new_temp = old_tl.temp + (self.temp_level_model.temp_levels[index.row() + 1].temp - old_tl.temp) / 2 def append_temp_level(self): old_tl = self.temp_level_model.temp_levels[-1] new_temp = old_tl.temp + 20 ix = self.temp_level_model.rowCount(None) new_tl = TempLevel("new " + str(ix), new_temp) self.temp_level_model.append_temp_level(new_tl) self.temp_level_view.setCurrentIndex(self.temp_level_model.index(ix, 0)) self.temp_level_added.emit(old_tl, new_tl) def remove_temp_level(self): self.temp_level_removed.emit( self.temp_level_model.remove_temp_level( self.temp_level_model.rowCount(None) - 1)) self.solder_changed.emit() self.temp_level_view.setCurrentIndex(self.temp_level_model.index(self.temp_level_model.rowCount(None) - 1, 0)) def temp_level_selected(self, index): if index.isValid(): row = index.row() if not self.readonly: self.controls.remove_button.setEnabled(not self.temp_level_model.temp_levels[row].is_env)