コード例 #1
0
ファイル: tableshow.py プロジェクト: hzyrc6011/pmgwidgets
class PMGTableShow(BaseExtendedWidget):
    default_bg = QTableWidgetItem().background()
    default_fg = QTableWidgetItem().foreground()

    def __init__(self,
                 layout_dir: str,
                 title: List[str],
                 initial_value: List[List[Union[int, float, str]]],
                 size_restricted=False,
                 header_adaption_h=False,
                 header_adaption_v=False,
                 background_color: List[List[Union[str]]] = None,
                 foreground_color: List[List[Union[str]]] = None):
        super().__init__(layout_dir=layout_dir)

        self.maximum_rows = 100
        self.size_restricted = size_restricted
        self.header_adaption_h = header_adaption_h
        self.header_adaption_v = header_adaption_v
        self.background_color = background_color if background_color is not None else ''
        self.foreground_color = foreground_color if foreground_color is not None else ''
        self.char_width = 15
        self.on_check_callback = None
        self.title_list = title
        entryLayout = QHBoxLayout()
        entryLayout.setContentsMargins(0, 0, 0, 0)

        self.ctrl = QTableWidget()
        self.ctrl.verticalHeader().setVisible(False)
        self.set_params(size_restricted, header_adaption_h, header_adaption_v)
        self.ctrl.setColumnCount(len(title))

        self.ctrl.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        for i, text in enumerate(title):
            self.ctrl.setColumnWidth(i, len(text) * self.char_width + 10)
            self.ctrl.setHorizontalHeaderItem(i, QTableWidgetItem(text))

        self.central_layout.addLayout(entryLayout)
        entryLayout.addWidget(self.ctrl)

        if initial_value is not None:
            for sublist in initial_value:
                assert len(sublist) == len(title), \
                    'title is not as long as sublist,%s,%s' % (repr(title), sublist)
                self.ctrl.setRowCount(len(initial_value))
                self.set_value(initial_value)

    def set_params(self,
                   size_restricted=False,
                   header_adaption_h=False,
                   header_adaption_v=False):
        self.size_restricted = size_restricted
        self.header_adaption_h = header_adaption_h
        self.header_adaption_v = header_adaption_v
        if header_adaption_h:
            self.ctrl.horizontalHeader().setSectionResizeMode(
                QHeaderView.Stretch)
        if header_adaption_v:
            self.ctrl.verticalHeader().setSectionResizeMode(
                QHeaderView.Stretch)

    def check_data(self, value: List[List[Union[int, float, str]]]):
        for sublist in value:
            assert len(sublist) == len(self.title_list),\
                '%s,%s' % (repr(sublist), repr(self.title_list))

    def set_value(self, value: List[List[Union[int, float, str]]]):
        self.check_data(value)
        self.ctrl.setRowCount(len(value))
        cols = len(value[0])
        if isinstance(self.foreground_color, str):
            fg = [[self.foreground_color for i in range(cols)]
                  for j in range(len(value))]

        else:
            fg = self.foreground_color
        if isinstance(self.background_color, str):
            bg = [[self.background_color for i in range(cols)]
                  for j in range(len(value))]
        else:
            bg = self.background_color
        for row, row_list in enumerate(value):
            for col, content in enumerate(row_list):
                if len(str(content)) * self.char_width > self.ctrl.columnWidth(
                        col):
                    self.ctrl.setColumnWidth(
                        col,
                        len(str(content)) * self.char_width + 10)
                table_item = QTableWidgetItem(str(content))
                table_item.setTextAlignment(Qt.AlignCenter)
                # 字体颜色(红色)
                if fg[row][col] == '':
                    table_item.setForeground(self.default_fg)
                else:
                    table_item.setForeground(
                        QBrush(QColor(*color_str2tup(fg[row][col]))))

                # 背景颜色(红色)
                if bg[row][col] == '':
                    table_item.setBackground(self.default_bg)
                else:
                    table_item.setBackground(
                        QBrush(QColor(*color_str2tup(bg[row][col]))))
                self.ctrl.setItem(row, col, table_item)

        if self.size_restricted:
            if self.header_adaption_h:
                self.ctrl.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
                scrollbar_area_width = 0
            else:
                self.ctrl.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
                scrollbar_area_width = 10
            self.ctrl.setMaximumHeight((self.ctrl.rowCount() + 1) * 30 +
                                       scrollbar_area_width)
            self.setMaximumHeight((self.ctrl.rowCount() + 1) * 30 +
                                  scrollbar_area_width)

    def alert(self, alert_level: int):
        self.ctrl.alert(alert_level)

    def add_row(self, row: List):
        assert len(row) == self.ctrl.columnCount()
        rc = self.ctrl.rowCount()
        self.ctrl.setRowCount(rc + 1)
        for i, val in enumerate(row):
            self.ctrl.setItem(rc, i, QTableWidgetItem(str(val)))
        if self.ctrl.rowCount() > self.maximum_rows:
            self.ctrl.removeRow(0)
コード例 #2
0
ファイル: camera.py プロジェクト: xuliangyin/pyNastran
class CameraWindow(PyDialog):
    """defines the CameraWindow class"""
    def __init__(self, data, win_parent=None):
        """
        +--------+
        | Camera |
        +--------+---------------+
        |  Camera Name           |
        |  +-------------------+ |
        |  |                   | |
        |  |                   | |
        |  |                   | |
        |  |                   | |
        |  |                   | |
        |  +-------------------+ |
        |                        |
        | Name xxx       Save    |
        | Delete   Set           |
        |                        |
        |    Apply   OK  Cancel  |
        +--------+---------------+
        """
        PyDialog.__init__(self, data, win_parent)
        self.setWindowTitle('Camera Views')
        #self.setWindowIcon(view_icon)

        self._default_name = 'Camera'
        self.out_data['clicked_ok'] = False

        self.cameras = deepcopy(data['cameras'])
        self.names = sorted(self.cameras.keys())

        self.name = QLabel("Name:")
        self.name_edit = QLineEdit(str(self._default_name))

        self.delete_button = QPushButton("Delete")
        self.set_button = QPushButton("Set")
        self.save_button = QPushButton("Save")

        # closing
        self.apply_button = QPushButton("Apply")
        self.close_button = QPushButton("Close")
        self.cancel_button = QPushButton("Cancel")

        self.table = QTableWidget()
        names_text = []
        for name in self.names:
            name_text = QTableWidgetItem(str(name))
            names_text.append(name_text)
        self.create_layout(names_text)
        self.set_connections()

    def create_layout(self, names_text):
        nrows = len(self.names)
        table = self.table
        table.setRowCount(nrows)
        table.setColumnCount(1)
        headers = ['Camera Name']
        table.setHorizontalHeaderLabels(headers)

        header = table.horizontalHeader()
        header.setStretchLastSection(True)

        for iname, name_text in enumerate(names_text):
            # row, col, value
            table.setItem(iname, 0, name_text)
        table.resizeRowsToContents()

        ok_cancel_box = QHBoxLayout()
        ok_cancel_box.addWidget(self.apply_button)
        ok_cancel_box.addWidget(self.close_button)
        ok_cancel_box.addWidget(self.cancel_button)

        grid = QGridLayout()

        irow = 0
        grid.addWidget(self.name, irow, 0)
        grid.addWidget(self.name_edit, irow, 1)
        grid.addWidget(self.save_button, irow, 2)
        irow += 1

        grid.addWidget(self.delete_button, irow, 0)
        grid.addWidget(self.set_button, irow, 1)
        irow += 1

        vbox = QVBoxLayout()
        vbox.addWidget(self.table)

        vbox.addLayout(grid)
        vbox.addStretch()
        vbox.addLayout(ok_cancel_box)
        self.setLayout(vbox)

    def set_connections(self):
        """creates the actions for the menu"""
        #if qt_version == 4:
        #self.connect(self.ok_button, QtCore.SIGNAL('clicked()'), self.on_ok)
        self.set_button.clicked.connect(self.on_set)
        self.save_button.clicked.connect(self.on_save)
        self.delete_button.clicked.connect(self.on_delete)
        self.apply_button.clicked.connect(self.on_apply)
        self.close_button.clicked.connect(self.on_close)
        self.cancel_button.clicked.connect(self.on_cancel)

    def on_set(self):
        objs = self.table.selectedIndexes()
        if len(objs) == 1:
            obj = objs[0]
            irow = obj.row()
            name = self.names[irow]
            self.set_camera(name)
            return True
        return False

    def on_save(self):
        name = str(self.name_edit.text()).strip()
        if name in self.cameras:
            return
        irow = self.nrows
        if len(name):
            self.table.insertRow(irow)
            name_text = QTableWidgetItem(str(name))
            self.table.setItem(irow, 0, name_text)
            self.name_edit.setText('')
            self.save_camera(name)

    def set_camera(self, name):
        camera_data = self.cameras[name]
        if self.win_parent is None:
            return
        self.win_parent.on_set_camera_data(camera_data)

    def save_camera(self, name):
        self.names.append(name)
        if self.win_parent is None:
            self.cameras[name] = None
            return
        self.cameras[name] = self.win_parent.get_camera_data()

    @property
    def nrows(self):
        return self.table.rowCount()

    def on_delete(self):
        irows = []
        for obj in self.table.selectedIndexes():
            irow = obj.row()
            irows.append(irow)
        irows.sort()

        for irow in reversed(irows):
            self.table.removeRow(irow)
            name = self.names.pop(irow)
            del self.cameras[name]
            #print('  removing irow=%s name=%r' % (irow, name))

    def closeEvent(self, event):
        event.accept()

    def on_apply(self):
        passed = self.on_set()
        #if passed:
        #    self.win_parent.create_plane(self.out_data)
        return passed

    def on_close(self):
        self.out_data['clicked_ok'] = True
        self.out_data['cameras'] = self.cameras
        self.close()

    def on_ok(self):
        passed = self.on_apply()
        if passed:
            name = str(self.name_edit.text()).strip()
            self.out_data['name'] = name
            self.out_data['cameras'] = self.cameras
            self.out_data['clicked_ok'] = True
            self.close()
            #self.destroy()

    def on_cancel(self):
        self.close()
