class Window(QMainWindow): """Main Window.""" def __init__(self, parent=None): """Initializer.""" super().__init__(parent) self.setWindowTitle('Password Genearator') self.setGeometry(10, 10, 1000, 800) self._createMenu() self._createStatusBar() def _createMenu(self): """ Create menubar. """ file_menu = self.menuBar().addMenu("File") # File Menu - New new_action = QAction("&New", self) new_action.setStatusTip('Create a new password.') new_action.setShortcut('Ctrl+Shift+N') new_action.triggered.connect(self.file_new) file_menu.addAction(new_action) # File Menu - Open open_action = QAction("Open", self) open_action.setStatusTip('Open password file.') open_action.setShortcut('Ctrl+Shift+O') open_action.triggered.connect(self.file_open) file_menu.addAction(open_action) # File Menu - Save save_action = QAction("&Save", self) save_action.setStatusTip('Save password file.') save_action.setShortcut('Ctrl+Shift+S') save_action.triggered.connect(self.file_save) file_menu.addAction(save_action) # File Menu - Delete delete_action = QAction("Delete", self) delete_action.setStatusTip('Delete password.') delete_action.triggered.connect(self.file_delete) file_menu.addAction(delete_action) file_menu.addSeparator() # File Menu - Exit exit_action = QAction("&Exit", self) exit_action.setStatusTip('Exit application.') exit_action.setShortcut('Ctrl+Shift+Q') exit_action.triggered.connect(self.close) file_menu.addAction(exit_action) # About Menu - Help about_action = QAction("About", self) about_action.setStatusTip('Brief summary about app.') about_action.triggered.connect(self.about_help) help_menu = self.menuBar().addMenu("Help") help_menu.addAction(about_action) def _createStatusBar(self): """ Create Status Bar """ status = QStatusBar() status.showMessage("Status Bar Area") self.setStatusBar(status) def file_new(self): """ Display fields to capture user data to generate a password """ # Text box to capture length of password being requested self.size_textbox = QLineEdit(self) self.size_textbox.move(100, 50) self.size_textbox.show() # Label for text to capture password length self.size_label = QLabel('Password Length', self) self.size_label.resize(self.size_label.minimumSizeHint()) self.size_label.move(210, 50) self.size_label.show() # Radio button to request PIN self.pin_radiobtn = QRadioButton('PIN', self) self.pin_radiobtn.resize(self.pin_radiobtn.minimumSizeHint()) self.pin_radiobtn.move(100, 100) self.pin_radiobtn.show() # Radio button to request alphanumeric password self.alphanum_radiobtn = QRadioButton('Alphanumeric', self) self.alphanum_radiobtn.resize(self.alphanum_radiobtn.minimumSizeHint()) self.alphanum_radiobtn.move(100, 150) self.alphanum_radiobtn.show() ''' Radio button to request alphanumeric password w/ special characters password. ''' self.special_radiobtn = QRadioButton( 'Alphanumeric w/ special characters', self) self.special_radiobtn.resize(self.special_radiobtn.minimumSizeHint()) self.special_radiobtn.move(100, 200) self.special_radiobtn.show() # Button to generate the password when clicked self.btn = QPushButton('Generate Password', self) self.btn.resize(self.btn.minimumSizeHint()) self.btn.clicked.connect(self.on_generate_btn_clicked) self.btn.move(250, 275) self.btn.show() # Non-editable text box to display password or error. # This box is hide until password or error is returned. self.generated_pwd = QLineEdit(self) self.generated_pwd.move(60, 325) self.generated_pwd.setEnabled(False) self.generated_pwd.resize(700, 32) self.generated_pwd.hide() def file_open(self): """ Open file containing passwords. """ self.textEdit = QTextEdit() self.setCentralWidget(self.textEdit) options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fname = QFileDialog.getOpenFileName( self, 'QFileDialog.getOpenFileNames()', '/home/mfsd1809/Dev/FullStackWebDeveloper/GUI/pass-gen/Files', 'JSON Files (*.json)', options=options) if fname[0]: f = open(fname[0], 'r') with f: data = json.load(f) self.pw = PasswordWindow() self.app_label = QLabel(self.pw) self.app_label.setText('Application - Password') self.app_label.resize(self.app_label.minimumSizeHint()) self.app_label.move(20, 20) self.b = QPlainTextEdit(self.pw) count = 1 for app, pwd in data.items(): self.b.insertPlainText( str(count) + '. ' + app + ' - ' + pwd + '\n') count = count + 1 self.b.setReadOnly(True) self.b.move(20, 50) self.b.resize(850, 250) self.pw.move(100, 150) self.pw.show() def file_save(self): """ Save application name and password to passwords file """ app, okPressed = QInputDialog.getText(self, "Application Name", "Enter App Name:", QLineEdit.Normal, "") app = app.lower().strip() try: if okPressed and app != '' and self.generated_pwd.text() != '': # Read JSON file with open( '/home/mfsd1809/Dev/FullStackWebDeveloper/GUI/pass-gen/' 'Files/passwords.json') as r_file: data = json.load(r_file) # print(json.dumps(data, indent=4)) # Add/Update JSON file data.update({app: self.generated_pwd.text()}) # Write update to JSON file with open( '/home/mfsd1809/Dev/FullStackWebDeveloper/GUI/pass-gen/' 'Files/passwords.json', 'w') as w_file: json.dump(data, w_file, indent=4) self.get_msg_box(QMessageBox.Information, 'Success', 'Password saved.') elif (okPressed and app == ''): self.get_msg_box(QMessageBox.Warning, 'Insufficient Data', 'You did not enter an app name.') except Exception: self.get_msg_box(QMessageBox.Warning, 'Insufficient Data', 'No password provided for the app you entered.') def file_delete(self): """ Delete application name and password from passwords file """ app, okPressed = QInputDialog.getText(self, "Application Name", "Enter App Name:", QLineEdit.Normal, "") app = app.lower().strip() try: if okPressed and app != '': # Read JSON file with open( '/home/mfsd1809/Dev/FullStackWebDeveloper/GUI/pass-gen/' 'Files/passwords.json') as r_file: data = json.load(r_file) # print(json.dumps(data, indent=4)) # Delete app/password from JSON file del data[app] # Write update to JSON file with open( '/home/mfsd1809/Dev/FullStackWebDeveloper/GUI/pass-gen/' 'Files/passwords.json', 'w') as w_file: json.dump(data, w_file, indent=4) self.get_msg_box(QMessageBox.Information, 'Success', 'Password deleted.') elif (okPressed and app == ''): self.get_msg_box(QMessageBox.Warning, 'Insufficient Data', 'You did not enter an app name.') except Exception: self.get_msg_box(QMessageBox.Warning, 'Insufficient Data', 'No password provided for the app you entered.') def about_help(self): """ Display information about application when Help-->About menu item is clicked """ self.get_msg_box( QMessageBox.Information, 'About', 'This application was created using Python and ' 'PyQt5. It is used to generate a password based ' 'on the user input of length and selected type.') def get_msg_box(self, icon, title, msg): """ Message box""" self.mb = QMessageBox(self) self.mb.setIcon(icon) self.mb.setWindowTitle(title) self.mb.setText(msg) self.mb.setStandardButtons(QMessageBox.Ok) self.mb.show() def get_pin(self, size): """Generate random password, numbers only.""" # Check if input an integer if (isinstance(size, int)): # Check if input is positive if (size < 0): self.get_response('You did not enter a positive integer!', 'error') elif (size < 4): self.get_response('The number must be greater or equal to 4.', 'error') else: digits = string.digits self.get_response( ''.join(random.choice(digits) for i in range(size)), 'success') else: self.get_response('You did NOT enter an integer!', 'error') def get_alphanumeric_password(self, size): """ Generate random password, alphanumeric only """ # Check if input an integer if (isinstance(size, int)): # Check if input is positive if (size < 0): self.get_response('You did not enter a positive integer!', 'error') elif (size < 8): self.get_response('The number must be greater or equal to 8.', 'error') else: letters_and_digits = string.ascii_letters + string.digits self.get_response( ''.join( random.choice(letters_and_digits) for i in range(size)), 'success') else: self.get_response('You did NOT enter an integer!', 'error') def get_alphanumeric_with_symbols_password(self, size): """ Generate random password, alphanumeric with symbols included """ # Check if input an integer if (isinstance(size, int)): # Check if input is positive if (size < 0): self.get_response('You did not enter a positive integer!', 'error') elif (size < 8): self.get_response('The number must be greater or equal to 8.', 'error') else: letters_digits_symbols = (string.ascii_letters + string.digits + string.punctuation) self.get_response( ''.join( random.choice(letters_digits_symbols) for i in range(size)), 'success') else: self.get_response('You did NOT enter an integer!', 'error') def get_response(self, text, result_type): """ Display response from request; password or error in non-editable text box """ self.generated_pwd.setText(text) if (result_type == 'error'): self.generated_pwd.setStyleSheet("color: rgb(255, 0, 0)") else: self.generated_pwd.setStyleSheet("color: rgb(0, 153, 0)") self.generated_pwd.show() def on_generate_btn_clicked(self): """ Execute request to generate password with validations """ try: input = self.size_textbox.text().strip() if (input == ''): self.get_response( 'You did not enter a value for password ' 'length.', 'error') else: input = int(input) if (self.pin_radiobtn.isChecked()): self.get_pin(input) elif (self.alphanum_radiobtn.isChecked()): self.get_alphanumeric_password(input) elif (self.special_radiobtn.isChecked()): self.get_alphanumeric_with_symbols_password(input) else: self.get_response('You must select a password option.', 'error') except ValueError: self.get_response('You entered a string.', 'error')