class CompleterLineEdit(QLineEdit): '''# does new completion after COMMA ,''' def __init__(self, wordlist, *args): QLineEdit.__init__(self, *args) self.mycompleter = QCompleter(wordlist) self.mycompleter.setCaseSensitivity(Qt.CaseInsensitive) self.mycompleter.setWidget(self) self.textChanged.connect(self.text_changed) self.mycompleter.activated.connect(self.complete_text) def text_changed(self, text): all_text = text text = all_text[:self.cursorPosition()] prefix = text.split(',')[-1].strip() self.mycompleter.setCompletionPrefix(prefix) if prefix != '': self.mycompleter.complete() def complete_text(self, text): cursor_pos = self.cursorPosition() before_text = self.text()[:cursor_pos] after_text = self.text()[cursor_pos:] prefix_len = len(before_text.split(',')[-1].strip()) self.setText(before_text[:cursor_pos - prefix_len] + text + after_text) self.setCursorPosition(cursor_pos - prefix_len + len(text)) textChangedX = Signal(str)
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)
class SearchCombBox(QComboBox): """ ComboCox with completer for fast search in multiple options """ if parse(QT_VERSION) < parse("5.14.0"): textActivated = Signal(str) # pragma: no cover def __init__(self, parent=None): super().__init__(parent) self.setEditable(True) self.completer_object = QCompleter() self.completer_object.setCaseSensitivity(Qt.CaseInsensitive) self.setCompleter(self.completer_object) # FIXME if parse(QT_VERSION) < parse("5.14.0"): # pragma: no cover self.currentIndexChanged.connect(self._text_activated) def _text_activated(self): # pragma: no cover self.textActivated.emit(self.currentText()) def addItem(self, *args): super().addItem(*args) self.completer_object.setModel(self.model()) def addItems(self, *args): super().addItems(*args) self.completer_object.setModel(self.model())
def initialize(self): history = STATUS.mdi_history.value if self._completer_enabled: completer = QCompleter() completer.setCaseSensitivity(Qt.CaseInsensitive) self.model = QStringListModel() completer.setModel(self.model) self.setCompleter(completer) self.model.setStringList(history) STATUS.mdi_history.notify(self.model.setStringList) STATUS.max_mdi_history_length = self.mdi_history_size
def __init__(self, appdata: CnaData, centralwidget: CentralWidget): QDialog.__init__(self) self.setWindowTitle("Yield optimization") self.appdata = appdata self.centralwidget = centralwidget self.eng = appdata.engine self.linear_re = re.compile( r'([ ]*(?P<factor1>[-]?\d*)[ ]*[*]?[ ]*(?P<reac_id>[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW]+\w*)[ ]*[*]?[ ]*(?P<factor2>[-]?\d*)[ ]*)' ) completer = QCompleter( self.appdata.project.cobra_py_model.reactions.list_attr("id"), self) completer.setCaseSensitivity(Qt.CaseInsensitive) self.layout = QVBoxLayout() l = QLabel( "Define the yield function Y=c*r/d*r by providing c and d as linear expression of form: \n \ id_1 * w_1 + ... id_n * w_n\n \ Where id_x are reaction ids and w_x optional weighting factor\n" ) self.layout.addWidget(l) t1 = QLabel("Define c") self.layout.addWidget(t1) self.c = CompleterLineEdit( self.appdata.project.cobra_py_model.reactions.list_attr("id"), "") self.c.setCompleter(completer) self.c.setPlaceholderText("") self.layout.addWidget(self.c) t2 = QLabel("Define d") self.layout.addWidget(t2) self.d = CompleterLineEdit( self.appdata.project.cobra_py_model.reactions.list_attr("id"), "") self.d.setPlaceholderText("") self.d.setCompleter(completer) self.layout.addWidget(self.d) l3 = QHBoxLayout() self.button = QPushButton("Compute") self.cancel = QPushButton("Close") l3.addWidget(self.button) l3.addWidget(self.cancel) self.layout.addItem(l3) self.setLayout(self.layout) # Connecting the signal self.c.textChangedX.connect(self.validate_dialog) self.d.textChangedX.connect(self.validate_dialog) self.cancel.clicked.connect(self.reject) self.button.clicked.connect(self.compute) self.validate_dialog()
class AutoCompleteLineEdit(QLineEdit): # http://blog.elentok.com/2011/08/autocomplete-textbox-for-multiple.html def __init__(self, items, parent=None): super().__init__(parent) self._separators = [",", " "] self._completer = QCompleter(items, self) self._completer.setWidget(self) self._completer.activated[str].connect(self.__insertCompletion) self._completer.setCaseSensitivity(Qt.CaseInsensitive) self.__keysToIgnore = [ Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab ] def __insertCompletion(self, completion): extra = len(completion) - len(self._completer.completionPrefix()) extra_text = completion[-extra:] extra_text += ", " self.setText(self.text() + extra_text) def textUnderCursor(self): text = self.text() text_under_cursor = "" i = self.cursorPosition() - 1 while i >= 0 and text[i] not in self._separators: text_under_cursor = text[i] + text_under_cursor i -= 1 return text_under_cursor def keyPressEvent(self, event): if self._completer.popup().isVisible(): if event.key() in self.__keysToIgnore: event.ignore() return super().keyPressEvent(event) completion_prefix = self.textUnderCursor() if completion_prefix != self._completer.completionPrefix(): self.__updateCompleterPopupItems(completion_prefix) if len(event.text()) > 0 and len(completion_prefix) > 0: self._completer.complete() if len(completion_prefix) == 0: self._completer.popup().hide() def __updateCompleterPopupItems(self, completionPrefix): self._completer.setCompletionPrefix(completionPrefix) self._completer.popup().setCurrentIndex( self._completer.completionModel().index(0, 0))
def __init__(self, parent=None): super(MDIEntry, self).__init__(parent) self.model = QStringListModel() completer = QCompleter() completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setModel(self.model) self.setCompleter(completer) self.validator = Validator(self) self.setValidator(self.validator) self.returnPressed.connect(self.submit)
def __init__(self, parent=None): super(MDIEntry, self).__init__(parent) self.mdi_rtnkey_behaviour_supressed = False self.mdi_history_size = 100 completer = QCompleter() completer.setCaseSensitivity(Qt.CaseInsensitive) self.model = QStringListModel() completer.setModel(self.model) self.setCompleter(completer) self.validator = Validator(self) self.setValidator(self.validator) self.returnPressed.connect(self.submit)
def __init__(self, parent=None): super(FileBrowserInputWidget, self).__init__(parent=parent) # setup model self.model = QFileSystemModel() self.model.setRootPath('/home/') filters = self.model.filter() self.model.setFilter(filters | QDir.Hidden) # setup completer completer = QCompleter(self.model, self) self.setCompleter(completer) installCompleterPopup(completer) self.setCompleter(completer) completer.setCaseSensitivity(Qt.CaseInsensitive) self.autoCompleteList = []
def __init__(self, parent=None): super(MDIEntry, self).__init__(parent) self.model = QStringListModel() completer = QCompleter() completer.setCaseSensitivity(Qt.CaseInsensitive) completer.setModel(self.model) self.setCompleter(completer) self.validator = Validator(self) self.setValidator(self.validator) self.loadMDIHystory() self.returnPressed.connect(self.submit) QApplication.instance().aboutToQuit.connect(self.saveMDIHistory)
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 __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 __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 AbstractComboListInputWidget(QComboBox): """ A custom QComboBox with a completer / model. This is designed to be an abstract class that will be inherited by the the GSV and Node ComboBoxes Attributes: exists (bool) flag used to determine whether or not the popup menu for the menu change should register or not (specific to copy/paste of a node. In plain english... this flag is toggled to hide the Warning PopUp Box from displaying to the user in some events. item_list (list): string list of all of the items in the list. Updating this will auto update the default settings for blank setups previous_text (str): the previous items text. This is stored for cancel events and allowing the user to return to the previous item after cancelling. """ TYPE = 'list' def __init__(self, parent=None): super(AbstractComboListInputWidget, self).__init__(parent) self.main_widget = self.parent() self.previous_text = '' self.setExistsFlag(True) # setup line edit #self.line_edit = QLineEdit("Select & Focus", self) self.line_edit = QLineEdit(self) self.line_edit.editingFinished.connect(self.userFinishedEditing) self.setLineEdit(self.line_edit) self.setEditable(True) # setup completer self.completer = QCompleter(self) self.completer.setCompletionMode(QCompleter.PopupCompletion) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setPopup(self.view()) self.setCompleter(self.completer) self.pFilterModel = QSortFilterProxyModel(self) # set size policy ( this will ignore the weird resizing effects) size_policy = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Preferred) self.setSizePolicy(size_policy) # initialize model... model = QStandardItemModel() self.setModel(model) self.setModelColumn(0) def populate(self, item_list): """ Creates all of the items from the item list and appends them to the model. item_list (list): list of strings to be displayed to the user this should be set with the setCleanItemsFunction. """ self.setItemList(item_list) for i, item_name in enumerate(self.getItemList()): item = QStandardItem(item_name) self.model().setItem(i, 0, item) self.setExistsFlag(False) def update(self): """ Updates the model items with all of the graph state variables. This is very similar to the populate call, except that with this, it will remove all of the items except for the current one. Which will ensure that an indexChanged event is not registered thus updating the UI. """ self.setExistsFlag(False) self.model().clear() self.populate(self.getCleanItems()) self.setCurrentIndexToText(self.previous_text) self.setExistsFlag(True) def setModel(self, model): # somehow this super makes the node type not resize... super(AbstractListInputWidget, self).setModel(model) self.pFilterModel.setSourceModel(model) self.completer.setModel(self.pFilterModel) def setModelColumn(self, column): self.completer.setCompletionColumn(column) self.pFilterModel.setFilterKeyColumn(column) super(AbstractListInputWidget, self).setModelColumn(column) def view(self): return self.completer.popup() """ UTILS """ def next_completion(self): row = self.completer.currentRow() # if does not exist reset if not self.completer.setCurrentRow(row + 1): self.completer.setCurrentRow(0) # if initializing if self.completer.popup().currentIndex().row() == -1: self.completer.setCurrentRow(0) index = self.completer.currentIndex() self.completer.popup().setCurrentIndex(index) def previous_completion(self): row = self.completer.currentRow() numRows = self.completer.completionCount() # if wrapping if not self.completer.setCurrentRow(row - 1): self.completer.setCurrentRow(numRows - 1) # if initializing if self.completer.popup().currentIndex().row() == -1: self.completer.setCurrentRow(numRows - 1) index = self.completer.currentIndex() self.completer.popup().setCurrentIndex(index) def setCurrentIndexToText(self, text): """ Sets the current index to the text provided. If no match can be found, this will default back to the first index. If no first index... create '' ? """ self.setExistsFlag(False) # get all matches items = self.model().findItems(text, Qt.MatchExactly) # set to index of match if len(items) > 0: index = self.model().indexFromItem(items[0]).row() self.setCurrentIndex(index) else: self.setCurrentIndex(0) self.previous_text = self.currentText() self.setExistsFlag(True) def isUserInputValid(self): """ Determines if the new user input is currently in the model. Returns True if this is an existing item, Returns false if it is not. """ items = self.model().findItems(self.currentText(), Qt.MatchExactly) if len(items) > 0: return True else: return False def setupStyleSheet(self): width = self.width() dropdown_width = int(width * 0.35) style_sheet_args = iColor.style_sheet_args style_sheet_args['width'] = dropdown_width # QComboBox {{ # border: None; # background-color: rgba{rgba_gray_0} # }} style_sheet = """ QComboBox{{ border: None; background-color: rgba{rgba_gray_0}; color: rgba{rgba_text}; }} QComboBox::drop-down {{ width: {width}px; }} QLineEdit{{ border: None; background-color: rgba{rgba_gray_0}; color: rgba{rgba_text}; }} QListView{{ border: None; background-color: rgba{rgba_gray_0}; color: rgba{rgba_text}; }} QListView::item:hover{{ background-color: rgba(255,0,0,255); }} """.format(**style_sheet_args) self.completer.popup().setStyleSheet(""" QListView{{ border: None; background-color: rgba{rgba_gray_0}; color: rgba{rgba_text}; }} QListView::item:hover{{ background-color: rgba(255,0,0,255); }} """.format(**style_sheet_args)) self.setStyleSheet(style_sheet) """ API """ def __selectionChangedEmit(self): pass def setSelectionChangedEmitEvent(self, method): """ sets the method for the selection changed emit call this will be called everytime the user hits enter/return inside of the line edits as a way of sending an emit signal from the current text changed (finalized) before input changed event... """ self.__selectionChangedEmit = method def __getCleanItems(self): return [] def setCleanItemsFunction(self, function): """ Sets the function to get the list of strings to populate the model function (function): function to return a list of strings to be shown to the user """ self.__getCleanItems = function def getCleanItems(self): """ Returns a list of strings based off of the function set with setCleanItemsFunction """ return self.__getCleanItems() """ EVENTS """ def userFinishedEditing(self): is_input_valid = self.isUserInputValid() if is_input_valid: self.__selectionChangedEmit() self.previous_text = self.currentText() #self.userFinishedEditingEvent(self.currentText()) else: self.setCurrentIndexToText(self.previous_text) def resizeEvent(self, event): self.setupStyleSheet() return QComboBox.resizeEvent(self, event) def event(self, event, *args, **kwargs): """ Registering key presses in here as for some reason they don't work in the keyPressEvent method... """ if event.type() == QEvent.KeyPress: # tab if event.key() == Qt.Key_Tab: self.next_completion() return True # shift tab elif event.key() == Qt.Key_Tab + 1: self.previous_completion() return True # enter pressed elif event.key() in [Qt.Key_Return, Qt.Key_Enter, Qt.Key_Down]: self.__selectionChangedEmit() elif event.type() == QEvent.MouseButtonRelease: self.completer.setPopup(self.view()) return QComboBox.event(self, event, *args, **kwargs) """ PROPERTIES """ def getExistsFlag(self): return self._exists def setExistsFlag(self, exists): self._exists = exists def getItemList(self): return self._item_list def setItemList(self, item_list): if self.previous_text == '': item_list.insert(0, '') self._item_list = item_list @property def previous_text(self): return self._previous_text @previous_text.setter def previous_text(self, previous_text): self._previous_text = previous_text
class AddPatchDialog(QDialog, Ui_AddPatchDialog): def __init__(self, app, *args, **kwargs): super().__init__(app.mainwin, *args, **kwargs) # Set up the user interface from Designer. self.setupUi(self) self.created_dt.setCalendarPopup(True) # auto-completion set up self.name_completer = QCompleter(app.patches, self.name_entry) self.name_completer.setCompletionColumn(0) self.name_completer.setCaseSensitivity(Qt.CaseInsensitive) self.name_entry.setCompleter(self.name_completer) self.shortname_completer = QCompleter(app.patches, self.shortname_entry) self.shortname_completer.setCompletionColumn(1) self.shortname_completer.setCaseSensitivity(Qt.CaseInsensitive) self.shortname_entry.setCompleter(self.shortname_completer) self.author_model = AuthorListModel(app.session) self.author_cb.setModel(self.author_model) self.author_cb.setModelColumn(2) self.manufacturer_model = ManufacturerListModel(app.session) self.manufacturer_cb.setModel(self.manufacturer_model) self.manufacturer_cb.setModelColumn(3) self.device_model = DeviceListModel(app.session) self.device_cb.setModel(self.device_model) self.device_cb.setModelColumn(3) self._last_author = None def new_from_data(self, data, title=None): if title: self.setWindowTitle(title) if self._last_author is None: self._last_author = get_fullname() name = get_patch_name(data) self.name_entry.setText(name) self.shortname_entry.setText(name) self.created_dt.setDateTime(datetime.now()) self.rating_cb.setCurrentIndex(0) self.tags_entry.setText('') self.description_entry.setPlainText('') author_idx = self.author_cb.findText(self._last_author) if author_idx != -1: self.author_cb.setCurrentIndex(author_idx) else: self.author_cb.setCurrentText(self._last_author) self.manufacturer_cb.setEnabled(False) self.device_cb.setEnabled(False) if self.exec_() == QDialog.Accepted: author = self.author_cb.currentText() self._last_author = author return dict(name=self.shortname_entry.text(), displayname=self.name_entry.text(), author=author, manufacturer=self.manufacturer_cb.currentText(), device=self.device_cb.currentText(), rating=self.rating_cb.currentIndex(), tags=self.tags_entry.text(), description=self.description_entry.toPlainText())
class IdePanel(QPlainTextEdit): def __init__(self): QPlainTextEdit.__init__(self) self.setWordWrapMode(QTextOption.NoWrap) self.setFont(QFont("monospace", 10)) self.setCursorWidth(2) self.installEventFilter(self) self.completer = QCompleter(self) self.completer.setWidget(self) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.activated.connect(self.insertCompletion) auto_complete = QShortcut(QKeySequence("Ctrl+Space"), self) auto_complete.activated.connect(self.activateCompleter) copy_line = QShortcut(QKeySequence("Ctrl+D"), self) copy_line.activated.connect(self.duplicateLine) select_fragment = QShortcut(QKeySequence("Ctrl+J"), self) select_fragment.activated.connect(self.selectFragment) def getText(self): return self.document().toPlainText() def eventFilter(self, qobject, qevent): if qobject == self and qevent.type() == QEvent.ToolTip: text_cursor = self.cursorForPosition(qevent.pos()) pos = text_cursor.positionInBlock() user_data = text_cursor.block().userData() if user_data is not None: #: :type: ConfigurationLine configuration_line = user_data.configuration_line # if configuration_line.keyword().hasKeywordDefinition(): # print(configuration_line.keyword().keywordDefinition().documentation) if pos in configuration_line.keyword(): self.setToolTip( configuration_line.validationStatusForToken( configuration_line.keyword()).message()) else: for argument in configuration_line.arguments(): if pos in argument: self.setToolTip( configuration_line.validationStatusForToken( argument).message()) else: self.setToolTip("") return QPlainTextEdit.eventFilter(self, qobject, qevent) def activateCompleter(self): text_cursor = self.textCursor() block = self.document().findBlock(text_cursor.position()) position_in_block = text_cursor.positionInBlock() self.selectWordUnderCursor(text_cursor) word = unicode(text_cursor.selectedText()) user_data = block.userData() self.completer.setCompletionPrefix(word) show_completer = False if user_data is None: self.completer.setModel(QStringListModel(self.handler_names)) show_completer = True else: keyword = user_data.keyword options = keyword.handler.parameterOptions(keyword, word, position_in_block) if len(options) == 1: self.insertCompletion(options[0]) elif len(options) > 1: self.completer.setModel(QStringListModel(options)) if self.completer.completionCount() == 1: self.insertCompletion(self.completer.currentCompletion()) else: show_completer = True if show_completer: rect = self.cursorRect(text_cursor) rect.setWidth( self.completer.popup().sizeHintForColumn(0) + self.completer.popup().verticalScrollBar().sizeHint().width()) self.completer.complete(rect) def keyPressEvent(self, qkeyevent): if self.completer.popup().isVisible(): dead_keys = [ Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab, Qt.Key_Backtab, ] if qkeyevent.key() in dead_keys: qkeyevent.ignore() return if qkeyevent.modifiers() == Qt.ShiftModifier: if qkeyevent.key() & Qt.Key_Delete == Qt.Key_Delete: self.deleteLine() QPlainTextEdit.keyPressEvent(self, qkeyevent) def insertCompletion(self, string): text_cursor = self.textCursor() self.selectWordUnderCursor(text_cursor) text_cursor.insertText(string) def isCursorInSpace(self): text_cursor = self.textCursor() if text_cursor.positionInBlock() > 0: text_cursor.movePosition(QTextCursor.Left, QTextCursor.MoveAnchor) text_cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor) if text_cursor.positionInBlock() < text_cursor.block().length() - 1: text_cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor) if unicode(text_cursor.selectedText()).strip() == "": return True return False def selectWordUnderCursor(self, text_cursor): if not self.isCursorInSpace(): # text_cursor.select(QTextCursor.WordUnderCursor) # pattern = "[\s|\v|\f|\n|\r|\t|\xe2\x80\xa8|\xe2\x80\xa9]" # pattern = "[\\s|\\xe2\\x80\\xa9|\\xe2\\x80\\xa8]" block_start = 0 block_end = text_cursor.block().length() cursor_pos = text_cursor.positionInBlock() pos = cursor_pos pattern = u"[\\s\u2029\u2028]" while pos >= block_start: text_cursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor) text = text_cursor.selectedText() if re.search(pattern, text): break pos -= 1 text_cursor.movePosition(QTextCursor.Right, QTextCursor.MoveAnchor) while pos < block_end: text_cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor) text = text_cursor.selectedText() if re.search(pattern, text): break pos += 1 text_cursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor) # pattern = "[\\s]" # start = self.document().find(QRegExp(pattern), text_cursor, QTextDocument.FindBackward | QTextDocument.FindCaseSensitively) # end = self.document().find(QRegExp(pattern), text_cursor, QTextDocument.FindCaseSensitively) # block_end_pos = text_cursor.block().position() + text_cursor.block().length() # # text_cursor.setPosition(start.position(), QTextCursor.MoveAnchor) # # text_cursor.setPosition(min(block_end_pos, end.position() - 1), QTextCursor.KeepAnchor) # text_cursor.setPosition(end.position() - 1, QTextCursor.KeepAnchor) def deleteLine(self): text_cursor = self.textCursor() text_cursor.beginEditBlock() text_cursor.select(QTextCursor.LineUnderCursor) text_cursor.removeSelectedText() text_cursor.deletePreviousChar() text_cursor.movePosition(QTextCursor.NextBlock) text_cursor.movePosition(QTextCursor.StartOfLine) self.setTextCursor(text_cursor) text_cursor.endEditBlock() def duplicateLine(self): text_cursor = self.textCursor() text_cursor.beginEditBlock() text_cursor.select(QTextCursor.LineUnderCursor) text = text_cursor.selectedText() text_cursor.movePosition(QTextCursor.EndOfLine) text_cursor.insertBlock() text_cursor.insertText(text) text_cursor.endEditBlock() def selectFragment(self): text_cursor = self.textCursor() self.selectWordUnderCursor(text_cursor) self.setTextCursor(text_cursor)
class AutoComplete(QObject): def __init__(self, parent): super(AutoComplete, self).__init__(parent) self.mode = COMPLETE_MODE.INLINE self.completer = None self._last_key = None parent.edit.installEventFilter(self) self.init_completion_list([]) def eventFilter(self, widget, event): if event.type() == QEvent.KeyPress: return bool(self.key_pressed_handler(event)) return False def key_pressed_handler(self, event): intercepted = False key = event.key() if key == Qt.Key_Tab: intercepted = self.handle_tab_key(event) elif key in (Qt.Key_Return, Qt.Key_Enter, Qt.Key_Space): intercepted = self.handle_complete_key(event) elif key == Qt.Key_Escape: intercepted = self.hide_completion_suggestions() self._last_key = key self.update_completion(key) return intercepted def handle_tab_key(self, event): if self.parent()._textCursor().hasSelection(): return False if self.mode == COMPLETE_MODE.DROPDOWN: if self.parent().input_buffer().strip(): if self.completing(): self.complete() else: self.trigger_complete() event.accept() return True elif self.mode == COMPLETE_MODE.INLINE: if self._last_key == Qt.Key_Tab: self.trigger_complete() event.accept() return True def handle_complete_key(self, event): if self.completing(): self.complete() event.accept() return True def init_completion_list(self, words): self.completer = QCompleter(words, self) self.completer.setCompletionPrefix(self.parent().input_buffer()) self.completer.setWidget(self.parent().edit) self.completer.setCaseSensitivity(Qt.CaseSensitive) self.completer.setModelSorting(QCompleter.CaseSensitivelySortedModel) if self.mode == COMPLETE_MODE.DROPDOWN: self.completer.setCompletionMode(QCompleter.PopupCompletion) self.completer.activated.connect(self.insert_completion) else: self.completer.setCompletionMode(QCompleter.InlineCompletion) def trigger_complete(self): _buffer = self.parent().input_buffer().strip() self.show_completion_suggestions(_buffer) def show_completion_suggestions(self, _buffer): words = self.parent().get_completions(_buffer) # No words to show, just return if len(words) == 0: return # Close any popups before creating a new one if self.completer.popup(): self.completer.popup().close() self.init_completion_list(words) leastcmn = long_substr(words) self.insert_completion(leastcmn) # If only one word to complete, just return and don't display options if len(words) == 1: return if self.mode == COMPLETE_MODE.DROPDOWN: cr = self.parent().edit.cursorRect() sbar_w = self.completer.popup().verticalScrollBar() popup_width = self.completer.popup().sizeHintForColumn(0) popup_width += sbar_w.sizeHint().width() cr.setWidth(popup_width) self.completer.complete(cr) elif self.mode == COMPLETE_MODE.INLINE: cl = columnize(words, colsep=' | ') self.parent()._insert_output_text('\n\n' + cl + '\n', lf=True, keep_buffer=True) def hide_completion_suggestions(self): if self.completing(): self.completer.popup().close() return True def completing(self): if self.mode == COMPLETE_MODE.DROPDOWN: return (self.completer.popup() and self.completer.popup().isVisible()) else: return False def insert_completion(self, completion): _buffer = self.parent().input_buffer().strip() # Handling the . operator in object oriented languages so we don't # overwrite the . when we are inserting the completion. Its not the . # operator If the buffer starts with a . (dot), but something else # perhaps terminal specific so do nothing. if '.' in _buffer and _buffer[0] != '.': idx = _buffer.rfind('.') + 1 _buffer = _buffer[idx:] if self.mode == COMPLETE_MODE.DROPDOWN: self.parent().insert_input_text(completion[len(_buffer):]) elif self.mode == COMPLETE_MODE.INLINE: self.parent().clear_input_buffer() self.parent().insert_input_text(completion) words = self.parent().get_completions(completion) if len(words) == 1: self.parent().insert_input_text(' ') def update_completion(self, key): if self.completing(): _buffer = self.parent().input_buffer() if len(_buffer) > 1: self.show_completion_suggestions(_buffer) self.completer.setCurrentRow(0) model = self.completer.completionModel() self.completer.popup().setCurrentIndex(model.index(0, 0)) else: self.completer.popup().hide() def complete(self): if self.completing() and self.mode == COMPLETE_MODE.DROPDOWN: index = self.completer.popup().currentIndex() model = self.completer.completionModel() word = model.itemData(index)[0] self.insert_completion(word) self.completer.popup().hide()