Beispiel #1
0
class ImportDialog(QDialog):
    def __init__(self, import_dict, local_dict, viewer, parent=None):
        """
        :type import_dict: dict[str, object]
        :type local_dict: dict[str, object]
        :param import_dict:
        :param local_dict:
        :param viewer:
        """
        super().__init__(parent=parent)
        self.setWindowTitle("Import")
        self.viewer = viewer()
        self.local_viewer = viewer()
        self.import_dict = import_dict
        self.local_dict = local_dict
        conflicts = set(local_dict.keys()) & set(import_dict.keys())
        # print(conflicts)

        self.list_view = QTreeWidget()
        self.list_view.setColumnCount(4)
        self.radio_group_list = []
        self.checked_num = len(import_dict)

        def rename_func(ob_name, new_name_field, rename_radio):
            end_reg = re.compile(r"(.*) \((\d+)\)$")

            def in_func():
                if not rename_radio.isChecked() or str(new_name_field.text()).strip() != "":
                    return

                match = end_reg.match(ob_name)
                if match:
                    new_name_format = match.group(1) + " ({})"
                    i = int(match.group(2)) + 1
                else:
                    new_name_format = ob_name + " ({})"
                    i = 1
                while new_name_format.format(i) in self.local_dict:
                    i += 1
                new_name_field.setText(new_name_format.format(i))

            return in_func

        def block_import(radio_btn, name_field):
            def inner_func():
                text = str(name_field.text()).strip()
                if text == "" and radio_btn.isChecked():
                    self.import_btn.setDisabled(True)
                else:
                    self.import_btn.setEnabled(True)

            return inner_func

        for name in sorted(import_dict.keys()):
            item = QTreeWidgetItem()
            item.setText(0, name)
            # noinspection PyTypeChecker
            item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
            item.setCheckState(0, Qt.Checked)
            self.list_view.addTopLevelItem(item)
            if name in conflicts:
                group = QButtonGroup()
                overwrite = QRadioButton("Overwrite")
                overwrite.setChecked(True)
                rename = QRadioButton("Rename")
                new_name = QLineEdit()
                new_name.textChanged.connect(block_import(rename, new_name))
                rename.toggled.connect(block_import(rename, new_name))
                overwrite.toggled.connect(block_import(rename, new_name))

                rename.toggled.connect(rename_func(name, new_name, rename))
                group.addButton(overwrite)
                group.addButton(rename)
                self.radio_group_list.append(group)
                self.list_view.setItemWidget(item, 1, overwrite)
                self.list_view.setItemWidget(item, 2, rename)
                self.list_view.setItemWidget(item, 3, new_name)

        self.import_btn = QPushButton("Import")
        self.cancel_btn = QPushButton("Cancel")
        self.check_btn = QPushButton("Check all")
        self.uncheck_btn = QPushButton("Uncheck all")

        self.cancel_btn.clicked.connect(self.close)
        self.import_btn.clicked.connect(self.accept)
        self.check_btn.clicked.connect(self.check_all)
        self.uncheck_btn.clicked.connect(self.uncheck_all)

        self.list_view.itemSelectionChanged.connect(self.preview)
        self.list_view.itemChanged.connect(self.checked_change)

        layout = QVBoxLayout()
        info_layout = QHBoxLayout()
        info_layout.addWidget(self.list_view, 2)
        v1_lay = QVBoxLayout()
        v1_lay.addWidget(QLabel("Import:"))
        v1_lay.addWidget(self.viewer)
        info_layout.addLayout(v1_lay, 1)
        # info_layout.addWidget(self.local_viewer, 1)
        v2_lay = QVBoxLayout()
        v2_lay.addWidget(QLabel("Local:"))
        v2_lay.addWidget(self.local_viewer)
        info_layout.addLayout(v2_lay, 1)
        layout.addLayout(info_layout)
        btn_layout = QHBoxLayout()
        btn_layout.addWidget(self.check_btn)
        btn_layout.addWidget(self.uncheck_btn)
        btn_layout.addStretch()
        btn_layout.addWidget(self.import_btn)
        btn_layout.addWidget(self.cancel_btn)
        layout.addLayout(btn_layout)
        self.setLayout(layout)

    def preview(self):
        item = self.list_view.currentItem()
        name = str(item.text(0))
        self.viewer.preview_object(self.import_dict[name])
        if self.list_view.itemWidget(item, 1) is not None:
            self.local_viewer.preview_object(self.local_dict[name])
        else:
            self.local_viewer.clear()

    def checked_change(self, item, _):
        if item.checkState(0) == Qt.Unchecked:
            self.checked_num -= 1
            if self.list_view.itemWidget(item, 1) is not None:
                self.list_view.itemWidget(item, 1).setDisabled(True)
                self.list_view.itemWidget(item, 2).setDisabled(True)
                self.list_view.itemWidget(item, 3).setDisabled(True)
        else:
            self.checked_num += 1
            if self.list_view.itemWidget(item, 1) is not None:
                self.list_view.itemWidget(item, 1).setEnabled(True)
                self.list_view.itemWidget(item, 2).setEnabled(True)
                self.list_view.itemWidget(item, 3).setEnabled(True)
        if self.checked_num == 0:
            self.import_btn.setDisabled(True)
        else:
            self.import_btn.setEnabled(True)

    def get_import_list(self):
        res = []
        for index in range(self.list_view.topLevelItemCount()):
            item = self.list_view.topLevelItem(index)
            if item.checkState(0) == Qt.Checked:
                chk = self.list_view.itemWidget(item, 2)
                if chk is not None and chk.isChecked():
                    res.append((str(item.text(0)), str(self.list_view.itemWidget(item, 3).text())))
                else:
                    name = str(item.text(0))
                    res.append((name, name))
        return res

    def uncheck_all(self):
        for index in range(self.list_view.topLevelItemCount()):
            item = self.list_view.topLevelItem(index)
            item.setCheckState(0, Qt.Unchecked)
        self.check_state[...] = False
        self.import_btn.setDisabled(True)
        self.checked_num = 0

    def check_all(self):
        for index in range(self.list_view.topLevelItemCount()):
            item = self.list_view.topLevelItem(index)
            item.setCheckState(0, Qt.Checked)
        self.checked_num = len(self.import_dict)
        self.check_state[...] = True
        self.import_btn.setDisabled(False)
Beispiel #2
0
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)