class ExposureWidget(QtGui.QWidget): table_attrs = [ {'addBtn': 0, 'delBtn': 0, 'viewclass': CustomTableView}, {'addBtn': 1, 'delBtn': 1, 'viewclass': CustomTableView}, {'addBtn': 1, 'delBtn': 1, 'viewclass': CustomTableView}, {'addBtn': 1, 'delBtn': 1, 'viewclass': CustomTableView}, {'addBtn': 1, 'delBtn': 1, 'viewclass': CustomTableView}, {'addBtn': 1, 'delBtn': 1, 'viewclass': CustomTableView}, ] def __init__(self, tableset, nrmlfile, parent=None): QtGui.QWidget.__init__(self, parent) self.tableset = tableset self.nrmlfile = nrmlfile self.message_bar = MessageBar(nrmlfile, self) self.tables = [tableset.tableExposure, tableset.tableCostType, tableset.tableLocation, tableset.tableAsset, tableset.tableCost, tableset.tableOccupancy] self.tv = collections.OrderedDict() for table, attr in zip(self.tables, self.table_attrs): table.attr.update(attr) tv = attr['viewclass'](table, self.getdefault) if len(table) == 0: # hide empty tables tv.hide() tv.tableModel.validationFailed.connect( lambda idx, err, tv=tv: self.show_validation_error(tv, idx, err)) self.tv[table.name] = tv self.setupUi() self.tv['tableLocation'].tableView.clicked.connect( self.show_asset) self.tv['tableAsset'].tableView.clicked.connect( self.show_cost_occupancy) def setupUi(self): layout = QtGui.QVBoxLayout() hlayout1 = QtGui.QHBoxLayout() hlayout2 = QtGui.QHBoxLayout() layout.addWidget(self.message_bar) hlayout1.addWidget(self.tv['tableExposure']) hlayout1.addWidget(self.tv['tableCostType']) hlayout1.addWidget(self.tv['tableLocation']) layout.addLayout(hlayout1) hlayout2.addWidget(self.tv['tableAsset']) hlayout2.addWidget(self.tv['tableCost']) hlayout2.addWidget(self.tv['tableOccupancy']) layout.addLayout(hlayout2) self.setLayout(layout) self.setSizePolicy( QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.MinimumExpanding) self.tv['tableAsset'].tableView.hideColumn(0) self.tv['tableCost'].tableView.hideColumn(0) self.tv['tableOccupancy'].tableView.hideColumn(0) self.tv['tableLocation'].tableView.hideColumn(0) self.show_asset(index(0, 0)) self.show_cost_occupancy(index(0, 0)) @QtCore.pyqtSlot(QtCore.QModelIndex, Exception) def show_validation_error(self, table_view, index, error): record = table_view.tableModel.table[index.row()] fieldname = record.fields[index.column()].name message = '%s: %s' % (fieldname, error) self.message_bar.show_message(message) def show_asset(self, row): # show only the assets at the given location try: loc_id, = self.tv['tableLocation'].tableModel.primaryKey(row) except IndexError: # empty table, nothing to show return self.tv['tableAsset'].showOnCondition( lambda rec: rec['location_id'] == loc_id) # reset Cost and Occupancy self.tv['tableCost'].showOnCondition(lambda rec: False) self.tv['tableOccupancy'].showOnCondition(lambda rec: False) def show_cost_occupancy(self, row): try: asset_ref, = self.tv['tableAsset'].tableModel.primaryKey(row) except IndexError: # empty table, nothing to show return # show only the rows corresponding to asset_ref self.tv['tableCost'].showOnCondition( lambda rec: rec['asset_ref'] == asset_ref) # show only the rows corresponding to asset_ref self.tv['tableOccupancy'].showOnCondition( lambda rec: rec['asset_ref'] == asset_ref) def getdefault(self, table): if table.name == 'tableAsset': return self.tv['tableLocation'].current_record()[:1] elif table.name in ('tableCost', 'tableOccupancy'): return [self.tv['tableAsset'].current_record()[1]] else: return []
class TripleTableWidget(QtGui.QWidget): table_attrs = [ {'addBtn': 1, 'delBtn': 1}, {'addBtn': 1, 'delBtn': 1}, {'addBtn': 1, 'delBtn': 1}, ] def __init__(self, tableset, nrmlfile, parent=None): QtGui.QWidget.__init__(self, parent) self.tableset = tableset self.nrmlfile = nrmlfile self.message_bar = MessageBar(nrmlfile, self) self.init_tv() # this goes before setupUi self.setupUi() def init_tv(self): self.tv = collections.OrderedDict() n_attrs = len(self.table_attrs) n_tables = len(self.tableset.tables) if n_attrs != n_tables: raise RuntimeError('There are %d tables but %d table attributes!' % (n_tables, n_attrs)) for i, (attr, table) in enumerate( zip(self.table_attrs, self.tableset.tables)): table.attr.update(attr) self.tv[table.name] = CustomTableView(table, self.getdefault, self) self.tv[i] = self.tv[table.name] # signals self.tv[LEFT].tableView.clicked.connect(self.show_right) self.tv[RIGHT].tableView.clicked.connect(self.show_down) for tv in self.tv.values(): tv.tableModel.validationFailed.connect( lambda idx, err, tv=tv: self.show_validation_error(tv, idx, err)) # hide primary key columns self.tv[RIGHT].tableView.hideColumn(0) self.tv[DOWN].tableView.hideColumn(0) self.tv[DOWN].tableView.hideColumn(1) def getdefault(self, table): # return the primary key tuple partially filled, depending on # the currently selected rows ordinal = table.ordinal if not ordinal: # top left table return [] return self.tv[ordinal - 1].current_record()[:ordinal] def plot(self, records, x_field, y_field, label): can_plot = Figure and records if can_plot: xs = [rec[x_field] for rec in records] ys = [rec[y_field] for rec in records] self.axes.clear() self.axes.grid(True) self.axes.plot(xs, ys, label=label) self.axes.legend(loc='upper left') self.canvas.draw() def reset_plot(self): if Figure: self.axes.clear() self.axes.grid(True) self.canvas.draw() def setupUi(self): layout = QtGui.QVBoxLayout() hlayout1 = QtGui.QHBoxLayout() hlayout2 = QtGui.QHBoxLayout() layout.addWidget(self.message_bar) hlayout1.addWidget(self.tv[LEFT]) hlayout1.addWidget(self.tv[RIGHT]) layout.addLayout(hlayout1) hlayout2.addWidget(self.tv[DOWN]) if Figure: # matplotlib is available self.fig = Figure() self.axes = self.fig.add_subplot(111) self.canvas = FigureCanvasQTAgg(self.fig) self.canvas.setParent(self) hlayout2.addWidget(self.canvas) layout.addLayout(hlayout2) self.setLayout(layout) self.setSizePolicy( QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.MinimumExpanding) # display table 1 and table 2 as if rows 0 and 0 where selected self.show_right(index(0, 0)) self.show_down(index(0, 0)) @QtCore.pyqtSlot(QtCore.QModelIndex, Exception) def show_validation_error(self, table_view, index, error): record = table_view.tableModel.table[index.row()] fieldname = record.fields[index.column()].name message = '%s: %s' % (fieldname, error) self.message_bar.show_message(message) def show_right(self, index): try: k0, = self.tv[LEFT].tableModel.primaryKey(index) except IndexError: # empty table, nothing to show return # show only the rows in table 1 corresponding to k0 self.tv[RIGHT].showOnCondition(lambda rec: rec[0] == k0) # table 2 must disappear because no index in table 1 is selected self.tv[DOWN].showOnCondition(lambda rec: False) self.reset_plot() def show_down(self, index): # show only the rows in table 2 corresponding to k0 and k1 try: k0, k1 = self.tv[RIGHT].tableModel.primaryKey(index) except IndexError: # empty table, nothing to show return self.tv[DOWN].showOnCondition( lambda rec: rec[0] == k0 and rec[1] == k1) self.plot([rec for rec in self.tableset.tables[2] if rec[0] == k0 and rec[1] == k1], 'IML', 'lossRatio', '%s-%s' % (k0, k1))