コード例 #3
0
class MCSDialog(QDialog):
    """A dialog to perform minimal cut set computation"""

    def __init__(self, appdata: CnaData, centralwidget):
        QDialog.__init__(self)
        self.setWindowTitle("Minimal Cut Sets Computation")

        self.appdata = appdata
        self.centralwidget = centralwidget
        self.eng = appdata.engine
        self.out = io.StringIO()
        self.err = io.StringIO()

        self.layout = QVBoxLayout()
        l1 = QLabel("Target Region(s)")
        self.layout.addWidget(l1)
        s1 = QHBoxLayout()

        completer = QCompleter(
            self.appdata.project.cobra_py_model.reactions.list_attr("id"), self)
        completer.setCaseSensitivity(Qt.CaseInsensitive)

        self.target_list = QTableWidget(1, 4)
        self.target_list.setHorizontalHeaderLabels(
            ["region no", "T", "≥/≤", "t"])
        self.target_list.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.target_list.horizontalHeader().setSectionResizeMode(0, QHeaderView.Fixed)
        self.target_list.horizontalHeader().resizeSection(0, 100)
        self.target_list.horizontalHeader().setSectionResizeMode(2, QHeaderView.Fixed)
        self.target_list.horizontalHeader().resizeSection(2, 50)
        item = QLineEdit("1")
        self.target_list.setCellWidget(0, 0, item)
        item2 = QLineEdit("")
        item2.setCompleter(completer)
        self.target_list.setCellWidget(0, 1, item2)
        combo = QComboBox(self.target_list)
        combo.insertItem(1, "≤")
        combo.insertItem(2, "≥")
        self.target_list.setCellWidget(0, 2, combo)
        item = QLineEdit("0")
        self.target_list.setCellWidget(0, 3, item)

        s1.addWidget(self.target_list)

        s11 = QVBoxLayout()
        self.add_target = QPushButton("+")
        self.add_target.clicked.connect(self.add_target_region)
        self.rem_target = QPushButton("-")
        self.rem_target.clicked.connect(self.rem_target_region)
        s11.addWidget(self.add_target)
        s11.addWidget(self.rem_target)
        s1.addItem(s11)
        self.layout.addItem(s1)

        l2 = QLabel("Desired Region(s)")
        self.layout.addWidget(l2)
        s2 = QHBoxLayout()
        self.desired_list = QTableWidget(1, 4)
        self.desired_list.setHorizontalHeaderLabels(
            ["region no", "D", "≥/≤", "d"])
        self.desired_list.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.desired_list.horizontalHeader().setSectionResizeMode(0, QHeaderView.Fixed)
        self.desired_list.horizontalHeader().resizeSection(0, 100)
        self.desired_list.horizontalHeader().setSectionResizeMode(2, QHeaderView.Fixed)
        self.desired_list.horizontalHeader().resizeSection(2, 50)
        item = QLineEdit("1")
        self.desired_list.setCellWidget(0, 0, item)
        item2 = QLineEdit("")
        item2.setCompleter(completer)
        self.desired_list.setCellWidget(0, 1, item2)
        combo = QComboBox(self.desired_list)
        combo.insertItem(1, "≤")
        combo.insertItem(2, "≥")
        self.desired_list.setCellWidget(0, 2, combo)
        item = QLineEdit("0")
        self.desired_list.setCellWidget(0, 3, item)
        s2.addWidget(self.desired_list)

        s21 = QVBoxLayout()
        self.add_desire = QPushButton("+")
        self.add_desire.clicked.connect(self.add_desired_region)
        self.rem_desire = QPushButton("-")
        self.rem_desire.clicked.connect(self.rem_desired_region)
        s21.addWidget(self.add_desire)
        s21.addWidget(self.rem_desire)
        s2.addItem(s21)
        self.layout.addItem(s2)

        s3 = QHBoxLayout()

        sgx = QVBoxLayout()
        self.gen_kos = QCheckBox("Gene KOs")
        self.exclude_boundary = QCheckBox(
            "Exclude boundary\nreactions as cuts")
        sg1 = QHBoxLayout()
        s31 = QVBoxLayout()
        l = QLabel("Max. Solutions")
        s31.addWidget(l)
        l = QLabel("Max. Size")
        s31.addWidget(l)
        l = QLabel("Time Limit [sec]")
        s31.addWidget(l)

        sg1.addItem(s31)

        s32 = QVBoxLayout()
        self.max_solu = QLineEdit("inf")
        self.max_solu.setMaximumWidth(50)
        s32.addWidget(self.max_solu)
        self.max_size = QLineEdit("7")
        self.max_size.setMaximumWidth(50)
        s32.addWidget(self.max_size)
        self.time_limit = QLineEdit("inf")
        self.time_limit.setMaximumWidth(50)
        s32.addWidget(self.time_limit)

        sg1.addItem(s32)
        sgx.addWidget(self.gen_kos)
        sgx.addWidget(self.exclude_boundary)
        sgx.addItem(sg1)
        s3.addItem(sgx)

        g3 = QGroupBox("Solver")
        s33 = QVBoxLayout()
        self.bg1 = QButtonGroup()
        optlang_solver_name = interface_to_str(
            appdata.project.cobra_py_model.problem)
        self.solver_optlang = QRadioButton(f"{optlang_solver_name} (optlang)")
        self.solver_optlang.setToolTip(
            "Uses the solver specified by the current model.")
        s33.addWidget(self.solver_optlang)
        self.bg1.addButton(self.solver_optlang)
        self.solver_cplex_matlab = QRadioButton("CPLEX (MATLAB)")
        self.solver_cplex_matlab.setToolTip(
            "Only enabled with MATLAB and CPLEX")
        s33.addWidget(self.solver_cplex_matlab)
        self.bg1.addButton(self.solver_cplex_matlab)
        self.solver_cplex_java = QRadioButton("CPLEX (Octave)")
        self.solver_cplex_java.setToolTip("Only enabled with Octave and CPLEX")
        s33.addWidget(self.solver_cplex_java)
        self.bg1.addButton(self.solver_cplex_java)
        self.solver_intlinprog = QRadioButton("intlinprog (MATLAB)")
        self.solver_intlinprog.setToolTip("Only enabled with MATLAB")
        s33.addWidget(self.solver_intlinprog)
        self.bg1.addButton(self.solver_intlinprog)
        self.solver_glpk = QRadioButton("GLPK (Octave/MATLAB)")
        s33.addWidget(self.solver_glpk)
        self.bg1.addButton(self.solver_glpk)
        self.bg1.buttonClicked.connect(self.configure_solver_options)
        g3.setLayout(s33)
        s3.addWidget(g3)

        g4 = QGroupBox("MCS search")
        s34 = QVBoxLayout()
        self.bg2 = QButtonGroup()
        self.any_mcs = QRadioButton("any MCS (fast)")
        self.any_mcs.setChecked(True)
        s34.addWidget(self.any_mcs)
        self.bg2.addButton(self.any_mcs)

        # Search type: by cardinality only with CPLEX possible
        self.mcs_by_cardinality = QRadioButton("by cardinality")
        s34.addWidget(self.mcs_by_cardinality)
        self.bg2.addButton(self.mcs_by_cardinality)

        self.smalles_mcs_first = QRadioButton("smallest MCS first")
        s34.addWidget(self.smalles_mcs_first)
        self.bg2.addButton(self.smalles_mcs_first)
        g4.setLayout(s34)

        s3.addWidget(g4)
        self.layout.addItem(s3)

        # Disable incompatible combinations
        if appdata.selected_engine == 'None':
            self.solver_optlang.setChecked(True)
            self.solver_cplex_matlab.setEnabled(False)
            self.solver_cplex_java.setEnabled(False)
            self.solver_glpk.setEnabled(False)
            self.solver_intlinprog.setEnabled(False)
            if optlang_solver_name != 'cplex':
                self.mcs_by_cardinality.setEnabled(False)
        else:
            self.solver_glpk.setChecked(True)
            if not self.eng.is_cplex_matlab_ready():
                self.solver_cplex_matlab.setEnabled(False)
            if not self.eng.is_cplex_java_ready():
                self.solver_cplex_java.setEnabled(False)
            if self.appdata.is_matlab_set():
                self.solver_cplex_java.setEnabled(False)
            if not self.appdata.is_matlab_set():
                self.solver_cplex_matlab.setEnabled(False)
                self.solver_intlinprog.setEnabled(False)
        self.configure_solver_options()

        s4 = QVBoxLayout()
        self.consider_scenario = QCheckBox(
            "Consider constraint given by scenario")
        s4.addWidget(self.consider_scenario)
        self.advanced = QCheckBox(
            "Advanced: Define knockout/addition costs for genes/reactions")
        self.advanced.setEnabled(False)
        s4.addWidget(self.advanced)
        self.layout.addItem(s4)

        buttons = QHBoxLayout()
        # self.save = QPushButton("save")
        # buttons.addWidget(self.save)
        # self.load = QPushButton("load")
        # buttons.addWidget(self.load)
        self.compute_mcs = QPushButton("Compute MCS")
        buttons.addWidget(self.compute_mcs)
        # self.compute_mcs2 = QPushButton("Compute MCS2")
        # buttons.addWidget(self.compute_mcs2)
        self.cancel = QPushButton("Close")
        buttons.addWidget(self.cancel)
        self.layout.addItem(buttons)

        # max width for buttons
        self.add_target.setMaximumWidth(20)
        self.rem_target.setMaximumWidth(20)
        self.add_desire.setMaximumWidth(20)
        self.rem_desire.setMaximumWidth(20)

        self.setLayout(self.layout)

        # Connecting the signal
        self.cancel.clicked.connect(self.reject)
        self.compute_mcs.clicked.connect(self.compute)

    @Slot()
    def configure_solver_options(self):
        optlang_solver_name = interface_to_str(
            self.appdata.project.cobra_py_model.problem)
        if self.solver_optlang.isChecked():
            self.gen_kos.setChecked(False)
            self.gen_kos.setEnabled(False)
            self.exclude_boundary.setEnabled(True)
            if optlang_solver_name != 'cplex':
                if self.mcs_by_cardinality.isChecked():
                    self.mcs_by_cardinality.setChecked(False)
                    self.any_mcs.setChecked(True)
                self.mcs_by_cardinality.setEnabled(False)
                self.mcs_by_cardinality.setChecked(False)

        else:
            self.gen_kos.setEnabled(True)
            self.exclude_boundary.setChecked(False)
            self.exclude_boundary.setEnabled(False)
            self.mcs_by_cardinality.setEnabled(True)

    def add_target_region(self):
        i = self.target_list.rowCount()
        self.target_list.insertRow(i)

        completer = QCompleter(
            self.appdata.project.cobra_py_model.reactions.list_attr("id"), self)
        completer.setCaseSensitivity(Qt.CaseInsensitive)

        item = QLineEdit("1")
        self.target_list.setCellWidget(i, 0, item)
        item2 = QLineEdit("")
        item2.setCompleter(completer)
        self.target_list.setCellWidget(i, 1, item2)
        combo = QComboBox(self.target_list)
        combo.insertItem(1, "≤")
        combo.insertItem(2, "≥")
        self.target_list.setCellWidget(i, 2, combo)
        item = QLineEdit("0")
        self.target_list.setCellWidget(i, 3, item)

    def add_desired_region(self):
        i = self.desired_list.rowCount()
        self.desired_list.insertRow(i)

        completer = QCompleter(
            self.appdata.project.cobra_py_model.reactions.list_attr("id"), self)
        completer.setCaseSensitivity(Qt.CaseInsensitive)

        item = QLineEdit("1")
        self.desired_list.setCellWidget(i, 0, item)
        item2 = QLineEdit("")
        item2.setCompleter(completer)
        self.desired_list.setCellWidget(i, 1, item2)
        combo = QComboBox(self.desired_list)
        combo.insertItem(1, "≤")
        combo.insertItem(2, "≥")
        self.desired_list.setCellWidget(i, 2, combo)
        item = QLineEdit("0")
        self.desired_list.setCellWidget(i, 3, item)

    def rem_target_region(self):
        i = self.target_list.rowCount()
        self.target_list.removeRow(i-1)

    def rem_desired_region(self):
        i = self.desired_list.rowCount()
        self.desired_list.removeRow(i-1)

    def compute(self):
        if self.solver_optlang.isChecked():
            self.compute_optlang()
        else:
            self.compute_legacy()

    def compute_legacy(self):
        self.setCursor(Qt.BusyCursor)
        # create CobraModel for matlab
        with self.appdata.project.cobra_py_model as model:
            if self.consider_scenario.isChecked():  # integrate scenario into model bounds
                for r in self.appdata.project.scen_values.keys():
                    model.reactions.get_by_id(
                        r).bounds = self.appdata.project.scen_values[r]
            cobra.io.save_matlab_model(model, os.path.join(
                self.appdata.cna_path, "cobra_model.mat"), varname="cbmodel")
        self.eng.eval("load('cobra_model.mat')",
                      nargout=0)

        try:
            self.eng.eval("cnap = CNAcobra2cna(cbmodel);",
                          nargout=0,
                          stdout=self.out, stderr=self.err)
        except Exception:
            output = io.StringIO()
            traceback.print_exc(file=output)
            exstr = output.getvalue()
            print(exstr)
            QMessageBox.warning(self, 'Unknown exception occured!',
                                exstr+'\nPlease report the problem to:\n\
                                    \nhttps://github.com/cnapy-org/CNApy/issues')
            return

        self.eng.eval("genes = [];", nargout=0,
                      stdout=self.out, stderr=self.err)
        cmd = "maxSolutions = " + str(float(self.max_solu.text())) + ";"
        self.eng.eval(cmd, nargout=0, stdout=self.out, stderr=self.err)

        cmd = "maxSize = " + str(int(self.max_size.text())) + ";"
        self.eng.eval(cmd, nargout=0, stdout=self.out, stderr=self.err)

        cmd = "milp_time_limit = " + str(float(self.time_limit.text())) + ";"
        self.eng.eval(cmd, nargout=0, stdout=self.out, stderr=self.err)

        if self.gen_kos.isChecked():
            self.eng.eval("gKOs = 1;", nargout=0)
        else:
            self.eng.eval("gKOs = 0;", nargout=0)
        if self.advanced.isChecked():
            self.eng.eval("advanced_on = 1;", nargout=0)
        else:
            self.eng.eval("advanced_on = 0;", nargout=0)

        if self.solver_intlinprog.isChecked():
            self.eng.eval("solver = 'intlinprog';", nargout=0)
        if self.solver_cplex_java.isChecked():
            self.eng.eval("solver = 'java_cplex_new';", nargout=0)
        if self.solver_cplex_matlab.isChecked():
            self.eng.eval("solver = 'matlab_cplex';", nargout=0)
        if self.solver_glpk.isChecked():
            self.eng.eval("solver = 'glpk';", nargout=0)
        if self.any_mcs.isChecked():
            self.eng.eval("mcs_search_mode = 'search_1';", nargout=0)
        elif self.mcs_by_cardinality.isChecked():
            self.eng.eval("mcs_search_mode = 'search_2';", nargout=0)
        elif self.smalles_mcs_first.isChecked():
            self.eng.eval("mcs_search_mode = 'search_3';", nargout=0)

        rows = self.target_list.rowCount()
        for i in range(0, rows):
            p1 = self.target_list.cellWidget(i, 0).text()
            p2 = self.target_list.cellWidget(i, 1).text()
            if self.target_list.cellWidget(i, 2).currentText() == '≤':
                p3 = "<="
            else:
                p3 = ">="
            p4 = self.target_list.cellWidget(i, 3).text()
            cmd = "dg_T = {[" + p1+"], '" + p2 + \
                "', '" + p3 + "', [" + p4 + "']};"
            self.eng.eval(cmd, nargout=0,
                          stdout=self.out, stderr=self.err)

        rows = self.desired_list.rowCount()
        for i in range(0, rows):
            p1 = self.desired_list.cellWidget(i, 0).text()
            p2 = self.desired_list.cellWidget(i, 1).text()
            if self.desired_list.cellWidget(i, 2).currentText() == '≤':
                p3 = "<="
            else:
                p3 = ">="
            p4 = self.desired_list.cellWidget(i, 3).text()
            cmd = "dg_D = {[" + p1+"], '" + p2 + \
                "', '" + p3 + "', [" + p4 + "']};"
            self.eng.eval(cmd, nargout=0)

        # get some data
        self.eng.eval("reac_id = cellstr(cnap.reacID).';",
                      nargout=0, stdout=self.out, stderr=self.err)

        mcs = []
        values = []
        reactions = []
        reac_id = []
        if self.appdata.is_matlab_set():
            reac_id = self.eng.workspace['reac_id']
            try:
                self.eng.eval("[mcs] = cnapy_compute_mcs(cnap, genes, maxSolutions, maxSize, milp_time_limit, gKOs, advanced_on, solver, mcs_search_mode, dg_T,dg_D);",
                              nargout=0)
            except Exception:
                output = io.StringIO()
                traceback.print_exc(file=output)
                exstr = output.getvalue()
                print(exstr)
                QMessageBox.warning(self, 'Unknown exception occured!',
                                    exstr+'\nPlease report the problem to:\n\
                                    \nhttps://github.com/cnapy-org/CNApy/issues')
                return
            else:
                self.eng.eval("[reaction, mcs, value] = find(mcs);", nargout=0,
                              stdout=self.out, stderr=self.err)
                reactions = self.eng.workspace['reaction']
                mcs = self.eng.workspace['mcs']
                values = self.eng.workspace['value']
        elif self.appdata.is_octave_ready():
            reac_id = self.eng.pull('reac_id')
            reac_id = reac_id[0]
            try:
                self.eng.eval("[mcs] = cnapy_compute_mcs(cnap, genes, maxSolutions, maxSize, milp_time_limit, gKOs, advanced_on, solver, mcs_search_mode, dg_T,dg_D);",
                              nargout=0)
            except Exception:
                output = io.StringIO()
                traceback.print_exc(file=output)
                exstr = output.getvalue()
                print(exstr)
                QMessageBox.warning(self, 'Unknown exception occured!',
                                    exstr+'\nPlease report the problem to:\n\
                                    \nhttps://github.com/cnapy-org/CNApy/issues')
                return
            else:
                self.eng.eval("[reaction, mcs, value] = find(mcs);", nargout=0,
                              stdout=self.out, stderr=self.err)
                reactions = self.eng.pull('reaction')
                mcs = self.eng.pull('mcs')
                values = self.eng.pull('value')

        if len(mcs) == 0:
            QMessageBox.information(self, 'No cut sets',
                                          'Cut sets have not been calculated or do not exist.')
        else:
            last_mcs = 1
            omcs = []
            current_mcs = {}
            for i in range(0, len(reactions)):
                reacid = int(reactions[i][0])
                reaction = reac_id[reacid-1]
                c_mcs = int(mcs[i][0])
                c_value = int(values[i][0])
                if c_value == -1:  # -1 stands for removed which is 0 in the ui
                    c_value = 0
                if c_mcs > last_mcs:
                    omcs.append(current_mcs)
                    last_mcs = c_mcs
                    current_mcs = {}
                current_mcs[reaction] = c_value
            omcs.append(current_mcs)
            self.appdata.project.modes = omcs
            self.centralwidget.mode_navigator.current = 0
            QMessageBox.information(self, 'Cut sets found',
                                          str(len(omcs))+' Cut sets have been calculated.')

        self.centralwidget.update_mode()
        self.centralwidget.mode_navigator.title.setText("MCS Navigation")

        self.setCursor(Qt.ArrowCursor)

    def compute_optlang(self):

        self.setCursor(Qt.BusyCursor)
        max_mcs_num = float(self.max_solu.text())
        max_mcs_size = int(self.max_size.text())
        timeout = float(self.time_limit.text())
        if timeout is float('inf'):
            timeout = None

        # if self.gen_kos.isChecked():
        #     self.eng.eval("gKOs = 1;", nargout=0)
        # else:
        #     self.eng.eval("gKOs = 0;", nargout=0)
        # if self.advanced.isChecked():
        #     self.eng.eval("advanced_on = 1;", nargout=0)
        # else:
        #     self.eng.eval("advanced_on = 0;", nargout=0)

        if self.smalles_mcs_first.isChecked():
            enum_method = 1
        elif self.mcs_by_cardinality.isChecked():
            enum_method = 2
        elif self.any_mcs.isChecked():
            enum_method = 3

        with self.appdata.project.cobra_py_model as model:
            if self.consider_scenario.isChecked():  # integrate scenario into model bounds
                for r in self.appdata.project.scen_values.keys():
                    model.reactions.get_by_id(
                        r).bounds = self.appdata.project.scen_values[r]
            reac_id = model.reactions.list_attr("id")
            reac_id_symbols = cMCS_enumerator.get_reac_id_symbols(reac_id)
            rows = self.target_list.rowCount()
            targets = dict()
            for i in range(0, rows):
                p1 = self.target_list.cellWidget(i, 0).text()
                p2 = self.target_list.cellWidget(i, 1).text()
                if len(p1) > 0 and len(p2) > 0:
                    if self.target_list.cellWidget(i, 2).currentText() == '≤':
                        p3 = "<="
                    else:
                        p3 = ">="
                    p4 = float(self.target_list.cellWidget(i, 3).text())
                    targets.setdefault(p1, []).append((p2, p3, p4))
            targets = list(targets.values())
            targets = [cMCS_enumerator.relations2leq_matrix(cMCS_enumerator.parse_relations(
                t, reac_id_symbols=reac_id_symbols), reac_id) for t in targets]

            rows = self.desired_list.rowCount()
            desired = dict()
            for i in range(0, rows):
                p1 = self.desired_list.cellWidget(i, 0).text()
                p2 = self.desired_list.cellWidget(i, 1).text()
                if len(p1) > 0 and len(p2) > 0:
                    if self.desired_list.cellWidget(i, 2).currentText() == '≤':
                        p3 = "<="
                    else:
                        p3 = ">="
                    p4 = float(self.desired_list.cellWidget(i, 3).text())
                    desired.setdefault(p1, []).append((p2, p3, p4))

            desired = list(desired.values())
            desired = [cMCS_enumerator.relations2leq_matrix(cMCS_enumerator.parse_relations(
                d, reac_id_symbols=reac_id_symbols), reac_id) for d in desired]

            try:
                mcs = cMCS_enumerator.compute_mcs(model,
                                                  targets=targets,
                                                  desired=desired,
                                                  enum_method=enum_method,
                                                  max_mcs_size=max_mcs_size,
                                                  max_mcs_num=max_mcs_num,
                                                  timeout=timeout,
                                                  exclude_boundary_reactions_as_cuts=self.exclude_boundary.isChecked())
            except cMCS_enumerator.InfeasibleRegion as e:
                QMessageBox.warning(self, 'Cannot calculate MCS', str(e))
                return targets, desired
            except Exception:
                output = io.StringIO()
                traceback.print_exc(file=output)
                exstr = output.getvalue()
                print(exstr)
                QMessageBox.warning(self, 'An exception has occured!',
                                    exstr+'\nPlease report the problem to:\n\
                                    \nhttps://github.com/cnapy-org/CNApy/issues')
                return targets, desired
            finally:
                self.setCursor(Qt.ArrowCursor)

        if len(mcs) == 0:
            QMessageBox.information(self, 'No cut sets',
                                          'Cut sets have not been calculated or do not exist.')
            return targets, desired

        omcs = [{reac_id[i]: 0 for i in m} for m in mcs]
        self.appdata.project.modes = omcs
        self.centralwidget.mode_navigator.current = 0
        QMessageBox.information(self, 'Cut sets found',
                                      str(len(omcs))+' Cut sets have been calculated.')

        self.centralwidget.update_mode()
        self.centralwidget.mode_navigator.title.setText("MCS Navigation")
