def __init__(self, settings, *args, **kwargs): super().__init__(*args, **kwargs) layout = QGridLayout(self) #layout.setContentsMargins(0, 0, 0, 0) settings_tabs = QTabWidget() layout.addWidget(settings_tabs) form = 'Gaussian' self.method = MethodOption(settings, form) settings_tabs.addTab(self.method, "Method") self.basis = BasisWidget(settings, form) settings_tabs.addTab(self.basis, "Basis Sets") #menu stuff menu = QMenuBar() self.presets_menu = menu.addMenu("Presets") menu.setNativeMenuBar(False) self._menu = menu layout.setMenuBar(menu) self.settings = settings self.presets = {} self.presets['Gaussian'] = loads(self.settings.gaussian_presets) self.presets['ORCA'] = loads(self.settings.orca_presets) self.presets['Psi4'] = loads(self.settings.psi4_presets) self.refresh_presets()
class Ui_Dialog(object): def setupUi(self, Dialog): def hello(self): print("hello") Dialog.setObjectName("Dialog") Dialog.setWindowModality(QtCore.Qt.ApplicationModal) Dialog.resize(1280, 840) exitAction = QAction(QIcon('exit.png'), 'Exit', parent=Dialog) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit application') exitAction.triggered.connect(qApp.quit) SaveAction = QAction(QIcon('save.png'), 'Save', parent=Dialog) SaveAction.setShortcut('Ctrl+S') SaveAction.setStatusTip('Save') SaveAction.triggered.connect(hello) Anti_Action = QAction(QIcon('Anti.png'), 'Anti-Forensic Tool Execution Trace', parent=Dialog) Anti_Action.setStatusTip('Anti-Forensic Tool Execution Trace') Anti_Action.triggered.connect(hello) Mal_Action = QAction(QIcon('mal.png'), 'Malicious File Execution Trace', parent=Dialog) Mal_Action.setStatusTip('Malicious File Execution Trace') Mal_Action.triggered.connect(hello) Freq_Action = QAction(QIcon('freq.png'), 'Freqently Used File Trace', parent=Dialog) Freq_Action.setStatusTip('Freqently Used File Trace') Freq_Action.triggered.connect(hello) Cont_Action = QAction(QIcon('cont.png'), 'Continuous File Execution Trace', parent=Dialog) Cont_Action.setStatusTip('Continuous File Execution Trace') Cont_Action.triggered.connect(hello) Dele_Action = QAction(QIcon('dele.png'), 'Currently Deleted Executable Trace', parent=Dialog) Dele_Action.setStatusTip('Currently Deleted Executable Trace') Dele_Action.triggered.connect(Defile) self.menubar = QMenuBar(Dialog) self.menubar.setNativeMenuBar(False) self.filemenu = self.menubar.addMenu('&File') self.filemenu.addAction(exitAction) self.filemenu.addAction(SaveAction) self.toolmenu = self.menubar.addMenu('&Tool') self.toolmenu.addAction(Anti_Action) self.toolmenu.addAction(Freq_Action) self.toolmenu.addAction(Cont_Action) self.toolmenu.addAction(Dele_Action) self.toolmenu.addAction(Mal_Action)
def _create_menu_bar(parent): """Create a menu bar. The menu bar is expected to behave consistently for every operating system since `setNativeMenuBar(False)` is called by default and therefore lifetime and ownership can be tested. """ menu_bar = QMenuBar(parent=parent) menu_bar.setNativeMenuBar(False) if parent is not None: parent.setMenuBar(menu_bar) return menu_bar
class _QtMenuBar(_AbstractMenuBar): def _menu_initialize(self, window): self._menus = dict() self._menu_actions = dict() self.menu_bar = QMenuBar() self.menu_bar.setNativeMenuBar(False) window.setMenuBar(self.menu_bar) def _menu_add_submenu(self, name, desc): self._menus[name] = self.menu_bar.addMenu(desc) def _menu_add_button(self, menu_name, name, desc, func): menu = self._menus[menu_name] self._menu_actions[name] = menu.addAction(desc, func)
def setup_menubar(self): menuBar = QMenuBar(self) menuBar.setNativeMenuBar(False) self.setMenuBar(menuBar) leagueMenu = menuBar.addMenu("&League") years = [2021, 2020, 2019, 2018] fantasy_games = ['nhl', 'nfl'] for year in years: year_menu = leagueMenu.addMenu(str(year)) for game in fantasy_games: game_menu = year_menu.addMenu(game) gm = yfa.Game(self.oauth, game) ids = gm.league_ids(year) for id in ids: lg = gm.to_league(id) lg_action = QAction(lg.settings()['name'], self) lg_action.league_id = id lg_action.game_type = game lg_action.year = year game_menu.addAction(lg_action) game_menu.triggered[QAction].connect(self.league_selected)
class Ui_MainWindow(object): def text_inputChanged(self): self.timer_wait_to_refresh.start(1500) def refresh_output_when_timeout(self): self.timer_wait_to_refresh.stop() a_input = self.text_input.toPlainText() print('\ninputed data\n' + a_input) cmd = 'wbxml2xml' try: ishex = int(a_input[:5], 16) finput = open(dirScript + '/input_file', 'wb') a_input = "".join(a_input.split()) a = [a_input[i:i + 2] for i in range(0, len(a_input), 2)] for aa in a: finput.write(binascii.unhexlify(aa)) finput.close() except Exception as e: finput = open(dirScript + '/input_file', 'w') finput.writelines(a_input) finput.close() cmd = 'xml2wbxml' fullcmd = 'export PATH=/usr/local/bin:$PATH;' + cmd + ' -o ' + dirScript + '/output_file ' + dirScript + '/input_file' output = subprocess.getstatusoutput(fullcmd) self.label_parse_result.setText(cmd) if output[0] == 0 else self.label_parse_result.setText(cmd + " failed") if output[0] == 0: if cmd == "xml2wbxml": try: with open(dirScript + '/output_file', "rb") as binary_file: # Read the whole file at once data = binary_file.read() chs = "" for ch in data: chs += "{0:02x}".format(ch) print('\nconverted wbxml\n' + chs) self.text_output.setText(chs) except Exception as e: print(str(e)) self.text_output.setText('Exception:\n' + str(e)) else: try: with open(dirScript + '/output_file', 'r') as xml_file: data = xml_file.read() print('\nconverted xml\n' + data) self.text_output.setPlainText(data) except Exception as e: print(str(e)) self.text_output.setText('Exception:\n' + str(e)) else: self.text_output.setText(output[1]) def setupUi(self, main_window): main_window.setObjectName("main_window") main_window.resize(1024, 600) # self.centralwidget = QtWidgets.QWidget(main_window) # self.centralwidget.setObjectName("centralwidget") # main_window.setCentralWidget(self.centralwidget) font = QFont('Roboto') font.setPointSize(16) fontmono = QFont('SF Mono') self.menubar = QMenuBar(main_window) if platform.uname().system == 'Darwin': self.menubar.setNativeMenuBar(True) self.menubar.setFont(font) self.menubar.setObjectName("menubar") main_window.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(main_window) self.statusbar.setObjectName("statusbar") main_window.setStatusBar(self.statusbar) self.subtitle = QHBoxLayout() self.label_input = QLabel() self.label_input.setFont(font) self.label_input.setAlignment(Qt.AlignCenter) self.label_input.setText("copy paste XML/WBXML here") self.label_parse_result = QLabel() self.label_parse_result.setFont(font) self.label_parse_result.setAlignment(Qt.AlignCenter) self.label_parse_result.setText("converted output") self.subtitle.addWidget(self.label_input) self.subtitle.addWidget(self.label_parse_result) self.text_input = QTextEdit() self.text_input.setAcceptRichText(False) self.text_input.setFont(fontmono) self.text_input.resize(450, 600) self.text_input.textChanged.connect(self.text_inputChanged) self.timer_wait_to_refresh = QTimer() self.timer_wait_to_refresh.setSingleShot(True) self.timer_wait_to_refresh.timeout.connect(self.refresh_output_when_timeout) self.text_output = QTextEdit() self.text_output.setFont(fontmono) self.text_output.resize(450, 600) self.text_output.setReadOnly(True) # self.text_output.setStyleSheet("background-color: gray") self.hbox = QHBoxLayout() # self.hbox.addStretch() self.hbox.addWidget(self.text_input) self.hbox.addWidget(self.text_output) # self.hbox.addStretch() self.vbox = QVBoxLayout() self.vbox.addLayout(self.subtitle) self.vbox.addLayout(self.hbox) self.mainWidget = QWidget() self.mainWidget.setLayout(self.vbox) main_window.setCentralWidget(self.mainWidget) main_window.setWindowTitle('JC WBXML Decoder') QtCore.QMetaObject.connectSlotsByName(main_window)
class WinApp(QMainWindow, Ui_MainWindow): stmt_signal = pyqtSignal(str) def __init__(self): super(QMainWindow, self).__init__() self.setupUi(self) self.connButtonBox.button(QDialogButtonBox.Ok).setText("Connect") self.runButtonBox.button(QDialogButtonBox.Ok).setText("Run") self.tunnelButton.clicked[bool].connect(self.toggle_tunnel) self.tunnelWidget.hide() self.keyFileButton.clicked.connect(self.choose_keyfile) self.clearButton.clicked.connect(self.clear_tunnel) self.keyComboBox.activated[str].connect(self.set_key_type) self.db_engine = DBEngine() self.db_engine.result_signal.connect(self.show_results) self.db_engine.progress_signal.connect(self.set_progress) self.db_engine.error_signal.connect(self.show_error) self.db_engine.msg_signal.connect(self.show_msg) self.stmt_signal.connect(self.db_engine.receive_stmt) self.db_lite = DBLite() self.tunnel = Tunnel() self.tunnel_keyfile = "" self.data_schema = [] self.settings = QSettings() self.restore_settings() history = self.db_lite.history() self.historyMenuBar = QMenuBar(self.sqlWidget) self.historyMenuBar.setNativeMenuBar(False) self.historyMenu = self.historyMenuBar.addMenu(' &History ⇲ ') actions = [ QAction(sql.replace('\n', ' '), self.historyMenu) for sql in history ] for i in range(len(actions)): actions[i].triggered.connect(partial(self.use_history, history[i])) self.historyMenu.addActions(actions) self.history_cache = pylru.lrucache(history_limit, self.remove_action) for i in reversed(range(len(history))): self.history_cache[history[i]] = { KEY_ACTION: actions[i], KEY_RESULTS: [], KEY_COLUMNS: [] } self.historyMenu.setStyleSheet(""" QMenu { max-width: 1000px; font-size: 12px; } """) self.historyMenuBar.setStyleSheet(""" QMenuBar { border: None; } QMenuBar::item { background: #404040; color: #ffffff; border-radius: 4px; } QMenuBar::item:selected { background: rgba(1, 1, 1, 0.2);; color: #404040; border-radius: 4px; } """) self.sqlWidgetLayout.insertWidget(0, self.historyMenuBar) self.connButtonBox.accepted.connect(self.connect) self.connButtonBox.rejected.connect(self.disconnect) self.runButtonBox.accepted.connect(self.run) self.runButtonBox.rejected.connect(self.cancel) self.tablesWidget.itemDoubleClicked.connect(self.get_meta) self.tablesWidget.itemExpanded.connect(self.get_meta) self.progressBar = QProgressBar() self.statusbar.addPermanentWidget(self.progressBar) self.progressBar.setValue(100) QApplication.processEvents() self.highlight = syntax.PrestoHighlighter(self.sqlEdit) self.dataWidget.setContextMenuPolicy(Qt.CustomContextMenu) self.dataWidget.customContextMenuRequested.connect( self.show_table_context_menu) self.dataWidget.horizontalHeader().setStretchLastSection(False) self.dataWidget.horizontalHeader().setSectionResizeMode( QHeaderView.ResizeToContents) self.schemaView.header().setStretchLastSection(False) self.schemaView.header().setSectionResizeMode( QHeaderView.ResizeToContents) self.runButtonBox.button( QDialogButtonBox.Ok).setShortcut("Ctrl+Return") self.completer = SQLCompleter(self) self.sqlEdit.setCompleter(self.completer) self.set_key_type(self.keyComboBox.currentText()) self.sqlEdit.setFocus() def connect(self): self.tablesWidget.clear() self.schemaView.clear() try: if self.serverEdit.text().strip() and self.gatewayEdit.text( ).strip() and self.tunnelUserEdit.text().strip(): self.statusbar.showMessage('Starting tunnel') QApplication.processEvents() self.tunnel.start_tunnel( self.serverEdit.text().strip(), self.gatewayEdit.text().strip(), self.tunnelUserEdit.text().strip(), self.keyComboBox.currentText() == 'KeyFile', self.tunnel_keyfile, self.pwdLineEdit.text(), self.urlEdit.text().strip()) self.statusbar.showMessage('Connecting') QApplication.processEvents() self.db_engine.connect(self.urlEdit.text().strip(), self.userEdit.text().strip()) self.statusbar.showMessage('Fetching db info') QApplication.processEvents() dbs = self.db_engine.dbs() for db in dbs: db_item = QTreeWidgetItem([db]) db_item.setChildIndicatorPolicy(QTreeWidgetItem.ShowIndicator) self.tablesWidget.addTopLevelItem(db_item) self.completer.addItems(dbs) self.statusbar.showMessage('Connected') except Exception as err: QMessageBox.critical(self, "Error", str(err)) self.db_engine.close() self.statusbar.showMessage('Disconnected') def disconnect(self): self.db_engine.close() self.tunnel.stop_tunnel() self.schemaView.clear() self.tablesWidget.clear() self.statusbar.showMessage('Disconnected') def get_meta(self, item): try: if item.parent(): columns = self.db_engine.columns(item.parent().text(0), item.text(0)) self.set_columns(columns) self.completer.addItems([column[0] for column in columns]) else: if item.childCount() <= 0: tables = self.db_engine.tables(item.text(0)) item.addChildren( [QTreeWidgetItem([table]) for table in tables]) self.completer.addTreeItem(item) except Exception as err: QMessageBox.critical(self, "Error", str(err)) def set_columns(self, columns): try: self.schemaView.clear() for column in columns: column_item = self.type_tree(column[0], type_parser.parse(column[1])) self.schemaView.addTopLevelItem(column_item) self.schemaView.expandToDepth(2) for j in range(self.schemaView.columnCount()): self.schemaView.resizeColumnToContents(j) except Exception as err: QMessageBox.critical(self, "Error", str(err)) def run(self): self.dataWidget.setRowCount(0) self.dataWidget.setColumnCount(0) try: self.stmt_signal.emit(self.sqlEdit.toPlainText().strip().replace( ';', '')) self.db_engine.start() except Exception as err: QMessageBox.critical(self, "Error", str(err)) def show_results(self, results, columns, sql, save=True): try: num_cols = len(columns) num_rows = len(results) self.dataWidget.setRowCount(num_rows) self.dataWidget.setColumnCount(num_cols) for i in range(num_rows): for j in range(num_cols): self.dataWidget.setItem( i, j, QTableWidgetItem(str(results[i][j]))) self.dataWidget.resizeColumnsToContents() for j in range(num_cols): header_label = columns[j][0] # header_width = self.fm.width(header_label) # if header_width > self.dataWidget.columnWidth(j): # self.dataWidget.setColumnWidth(j, header_width) self.dataWidget.setHorizontalHeaderItem( j, QTableWidgetItem(header_label)) self.data_schema = [column[1] for column in columns] if not columns and not results: self.dataWidget.setColumnCount(1) self.dataWidget.setHorizontalHeaderItem( 0, QTableWidgetItem("Empty Result")) if save: self.save_history(sql, results, columns) except Exception as err: QMessageBox.critical(self, "Error", str(err)) finally: self.statusbar.showMessage('Finished') def cancel(self): self.db_engine.cancel() def set_progress(self, progress): self.progressBar.setValue(progress) QApplication.processEvents() def save_history(self, sql, results, columns): if sql not in self.history_cache: action = QAction(sql.replace('\n', ' '), self.historyMenu) action.triggered.connect(partial(self.use_history, sql)) self.history_cache[sql] = { KEY_ACTION: action, KEY_RESULTS: results, KEY_COLUMNS: columns } else: action = self.history_cache[sql][KEY_ACTION] self.historyMenu.removeAction(action) if len(results) * len(columns) <= CACHE_LIMIT: self.history_cache[sql][KEY_RESULTS] = results self.history_cache[sql][KEY_COLUMNS] = columns else: self.history_cache[sql][KEY_RESULTS] = [] self.history_cache[sql][KEY_COLUMNS] = [ ("results too large to cache", "varchar") ] self.historyMenu.insertAction( self.historyMenu.actions()[0] if (self.historyMenu.actions()) else None, action) self.db_lite.upsert(sql) def use_history(self, sql): self.sqlEdit.setText(sql) QApplication.processEvents() cached = self.history_cache[sql] self.db_engine.result_signal.emit(cached[KEY_RESULTS], cached[KEY_COLUMNS], sql, False) self.statusbar.showMessage("Loaded cached history") def remove_action(self, sql, cached): self.historyMenu.removeAction(cached[KEY_ACTION]) def show_table_context_menu(self, position): col = self.dataWidget.columnAt(position.x()) dialog = QDialog(self, Qt.Popup) schema_view = QTreeWidget(dialog) schema_view.headerItem().setText(0, "Field") schema_view.headerItem().setText(1, "Type") root = type_parser.parse(self.data_schema[col]) schema_tree = self.type_tree( self.dataWidget.horizontalHeaderItem(col).text(), root) schema_view.addTopLevelItem(schema_tree) schema_view.expandToDepth(2) schema_view.header().setStretchLastSection(False) schema_view.setSizeAdjustPolicy( QAbstractScrollArea.AdjustToContentsOnFirstShow) schema_view.header().setSectionResizeMode(QHeaderView.ResizeToContents) schema_view.setMinimumHeight(30) schema_view.setMaximumHeight(400) schema_view.adjustSize() schema_view.setHeaderHidden(True) dialog.move( self.dataWidget.mapToGlobal(position) + QPoint(dialog.width() / 5 * 2, dialog.height() + 5)) dialog.adjustSize() dialog.show() def type_tree(self, name, root): if root.children[0].data == 'primitive_type': return QTreeWidgetItem([name, root.children[0].children[0].value]) elif root.children[0].data == 'row_type': root_widget = QTreeWidgetItem([name, 'row']) for i in range(len(root.children[0].children) // 2): name = root.children[0].children[i * 2].value child_type = root.children[0].children[i * 2 + 1] root_widget.addChild(self.type_tree(name, child_type)) return root_widget elif root.children[0].data == 'array_type': if root.children[0].children[0].children[ 0].data == 'primitive_type': return QTreeWidgetItem([ name, 'array(' + root.children[0].children[0].children[0].children[0].value + ')' ]) else: root_widget = QTreeWidgetItem([name, 'array(row)']) for i in range( len(root.children[0].children[0].children[0].children) // 2): name = root.children[0].children[0].children[0].children[ i * 2].value child_type = root.children[0].children[0].children[ 0].children[i * 2 + 1] root_widget.addChild(self.type_tree(name, child_type)) return root_widget elif root.children[0].data == 'map_type': root_widget = QTreeWidgetItem([name, 'map']) key = self.type_tree('_key', root.children[0].children[0]) value = self.type_tree('_value', root.children[0].children[1]) root_widget.addChildren([key, value]) return root_widget else: pass def toggle_tunnel(self, pressed): if pressed: self.tunnelWidget.show() self.repaint() else: self.tunnelWidget.hide() def choose_keyfile(self): file_name, _ = QFileDialog.getOpenFileName(self, "Choose Key File", QDir.homePath() + "/.ssh", "All Files (*)") if file_name: self.tunnel_keyfile = file_name self.keyFileButton.setText(file_name.split('/')[-1]) def clear_tunnel(self): self.tunnel_keyfile = None self.keyFileButton.setText("Choose Key File...") self.serverEdit.clear() self.gatewayEdit.clear() self.tunnelUserEdit.clear() self.pwdLineEdit.clear() def close_all(self): self.save_settings() self.db_engine.close() self.tunnel.stop_tunnel() def restore_settings(self): self.urlEdit.setText(self.settings.value(URL, "")) self.userEdit.setText(self.settings.value(USER, "")) self.serverEdit.setText(self.settings.value(SERVER, "")) self.gatewayEdit.setText(self.settings.value(GATEWAY, "")) self.tunnelUserEdit.setText(self.settings.value(TUNNEL_USER, "")) self.tunnel_keyfile = self.settings.value(KEYFILE, "") if self.tunnel_keyfile: self.keyFileButton.setText(self.tunnel_keyfile.split('/')[-1]) self.pwdLineEdit.setText(self.settings.value(TUNNEL_PWD, "")) self.keyComboBox.setCurrentText(self.settings.value( KEYTYPE, "KeyFile")) def save_settings(self): self.settings.setValue(URL, self.urlEdit.text().strip()) self.settings.setValue(USER, self.userEdit.text().strip()) self.settings.setValue(SERVER, self.serverEdit.text().strip()) self.settings.setValue(GATEWAY, self.gatewayEdit.text().strip()) self.settings.setValue(TUNNEL_USER, self.tunnelUserEdit.text().strip()) self.settings.setValue(KEYFILE, self.tunnel_keyfile) self.settings.setValue(KEYTYPE, self.keyComboBox.currentText()) self.settings.setValue(TUNNEL_PWD, self.pwdLineEdit.text()) self.settings.sync() def show_error(self, error): QMessageBox.critical(self, "Error", error) def show_msg(self, msg): self.statusbar.showMessage(msg) def set_key_type(self, key_type): if key_type == 'KeyFile': self.pwdLineEdit.hide() self.keyFileButton.show() else: self.keyFileButton.hide() self.pwdLineEdit.show()
class Window(QWidget): def __init__(self): # other lines above QWidget.__init__(self) self.resize(450, 250) self.setWindowTitle('Tax Calculation') self.layout = QGridLayout() self.setLayout(self.layout) # This is for filename self.file_name = '' # Add status bar self.statusbar = QStatusBar() # Add MenuBar self.menubar = QMenuBar() # The default menu is usually in Mac OS, # but we don't want to use the one in the OS. self.menubar.setNativeMenuBar(False) # Display Menu Bar self.menubar.show() # Add menus self.file_menu = self.menubar.addMenu('File') self.edit_menu = self.menubar.addMenu('Edit') self.help_menu = self.menubar.addMenu('Help') self.action_open = QAction('Open', self) self.action_open.setShortcut('Ctrl+O') self.action_save = QAction('Save', self) self.action_save.setShortcut('Ctrl+S') self.action_quit = QAction('Quit', self) self.action_quit.setShortcut('Ctrl+Q') self.action_clear = QAction('Clear All', self) self.action_about = QAction('About', self) # Link the action to the menu self.file_menu.addAction(self.action_open) self.file_menu.addAction(self.action_save) # To separate (dividing line between open, save, and quit) self.file_menu.addSeparator() self.file_menu.addAction(self.action_quit) self.edit_menu.addAction(self.action_clear) self.help_menu.addAction(self.action_about) # Empty text editor (make typing) self.tax_editor = QTextEdit() self.layout.addWidget(self.menubar) self.layout.addWidget(self.tax_editor) self.layout.addWidget(self.statusbar) # Connect to function self.action_open.triggered.connect(self.open_text) self.action_save.triggered.connect(self.save_text) self.action_quit.triggered.connect(self.quit) self.action_clear.triggered.connect(self.tax_editor.clear) self.action_about.triggered.connect(self.about) # If we want to know how many lines we have written self.tax_editor.textChanged.connect(self.show_lines) # Functions inside the Window class def save_text(self): # 0pen file and save # 0pen dialog, filter as .txt # To filter save as text >> name, _ = QFileDialog.getSaveFileName(self, 'Save', self.file_name, 'TXT(*.txt)') # dialog exists and file is opening if name: # set file name self.file_name = name # 'w' >> set to write mode file = open(name, 'w') # Abis itu we get the text from editor text = self.tax_editor.toPlainText() # write to file file.write(text) # close file >> so files that are opened must be closed file.close() # Similar to the function above (save_text) def open_text(self): # open file and load # open dialog, filter only .txt files, no file name name, _ = QFileDialog.getOpenFileName(self, 'Open', '', 'TXT(*.txt)') # file exists if name: # set file name self.file_name = name # set to read mode file = open(name, 'r') # process file, read and set to text edit widget with file: data = file.read() enter = data.split('\n') self.result_TI = float(enter[0]) - float(enter[1]) my_num = self.result_TI # Python string format thounsand separators # To convert float values into commas as thousands separators my_ti = '{:,.2f}'.format(my_num) agi = '{:,.2f}'.format(float(enter[0])) nti = '{:,.2f}'.format(float(enter[1])) # The text editor is empty first then fill in the data self.tax_editor.setPlainText('') self.tax_editor.setPlainText( f'Your Annual Gross Income\t: Rp{agi} \nYour Non-Taxable Income\t: Rp{nti}\nYour Tax Income\t: Rp{str(my_ti)}\nYour Income Tax\t: Rp{str(self.calculate_tax())}' ) # close file file.close() def calculate_tax(self): # Declare Percent as: percent_level_1 = 0.05 percent_level_2 = 0.15 percent_level_3 = 0.25 percent_level_4 = 0.30 # Income Tax Formula: tax_level_1 = self.result_TI * percent_level_1 tax_level_2 = percent_level_1 * 50000000 + (self.result_TI - 50000000) * percent_level_2 tax_level_3 = percent_level_1 * 50000000 + percent_level_2 * ( 250000000 - 50000000) + (self.result_TI - 250000000) * percent_level_3 tax_level_4 = percent_level_1 * 50000000 + percent_level_2 * ( 250000000 - 50000000) + percent_level_3 * ( 500000000 - 250000000) + (self.result_TI - 500000000) * percent_level_4 # income tax if self.result_TI <= 50000000: my_num = tax_level_1 # Python string format thounsand separators my_tax = '{:,.2f}'.format(my_num) return my_tax elif 50000000 < self.result_TI <= 250000000: my_num = tax_level_2 # Python string format thounsand separators my_tax = '{:,.2f}'.format(my_num) return my_tax elif 250000000 < self.result_TI <= 500000000: my_num = tax_level_3 # Python string format thounsand separators my_tax = '{:,.2f}'.format(my_num) return my_tax elif self.result_TI > 500000000: my_num = tax_level_4 # Python string format thounsand separators my_tax = '{:,.2f}'.format(my_num) return my_tax def quit(self): # quit application QApplication.quit() def about(self): # show message dengan message box msg = QMessageBox() msg.setText('This is a dummy Taxpad') msg.exec_() # Functions inside the Window class def show_lines(self): # get text text = self.tax_editor.toPlainText() len_text = len(text.split('\n')) self.statusbar.showMessage('Lines: %s' % str(len_text))
def _build_ui(self): layout = QVBoxLayout() self.file_selector = FilereaderComboBox(self.session) self.file_selector.currentIndexChanged.connect(self.fill_table) layout.insertWidget(0, self.file_selector, 0) self.table = QTableWidget() self.table.setColumnCount(2) self.table.setHorizontalHeaderLabels(['Data', 'Value']) self.table.horizontalHeader().setStretchLastSection(False) self.table.horizontalHeader().setSectionResizeMode( 0, QHeaderView.Interactive) self.table.setEditTriggers(QTableWidget.NoEditTriggers) self.table.horizontalHeader().setSectionResizeMode( 1, QHeaderView.Stretch) self.table.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) layout.insertWidget(1, self.table, 1) self.filter = QLineEdit() self.filter.setPlaceholderText("filter data") self.filter.textChanged.connect(self.apply_filter) self.filter.setClearButtonEnabled(True) layout.insertWidget(2, self.filter, 0) menu = QMenuBar() export = menu.addMenu("&Export") copy = QAction("&Copy CSV to clipboard", self.tool_window.ui_area) copy.triggered.connect(self.copy_csv) shortcut = QKeySequence(Qt.CTRL + Qt.Key_C) copy.setShortcut(shortcut) export.addAction(copy) self.copy = copy save = QAction("&Save CSV...", self.tool_window.ui_area) save.triggered.connect(self.save_csv) #this shortcut interferes with main window's save shortcut #I've tried different shortcut contexts to no avail #thanks Qt... #shortcut = QKeySequence(Qt.CTRL + Qt.Key_S) #save.setShortcut(shortcut) #save.setShortcutContext(Qt.WidgetShortcut) export.addAction(save) delimiter = export.addMenu("Delimiter") # comma = QAction("comma", self.tool_window.ui_area, checkable=True) # comma.setChecked(self.settings.delimiter == "comma") # comma.triggered.connect(lambda *args, delim="comma": self.settings.__setattr__("delimiter", delim)) # delimiter.addAction(comma) tab = QAction("tab", self.tool_window.ui_area, checkable=True) tab.setChecked(self.settings.delimiter == "tab") tab.triggered.connect(lambda *args, delim="tab": self.settings. __setattr__("delimiter", delim)) delimiter.addAction(tab) # space = QAction("space", self.tool_window.ui_area, checkable=True) # space.setChecked(self.settings.delimiter == "space") # space.triggered.connect(lambda *args, delim="space": self.settings.__setattr__("delimiter", delim)) # delimiter.addAction(space) semicolon = QAction("semicolon", self.tool_window.ui_area, checkable=True) semicolon.setChecked(self.settings.delimiter == "semicolon") semicolon.triggered.connect(lambda *args, delim="semicolon": self. settings.__setattr__("delimiter", delim)) delimiter.addAction(semicolon) add_header = QAction("&Include CSV header", self.tool_window.ui_area, checkable=True) add_header.setChecked(self.settings.include_header) add_header.triggered.connect(self.header_check) export.addAction(add_header) tab.triggered.connect( lambda *args, action=semicolon: action.setChecked(False)) semicolon.triggered.connect( lambda *args, action=tab: action.setChecked(False)) archive = QAction("Include archive if present", self.tool_window.ui_area, checkable=True) archive.triggered.connect( lambda checked: setattr(self.settings, "archive", checked)) archive.triggered.connect( lambda *args: self.fill_table(self.file_selector.count() - 1)) archive.setChecked(self.settings.archive) export.addAction(archive) unit = menu.addMenu("&Units") energy = unit.addMenu("energy") hartree = QAction("Hartree", self.tool_window.ui_area, checkable=True) hartree.setChecked(self.settings.energy == "Hartree") kcal = QAction("kcal/mol", self.tool_window.ui_area, checkable=True) kcal.setChecked(self.settings.energy == "kcal/mol") kjoule = QAction("kJ/mol", self.tool_window.ui_area, checkable=True) kjoule.setChecked(self.settings.energy == "kJ/mol") energy.addAction(hartree) energy.addAction(kcal) energy.addAction(kjoule) hartree.triggered.connect( lambda *args, val="Hartree": setattr(self.settings, "energy", val)) hartree.triggered.connect( lambda *args: self.fill_table(self.file_selector.count() - 1)) hartree.triggered.connect( lambda *args, action=kcal: action.setChecked(False)) hartree.triggered.connect( lambda *args, action=kjoule: action.setChecked(False)) kcal.triggered.connect(lambda *args, val="kcal/mol": setattr( self.settings, "energy", val)) kcal.triggered.connect( lambda *args: self.fill_table(self.file_selector.count() - 1)) kcal.triggered.connect( lambda *args, action=hartree: action.setChecked(False)) kcal.triggered.connect( lambda *args, action=kjoule: action.setChecked(False)) kjoule.triggered.connect( lambda *args, val="kJ/mol": setattr(self.settings, "energy", val)) kjoule.triggered.connect( lambda *args: self.fill_table(self.file_selector.count() - 1)) kjoule.triggered.connect( lambda *args, action=hartree: action.setChecked(False)) kjoule.triggered.connect( lambda *args, action=kcal: action.setChecked(False)) mass = unit.addMenu("mass") kg = QAction("kg", self.tool_window.ui_area, checkable=True) kg.setChecked(self.settings.mass == "kg") amu = QAction("Da", self.tool_window.ui_area, checkable=True) amu.setChecked(self.settings.mass == "Da") mass.addAction(kg) mass.addAction(amu) kg.triggered.connect( lambda *args, val="kg": setattr(self.settings, "mass", val)) kg.triggered.connect( lambda *args: self.fill_table(self.file_selector.count() - 1)) kg.triggered.connect( lambda *args, action=amu: action.setChecked(False)) amu.triggered.connect( lambda *args, val="Da": setattr(self.settings, "mass", val)) amu.triggered.connect( lambda *args: self.fill_table(self.file_selector.count() - 1)) amu.triggered.connect( lambda *args, action=kg: action.setChecked(False)) rot_const = unit.addMenu("rotational constants") temperature = QAction("K", self.tool_window.ui_area, checkable=True) temperature.setChecked(self.settings.rot_const == "K") hertz = QAction("GHz", self.tool_window.ui_area, checkable=True) hertz.setChecked(self.settings.rot_const == "GHz") rot_const.addAction(temperature) rot_const.addAction(hertz) temperature.triggered.connect( lambda *args, val="K": setattr(self.settings, "rot_const", val)) temperature.triggered.connect( lambda *args: self.fill_table(self.file_selector.count() - 1)) temperature.triggered.connect( lambda *args, action=hertz: action.setChecked(False)) hertz.triggered.connect( lambda *args, val="GHz": setattr(self.settings, "rot_const", val)) hertz.triggered.connect( lambda *args: self.fill_table(self.file_selector.count() - 1)) hertz.triggered.connect( lambda *args, action=temperature: action.setChecked(False)) menu.setNativeMenuBar(False) self._menu = menu layout.setMenuBar(menu) if len(self.session.filereader_manager.list()) > 0: self.fill_table(0) self.tool_window.ui_area.setLayout(layout) self.tool_window.manage(None)
def init_gui(self): import_tptp_file_action = QAction('&Import TPTP syntax file', self) import_tptp_file_action.setShortcut('Ctrl+I') import_tptp_file_action.triggered.connect(self.load_tptp_syntax_file) import_tptp_file_from_web_action = QAction('&Import TPTP syntax file from web', self) import_tptp_file_from_web_action.setShortcut('Ctrl+W') import_tptp_file_from_web_action.triggered.connect(self.get_tptp_syntax_from_web) save_with_control_file_action = QAction('&Reduce and save TPTP syntax with control file', self) save_with_control_file_action.setShortcut('Ctrl+S') save_with_control_file_action.triggered.connect(self.output_tptp_syntax_from_control_file_without_comments) save_tptp_grammar_file_from_selection_action = QAction('&Reduce and save TPTP syntax with selection', self) save_tptp_grammar_file_from_selection_action.setShortcut('Ctrl+D') save_tptp_grammar_file_from_selection_action.triggered.connect(self.create_tptp_syntax_file_from_selection_without_comments) produce_reduced_tptp_grammar_action = QAction('&Reduce TPTP syntax with selection', self) produce_reduced_tptp_grammar_action.setShortcut('Ctrl+R') produce_reduced_tptp_grammar_action.triggered.connect(self.reduce_tptp_syntax_with_selection) save_control_file_action = QAction('&Produce and save control file from selection', self) save_control_file_action.setShortcut('Ctrl+F') save_control_file_action.triggered.connect(self.output_control_file) toggle_comments_action = QAction('&Toggle comments', self) toggle_comments_action.setShortcut('Ctrl+C') toggle_comments_action.triggered.connect(self.toggle_comments) import_control_file_action = QAction('&Import control file', self) import_control_file_action.setShortcut('Ctrl+O') import_control_file_action.triggered.connect(self.load_control_file) save_with_control_file_comments_action = QAction('&Reduce and save TPTP syntax with control file with external comment syntax', self) save_with_control_file_comments_action.triggered.connect(self.create_tptp_syntax_from_control_file_with_comments) save_tptp_grammar_file_from_selection_comments_action = QAction('&Reduce and save TPTP syntax from selection with external comment syntax', self) save_tptp_grammar_file_from_selection_comments_action.triggered.connect(self.create_tptp_syntax_file_from_selection_with_comments) menubar = QMenuBar() self.setMenuBar(menubar) menubar.setNativeMenuBar(False) import_menu = menubar.addMenu("Import syntax") import_menu.addAction(import_tptp_file_action) import_menu.addAction(import_tptp_file_from_web_action) save_menu = menubar.addMenu("Save syntax") save_menu.addAction(save_tptp_grammar_file_from_selection_action) save_menu.addAction(save_with_control_file_action) save_menu.addSeparator() save_menu.addAction(save_with_control_file_comments_action) save_menu.addAction(save_tptp_grammar_file_from_selection_comments_action) reduce_menu = menubar.addMenu("Reduce") reduce_menu.addAction(produce_reduced_tptp_grammar_action) control_file_menu = menubar.addMenu("Control file") control_file_menu.addAction(import_control_file_action) control_file_menu.addAction(save_control_file_action) view_menu = menubar.addMenu("View") view_menu.addAction(toggle_comments_action) self.setWindowTitle('TPTP sub-syntax extractor') self.showMaximized()
def ui(self): menubar = QMenuBar() menubar.setNativeMenuBar(True) # make the menu bar OS specific bar_file = menubar.addMenu(self.tr("&File")) file_load = QAction(self.tr("&Load image"), self, shortcut=QKeySequence.New, statusTip=self.tr("Load a new image"), triggered=self.open_file) file_save = QAction(self.tr("&Save plate"), self, shortcut=QKeySequence.Save, statusTip=self.tr("Save the pattern"), triggered=self.save_file) file_print = QAction(self.tr("&Print"), self, shortcut=QKeySequence.Print, statusTip=self.tr("Print pixel pattern"), triggered=self.print_file) file_settings = QAction(self.tr("S&ettings"), self, statusTip=self.tr('Change settings'), triggered=self.change_settings) file_quit = QAction(self.tr("&Quit"), self, shortcut=QKeySequence.Quit, statusTip=self.tr('Quit the program'), triggered=self.close) bar_file.addAction(file_load) bar_file.addAction(file_save) bar_file.addAction(file_print) bar_file.addAction(file_settings) bar_file.addAction(file_quit) bar_about = menubar.addMenu(self.tr("&About")) about_about = QAction(self.tr("&About"), self, statusTip=self.tr("Show about PyBigPix"), triggered=self.show_about) about_licence = QAction(self.tr("&License"), self, statusTip=self.tr('Show license'), triggered=self.show_license) about_QT = QAction(self.tr("About &QT"), self, statusTip=self.tr("Show about QT"), triggered=qApp.aboutQt) bar_about.addAction(about_about) bar_about.addAction(about_licence) bar_about.addAction(about_QT) self.setMenuWidget(menubar) self.setMenuBar(menubar) self.setWindowTitle(self.window_title) self.label_image = QLabel(self.tr("Start Image")) self.label_image.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.label_image.setMinimumSize(400, 400) self.label_image.textFormat() self.label_image.setFrameShape(QFrame.Panel) self.label_image.setAlignment(Qt.AlignCenter) self.lable_pixels = QLabel(self.tr("Pixel Image")) self.lable_pixels.setMinimumSize(400, 400) self.lable_pixels.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.lable_pixels.setAlignment(Qt.AlignCenter) self.lable_pixels.setFrameShape(QFrame.Panel) self.centeralwidget = QWidget() layout = QHBoxLayout(self.centeralwidget) layout.addWidget(self.label_image) layout.addWidget(self.lable_pixels) self.setCentralWidget(self.centeralwidget)
def _build_ui(self): layout = QGridLayout() tabs = QTabWidget() calc_widget = QWidget() calc_layout = QFormLayout(calc_widget) vis_widget = QWidget() vis_layout = QFormLayout(vis_widget) layout.addWidget(tabs) tabs.addTab(calc_widget, "calculation") tabs.addTab(vis_widget, "visualization") self.radii_option = QComboBox() self.radii_option.addItems(["Bondi", "UMN"]) ndx = self.radii_option.findText(self.settings.radii, Qt.MatchExactly) self.radii_option.setCurrentIndex(ndx) calc_layout.addRow("radii:", self.radii_option) self.scale = QDoubleSpinBox() self.scale.setValue(self.settings.vdw_scale) self.scale.setSingleStep(0.01) self.scale.setRange(1., 1.5) calc_layout.addRow("VDW scale:", self.scale) set_ligand_atoms = QPushButton("set ligands to current selection") set_ligand_atoms.clicked.connect(self.set_ligand_atoms) set_ligand_atoms.setToolTip( "specify atoms to use in calculation\n" + "by default, all atoms will be used unless a single center is specified\n" + "in the case of a single center, all atoms except the center is used" ) calc_layout.addRow(set_ligand_atoms) self.set_ligand_atoms = set_ligand_atoms self.radius = QDoubleSpinBox() self.radius.setValue(self.settings.center_radius) self.radius.setSuffix(" \u212B") self.radius.setDecimals(1) self.radius.setSingleStep(0.1) self.radius.setRange(1., 15.) calc_layout.addRow("radius around center:", self.radius) self.method = QComboBox() self.method.addItems(["Lebedev", "Monte-Carlo"]) self.method.setToolTip("Lebedev: deterministic method\n" + "Monte-Carlo: non-deterministic method") ndx = self.method.findText(self.settings.method, Qt.MatchExactly) self.method.setCurrentIndex(ndx) calc_layout.addRow("integration method:", self.method) leb_widget = QWidget() leb_layout = QFormLayout(leb_widget) leb_layout.setContentsMargins(0, 0, 0, 0) self.radial_points = QComboBox() self.radial_points.addItems(["20", "32", "64", "75", "99", "127"]) self.radial_points.setToolTip( "more radial points will give more accurate results, but integration will take longer" ) ndx = self.radial_points.findText(self.settings.radial_points, Qt.MatchExactly) self.radial_points.setCurrentIndex(ndx) leb_layout.addRow("radial points:", self.radial_points) self.angular_points = QComboBox() self.angular_points.addItems([ "110", "194", "302", "590", "974", "1454", "2030", "2702", "5810" ]) self.angular_points.setToolTip( "more angular points will give more accurate results, but integration will take longer" ) ndx = self.angular_points.findText(self.settings.angular_points, Qt.MatchExactly) self.angular_points.setCurrentIndex(ndx) leb_layout.addRow("angular points:", self.angular_points) calc_layout.addRow(leb_widget) mc_widget = QWidget() mc_layout = QFormLayout(mc_widget) mc_layout.setContentsMargins(0, 0, 0, 0) self.min_iter = QSpinBox() self.min_iter.setValue(self.settings.minimum_iterations) self.min_iter.setRange(0, 10000) self.min_iter.setToolTip( "each iteration is 3000 points\n" + "iterations continue until convergence criteria are met") mc_layout.addRow("minimum interations:", self.min_iter) calc_layout.addRow(mc_widget) if self.settings.method == "Lebedev": mc_widget.setVisible(False) elif self.settings.method == "Monte-Carlo": leb_widget.setVisible(False) self.method.currentTextChanged.connect( lambda text, widget=leb_widget: widget.setVisible(text == "Lebedev" )) self.method.currentTextChanged.connect( lambda text, widget=mc_widget: widget.setVisible(text == "Monte-Carlo")) self.use_centroid = QCheckBox() self.use_centroid.setChecked(self.settings.use_centroid) self.use_centroid.setToolTip( "place the center between selected atoms\n" + "might be useful for polydentate ligands") calc_layout.addRow("use centroid of centers:", self.use_centroid) steric_map_options = QGroupBox("steric map") steric_map_layout = QFormLayout(steric_map_options) self.steric_map = QCheckBox() self.steric_map.setChecked(self.settings.steric_map) self.steric_map.setToolTip( "produce a 2D projection of steric bulk\ncauses buried volume to be reported for individual quadrants" ) steric_map_layout.addRow("create steric map:", self.steric_map) self.use_scene = QCheckBox() self.use_scene.setChecked(self.settings.use_scene) self.use_scene.setToolTip( "steric map will use the orientation the molecule is displayed in") steric_map_layout.addRow("use display orientation:", self.use_scene) self.num_pts = QSpinBox() self.num_pts.setRange(25, 250) self.num_pts.setValue(self.settings.num_pts) self.num_pts.setToolTip("number of points along x and y axes") steric_map_layout.addRow("number of points:", self.num_pts) self.include_vbur = QCheckBox() self.include_vbur.setChecked(self.settings.include_vbur) steric_map_layout.addRow("label quadrants with %V<sub>bur</sub>", self.include_vbur) self.map_shape = QComboBox() self.map_shape.addItems(["circle", "square"]) ndx = self.map_shape.findText(self.settings.map_shape, Qt.MatchExactly) self.map_shape.setCurrentIndex(ndx) steric_map_layout.addRow("map shape:", self.map_shape) self.auto_minmax = QCheckBox() self.auto_minmax.setChecked(self.settings.auto_minmax) steric_map_layout.addRow("automatic min. and max.:", self.auto_minmax) self.map_min = QDoubleSpinBox() self.map_min.setRange(-15., 0.) self.map_min.setSuffix(" \u212B") self.map_min.setSingleStep(0.1) self.map_min.setValue(self.settings.map_min) steric_map_layout.addRow("minimum value:", self.map_min) self.map_max = QDoubleSpinBox() self.map_max.setRange(0., 15.) self.map_max.setSuffix(" \u212B") self.map_max.setSingleStep(0.1) self.map_max.setValue(self.settings.map_max) steric_map_layout.addRow("maximum value:", self.map_max) self.use_scene.setEnabled(self.settings.steric_map) self.steric_map.stateChanged.connect( lambda state, widget=self.use_scene: widget.setEnabled(state == Qt. Checked)) self.num_pts.setEnabled(self.settings.steric_map) self.steric_map.stateChanged.connect( lambda state, widget=self.num_pts: widget.setEnabled(state == Qt. Checked)) self.include_vbur.setEnabled(self.settings.steric_map) self.steric_map.stateChanged.connect( lambda state, widget=self.include_vbur: widget.setEnabled( state == Qt.Checked)) self.map_shape.setEnabled(self.settings.steric_map) self.steric_map.stateChanged.connect( lambda state, widget=self.map_shape: widget.setEnabled(state == Qt. Checked)) self.auto_minmax.setEnabled(self.settings.steric_map) self.steric_map.stateChanged.connect( lambda state, widget=self.auto_minmax: widget.setEnabled( state == Qt.Checked)) self.map_min.setEnabled(not self.settings.auto_minmax and self.settings.steric_map) self.steric_map.stateChanged.connect( lambda state, widget=self.map_min, widget2=self.auto_minmax: widget .setEnabled(state == Qt.Checked and not widget2.isChecked())) self.auto_minmax.stateChanged.connect( lambda state, widget=self.map_min, widget2=self.steric_map: widget. setEnabled(not state == Qt.Checked and widget2.isChecked())) self.map_max.setEnabled(not self.settings.auto_minmax and self.settings.steric_map) self.steric_map.stateChanged.connect( lambda state, widget=self.map_max, widget2=self.auto_minmax: widget .setEnabled(state == Qt.Checked and not widget2.isChecked())) self.auto_minmax.stateChanged.connect( lambda state, widget=self.map_max, widget2=self.steric_map: widget. setEnabled(not state == Qt.Checked and widget2.isChecked())) vis_layout.addRow(steric_map_options) cutout_options = QGroupBox("volume cutout") cutout_layout = QFormLayout(cutout_options) self.display_cutout = QComboBox() self.display_cutout.addItems(["no", "free", "buried"]) ndx = self.display_cutout.findText(self.settings.display_cutout, Qt.MatchExactly) self.display_cutout.setCurrentIndex(ndx) self.display_cutout.setToolTip("show free or buried volume") cutout_layout.addRow("display volume:", self.display_cutout) self.point_spacing = QDoubleSpinBox() self.point_spacing.setDecimals(3) self.point_spacing.setRange(0.01, 0.5) self.point_spacing.setSingleStep(0.005) self.point_spacing.setSuffix(" \u212B") self.point_spacing.setValue(self.settings.point_spacing) self.point_spacing.setToolTip( "distance between points on cutout\n" + "smaller spacing will narrow gaps, but increase time to create the cutout" ) cutout_layout.addRow("point spacing:", self.point_spacing) self.intersection_scale = QDoubleSpinBox() self.intersection_scale.setDecimals(2) self.intersection_scale.setRange(1., 10.) self.intersection_scale.setSingleStep(0.5) self.intersection_scale.setSuffix("x") self.intersection_scale.setToolTip( "relative density of points where VDW radii intersect\n" + "higher density will narrow gaps, but increase time to create cutout" ) self.intersection_scale.setValue(self.settings.intersection_scale) cutout_layout.addRow("intersection density:", self.intersection_scale) self.point_spacing.setEnabled(self.settings.display_cutout != "no") self.intersection_scale.setEnabled( self.settings.display_cutout != "no") self.display_cutout.currentTextChanged.connect( lambda text, widget=self.point_spacing: widget.setEnabled(text != "no")) self.display_cutout.currentTextChanged.connect( lambda text, widget=self.intersection_scale: widget.setEnabled( text != "no")) vis_layout.addRow(cutout_options) calc_vbur_button = QPushButton( "calculate % buried volume for selected centers") calc_vbur_button.clicked.connect(self.calc_vbur) calc_layout.addRow(calc_vbur_button) self.calc_vbur_button = calc_vbur_button remove_vbur_button = QPushButton( "remove % buried volume visualizations") remove_vbur_button.clicked.connect(self.del_vbur) cutout_layout.addRow(remove_vbur_button) self.table = QTableWidget() self.table.setColumnCount(3) self.table.setHorizontalHeaderLabels(['model', 'center', '%Vbur']) self.table.setSelectionBehavior(QTableWidget.SelectRows) self.table.setEditTriggers(QTableWidget.NoEditTriggers) self.table.resizeColumnToContents(0) self.table.resizeColumnToContents(1) self.table.resizeColumnToContents(2) self.table.horizontalHeader().setSectionResizeMode( 2, QHeaderView.Stretch) calc_layout.addRow(self.table) menu = QMenuBar() export = menu.addMenu("&Export") copy = QAction("&Copy CSV to clipboard", self.tool_window.ui_area) copy.triggered.connect(self.copy_csv) shortcut = QKeySequence(Qt.CTRL + Qt.Key_C) copy.setShortcut(shortcut) export.addAction(copy) self.copy = copy save = QAction("&Save CSV...", self.tool_window.ui_area) save.triggered.connect(self.save_csv) #this shortcut interferes with main window's save shortcut #I've tried different shortcut contexts to no avail #thanks Qt... #shortcut = QKeySequence(Qt.CTRL + Qt.Key_S) #save.setShortcut(shortcut) #save.setShortcutContext(Qt.WidgetShortcut) export.addAction(save) delimiter = export.addMenu("Delimiter") comma = QAction("comma", self.tool_window.ui_area, checkable=True) comma.setChecked(self.settings.delimiter == "comma") comma.triggered.connect(lambda *args, delim="comma": self.settings. __setattr__("delimiter", delim)) delimiter.addAction(comma) tab = QAction("tab", self.tool_window.ui_area, checkable=True) tab.setChecked(self.settings.delimiter == "tab") tab.triggered.connect(lambda *args, delim="tab": self.settings. __setattr__("delimiter", delim)) delimiter.addAction(tab) space = QAction("space", self.tool_window.ui_area, checkable=True) space.setChecked(self.settings.delimiter == "space") space.triggered.connect(lambda *args, delim="space": self.settings. __setattr__("delimiter", delim)) delimiter.addAction(space) semicolon = QAction("semicolon", self.tool_window.ui_area, checkable=True) semicolon.setChecked(self.settings.delimiter == "semicolon") semicolon.triggered.connect(lambda *args, delim="semicolon": self. settings.__setattr__("delimiter", delim)) delimiter.addAction(semicolon) add_header = QAction("&Include CSV header", self.tool_window.ui_area, checkable=True) add_header.setChecked(self.settings.include_header) add_header.triggered.connect(self.header_check) export.addAction(add_header) comma.triggered.connect( lambda *args, action=tab: action.setChecked(False)) comma.triggered.connect( lambda *args, action=space: action.setChecked(False)) comma.triggered.connect( lambda *args, action=semicolon: action.setChecked(False)) tab.triggered.connect( lambda *args, action=comma: action.setChecked(False)) tab.triggered.connect( lambda *args, action=space: action.setChecked(False)) tab.triggered.connect( lambda *args, action=semicolon: action.setChecked(False)) space.triggered.connect( lambda *args, action=comma: action.setChecked(False)) space.triggered.connect( lambda *args, action=tab: action.setChecked(False)) space.triggered.connect( lambda *args, action=semicolon: action.setChecked(False)) semicolon.triggered.connect( lambda *args, action=comma: action.setChecked(False)) semicolon.triggered.connect( lambda *args, action=tab: action.setChecked(False)) semicolon.triggered.connect( lambda *args, action=space: action.setChecked(False)) menu.setNativeMenuBar(False) self._menu = menu layout.setMenuBar(menu) self.tool_window.ui_area.setLayout(layout) self.tool_window.manage(None)
def _build_ui(self): #each group has an empty widget at the bottom so they resize the way I want while also having the #labels where I want them layout = QGridLayout() self.tab_widget = QTabWidget() layout.addWidget(self.tab_widget) #layout for absolute thermo stuff absolute_widget = QWidget() absolute_layout = QGridLayout(absolute_widget) #box for sp sp_area_widget = QGroupBox("Single-point") sp_layout = QGridLayout(sp_area_widget) self.sp_selector = FilereaderComboBox(self.session, otherItems=['energy']) self.sp_selector.currentIndexChanged.connect(self.set_sp) sp_layout.addWidget(self.sp_selector, 0, 0, 1, 3, Qt.AlignTop) nrg_label = QLabel("E =") sp_layout.addWidget(nrg_label, 1, 0, 1, 1, Qt.AlignRight | Qt.AlignVCenter) self.sp_nrg_line = QLineEdit() self.sp_nrg_line.setReadOnly(True) self.sp_nrg_line.setToolTip("electronic energy") sp_layout.addWidget(self.sp_nrg_line, 1, 1, 1, 1, Qt.AlignTop) sp_layout.addWidget(QLabel("E<sub>h</sub>"), 1, 2, 1, 1, Qt.AlignVCenter) sp_layout.addWidget(QWidget(), 2, 0) sp_layout.setColumnStretch(0, 0) sp_layout.setColumnStretch(1, 1) sp_layout.setRowStretch(0, 0) sp_layout.setRowStretch(1, 0) sp_layout.setRowStretch(2, 1) row = 0 #box for thermo therm_area_widget = QGroupBox("Thermal corrections") thermo_layout = QGridLayout(therm_area_widget) self.thermo_selector = FilereaderComboBox(self.session, otherItems=['frequency']) self.thermo_selector.currentIndexChanged.connect(self.set_thermo_mdl) thermo_layout.addWidget(self.thermo_selector, row, 0, 1, 3, Qt.AlignTop) row += 1 thermo_layout.addWidget(QLabel("T ="), row, 0, 1, 1, Qt.AlignRight | Qt.AlignVCenter) self.temperature_line = QDoubleSpinBox() self.temperature_line.setMaximum(2**31 - 1) self.temperature_line.setValue(298.15) self.temperature_line.setSingleStep(10) self.temperature_line.setSuffix(" K") self.temperature_line.setMinimum(0) self.temperature_line.valueChanged.connect(self.set_thermo) thermo_layout.addWidget(self.temperature_line, row, 1, 1, 2, Qt.AlignTop) row += 1 thermo_layout.addWidget(QLabel("𝜔<sub>0</sub> ="), row, 0, 1, 1, Qt.AlignRight | Qt.AlignVCenter) self.v0_edit = QDoubleSpinBox() self.v0_edit.setMaximum(4000) self.v0_edit.setValue(self.settings.w0) self.v0_edit.setSingleStep(25) self.v0_edit.setSuffix(" cm\u207b\u00b9") self.v0_edit.valueChanged.connect(self.set_thermo) self.v0_edit.setMinimum(0) self.v0_edit.setToolTip( "frequency parameter for quasi treatments of entropy") thermo_layout.addWidget(self.v0_edit, row, 1, 1, 2, Qt.AlignTop) row += 1 thermo_layout.addWidget(QLabel("𝛿ZPE ="), row, 0, 1, 1, Qt.AlignRight | Qt.AlignVCenter) self.zpe_line = QLineEdit() self.zpe_line.setReadOnly(True) self.zpe_line.setToolTip("zero-point energy correction") thermo_layout.addWidget(self.zpe_line, row, 1, 1, 1, Qt.AlignTop) thermo_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1, Qt.AlignVCenter) row += 1 thermo_layout.addWidget(QLabel("𝛿H<sub>RRHO</sub> ="), row, 0, 1, 1, Qt.AlignRight | Qt.AlignVCenter) self.enthalpy_line = QLineEdit() self.enthalpy_line.setReadOnly(True) self.enthalpy_line.setToolTip("RRHO enthalpy correction") thermo_layout.addWidget(self.enthalpy_line, row, 1, 1, 1, Qt.AlignTop) thermo_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1, Qt.AlignVCenter) row += 1 thermo_layout.addWidget(QLabel("𝛿G<sub>RRHO</sub> ="), row, 0, 1, 1, Qt.AlignRight | Qt.AlignVCenter) self.rrho_g_line = QLineEdit() self.rrho_g_line.setReadOnly(True) self.rrho_g_line.setToolTip( """RRHO free energy correction\nRotational motion is completely independent from vibrations\nNormal mode vibrations behave like harmonic oscillators""" ) thermo_layout.addWidget(self.rrho_g_line, row, 1, 1, 1, Qt.AlignTop) thermo_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1, Qt.AlignVCenter) row += 1 dqrrho_g_label = QLabel() dqrrho_g_label.setText( "<a href=\"Grimme's Quasi-RRHO\" style=\"text-decoration: none;\">𝛿G<sub>Quasi-RRHO</sub></a> =" ) dqrrho_g_label.setTextFormat(Qt.RichText) dqrrho_g_label.setTextInteractionFlags(Qt.TextBrowserInteraction) dqrrho_g_label.linkActivated.connect(self.open_link) dqrrho_g_label.setToolTip("click to open a relevant reference\n" + \ "see the \"Computation of internal (gas‐phase) entropies\" section for a description of the method") thermo_layout.addWidget(dqrrho_g_label, row, 0, 1, 1, Qt.AlignRight | Qt.AlignVCenter) self.qrrho_g_line = QLineEdit() self.qrrho_g_line.setReadOnly(True) self.qrrho_g_line.setToolTip("Quasi-RRHO free energy correction\n" + \ "Vibrational entropy of each mode is weighted and complemented with rotational entropy\n" + \ "The weighting is much lower for modes with frequencies less than 𝜔\u2080") thermo_layout.addWidget(self.qrrho_g_line, row, 1, 1, 1, Qt.AlignTop) thermo_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1, Qt.AlignVCenter) row += 1 dqharm_g_label = QLabel("") dqharm_g_label.setText( "<a href=\"Truhlar's Quasi-Harmonic\" style=\"text-decoration: none;\">𝛿G<sub>Quasi-Harmonic</sub></a> =" ) dqharm_g_label.setTextFormat(Qt.RichText) dqharm_g_label.setTextInteractionFlags(Qt.TextBrowserInteraction) dqharm_g_label.linkActivated.connect(self.open_link) dqharm_g_label.setToolTip("click to open a relevant reference\n" + \ "see the \"Computations\" section for a description of the method") thermo_layout.addWidget(dqharm_g_label, row, 0, 1, 1, Qt.AlignRight | Qt.AlignVCenter) self.qharm_g_line = QLineEdit() self.qharm_g_line.setReadOnly(True) self.qharm_g_line.setToolTip("Quasi-hamonic free energy correction\n" + \ "For entropy, real vibrational modes lower than 𝜔\u2080 are treated as 𝜔\u2080") thermo_layout.addWidget(self.qharm_g_line, row, 1, 1, 1, Qt.AlignTop) thermo_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1, Qt.AlignVCenter) thermo_layout.addWidget(QWidget(), row + 1, 0) thermo_layout.setColumnStretch(0, 0) thermo_layout.setColumnStretch(1, 1) for i in range(0, row): thermo_layout.setRowStretch(i, 0) thermo_layout.setRowStretch(row + 1, 1) row = 0 # for for total sum_area_widget = QGroupBox("Thermochemistry") sum_layout = QGridLayout(sum_area_widget) sum_layout.addWidget(QLabel("ZPE ="), row, 0, 1, 1, Qt.AlignRight | Qt.AlignVCenter) self.zpe_sum_line = QLineEdit() self.zpe_sum_line.setReadOnly(True) self.zpe_sum_line.setToolTip( "sum of electronic energy and ZPE correction") sum_layout.addWidget(self.zpe_sum_line, row, 1, 1, 1, Qt.AlignTop) sum_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1, Qt.AlignVCenter) row += 1 sum_layout.addWidget(QLabel("H<sub>RRHO</sub> ="), row, 0, 1, 1, Qt.AlignRight | Qt.AlignVCenter) self.h_sum_line = QLineEdit() self.h_sum_line.setReadOnly(True) self.h_sum_line.setToolTip( "sum of electronic energy and RRHO enthalpy correction") sum_layout.addWidget(self.h_sum_line, row, 1, 1, 1, Qt.AlignTop) sum_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1, Qt.AlignVCenter) row += 1 sum_layout.addWidget(QLabel("G<sub>RRHO</sub> ="), row, 0, 1, 1, Qt.AlignRight | Qt.AlignVCenter) self.rrho_g_sum_line = QLineEdit() self.rrho_g_sum_line.setReadOnly(True) self.rrho_g_sum_line.setToolTip( "sum of electronic energy and RRHO free energy correction\nRotational motion is completely independent from vibrations\nNormal mode vibrations behave like harmonic oscillators" ) sum_layout.addWidget(self.rrho_g_sum_line, row, 1, 1, 1, Qt.AlignTop) sum_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1, Qt.AlignVCenter) row += 1 sum_layout.addWidget(QLabel("G<sub>Quasi-RRHO</sub> ="), row, 0, 1, 1, Qt.AlignRight | Qt.AlignVCenter) self.qrrho_g_sum_line = QLineEdit() self.qrrho_g_sum_line.setReadOnly(True) self.qrrho_g_sum_line.setToolTip("Sum of electronic energy and quasi-RRHO free energy correction\n" + \ "Vibrational entropy of each mode is weighted and complemented with rotational entropy\n" + \ "The weighting is much lower for modes with frequencies less than 𝜔\u2080") sum_layout.addWidget(self.qrrho_g_sum_line, row, 1, 1, 1, Qt.AlignTop) sum_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1, Qt.AlignVCenter) row += 1 sum_layout.addWidget(QLabel("G<sub>Quasi-Harmonic</sub> ="), row, 0, 1, 1, Qt.AlignRight | Qt.AlignVCenter) self.qharm_g_sum_line = QLineEdit() self.qharm_g_sum_line.setReadOnly(True) self.qharm_g_sum_line.setToolTip("Sum of electronic energy and quasi-harmonic free energy correction\n" + \ "For entropy, real vibrational modes lower than 𝜔\u2080 are treated as 𝜔\u2080") sum_layout.addWidget(self.qharm_g_sum_line, row, 1, 1, 1, Qt.AlignTop) sum_layout.addWidget(QLabel("E<sub>h</sub>"), row, 2, 1, 1, Qt.AlignVCenter) sum_layout.addWidget(QWidget(), row + 1, 0) sum_layout.setColumnStretch(0, 0) for i in range(0, row): sum_layout.setRowStretch(i, 0) sum_layout.setRowStretch(row + 1, 1) splitter = QSplitter(Qt.Horizontal) splitter.setChildrenCollapsible(False) splitter.addWidget(sp_area_widget) splitter.addWidget(therm_area_widget) splitter.addWidget(sum_area_widget) absolute_layout.addWidget(splitter) self.status = QStatusBar() self.status.setSizeGripEnabled(False) self.status.setStyleSheet("color: red") absolute_layout.addWidget(self.status, 1, 0, 1, 1, Qt.AlignTop) self.tab_widget.addTab(absolute_widget, "absolute") relative_widget = QWidget() relative_layout = QGridLayout(relative_widget) size = [self.settings.ref_col_1, self.settings.ref_col_2] self.ref_group = ThermoGroup("reference group", self.session, self.nrg_fr, self.thermo_co, size) self.ref_group.changes.connect(self.calc_relative_thermo) relative_layout.addWidget(self.ref_group, 0, 0, 1, 3, Qt.AlignTop) size = [self.settings.other_col_1, self.settings.other_col_2] self.other_group = ThermoGroup("other group", self.session, self.nrg_fr, self.thermo_co, size) self.other_group.changes.connect(self.calc_relative_thermo) relative_layout.addWidget(self.other_group, 0, 3, 1, 3, Qt.AlignTop) self.relative_temperature = QDoubleSpinBox() self.relative_temperature.setMaximum(2**31 - 1) self.relative_temperature.setValue(self.settings.rel_temp) self.relative_temperature.setSingleStep(10) self.relative_temperature.setSuffix(" K") self.relative_temperature.setMinimum(0) self.relative_temperature.valueChanged.connect( self.calc_relative_thermo) relative_layout.addWidget(QLabel("T ="), 1, 0, 1, 1, Qt.AlignRight | Qt.AlignVCenter) relative_layout.addWidget(self.relative_temperature, 1, 1, 1, 5, Qt.AlignLeft | Qt.AlignVCenter) self.relative_v0 = QDoubleSpinBox() self.relative_v0.setMaximum(2**31 - 1) self.relative_v0.setValue(self.settings.w0) self.relative_v0.setSingleStep(25) self.relative_v0.setSuffix(" cm\u207b\u00b9") self.relative_v0.setMinimum(0) self.relative_v0.setToolTip( "frequency parameter for quasi treatments of entropy") self.relative_v0.valueChanged.connect(self.calc_relative_thermo) relative_layout.addWidget(QLabel("𝜔<sub>0</sub> ="), 2, 0, 1, 1, Qt.AlignRight | Qt.AlignVCenter) relative_layout.addWidget(self.relative_v0, 2, 1, 1, 5, Qt.AlignLeft | Qt.AlignVCenter) relative_layout.addWidget( QLabel("Boltzmann-weighted relative energies in kcal/mol:"), 3, 0, 1, 6, Qt.AlignVCenter | Qt.AlignLeft) relative_layout.addWidget(QLabel("ΔE"), 4, 0, Qt.AlignTop | Qt.AlignVCenter) self.relative_dE = QLineEdit() self.relative_dE.setReadOnly(True) relative_layout.addWidget(self.relative_dE, 5, 0, Qt.AlignTop | Qt.AlignVCenter) relative_layout.addWidget(QLabel("ΔZPE"), 4, 1, Qt.AlignTop | Qt.AlignVCenter) self.relative_dZPVE = QLineEdit() self.relative_dZPVE.setReadOnly(True) relative_layout.addWidget(self.relative_dZPVE, 5, 1, Qt.AlignTop | Qt.AlignVCenter) relative_layout.addWidget(QLabel("ΔH<sub>RRHO</sub>"), 4, 2, Qt.AlignTop | Qt.AlignVCenter) self.relative_dH = QLineEdit() self.relative_dH.setReadOnly(True) relative_layout.addWidget(self.relative_dH, 5, 2, Qt.AlignTop | Qt.AlignVCenter) relative_layout.addWidget(QLabel("ΔG<sub>RRHO</sub>"), 4, 3, Qt.AlignTop | Qt.AlignVCenter) self.relative_dG = QLineEdit() self.relative_dG.setReadOnly(True) relative_layout.addWidget(self.relative_dG, 5, 3, Qt.AlignTop | Qt.AlignVCenter) relative_layout.addWidget(QLabel("ΔG<sub>Quasi-RRHO</sub>"), 4, 4, Qt.AlignTop | Qt.AlignVCenter) self.relative_dQRRHOG = QLineEdit() self.relative_dQRRHOG.setReadOnly(True) relative_layout.addWidget(self.relative_dQRRHOG, 5, 4, Qt.AlignTop | Qt.AlignVCenter) relative_layout.addWidget(QLabel("ΔG<sub>Quasi-Harmonic</sub>"), 4, 5, Qt.AlignTop | Qt.AlignVCenter) self.relative_dQHARMG = QLineEdit() self.relative_dQHARMG.setReadOnly(True) relative_layout.addWidget(self.relative_dQHARMG, 5, 5, Qt.AlignTop | Qt.AlignVCenter) relative_layout.setRowStretch(0, 1) relative_layout.setRowStretch(1, 0) relative_layout.setRowStretch(2, 0) relative_layout.setRowStretch(3, 0) relative_layout.setRowStretch(4, 0) relative_layout.setRowStretch(5, 0) self.tab_widget.addTab(relative_widget, "relative") #menu stuff menu = QMenuBar() export = menu.addMenu("&Export") copy = QAction("&Copy CSV to clipboard", self.tool_window.ui_area) copy.triggered.connect(self.copy_csv) shortcut = QKeySequence(Qt.CTRL + Qt.Key_C) copy.setShortcut(shortcut) export.addAction(copy) self.copy = copy save = QAction("&Save CSV...", self.tool_window.ui_area) save.triggered.connect(self.save_csv) #this shortcut interferes with main window's save shortcut #I've tried different shortcut contexts to no avail #thanks Qt... #shortcut = QKeySequence(Qt.CTRL + Qt.Key_S) #save.setShortcut(shortcut) #save.setShortcutContext(Qt.WidgetShortcut) export.addAction(save) delimiter = export.addMenu("Delimiter") comma = QAction("comma", self.tool_window.ui_area, checkable=True) comma.setChecked(self.settings.delimiter == "comma") comma.triggered.connect(lambda *args, delim="comma": self.settings. __setattr__("delimiter", delim)) delimiter.addAction(comma) tab = QAction("tab", self.tool_window.ui_area, checkable=True) tab.setChecked(self.settings.delimiter == "tab") tab.triggered.connect(lambda *args, delim="tab": self.settings. __setattr__("delimiter", delim)) delimiter.addAction(tab) space = QAction("space", self.tool_window.ui_area, checkable=True) space.setChecked(self.settings.delimiter == "space") space.triggered.connect(lambda *args, delim="space": self.settings. __setattr__("delimiter", delim)) delimiter.addAction(space) semicolon = QAction("semicolon", self.tool_window.ui_area, checkable=True) semicolon.setChecked(self.settings.delimiter == "semicolon") semicolon.triggered.connect(lambda *args, delim="semicolon": self. settings.__setattr__("delimiter", delim)) delimiter.addAction(semicolon) add_header = QAction("&Include CSV header", self.tool_window.ui_area, checkable=True) add_header.setChecked(self.settings.include_header) add_header.triggered.connect(self.header_check) export.addAction(add_header) comma.triggered.connect( lambda *args, action=tab: action.setChecked(False)) comma.triggered.connect( lambda *args, action=space: action.setChecked(False)) comma.triggered.connect( lambda *args, action=semicolon: action.setChecked(False)) tab.triggered.connect( lambda *args, action=comma: action.setChecked(False)) tab.triggered.connect( lambda *args, action=space: action.setChecked(False)) tab.triggered.connect( lambda *args, action=semicolon: action.setChecked(False)) space.triggered.connect( lambda *args, action=comma: action.setChecked(False)) space.triggered.connect( lambda *args, action=tab: action.setChecked(False)) space.triggered.connect( lambda *args, action=semicolon: action.setChecked(False)) semicolon.triggered.connect( lambda *args, action=comma: action.setChecked(False)) semicolon.triggered.connect( lambda *args, action=tab: action.setChecked(False)) semicolon.triggered.connect( lambda *args, action=space: action.setChecked(False)) menu.setNativeMenuBar(False) self._menu = menu layout.setMenuBar(menu) self.tool_window.ui_area.setLayout(layout) self.tool_window.manage(None)
def _build_ui(self): layout = QFormLayout() self.radii_option = QComboBox() self.radii_option.addItems(["Bondi", "UMN"]) ndx = self.radii_option.findText(self.settings.radii, Qt.MatchExactly) self.radii_option.setCurrentIndex(ndx) layout.addRow("radii:", self.radii_option) self.display_vectors = QCheckBox() self.display_vectors.setChecked(self.settings.display_vectors) layout.addRow("show vectors:", self.display_vectors) self.display_radii = QCheckBox() self.display_radii.setChecked(self.settings.display_radii) layout.addRow("show radii:", self.display_radii) calc_sterimol_button = QPushButton( "calculate parameters for selected substituents") calc_sterimol_button.clicked.connect(self.calc_sterimol) layout.addRow(calc_sterimol_button) self.calc_sterimol_button = calc_sterimol_button remove_sterimol_button = QPushButton("remove Sterimol visualizations") remove_sterimol_button.clicked.connect(self.del_sterimol) layout.addRow(remove_sterimol_button) self.remove_sterimol_button = remove_sterimol_button self.table = QTableWidget() self.table.setColumnCount(8) self.table.setHorizontalHeaderLabels([ 'substituent atom', 'bonded atom', 'B\u2081', 'B\u2082', 'B\u2083', 'B\u2084', 'B\u2085', 'L', ]) self.table.setSelectionBehavior(QTableWidget.SelectRows) self.table.setEditTriggers(QTableWidget.NoEditTriggers) self.table.resizeColumnToContents(0) self.table.resizeColumnToContents(1) self.table.resizeColumnToContents(2) self.table.resizeColumnToContents(3) self.table.resizeColumnToContents(4) self.table.resizeColumnToContents(5) self.table.resizeColumnToContents(6) self.table.resizeColumnToContents(7) self.table.horizontalHeader().setSectionResizeMode( 2, QHeaderView.Stretch) self.table.horizontalHeader().setSectionResizeMode( 3, QHeaderView.Stretch) self.table.horizontalHeader().setSectionResizeMode( 4, QHeaderView.Stretch) self.table.horizontalHeader().setSectionResizeMode( 5, QHeaderView.Stretch) self.table.horizontalHeader().setSectionResizeMode( 6, QHeaderView.Stretch) self.table.horizontalHeader().setSectionResizeMode( 7, QHeaderView.Stretch) layout.addRow(self.table) menu = QMenuBar() export = menu.addMenu("&Export") copy = QAction("&Copy CSV to clipboard", self.tool_window.ui_area) copy.triggered.connect(self.copy_csv) shortcut = QKeySequence(Qt.CTRL + Qt.Key_C) copy.setShortcut(shortcut) export.addAction(copy) save = QAction("&Save CSV...", self.tool_window.ui_area) save.triggered.connect(self.save_csv) #this shortcut interferes with main window's save shortcut #I've tried different shortcut contexts to no avail #thanks Qt... #shortcut = QKeySequence(Qt.CTRL + Qt.Key_S) #save.setShortcut(shortcut) #save.setShortcutContext(Qt.WidgetShortcut) export.addAction(save) delimiter = export.addMenu("Delimiter") comma = QAction("comma", self.tool_window.ui_area, checkable=True) comma.setChecked(self.settings.delimiter == "comma") comma.triggered.connect(lambda *args, delim="comma": self.settings. __setattr__("delimiter", delim)) delimiter.addAction(comma) tab = QAction("tab", self.tool_window.ui_area, checkable=True) tab.setChecked(self.settings.delimiter == "tab") tab.triggered.connect(lambda *args, delim="tab": self.settings. __setattr__("delimiter", delim)) delimiter.addAction(tab) space = QAction("space", self.tool_window.ui_area, checkable=True) space.setChecked(self.settings.delimiter == "space") space.triggered.connect(lambda *args, delim="space": self.settings. __setattr__("delimiter", delim)) delimiter.addAction(space) semicolon = QAction("semicolon", self.tool_window.ui_area, checkable=True) semicolon.setChecked(self.settings.delimiter == "semicolon") semicolon.triggered.connect(lambda *args, delim="semicolon": self. settings.__setattr__("delimiter", delim)) delimiter.addAction(semicolon) add_header = QAction("&Include CSV header", self.tool_window.ui_area, checkable=True) add_header.setChecked(self.settings.include_header) add_header.triggered.connect(self.header_check) export.addAction(add_header) comma.triggered.connect( lambda *args, action=tab: action.setChecked(False)) comma.triggered.connect( lambda *args, action=space: action.setChecked(False)) comma.triggered.connect( lambda *args, action=semicolon: action.setChecked(False)) tab.triggered.connect( lambda *args, action=comma: action.setChecked(False)) tab.triggered.connect( lambda *args, action=space: action.setChecked(False)) tab.triggered.connect( lambda *args, action=semicolon: action.setChecked(False)) space.triggered.connect( lambda *args, action=comma: action.setChecked(False)) space.triggered.connect( lambda *args, action=tab: action.setChecked(False)) space.triggered.connect( lambda *args, action=semicolon: action.setChecked(False)) semicolon.triggered.connect( lambda *args, action=comma: action.setChecked(False)) semicolon.triggered.connect( lambda *args, action=tab: action.setChecked(False)) semicolon.triggered.connect( lambda *args, action=space: action.setChecked(False)) menu.setNativeMenuBar(False) self._menu = menu layout.setMenuBar(menu) self.tool_window.ui_area.setLayout(layout) self.tool_window.manage(None)
def _build_ui(self): layout = QGridLayout() self.figure = Figure(figsize=(2, 2)) self.canvas = Canvas(self.figure) ax = self.figure.add_axes((0.15, 0.20, 0.80, 0.70)) fr = self.filereader if fr.all_geom is None: self.opened = False return data = [] for step in fr.all_geom: info = [ item for item in step if isinstance(item, dict) and "energy" in item ] if len(info) < 1: #we will be unable to load an enegy plot because some structure does not have an associated energy self.opened = False self.session.logger.error( "not enough iterations to plot - %i found" % len(info)) return else: info = info[0] data.append(info["energy"]) self.ys = data se = np.ptp(data) self.nrg_plot = ax.plot(self.structure.coordset_ids, data, marker='o', c='gray', markersize=3) self.nrg_plot = self.nrg_plot[0] ax.set_xlabel('iteration') ax.set_ylabel(r'energy ($E_h$)') ax.set_ylim(bottom=(min(data) - se / 10), top=(max(data) + se / 10)) minlocs = [ self.structure.coordset_ids[i] for i in range(0, self.structure.num_coordsets) if data[i] == min(data) ] mins = [min(data) for m in minlocs] maxlocs = [ self.structure.coordset_ids[i] for i in range(0, self.structure.num_coordsets) if data[i] == max(data) ] maxs = [max(data) for m in minlocs] ax.plot(minlocs, mins, marker='*', c='blue', markersize=5) ax.plot(maxlocs, maxs, marker='*', c='red', markersize=5) ax.ticklabel_format(axis='y', style='sci', scilimits=(0, 0), useOffset=True) ax.ticklabel_format(axis='x', style='plain', useOffset=False) self.canvas.mpl_connect('button_release_event', self.unclick) self.canvas.mpl_connect('button_press_event', self.onclick) self.canvas.mpl_connect('motion_notify_event', self.drag) self.canvas.mpl_connect('scroll_event', self.zoom) self.annotation = ax.annotate("", xy=(0, 0), xytext=(0, 10), textcoords="offset points", fontfamily='Arial') self.annotation.set_visible(False) ax.autoscale() self.canvas.draw() self.canvas.setMinimumWidth(400) self.canvas.setMinimumHeight(200) layout.addWidget(self.canvas) toolbar_widget = QWidget() toolbar = NavigationToolbar(self.canvas, toolbar_widget) toolbar.setMaximumHeight(32) self.toolbar = toolbar layout.addWidget(toolbar) #menu bar for saving stuff menu = QMenuBar() file = menu.addMenu("&Export") file.addAction("&Save CSV...") file.triggered.connect(self.save) menu.setNativeMenuBar(False) self._menu = menu layout.setMenuBar(menu) self.tool_window.ui_area.setLayout(layout) self.tool_window.manage(None) self.opened = True
class MainWindow(QMainWindow): def __init__(self): super().__init__() # Proyecto self.project = None # Título self.setWindowTitle("3D Cell Reconstruction") # Inicializa el menú self.initMenubar() # Visor de las imágenes (imagen y control van en el mismo layout) # NOTA: Es el objeto central del objeto QMainWindow, que tiene eso, una barra de estado, etc. Podemos volver al QWidget si es fuese mejor. self.imageViewer = QWidget(self) self.imageViewer.setLayout(QGridLayout()) # Fija márgenes para centrar la imagen self.imageViewer.layout().setColumnStretch(0, 0) self.imageViewer.layout().setColumnStretch(2, 0) self.imageViewer.layout().setRowStretch(1, 0) self.imageViewer.layout().setRowStretch(3, 0) # Crea un campo de texto para mostrar el nombre de la imagen self.imageName = QLineEdit("No project loaded") self.imageName.setReadOnly(True) self.imageViewer.layout().addWidget(self.imageName, 0, 1) # Crea un objeto de la clase ImageView para mostrar la imagen y dibujar self.imageView = ImageView() self.imageViewer.layout().addWidget(self.imageView, 2, 1) # Inicializa los botones de control self.initControlLayout() self.imageViewer.layout().addLayout(self.control_layout, 3, 0, 1, 3) # Lo situa como objeto pricipal de la aplicación. self.setCentralWidget(self.imageViewer) # NOTA: Como inicialmente no hay proyecto abierto, deshabilita los botones. self.enableControls(False) def initMenubar(self): ''' Crea el menú de la aplicación y lo almacena en self.menuBar ''' self.menuBar = QMenuBar() self.setMenuBar(self.menuBar) self.menuBar.setNativeMenuBar( False) # Necesario para que funcione en MacOS # Menu File fileMenu = self.menuBar.addMenu("File") openAction = QAction('Open image sequence', self) fileMenu.addAction(openAction) openAction.triggered.connect(self.open) exitAction = QAction('Exit', self) fileMenu.addAction(exitAction) exitAction.triggered.connect(self.close) # Menu Display displayMenu = self.menuBar.addMenu("Display") gen3DAction = QAction('Generate 3D structure', self) displayMenu.addAction(gen3DAction) gen3DAction.triggered.connect(self.gen3D) # Help Display helpMenu = self.menuBar.addMenu("Help") aboutAction = QAction("About", self) helpMenu.addAction(aboutAction) # aboutAction.triggered.connect(self.about) # Una ventana que muestre tu nombre, y eso. def initControlLayout(self): ''' Añade los botones para navegar sobre las imágenes en un imgViewerLayout denominado self.control_layout. ''' # Alante y atrás self.btn_next = QPushButton() self.btn_next.setIcon(QIcon('resources/next.png')) self.btn_next.setFixedWidth(50) self.btn_prev = QPushButton() self.btn_prev.setIcon(QIcon('resources/back.png')) self.btn_prev.setFixedWidth(50) # Borrar y deshacer self.btn_clear = QPushButton("Clear") self.btn_clear.setFixedWidth(80) self.btn_undo = QPushButton("Undo") self.btn_undo.setFixedWidth(80) # Mostrar o no información de las imágenes anteriores. self.check_showC = QCheckBox("Previous Image Curves") self.check_showP = QCheckBox("Previous Image Particles") self.check_showC.setChecked(False) self.check_showP.setChecked(False) # Panel para colocar los controles. self.control_layout = QHBoxLayout() # Coloca los controles en el imgViewerLayout self.control_layout.addWidget(self.btn_prev) self.control_layout.addWidget(self.btn_next) self.control_layout.addStretch() self.control_layout.addWidget(self.check_showC) self.control_layout.addWidget(self.check_showP) self.control_layout.addWidget(self.btn_undo) self.control_layout.addWidget(self.btn_clear) # Conecta los componentes con las acciones correspondientes. self.btn_next.clicked.connect(self.next) self.btn_prev.clicked.connect(self.prev) self.btn_clear.clicked.connect(self.clear) self.btn_undo.clicked.connect(self.undo) #self.check_showC.clicked.connect(self.showC) #self.check_showP.clicked.connect(self.showP) def enableControls(self, state): ''' Habilita o deshabilita los controles y la vista de la imagen. ''' self.imageName.setEnabled(state) self.imageView.setEnabled(state) self.btn_next.setEnabled(state) self.btn_prev.setEnabled(state) self.btn_clear.setEnabled(state) self.btn_undo.setEnabled(state) self.check_showC.setEnabled(state) self.check_showP.setEnabled(state) def updateWindowSize(self): ''' Aujsta el tamaño de la ventana y la centra ''' # Calcula el tamaño ideal para la vista y la ventana. Para ello determina, el ratio # en función la máxima altura o anchura que puede tener la imagen. if not self.project is None: ratioWidth = (screenSize.getCoords()[2] - 100) / (self.project.imgShape[1]) ratioHeight = (screenSize.getCoords()[3] - 150) / (self.project.imgShape[0]) ratio = ratioWidth if ratioWidth < ratioHeight else ratioHeight self.imageView.setFixedWidth(int(self.project.imgShape[1] * ratio)) self.imageView.setFixedHeight(int(self.project.imgShape[0] * ratio)) # Ajusta el tamaño de la ventana. self.adjustSize() # Centra la ventana windowPosition = self.geometry() windowPosition.moveCenter(screenSize.center()) self.move(windowPosition.topLeft()) def updateImageView(self): ''' Actualiza la imagen ''' # Actualiza el texto y la imagen (recortada). self.imageName.setText( self.project.imgSequence[self.project.currentImgId]) utils.cropImageBorders( self.project.folder + '/' + self.project.imgSequence[self.project.currentImgId]) self.imageView.loadImage( self.project.folder + '/' + self.project.imgSequence[self.project.currentImgId]) def open(self): ''' Abre un proyecto. ''' # Selecciona un directorio de trabajo para cargarlo en un proyecto. selectedDirectory = str( QFileDialog.getExistingDirectory(self, "Select directory")) # Vuelve si se ha cancelado la apertura. if len(selectedDirectory) == 0: # NOTA: Fíjate que lo que hacemos es dejarlo como estaba. Si había cargado un proyecto, se queda # abierto y los botones y eso habilitados. Si no había nada abierto, sigue sin abrirse. return # NOTA: Solamente llega aquí si se ha seleccionado un directorio. # Se crea el proyecto self.project = Project(selectedDirectory) # Si en la carpeta seleccionada no hay ninguna imagen, deshabilitamos if len(self.project.imgSequence) == 0: #self.imageView.scene.clear() self.enableControls(False) return # NOTA: Solamente llega aquí si el proyecto tiene imágenes # Actualiza el tamaño de la ventana. self.updateWindowSize() # Muestra la información actual del proyecto. self.updateImageView() # Habilita los controles. self.enableControls(True) def next(self): ''' Pasa a la siguiente imagen. ''' self.project.next() self.updateImageView() def prev(self): ''' Pasa a la imagen anterior. ''' self.project.prev() self.updateImageView() def undo(self): self.imageView.removeLastCurve() def clear(self): self.imageView.clear() def gen3D(self): ''' Genera la reconstrucción 3D ''' pass
class Example(QWidget): def __init__(self): super().__init__() self.filenames = json_files() if type(self.filenames) is list: self.curr_file = self.filenames[0] else: self.curr_file = self.filenames self.initUI() def initUI(self): self.num = -1 # index for search bar query self.show_save = False # bool for showing unsaved changes dialog self.temp_file = ".temp.csv" self.refresh_file = False # failsafe 1 for itemChanged trigger self.list_1 = QListWidget() lister(file=self.curr_file, target=self.list_1, index=0, mode=0) self.list_1.clicked.connect(self.clear_selection) self.list_1.installEventFilter(self) self.list_items = self.list_1.count( ) # failsafe 2 for itemChanged trigger self.list_1.itemChanged.connect(self.edit_next_item) self.list_1.verticalScrollBar().valueChanged.connect(self.sync_scroll) self.list_2 = QListWidget() lister(file=self.curr_file, target=self.list_2, index=1, mode=0) self.list_2.clicked.connect(self.clear_selection) self.list_3 = QListWidget() lister(file=self.curr_file, target=self.list_3, index=2, mode=0) self.list_3.clicked.connect(self.clear_selection) self.all_lists = [self.list_1, self.list_2, self.list_3] self.menubar = QMenuBar() self.menubar.setNativeMenuBar(False) exit_event = QAction('Exit', self) exit_event.setShortcut('Ctrl+W') exit_event.triggered.connect(app.quit) showAct = QAction('Show extras', self, checkable=True) showAct.setChecked(False) showAct.setShortcut('Ctrl+E') showAct.triggered.connect(self.hide_notes) addAct = QAction('Fields', self) addAct.setShortcut('Ctrl+N') addAct.triggered.connect(self.add_item) fileOpen = QAction('Open file', self) fileOpen.triggered.connect(self.fileDialog) fileOpen.setShortcut('Ctrl+O') fileSave = QAction('Save file', self) fileSave.triggered.connect(self.save) fileSave.triggered.connect(self.refresh_recents) fileSave.setShortcut('Ctrl+S') self.fileRecents = QMenu('Recent file', self) self.refresh_recents() self.toggle_theme = QAction('Toggle theme', self, checkable=True) self.toggle_theme.setChecked(json_theme()) self.toggle_theme.triggered.connect(self.theme) self.toggle_theme.setShortcut('Ctrl+T') self.col_sort_index = QMenu('Sorting column index', self) self.col_sort_index.addAction(QAction(str(0), self)) self.col_sort_index.addAction(QAction(str(1), self)) self.col_sort_index.addAction(QAction(str(2), self)) self.col_sort_index.triggered.connect(self.sort_col_choice) self.col_search_index = QMenu('Searching column index', self) self.col_search_index.addAction(QAction(str(0), self)) self.col_search_index.addAction(QAction(str(1), self)) self.col_search_index.addAction(QAction(str(2), self)) self.col_search_index.triggered.connect(self.search_col_choice) self.sort = QAction('Sort entries', self, checkable=True) self.curr_col = 0 self.search_col = 0 self.sort.triggered.connect(self.refresh_list) self.sort.setShortcut('Ctrl+R') self.addFields = self.menubar.addMenu('Add') self.addFields.addAction(addAct) self.optionMenu = self.menubar.addMenu('Options') self.optionMenu.addAction(exit_event) self.optionMenu.addAction(showAct) self.optionMenu.addAction(self.toggle_theme) self.optionMenu.addMenu(self.col_sort_index) self.optionMenu.addMenu(self.col_search_index) self.optionMenu.addAction(self.sort) self.fileMenu = self.menubar.addMenu('File') self.fileMenu.addAction(fileOpen) self.fileMenu.addAction(fileSave) self.fileMenu.addMenu(self.fileRecents) self.search_bar = QLineEdit() self.search_bar.setPlaceholderText('Search vocab') self.search_bar.setClearButtonEnabled(True) self.search_bar.setMaxLength(10) self.search_bar.returnPressed.connect(self.search_item) self.status_bar = QStatusBar() status(self.status_bar, self.list_1) grid = QGridLayout() grid.setSpacing(10) grid.addWidget(self.menubar, 0, 0) grid.addWidget(self.list_1, 1, 0) grid.addWidget(self.list_2, 1, 1) grid.addWidget(self.list_3, 1, 2) grid.addWidget(self.search_bar, 0, 1) grid.addWidget(self.status_bar) self.theme() self.setLayout(grid) self.setGeometry(*json_window_size()) self.setWindowTitle(f'{split_name(self.curr_file)}') self.show() self.list_1.scrollToBottom() self.list_2.verticalScrollBar().setHidden(True) self.list_3.verticalScrollBar().setHidden(True) self.list_3.setHidden(True) def sync_scroll(self): scroll_location = self.list_1.verticalScrollBar().value() self.list_2.verticalScrollBar().setValue(scroll_location) self.list_3.verticalScrollBar().setValue(scroll_location) def edit_next_item(self, event): """When an item is added and edited on the first col, starts editing its counterpart on the next col""" if self.list_items == self.list_1.count( ) - 2 or self.list_items != self.list_1.count( ) and self.refresh_file == False: item = self.list_2.item(self.list_2.count() - 1) self.list_2.editItem(item) self.list_items = self.list_1.count() def closeEvent(self, event): """Triggered upon program exit, shows a dialog for unsaved changes using a bool""" if self.show_save == True: reply = QMessageBox.question( self, 'Message', "You may have unsaved changes, are you sure you want to quit?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if reply == QMessageBox.Yes: try: remove(self.temp_file) except: pass event.accept() else: event.ignore() else: pass def sort_col_choice(self, action): self.curr_col = int(action.text()) def search_col_choice(self, action): self.search_col = int(action.text()) def refresh_list(self): """Refreshes the contents of the lists, when sorting is used""" self.save( mode=1 ) # saves a temp copy, with changes, but irreversable sorting introduced clear_lists(self.all_lists) if self.sort.isChecked() == True: mode = 2 else: mode = 0 try: lister(file=self.temp_file, target=self.list_1, index=0, mode=mode, column=self.curr_col) lister(file=self.temp_file, target=self.list_2, index=1, mode=mode, column=self.curr_col) lister(file=self.temp_file, target=self.list_3, index=2, mode=mode, column=self.curr_col) except: lister(file=self.curr_file, target=self.list_1, index=0, mode=mode, column=self.curr_col) lister(file=self.curr_file, target=self.list_2, index=1, mode=mode, column=self.curr_col) lister(file=self.curr_file, target=self.list_3, index=2, mode=mode, column=self.curr_col) def refresh_recents(self): try: file_1 = QAction(self.curr_file, self) self.fileRecents.addAction(file_1) file_1.triggered.connect(self.clickedFileAct) if type(self.filenames) is list: if self.filenames[1] != None: file_2 = QAction(self.filenames[1], self) self.fileRecents.addAction(file_2) file_2.triggered.connect(self.clickedFileAct) if self.filenames[2] != None: file_3 = QAction(self.filenames[2], self) self.fileRecents.addAction(file_3) file_3.triggered.connect(self.clickedFileAct) except: pass def clickedFileAct(self): self.refresh_file = True file = self.sender().text() self.curr_file = file self.setWindowTitle(f'{split_name(self.curr_file)}') clear_lists(self.all_lists) lister(file=self.curr_file, target=self.list_1, index=0) lister(file=self.curr_file, target=self.list_2, index=1) lister(file=self.curr_file, target=self.list_3, index=2) status(self.status_bar, self.list_1) self.theme() self.list_1.scrollToBottom() self.list_3.setHidden(True) self.refresh_file = False def eventFilter(self, source, event): """Item (row) deletion""" if (event.type() == QEvent.ContextMenu and source is self.list_1): menu = QMenu() menu.addAction("Delete row") if menu.exec_(event.globalPos()): item = source.itemAt(event.pos()) try: model = self.list_1.indexFromItem(item) row = model.row() self.show_save = True self.list_1.takeItem(row) self.list_2.takeItem(row) self.list_3.takeItem(row) status(self.status_bar, self.list_1, f'Deleted row number: {row+1}.') self.clearSelection() except: pass return True return super(Example, self).eventFilter(source, event) def hide_notes(self): """Toggles showing the note column and stretches the window for clearer reading of it""" self.list_3.setHidden(not self.list_3.isHidden()) def theme(self): """Sets the theme for the window and its widgets""" palette = QPalette() # dark theme if self.toggle_theme.isChecked() == True: palette.setColor(QPalette.Window, QColor(0, 0, 0)) dark = "background-color: rgb(0, 0, 0); color: rgb(255, 255, 255);" self.menubar.setStyleSheet(dark) self.addFields.setStyleSheet(dark) self.optionMenu.setStyleSheet(dark) self.fileMenu.setStyleSheet(dark) self.search_bar.setStyleSheet( "background-color: rgb(0, 0, 0); color: rgb(255, 255, 255)" ) # border: 0px; for transparency self.status_bar.setStyleSheet(dark) style_items(self.all_lists, dark_theme=True) # light theme elif self.toggle_theme.isChecked() == False: palette.setColor(QPalette.Window, QColor(255, 255, 255)) light = "background-color: rgb(255, 255, 255); color: rgb(0, 0, 0)" self.menubar.setStyleSheet(light) self.addFields.setStyleSheet(light) self.optionMenu.setStyleSheet(light) self.fileMenu.setStyleSheet(light) self.search_bar.setStyleSheet(light) self.status_bar.setStyleSheet(light) style_items(self.all_lists, dark_theme=False) self.setPalette(palette) self.theme_bool = self.toggle_theme.isChecked( ) # used in the save func def search_item(self): """Takes input from the search bar and matches with an item, gets index and scrolls to it, more reusults being qued with the num class var """ query = self.search_bar.text() search = self.all_lists[self.search_col].findItems( query, Qt.MatchContains) status(self.status_bar, self.list_1, f'Found {len(search)} results.') self.clear_selection() # testing search in all column # search_list =[] # for x in range(3): # search_list.append(self.all_lists[x].findItems(query, Qt.MatchContains)) # parent_list = [] # for x in range(3): # for y in range(len(search_list[x])): # parent_list.append(self.all_lists[x]) # replace with x # import itertools # merged = list(itertools.chain.from_iterable(search_list)) # search_dict = dict(zip(parent_list, merged)) # print(search_dict) # print() # print(len(merged)) # print(len(parent_list)) self.num += 1 for i in search: try: model_index = self.all_lists[self.search_col].indexFromItem( search[self.num]) except: self.num = 0 model_index = self.all_lists[self.search_col].indexFromItem( search[self.num]) item_index = model_index.row() self.all_lists[self.search_col].item(item_index).setSelected(True) self.list_1.scrollToItem(self.list_1.item(item_index), QAbstractItemView.PositionAtCenter) def add_item(self): self.show_save = True for x in range(3): if x == 0: lister(file=self.curr_file, target=self.list_1, index=x, mode=1) elif x == 1: lister(file=self.curr_file, target=self.list_2, index=x, mode=1) elif x == 2: lister(file=self.curr_file, target=self.list_3, index=x, mode=1) item = self.list_1.item(self.list_1.count() - 1) self.list_1.editItem(item) status(self.status_bar, self.list_1) self.list_1.scrollToBottom() self.list_2.scrollToBottom() self.list_3.scrollToBottom() def clear_selection(self): """Clears all item slections for aesthetical purposes, but only single clicks""" self.list_1.clearSelection() self.list_2.clearSelection() self.list_3.clearSelection() def fileDialog(self): fname = QFileDialog() path = fname.getOpenFileName(self, 'Open file', getcwd(), filter='csv (*.csv);;') if path[0] == '': # failsafe for canceling the dialog return self.curr_file self.curr_file = path[0] self.setWindowTitle(f'{split_name(self.curr_file)}') clear_lists(self.all_lists) lister(file=self.curr_file, target=self.list_1, index=0) lister(file=self.curr_file, target=self.list_2, index=1) lister(file=self.curr_file, target=self.list_3, index=2) status(self.status_bar, self.list_1) self.theme() def save(self, mode=0): self.show_save = False list1_items = items_text(self.list_1) list2_items = items_text(self.list_2) list3_items = items_text(self.list_3) total_dicts = [] for (a, b, c) in zip(list1_items, list2_items, list3_items): # each letter is a column dictionary = {'word_1': a, 'word_2': b, 'notes': c} total_dicts.append(dictionary) if mode == 0: writer(file=self.curr_file, data=total_dicts) status(self.status_bar, self.list_1, ('Saved current changes.')) try: json_template(theme=self.theme_bool, files=[self.curr_file, None, None], window_size=self.geometry().getRect() ) # current size values of the window except: json_template( ) # bug cannot be avoided, even though used setChecked at the beggining elif mode == 1: self.show_save = True writer(file=self.temp_file, data=total_dicts) # avoids stacking and refreshes recent file actions actions = self.fileRecents.actions() for action in actions: self.fileRecents.removeAction(action)
class VGenesTextMain(QMainWindow): def __init__(self): super(VGenesTextMain, self).__init__() self.setupUi() def setupUi(self): self.curFile = '' self.textEdit = QTextEdit() self.textEdit.setTextInteractionFlags(Qt.TextEditorInteraction) self.setCentralWidget(self.textEdit) #self.textEdit_legend = QTextEdit() #grid = QGridLayout() #grid.setSpacing(10) #grid.addWidget(self.textEdit, 1, 0) #grid.addWidget(self.textEdit_legend, 1, 1) #self.setLayout(grid) #vbox = QVBoxLayout() #vbox.addStretch(1) #vbox.addLayout(self.textEdit) #vbox.addLayout(self.textEdit_legend) #self.setLayout(vbox) self.createActions() self.createMenus() self.createToolBars() self.createStatusBar() self.readSettings() self.textEdit.document().contentsChanged.connect( self.documentWasModified) self.setCurrentFile('') def closeEvent(self, event): if self.maybeSave(): self.writeSettings() event.accept() else: event.ignore() def newFile(self): if self.maybeSave(): self.textEdit.clear() self.setCurrentFile('') def open(self): if self.maybeSave(): fileName, _ = QFileDialog.getOpenFileName(self) if fileName: self.loadFile(fileName) def print_(self): document = self.textEdit.document() printer = QPrinter() dlg = QPrintDialog(printer, self) if dlg.exec_() != QDialog.Accepted: return document.print_(printer) self.statusBar().showMessage("Ready", 2000) def save(self): if self.curFile: return self.saveFile(self.curFile) return self.saveAs() def saveAs(self): fileName, _ = QFileDialog.getSaveFileName(self) if fileName: return self.saveFile(fileName) return False def IncreaseFont(self): FontIs = self.textEdit.currentFont() font = QFont(FontIs) FontSize = int(font.pointSize()) FontFam = font.family() if FontSize < 36: FontSize += 1 font.setPointSize(FontSize) font.setFamily(FontFam) self.textEdit.setFont(font) def DecreaseFont(self): FontIs = self.textEdit.currentFont() font = QFont(FontIs) FontSize = int(font.pointSize()) FontFam = font.family() if FontSize > 6: FontSize -= 1 font.setPointSize(FontSize) font.setFamily(FontFam) self.textEdit.setFont(font) def legend_act(self): pass def about(self): QMessageBox.about( self, "About VGenes Text Editor", "The <b>VGenes Text Editor</b> allows " "you to edit, save, and print documents " "generated by VGenes.") def documentWasModified(self): self.setWindowModified(self.textEdit.document().isModified()) def createActions(self): self.newAct = QAction(QIcon(':/PNG-Icons/page.png'), "&New", self, shortcut=QKeySequence.New, statusTip="Create a new file", triggered=self.newFile) self.openAct = QAction(QIcon(':/PNG-Icons/folder.png'), "&Open...", self, shortcut=QKeySequence.Open, statusTip="Open an existing file", triggered=self.open) self.saveAct = QAction(QIcon(':/PNG-Icons/SaveIcon.png'), "&Save", self, shortcut=QKeySequence.Save, statusTip="Save the document to disk", triggered=self.save) self.saveAsAct = QAction( "Save &As...", self, shortcut=QKeySequence.SaveAs, statusTip="Save the document under a new name", triggered=self.saveAs) self.closeAct = QAction("Close", self, shortcut=QKeySequence.Close, statusTip="Close window", triggered=self.close) self.exitAct = QAction("E&xit", self, shortcut="Ctrl+Q", statusTip="Exit VGenes Text Editor", triggered=self.close) self.cutAct = QAction( QIcon(':/PNG-Icons/scissor.png'), "Cu&t", self, shortcut=QKeySequence.Cut, statusTip="Cut the current selection's contents to the clipboard", triggered=self.textEdit.cut) self.IncreaseAct = QAction(QIcon(':/PNG-Icons/plus.png'), "&Increase", self, statusTip="Increase font size", triggered=self.IncreaseFont) self.DecreaseAct = QAction(QIcon(':/PNG-Icons/minus.png'), "&Decrease", self, statusTip="Decrease font size", triggered=self.DecreaseFont) self.printAct = QAction(QIcon(':/PNG-Icons/print.png'), "&Print...", self, shortcut=QKeySequence.Print, statusTip="Print the current form letter", triggered=self.print_) self.copyAct = QAction( QIcon(':/PNG-Icons/pages.png'), "&Copy", self, shortcut=QKeySequence.Copy, statusTip="Copy the current selection's contents to the clipboard", triggered=self.textEdit.copy) self.pasteAct = QAction( QIcon(':/PNG-Icons/Paste.png'), "&Paste", self, shortcut=QKeySequence.Paste, statusTip= "Paste the clipboard's contents into the current selection", triggered=self.textEdit.paste) self.aboutAct = QAction("&About", self, statusTip="Show the application's About box", triggered=self.about) self.Legend = QAction(QIcon(':/PNG-Icons/ScalePic.png'), "&Legend", self, statusTip="Legend", triggered=self.legend_act) # self.aboutQtAct = QAction("About &Qt", self, # statusTip="Show the Qt library's About box", # triggered=QApplication.instance().aboutQt) self.cutAct.setEnabled(False) self.copyAct.setEnabled(False) self.textEdit.copyAvailable.connect(self.cutAct.setEnabled) self.textEdit.copyAvailable.connect(self.copyAct.setEnabled) def createMenus(self): self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 1029, 22)) self.menubar.setDefaultUp(False) self.menubar.setNativeMenuBar(False) self.menubar.setObjectName("menubar") self.menuFile = QMenu(self.menubar) self.setMenuBar(self.menubar) self.fileMenu = self.menuBar().addMenu("&File") self.fileMenu.addAction(self.newAct) self.fileMenu.addAction(self.openAct) self.fileMenu.addAction(self.closeAct) self.fileMenu.addAction(self.saveAct) self.fileMenu.addAction(self.saveAsAct) self.fileMenu.addAction(self.printAct) self.fileMenu.addSeparator() self.fileMenu.addAction(self.exitAct) self.editMenu = self.menuBar().addMenu("&Edit") self.editMenu.addAction(self.cutAct) self.editMenu.addAction(self.copyAct) self.editMenu.addAction(self.pasteAct) self.menuBar().addSeparator() self.helpMenu = self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.aboutAct) # self.helpMenu.addAction(self.aboutQtAct) def createToolBars(self): self.fileToolBar = self.addToolBar("File") self.fileToolBar.addAction(self.newAct) self.fileToolBar.addAction(self.openAct) self.fileToolBar.addAction(self.closeACT) self.fileToolBar.addAction(self.saveAct) self.fileMenu.addAction(self.saveAsAct) self.fileToolBar.addAction(self.printAct) self.editToolBar = self.addToolBar("Edit") self.editToolBar.addAction(self.cutAct) self.editToolBar.addAction(self.copyAct) self.editToolBar.addAction(self.pasteAct) #self.FontSizeToolBar = self.addToolBar("FontSize") #self.FontSizeToolBar.addAction(self.IncreaseAct) #self.FontSizeToolBar.addAction(self.DecreaseAct) self.LegendToolBar = self.addToolBar("Legend") self.LegendToolBar.addAction(self.Legend) def createStatusBar(self): self.statusBar().showMessage("Ready") def readSettings(self): settings = QSettings("Trolltech", "VGenes Text Editor") pos = settings.value("pos", QPoint(200, 200)) size = settings.value("size", QSize(400, 400)) self.resize(size) self.move(pos) def writeSettings(self): settings = QSettings("Trolltech", "VGenes Text Editor") settings.setValue("pos", self.pos()) settings.setValue("size", self.size()) def maybeSave(self): if self.textEdit.document().isModified(): ret = QMessageBox.warning( self, "VGenes Text Editor", "The document has been modified.\nDo you want to save " "your changes?", QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel) if ret == QMessageBox.Save: return self.save() if ret == QMessageBox.Cancel: return False return True def loadFile(self, fileName): file = QFile(fileName) if not file.open(QFile.ReadOnly | QFile.Text): QMessageBox.warning( self, "VGenes Text Editor", "Cannot read file %s:\n%s." % (fileName, file.errorString())) return inf = QTextStream(file) QApplication.setOverrideCursor(Qt.WaitCursor) self.textEdit.setPlainText(inf.readAll()) QApplication.restoreOverrideCursor() self.setCurrentFile(fileName) self.statusBar().showMessage("File loaded", 2000) def saveFile(self, fileName): file = QFile(fileName) if not file.open(QFile.WriteOnly | QFile.Text): QMessageBox.warning( self, "VGenes Text Editor", "Cannot write file %s:\n%s." % (fileName, file.errorString())) return False outf = QTextStream(file) QApplication.setOverrideCursor(Qt.WaitCursor) outf << self.textEdit.toPlainText() QApplication.restoreOverrideCursor() self.setCurrentFile(fileName) self.statusBar().showMessage("File saved", 2000) return True def setCurrentFile(self, fileName): self.curFile = fileName self.textEdit.document().setModified(False) self.setWindowModified(False) if self.curFile: shownName = self.strippedName(self.curFile) else: shownName = 'untitled.txt' self.setWindowTitle("%s[*] - VGenes Text Editor" % shownName) def strippedName(self, fullFileName): return QFileInfo(fullFileName).fileName()
class VGenesTextMain(QMainWindow): def __init__(self): super(VGenesTextMain, self).__init__() self.setupUi() def setupUi(self): self.curFile = '' self.textEdit = QTextEdit() self.textEdit.setTextInteractionFlags(Qt.TextEditorInteraction) self.setCentralWidget(self.textEdit) self.createActions() self.createMenus() self.createToolBars() self.createStatusBar() self.readSettings() self.textEdit.document().contentsChanged.connect(self.documentWasModified) self.setCurrentFile('') def closeEvent(self, event): if self.maybeSave(): self.writeSettings() event.accept() else: event.ignore() def newFile(self): if self.maybeSave(): self.textEdit.clear() self.setCurrentFile('') def open(self): if self.maybeSave(): fileName, _ = QFileDialog.getOpenFileName(self) if fileName: self.loadFile(fileName) def print_(self): document = self.textEdit.document() printer = QPrinter() dlg = QPrintDialog(printer, self) if dlg.exec_() != QDialog.Accepted: return document.print_(printer) self.statusBar().showMessage("Ready", 2000) def save(self): if self.curFile: return self.saveFile(self.curFile) return self.saveAs() def saveAs(self): fileName, _ = QFileDialog.getSaveFileName(self) if fileName: return self.saveFile(fileName) return False def IncreaseFont(self): FontIs = self.textEdit.currentFont() font = QFont(FontIs) FontSize = int(font.pointSize()) FontFam = font.family() if FontSize < 36: FontSize += 1 font.setPointSize(FontSize) font.setFamily(FontFam) self.textEdit.setFont(font) def DecreaseFont(self): FontIs = self.textEdit.currentFont() font = QFont(FontIs) FontSize = int(font.pointSize()) FontFam = font.family() if FontSize > 6: FontSize -= 1 font.setPointSize(FontSize) font.setFamily(FontFam) self.textEdit.setFont(font) def about(self): QMessageBox.about(self, "About VGenes Text Editor", "The <b>VGenes Text Editor</b> allows " "you to edit, save, and print documents " "generated by VGenes.") def documentWasModified(self): self.setWindowModified(self.textEdit.document().isModified()) def createActions(self): self.newAct = QAction(QIcon(':/PNG-Icons/page.png'), "&New", self, shortcut=QKeySequence.New, statusTip="Create a new file", triggered=self.newFile) self.openAct = QAction(QIcon(':/PNG-Icons/folder.png'), "&Open...", self, shortcut=QKeySequence.Open, statusTip="Open an existing file", triggered=self.open) self.saveAct = QAction(QIcon(':/PNG-Icons/SaveIcon.png'), "&Save", self, shortcut=QKeySequence.Save, statusTip="Save the document to disk", triggered=self.save) self.saveAsAct = QAction("Save &As...", self, shortcut=QKeySequence.SaveAs, statusTip="Save the document under a new name", triggered=self.saveAs) self.closeAct = QAction("Close", self, shortcut=QKeySequence.Close, statusTip="Close window", triggered=self.close) self.exitAct = QAction("E&xit", self, shortcut="Ctrl+Q", statusTip="Exit VGenes Text Editor", triggered=self.close) self.cutAct = QAction(QIcon(':/PNG-Icons/scissor.png'), "Cu&t", self, shortcut=QKeySequence.Cut, statusTip="Cut the current selection's contents to the clipboard", triggered=self.textEdit.cut) self.IncreaseAct = QAction(QIcon(':/PNG-Icons/plus.png'), "&Increase", self, statusTip="Increase font size", triggered=self.IncreaseFont) self.DecreaseAct = QAction(QIcon(':/PNG-Icons/minus.png'), "&Decrease", self, statusTip="Decrease font size", triggered=self.DecreaseFont) self.printAct = QAction(QIcon(':/PNG-Icons/print.png'), "&Print...", self, shortcut=QKeySequence.Print, statusTip="Print the current form letter", triggered=self.print_) self.copyAct = QAction(QIcon(':/PNG-Icons/pages.png'), "&Copy", self, shortcut=QKeySequence.Copy, statusTip="Copy the current selection's contents to the clipboard", triggered=self.textEdit.copy) self.pasteAct = QAction(QIcon(':/PNG-Icons/Paste.png'), "&Paste", self, shortcut=QKeySequence.Paste, statusTip="Paste the clipboard's contents into the current selection", triggered=self.textEdit.paste) self.aboutAct = QAction("&About", self, statusTip="Show the application's About box", triggered=self.about) # self.aboutQtAct = QAction("About &Qt", self, # statusTip="Show the Qt library's About box", # triggered=QApplication.instance().aboutQt) self.cutAct.setEnabled(False) self.copyAct.setEnabled(False) self.textEdit.copyAvailable.connect(self.cutAct.setEnabled) self.textEdit.copyAvailable.connect(self.copyAct.setEnabled) def createMenus(self): self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 1029, 22)) self.menubar.setDefaultUp(False) self.menubar.setNativeMenuBar(False) self.menubar.setObjectName("menubar") self.menuFile = QMenu(self.menubar) self.setMenuBar(self.menubar) self.fileMenu = self.menuBar().addMenu("&File") self.fileMenu.addAction(self.newAct) self.fileMenu.addAction(self.openAct) self.fileMenu.addAction(self.closeAct) self.fileMenu.addAction(self.saveAct) self.fileMenu.addAction(self.saveAsAct) self.fileMenu.addAction(self.printAct) self.fileMenu.addSeparator(); self.fileMenu.addAction(self.exitAct) self.editMenu = self.menuBar().addMenu("&Edit") self.editMenu.addAction(self.cutAct) self.editMenu.addAction(self.copyAct) self.editMenu.addAction(self.pasteAct) self.menuBar().addSeparator() self.helpMenu = self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.aboutAct) # self.helpMenu.addAction(self.aboutQtAct) def createToolBars(self): self.fileToolBar = self.addToolBar("File") self.fileToolBar.addAction(self.newAct) self.fileToolBar.addAction(self.openAct) self.fileToolBar.addAction(self.closeACT) self.fileToolBar.addAction(self.saveAct) self.fileMenu.addAction(self.saveAsAct) self.fileToolBar.addAction(self.printAct) self.editToolBar = self.addToolBar("Edit") self.editToolBar.addAction(self.cutAct) self.editToolBar.addAction(self.copyAct) self.editToolBar.addAction(self.pasteAct) self.FontSizeToolBar = self.addToolBar("FontSize") self.FontSizeToolBar.addAction(self.IncreaseAct) self.FontSizeToolBar.addAction(self.DecreaseAct) def createStatusBar(self): self.statusBar().showMessage("Ready") def readSettings(self): settings = QSettings("Trolltech", "VGenes Text Editor") pos = settings.value("pos", QPoint(200, 200)) size = settings.value("size", QSize(400, 400)) self.resize(size) self.move(pos) def writeSettings(self): settings = QSettings("Trolltech", "VGenes Text Editor") settings.setValue("pos", self.pos()) settings.setValue("size", self.size()) def maybeSave(self): if self.textEdit.document().isModified(): ret = QMessageBox.warning(self, "VGenes Text Editor", "The document has been modified.\nDo you want to save " "your changes?", QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel) if ret == QMessageBox.Save: return self.save() if ret == QMessageBox.Cancel: return False return True def loadFile(self, fileName): file = QFile(fileName) if not file.open(QFile.ReadOnly | QFile.Text): QMessageBox.warning(self, "VGenes Text Editor", "Cannot read file %s:\n%s." % (fileName, file.errorString())) return inf = QTextStream(file) QApplication.setOverrideCursor(Qt.WaitCursor) self.textEdit.setPlainText(inf.readAll()) QApplication.restoreOverrideCursor() self.setCurrentFile(fileName) self.statusBar().showMessage("File loaded", 2000) def saveFile(self, fileName): file = QFile(fileName) if not file.open(QFile.WriteOnly | QFile.Text): QMessageBox.warning(self, "VGenes Text Editor", "Cannot write file %s:\n%s." % (fileName, file.errorString())) return False outf = QTextStream(file) QApplication.setOverrideCursor(Qt.WaitCursor) outf << self.textEdit.toPlainText() QApplication.restoreOverrideCursor() self.setCurrentFile(fileName); self.statusBar().showMessage("File saved", 2000) return True def setCurrentFile(self, fileName): self.curFile = fileName self.textEdit.document().setModified(False) self.setWindowModified(False) if self.curFile: shownName = self.strippedName(self.curFile) else: shownName = 'untitled.txt' self.setWindowTitle("%s[*] - VGenes Text Editor" % shownName) def strippedName(self, fullFileName): return QFileInfo(fullFileName).fileName()