From b494a9c05ebd58efb61a4f89789f0691dd52271c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20K=C3=B6gl?= Date: Thu, 22 Nov 2012 19:59:40 +0100 Subject: [PATCH] fixed selection issues after insert/remove ops, more about info, ... --- reflowctl/reflowctl_gui.py | 520 +++++++++++++++++++------------------ 1 file changed, 273 insertions(+), 247 deletions(-) diff --git a/reflowctl/reflowctl_gui.py b/reflowctl/reflowctl_gui.py index 2a5ef01..56601cd 100755 --- a/reflowctl/reflowctl_gui.py +++ b/reflowctl/reflowctl_gui.py @@ -104,6 +104,184 @@ class TempLevel(QtCore.QObject): self.is_env = is_env self.color = None +class TempLevelModel(QtCore.QAbstractTableModel): + solder_changed = QtCore.pyqtSignal() + + 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 + 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 == 0: + self.temp_levels[index.row()].name = str(variant.toString()) + elif col == 1: + self.temp_levels[index.row()].temp = variant.toInt()[0] + print "emit solder_changed" + 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 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 TempLevelWidget(QtGui.QWidget): + temp_level_removed = QtCore.pyqtSignal(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.add_temp_level) + + self.connect( + self.controls.remove_button, + QtCore.SIGNAL("clicked()"), + self.remove_temp_level) + + 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.temp_level_model, + QtCore.SIGNAL("solder_changed()"), + self._solder_changed) + + def _solder_changed(self): + print self._solder_changed + self.solder_changed.emit() + + + def setData(self, solder): + self.temp_level_model.setTempLevels(solder.temp_levels) + self.temp_level_view.resizeColumnsToContents() + + + def add_temp_level(self): + index = self.temp_level_view.currentIndex() + self.temp_level_model.add_temp_level(index, TempLevel("new " + str(self.temp_level_model.rowCount(None)), 0)) + self.temp_level_view.setCurrentIndex(self.temp_level_model.index(index.row() + 1, 0)) + + + def remove_temp_level(self): + self.temp_level_removed.emit( + self.temp_level_model.remove_temp_level( + self.temp_level_view.currentIndex().row())) + self.solder_changed.emit() + + def temp_level_up(self): + dst_row = self.temp_level_view.currentIndex().row() + self.temp_level_model.temp_levels[dst_row - 1], self.temp_level_model.temp_levels[dst_row] = self.temp_level_model.temp_levels[dst_row], self.temp_level_model.temp_levels[dst_row - 1] + self.temp_level_model.reset() + self.solder_changed.emit() + + def temp_level_down(self): + dst_row = self.selected_temp_levels_view.currentIndex().row() + self.temp_level_model.temp_levels[dst_row], self.temp_level_model.temp_levels[dst_row + 1] = self.temp_level_model.temp_levels[dst_row + 1], self.temp_level_model.temp_levels[dst_row] + self.temp_level_model.reset() + self.solder_changed.emit() + + + def temp_level_selected(self, index): + if index.isValid(): + row = index.row() + if not self.readonly: + 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) + class Solder(QtCore.QObject): @@ -282,9 +460,11 @@ class Solder(QtCore.QObject): rate.append(etree.Element("state", {"name" : temp_level.name})) solder_node.append(rate) - dirname = os.path.join(os.path.dirname(__file__), "solder_types") + dirname = SolderListModel.dirname() root = etree.Element("xml") root.append(solder_node) + if self.filename is None: + self.filename = os.path.join(dirname, self.name + ".xml") etree.ElementTree(root).write(self.filename, "UTF-8", True) self.changed = False @@ -306,7 +486,7 @@ class SolderListModel(QtCore.QAbstractListModel): return len(self.listdata) def reload(self): - dirname = os.path.join(os.path.dirname(__file__), "solder_types") + dirname = self.dirname() dirlisting = filter(lambda x: os.path.splitext(x)[1] == ".xml", os.listdir(dirname)) self.listdata = [] for p in dirlisting: @@ -345,92 +525,63 @@ class SolderListModel(QtCore.QAbstractListModel): return QtCore.Qt.ItemFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable) def create_solder(self): - solder = Solder("new", "") + solder = Solder(None, "new", "") tl = solder.add_temp_level("environment temp", getTemperature(), True) tl.color = QtGui.QColor(0, 0, 0) self.listdata.append(solder) self.reset() - -class TempLevelModel(QtCore.QAbstractTableModel): - solder_changed = QtCore.pyqtSignal() - - 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 - 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 == 0: - self.temp_levels[index.row()].name = str(variant.toString()) - elif col == 1: - self.temp_levels[index.row()].temp = variant.toInt()[0] - print "emit solder_changed" - 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 setTempLevels(self, temp_levels): - assert isinstance(temp_levels, list) - self.temp_levels = temp_levels - self.reset() + @staticmethod + def dirname(): + return os.path.join(os.path.dirname(__file__), "solder_types") + - def clear(self): - self.temp_levels = list() - self.reset() +class SolderWidget(QtGui.QWidget): + def __init__(self, parent, readonly=False): + super(SolderWidget, self).__init__(parent) + self.solder_model = SolderListModel(self) + self.solder_view = QtGui.QListView() + self.solder_view.setModel(self.solder_model) + self.solder_controls = AddRemoveWidget(self, False) + + layout = QtGui.QHBoxLayout(self) + layout.addWidget(self.solder_view, 3) + layout.addWidget(self.solder_controls, 1) + + + self.connect( + self.solder_controls.add_button, + QtCore.SIGNAL("clicked()"), + self.solder_model.create_solder) + + self.connect( + self.solder_controls.remove_button, + QtCore.SIGNAL("clicked()"), + self.remove_solder) + + self.solder_view.setCurrentIndex(self.solder_model.index(0,0)) + + def remove_solder(self): + index = self.solder_view.currentIndex() + solder = self.solder_model.listdata[index.row()] + try: + os.remove(solder.filename) + except OSError, e: + print e + pass + del self.solder_model.listdata[index.row()] + self.solder_model.reset() + new_index = self.solder_model.index(0) + self.solder_view.setCurrentIndex(new_index) + return new_index + + def save_solder(self, index): + self.solder_model.listdata[index.row()].save() + self.solder_model.reset() + new_index = self.solder_model.index(self.solder_model.listdata.index(self.plotter.solder)) + self.solder_widget.solder_view.setCurrentIndex(new_index) class Plotter(FigureCanvas): @@ -475,21 +626,25 @@ class Plotter(FigureCanvas): self.updated = False def update_figure(self): - self.fig.lines = lines = list() if self.updated: + self.fig.lines = lines = list() self.updated = False self.axes.patches = list() self.axes.texts = list() self.x = list() self.y = list() - self.x, self.y, self.xmin, self.xmax, self.ymin, self.ymax, self.used, self.unused = self.solder.calc_profile() + try: + self.x, self.y, self.xmin, self.xmax, self.ymin, self.ymax, self.used, self.unused = self.solder.calc_profile() + except ValueError: + self.x, self.y, self.xmin, self.xmax, self.ymin, self.ymax, self.used, self.unused = [], [], 0., 300., 0., 300., [], self.solder.temp_levels self.plot_data.set_xdata(self.x) self.plot_data.set_ydata(self.y) self.axes.set_xbound(lower=self.xmin, upper=self.xmax + 20) self.axes.set_ybound(lower=self.ymin, upper=self.ymax + 20) + self.axes.set_xlim(self.xmin, self.xmax + 20, auto=True) self.axes.set_yticks(self.y) self.axes.set_xticks(self.x) @@ -502,16 +657,15 @@ class Plotter(FigureCanvas): self.axes.legend(("Estimated profile",), loc=2) - 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) + 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.draw() + self.draw() def solder_changed(self): - print self.solder_changed self.solder.setChanged() self.updated = True @@ -700,9 +854,10 @@ class ConstraintWidget(QtGui.QWidget): self.controls.up_button.setEnabled(True) self.controls.down_button.setEnabled(True) - def add_constraint(self): self.constraint_model.append_constraint() + new_index = self.constraint_model.rowCount() - 1 + self.constraint_view.setCurrentIndex(self.constraint_model.index(new_index, 0)) self.set_controls() self.solder_changed.emit() @@ -789,6 +944,28 @@ class DurationConstraintWidget(ConstraintWidget): self.controls.value.setValue(0) +class RateConstraintWidget(ConstraintWidget): + + def _set_data(self, solder): + self.spinbox_block = True + self.constraint_model.constraint_list = solder.rates + self.constraint_model.reset() + ix = self.constraint_model.index(0, 0) + self._constraint_selected(ix) + self.constraint_view.setCurrentIndex(ix) + + + def _constraint_selected(self, index): + if index.isValid(): + 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) + else: + self.spinbox_block = True + self.selected_temp_levels.setTempLevels([]) + self.controls.value.setValue(0) + class OvenControlsWidget(QtGui.QWidget): def __init__(self, parent=None): @@ -850,148 +1027,6 @@ class OvenControlsWidget(QtGui.QWidget): self.start_button.setIcon(self.sicon) -class RateConstraintWidget(ConstraintWidget): - - def _set_data(self, solder): - self.spinbox_block = True - self.constraint_model.constraint_list = solder.rates - self.constraint_model.reset() - ix = self.constraint_model.index(0, 0) - self._constraint_selected(ix) - self.constraint_view.setCurrentIndex(ix) - - - def _constraint_selected(self, index): - if index.isValid(): - 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) - else: - self.spinbox_block = True - self.selected_temp_levels.setTempLevels([]) - self.controls.value.setValue(0) - -class SolderWidget(QtGui.QWidget): - def __init__(self, parent, readonly=False): - super(SolderWidget, self).__init__(parent) - self.solder_model = SolderListModel(self) - self.solder_view = QtGui.QListView() - self.solder_view.setModel(self.solder_model) - self.solder_controls = AddRemoveWidget(self, False) - - layout = QtGui.QHBoxLayout(self) - layout.addWidget(self.solder_view, 3) - layout.addWidget(self.solder_controls, 1) - - - self.connect( - self.solder_controls.add_button, - QtCore.SIGNAL("clicked()"), - self.solder_model.create_solder) - - self.solder_view.setCurrentIndex(self.solder_model.index(0,0)) - - -class TempLevelWidget(QtGui.QWidget): - temp_level_removed = QtCore.pyqtSignal(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.add_temp_level) - - self.connect( - self.controls.remove_button, - QtCore.SIGNAL("clicked()"), - self.remove_temp_level) - - 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.temp_level_model, - QtCore.SIGNAL("solder_changed()"), - self._solder_changed) - - def _solder_changed(self): - print self._solder_changed - self.solder_changed.emit() - - - def setData(self, solder): - self.temp_level_model.setTempLevels(solder.temp_levels) - self.temp_level_view.resizeColumnsToContents() - - - def add_temp_level(self): - index = self.temp_level_view.currentIndex() - self.temp_level_model.add_temp_level(index, TempLevel("new " + str(self.temp_level_model.rowCount(None)), 0)) - self.temp_level_view.setCurrentIndex(self.temp_level_model.index(index.row() + 1, 0)) - self.plotter.solder.changed = True - self.solder_changed.emit() - - - def remove_temp_level(self): - self.temp_level_removed.emit( - self.temp_level_model.remove_temp_level( - self.temp_level_view.currentIndex().row())) - self.solder_changed.emit() - - def temp_level_up(self): - dst_row = self.temp_level_view.currentIndex().row() - self.temp_level_model.temp_levels[dst_row - 1], self.temp_level_model.temp_levels[dst_row] = self.temp_level_model.temp_levels[dst_row], self.temp_level_model.temp_levels[dst_row - 1] - self.temp_level_model.reset() - self.solder_changed.emit() - - def temp_level_down(self): - dst_row = self.selected_temp_levels_view.currentIndex().row() - self.temp_level_model.temp_levels[dst_row], self.temp_level_model.temp_levels[dst_row + 1] = self.temp_level_model.temp_levels[dst_row + 1], self.temp_level_model.temp_levels[dst_row] - self.temp_level_model.reset() - self.solder_changed.emit() - - - def temp_level_selected(self, index): - if index.isValid(): - row = index.row() - if not self.readonly: - 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) class Report(QtGui.QWidget): @@ -1071,8 +1106,6 @@ class ApplicationWindow(QtGui.QMainWindow): self.controls_widget = OvenControlsWidget(self) self.controls_widget.setVisible(False) - - self.connect( self.duration_widget, QtCore.SIGNAL("solder_changed()"), @@ -1131,7 +1164,7 @@ class ApplicationWindow(QtGui.QMainWindow): self.setCentralWidget(self.splitter) - self.statusBar().showMessage("I'm in reflow heaven", 2000) + self.statusBar().showMessage("Reflow GORE!1!", 10000) 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) @@ -1161,14 +1194,7 @@ class ApplicationWindow(QtGui.QMainWindow): solder.log_message.connect(self.profile_log.setPlainText) def remove_solder(self): - index = self.solder_widget.solder_view.currentIndex() - solder = self.solder_widget.solder_model.listdata[index.row()] - del self.solder_widget.solder_model.listdata[index.row()] - self.solder_widget.solder_model.reset() - new_index = self.solder_widget.solder_model.index(0) - self.solder_widget.solder_view.setCurrentIndex(new_index) - self.solder_selected(new_index) - os.remove(solder.filename) + self.solder_selected(self.solder_widget.remove_solder()) def open_controls_view(self): self.controls_widget.show() @@ -1186,7 +1212,9 @@ class ApplicationWindow(QtGui.QMainWindow): def save_solder(self): self.plotter.solder.save() - self.solder_widget.solder_model.reload() + self.solder_widget.solder_model.reset() + new_index = self.solder_widget.solder_model.index(self.solder_widget.solder_model.listdata.index(self.plotter.solder)) + self.solder_widget.solder_view.setCurrentIndex(new_index) def reload_solder(self): old_index = self.solder_widget.solder_view.currentIndex() @@ -1205,9 +1233,7 @@ class ApplicationWindow(QtGui.QMainWindow): def about(self): QtGui.QMessageBox.about(self, "About %s" % progname, - u"%(prog)s version %(version)s\n" \ - u"Copyright \N{COPYRIGHT SIGN} 2012 Stefan Kögl\n\n" \ - u"reflowctl frontend" % {"prog": progname, "version": progversion}) + QtCore.QString(u"%(prog)s version %(version)s
Copyright \N{COPYRIGHT SIGN} 2012 Stefan Kögl

reflowctl frontend

Special thanks to Chaostreff Dortmund" % {"prog": progname, "version": progversion})) def main():