コード例 #4
0
class Extension2ReaderTable(QWidget):
    """Table showing extension to reader mappings with removal button.

    Widget presented in preferences-plugin dialog."""

    valueChanged = Signal(int)

    def __init__(self, parent=None):
        super().__init__(parent=parent)

        self._table = QTableWidget()
        self._table.setShowGrid(False)
        self._populate_table()

        layout = QVBoxLayout()
        layout.addWidget(self._table)
        self.setLayout(layout)

    def _populate_table(self):
        """Add row for each extension to reader mapping in settings"""
        self._extension_col = 0
        self._reader_col = 1

        header_strs = [trans._('Extension'), trans._('Reader Plugin')]

        self._table.setColumnCount(2)
        self._table.setColumnWidth(self._extension_col, 100)
        self._table.setColumnWidth(self._reader_col, 150)
        self._table.verticalHeader().setVisible(False)
        self._table.setMinimumHeight(120)

        extension2reader = get_settings().plugins.extension2reader
        if len(extension2reader) > 0:
            self._table.setRowCount(len(extension2reader))
            self._table.horizontalHeader().setStretchLastSection(True)
            self._table.horizontalHeader().setStyleSheet(
                'border-bottom: 2px solid white;')
            self._table.setHorizontalHeaderLabels(header_strs)

            for row, (extension,
                      plugin_name) in enumerate(extension2reader.items()):
                item = QTableWidgetItem(extension)
                item.setFlags(Qt.NoItemFlags)
                self._table.setItem(row, self._extension_col, item)

                plugin_widg = QWidget()
                # need object name to easily find row
                plugin_widg.setObjectName(f'{extension}')
                plugin_widg.setLayout(QHBoxLayout())
                plugin_widg.layout().setContentsMargins(0, 0, 0, 0)

                plugin_label = QLabel(plugin_name)
                # need object name to easily work out which button was clicked
                remove_btn = QPushButton('x', objectName=f'{extension}')
                remove_btn.setFixedWidth(30)
                remove_btn.setStyleSheet('margin: 4px;')
                remove_btn.setToolTip(
                    trans._('Remove this extension to reader association'))
                remove_btn.clicked.connect(self._remove_extension_assignment)

                plugin_widg.layout().addWidget(plugin_label)
                plugin_widg.layout().addWidget(remove_btn)
                self._table.setCellWidget(row, self._reader_col, plugin_widg)
        else:
            # Display that there are no extensions with reader associations
            self._table.setRowCount(1)
            self._table.setHorizontalHeaderLabels(header_strs)

            self._table.setColumnHidden(self._reader_col, True)
            self._table.setColumnWidth(self._extension_col, 200)
            item = QTableWidgetItem(trans._('No extensions found.'))
            item.setFlags(Qt.NoItemFlags)
            self._table.setItem(0, 0, item)

    def _remove_extension_assignment(self, event):
        """Delete extension to reader mapping setting and remove table row"""
        extension_to_remove = self.sender().objectName()
        current_settings = get_settings().plugins.extension2reader
        # need explicit assignment to new object here for persistence
        get_settings().plugins.extension2reader = {
            k: v
            for k, v in current_settings.items() if k != extension_to_remove
        }

        for i in range(self._table.rowCount()):
            row_widg_name = self._table.cellWidget(
                i, self._reader_col).objectName()
            if row_widg_name == extension_to_remove:
                self._table.removeRow(i)
                return
