def validator(self): url_validate = QRegExpValidator(QRegExp(r'^.*[.amazon.in].*$')) price_validate = QDoubleValidator(bottom=0, decimals=0) email_validate = QRegExpValidator( QRegExp(r'^[a-z0-9]+[\._]?[a-z0-9]+[@]\w+[.]\w{2,3}$')) again = "" self.url = self.txtUrl.toPlainText() self.p = self.txtPrice.toPlainText() self.usr_email = self.txtEmail.toPlainText() if url_validate.validate(self.url, 0)[0] != QValidator.Acceptable: print(url_validate.validate(self.url, 0)) again = again + "URL : url must be of www.amazon.in\n" self.txtUrl.clear() if price_validate.validate(self.p, 4)[0] != QValidator.Acceptable: print(price_validate.validate(self.p, 4)) again = again + "Price : It must be Number without , and .\n" self.txtPrice.clear() if email_validate.validate(self.usr_email, 0)[0] != QValidator.Acceptable: print(email_validate.validate(self.usr_email, 0)) again = again + "Email : Please enter right email\n" self.txtEmail.clear() return again
class Validador(QItemDelegate): def __init__(self): super().__init__() def createEditor(self, parent, option, index): regex = QRegExp("[0-9a-fA-F]{2}") self.rxval = QRegExpValidator(regex, self) self.edt_rx = QLineEdit(parent) self.edt_rx.textChanged[str].connect(self.verificar) self.edt_rx.editingFinished.connect(self.finalizado) return self.edt_rx def verificar(self, cadena): a = self.rxval.validate(cadena, 0) if a[0] == 0: c = self.edt_rx.text() c = c[0:len(c) - 1] self.edt_rx.setText(c) def finalizado(self): cadena = self.edt_rx.text() a = self.rxval.validate(cadena, 0) if a[0] == 1: c = self.edt_rx.text() c = c.zfill(2) self.edt_rx.setText(c) self.finalizado()
def letterValidator(self): validator = QRegExpValidator(QRegExp(self.letterPattern)) message = "Ошибка в индексах столбцов. Допустимы только буквы латинского алфавита." result = validator.validate(self.widget.text(), 0) if self.buttonSwitcher(result[0], message) != QValidator.Acceptable: self.result["letter"] = True return result[0]
def numberValidator(self): validator = QRegExpValidator(QRegExp(self.numberPattern)) message = "Ошибка в индексах строк. Допустимы только цифры." result = validator.validate(self.widget.text(), 0) if self.buttonSwitcher(result[0], message) != QValidator.Acceptable: self.result["number"] = True return result[0]
class SpinBoxHex(QSpinBox): def __init__(self, parent=None, default_value=0): super().__init__(parent) self.validator = QRegExpValidator(QRegExp('^([ ]*[0-9A-Fa-f][ ]*){1,8}$'), self) self.setValue(default_value) def validate(self, text, pos): return self.validator.validate(text, pos) def valueFromText(self, text): return min(int(text.replace(' ', ''), 16), (1 << 31) - 1) def textFromValue(self, value): s = '' for i, c in enumerate(reversed(hex(value).replace('0x', '').upper())): if i % 2 == 0: s = ' ' + s s = c + s s = s.strip() if len(s.replace(' ', '')) % 2 == 1: s = '0' + s return s
class TimeSpinBox(QSpinBox): """Custom widget to collect an interval in time, used primarily in the settings dialog""" SUFFIXES = {'s': 1, 'm':60, 'h':60*60, 'd':60*60*24} def __init__(self, parent=None, time=900): super(TimeSpinBox, self).__init__(parent) self.validator = QRegExpValidator(QRegExp(r'(\d+\s*[{}]\s*)+'.format(''.join([key for key in self.SUFFIXES.keys()]), Qt.CaseInsensitive))) self.setMaximum(60*60*24*7 - 1) self.setValue(time) def validate(self, text, pos): '''Overriden validation alidate using regex''' return self.validator.validate(text, pos) def textFromValue(self, value): '''Overriden method to get the line edit's text from a value in seconds''' text = '' # add a #s entry to the text per suffix for suffix in sorted(self.SUFFIXES): if value >= self.SUFFIXES[suffix]: text += '{}{}{}'.format('' if text == '' else ' ', value//self.SUFFIXES[suffix], suffix) value %= self.SUFFIXES[suffix] elif text != '': text += ' 0{}'.format(suffix) return text def valueFromText(self, value): '''Overriden method to get the value in seconds from the line edit's text''' num = 0 # get the number of each extension and multiply by their value in SUFFIXES for suffix in self.SUFFIXES: entry = re.search(r"(\d+)\s*{}".format(suffix), value) if entry: num += int(entry.group(1))*self.SUFFIXES[suffix] return num
def checkInput(self): # Check input validLineEdit = True validPLainText = True stringCallable = True methodToSolve = True # Get children of verticalLayout for count in range(self.ui.parameters_verticalLayout.count()): child = self.ui.parameters_verticalLayout.itemAt(count).widget() # Check if specified lineEdit are differ then zero if child.objectName() in ["mass_lineEdit", "stiffness_lineEdit", "end_time_lineEdit", "time_step_lineEdit"]: if child.text() == "": validLineEdit = False # Check if excitation force is valid elif child.objectName() == "excitation_force_plainTextEdit": excitationForce = child.toPlainText() validator_function = QRegExpValidator(QRegExp(r"[\d|t|sin|cos| |+|-|*|/|.|(|)|=|<|>|if|else|elif|:]*")) # If string contains valid characters if validator_function.validate(excitationForce, 2)[0] == QValidator.Acceptable: excitationForce = excitationForce.replace("cos", "np.cos") excitationForce = excitationForce.replace("sin", "np.sin") # Convert string to callable function self.f = lambda t: eval(excitationForce) # Test if callable string is valid try: self.f(0) except: stringCallable = False # If string contains also non-valid characters else: validPLainText = False # Any method to solve methodChecked = [self.ui.solve_ForwardEuler_checkBox.isChecked(), self.ui.solve_RungeKutta4th_checkBox.isChecked(), self.ui.solve_LeapFrog_checkBox.isChecked(), self.ui.solve_Newmark_checkBox.isChecked()] if not any(methodChecked): methodToSolve = False # If error show message else solve if not validLineEdit: self.errorMessage("Mass, Stiffness, End time and Time step must be bigger than 0") elif float(self.ui.end_time_lineEdit.text()) <= float(self.ui.time_step_lineEdit.text()): self.errorMessage("Time step must be smaller than End time") elif not validPLainText: self.errorMessage("Excitation force contains forbidden characters") elif not stringCallable: self.errorMessage("Check excitation force, it is not written correctly") elif not methodToSolve: self.errorMessage("Choose at least one method to solve") else: self.solveInput()
def validate_input(self): reg_ex = QRegExp('^(?:0*(?:\.\d+)?|1(\.0*)?)$') input_validator = QRegExpValidator(reg_ex, self.input_value) self.input_value.setValidator(input_validator) state = input_validator.validate(self.input_value.text(), 0) if state[0] == QRegExpValidator.Acceptable: return 1 else: return 0
class jeu(QWidget): def __init__(self,num): global numero_question numero_question+=1 super().__init__() self.num=num self.mot=selection(self.num) self.melange=melanger(self.mot) ch="" for i in range(len(self.mot)): ch+=(" - "+self.melange[i]) self.text=QLabel("""Devinez la mot caché derriere """+ch) self.ligne=QLineEdit() self.exp=QRegExp("[a-zA-Z]{1,}") self.validator=QRegExpValidator(self.exp) """ self.ligne.setValidator(self.validator)""" self.boutton=QPushButton("tester le mot") self.layout =QGridLayout() self.layout.addWidget(self.text,0,0) self.layout.addWidget(self.ligne,1,0) self.layout.addWidget(self.boutton,2,0) self.setLayout(self.layout) self.setFixedSize(300,300) self.boutton.clicked.connect(self.test) def showing(self): super().show() def test(self): pos=0 res=(self.validator.validate(self.ligne.text(),pos))[0] if(self.ligne.text()==""): QMessageBox.critical(self,"erreur","veuillez saisir un mot") elif(self.ligne.text()==self.mot): """ fermer la fenetre actuelle et ouvrir une autre self.jeu=jeu(6) self.jeu.showing() super().close() """ self.message=QMessageBox(self) self.message.setText("bravo votre réponse est correcte") self.message.exec() super().close() global numero_question self. f=principale(numero_question) self. f.show() elif( res!=2): QMessageBox.critical(self,"erreur","veuillez saisir uniquement des lettres") elif(self.ligne.text()!=self.mot): QMessageBox.critical(self,"mystere","mot incorrect veuillez essayer une autre foix")
def __validate_input(self): """ Applies a regular expression to QLineEdit field and validates IPv4 :return: """ regex = QRegExp() regex.setPattern( '(^[2][0-5][0-5]|^[1]{0,1}[0-9]{1,2})\.([0-2][0-5][0-5]|[1]{0,1}[0-9]{1,2})\.' '([0-2][0-5][0-5]|[1]{0,1}[0-9]{1,2})\.([0-2][0-5][0-5]|[1]{0,1}[0-9]{1,2})$' ) validator = QRegExpValidator(regex, self.ui.line_IP) self.ui.line_IP.setValidator(validator) state = validator.validate(self.ui.line_IP.text(), 0)[0] if state == validator.Acceptable: return True
class SpinBoxHex(QSpinBox): def __init__(self, parent=None, default_value=0, digit_block_size=2): super().__init__(parent) self.validator = QRegExpValidator( QRegExp('^([ ]*[0-9A-Fa-f][ ]*){1,8}$'), self) self.digit_block_size = digit_block_size self.hex_mode_enabled = True self.setValue(default_value) def enable_hex_mode(self, digit_block_size=None): self.hex_mode_enabled = True if digit_block_size is not None: self.digit_block_size = digit_block_size self.setValue(self.value()) def disable_hex_mode(self): self.hex_mode_enabled = False self.setValue(self.value()) def validate(self, text, pos): if not self.hex_mode_enabled: return super().validate(text, pos) return self.validator.validate(text, pos) def valueFromText(self, text): if not self.hex_mode_enabled: return super().valueFromText(text) return min(int(text.replace(' ', ''), 16), self.maximum()) def textFromValue(self, value): if not self.hex_mode_enabled: return super().textFromValue(value) rev_text = hex(value).replace('0x', '').upper()[::-1] blocks = [ rev_text[i:i + self.digit_block_size] for i in range(0, len(rev_text), self.digit_block_size) ] # Reverse blocks and chars in block to undo reverse on the string above text = ' '.join(s[::-1] for s in blocks[::-1]) if len(blocks[0]) != self.digit_block_size: text = '0' * (self.digit_block_size - len(blocks[0])) + text return text
class TextEdit_DropFormulas(QtWidgets.QTextEdit): def __init__(self, *args, **kwargs): QtWidgets.QTextEdit.__init__(self, *args, **kwargs) regexp = QtCore.QRegExp("[^\'\"¨&\[\]{};`~?|!@#$\\=]*") self.validator = QRegExpValidator(regexp) def keyPressEvent(self, event): keypress = self.validator.validate(event.text(), 0) if keypress[0] == QValidator.Acceptable or event.key( ) == QtCore.Qt.Key_Backspace: QtWidgets.QTextEdit.keyPressEvent(self, event) def dragEnterEvent(self, event): if isinstance(event.source(), QtWidgets.QListWidget): event.accept() self.setAcceptDrops(True) event.acceptProposedAction() def dragMoveEvent(self, event): if isinstance(event.source(), QtWidgets.QListWidget): event.accept() def dropEvent(self, event): if isinstance(event.source(), QtWidgets.QListWidget): listwidget = event.source() item = listwidget.item(listwidget.currentRow()) if listwidget.objectName() == "listwidget_formulas_constants": text = item.data(QtCore.Qt.UserRole).name if listwidget.objectName() == "listwidget_formulas_variables": text = item.data(QtCore.Qt.UserRole).keyword self.insertHtml("[") self.insertHtml("<span style='font-size:8pt; color:#00aa00;'>" + text) self.insertHtml("]") self.setFocus() cursor = QTextCursor(self.document()) cursor.movePosition(QTextCursor.End) self.setTextCursor(cursor)
class RomanSpinBox(QSpinBox): def __init__(self, parent=None): super(RomanSpinBox, self).__init__(parent) regex = QRegExp(r"^M?M?M?(?:CM|CD|D?C?C?C?)" r"(?:XC|XL|L?X?X?X?)(?:IX|IV|V?I?I?I?)$") regex.setCaseSensitivity(Qt.CaseInsensitive) self.validator = QRegExpValidator(regex, self) self.setRange(1, 3999) self.valueChanged[str].connect(self.fixCase) def fixCase(self, text): self.lineEdit().setText(text.upper()) def validate(self, text, pos): return self.validator.validate(text, pos) def valueFromText(self, text): return intFromRoman(str(text)) def textFromValue(self, value): return romanFromInt(value)
def check_param(self, param): """ Check if 'param' is valid :param param: value of the field """ # double if not param.is_array() and param.get_type() == "double": # double validator validator = get_custom_double_validator() # double array elif param.is_array() and param.get_type() == "double": string = "" # dinamic regular expresion for x in range(0, int(param.get_array_size())): if x == int(param.get_array_size()) - 1: string += "-?[\\d\\.]*" else: string += "-?[\\d\\.]*,\s*" regexp = QRegExp("\\[" + string + "\\]") validator = QRegExpValidator(regexp) # boolean array elif param.is_array() and param.get_type() == "boolean": string = "" # dinamic regular expresion for x in range(0, int(param.get_array_size())): if x == int(param.get_array_size()) - 1: string += "(true|false)" else: string += "(true|false),\s*" regexp = QRegExp("\\[" + string + "\\]") validator = QRegExpValidator(regexp) state = validator.validate(param.get_value(), 0)[0] return state
class MainWidget(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.dict_gen = Dictionary_generator('merriam webster', ['noun', 'verb', 'adjective'], 'random') self.setWindowTitle('Dictionary Text Generator') screen_rect = QDesktopWidget().availableGeometry(self) screen_w, screen_h = screen_rect.width(), screen_rect.height() app_w = screen_w * .25 app_h = screen_h * .75 self.resize(app_w, app_h) selectDictionaryLabel = QLabel('Select dictionary to use:') selectDictionaryLabel.setAlignment(Qt.AlignTop) self.selectDictionaryDropdown = QComboBox() self.selectDictionaryDropdown.addItems( Dictionary_generator.dictionaries) selectMethodLabel = QLabel('Select method to use:') self.selectMethodDropdown = QComboBox() self.selectMethodDropdown.addItems(Dictionary_generator.methods) originWordLabel = QLabel( 'Choose origin word(s) (if multiple, use a comma separated list):') self.originWord = QLineEdit() regexp = QRegExp('^[a-zA-Z]+(,[ ][a-zA-Z]+)*') self.validator = QRegExpValidator(regexp) self.originWord.setValidator(self.validator) numberOfWordsLabel = QLabel('Choose number of words used per output:') self.numberOfWords = QSpinBox() self.numberOfWords.setMinimum(1) numberOfLoopsLabel = QLabel('Choose number of times to loop output:') self.numberOfLoops = QSpinBox() self.numberOfLoops.setMinimum(1) generateButton = QPushButton('Generate text') #generateButton.clicked.connect(self.generate_text) generateButton.clicked.connect(self.start_generation) noteText = QLabel( 'Note: Parts of speech used are noun, verb, and adjective') self.output = QLabel('') self.output.setFrameStyle(QFrame.Panel | QFrame.Sunken) self.output.setWordWrap(True) self.output.setAlignment(Qt.AlignTop) outputScrollArea = QScrollArea() outputScrollArea.setWidget(self.output) outputScrollArea.setWidgetResizable(True) clearTextButton = QPushButton('Clear output') clearTextButton.clicked.connect(self.clear_text) parametersGroup = QGroupBox('Input Parameters:') outputGroup = QGroupBox('Output:') parametersLayout = QVBoxLayout() outputLayout = QVBoxLayout() parametersLayout.addWidget(selectDictionaryLabel) parametersLayout.addWidget(self.selectDictionaryDropdown) parametersLayout.addWidget(selectMethodLabel) parametersLayout.addWidget(self.selectMethodDropdown) parametersLayout.addWidget(originWordLabel) parametersLayout.addWidget(self.originWord) parametersLayout.addWidget(numberOfWordsLabel) parametersLayout.addWidget(self.numberOfWords) parametersLayout.addWidget(numberOfLoopsLabel) parametersLayout.addWidget(self.numberOfLoops) parametersLayout.addWidget(generateButton) parametersLayout.setAlignment(generateButton, Qt.AlignCenter) parametersLayout.addWidget(noteText) outputLayout.addWidget(outputScrollArea) outputLayout.addWidget(clearTextButton) outputLayout.setAlignment(clearTextButton, Qt.AlignCenter) parametersGroup.setLayout(parametersLayout) parametersGroup.setMaximumHeight(app_h * .4) outputGroup.setLayout(outputLayout) mainLayout = QVBoxLayout(self) mainLayout.addWidget(parametersGroup) mainLayout.addWidget(outputGroup) self.setLayout(mainLayout) #self.show() ''' def generate_text(self): words = self.originWord.text().split(', ') numLoops = self.numberOfLoops.value() numWords = self.numberOfWords.value() self.dict_gen.dic_name = self.selectDictionaryDropdown.currentText() self.dict_gen.method = self.selectMethodDropdown.currentText() for _ in range(numLoops): for word in words: self.dict_gen.text= [] self.dict_gen.words_used = [] self.dict_gen.generate_story(numWords, word) curText = self.output.text() self.output.setText(curText + str(self.dict_gen) + '\n' + str(self.dict_gen.words_used) + '\n') ''' def start_generation(self): lineedit_state = self.validator.validate(self.originWord.text(), 0)[0] if lineedit_state != QValidator.Acceptable: message = 'Please make sure your input words are a proper comma separated list.' msgbox = QMessageBox() msgbox.setText(message) msgbox.setWindowTitle('Error') msgbox.exec() return self.words = self.originWord.text().split(', ') numLoops = self.numberOfLoops.value() numWords = self.numberOfWords.value() totalNum = numLoops * len(self.words) message = '0 outputs out of ' + str(totalNum) + ' generated' self.parent().set_status_message(message) self.dict_gen.dic_name = self.selectDictionaryDropdown.currentText() self.dict_gen.method = self.selectMethodDropdown.currentText() self.generation_thread = OutputText(words=self.words, numWords=numWords, numLoops=numLoops, dict_gen=self.dict_gen) self.generation_thread.updateProgress.connect(self.update_generation) self.generation_thread.errorEncountered.connect(self.show_error) self.generation_thread.start() def update_generation(self, outputs_done, text_generated, words_used): curNum = outputs_done totalNum = self.numberOfLoops.value() * len(self.words) message = str(curNum) + ' outputs out of ' + str( totalNum) + ' generated' self.parent().set_status_message(message) curText = self.output.text() self.output.setText(curText + text_generated + '\n' + words_used + '\n') # used in case that one of the words given does not have any appropriate example sentences in the dictionary def show_error(self, error_word): message = 'The word ' + error_word + ' does not have any available example sentences. Please try a different word.' msgbox = QMessageBox() msgbox.setText(message) msgbox.setWindowTitle('Error') msgbox.exec() def clear_text(self): self.output.setText('') self.parent().clear_status_message()
class CooperationPage(ConfigurationPageBase, Ui_CooperationPage): """ Class implementing the Cooperation configuration page. """ def __init__(self): """ Constructor """ super(CooperationPage, self).__init__() self.setupUi(self) self.setObjectName("CooperationPage") self.__bannedUserValidator = QRegExpValidator( QRegExp("[a-zA-Z0-9.-]+@" "(?:(?:2(?:[0-4][0-9]|5[0-5])|[01]?[0-9]{1,2})\.){3}" "(?:2(?:[0-4][0-9]|5[0-5])|[01]?[0-9]{1,2})"), self.bannedUserEdit) self.bannedUserEdit.setValidator(self.__bannedUserValidator) # set initial values self.autostartCheckBox.setChecked( Preferences.getCooperation("AutoStartServer")) self.otherPortsCheckBox.setChecked( Preferences.getCooperation("TryOtherPorts")) self.serverPortSpin.setValue(Preferences.getCooperation("ServerPort")) self.portToTrySpin.setValue( Preferences.getCooperation("MaxPortsToTry")) self.autoAcceptCheckBox.setChecked( Preferences.getCooperation("AutoAcceptConnections")) self.bannedUsersList.addItems( sorted(Preferences.getCooperation("BannedUsers"))) def save(self): """ Public slot to save the Cooperation configuration. """ Preferences.setCooperation("AutoStartServer", self.autostartCheckBox.isChecked()) Preferences.setCooperation("TryOtherPorts", self.otherPortsCheckBox.isChecked()) Preferences.setCooperation("AutoAcceptConnections", self.autoAcceptCheckBox.isChecked()) Preferences.setCooperation("ServerPort", self.serverPortSpin.value()) Preferences.setCooperation("MaxPortsToTry", self.portToTrySpin.value()) bannedUsers = [] for row in range(self.bannedUsersList.count()): bannedUsers.append(self.bannedUsersList.item(row).text()) Preferences.setCooperation("BannedUsers", bannedUsers) @pyqtSlot() def on_bannedUsersList_itemSelectionChanged(self): """ Private slot to react on changes of selected banned users. """ self.deleteBannedUsersButton.setEnabled( len(self.bannedUsersList.selectedItems()) > 0) @pyqtSlot(str) def on_bannedUserEdit_textChanged(self, txt): """ Private slot to handle the user entering a banned user. @param txt text entered by the user (string) """ self.addBannedUserButton.setEnabled( self.__bannedUserValidator.validate(txt, len(txt))[0] == QValidator.Acceptable) @pyqtSlot() def on_deleteBannedUsersButton_clicked(self): """ Private slot to remove the selected users from the list of banned users. """ for itm in self.bannedUsersList.selectedItems(): row = self.bannedUsersList.row(itm) itm = self.bannedUsersList.takeItem(row) del itm @pyqtSlot() def on_addBannedUserButton_clicked(self): """ Private slot to add a user to the list of banned users. """ self.bannedUsersList.addItem(self.bannedUserEdit.text()) self.bannedUserEdit.clear()
class DurationEdit(QAbstractSpinBox): """Duration edit.""" valueChanged = pyqtSignal(int) def __init__(self, parent=None, hour_length=2): """Construct a duration edit.""" super().__init__(parent) self._hour_length = hour_length regexp = QRegExp('^[0-9]{1,' + str(self._hour_length) + '}:[0-5]{,1}[0-9]?$') self._validator = QRegExpValidator(regexp) self._minutes = 0 self.lineEdit().textChanged.connect(self.text_changed) def __text(self): """Get the line edit text.""" return self.lineEdit().text() def __cursor_position(self): """Get the cursor position.""" return self.lineEdit().cursorPosition() def __max_hours(self): """Get the max hours that can be reached for the hour length.""" return 10**self._hour_length - 1 def validate(self, text, pos): """Determine whether input is valid.""" return self._validator.validate(text, pos) @staticmethod def minutesToText(minutes): """Convert minutes to a time string.""" return '{:02d}:{:02d}'.format(*divmod(minutes, 60)) @staticmethod def textToMinutes(text): """Convert time text to minutes.""" hours = minutes = 0 array = text.split(':') try: hours = int(array[0]) except ValueError: hours = 0 if len(array) == 2: try: minutes = int(array[1]) except ValueError: minutes = 0 return hours * 60 + minutes @property def minutes(self): """Get the total minutes.""" return self._minutes @minutes.setter def minutes(self, minutes): """Set the total minutes.""" try: minutes = int(minutes) except TypeError: self._minutes = 0 self.valueChanged.emit(self._minutes) else: hours = divmod(minutes, 60)[0] if hours > self.__max_hours(): self._minutes = 0 self.valueChanged.emit(self._minutes) else: self._minutes = minutes self.valueChanged.emit(self._minutes) self.lineEdit().setText(self.minutesToText(self._minutes)) def stepBy(self, steps): """Trigger a step.""" cursor_position = self.__cursor_position() text = self.__text() try: index = text.index(':') except ValueError: # we have only hours in the field self.minutes = self.minutes + steps * 60 else: value = 0 if 0 <= cursor_position <= index: value = steps * 60 elif index + 1 <= cursor_position <= len(text): value = steps self.minutes = self.minutes + value self.lineEdit().setCursorPosition(cursor_position) def stepEnabled(self): """Determine whether stepping up and down is legal at any time.""" cursor_position = self.__cursor_position() text = self.__text() try: index = text.index(':') except ValueError: # no : in string try: hours = int(text) except ValueError: hours = 0 # we have only hours in the field if hours <= 0: return QAbstractSpinBox.StepUpEnabled elif hours >= self.__max_hours(): return QAbstractSpinBox.StepDownEnabled else: return (QAbstractSpinBox.StepUpEnabled | QAbstractSpinBox.StepDownEnabled) else: try: hours = int(text[:index]) except ValueError: hours = 0 try: minutes = int(text[index + 1:]) except ValueError: minutes = 0 if 0 <= cursor_position <= index: if hours <= 0: return QAbstractSpinBox.StepUpEnabled elif hours >= self.__max_hours(): return QAbstractSpinBox.StepDownEnabled else: return (QAbstractSpinBox.StepUpEnabled | QAbstractSpinBox.StepDownEnabled) elif index + 1 <= cursor_position <= len(text): if minutes <= 0: return QAbstractSpinBox.StepUpEnabled elif minutes >= 59: return QAbstractSpinBox.StepDownEnabled else: return (QAbstractSpinBox.StepUpEnabled | QAbstractSpinBox.StepDownEnabled) return QAbstractSpinBox.StepNone def event(self, event): """Handle event and check for Tab and Shift+Tab.""" if event.type() == QEvent.KeyPress: key = event.key() if key in (Qt.Key_Enter, Qt.Key_Return): self.minutes = self.textToMinutes(self.__text()) return super().event(event) text = self.__text() try: index = text.index(':') except ValueError: # no : in string, on tab or backtab, go to next field, but # format this one before if key in (Qt.Key_Tab, Qt.Key_Backtab): self.minutes = self.textToMinutes(self.__text()) return super().event(event) else: cursor_position = self.__cursor_position() if key == Qt.Key_Colon: # go to minutes on : type if cursor is on hours if cursor_position <= index: self.lineEdit().setSelection(index + 1, len(text)) return True else: return False if key == Qt.Key_Tab: if cursor_position <= index: # go to minutes on tab self.lineEdit().setSelection(index + 1, len(text)) return True else: # go to next field on tab, but update minutes before self.minutes = self.textToMinutes(self.__text()) return super().event(event) elif key == Qt.Key_Backtab: if cursor_position > index: # go to hours on backtab self.lineEdit().setSelection(0, index) return True else: # go to previous field on backtab, but update minutes # before self.minutes = self.textToMinutes(self.__text()) return super().event(event) if event.type() == QEvent.KeyRelease: # on [0-9] key release, if hours are filled, go to minutes if event.key() in (Qt.Key_0, Qt.Key_1, Qt.Key_3, Qt.Key_2, Qt.Key_4, Qt.Key_5, Qt.Key_6, Qt.Key_7, Qt.Key_8, Qt.Key_9): text = self.__text() try: index = text.index(':') except ValueError: pass else: cursor_position = self.__cursor_position() if index == cursor_position == self._hour_length: self.lineEdit().setSelection(index + 1, len(text)) return True return super().event(event) def focusOutEvent(self, event): """Receive keyboard focus events (focus lost) for the widget.""" super().focusOutEvent(event) self.minutes = self.textToMinutes(self.__text()) def focusInEvent(self, event): """Receive keyboard focus events (focus received) for the widget.""" super().focusInEvent(event) text = self.__text() reason = event.reason() try: index = text.index(':') except ValueError: pass else: if reason == Qt.BacktabFocusReason: self.lineEdit().setSelection(index + 1, len(text)) elif reason == Qt.TabFocusReason: self.lineEdit().setSelection(0, index) @pyqtSlot(str) def text_changed(self, text): """Update the stored value.""" self._minutes = self.textToMinutes(text) def sizeHint(self): """Return the recommended size for the widget.""" string = '_' * self._hour_length + ':__ ' fm = self.fontMetrics() height = self.lineEdit().sizeHint().height() width = fm.width(string) + 12 hint = QSize(width, height) option = QStyleOptionSpinBox() return (self.style().sizeFromContents(QStyle.CT_SpinBox, option, hint, self).expandedTo( QApplication.globalStrut()))
class QTimeSelect(QDoubleSpinBox): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) regex = QRegExp(r"\d:\d{1,2}:\d{1,2}(?:\.\d{0,9})") regex.setCaseSensitivity(Qt.CaseInsensitive) self._validator = QRegExpValidator(regex) self.setDecimals(9) def validate(self, text, pos): return self._validator.validate(text, pos) def valueFromText(self, text): matches = regex.findall(r"^(\d+):(\d+):(\d+(?:\.\d*))$", text) if matches: (h, m, s), = matches return 3600 * int(h) + 60 * int(m) + float(s) def textFromValue(self, value): m, s = divmod(value, 60) h, m = divmod(int(m), 60) return f"{h}:{m:02d}:{s:012.9f}" def stepBy(self, dt): currentValue = self.value() currentText = self.text() currentPosition = self.lineEdit().cursorPosition() matches = regex.findall(r"^(\d+):(\d+):(\d+(?:\.\d*))$", currentText) if matches: (h, m, s), = matches if currentPosition <= len(h): self.setValue(currentValue + 3600 * dt) self.selectHours() elif currentPosition <= len(f"{h}:{m}"): self.setValue(currentValue + 60 * dt) self.selectMinutes() else: self.setValue(currentValue + dt) self.selectSeconds() def keyPressEvent(self, event): selectedText = self.lineEdit().selectedText() if ":" in selectedText: if event.key() not in (Qt.Key_Right, Qt.Key_Left): return selectionStart = self.lineEdit().selectionStart() selectionEnd = selectionStart + len(selectedText) currentPosition = self.lineEdit().cursorPosition() text = self.text() textBeforeCursor = text[:currentPosition] textAfterCursor = text[currentPosition:] matches = regex.findall(r"^(\d+):(\d+):(\d+(?:\.\d*))$", text) if matches: (h, m, s), = matches else: h = m = s = "" if (event.key() == Qt.Key_Right and event.modifiers() == Qt.ControlModifier): if currentPosition <= len(h): self.selectMinutes() elif currentPosition <= len(f"{h}:{m}"): self.selectSeconds() return if (event.key() == Qt.Key_Left and event.modifiers() == Qt.ControlModifier): if currentPosition >= len(f"{h}:{m}:"): self.selectMinutes() elif currentPosition >= len(f"{h}:"): self.selectHours() return if event.key() == Qt.Key_Backspace: if selectedText == "" and textBeforeCursor.endswith(":"): return if event.key() == Qt.Key_Delete: if selectedText == "" and textAfterCursor.startswith(":"): return if event.key() == Qt.Key_Colon: if textAfterCursor.startswith(":") and not selectedText: nextColon = textAfterCursor.find(":", 1) if nextColon >= 0: self.lineEdit().setSelection( len(textBeforeCursor) + 1, nextColon - 1) else: self.lineEdit().setSelection( len(textBeforeCursor) + 1, len(textAfterCursor) - 1) return super().keyPressEvent(event) maxhours = int(self.maximum() // 3600) maxhourdigits = 1 while maxhours > 10: maxhourdigits += 1 maxhours //= 10 if Qt.Key_0 <= event.key() <= Qt.Key_9: if currentPosition == len(h) == maxhourdigits - 1: self.selectMinutes() elif len(selectedText) == 1 and selectionEnd == maxhourdigits: self.selectMinutes() elif currentPosition == len(f"{h}:{m}") and len(m) == 1: self.selectSeconds() elif len(selectedText) == 1 and selectionEnd == len(f"{h}:00"): self.selectSeconds() def selectHours(self): text = self.text() matches = regex.findall(r"^(\d+):(\d+):(\d+(?:\.\d*))$", text) if matches: (h, m, s), = matches self.lineEdit().setSelection(0, len(h)) def selectMinutes(self): text = self.text() matches = regex.findall(r"^(\d+):(\d+):(\d+(?:\.\d*))$", text) if matches: (h, m, s), = matches self.lineEdit().setSelection(len(f"{h}:"), len(m)) def selectSeconds(self): text = self.text() matches = regex.findall(r"^(\d+):(\d+):(\d+(?:\.\d*))$", text) if matches: (h, m, s), = matches self.lineEdit().setSelection(len(f"{h}:{m}:"), len(s))
class TopicsAnalyser_UI(QMainWindow): def __init__(self): super(TopicsAnalyser_UI, self).__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.run_btn.clicked.connect(self.run_topics_analyser) self.ui.browse_btn.clicked.connect(self.getfile) self.setup_validators() def run_topics_analyser(self): status = self.validate_inputs() if (status != 0): return def get_wordlist(string_: str): return [word.strip() for word in string_.split(',') ] if (len(string_) > 0) else [] groupby_cols = get_wordlist(self.ui.groupby_cols_txt.text()) addl_stopwords = get_wordlist(self.ui.addl_stopwords_txt.text()) # TODO: these column names should come from the input screen text_col = 'Reason for filling position(s) with Federal Government Employee -OTHER' # text_col = 'Please briefly describe an example of one burdensome administrative task or process which you believe is "low value"' other_cols = [ 'AGENCY', 'COMPONENT', 'SUB_COMPONENT', 'GRADELEVEL', 'SUP_STATUS' ] data = TextFileReader.get_dataframe(self.ui.data_file_txt.text(), text_col, other_cols) analyser = TopicsAnalyser(data) message = analyser.get_topics(self.ui.num_topics_spb.value(), groupby_cols, self.ui.num_ngrams_spb.value(), addl_stopwords) self.ui.statusbar.showMessage(message) def setup_validators(self): # check if the text is an empty string rx = QRegExp('^(?!\\s*$).+') self.filename_validator = QRegExpValidator(rx) def validate_inputs(self): self.error_dialog = QErrorMessage() errors = [] filename_val_status, _, _ = self.filename_validator.validate( self.ui.data_file_txt.text(), 0) if (filename_val_status != 2): errors.append('Data file is required.') if (len(errors) > 0): self.error_dialog.showMessage('\n'.join(errors)) return -1 return 0 def getfile(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog filename, _ = QFileDialog.getOpenFileName(self, "Open File", "", "Excel files (*.xlsx)", options=options) if (filename): self.ui.data_file_txt.setText(filename)
class CooperationPage(ConfigurationPageBase, Ui_CooperationPage): """ Class implementing the Cooperation configuration page. """ def __init__(self): """ Constructor """ super(CooperationPage, self).__init__() self.setupUi(self) self.setObjectName("CooperationPage") self.__bannedUserValidator = QRegExpValidator( QRegExp("[a-zA-Z0-9.-]+@" "(?:(?:2(?:[0-4][0-9]|5[0-5])|[01]?[0-9]{1,2})\.){3}" "(?:2(?:[0-4][0-9]|5[0-5])|[01]?[0-9]{1,2})"), self.bannedUserEdit) self.bannedUserEdit.setValidator(self.__bannedUserValidator) # set initial values self.autostartCheckBox.setChecked( Preferences.getCooperation("AutoStartServer")) self.otherPortsCheckBox.setChecked( Preferences.getCooperation("TryOtherPorts")) self.serverPortSpin.setValue( Preferences.getCooperation("ServerPort")) self.portToTrySpin.setValue( Preferences.getCooperation("MaxPortsToTry")) self.autoAcceptCheckBox.setChecked( Preferences.getCooperation("AutoAcceptConnections")) self.bannedUsersList.addItems(sorted( Preferences.getCooperation("BannedUsers"))) def save(self): """ Public slot to save the Cooperation configuration. """ Preferences.setCooperation( "AutoStartServer", self.autostartCheckBox.isChecked()) Preferences.setCooperation( "TryOtherPorts", self.otherPortsCheckBox.isChecked()) Preferences.setCooperation( "AutoAcceptConnections", self.autoAcceptCheckBox.isChecked()) Preferences.setCooperation( "ServerPort", self.serverPortSpin.value()) Preferences.setCooperation( "MaxPortsToTry", self.portToTrySpin.value()) bannedUsers = [] for row in range(self.bannedUsersList.count()): bannedUsers.append(self.bannedUsersList.item(row).text()) Preferences.setCooperation("BannedUsers", bannedUsers) @pyqtSlot() def on_bannedUsersList_itemSelectionChanged(self): """ Private slot to react on changes of selected banned users. """ self.deleteBannedUsersButton.setEnabled( len(self.bannedUsersList.selectedItems()) > 0) @pyqtSlot(str) def on_bannedUserEdit_textChanged(self, txt): """ Private slot to handle the user entering a banned user. @param txt text entered by the user (string) """ self.addBannedUserButton.setEnabled( self.__bannedUserValidator.validate(txt, len(txt))[0] == QValidator.Acceptable) @pyqtSlot() def on_deleteBannedUsersButton_clicked(self): """ Private slot to remove the selected users from the list of banned users. """ for itm in self.bannedUsersList.selectedItems(): row = self.bannedUsersList.row(itm) itm = self.bannedUsersList.takeItem(row) del itm @pyqtSlot() def on_addBannedUserButton_clicked(self): """ Private slot to add a user to the list of banned users. """ self.bannedUsersList.addItem(self.bannedUserEdit.text()) self.bannedUserEdit.clear()
class SubCubeControl(QWidget): __LOG: Logger = LogHelper.logger("SubCubeControl") cancel = pyqtSignal() save = pyqtSignal(SaveSubCubeEvent) def __init__(self, files: Dict[str, FileSubCubeParams], parent=None): super().__init__(parent) self.__files = files num_files = len(self.__files) layout = QVBoxLayout() form_layout = QFormLayout() self.__file_list = QComboBox(self) if num_files > 1: self.__file_list.insertItem(0, "Select origin file...") self.__file_list.insertItems(1, self.__files.keys()) else: self.__file_list.insertItems(0, self.__files.keys()) self.__file_list.currentIndexChanged.connect(self.__handle_file_select) form_layout.addRow("Original File:", self.__file_list) self.__file_type = QComboBox(self) self.__format_map = { OpenSpectraHeader.BIL_INTERLEAVE: "BIL - Band Interleaved by Line", OpenSpectraHeader.BSQ_INTERLEAVE: "BSQ - Band Sequential", OpenSpectraHeader.BIP_INTERLEAVE: "BIP - Band Interleaved by Pixel" } self.__file_type.insertItem(0, "") self.__file_type.insertItems(1, self.__format_map.values()) form_layout.addRow("Output File Interleave:", self.__file_type) self.__sample_range = RangeSelector(self) form_layout.addRow("Sample Range:", self.__sample_range) self.__line_range = RangeSelector(self) form_layout.addRow("Line Range:", self.__line_range) self.__band_select = QLineEdit(self) self.__band_select.setMinimumWidth(250) self.__band_validator = QRegExpValidator( QRegExp("[1-9][0-9]*((-|,)([1-9][0-9]*))*")) self.__band_select.setValidator(self.__band_validator) self.__band_select.setToolTip\ ("Use '-' for a range, ',' to separate ranges and single bands.\nExample: 1-10,12,14,19-21") self.__max_band = 0 form_layout.addRow("Bands:", self.__band_select) layout.addLayout(form_layout) button_layout = QHBoxLayout() cancel_button = QPushButton("Cancel", self) cancel_button.clicked.connect(self.cancel) button_layout.addWidget(cancel_button) self.__save_button = QPushButton("Save", self) self.__save_button.setDisabled(True) self.__save_button.clicked.connect(self.__handle_save) button_layout.addWidget(self.__save_button) layout.addLayout(button_layout) self.setLayout(layout) self.__handle_file_select(0) @pyqtSlot(int) def __handle_file_select(self, index: int): if index == 0 and len(self.__files) > 1: self.__save_button.setDisabled(True) self.__line_range.clear() self.__sample_range.clear() self.__max_band = 0 self.__band_select.clear() self.__file_type.setCurrentIndex(0) else: selected_file_name = self.__file_list.currentText() params: FileSubCubeParams = self.__files[selected_file_name] self.__line_range.set_range(1, params.lines()) self.__sample_range.set_range(1, params.samples()) self.__max_band = params.bands() self.__band_select.setText("1-" + str(self.__max_band)) self.__file_type.setCurrentText( self.__format_map[params.file_format()]) self.__save_button.setDisabled(False) @pyqtSlot() def __handle_save(self): source_file_name = self.__file_list.currentText() file_type = self.__file_type.currentText()[0:3].lower() # Convert to zero based indexing using slice range rules lines = self.__line_range.from_value() - 1, self.__line_range.to_value( ) samples = self.__sample_range.from_value( ) - 1, self.__sample_range.to_value() bands_str = self.__band_select.text() SubCubeControl.__LOG.debug( "save button clicked, source file: {0}, type: {1}, lines: {2}, samples: {3}, bands: {4}" .format(source_file_name, file_type, lines, samples, bands_str)) # validate bands args and build the parameter bands = self.__get_band_list(bands_str) SubCubeControl.__LOG.debug("get_band_list returned: {0}".format(bands)) if bands is not None: cube_params = CubeParams(file_type, lines, samples, bands) self.save.emit(SaveSubCubeEvent(source_file_name, cube_params)) def __get_band_list(self, bands: str) -> Union[Tuple[int, int], List[int]]: bands_str = bands validate_result = self.__band_validator.validate(bands_str, 0) if validate_result[0] == QValidator.Invalid: self.__show_error( "Cannot validate band list argument of {0}".format( self.__band_select.text())) return None elif validate_result[0] == QValidator.Intermediate: if str.endswith(bands_str, (",", "-")): bands_str = bands_str[:len(bands_str) - 1] SubCubeControl.__LOG.debug( "attempted to fix band str and got: {0}".format(bands_str)) validate_result = self.__band_validator.validate(bands_str, 0) if validate_result[0] != QValidator.Acceptable: self.__show_error( "Cannot validate band list argument of {0}".format( self.__band_select.text())) return None # collect up the ranges and single bands ranges: List[Tuple[int, int]] = list() single_bands: List[int] = list() # this should produce a list of ranges, 1-5, and individual values # we also convert indexes from 1 based to 0 here # thanks to the validator we should not be getting 0 or negative values so no need to check # validate against self.__max_bands band_range_strs = str.split(bands_str, ",") for band_range in band_range_strs: range_parts = str.split(band_range, "-") if len(range_parts) == 2: # make sure tuple ranges have the lesser value first # it will make things a bit more simple below r1 = int(range_parts[0]) - 1 r2 = int(range_parts[1]) if r1 > self.__max_band: self.__show_error( "Band range value cannot exceed {0}, received range with one end {1}" .format(self.__max_band, range_parts[0])) if r2 > self.__max_band: self.__show_error( "Band range value cannot exceed {0}, received range with one end {1}" .format(self.__max_band, range_parts[1])) if r1 < r2: ranges.append((r1, r2)) elif r2 < r1: ranges.append((r2, r1)) else: # they were equal single_bands.append(r1) elif len(range_parts) == 1: b = int(range_parts[0]) if b >= self.__max_band: self.__show_error( "Band value cannot exceed {0}, received single band index of {1}" .format(self.__max_band, range_parts[0])) single_bands.append(b) else: self.__show_error( "Cannot validate band list argument of {0}".format( self.__band_select.text())) return None # check to see if we just have a single range or band range_cnt = len(ranges) singles_cnt = len(single_bands) if range_cnt == 1 and singles_cnt == 0: return ranges[0] if range_cnt == 0 and singles_cnt == 1: return single_bands # otherwise consolidate the lists to a minimum set of ranges and single bands # reducing it to a tuple if possible # first generate a list of containing all the ranges range_list_list = [list(range(r[0], r[1])) for r in ranges] # SubCubeControl.__LOG.debug("range_list_list: {0}".format(range_list_list)) band_list = list(chain.from_iterable(range_list_list)) # SubCubeControl.__LOG.debug("band_list: {0}".format(band_list)) band_list.extend(single_bands) # SubCubeControl.__LOG.debug("full band_list: {0}".format(band_list)) # now we have all the bands specified by both ranges and single bands # so now create a set from the list to eliminate duplicates band_set = set(band_list) sorted_band_list = sorted(band_set) # SubCubeControl.__LOG.debug("sorted band_set: {0}".format(sorted_band_list)) # now see if it's contiguous and can be returned as a tuple is_contiguous = True last_index = -1 for band_index in sorted_band_list: if last_index == -1: last_index = band_index elif band_index != last_index + 1: is_contiguous = False break else: last_index = band_index if is_contiguous: # then return the bounds as a tuple return sorted_band_list[0], sorted_band_list[len(sorted_band_list) - 1] else: return sorted_band_list def __show_error(self, message: str): dialog = QMessageBox(self) dialog.setIcon(QMessageBox.Critical) dialog.setText(message) dialog.addButton(QMessageBox.Ok) dialog.exec()