class Editor(QDialog): """Basic scene editor.""" def __init__(self, parent: MainWindow, renderers: List[Renderer]) -> None: """Initialize the Editor.""" super().__init__(parent=parent) self.renderers = renderers self.tree_widget = QTreeWidget() self.tree_widget.setHeaderHidden(True) self.stacked_widget = QStackedWidget() self.layout = QHBoxLayout() self.layout.addWidget(self.tree_widget) self.layout.addWidget(self.stacked_widget) def _selection_callback() -> None: for item in self.tree_widget.selectedItems(): widget_idx = item.data(0, Qt.ItemDataRole.UserRole) self.stacked_widget.setCurrentIndex(widget_idx) self.tree_widget.itemSelectionChanged.connect(_selection_callback) self.setLayout(self.layout) self.setWindowTitle("Editor") self.setModal(True) self.update() def update(self) -> None: """Update the internal widget list.""" self.tree_widget.clear() for idx, renderer in enumerate(self.renderers): actors = renderer._actors # pylint: disable=protected-access widget_idx = self.stacked_widget.addWidget( _get_renderer_widget(renderer)) top_item = QTreeWidgetItem(self.tree_widget, ["Renderer {}".format(idx)]) top_item.setData(0, Qt.ItemDataRole.UserRole, widget_idx) self.tree_widget.addTopLevelItem(top_item) for name, actor in actors.items(): if actor is not None: widget_idx = self.stacked_widget.addWidget( _get_actor_widget(actor)) child_item = QTreeWidgetItem(top_item, [name]) child_item.setData(0, Qt.ItemDataRole.UserRole, widget_idx) top_item.addChild(child_item) self.tree_widget.expandAll() def toggle(self) -> None: """Toggle the editor visibility.""" self.update() if self.isVisible(): self.hide() else: self.show()
class AlgorithmMonitorDialog(QDialog): """ Displays progress of all running algorithms. """ def __init__(self, parent, model): super(AlgorithmMonitorDialog, self).__init__(parent) self.tree = QTreeWidget(self) self.tree.setColumnCount(3) self.tree.setSelectionMode(QTreeWidget.NoSelection) self.tree.setColumnWidth(0, 220) self.tree.setHeaderLabels(['Algorithm', 'Progress', '']) header = self.tree.header() header.setSectionResizeMode(1, QHeaderView.Stretch) header.setSectionResizeMode(2, QHeaderView.Fixed) header.setStretchLastSection(False) button_layout = QHBoxLayout() self.close_button = QPushButton('Close') button_layout.addStretch() button_layout.addWidget(self.close_button) layout = QVBoxLayout() layout.addWidget(self.tree) layout.addLayout(button_layout) self.setLayout(layout) self.setWindowTitle('Mantid - Algorithm progress') self.setWindowIcon(QIcon(":/MantidPlot_Icon_32offset.png")) self.resize(500, 300) self.presenter = AlgorithmProgressDialogPresenter(self, model) self.presenter.update_gui() def update(self, data): """ Update the gui elements. :param data: Data in format of AlgorithmProgressModel.get_running_algorithm_data() """ self.tree.clear() for alg_data in data: name, id, properties = alg_data item = QTreeWidgetItem([name]) self.tree.addTopLevelItem(item) progress_bar = QProgressBar() progress_bar.setAlignment(Qt.AlignHCenter) self.presenter.add_progress_bar(id, progress_bar) cancel_button = CancelButton(self.presenter, id) self.tree.setItemWidget(item, 1, progress_bar) self.tree.setItemWidget(item, 2, cancel_button) for prop in properties: item.addChild(QTreeWidgetItem(prop))
class AlgorithmMonitorDialog(QDialog): """ Displays progress of all running algorithms. """ def __init__(self, parent, model): super(AlgorithmMonitorDialog, self).__init__(parent) self.tree = QTreeWidget(self) self.tree.setColumnCount(3) self.tree.setSelectionMode(QTreeWidget.NoSelection) self.tree.setColumnWidth(0, 220) self.tree.setHeaderLabels(['Algorithm', 'Progress', '']) header = self.tree.header() header.setSectionResizeMode(1, QHeaderView.Stretch) header.setSectionResizeMode(2, QHeaderView.Fixed) header.setStretchLastSection(False) button_layout = QHBoxLayout() self.close_button = QPushButton('Close') button_layout.addStretch() button_layout.addWidget(self.close_button) layout = QVBoxLayout() layout.addWidget(self.tree) layout.addLayout(button_layout) self.setLayout(layout) self.setWindowTitle('Mantid - Algorithm progress') self.setWindowIcon(QIcon(":/MantidPlot_Icon_32offset.png")) self.resize(500, 300) self.presenter = AlgorithmProgressDialogPresenter(self, model) self.presenter.update_gui() def update(self, data): """ Update the gui elements. :param data: Data in format of AlgorithmProgressModel.get_running_algorithm_data() """ self.tree.clear() for alg_data in data: name, id, properties = alg_data item = QTreeWidgetItem([name]) self.tree.addTopLevelItem(item) progress_bar = QProgressBar() progress_bar.setAlignment(Qt.AlignHCenter) self.presenter.add_progress_bar(id, progress_bar) cancel_button = CancelButton(self.presenter, id) self.tree.setItemWidget(item, 1, progress_bar) self.tree.setItemWidget(item, 2, cancel_button) for prop in properties: item.addChild(QTreeWidgetItem(prop))
class SystemLog(PyDMFrame): def __init__(self, parent=None, init_channel=None): PyDMFrame.__init__(self, parent, init_channel) self._systemLog = None self._node = None def connection_changed(self, connected): build = (self._node is None) and (self._connected != connected and connected is True) super(SystemLog, self).connection_changed(connected) if not build: return self._node = nodeFromAddress(self.channel) self._path = self.channel.replace('SystemLog', 'ClearLog') vb = QVBoxLayout() self.setLayout(vb) gb = QGroupBox('System Log (20 most recent entries)') vb.addWidget(gb) vb = QVBoxLayout() gb.setLayout(vb) self._systemLog = QTreeWidget() vb.addWidget(self._systemLog) self._systemLog.setColumnCount(2) self._systemLog.setHeaderLabels(['Field', 'Value']) self._systemLog.setColumnWidth(0, 200) self._pb = PyDMPushButton(label='Clear Log', pressValue=1, init_channel=self._path) vb.addWidget(self._pb) def value_changed(self, new_val): lst = json.loads(new_val) self._systemLog.clear() # Show only the last 20 entries # In the future we can consider a pop up dialog with the full log. # Unclear if that is neccessary. for ent in lst[-20:]: widget = QTreeWidgetItem(self._systemLog) widget.setText( 0, time.strftime("%Y-%m-%d %H:%M:%S %Z", time.localtime(ent['created']))) widget.setText(1, ent['message']) widget.setExpanded(False) widget.setTextAlignment(0, Qt.AlignTop) temp = QTreeWidgetItem(widget) temp.setText(0, 'Name') temp.setText(1, str(ent['name'])) temp.setTextAlignment(0, Qt.AlignRight) temp = QTreeWidgetItem(widget) temp.setText(0, 'Level') temp.setText( 1, '{} ({})'.format(ent['levelName'], ent['levelNumber'])) temp.setTextAlignment(0, Qt.AlignRight) if ent['exception'] is not None: exc = QTreeWidgetItem(widget) exc.setText(0, 'exception') exc.setText(1, str(ent['exception'])) exc.setExpanded(False) exc.setTextAlignment(0, Qt.AlignRight) for v in ent['traceBack']: temp = QTreeWidgetItem(exc) temp.setText(0, '') temp.setText(1, v)
class ReactionMask(QWidget): """The input mask for a reaction""" def __init__(self, parent: ReactionList): QWidget.__init__(self) self.parent = parent self.reaction = None self.is_valid = True self.changed = False self.setAcceptDrops(False) layout = QVBoxLayout() l = QHBoxLayout() self.delete_button = QPushButton("Delete reaction") self.delete_button.setIcon(QIcon.fromTheme("edit-delete")) policy = QSizePolicy() policy.ShrinkFlag = True self.delete_button.setSizePolicy(policy) l.addWidget(self.delete_button) layout.addItem(l) l = QHBoxLayout() label = QLabel("Id:") self.id = QLineEdit() l.addWidget(label) l.addWidget(self.id) layout.addItem(l) l = QHBoxLayout() label = QLabel("Name:") self.name = QLineEdit() l.addWidget(label) l.addWidget(self.name) layout.addItem(l) l = QHBoxLayout() label = QLabel("Equation:") self.equation = QLineEdit() l.addWidget(label) l.addWidget(self.equation) layout.addItem(l) l = QHBoxLayout() label = QLabel("Rate min:") self.lower_bound = QLineEdit() l.addWidget(label) l.addWidget(self.lower_bound) layout.addItem(l) l = QHBoxLayout() label = QLabel("Rate max:") self.upper_bound = QLineEdit() l.addWidget(label) l.addWidget(self.upper_bound) layout.addItem(l) l = QHBoxLayout() label = QLabel("Coefficient in obj. function:") self.coefficent = QLineEdit() l.addWidget(label) l.addWidget(self.coefficent) layout.addItem(l) l = QHBoxLayout() label = QLabel("Gene reaction rule:") self.gene_reaction_rule = QLineEdit() l.addWidget(label) l.addWidget(self.gene_reaction_rule) layout.addItem(l) l = QVBoxLayout() label = QLabel("Annotations:") l.addWidget(label) l2 = QHBoxLayout() self.annotation = QTableWidget(0, 2) self.annotation.setHorizontalHeaderLabels( ["key", "value"]) self.annotation.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) l2.addWidget(self.annotation) self.add_anno = QPushButton("+") self.add_anno.clicked.connect(self.add_anno_row) l2.addWidget(self.add_anno) l.addItem(l2) layout.addItem(l) l = QVBoxLayout() label = QLabel("Metabolites involved in this reaction:") l.addWidget(label) l2 = QHBoxLayout() self.metabolites = QTreeWidget() self.metabolites.setHeaderLabels(["Id"]) self.metabolites.setSortingEnabled(True) l2.addWidget(self.metabolites) l.addItem(l2) self.metabolites.itemDoubleClicked.connect( self.emit_jump_to_metabolite) layout.addItem(l) self.jump_list = JumpList(self) layout.addWidget(self.jump_list) self.setLayout(layout) self.delete_button.clicked.connect(self.delete_reaction) self.throttler = SignalThrottler(500) self.throttler.triggered.connect(self.reaction_data_changed) self.id.textEdited.connect(self.throttler.throttle) self.name.textEdited.connect(self.throttler.throttle) self.equation.textEdited.connect(self.throttler.throttle) self.lower_bound.textEdited.connect(self.throttler.throttle) self.upper_bound.textEdited.connect(self.throttler.throttle) self.coefficent.textEdited.connect(self.throttler.throttle) self.gene_reaction_rule.textEdited.connect(self.throttler.throttle) self.annotation.itemChanged.connect(self.throttler.throttle) self.validate_mask() def add_anno_row(self): i = self.annotation.rowCount() self.annotation.insertRow(i) self.changed = True def apply(self): try: self.reaction.id = self.id.text() except ValueError: turn_red(self.id) QMessageBox.information( self, 'Invalid id', 'Could not apply changes identifier ' + self.id.text() + ' already used.') else: self.reaction.name = self.name.text() self.reaction.build_reaction_from_string(self.equation.text()) self.reaction.lower_bound = float(self.lower_bound.text()) self.reaction.upper_bound = float(self.upper_bound.text()) self.reaction.objective_coefficient = float(self.coefficent.text()) self.reaction.gene_reaction_rule = self.gene_reaction_rule.text() self.reaction.annotation = {} rows = self.annotation.rowCount() for i in range(0, rows): key = self.annotation.item(i, 0).text() if self.annotation.item(i, 1) is None: value = "" else: value = self.annotation.item(i, 1).text() self.reaction.annotation[key] = value self.changed = False self.reactionChanged.emit(self.reaction) def delete_reaction(self): self.hide() self.reactionDeleted.emit(self.reaction) def validate_id(self): with self.parent.appdata.project.cobra_py_model as model: try: r = cobra.Reaction(id=self.id.text()) model.add_reaction(r) except ValueError: turn_red(self.id) return False else: turn_white(self.id) return True def validate_name(self): with self.parent.appdata.project.cobra_py_model as model: try: r = cobra.Reaction(id="testid", name=self.name.text()) model.add_reaction(r) except ValueError: turn_red(self.name) return False else: turn_white(self.name) return True def validate_equation(self): ok = False test_reaction = cobra.Reaction( "xxxx_cnapy_test_reaction", name="cnapy test reaction") with self.parent.appdata.project.cobra_py_model as model: model.add_reaction(test_reaction) try: eqtxt = self.equation.text().rstrip() if len(eqtxt) > 0 and eqtxt[-1] == '+': turn_red(self.equation) else: test_reaction.build_reaction_from_string(eqtxt) turn_white(self.equation) ok = True except ValueError: turn_red(self.equation) try: test_reaction = self.parent.appdata.project.cobra_py_model.reactions.get_by_id( "xxxx_cnapy_test_reaction") self.parent.appdata.project.cobra_py_model.remove_reactions( [test_reaction], remove_orphans=True) except KeyError: pass return ok def validate_lowerbound(self): try: _x = float(self.lower_bound.text()) except ValueError: turn_red(self.lower_bound) return False else: turn_white(self.lower_bound) return True def validate_upperbound(self): try: _x = float(self.upper_bound.text()) except ValueError: turn_red(self.upper_bound) return False else: turn_white(self.upper_bound) return True def validate_coefficient(self): try: _x = float(self.coefficent.text()) except ValueError: turn_red(self.coefficent) return False else: turn_white(self.coefficent) return True def validate_gene_reaction_rule(self): try: _x = float(self.gene_reaction_rule.text()) except ValueError: turn_red(self.gene_reaction_rule) return False else: turn_white(self.gene_reaction_rule) return True def validate_mask(self): valid_id = self.validate_id() valid_name = self.validate_name() valid_equation = self.validate_equation() valid_lb = self.validate_lowerbound() valid_ub = self.validate_upperbound() valid_coefficient = self.validate_coefficient() if valid_id & valid_name & valid_equation & valid_lb & valid_ub & valid_coefficient: self.is_valid = True else: self.is_valid = False def reaction_data_changed(self): self.changed = True self.validate_mask() if self.is_valid: self.apply() self.update_state() def update_state(self): self.jump_list.clear() for name, m in self.parent.appdata.project.maps.items(): if self.id.text() in m["boxes"]: self.jump_list.add(name) self.metabolites.clear() if self.parent.appdata.project.cobra_py_model.reactions.has_id(self.id.text()): reaction = self.parent.appdata.project.cobra_py_model.reactions.get_by_id( self.id.text()) for m in reaction.metabolites: item = QTreeWidgetItem(self.metabolites) item.setText(0, m.id) item.setText(1, m.name) item.setData(2, 0, m) text = "Id: " + m.id + "\nName: " + m.name item.setToolTip(1, text) def emit_jump_to_map(self, name): self.jumpToMap.emit(name, self.id.text()) def emit_jump_to_metabolite(self, metabolite): self.jumpToMetabolite.emit(str(metabolite.data(2, 0))) jumpToMap = Signal(str, str) jumpToMetabolite = Signal(str) reactionChanged = Signal(cobra.Reaction) reactionDeleted = Signal(cobra.Reaction)
class MetabolitesMask(QWidget): """The input mask for a metabolites""" def __init__(self, appdata): QWidget.__init__(self) self.appdata = appdata self.metabolite = None self.is_valid = True self.changed = False self.setAcceptDrops(False) layout = QVBoxLayout() l = QHBoxLayout() label = QLabel("Id:") self.id = QLineEdit() l.addWidget(label) l.addWidget(self.id) layout.addItem(l) l = QHBoxLayout() label = QLabel("Name:") self.name = QLineEdit() l.addWidget(label) l.addWidget(self.name) layout.addItem(l) l = QHBoxLayout() label = QLabel("Formula:") self.formula = QLineEdit() l.addWidget(label) l.addWidget(self.formula) layout.addItem(l) l = QHBoxLayout() label = QLabel("Charge:") self.charge = QLineEdit() l.addWidget(label) l.addWidget(self.charge) layout.addItem(l) l = QHBoxLayout() label = QLabel("Compartment:") self.compartment = QLineEdit() l.addWidget(label) l.addWidget(self.compartment) layout.addItem(l) l = QVBoxLayout() label = QLabel("Annotations:") l.addWidget(label) l2 = QHBoxLayout() self.annotation = QTableWidget(0, 2) self.annotation.setHorizontalHeaderLabels( ["key", "value"]) self.annotation.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) l2.addWidget(self.annotation) self.add_anno = QPushButton("+") self.add_anno.clicked.connect(self.add_anno_row) l2.addWidget(self.add_anno) l.addItem(l2) layout.addItem(l) l = QVBoxLayout() label = QLabel("Reactions using this metabolite:") l.addWidget(label) l2 = QHBoxLayout() self.reactions = QTreeWidget() self.reactions.setHeaderLabels(["Id"]) self.reactions.setSortingEnabled(True) l2.addWidget(self.reactions) l.addItem(l2) self.reactions.itemDoubleClicked.connect(self.emit_jump_to_reaction) layout.addItem(l) self.setLayout(layout) self.throttler = SignalThrottler(500) self.throttler.triggered.connect(self.metabolites_data_changed) self.id.textEdited.connect(self.throttler.throttle) self.name.textEdited.connect(self.throttler.throttle) self.formula.textEdited.connect(self.throttler.throttle) self.charge.textEdited.connect(self.throttler.throttle) self.compartment.textEdited.connect(self.throttler.throttle) self.annotation.itemChanged.connect(self.throttler.throttle) self.validate_mask() def add_anno_row(self): i = self.annotation.rowCount() self.annotation.insertRow(i) self.changed = True def apply(self): try: self.metabolite.id = self.id.text() except ValueError: turn_red(self.id) QMessageBox.information( self, 'Invalid id', 'Could not apply changes identifier ' + self.id.text()+' already used.') else: self.metabolite.name = self.name.text() self.metabolite.formula = self.formula.text() if self.charge.text() == "": self.metabolite.charge = None else: self.metabolite.charge = int(self.charge.text()) self.metabolite.compartment = self.compartment.text() self.metabolite.annotation = {} rows = self.annotation.rowCount() for i in range(0, rows): key = self.annotation.item(i, 0).text() if self.annotation.item(i, 1) is None: value = "" else: value = self.annotation.item(i, 1).text() self.metabolite.annotation[key] = value self.changed = False self.metaboliteChanged.emit(self.metabolite) def validate_id(self): with self.appdata.project.cobra_py_model as model: text = self.id.text() if text == "": turn_red(self.id) return False if ' ' in text: turn_red(self.id) return False try: m = cobra.Metabolite(id=self.id.text()) model.add_metabolites([m]) except ValueError: turn_red(self.id) return False else: turn_white(self.id) return True def validate_name(self): with self.appdata.project.cobra_py_model as model: try: m = cobra.Metabolite(id="test_id", name=self.name.text()) model.add_metabolites([m]) except ValueError: turn_red(self.name) return False else: turn_white(self.name) return True def validate_formula(self): return True def validate_charge(self): try: if self.charge.text() != "": _x = int(self.charge.text()) except ValueError: turn_red(self.charge) return False else: turn_white(self.charge) return True def validate_compartment(self): try: if ' ' in self.compartment.text(): turn_red(self.compartment) return False if '-' in self.compartment.text(): turn_red(self.compartment) return False _m = cobra.Metabolite(id="test_id", name=self.compartment.text()) except ValueError: turn_red(self.compartment) return False else: turn_white(self.compartment) return True def validate_mask(self): valid_id = self.validate_id() valid_name = self.validate_name() valid_formula = self.validate_formula() valid_charge = self.validate_charge() valid_compartment = self.validate_compartment() if valid_id & valid_name & valid_formula & valid_charge & valid_compartment: self.is_valid = True else: self.is_valid = False def metabolites_data_changed(self): self.changed = True self.validate_mask() if self.is_valid: self.apply() self.update_state() def update_state(self): self.reactions.clear() if self.appdata.project.cobra_py_model.metabolites.has_id(self.id.text()): metabolite = self.appdata.project.cobra_py_model.metabolites.get_by_id( self.id.text()) for r in metabolite.reactions: item = QTreeWidgetItem(self.reactions) item.setText(0, r.id) item.setText(1, r.name) item.setData(2, 0, r) text = "Id: " + r.id + "\nName: " + r.name item.setToolTip(1, text) def emit_jump_to_reaction(self, reaction): self.jumpToReaction.emit(reaction.data(2, 0).id) jumpToReaction = Signal(str) metaboliteChanged = Signal(cobra.Metabolite)
class MetaboliteList(QWidget): """A list of metabolites""" def __init__(self, appdata: CnaData): QWidget.__init__(self) self.appdata = appdata self.last_selected = None self.metabolite_list = QTreeWidget() self.metabolite_list.setHeaderLabels(["Id", "Name"]) self.metabolite_list.setSortingEnabled(True) for m in self.appdata.project.cobra_py_model.metabolites: self.add_metabolite(m) self.metabolite_list.setContextMenuPolicy(Qt.CustomContextMenu) self.metabolite_list.customContextMenuRequested.connect( self.on_context_menu) # create context menu self.pop_menu = QMenu(self.metabolite_list) in_out_fluxes_action = QAction( 'compute in/out fluxes for this metabolite', self.metabolite_list) self.pop_menu.addAction(in_out_fluxes_action) in_out_fluxes_action.triggered.connect(self.emit_in_out_fluxes_action) self.metabolite_mask = MetabolitesMask(appdata) self.metabolite_mask.hide() self.layout = QVBoxLayout() self.layout.setContentsMargins(0, 0, 0, 0) self.splitter = QSplitter() self.splitter.setOrientation(Qt.Vertical) self.splitter.addWidget(self.metabolite_list) self.splitter.addWidget(self.metabolite_mask) self.layout.addWidget(self.splitter) self.setLayout(self.layout) self.metabolite_list.currentItemChanged.connect( self.metabolite_selected) self.metabolite_mask.metaboliteChanged.connect( self.handle_changed_metabolite) self.metabolite_mask.jumpToReaction.connect( self.emit_jump_to_reaction) def clear(self): self.metabolite_list.clear() self.metabolite_mask.hide() def add_metabolite(self, metabolite): item = QTreeWidgetItem(self.metabolite_list) item.setText(0, metabolite.id) item.setText(1, metabolite.name) item.setData(2, 0, metabolite) def on_context_menu(self, point): if len(self.appdata.project.cobra_py_model.metabolites) > 0: self.pop_menu.exec_(self.mapToGlobal(point)) def update_annotations(self, annotation): self.metabolite_mask.annotation.itemChanged.disconnect( self.metabolite_mask.throttler.throttle) c = self.metabolite_mask.annotation.rowCount() for i in range(0, c): self.metabolite_mask.annotation.removeRow(0) i = 0 for key in annotation: self.metabolite_mask.annotation.insertRow(i) keyl = QTableWidgetItem(key) iteml = QTableWidgetItem(str(annotation[key])) self.metabolite_mask.annotation.setItem(i, 0, keyl) self.metabolite_mask.annotation.setItem(i, 1, iteml) i += 1 self.metabolite_mask.annotation.itemChanged.connect( self.metabolite_mask.throttler.throttle) def handle_changed_metabolite(self, metabolite: cobra.Metabolite): # Update metabolite item in list root = self.metabolite_list.invisibleRootItem() child_count = root.childCount() for i in range(child_count): item = root.child(i) if item.data(2, 0) == metabolite: old_id = item.text(0) item.setText(0, metabolite.id) item.setText(1, metabolite.name) break self.last_selected = self.metabolite_mask.id.text() self.metaboliteChanged.emit(old_id, metabolite) def update_selected(self, string): root = self.metabolite_list.invisibleRootItem() child_count = root.childCount() for i in range(child_count): item = root.child(i) item.setHidden(True) for item in self.metabolite_list.findItems(string, Qt.MatchContains, 0): item.setHidden(False) for item in self.metabolite_list.findItems(string, Qt.MatchContains, 1): item.setHidden(False) def metabolite_selected(self, item, _column): if item is None: self.metabolite_mask.hide() else: self.metabolite_mask.show() metabolite: cobra.Metabolite = item.data(2, 0) self.metabolite_mask.metabolite = metabolite self.metabolite_mask.id.setText(metabolite.id) self.metabolite_mask.name.setText(metabolite.name) self.metabolite_mask.formula.setText(metabolite.formula) if metabolite.charge is None: pass else: self.metabolite_mask.charge.setText(str(metabolite.charge)) self.metabolite_mask.compartment.setText(metabolite.compartment) self.update_annotations(metabolite.annotation) self.metabolite_mask.changed = False turn_white(self.metabolite_mask.id) turn_white(self.metabolite_mask.name) turn_white(self.metabolite_mask.formula) turn_white(self.metabolite_mask.charge) turn_white(self.metabolite_mask.compartment) self.metabolite_mask.is_valid = True self.metabolite_mask.update_state() def update(self): self.metabolite_list.clear() for m in self.appdata.project.cobra_py_model.metabolites: self.add_metabolite(m) if self.last_selected is None: pass else: items = self.metabolite_list.findItems( self.last_selected, Qt.MatchExactly) for i in items: self.metabolite_list.setCurrentItem(i) break def set_current_item(self, key): self.last_selected = key self.update() def emit_jump_to_reaction(self, reaction): self.jumpToReaction.emit(reaction) def emit_in_out_fluxes_action(self): self.computeInOutFlux.emit(self.metabolite_list.currentItem().text(0)) itemActivated = Signal(str) metaboliteChanged = Signal(str, cobra.Metabolite) jumpToReaction = Signal(str) computeInOutFlux = Signal(str)