コード例 #5
0
class EventsDialog(QDialog):
    def __init__(self, parent, pos, desc):
        super().__init__(parent)
        self.setWindowTitle("Edit Events")

        self.table = QTableWidget(len(pos), 2)

        for row, (p, d) in enumerate(zip(pos, desc)):
            self.table.setItem(row, 0, IntTableWidgetItem(p))
            self.table.setItem(row, 1, IntTableWidgetItem(d))

        self.table.setHorizontalHeaderLabels(["Position", "Type"])
        self.table.horizontalHeader().setStretchLastSection(True)
        self.table.verticalHeader().setVisible(False)
        self.table.setShowGrid(False)
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table.setSortingEnabled(True)
        self.table.sortByColumn(0, Qt.AscendingOrder)

        vbox = QVBoxLayout(self)
        vbox.addWidget(self.table)
        hbox = QHBoxLayout()
        self.add_button = QPushButton("+")
        self.remove_button = QPushButton("-")
        buttonbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        hbox.addWidget(self.add_button)
        hbox.addWidget(self.remove_button)
        hbox.addStretch()
        hbox.addWidget(buttonbox)
        vbox.addLayout(hbox)
        buttonbox.accepted.connect(self.accept)
        buttonbox.rejected.connect(self.reject)
        self.table.itemSelectionChanged.connect(self.toggle_buttons)
        self.remove_button.clicked.connect(self.remove_event)
        self.add_button.clicked.connect(self.add_event)
        self.toggle_buttons()
        self.resize(300, 500)

    @Slot()
    def toggle_buttons(self):
        """Toggle + and - buttons."""
        n_items = len(self.table.selectedItems())
        if n_items == 2:  # one row (2 items) selected
            self.add_button.setEnabled(True)
            self.remove_button.setEnabled(True)
        elif n_items > 2:  # more than one row selected
            self.add_button.setEnabled(False)
            self.remove_button.setEnabled(True)
        else:  # no rows selected
            self.add_button.setEnabled(False)
            self.remove_button.setEnabled(False)

    def add_event(self):
        current_row = self.table.selectedIndexes()[0].row()
        pos = int(self.table.item(current_row, 0).data(Qt.DisplayRole))
        self.table.setSortingEnabled(False)
        self.table.insertRow(current_row)
        self.table.setItem(current_row, 0, IntTableWidgetItem(pos))
        self.table.setItem(current_row, 1, IntTableWidgetItem(0))
        self.table.setSortingEnabled(True)

    def remove_event(self):
        rows = {index.row() for index in self.table.selectedIndexes()}
        self.table.clearSelection()
        for row in sorted(rows, reverse=True):
            self.table.removeRow(row)
