class MaskDialog(QDialog): def __init__(self, mask_names): super().__init__() self.mask_names = mask_names completer = QCompleter(list(mask_names)) completer.setCaseSensitivity(Qt.CaseInsensitive) self.setWindowTitle("Masks name choose") self.mask1_name = QLineEdit() self.cancel_btn = QPushButton("Cancel") self.ok_btn = QPushButton("Ok") self.mask1_name.setCompleter(completer) self.mask1_name.textChanged.connect(self.text_changed) self.cancel_btn.clicked.connect(self.close) self.ok_btn.clicked.connect(self.accept) self.ok_btn.setDisabled(True) layout = QGridLayout() layout.addWidget(right_label("Mask 1 name:"), 0, 0) layout.addWidget(self.mask1_name, 0, 1) layout.addWidget(self.cancel_btn, 2, 0) layout.addWidget(self.ok_btn, 2, 1) self.setLayout(layout) def text_changed(self): text1 = self.get_result()[0] if text1 == "" or text1 not in self.mask_names: self.ok_btn.setDisabled(True) else: self.ok_btn.setDisabled(False) def get_result(self): text1 = str(self.mask1_name.text()).strip() return (text1,)
class TwoMaskDialog(QDialog): def __init__(self, mask_names): """ :type mask_names: set :param mask_names: iterable collection of all available mask names """ super().__init__() self.mask_names = mask_names completer = QCompleter(list(mask_names)) completer.setCaseSensitivity(Qt.CaseInsensitive) self.setWindowTitle("Masks name choose") self.mask1_name = QLineEdit() self.mask2_name = QLineEdit() self.cancel_btn = QPushButton("Cancel") self.ok_btn = QPushButton("Ok") self.mask1_name.setCompleter(completer) self.mask1_name.textChanged.connect(self.text_changed) self.mask2_name.setCompleter(completer) self.mask2_name.textChanged.connect(self.text_changed) self.cancel_btn.clicked.connect(self.close) self.ok_btn.clicked.connect(self.accept) self.ok_btn.setDisabled(True) layout = QGridLayout() layout.addWidget(right_label("Mask 1 name:"), 0, 0) layout.addWidget(self.mask1_name, 0, 1) layout.addWidget(right_label("Mask 2 name:"), 1, 0) layout.addWidget(self.mask2_name, 1, 1) layout.addWidget(self.cancel_btn, 2, 0) layout.addWidget(self.ok_btn, 2, 1) self.setLayout(layout) def text_changed(self): text1, text2 = self.get_result() if text1 == "" or text2 == "" or text1 not in self.mask_names or text2 not in self.mask_names: self.ok_btn.setDisabled(True) return else: self.ok_btn.setDisabled(text1 == text2) def get_result(self): text1 = str(self.mask1_name.text()).strip() text2 = str(self.mask2_name.text()).strip() return text1, text2
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)
import sys from qtpy.QtCore import Qt from qtpy.QtWidgets import QApplication, QCompleter, QLineEdit, QStringListModel def get_data(model): model.setStringList(["completion", "data", "goes", "here"]) if __name__ == "__main__": app = QApplication(sys.argv) edit = QLineEdit() completer = QCompleter() edit.setCompleter(completer) model = QStringListModel() completer.setModel(model) get_data(model) edit.show() sys.exit(app.exec_())
class PMGListCtrl(BaseExtendedWidget): def __init__(self, layout_dir: str, title: str, initial_value: List[List[str]], new_id_func: Callable = None): super().__init__(layout_dir) self.choices = [] self.text_list = [] lab_title = QLabel(text=title) layout = QHBoxLayout() self.central_layout.addWidget(lab_title) self.on_check_callback = None self.list_widget = QListWidget() self.list_widget.mouseDoubleClickEvent = self.on_listwidget_double_cicked self.set_value(initial_value) layout_tools = QVBoxLayout() self.button_add_item = QPushButton('+') self.button_delete_item = QPushButton('-') self.button_delete_item.clicked.connect(self.delete_row) self.button_add_item.clicked.connect(self.add_row) self.button_add_item.setMaximumWidth(20) self.button_delete_item.setMaximumWidth(20) layout_tools.addWidget(self.button_add_item) layout_tools.addWidget(self.button_delete_item) layout.addLayout(layout_tools) layout.addWidget(self.list_widget) self.central_layout.addLayout(layout) self.data = initial_value self.new_id_func = new_id_func self.text_edit = QLineEdit(parent=self.list_widget) self.text_edit.setWindowFlags(self.text_edit.windowFlags() | Qt.Dialog | Qt.FramelessWindowHint) self.text_edit.hide() self.completer = QCompleter() self.text_edit.setCompleter(self.completer) self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion) def set_completions(self, completions: List[str]): """ 设置补全内容 Args: completions: Returns: """ self.completer.setModel(QStringListModel(completions)) def new_id(self): if callable(self.new_id_func): return self.new_id_func() else: return None def add_row(self): self.data = self.get_value() self.data[0].append(self.new_id()) self.data[1].append('Unnamed') self.list_widget.addItem(QListWidgetItem('Unnamed')) def delete_row(self): index = self.list_widget.currentIndex().row() self.data[0].pop(index) self.data[1].pop(index) self.list_widget.takeItem(index) def on_listwidget_double_cicked(self, evt: QMouseEvent): print('edit', evt) pos = evt.globalPos() current_item: QListWidgetItem = self.list_widget.currentItem() def set_value(): current_item.setText(self.text_edit.text()) self.text_edit.hide() self.text_edit.returnPressed.disconnect(set_value) item: QListWidgetItem = self.list_widget.currentItem() self.text_edit.setGeometry(pos.x(), pos.y(), 200, 20) self.text_edit.returnPressed.connect(set_value) self.text_edit.show() # self.list_widget.editItem(item) def get_value(self): text = [] for i in range(self.list_widget.count()): text.append(self.list_widget.item(i).text()) self.data[1] = text assert len(self.data[1]) == len(self.data[0]), repr(self.data) return self.data def set_value(self, data: List[List[str]]): self.list_widget.clear() self.list_widget.addItems(data[1]) self.data = data for index in range(self.list_widget.count()): item: QListWidgetItem = self.list_widget.item(index)
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)
class PhasePlaneDialog(QDialog): """A dialog to create phase plane plots""" def __init__(self, appdata): QDialog.__init__(self) self.setWindowTitle("Phase plane plotting") self.appdata = appdata completer = QCompleter( self.appdata.project.cobra_py_model.reactions.list_attr("id"), self) completer.setCaseSensitivity(Qt.CaseInsensitive) self.layout = QVBoxLayout() l1 = QHBoxLayout() t1 = QLabel("Reaction (x-axis):") l1.addWidget(t1) self.x_axis = CompleterLineEdit( self.appdata.project.cobra_py_model.reactions.list_attr("id"), "") self.x_axis.setPlaceholderText("Enter reaction Id") l1.addWidget(self.x_axis) l2 = QHBoxLayout() t2 = QLabel("Reaction (y-axis):") l2.addWidget(t2) self.y_axis = QLineEdit("") self.y_axis.setPlaceholderText("Enter reaction Id") self.y_axis.setCompleter(completer) l2.addWidget(self.y_axis) self.layout.addItem(l1) self.layout.addItem(l2) l3 = QHBoxLayout() self.button = QPushButton("Plot") self.cancel = QPushButton("Close") l3.addWidget(self.button) l3.addWidget(self.cancel) self.layout.addItem(l3) self.setLayout(self.layout) # Connecting the signal self.cancel.clicked.connect(self.reject) self.button.clicked.connect(self.compute) def compute(self): self.setCursor(Qt.BusyCursor) with self.appdata.project.cobra_py_model as model: self.appdata.project.load_scenario_into_model(model) x_axis = self.x_axis.text() y_axis = self.y_axis.text() try: x_reac_idx = model.reactions.index(x_axis) y_reac_idx = model.reactions.index(y_axis) except KeyError: return points = 100 with model as ppmodel: ppmodel.objective = ppmodel.reactions[x_reac_idx] ppmodel.objective.direction = 'min' x_lb = ppmodel.slim_optimize() ppmodel.objective.direction = 'max' x_ub = ppmodel.slim_optimize() result2 = numpy.zeros((points, 3)) result2[:, 0] = numpy.linspace(x_lb, x_ub, num=points) var = numpy.linspace(x_lb, x_ub, num=points) lb = numpy.full(points, numpy.nan) ub = numpy.full(points, numpy.nan) with model as ppmodel: ppmodel.objective = ppmodel.reactions[y_reac_idx] for i in range(points): # without second context the original reaction bounds are not restored (?) with ppmodel as ppmodel2: ppmodel2.reactions[x_reac_idx].lower_bound = result2[i, 0] ppmodel2.reactions[x_reac_idx].upper_bound = result2[i, 0] ppmodel2.objective.direction = 'min' lb[i] = result2[i, 1] = ppmodel2.slim_optimize() ppmodel2.objective.direction = 'max' ub[i] = result2[i, 2] = ppmodel2.slim_optimize() _fig, axes = plt.subplots() axes.set_xlabel(model.reactions[x_reac_idx].id) axes.set_ylabel(model.reactions[y_reac_idx].id) x = [v for v in var] + [v for v in reversed(var)] y = [v for v in lb] + [v for v in reversed(ub)] if lb[0] != ub[0]: x.extend([var[0], var[0]]) y.extend([lb[0], ub[0]]) plt.plot(x, y) plt.show() self.appdata.window.centralWidget().show_bottom_of_console() self.setCursor(Qt.ArrowCursor)
class LabelDialog(QDialog): def __init__(self, text="Enter object label", parent=None, listItem=None): super(LabelDialog, self).__init__(parent) self.edit = QLineEdit() self.edit.setText(text) self.edit.setValidator(self.label_validator()) self.edit.editingFinished.connect(self.post_process) model = QStringListModel() model.setStringList(listItem) completer = QCompleter() completer.setModel(model) self.edit.setCompleter(completer) layout = QVBoxLayout() layout.addWidget(self.edit) self.buttonBox = bb = BB(BB.Ok | BB.Cancel, Qt.Horizontal, self) bb.button(BB.Ok).setIcon(QIcon('icons/done.png')) bb.button(BB.Cancel).setIcon(QIcon('icons/undo.png')) bb.accepted.connect(self.validate) bb.rejected.connect(self.reject) layout.addWidget(bb) if listItem is not None and len(listItem) > 0: self.listWidget = QListWidget(self) for item in listItem: self.listWidget.addItem(item) self.listWidget.itemClicked.connect(self.listItemClick) self.listWidget.itemDoubleClicked.connect(self.listItemDoubleClick) layout.addWidget(self.listWidget) self.setLayout(layout) def label_validator(self): return QRegExpValidator(QRegExp(r'^[^ \t].+'), None) def validate(self): try: if self.edit.text().trimmed(): self.accept() except AttributeError: if self.edit.text().strip(): self.accept() def post_process(self): try: self.edit.setText(self.edit.text().trimmed()) except AttributeError: self.edit.setText(self.edit.text()) def pop_up(self, text='', move=True): self.edit.setText(text) self.edit.setSelection(0, len(text)) self.edit.setFocus(Qt.PopupFocusReason) if move: self.move(QCursor.pos()) return self.edit.text() if self.exec_() else None def listItemClick(self, tQListWidgetItem): try: text = tQListWidgetItem.text().trimmed() except AttributeError: # PyQt5: AttributeError: 'str' object has no attribute 'trimmed' text = tQListWidgetItem.text().strip() self.edit.setText(text) def listItemDoubleClick(self, tQListWidgetItem): self.listItemClick(tQListWidgetItem) self.validate()