コード例 #6
0
class MeasurementWidget(QWidget):
    """
    :type settings: Settings
    :type segment: Segment
    """
    def __init__(self, settings: PartSettings, segment=None):
        super().__init__()
        self.settings = settings
        self.segment = segment
        self.measurements_storage = MeasurementsStorage()
        self.recalculate_button = QPushButton(
            "Recalculate and\n replace measurement", self)
        self.recalculate_button.clicked.connect(
            self.replace_measurement_result)
        self.recalculate_append_button = QPushButton(
            "Recalculate and\n append measurement", self)
        self.recalculate_append_button.clicked.connect(
            self.append_measurement_result)
        self.copy_button = QPushButton("Copy to clipboard", self)
        self.copy_button.setToolTip(
            "You cacn copy also with 'Ctrl+C'. To get raw copy copy with 'Ctrl+Shit+C'"
        )
        self.horizontal_measurement_present = QCheckBox(
            "Horizontal view", self)
        self.no_header = QCheckBox("No header", self)
        self.no_units = QCheckBox("No units", self)
        self.no_units.setChecked(True)
        self.no_units.clicked.connect(self.refresh_view)
        self.expand_mode = QCheckBox("Expand", self)
        self.expand_mode.setToolTip(
            "Shows results for each component in separate entry")
        self.file_names = EnumComboBox(FileNamesEnum)
        self.file_names_label = QLabel("Add file name:")
        self.file_names.currentIndexChanged.connect(self.refresh_view)
        self.horizontal_measurement_present.stateChanged.connect(
            self.refresh_view)
        self.expand_mode.stateChanged.connect(self.refresh_view)
        self.copy_button.clicked.connect(self.copy_to_clipboard)
        self.measurement_type = SearchCombBox(self)
        # noinspection PyUnresolvedReferences
        self.measurement_type.currentIndexChanged.connect(
            self.measurement_profile_selection_changed)
        self.measurement_type.addItem("<none>")
        self.measurement_type.addItems(
            list(sorted(self.settings.measurement_profiles.keys())))
        self.measurement_type.setToolTip(
            'You can create new measurement profile in advanced window, in tab "Measurement settings"'
        )
        self.channels_chose = ChannelComboBox()
        self.units_choose = EnumComboBox(Units)
        self.units_choose.set_value(self.settings.get("units_value", Units.nm))
        self.info_field = QTableWidget(self)
        self.info_field.setColumnCount(3)
        self.info_field.setHorizontalHeaderLabels(["Name", "Value", "Units"])
        self.measurement_add_shift = 0
        layout = QVBoxLayout()
        # layout.addWidget(self.recalculate_button)
        v_butt_layout = QVBoxLayout()
        v_butt_layout.setSpacing(1)
        self.up_butt_layout = QHBoxLayout()
        self.up_butt_layout.addWidget(self.recalculate_button)
        self.up_butt_layout.addWidget(self.recalculate_append_button)
        self.butt_layout = QHBoxLayout()
        # self.butt_layout.setMargin(0)
        # self.butt_layout.setSpacing(10)
        self.butt_layout.addWidget(self.horizontal_measurement_present, 1)
        self.butt_layout.addWidget(self.no_header, 1)
        self.butt_layout.addWidget(self.no_units, 1)
        self.butt_layout.addWidget(self.expand_mode, 1)
        self.butt_layout.addWidget(self.file_names_label)
        self.butt_layout.addWidget(self.file_names, 1)
        self.butt_layout.addWidget(self.copy_button, 2)
        self.butt_layout2 = QHBoxLayout()
        self.butt_layout3 = QHBoxLayout()
        self.butt_layout3.addWidget(QLabel("Channel:"))
        self.butt_layout3.addWidget(self.channels_chose)
        self.butt_layout3.addWidget(QLabel("Units:"))
        self.butt_layout3.addWidget(self.units_choose)
        # self.butt_layout3.addWidget(QLabel("Noise removal:"))
        # self.butt_layout3.addWidget(self.noise_removal_method)
        self.butt_layout3.addWidget(QLabel("Measurement set:"))
        self.butt_layout3.addWidget(self.measurement_type, 2)
        v_butt_layout.addLayout(self.up_butt_layout)
        v_butt_layout.addLayout(self.butt_layout)
        v_butt_layout.addLayout(self.butt_layout2)
        v_butt_layout.addLayout(self.butt_layout3)
        layout.addLayout(v_butt_layout)
        # layout.addLayout(self.butt_layout)
        layout.addWidget(self.info_field)
        self.setLayout(layout)
        # noinspection PyArgumentList
        self.clip = QApplication.clipboard()
        self.settings.image_changed[int].connect(self.image_changed)
        self.previous_profile = None

    def check_if_measurement_can_be_calculated(self, name):
        if name == "<none>":
            return "<none>"
        profile: MeasurementProfile = self.settings.measurement_profiles.get(
            name)
        if profile.is_any_mask_measurement() and self.settings.mask is None:
            QMessageBox.information(
                self, "Need mask",
                "To use this measurement set please use data with mask loaded",
                QMessageBox.Ok)
            self.measurement_type.setCurrentIndex(0)
            return "<none>"
        if self.settings.roi is None:
            QMessageBox.information(
                self,
                "Need segmentation",
                'Before calculating please create segmentation ("Execute" button)',
                QMessageBox.Ok,
            )
            self.measurement_type.setCurrentIndex(0)
            return "<none>"
        return name

    def image_changed(self, channels_num):
        self.channels_chose.change_channels_num(channels_num)

    def measurement_profile_selection_changed(self, index):
        text = self.measurement_type.itemText(index)
        text = self.check_if_measurement_can_be_calculated(text)
        try:
            stat = self.settings.measurement_profiles[text]
            is_mask = stat.is_any_mask_measurement()
            disable = is_mask and (self.settings.mask is None)
        except KeyError:
            disable = True
        self.recalculate_button.setDisabled(disable)
        self.recalculate_append_button.setDisabled(disable)
        if disable:
            self.recalculate_button.setToolTip(
                "Measurement profile contains mask measurements when mask is not loaded"
            )
            self.recalculate_append_button.setToolTip(
                "Measurement profile contains mask measurements when mask is not loaded"
            )
        else:
            self.recalculate_button.setToolTip("")
            self.recalculate_append_button.setToolTip("")

    def copy_to_clipboard(self):
        s = ""
        for r in range(self.info_field.rowCount()):
            for c in range(self.info_field.columnCount()):
                try:
                    s += str(self.info_field.item(r, c).text()) + "\t"
                except AttributeError:
                    s += "\t"
            s = s[:-1] + "\n"  # eliminate last '\t'
        self.clip.setText(s)

    def replace_measurement_result(self):
        self.measurements_storage.clear()
        self.previous_profile = ""
        self.append_measurement_result()

    def refresh_view(self):
        self.measurements_storage.set_expand(self.expand_mode.isChecked())
        self.measurements_storage.set_show_units(not self.no_units.isChecked())
        self.info_field.clear()
        save_orientation = self.horizontal_measurement_present.isChecked()
        columns, rows = self.measurements_storage.get_size(save_orientation)
        self.info_field.setColumnCount(columns)
        self.info_field.setRowCount(rows)
        self.info_field.setHorizontalHeaderLabels(
            self.measurements_storage.get_header(save_orientation))
        self.info_field.setVerticalHeaderLabels(
            self.measurements_storage.get_rows(save_orientation))
        for x in range(rows):
            for y in range(columns):
                self.info_field.setItem(
                    x, y,
                    QTableWidgetItem(
                        self.measurements_storage.get_val_as_str(
                            x, y, save_orientation)))
        if self.file_names.get_value() == FileNamesEnum.No:
            if save_orientation:
                self.info_field.removeColumn(0)
            else:
                self.info_field.removeRow(0)
        elif self.file_names.get_value() == FileNamesEnum.Short:
            if save_orientation:
                columns = 1
            else:
                rows = 1
            for x in range(rows):
                for y in range(columns):
                    item = self.info_field.item(x, y)
                    item.setText(os.path.basename(item.text()))

        self.info_field.setEditTriggers(QAbstractItemView.NoEditTriggers)

    def append_measurement_result(self):
        try:
            compute_class = self.settings.measurement_profiles[
                self.measurement_type.currentText()]
        except KeyError:
            QMessageBox.warning(
                self,
                "Measurement profile not found",
                f"Measurement profile '{self.measurement_type.currentText()}' not found'",
            )
            return

        if self.settings.roi is None:
            return
        units = self.units_choose.get_value()

        # FIXME find which errors should be displayed as warning
        # def exception_hook(exception):
        #    QMessageBox.warning(self, "Calculation error", f"Error during calculation: {exception}")

        for num in compute_class.get_channels_num():
            if num >= self.settings.image.channels:
                QMessageBox.warning(
                    self,
                    "Measurement error",
                    "Cannot calculate this measurement because "
                    f"image do not have channel {num+1}",
                )
                return

        thread = ExecuteFunctionThread(
            compute_class.calculate,
            [
                self.settings.image,
                self.channels_chose.currentIndex(), self.settings.roi_info,
                units
            ],
        )
        dial = WaitingDialog(
            thread,
            "Measurement calculation")  # , exception_hook=exception_hook)
        dial.exec()
        stat: MeasurementResult = thread.result
        if stat is None:
            return
        stat.set_filename(self.settings.image_path)
        self.measurements_storage.add_measurements(stat)
        self.previous_profile = compute_class.name
        self.refresh_view()

    def keyPressEvent(self, e: QKeyEvent):
        if e.modifiers() & Qt.ControlModifier:
            selected = self.info_field.selectedRanges()

            if e.key() == Qt.Key_C:  # copy
                s = ""

                for r in range(selected[0].topRow(),
                               selected[0].bottomRow() + 1):
                    for c in range(selected[0].leftColumn(),
                                   selected[0].rightColumn() + 1):
                        try:
                            s += str(self.info_field.item(r, c).text()) + "\t"
                        except AttributeError:
                            s += "\t"
                    s = s[:-1] + "\n"  # eliminate last '\t'
                self.clip.setText(s)

    def update_measurement_list(self):
        self.measurement_type.blockSignals(True)
        available = list(sorted(self.settings.measurement_profiles.keys()))
        text = self.measurement_type.currentText()
        try:
            index = available.index(text) + 1
        except ValueError:
            index = 0
        self.measurement_type.clear()
        self.measurement_type.addItem("<none>")
        self.measurement_type.addItems(available)
        self.measurement_type.setCurrentIndex(index)
        self.measurement_type.blockSignals(False)

    def showEvent(self, _):
        self.update_measurement_list()

    def event(self, event: QEvent):
        if event.type() == QEvent.WindowActivate:
            self.update_measurement_list()
        return super().event(event)

    @staticmethod
    def _move_widgets(widgets_list: List[Tuple[QWidget, int]],
                      layout1: QBoxLayout, layout2: QBoxLayout):
        for el in widgets_list:
            layout1.removeWidget(el[0])
            layout2.addWidget(el[0], el[1])

    def resizeEvent(self, _event: QResizeEvent) -> None:
        if self.width() < 800 and self.butt_layout2.count() == 0:
            self._move_widgets(
                [(self.file_names_label, 1), (self.file_names, 1),
                 (self.copy_button, 2)],
                self.butt_layout,
                self.butt_layout2,
            )
        elif self.width() > 800 and self.butt_layout2.count() != 0:
            self._move_widgets(
                [(self.file_names_label, 1), (self.file_names, 1),
                 (self.copy_button, 2)],
                self.butt_layout2,
                self.butt_layout,
            )
コード例 #7
0
ファイル: rulesctrl.py プロジェクト: hzyrc6011/pmgwidgets
class PMGRuleCtrl(BaseExtendedWidget):
    """
    rules:
    {'name':'regex',
    'text':'匹配正则表达式',
    'init':False
    }
    """
    def __init__(self,
                 layout_dir='v',
                 title='',
                 rules: List[Dict[str, Union[bool, int, float, str]]] = None):
        super().__init__(layout_dir)
        self.table_h_headers = []
        self.table_keys = []
        self.initial_values = []
        for rule in rules:
            self.table_h_headers.append(rule['text'])
            self.table_keys.append(rule['name'])
            self.initial_values.append(rule['init'])
        self.regulations_table = QTableWidget(0, len(self.table_h_headers))
        self.regulations_table.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        self.regulations_table.setHorizontalHeaderLabels(self.table_h_headers)

        self.layout().addWidget(self.regulations_table)
        self.set_layout = QHBoxLayout()
        self.layout().addLayout(self.set_layout)
        self.button_add = QPushButton('Add')
        self.button_remove = QPushButton('Remove')
        self.set_layout.addWidget(self.button_add)
        self.set_layout.addWidget(self.button_remove)
        self.button_add.clicked.connect(self.add_regulation)
        self.button_remove.clicked.connect(self.remove_regulation)

    def load_regulations(self, regulations: List[Dict[str,
                                                      Union[int, str, float,
                                                            bool]]]):
        row_count = len(regulations)
        self.regulations_table.setRowCount(row_count)
        for i, regulation in enumerate(regulations):
            l = [regulation[k] for k in self.table_keys]
            for j, obj in enumerate(l):
                item = QTableWidgetItem()
                item.setData(0, obj)
                self.regulations_table.setItem(i, j, item)

    def add_regulation(self):
        rc = self.regulations_table.rowCount()
        self.regulations_table.setRowCount(rc + 1)
        for i, obj in enumerate(self.initial_values):
            item = QTableWidgetItem()
            item.setData(0, obj)
            self.regulations_table.setItem(rc, i, item)

    def remove_regulation(self):
        self.regulations_table.removeRow(self.regulations_table.currentRow())

    def get_value(self) -> List[Dict]:
        l = []
        for i in range(self.regulations_table.rowCount()):
            dic = {}
            for j in range(self.regulations_table.columnCount()):
                item = self.regulations_table.item(i, j)
                dic[self.table_keys[j]] = item.data(0)
            l.append(dic)
        return l

    def set_value(self, value):
        self.load_regulations(value)
コード例 #8
0
ファイル: qt_extension2reader.py プロジェクト: kne42/napari
class Extension2ReaderTable(QWidget):
    """Table showing extension to reader mappings with removal button.

    Widget presented in preferences-plugin dialog."""

    valueChanged = Signal(int)

    def __init__(self, parent=None, npe2_readers=None, npe1_readers=None):
        super().__init__(parent=parent)

        npe2, npe1 = get_all_readers()
        if npe2_readers is None:
            npe2_readers = npe2
        if npe1_readers is None:
            npe1_readers = npe1

        self._npe2_readers = npe2_readers
        self._npe1_readers = npe1_readers

        self._table = QTableWidget()
        self._table.setShowGrid(False)
        self._set_up_table()
        self._edit_row = self._make_new_preference_row()
        self._populate_table()

        instructions = QLabel(
            trans.
            _('Enter a filename pattern to associate with a reader e.g. "*.tif" for all TIFF files.'
              ) + trans.
            _('Available readers will be filtered to those compatible with your pattern. Hover over a reader to see what patterns it accepts.'
              ) + trans.
            _('\n\nPreference saving for folder readers is not supported, so these readers are not shown.'
              ) + trans.
            _('\n\nFor documentation on valid filename patterns, see https://docs.python.org/3/library/fnmatch.html'
              ))
        instructions.setWordWrap(True)
        instructions.setOpenExternalLinks(True)

        layout = QVBoxLayout()
        instructions.setSizePolicy(QSizePolicy.MinimumExpanding,
                                   QSizePolicy.Expanding)
        layout.addWidget(instructions)
        layout.addWidget(self._edit_row)
        layout.addWidget(self._table)
        self.setLayout(layout)

    def _set_up_table(self):
        """Add table columns and headers, define styling"""
        self._fn_pattern_col = 0
        self._reader_col = 1

        header_strs = [trans._('Filename Pattern'), trans._('Reader Plugin')]

        self._table.setColumnCount(2)
        self._table.setColumnWidth(self._fn_pattern_col, 200)
        self._table.setColumnWidth(self._reader_col, 200)
        self._table.verticalHeader().setVisible(False)
        self._table.setMinimumHeight(120)
        self._table.horizontalHeader().setStyleSheet(
            'border-bottom: 2px solid white;')
        self._table.setHorizontalHeaderLabels(header_strs)
        self._table.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

    def _populate_table(self):
        """Add row for each extension to reader mapping in settings"""

        fnpattern2reader = get_settings().plugins.extension2reader
        if len(fnpattern2reader) > 0:
            for fn_pattern, plugin_name in fnpattern2reader.items():
                self._add_new_row(fn_pattern, plugin_name)
        else:
            # Display that there are no filename patterns with reader associations
            self._display_no_preferences_found()

    def _make_new_preference_row(self):
        """Make row for user to add a new filename pattern assignment"""
        edit_row_widget = QWidget()
        edit_row_widget.setLayout(QGridLayout())
        edit_row_widget.layout().setContentsMargins(0, 0, 0, 0)

        self._fn_pattern_edit = QLineEdit()
        self._fn_pattern_edit.setPlaceholderText(
            "Start typing filename pattern...")
        self._fn_pattern_edit.textChanged.connect(
            self._filter_compatible_readers)

        add_reader_widg = QWidget()
        add_reader_widg.setLayout(QHBoxLayout())
        add_reader_widg.layout().setContentsMargins(0, 0, 0, 0)

        self._new_reader_dropdown = QComboBox()
        for i, (plugin_name, display_name) in enumerate(
                sorted(dict(self._npe2_readers,
                            **self._npe1_readers).items())):
            self._add_reader_choice(i, plugin_name, display_name)

        add_btn = QPushButton('Add')
        add_btn.setToolTip(trans._('Save reader preference for pattern'))
        add_btn.clicked.connect(self._save_new_preference)

        add_reader_widg.layout().addWidget(self._new_reader_dropdown)
        add_reader_widg.layout().addWidget(add_btn)

        edit_row_widget.layout().addWidget(
            self._fn_pattern_edit,
            0,
            0,
        )
        edit_row_widget.layout().addWidget(add_reader_widg, 0, 1)

        return edit_row_widget

    def _display_no_preferences_found(self):
        self._table.setRowCount(1)
        item = QTableWidgetItem(trans._('No filename preferences found.'))
        item.setFlags(Qt.NoItemFlags)
        self._table.setItem(self._fn_pattern_col, 0, item)

    def _add_reader_choice(self, i, plugin_name, display_name):
        """Add dropdown item for plugin_name with reader pattern tooltip"""
        reader_patterns = get_filename_patterns_for_reader(plugin_name)
        # TODO: no reader_patterns means directory reader,
        # we don't support preference association yet
        if not reader_patterns:
            return

        self._new_reader_dropdown.addItem(display_name, plugin_name)
        if '*' in reader_patterns:
            tooltip_text = 'Accepts all'
        else:
            reader_patterns_formatted = ', '.join(sorted(
                list(reader_patterns)))
            tooltip_text = f'Accepts: {reader_patterns_formatted}'
        self._new_reader_dropdown.setItemData(i,
                                              tooltip_text,
                                              role=Qt.ToolTipRole)

    def _filter_compatible_readers(self, new_pattern):
        """Filter reader dropwdown items to those that accept `new_extension`"""
        self._new_reader_dropdown.clear()

        readers = self._npe2_readers.copy()
        to_delete = []

        compatible_readers = get_potential_readers(new_pattern)
        for plugin_name, display_name in readers.items():
            if plugin_name not in compatible_readers:
                to_delete.append(plugin_name)

        for reader in to_delete:
            del readers[reader]
        readers.update(self._npe1_readers)

        if not readers:
            self._new_reader_dropdown.addItem("None available")
        else:
            for i, (plugin_name,
                    display_name) in enumerate(sorted(readers.items())):
                self._add_reader_choice(i, plugin_name, display_name)

    def _save_new_preference(self, event):
        """Save current preference to settings and show in table"""
        fn_pattern = self._fn_pattern_edit.text()
        reader = self._new_reader_dropdown.currentData()

        if not fn_pattern or not reader:
            return

        # if user types pattern that starts with a . it's probably a file extension so prepend the *
        if fn_pattern.startswith('.'):
            fn_pattern = f'*{fn_pattern}'

        if fn_pattern in get_settings().plugins.extension2reader:
            self._edit_existing_preference(fn_pattern, reader)
        else:
            self._add_new_row(fn_pattern, reader)
        get_settings().plugins.extension2reader = {
            **get_settings().plugins.extension2reader,
            fn_pattern: reader,
        }

    def _edit_existing_preference(self, fn_pattern, reader):
        """Edit existing extension preference"""
        current_reader_label = self.findChild(QLabel, fn_pattern)
        if reader in self._npe2_readers:
            reader = self._npe2_readers[reader]
        current_reader_label.setText(reader)

    def _add_new_row(self, fn_pattern, reader):
        """Add new reader preference to table"""
        last_row = self._table.rowCount()

        if (last_row == 1 and 'No filename preferences found'
                in self._table.item(0, 0).text()):
            self._table.removeRow(0)
            last_row = 0

        self._table.insertRow(last_row)
        item = QTableWidgetItem(fn_pattern)
        item.setFlags(Qt.NoItemFlags)
        self._table.setItem(last_row, self._fn_pattern_col, item)

        plugin_widg = QWidget()
        # need object name to easily find row
        plugin_widg.setObjectName(f'{fn_pattern}')
        plugin_widg.setLayout(QHBoxLayout())
        plugin_widg.layout().setContentsMargins(0, 0, 0, 0)

        if reader in self._npe2_readers:
            reader = self._npe2_readers[reader]
        plugin_label = QLabel(reader, objectName=fn_pattern)
        # need object name to easily work out which button was clicked
        remove_btn = QPushButton('X', objectName=fn_pattern)
        remove_btn.setFixedWidth(30)
        remove_btn.setStyleSheet('margin: 4px;')
        remove_btn.setToolTip(
            trans._('Remove this filename pattern to reader association'))
        remove_btn.clicked.connect(self.remove_existing_preference)

        plugin_widg.layout().addWidget(plugin_label)
        plugin_widg.layout().addWidget(remove_btn)
        self._table.setCellWidget(last_row, self._reader_col, plugin_widg)

    def remove_existing_preference(self, event):
        """Delete extension to reader mapping setting and remove table row"""
        pattern_to_remove = self.sender().objectName()
        current_settings = get_settings().plugins.extension2reader
        # need explicit assignment to new object here for persistence
        get_settings().plugins.extension2reader = {
            k: v
            for k, v in current_settings.items() if k != pattern_to_remove
        }

        for i in range(self._table.rowCount()):
            row_widg_name = self._table.cellWidget(
                i, self._reader_col).objectName()
            if row_widg_name == pattern_to_remove:
                self._table.removeRow(i)
                break

        if self._table.rowCount() == 0:
            self._display_no_preferences_found()

    def value(self):
        """Return extension:reader mapping from settings.

        Returns
        -------
        Dict[str, str]
            mapping of extension to reader plugin display name
        """
        return get_settings().plugins.extension2reader