class SampleBar(QMainWindow): """Main Application""" def __init__(self, parent=None): # print('Starting the main Application') super(SampleBar, self).__init__(parent) self.initUI() def initUI(self): # Pre Params: self.setMinimumSize(800, 600) # File Menus & Status Bar: self.statusBar = QStatusBar() self.statusBar.setStyleSheet('QStatusBar::item {border: none;}') self.setStatusBar(self.statusBar) self.statusBar.showMessage('准备') self.progressBar = QProgressBar() self.pushbutton = QPushButton("点这里") self.label = QLabel() self.label2 = QLabel() self.label.setText("开始计算 ") self.label2.setText("正在计算: ") # self.statusBar.addWidget(self.label, 0) self.statusBar.addPermanentWidget(self.progressBar, stretch=6) self.statusBar.addPermanentWidget(self.label, stretch=1) self.statusBar.addPermanentWidget(self.label2, stretch=1) # self.statusBar().addWidget(self.progressBar) # self.statusBar.removeWidget(self.progressBar) // remove the progress bar # This is simply to show the bar # self.progressBar.setGeometry(0, 0, 100, 5) self.progressBar.setRange(0, 500) # 设置进度条的范围 self.progressBar.setValue(20)
class StatusBar(QWidget): def __init__(self): super(StatusBar, self).__init__() self.statusbar = QStatusBar() self.statusbar.setObjectName("statusbar") self.statusbar.setStyleSheet( "#statusbar{background-color:white;color:black;border:none;border-radius:2px;font-weight: bloder }" ) self.statusbar.showMessage("空闲")
class MainWindow(QMainWindow): def __init__(self): super().__init__() self.fileList = ui.FileList.FileList(self) self.fileListLabel = self.getLabel(self.fileList, "项目列表") self.imageArea = ui.ImageArea.ImageArea(self) self.imageAreaLabel = self.getLabel(self.imageArea, "图像预览") self.infoTable = ui.InfoTable.InfoTable(self) self.infoTableLabel = self.getLabel(self.infoTable, "输出列表") self.staBar = QStatusBar() self.staBar.setStyleSheet(uiConfig.STATUSBAR_S) self.setStatusBar(self.staBar) # 创建一个QSplitter,用来分割窗口 self.splitter = QSplitter(self) self.splitter.addWidget(self.fileListLabel) self.splitter.addWidget(self.imageAreaLabel) self.splitter.addWidget(self.infoTableLabel) self.splitter.setStretchFactor(0, 1) self.splitter.setStretchFactor(1, 3) self.splitter.setStretchFactor(2, 2) # QSplitter按照垂直分割 self.splitter.setStyleSheet(uiConfig.SPLITER_S) self.splitter.setOrientation(Qt.Horizontal) self.setCentralWidget(self.splitter) self.setWindowTitle("地图坐标拾取系统") # self.setStyleSheet("QMainWindow::separator { background: rgb(190,231,233) }") # self.setWindowFlag(Qt.WindowMaximizeButtonHint, False) # self.setWindowFlags(Qt.FramelessWindowHint) self.setWindowState(Qt.WindowMaximized) size = QDesktopWidget().screenGeometry(-1) self.setFixedSize(size.width(), size.height()) self.setWindowIcon(QIcon("ui/images/logo.png")) self.setStyleSheet(uiConfig.MAINWINDOW_S) def getLabel(self, mWidget, text): qLabel = QLabel() qLabel.setStyleSheet(uiConfig.GRANDLABEL_S) vLayout = QVBoxLayout() textLabel = QLabel() textLabel.setStyleSheet(uiConfig.TEXTLABEL_S) textLabel.setText(" " + text) textLabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) mWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) vLayout.setContentsMargins(0, 0, 0, 0) vLayout.setSpacing(0) vLayout.addWidget(textLabel) vLayout.addWidget(mWidget) qLabel.setLayout(vLayout) return qLabel
class App(QMainWindow): def __init__(self): super().__init__() self.title = 'kfit' self.left = 400 self.top = 150 self.width = 1200 self.height = 800 self.file_name = '' self.xcol_idx = 0 self.ycol_idx = 1 self.ngau = 0 self.nlor = 0 self.nvoi = 0 self.nlin = 1 self.model = None self.result = None self.curves_df = None self.params_df = None self.edit_mode = False # empty Parameters to hold parameter guesses/constraints self.params = Parameters() self.guesses = {'value': {}, 'min': {}, 'max': {}} self.usr_vals = {'value': {}, 'min': {}, 'max': {}} self.usr_entry_widgets = {} self.cid = None # file import settings self.sep = ',' self.header = 'infer' self.index_col = None self.skiprows = None self.dtype = None self.encoding = None # keyboard shortcuts self.fit_shortcut = QShortcut(QKeySequence('Ctrl+F'), self) self.fit_shortcut.activated.connect(self.fit) self.reset_shortcut = QShortcut(QKeySequence('Ctrl+R'), self) self.reset_shortcut.activated.connect(self.hard_reset) self.save_fit = QShortcut(QKeySequence('Ctrl+S'), self) self.save_fit.activated.connect(self.export_results) self.add_gau = QShortcut(QKeySequence('G'), self) self.add_gau.activated.connect(lambda: self.increment('gau', True)) self.add_gau.activated.connect(self.init_param_widgets) self.sub_gau = QShortcut(QKeySequence('Shift+G'), self) self.sub_gau.activated.connect(lambda: self.increment('gau', False)) self.sub_gau.activated.connect(self.init_param_widgets) self.add_lor = QShortcut(QKeySequence('L'), self) self.add_lor.activated.connect(lambda: self.increment('lor', True)) self.add_lor.activated.connect(self.init_param_widgets) self.sub_lor = QShortcut(QKeySequence('Shift+L'), self) self.sub_lor.activated.connect(lambda: self.increment('lor', False)) self.sub_lor.activated.connect(self.init_param_widgets) self.add_voi = QShortcut(QKeySequence('V'), self) self.add_voi.activated.connect(lambda: self.increment('voi', True)) self.add_voi.activated.connect(self.init_param_widgets) self.sub_voi = QShortcut(QKeySequence('Shift+V'), self) self.sub_voi.activated.connect(lambda: self.increment('voi', False)) self.sub_voi.activated.connect(self.init_param_widgets) self.add_lin = QShortcut(QKeySequence('N'), self) self.add_lin.activated.connect(lambda: self.increment('lin', True)) self.add_lin.activated.connect(self.init_param_widgets) self.sub_lin = QShortcut(QKeySequence('Shift+N'), self) self.sub_lin.activated.connect(lambda: self.increment('lin', False)) self.sub_lin.activated.connect(self.init_param_widgets) # temporary data x = np.linspace(0, 10, 500) y = models.gauss(x, 0.5, 4, 0.4) + \ models.gauss(x, 0.8, 5, 0.2) + \ models.gauss(x, 0.4, 6, 0.3) + 0.2 # set data self.data = pd.DataFrame([x, y]).T self.data.columns = ['x', 'y'] self.x = self.data['x'] self.y = self.data['y'] self.xmin = self.data['x'].min() self.xmax = self.data['x'].max() self.initUI() def initUI(self): self.setGeometry(self.left, self.top, self.width, self.height) self.setWindowTitle(self.title) self.setWindowIcon(QIcon('../images/K.png')) # set up the status bar self.status_bar = QStatusBar() self.setStatusBar(self.status_bar) self.status_bar.showMessage('Welcome to kfit!', msg_length) self.status_bar.setStyleSheet('background-color: white') # Create the Main Widget and Layout self.main_layout = QVBoxLayout() self.main_widget = QSplitter() self.main_widget.setOrientation(Qt.Vertical) self.setCentralWidget(self.main_widget) # create "top bar" widget self.topbar_layout = QHBoxLayout() self.topbar_widget = QWidget() # fit button self.fit_button = QPushButton('Fit', self) self.fit_button.setMaximumWidth(100) self.fit_button.clicked.connect(self.fit) self.fit_button.installEventFilter(self) # import button self.import_button = QPushButton('Import', self) self.import_button.setMaximumWidth(100) self.import_button.clicked.connect(self.get_data) self.import_button.installEventFilter(self) # import settings button self.import_settings_button = QPushButton('', self) self.import_settings_button.setIcon( QIcon.fromTheme('stock_properties')) self.import_settings_button.setMaximumWidth(40) self.import_settings_button.clicked.connect( self.import_settings_dialog) self.import_settings_button.installEventFilter(self) # reset fit button self.reset_button = QPushButton('', self) self.reset_button.setIcon(QIcon.fromTheme('view-refresh')) self.reset_button.setMaximumWidth(40) self.reset_button.clicked.connect(self.hard_reset) self.reset_button.installEventFilter(self) # save results button self.save_button = QPushButton('', self) self.save_button.setIcon(QIcon.fromTheme('filesave')) self.save_button.setMaximumWidth(40) self.save_button.clicked.connect(self.export_results) self.save_button.installEventFilter(self) # progress bar self.progress_bar = QProgressBar() # self.progressBar.setMaximumWidth(150) self.progress_bar.hide() # get column header for x self.xlabel = QLabel(self) self.xlabel.setText('ColumnIndex(X):') self.xlabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) # self.xlabel.setMaximumWidth(250) self.xline_entry = QLineEdit(self) self.xline_entry.setText('0') self.xline_entry.setAlignment(Qt.AlignCenter) # self.xline_entry.setMaximumWidth(50) self.xline_entry.returnPressed.connect(self.column_index_set) # get column header for y self.ylabel = QLabel(self) self.ylabel.setText('ColumnIndex(Y):') self.ylabel.setAlignment(Qt.AlignRight | Qt.AlignVCenter) # self.ylabel.setMaximumWidth(100) self.yline_entry = QLineEdit(self) self.yline_entry.setText('1') self.yline_entry.setAlignment(Qt.AlignCenter) # self.yline_entry.setMaximumWidth(50) self.yline_entry.returnPressed.connect(self.column_index_set) # add topbar widgets to layout self.topbar_layout.addSpacing(600) self.topbar_layout.addWidget(self.xlabel) self.topbar_layout.addWidget(self.xline_entry) self.topbar_layout.addWidget(self.ylabel) self.topbar_layout.addWidget(self.yline_entry) self.topbar_layout.addWidget(self.fit_button) self.topbar_layout.addWidget(self.import_button) self.topbar_layout.addWidget(self.import_settings_button) self.topbar_layout.addWidget(self.reset_button) self.topbar_layout.addWidget(self.save_button) self.topbar_layout.addWidget(self.progress_bar) self.topbar_layout.setAlignment(Qt.AlignRight) self.topbar_widget.setLayout(self.topbar_layout) self.topbar_widget.setMaximumHeight(75) # create tabs widget self.tabs = QTabWidget(self) self.tab1 = QWidget(self) self.tab2 = QTableView(self) self.tab3 = QWidget(self) self.tabs.addTab(self.tab1, 'Graph') self.tabs.addTab(self.tab2, 'Data') self.tabs.addTab(self.tab3, 'Output') self.tabs.setMinimumHeight(300) # create params widget self.params_widget = QSplitter() self.gau_layout = QVBoxLayout() self.gau_layout.setAlignment(Qt.AlignTop) self.gau_widget = QWidget() self.gau_widget.setLayout(self.gau_layout) self.gau_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.gau_scroll = QScrollArea() self.gau_scroll.setWidget(self.gau_widget) self.gau_scroll.setWidgetResizable(True) self.lor_widget = QWidget() self.lor_layout = QVBoxLayout() self.lor_layout.setAlignment(Qt.AlignTop) self.lor_widget.setLayout(self.lor_layout) self.lor_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.lor_scroll = QScrollArea() self.lor_scroll.setWidget(self.lor_widget) self.lor_scroll.setWidgetResizable(True) self.voi_widget = QWidget() self.voi_layout = QVBoxLayout() self.voi_layout.setAlignment(Qt.AlignTop) self.voi_widget.setLayout(self.voi_layout) self.voi_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.voi_scroll = QScrollArea() self.voi_scroll.setWidget(self.voi_widget) self.voi_scroll.setWidgetResizable(True) self.lin_widget = QWidget() self.lin_layout = QVBoxLayout() self.lin_layout.setAlignment(Qt.AlignTop) self.lin_widget.setLayout(self.lin_layout) self.lin_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.lin_scroll = QScrollArea() self.lin_scroll.setWidget(self.lin_widget) self.lin_scroll.setWidgetResizable(True) self.params_widget.addWidget(self.gau_scroll) self.params_widget.addWidget(self.lor_scroll) self.params_widget.addWidget(self.voi_scroll) self.params_widget.addWidget(self.lin_scroll) self.params_widget.setMinimumHeight(180) # add everything to main widget self.main_widget.addWidget(self.topbar_widget) self.main_widget.addWidget(self.tabs) self.main_widget.addWidget(self.params_widget) # Tab 1 - Graph / Model # Graph plt.style.use('fivethirtyeight') self.tab1.figure = Figure(figsize=(8, 6), dpi=60) self.tab1.canvas = FigureCanvas(self.tab1.figure) self.tab1.toolbar = NavigationToolbar(self.tab1.canvas, self) # tristate checkbox for edit mode self.emode_box = QCheckBox() self.emode_box.setTristate(True) self.emode_box.setIcon(QIcon.fromTheme('stock_edit')) self.emode_box.stateChanged.connect(self.toggle_edit_mode) self.emode_box.installEventFilter(self) # tweaking the toolbar layout self.tab1.toolbar.setIconSize(QSize(18, 18)) spacer = QWidget() spacer.setFixedWidth(20) self.tab1.toolbar.addWidget(spacer) self.tab1.toolbar.addWidget(self.emode_box) self.tab1.toolbar.locLabel.setAlignment(Qt.AlignRight | Qt.AlignCenter) graph_layout = QVBoxLayout() graph_layout.addWidget(self.tab1.toolbar) graph_layout.addWidget(self.tab1.canvas) # The "Set Model" layout model_layout = QGridLayout() widget_setgau = QWidget() layout_setgau = QHBoxLayout() layout_setgau.setSizeConstraint(QLayout.SetFixedSize) widget_setgau.setLayout(layout_setgau) widget_setlor = QWidget() layout_setlor = QHBoxLayout() layout_setlor.setSizeConstraint(QLayout.SetFixedSize) widget_setlor.setLayout(layout_setlor) widget_setvoi = QWidget() layout_setvoi = QHBoxLayout() layout_setvoi.setSizeConstraint(QLayout.SetFixedSize) widget_setvoi.setLayout(layout_setvoi) widget_setlin = QWidget() layout_setlin = QHBoxLayout() layout_setlin.setSizeConstraint(QLayout.SetFixedSize) widget_setlin.setLayout(layout_setlin) model_layout.addWidget(widget_setgau, 0, 0) model_layout.addWidget(widget_setlor, 0, 1) model_layout.addWidget(widget_setvoi, 0, 2) model_layout.addWidget(widget_setlin, 0, 3) # specify number of gaussian curves gauss_label = QLabel(self) gauss_label.setText('Gaussians') gauss_label.setAlignment(Qt.AlignVCenter) gauss_button_add = QPushButton('', self) gauss_button_add.setIcon(QIcon.fromTheme('list-add')) gauss_button_add.clicked.connect(lambda: self.increment('gau', True)) gauss_button_add.clicked.connect(self.init_param_widgets) gauss_button_sub = QPushButton('', self) gauss_button_sub.setIcon(QIcon.fromTheme('list-remove')) gauss_button_sub.clicked.connect(lambda: self.increment('gau', False)) gauss_button_sub.clicked.connect(self.init_param_widgets) layout_setgau.addWidget(gauss_label) layout_setgau.addWidget(gauss_button_add) layout_setgau.addWidget(gauss_button_sub) # specify number of lorentzian curves lorentz_label = QLabel(self) lorentz_label.setText('Lorentzians') lorentz_label.setAlignment(Qt.AlignVCenter) lorentz_button_add = QPushButton('', self) lorentz_button_add.setIcon(QIcon.fromTheme('list-add')) lorentz_button_add.clicked.connect(lambda: self.increment('lor', True)) lorentz_button_add.clicked.connect(self.init_param_widgets) lorentz_button_sub = QPushButton('', self) lorentz_button_sub.setIcon(QIcon.fromTheme('list-remove')) lorentz_button_sub.clicked.connect( lambda: self.increment('lor', False)) lorentz_button_sub.clicked.connect(self.init_param_widgets) layout_setlor.addWidget(lorentz_label) layout_setlor.addWidget(lorentz_button_add) layout_setlor.addWidget(lorentz_button_sub) # specify number of voigt curves voigt_label = QLabel(self) voigt_label.setText('Pseudo-Voigts') voigt_label.setAlignment(Qt.AlignVCenter) voigt_button_add = QPushButton('', self) voigt_button_add.setIcon(QIcon.fromTheme('list-add')) voigt_button_add.clicked.connect(lambda: self.increment('voi', True)) voigt_button_add.clicked.connect(self.init_param_widgets) voigt_button_sub = QPushButton('', self) voigt_button_sub.setIcon(QIcon.fromTheme('list-remove')) voigt_button_sub.clicked.connect(lambda: self.increment('voi', False)) voigt_button_sub.clicked.connect(self.init_param_widgets) layout_setvoi.addWidget(voigt_label) layout_setvoi.addWidget(voigt_button_add) layout_setvoi.addWidget(voigt_button_sub) # specify number of lines line_label = QLabel(self) line_label.setText('Lines:') line_label.setAlignment(Qt.AlignVCenter) line_button_add = QPushButton('', self) line_button_add.setIcon(QIcon.fromTheme('list-add')) line_button_add.clicked.connect(lambda: self.increment('lin', True)) line_button_add.clicked.connect(self.init_param_widgets) line_button_sub = QPushButton('', self) line_button_sub.setIcon(QIcon.fromTheme('list-remove')) line_button_sub.clicked.connect(lambda: self.increment('lin', False)) line_button_sub.clicked.connect(self.init_param_widgets) layout_setlin.addWidget(line_label) layout_setlin.addWidget(line_button_add) layout_setlin.addWidget(line_button_sub) graph_layout.addLayout(model_layout) self.tab1.setLayout(graph_layout) self.plot() # Tab 2 - Data Table self.table_model = PandasModel(self.data) self.tab2.setModel(self.table_model) self.tab2.resizeColumnsToContents() # Tab 3 - Output self.tab3_widget = QPlainTextEdit() tab3_layout = QVBoxLayout() tab3_layout.addWidget(self.tab3_widget) self.tab3.setLayout(tab3_layout) self.init_param_widgets() self.show() def export_results(self): self.process_results() # open file dialog exp_file_name, _ = QFileDialog.getSaveFileName( self, 'QFileDialog.getSaveFileName()', 'fit_results.csv', 'CSV files (*.csv)', ) if exp_file_name: self.process_results() self.curves_df.to_csv(exp_file_name) # NOTE: if user chooses a file extension other than .csv, or does # not use a file extension, this should still work, but I haven't # tested too rigorously yet self.params_df.to_csv('{}.params.csv'.format( exp_file_name[:exp_file_name.find('.csv')])) self.status_bar.showMessage( 'Exported fit results to: ' + exp_file_name, 2 * msg_length) else: self.status_bar.showMessage('Export canceled.', 2 * msg_length) return def process_results(self): if self.result is not None: self.params_df = pd.DataFrame.from_dict(self.result.best_values, orient='index') self.params_df.index.name = 'parameter' self.params_df.columns = ['value'] curves_dict = { 'data': self.y, 'total_fit': self.result.best_fit, } components = self.result.eval_components() for i, comp in enumerate(components): curves_dict[comp[:comp.find('_')]] = components[comp] self.curves_df = pd.DataFrame.from_dict(curves_dict) self.curves_df.index = self.x self.curves_df.index.name = self.data.columns[self.xcol_idx] else: self.status_bar.showMessage('No fit results to export!', msg_length) def eventFilter(self, object, event): if event.type() == QEvent.Enter: if object is self.reset_button: self.status_bar.showMessage("Reset fit") if object is self.import_settings_button: self.status_bar.showMessage("File import settings") if object is self.import_button: self.status_bar.showMessage("Import .csv file") if object is self.fit_button: self.status_bar.showMessage("Fit data") if object is self.emode_box: self.status_bar.showMessage("Toggle edit mode") if object is self.save_button: self.status_bar.showMessage("Export fit results") return True elif event.type() == QEvent.Leave: self.status_bar.showMessage(None) return False def init_model(self): # increment() ensures nlin >= 1 self.model = models.line_mod(self.nlin) if self.ngau != 0: self.model += models.gauss_mod(self.ngau) if self.nlor != 0: self.model += models.lor_mod(self.nlor) if self.nvoi != 0: self.model += models.voigt_mod(self.nvoi) self.status_bar.showMessage( "Model updated: " + str([self.ngau, self.nlor, self.nvoi, self.nlin]), msg_length) def init_param_widgets(self): self.init_model() self.usr_entry_widgets = {'value': {}, 'min': {}, 'max': {}} labels = {} rnd = 3 # decimals to round to in placeholder text self.clear_fit_layouts() for param_name in self.model.param_names: # set param label text labels[param_name] = QLabel() labels[param_name].setText(param_name) # make qlineedit widgets for key in self.usr_entry_widgets: self.usr_entry_widgets[key][param_name] = QLineEdit() if param_name in self.usr_vals[key]: self.usr_entry_widgets[key][param_name]\ .setPlaceholderText( str(round(self.usr_vals[key][param_name], rnd)) ) else: self.usr_entry_widgets[key][param_name]\ .setPlaceholderText(key) # set up connections # connect() expects a callable func, hence the lambda self.usr_entry_widgets[key][param_name].returnPressed.connect( lambda: self.update_usr_vals(self.usr_entry_widgets)) # add widgets to respective layouts sublayout1 = QVBoxLayout() sublayout2 = QHBoxLayout() sublayout1.addWidget(labels[param_name]) for key in self.usr_entry_widgets: sublayout2.addWidget(self.usr_entry_widgets[key][param_name]) if param_name.find('gau') != -1: self.gau_layout.addLayout(sublayout1) self.gau_layout.addLayout(sublayout2) if param_name.find('lor') != -1: self.lor_layout.addLayout(sublayout1) self.lor_layout.addLayout(sublayout2) if param_name.find('voi') != -1: self.voi_layout.addLayout(sublayout1) self.voi_layout.addLayout(sublayout2) if param_name.find('lin') != -1: self.lin_layout.addLayout(sublayout1) self.lin_layout.addLayout(sublayout2) # Resize all of the LineEntry widgets for key in self.usr_entry_widgets: for param, widget in self.usr_entry_widgets[key].items(): widget.setMaximumWidth(150) if self.result is not None: self.set_params() self.update_param_widgets() def update_usr_vals(self, entry): # get text input from each usr_entry_widget for val_type, param_dict in self.usr_entry_widgets.items(): for param, param_widget in param_dict.items(): try: self.usr_vals[val_type][param] = \ float(param_widget.text()) except Exception: pass def update_param_widgets(self): rnd = 3 # the 'value' placeholder text is the result for that param # taken from self.result # the 'min' and 'max' text is from either the self.guesses # or from self.usr_vals for param in self.params: if param in self.result.best_values: self.usr_entry_widgets['value'][param].setPlaceholderText( str(round(self.result.best_values[param], rnd))) self.usr_entry_widgets['min'][param].setPlaceholderText( str(round(self.params[param].min, rnd))) self.usr_entry_widgets['max'][param].setPlaceholderText( str(round(self.params[param].max, rnd))) def guess_params(self): for comp in self.model.components: if comp.prefix.find('gau') != -1 or \ comp.prefix.find('lor') != -1 or \ comp.prefix.find('voi') != -1: # need to define explicitly to make proper guesses c = comp.prefix + 'center' a = comp.prefix + 'amplitude' s = comp.prefix + 'sigma' f = comp.prefix + 'fraction' self.guesses['value'][c] = \ self.data.iloc[:, self.xcol_idx].mean() self.guesses['value'][a] = \ self.data.iloc[:, self.ycol_idx].mean() self.guesses['value'][s] = \ self.data.iloc[:, self.xcol_idx].std() self.guesses['min'][c] = None self.guesses['min'][a] = 0 self.guesses['min'][s] = 0 self.guesses['max'][c] = None self.guesses['max'][a] = None self.guesses['max'][s] = None if comp.prefix.find('voi') != -1: self.guesses['value'][f] = 0.5 self.guesses['min'][f] = 0 self.guesses['max'][f] = 1 else: slope = comp.prefix + 'slope' intc = comp.prefix + 'intercept' for p in [slope, intc]: self.guesses['value'][p] = \ self.data.iloc[:, self.ycol_idx].mean() self.guesses['min'][p] = None self.guesses['max'][p] = None def set_params(self): self.params = Parameters() self.guess_params() self.update_usr_vals(self.usr_entry_widgets) vals = {} # fill params with any user-entered values # fill in blanks with guesses for param_name in self.model.param_names: for val_type in ['value', 'min', 'max']: if param_name in self.usr_vals[val_type]: vals[val_type] = self.usr_vals[val_type][param_name] # print('param: ' + param_name + ', type: ' +\ # val_type + ', set_by: user') else: vals[val_type] = self.guesses[val_type][param_name] # print('param: ' + param_name + ', type: ' +\ # val_type + ', set_by: guess') self.params.add(name=param_name, value=vals['value'], vary=True, min=vals['min'], max=vals['max']) def set_xy_range(self): self.x = self.data.iloc[:, self.xcol_idx] self.y = self.data.iloc[:, self.ycol_idx] self.xmin, self.xmax = self.ax.get_xlim() range_bool = (self.x >= self.xmin) & (self.x <= self.xmax) self.x = self.x[range_bool].values self.y = self.y[range_bool].values def reset_xy_range(self): self.xmin = np.min(self.x) self.xmax = np.max(self.x) def fit(self): self.emode_box.setCheckState(0) self.toggle_edit_mode() self.set_xy_range() self.set_params() self.result = self.model.fit(data=self.y, params=self.params, x=self.x, method='least_squares') self.tab3_widget.clear() self.tab3_widget.insertPlainText(self.result.fit_report()) self.plot() # overwrite widgets to clear input (not ideal method..) self.init_param_widgets() # update widgets with new placeholder text self.update_param_widgets() def column_index_set(self): # make sure user enters index that can be converted to int try: idx_x = int(self.xline_entry.text()) except ValueError: self.status_bar.showMessage(idx_type_error_msg, msg_length) self.xline_entry.setText(None) return try: idx_y = int(self.yline_entry.text()) except ValueError: self.status_bar.showMessage(idx_type_error_msg, msg_length) self.yline_entry.setText(None) return self.xcol_idx = idx_x self.ycol_idx = idx_y self.result = None # make sure user enters an index that's in the data range try: self.x = self.data.iloc[:, self.xcol_idx] except IndexError: self.status_bar.showMessage(idx_range_error_msg, msg_length) self.xline_entry.setText(None) return try: self.y = self.data.iloc[:, self.ycol_idx] except IndexError: self.status_bar.showMessage(idx_range_error_msg, msg_length) self.yline_entry.setText(None) return self.xmin = np.min(self.x) self.xmax = np.max(self.x) self.plot() self.status_bar.showMessage( 'ColumnIndex(X) = ' + str(idx_x) + ', ' + 'ColumnIndex(Y) = ' + str(idx_y), msg_length) def toggle_edit_mode(self): # first toggle off the zoom or pan button # so they don't interfere with edit_mode cursor style if self.tab1.toolbar._active == 'ZOOM': self.tab1.toolbar.zoom() if self.tab1.toolbar._active == 'PAN': self.tab1.toolbar.pan() states = { 0: 'Edit mode off', 1: 'Edit mode on | copy x-value', 2: 'Edit mode on | copy y-value', } self.status_bar.showMessage(states[self.emode_box.checkState()], msg_length) if self.emode_box.checkState() == 0: self.mpl_cursor = None self.tab1.canvas.mpl_disconnect(self.cid) if self.emode_box.checkState() == 1: self.mpl_cursor = Cursor(self.ax, lw=1, c='red', linestyle='--') self.cid = self.tab1.canvas.mpl_connect('button_press_event', self.get_coord_click) if self.emode_box.checkState() == 2: self.cid = self.tab1.canvas.mpl_connect('button_press_event', self.get_coord_click) def get_coord_click(self, event): self.x_edit, self.y_edit = round(event.xdata, 3), round(event.ydata, 3) if self.emode_box.checkState() == 1: pyperclip.copy(self.x_edit) self.status_bar.showMessage( 'Copied X=' + str(self.x_edit) + ' to clipboard!', msg_length) if self.emode_box.checkState() == 2: pyperclip.copy(self.y_edit) self.status_bar.showMessage( 'Copied Y=' + str(self.y_edit) + ' to clipboard!', msg_length) def close_app(self): sys.exit() def get_data(self): self.emode_box.setCheckState(0) self.toggle_edit_mode() # reset column indices self.xcol_idx = 0 self.ycol_idx = 1 # open file dialog self.file_name, _ = QFileDialog.getOpenFileName( self, 'Open File', '', 'CSV files (*.csv);; All Files (*)') if self.file_name: # this message isn't showing up... # TODO: needs to be threaded self.status_bar.showMessage('Importing: ' + self.file_name, msg_length) try: df = tools.to_df(self.file_name, sep=self.sep, header=self.header, index_col=self.index_col, skiprows=self.skiprows, dtype=self.dtype, encoding=self.encoding) df.iloc[:, self.xcol_idx] df.iloc[:, self.ycol_idx] except Exception: self.status_bar.showMessage(file_import_error_msg, 2 * msg_length) return else: self.status_bar.showMessage('Import canceled.', msg_length) return self.data = df self.table_model = PandasModel(self.data) self.tab2.setModel(self.table_model) self.tab2.resizeColumnsToContents() # clear any previous fit result self.result = None # reset x, y, and xlim self.x = self.data.iloc[:, self.xcol_idx].values self.y = self.data.iloc[:, self.ycol_idx].values self.xmin = self.data.iloc[:, self.xcol_idx].min() self.xmax = self.data.iloc[:, self.xcol_idx].max() self.plot() self.status_bar.showMessage('Import finished.', msg_length) def import_settings_dialog(self): self.dialog_window = QDialog() self.dialog_window.setWindowTitle('File Import Settings') toplevel = QVBoxLayout() dialog_layout = QHBoxLayout() label_layout = QVBoxLayout() entry_layout = QVBoxLayout() button_layout = QVBoxLayout() label1 = QLabel(self.dialog_window) label1.setText('sep') label2 = QLabel(self.dialog_window) label2.setText('header') label3 = QLabel(self.dialog_window) label3.setText('skiprows') label4 = QLabel(self.dialog_window) label4.setText('dtype') label5 = QLabel(self.dialog_window) label5.setText('encoding') for lbl in [label1, label2, label3, label4, label5]: label_layout.addWidget(lbl) self.sep_edit = QLineEdit(self.dialog_window) self.head_edit = QLineEdit(self.dialog_window) self.skipr_edit = QLineEdit(self.dialog_window) self.dtype_edit = QLineEdit(self.dialog_window) self.enc_edit = QLineEdit(self.dialog_window) self.sep_edit.setText(self.sep) self.head_edit.setText(self.header) # if value is None, show text as 'None' if self.skiprows is not None: self.skipr_edit.setText(self.skiprows) else: self.skipr_edit.setText('None') if self.dtype is not None: self.dtype_edit.setText(self.dtype) else: self.dtype_edit.setText('None') if self.encoding is not None: self.enc_edit.setText(self.encoding) else: self.enc_edit.setText('None') # add widgets to layout for ewidget in [ self.sep_edit, self.head_edit, self.skipr_edit, self.dtype_edit, self.enc_edit ]: ewidget.setAlignment(Qt.AlignCenter) entry_layout.addWidget(ewidget) button1 = QPushButton('Set', self.dialog_window) button2 = QPushButton('Set', self.dialog_window) button3 = QPushButton('Set', self.dialog_window) button4 = QPushButton('Set', self.dialog_window) button5 = QPushButton('Set', self.dialog_window) for btn in [button1, button2, button3, button4, button5]: btn.clicked.connect(self.set_import_settings) button_layout.addWidget(btn) reflabel = QLabel(self.dialog_window) reflabel.setText( "for help, refer to <a href='https://pandas.pydata.org/" + "pandas-docs/stable/reference/api/" + "pandas.read_csv.html'>pandas.read_csv()</a>") reflabel.setOpenExternalLinks(True) reflabel.setAlignment(Qt.AlignCenter) for lo in [label_layout, entry_layout, button_layout]: dialog_layout.addLayout(lo) toplevel.addLayout(dialog_layout) toplevel.addSpacing(25) toplevel.addWidget(reflabel) self.dialog_window.setLayout(toplevel) self.dialog_window.setWindowModality(Qt.ApplicationModal) self.dialog_window.exec_() def set_import_settings(self): self.sep = self.sep_edit.text() self.header = self.head_edit.text() # convert 'None' entries to None if self.skipr_edit.text() == 'None': self.skiprows = None else: self.skiprows = self.skipr_edit.text() if self.dtype_edit.text() == 'None': self.dtype = None else: self.dtype = self.dtype_edit.text() if self.enc_edit.text() == 'None': self.encoding = None else: self.encoding = self.enc_edit.text() def plot(self): self.tab1.figure.clear() self.ax = self.tab1.figure.add_subplot(111, label=self.file_name) self.ax.scatter(self.x, self.y, s=100, c='None', edgecolors='black', linewidth=1, label='data') if self.result is not None: yfit = self.result.best_fit self.ax.plot(self.x, yfit, c='r', linewidth=2.5) cmap = cm.get_cmap('gnuplot') components = self.result.eval_components() for i, comp in enumerate(components): self.ax.plot(self.x, components[comp], linewidth=2.5, linestyle='--', c=cmap(i / len(components)), label=comp[:comp.find('_')]) self.ax.set_xlabel(self.data.columns[self.xcol_idx], labelpad=15) self.ax.set_ylabel(self.data.columns[self.ycol_idx], labelpad=15) self.ax.set_xlim([self.xmin, self.xmax]) self.ax.legend(loc='upper right') self.tab1.figure.subplots_adjust(bottom=0.15, left=0.06, right=0.94) self.tab1.canvas.draw() def clear_layout(self, layout): if layout: while layout.count(): item = layout.takeAt(0) widget = item.widget() if widget: widget.deleteLater() else: self.clear_layout(item.layout()) layout.removeItem(item) def clear_fit_layouts(self): for layout in [ self.gau_layout, self.lor_layout, self.voi_layout, self.lin_layout ]: self.clear_layout(layout) def hard_reset(self): self.clear_fit_layouts() self.ngau = 0 self.nlor = 0 self.nvoi = 0 self.nlin = 1 self.init_model() self.params = Parameters() self.result = None self.params_df = None self.curves_df = None self.guesses = {'value': {}, 'min': {}, 'max': {}} self.usr_vals = {'value': {}, 'min': {}, 'max': {}} self.init_param_widgets() self.plot() def increment(self, val, add): if add: if val == 'gau': self.ngau += 1 if val == 'lor': self.nlor += 1 if val == 'voi': self.nvoi += 1 if val == 'lin': self.nlin += 1 if not add: if val == 'gau': self.ngau -= 1 if val == 'lor': self.nlor -= 1 if val == 'voi': self.nvoi -= 1 if val == 'lin': self.nlin -= 1 # make sure value doesn't go below zero if self.ngau < 0: self.ngau = 0 if self.nlor < 0: self.nlor = 0 if self.nvoi < 0: self.nvoi = 0 if self.nlin < 1: self.nlin = 1
class App(QWid): def __init__(self): super().__init__() self.title = "Tutorial Point Scrapper" self.showMaximized() self.initUI() def initUI(self): self.setWindowIcon(Qico('pythonlogo.png')) self.setWindowTitle(self.title) self.SetWidgets() self.show() def Selector(self, index): self.scbox.clear() self.scbox.addItem("--Select--") if self.cbox.currentText() != "--Select--": file_name = "COURSES/" + self.cbox.currentText() + ".csv" csv_file = open(file_name) csv_reader = csv.reader(csv_file, delimiter=',') for i in csv_reader: self.scbox.addItem(i[1]) def Clicked(self): if self.cbox.currentText() != "--Select--": file_name = "COURSES/" + self.cbox.currentText() + ".csv" csv_file = open(file_name) csv_reader = csv.reader(csv_file, delimiter=',') if self.scbox.currentText() != "--Select--": for i in csv_reader: if (i[1] == self.scbox.currentText()): url_open = i[2] break driver = webdriver.Chrome( '/usr/lib/chromium-browser/chromedriver') driver.get(url_open) def SetWidgets(self): #Grid Layout layout = Grid() layout.setColumnStretch(1, 9) layout.setColumnStretch(2, 9) layout.setColumnStretch(3, 9) layout.setColumnStretch(4, 9) layout.setColumnStretch(5, 9) layout.setColumnStretch(6, 9) layout.setColumnStretch(7, 9) layout.setColumnStretch(8, 9) layout.setColumnStretch(9, 9) layout.setRowStretch(0, 3) layout.setRowStretch(1, 11) layout.setRowStretch(2, 11) layout.setRowStretch(3, 11) layout.setRowStretch(4, 11) layout.setRowStretch(5, 11) layout.setRowStretch(5, 11) layout.setRowStretch(6, 11) layout.setRowStretch(7, 11) layout.setRowStretch(8, 11) layout.setRowStretch(9, 11) layout.setRowStretch(10, 11) layout.setRowStretch(11, 11) #End of Grid Layout self.main = QLbl("Tutorial Point Library Searcher") self.main.setStyleSheet( '''QLabel{font-size:30px;font-weight:bold;text-align:center;}''') layout.addWidget(self.main, 0, 4, 1, 4) #Category Widget self.cbox = CBox() self.cbox.setGeometry(80, 10, 60, 10) self.cbox.view().setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.cbox.view().setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.cbox.view().setAutoScroll(True) self.cbox.addItem("--Select--") for i in list_files: self.cbox.addItem(i) self.category = QLbl("Category") layout.addWidget(self.category, 2, 4, 1, 1) layout.addWidget(self.cbox, 2, 5, 1, 1) self.cbox.currentIndexChanged.connect(self.Selector) #End of Category Widget #Sub Category Widget self.scbox = CBox() #self.scbox.setGeometry(80,10,60,10) self.scbox.view().setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.scbox.view().setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.scbox.view().setAutoScroll(True) self.subcategory = QLbl("Sub Category") self.scbox.addItem("--Select--") layout.addWidget(self.subcategory, 4, 4, 1, 1) layout.addWidget(self.scbox, 4, 5, 1, 1) #End of Sub Category Widget #StatusBar Widget self.statusBar = QStat() self.statusBar.showMessage(datetime.date.today().strftime("%d %b %Y")) self.statusBar.setStyleSheet( '''QStatusBar{padding-left:50%;background-color:blue;color:white;font-weight:16px;text-align:center;}''' ) layout.addWidget(self.statusBar, 11, 0, 1, 10) #End of StatusBar Widget #Go Button self.go = QBtn("Go") layout.addWidget(self.go, 6, 5, 1, 1) self.go.setStyleSheet( '''QPushButton{color:white;background-color:green;}''') self.go.clicked.connect(self.Clicked) #End of Go Button self.setLayout(layout)
class Dimili(QMainWindow): def baslat(self, anaPencere): anaPencere.resize(600, 400) anaPencere.setWindowTitle("Dimili-Türkçe Sözlük") anaPencere.setFixedSize(600,400) icon =QIcon() icon.addPixmap(QPixmap("Dictionary.png"),QIcon.Normal,QIcon.Off) anaPencere.setWindowIcon(icon) zemin=QWidget(anaPencere) zemin.setGeometry(QRect(0,30,600,390)) zemin.setStyleSheet("background-color:rgb(167, 196, 233);") self.araKutu = QLineEdit(anaPencere) self.araKutu.setGeometry(QRect(10, 80, 200, 20)) self.araKutu.textChanged.connect(self.benzerKelimeler) self.kelimeGir = QLabel("Kelimeler:",anaPencere) self.kelimeGir.setGeometry(QRect(10, 110, 141, 21)) self.kelimeGor = QLabel("Kelime Ara",anaPencere) self.kelimeGor.setGeometry(QRect(10, 30, 91, 16)) self.harfGrup=QButtonGroup(anaPencere) aharf=QPushButton("â",anaPencere) aharf.setGeometry(QRect(10,50,25,25)) eharf=QPushButton("é",anaPencere) eharf.setGeometry(QRect(30,50,25,25)) self.DilGrup=QButtonGroup(anaPencere) self.Dil1 = QPushButton("Zazaca-Türkçe",anaPencere) self.Dil1.setGeometry(QRect(230, 80, 91, 23)) self.Dil1.setCheckable(True) self.Dil1.setAutoExclusive(True) self.Dil1.setChecked(True) self.Dil1.setStyleSheet("background-color: rgb(102, 255, 0);") self.Dil2 = QPushButton("Türkçe-Zazaca",anaPencere) self.Dil2.setGeometry(QRect(330, 80, 91, 23)) self.Dil2.setCheckable(True) self.Dil2.setAutoExclusive(True) self.Dil2.setStyleSheet("background-color: rgb(255, 94, 105);") self.DilGrup.addButton(self.Dil1,1) self.DilGrup.addButton(self.Dil2,2) self.DilGrup.buttonClicked[int].connect(self.dilSecme) self.kelimeListesi=QListWidget(anaPencere) self.kelimeListesi.setGeometry(QRect(10, 130, 191, 231)) self.kelimeListesi.itemClicked.connect(self.kelimeAcikla) self.kelimeAnlam = QLabel("Kelimenin Anlamı:",anaPencere) self.kelimeAnlam.setGeometry(QRect(230, 110, 131, 21)) self.cumleList1 = QListWidget(anaPencere) self.cumleList1.setGeometry(QRect(230, 130, 351, 51)) self.ornekCumle1 = QLabel("Örnek Zazaca Cümle:",anaPencere) self.ornekCumle1.setGeometry(QRect(230, 200, 101, 21)) self.cumleList2 = QListWidget(anaPencere) self.cumleList2.setGeometry(QRect(230, 220, 351, 51)) self.ornekCumle2 = QLabel("Örnek Türkçe Cümle:",anaPencere) self.ornekCumle2.setGeometry(QRect(230, 290, 111, 16)) self.cumleList3 = QListWidget(anaPencere) self.cumleList3.setGeometry(QRect(230, 310, 351, 51)) self.anaMenu = QMenuBar(anaPencere) self.anaMenu.setGeometry(QRect(0, 0, 600, 21)) self.menuDosya = QMenu("Dosya",self.anaMenu) self.menuDuzenle = QMenu("Düzenle",self.anaMenu) self.menuYardim = QMenu("Yardım",self.anaMenu) anaPencere.setMenuBar(self.anaMenu) self.durum = QStatusBar(zemin) anaPencere.setStatusBar(self.durum) self.durum.setStyleSheet("background-color:white") self.durum.showMessage("Hazır") self.cikis= QAction(QIcon("Exit.ico"),"&Çıkış",anaPencere) self.cikis.setShortcut("Ctrl+X") self.cikis.triggered.connect(anaPencere.close) self.actionHakkinda = QAction("Hakkında",anaPencere) self.actionHakkinda.triggered.connect(self.hakkinda) self.actionSecenekler = QAction("Seçenekler",anaPencere) self.menuDosya.addAction(self.cikis) self.menuDuzenle.addAction(self.actionSecenekler) self.menuYardim.addAction(self.actionHakkinda) self.anaMenu.addAction(self.menuDosya.menuAction()) self.anaMenu.addAction(self.menuDuzenle.menuAction()) self.anaMenu.addAction(self.menuYardim.menuAction()) def kelimeAcikla(self): if self.DilGrup.checkedId()==1: self.cumleList1.clear() self.cumleList2.clear() self.cumleList3.clear() itemtext= [str(x.text()) for x in self.kelimeListesi.selectedItems()] for it in itemtext: itemtext=it self.im.execute("select Tur from DimTur where Zazaca=?",[itemtext]) turliste=[tur[0] for tur in self.im.fetchall()] for tura in turliste: turliste=tura self.im.execute("select Turkce from DimTur where Zazaca=?",[itemtext]) turkAnlam=[tur[0] for tur in self.im.fetchall()] for tr in turkAnlam: self.cumleList1.addItem(itemtext+"("+turliste+")"+" : "+tr) self.im.execute("select OrnekZazacaCumle from DimTur where Zazaca=?",[itemtext]) ornekZaza=[zaza[0] for zaza in self.im.fetchall()] for za in ornekZaza: ornekZaza=za self.cumleList2.addItem(ornekZaza) self.im.execute("select OrnekTurkceCumle from DimTur where Zazaca=?",[itemtext]) ornekTurk=[turk[0] for turk in self.im.fetchall()] for orn in ornekTurk: ornekTurk=orn self.cumleList3.addItem(ornekTurk) if self.DilGrup.checkedId()==2: self.cumleList1.clear() self.cumleList2.clear() self.cumleList3.clear() itemtext= [str(x.text()) for x in self.kelimeListesi.selectedItems()] for it in itemtext: itemtext=it self.im.execute("select Tur from DimTur where Turkce=?",[itemtext]) turliste=[tur[0] for tur in self.im.fetchall()] for tura in turliste: turliste=tura self.im.execute("select Zazaca from DimTur where Turkce=?",[itemtext]) zazaAnlam=[tur[0] for tur in self.im.fetchall()] for tr in zazaAnlam: self.cumleList1.addItem(itemtext+"("+turliste+")"+" : "+tr) self.im.execute("select OrnekZazacaCumle from DimTur where Turkce=?",[itemtext]) ornekTurk=[turk[0] for turk in self.im.fetchall()] for orn in ornekTurk: ornekTurk=orn self.cumleList2.addItem(ornekTurk) self.im.execute("select OrnekTurkceCumle from DimTur where Turkce=?",[itemtext]) ornekZaza=[zaza[0] for zaza in self.im.fetchall()] for za in ornekZaza: ornekZaza=za self.cumleList3.addItem(ornekZaza) def benzerKelimeler(self): if self.DilGrup.checkedId()==1: self.VT=sqlite3.connect("DimiliVT.sqlite") self.im=self.VT.cursor() self.kelimeListesi.clear() kelime=self.araKutu.text() if kelime=="" or kelime==None: self.kelimeListesi.clear() else: self.im.execute("select Zazaca from DimTur where Zazaca like ? order by Zazaca ",[kelime+'%']) zazaListe=[za[0] for za in self.im.fetchall()] for i in zazaListe: self.kelimeListesi.addItem(i) if self.DilGrup.checkedId()==2: self.VT=sqlite3.connect("DimiliVT.sqlite") self.im=self.VT.cursor() kelime=self.araKutu.text() self.kelimeListesi.clear() if kelime=="" or kelime==None: self.kelimeListesi.clear() else: self.im.execute("select Turkce from DimTur where Turkce like ? ",[kelime+'%']) turkListe=[tu[0] for tu in self.im.fetchall()] for i in turkListe: self.kelimeListesi.addItem(i) def dilSecme(self,ind): if ind==1: self.araKutu.setText("") self.kelimeListesi.clear() self.cumleList1.clear() self.cumleList2.clear() self.cumleList3.clear() self.Dil1.setStyleSheet("background:#66FF00") self.Dil2.setStyleSheet("background-color:#E41841") if ind==2: self.araKutu.setText("") self.kelimeListesi.clear() self.cumleList1.clear() self.cumleList2.clear() self.cumleList3.clear() self.Dil2.setStyleSheet("background:#66FF00") self.Dil1.setStyleSheet("background-color:#E41841") def hakkinda(self): QMessageBox.about(self, "Program Hakkında", "Bu program <b>bla bla</b> tarafından programlanmıştır. 2015")
class convertWindow(QMainWindow): def __init__(self, parent=None): super(convertWindow, self).__init__(parent) self.colorSpaceIcon = QIcon( '/s/prodanim/ta/_sandbox/duda/tmp/colormanager.png') self.xSize = 1000 self.ySize = 375 self.startFrame = '1' self.endFrame = '2' self.InitUI() def InitUI(self): self.setWindowTitle('ImageConvert') self.centralWidget = QWidget() self.mainLayout = QGridLayout() self.centralWidget.setLayout(self.mainLayout) self.colorSpacesNames = self.findColorSpacesNames() self.statusBar = QStatusBar() self.statusBar.showMessage("What can I cook for you today " + _USER_ + " ?") self.statusBar.setStyleSheet("color : green") self.statusBar.setFont(QFont('Pilkius Romeus', 12)) self.setStatusBar(self.statusBar) # menubar self.bar = self.menuBar() self.fileBar = self.bar.addMenu("&File") self.quitAction = QAction('&Quit', self) self.quitAction.setShortcut("Ctrl+Q") self.quitAction.setStatusTip( 'Quit the program with some regrets but no remorse') self.quitAction.triggered.connect(qApp.quit) self.fileBar.addAction(self.quitAction) # button to do the convertion self.convertButton = QPushButton('convert') self.convertButton.setStyleSheet( "background-color: rgba(180,180,180,255)") #---------------------------Shot Group Box------------------------------ self.shotGroupBox = QGroupBox('convert') self.shotGroupBox.setCheckable(True) self.shotGroupBox.setAttribute(Qt.WA_StyledBackground, True) self.shotGroupBox.setStyleSheet( "QGroupBox{background-color: rgba(180,180,180,255);},QTGroupBox::QToolTip{ background-color: yellow; }" ) #self.shotGroupBox.setFixedSize(700, 250) self.shotLayout = QGridLayout(self.shotGroupBox) # Color space group Box self.colorSpaceCheckBox = QCheckBox('Use Color Spaces') self.colorSpaceCheckBox.setToolTip('use color space convertion') self.colorSpaceCheckBox.setIcon(self.colorSpaceIcon) self.colorSpaceCheckBox.setChecked(False) self.colorSpaceGroupBox = QGroupBox() self.colorSpaceGroupBox.setToolTip('choose the in/out color spaces') self.colorSpaceGroupBox.setAttribute(Qt.WA_StyledBackground, True) self.colorSpaceCheckBox.setStyleSheet( "QGroupBox{background-color: rgba(100,100,100,255);},QGroupBox::QToolTip{ background-color: yellow; }" ) self.colorSpaceGroupBox.setVisible(False) # self.colorSpaceGroupBox.setCheckable(True) # self.colorSpaceGroupBox.setChecked(False) self.colorSpaceLayout = QGridLayout(self.colorSpaceGroupBox) self.inColorSpaceComboBox = QComboBox() self.inColorSpaceComboBox.setFixedSize(120, 25) self.inColorSpaceComboBox.setToolTip('from color space') self.inColorSpaceComboBox.addItems(self.colorSpacesNames) self.inColorSpaceComboBox.setCurrentIndex(self.getColorSpace()) self.outColorSpaceComboBox = QComboBox() self.outColorSpaceComboBox.setFixedSize(120, 25) self.outColorSpaceComboBox.setToolTip('to color space') self.outColorSpaceComboBox.addItems(self.colorSpacesNames) self.outColorSpaceComboBox.setCurrentIndex(self.getColorSpace('srgb8')) self.inLabel = QLabel('in color space') self.outLabel = QLabel('out color space') self.choiceSpaceLabel = QLabel('conversion type') self.choiceSpaceComboBox = QComboBox() self.choiceSpaceComboBox.addItems(__CONVERTION_LIST__.keys()) self.choiceSpaceComboBox.setToolTip(__CONVERTION_LIST__[str( self.choiceSpaceComboBox.currentText())]) self.choiceSpaceComboBox.setFixedSize(170, 25) self.useOutSpaceName = QCheckBox('out space to name') self.useOutSpaceName.setToolTip( 'add the output color space to the name (useful for rv)') self.useOutSpaceName.setChecked(False) self.widgetSpace = QWidget() self.colorSpaceLayout.addWidget(self.choiceSpaceLabel, 0, 0) self.colorSpaceLayout.addWidget(self.inLabel, 0, 1) self.colorSpaceLayout.addWidget(self.outLabel, 0, 2) self.colorSpaceLayout.addWidget(self.choiceSpaceComboBox, 1, 0) self.colorSpaceLayout.addWidget(self.inColorSpaceComboBox, 1, 1) self.colorSpaceLayout.addWidget(self.outColorSpaceComboBox, 1, 2) self.colorSpaceLayout.addWidget(self.widgetSpace, 1, 3) self.colorSpaceLayout.addWidget(self.widgetSpace, 1, 4) self.colorSpaceLayout.addWidget(self.useOutSpaceName, 1, 5) self.inLabel.setVisible(False) self.outLabel.setVisible(False) self.inColorSpaceComboBox.setVisible(False) self.outColorSpaceComboBox.setVisible(False) # file in/out groupBox self.fileGroupBox = QGroupBox('file in/out') self.fileGroupBox.setToolTip('in/out setting') self.fileMainGridLayout = QGridLayout(self.fileGroupBox) # file type self.fileTypeLayout = QVBoxLayout() self.fileTypeCombo = QComboBox() self.fileTypeCombo.addItems(__FILE_TYPE__) self.fileTypeCombo.setFixedSize(105, 25) self.fileTypeCombo.setToolTip( 'type of image to import (i.e: single frame, sequence of frames, movie)' ) self.fileTypeLabel = QLabel('file type') self.fileTypeLayout.addWidget(self.fileTypeLabel) self.fileTypeLayout.addWidget(self.fileTypeCombo) # in self.fileInLayout = QGridLayout() self.fileInPushbutton = QPushButton('file in') self.fileInPushbutton.setToolTip('In file') self.fileInLineEdit = QLineEdit() self.fileInLineEdit.setMinimumSize(300, 25) self.fileInFormatLineEdit = QLineEdit() self.fileInFormatLineEdit.setToolTip('input format') self.fileInFormatLineEdit.setFixedSize(50, 25) self.fileInFormatLineEdit.setEnabled(False) self.fileInFormatLineEdit.setStyleSheet("color: green;") self.fileInFormatLabel = QLabel('in format') self.fileInLineEdit.setToolTip('image to convert from') self.fileInPadLabel = QLabel('in padding') self.fileInPadLabel.setEnabled(True) self.fileInPadLineEdit = QLineEdit() self.fileInPadLineEdit.setToolTip("number of frame to use as padding") self.fileInPadLineEdit.setFixedSize(25, 25) self.fileInPadLineEdit.setEnabled(False) self.fileInPadLineEdit.setStyleSheet("color: green;") self.fileInInputFrameLabel = QLabel('frames') self.fileInInputLineEdit = QLineEdit() self.fileInInputLineEdit.setFixedSize(100, 25) self.validator = QRegExpValidator(QRegExp("[0-9,-x]*")) self.fileInInputLineEdit.setValidator(self.validator) self.fileInInputLineEdit.setToolTip( 'frame to extract separated with a "," or "-"i.e: 20,30,40-50....') self.fileInAllCheckbox = QCheckBox('all') self.fileInAllCheckbox.setToolTip( 'convert all frames from sequence/movie') self.fileInLayout.addWidget(self.fileInPushbutton, 1, 0) self.fileInLayout.addWidget(self.fileInLineEdit, 1, 1) self.fileInLayout.addWidget(self.fileInFormatLabel, 0, 2) self.fileInLayout.addWidget(self.fileInFormatLineEdit, 1, 2) self.fileInLayout.addWidget(self.fileInInputFrameLabel, 0, 3) self.fileInLayout.addWidget(self.fileInInputLineEdit, 1, 3) self.fileInLayout.addWidget(self.fileInAllCheckbox, 1, 5) self.fileInLayout.addWidget(self.fileInPadLabel, 0, 6) self.fileInLayout.addWidget(self.fileInPadLineEdit, 1, 6) self.fileInInputFrameLabel.setVisible(False) self.fileInInputLineEdit.setVisible(False) self.fileInAllCheckbox.setVisible(False) self.fileInPadLabel.setVisible(False) self.fileInPadLineEdit.setVisible(False) #out self.fileOutLayout = QGridLayout() self.fileOutPushbutton = QPushButton('file out') self.fileOutPushbutton.setToolTip('Out Path') self.fileOutPathLabel = QLabel('out directory') self.fileOutLineEdit = QLineEdit() self.fileOutLineEdit.setMinimumSize(300, 25) self.fileOutLineEdit.setToolTip('image to convert to') self.fileOutFormatLabel = QLabel('out format') self.fileOutComboBox = QComboBox() self.fileOutComboBox.addItems(__FILE_FORMAT__) self.fileOutComboBox.setToolTip(('output format')) self.fileOutNameLineEdit = QLineEdit() self.fileOutNameLineEdit.setToolTip('name for output image(s)') self.fileOutNameLineEdit.setFixedSize(130, 25) self.fileOutNameLabel = QLabel('output name') self.fileOutPadLabel = QLabel('out padding') self.fileOutPadLineEdit = QLineEdit() self.fileOutPadLineEdit.setToolTip('out padding') self.fileOutPadLineEdit.setFixedSize(25, 25) self.fileOutPadCheck = QCheckBox('use padding') self.fileOutPadCheck.setToolTip('use padding for output') self.fileOutPadCheck.setChecked(False) self.fileOutLayout.addWidget(self.fileOutPushbutton, 1, 0) self.fileOutLayout.addWidget(self.fileOutLineEdit, 1, 1) self.fileOutLayout.addWidget(self.fileOutNameLineEdit, 1, 2) self.fileOutLayout.addWidget(self.fileOutComboBox, 1, 3) self.fileOutLayout.addWidget(self.fileOutPathLabel, 0, 1) self.fileOutLayout.addWidget(self.fileOutFormatLabel, 0, 3) self.fileOutLayout.addWidget(self.fileOutNameLabel, 0, 2) self.fileOutLayout.addWidget(self.fileOutPadLabel, 0, 4) self.fileOutLayout.addWidget(self.fileOutPadLineEdit, 1, 5) self.fileOutLayout.addWidget(self.fileOutPadCheck, 1, 4) self.fileOutPadLineEdit.setVisible(False) self.fileOutPadLabel.setVisible(False) self.fileOutPadCheck.setVisible(False) self.fileMainGridLayout.addLayout(self.fileTypeLayout, 0, 0) self.fileMainGridLayout.addLayout(self.fileInLayout, 1, 0) self.fileMainGridLayout.addLayout(self.fileOutLayout, 2, 0) self.shotLayout.addWidget(self.fileGroupBox, 0, 0) self.shotLayout.addWidget(self.colorSpaceCheckBox, 1, 0) self.shotLayout.addWidget(self.colorSpaceGroupBox, 2, 0) #----------------------end Shot Group Box-------------------------------- self.mainLayout.addWidget(self.shotGroupBox, 0, 0) self.mainLayout.addWidget(self.convertButton, 1, 0) self.setCentralWidget(self.centralWidget) self.setFixedSize(self.xSize, self.ySize) #self.colorSpaceGroupBox.toggled.connect(self.enableColorSpacesChoice) self.colorSpaceCheckBox.toggled.connect(self.displayColorSpace) self.fileInAllCheckbox.toggled.connect(self.setAllImages) self.fileInPushbutton.clicked.connect(self.findFile) self.fileOutPushbutton.clicked.connect(self.findDirectory) self.fileTypeCombo.currentTextChanged.connect(self.fileTypeChanged) self.choiceSpaceComboBox.currentTextChanged.connect( self.convertionChoice) self.fileOutPadCheck.toggled.connect(self.showOutPadding) self.convertButton.clicked.connect(self.convertImages) def showOutPadding(self, s): if s: self.fileOutPadLineEdit.setVisible(True) else: self.fileOutPadLineEdit.setVisible(False) def convertionChoice(self): self.choiceSpaceComboBox.setToolTip(__CONVERTION_LIST__[str( self.choiceSpaceComboBox.currentText())]) if self.choiceSpaceComboBox.currentText() == 'custom': self.inLabel.setVisible(True) self.outLabel.setVisible(True) self.inColorSpaceComboBox.setVisible(True) self.outColorSpaceComboBox.setVisible(True) self.widgetSpace.setVisible(False) else: self.inLabel.setVisible(False) self.outLabel.setVisible(False) self.inColorSpaceComboBox.setVisible(False) self.outColorSpaceComboBox.setVisible(False) self.widgetSpace.setVisible(True) def displayColorSpace(self, s): if s: self.setFixedSize(self.xSize, self.ySize + 80) self.colorSpaceGroupBox.setVisible(True) self.useOutSpaceName.setChecked(True) else: self.setFixedSize(self.xSize, self.ySize) self.colorSpaceGroupBox.setVisible(False) self.useOutSpaceName.setChecked(False) def setAllImages(self, s): if s: self.fileInInputLineEdit.setVisible(False) self.fileInInputFrameLabel.setVisible(False) else: self.fileInInputLineEdit.setVisible(True) self.fileInInputFrameLabel.setVisible(True) def fileTypeChanged(self): if self.fileTypeCombo.currentText() != __FILE_TYPE__[0]: #reset the lineEdit self.fileInLineEdit.setText('') self.fileOutLineEdit.setText('') self.fileOutNameLineEdit.setText('') self.fileInPadLineEdit.setText('') self.fileInFormatLineEdit.setText('') self.fileOutPadLineEdit.setText('') # change the size of combobox self.fileTypeCombo.setFixedSize(150, 25) # uncheck the all checkbox self.fileInAllCheckbox.setChecked(False) # reset the frame text self.fileInInputLineEdit.setText('') # reset the padding to invisible self.fileInPadLabel.setVisible(False) self.fileInPadLineEdit.setVisible(False) # set the line edit to be visible self.fileInInputFrameLabel.setVisible(True) self.fileInInputLineEdit.setVisible(True) self.fileInAllCheckbox.setVisible(True) self.fileOutPadLabel.setVisible(True) #self.fileOutPadLineEdit.setVisible(True) self.fileOutPadCheck.setVisible(True) if self.fileTypeCombo.currentText() == __FILE_TYPE__[1]: self.fileInPadLabel.setVisible(True) self.fileInPadLineEdit.setVisible(True) self.fileOutPadCheck.setVisible(False) else: # reset the lineEdit self.fileInLineEdit.setText('') self.fileOutLineEdit.setText('') self.fileOutNameLineEdit.setText('') self.fileInPadLineEdit.setText('') self.fileInFormatLineEdit.setText('') self.fileOutPadLineEdit.setText('') # change the size of combobox self.fileTypeCombo.setFixedSize(105, 25) self.fileInInputLineEdit.setText('') self.fileInAllCheckbox.setChecked(False) self.fileInInputFrameLabel.setVisible(False) self.fileInInputLineEdit.setVisible(False) self.fileInAllCheckbox.setVisible(False) self.fileInPadLabel.setVisible(False) self.fileInPadLineEdit.setVisible(False) self.fileOutPadLabel.setVisible(False) self.fileOutPadLineEdit.setVisible(False) self.fileOutPadCheck.setVisible(False) def getColorSpace(self, colorSpace='acescg'): #indexNb =0 try: indexNb = self.colorSpacesNames.index(colorSpace) except: return None else: return indexNb def enableColorSpacesChoice(self, s): if s: self.setFixedSize(self.xSize, 350) self.inColorSpaceComboBox.setEnabled(True) self.outColorSpaceComboBox.setEnabled(True) else: self.inColorSpaceComboBox.setEnabled(False) self.outColorSpaceComboBox.setEnabled(False) self.useOutSpaceName.setChecked(False) self.centralWidget.setFixedHeight(250) def findColorSpacesNames(self): config = ocio.GetCurrentConfig() colorSpaces = [cs.getName() for cs in config.getColorSpaces()] return colorSpaces def findDirectory(self): dirName = QFileDialog.getExistingDirectory(self, 'Open directory', '/s/prodanim/ta') self.fileOutLineEdit.setText(dirName + '/') def findFile(self): """dialog to open file of type .mov""" filename = '' splitFileName = '' self.startFrame = -1 self.endFrame = -1 if self.fileTypeCombo.currentText() == __FILE_TYPE__[0]: filename = QFileDialog.getOpenFileName( self, 'Open file', '/s/prodanim/ta', "Image files ( *.exr *.jpg *.png *.tif)") filename = str(filename[0]) # split the filename with the . splitFileName = filename.split('.') # set the format of the in file self.fileInFormatLineEdit.setText('.' + splitFileName[-1]) # pop the format and recreate the name splitFileName.pop(-1) pathFileName = filename[:filename.rfind('.')] # put the name without format in the in path self.fileInLineEdit.setText(pathFileName) nameframe = filename[filename.rfind('/') + 1:filename.rfind('.')] # find the path of the file and set the output with it path = filename[:filename.rfind('/')] self.fileOutLineEdit.setText(path + '/') # prefill the name of the output file nameLength = len(nameframe) self.fileOutNameLineEdit.setFixedSize(nameLength * 8, 25) self.fileOutNameLineEdit.setText(nameframe) # else if the type is sequence elif self.fileTypeCombo.currentText() == __FILE_TYPE__[1]: filename = QFileDialog.getOpenFileName( self, 'Open file', '/s/prodanim/ta', "Image files ( *.exr *.jpg *.png *.tif)") filename = str(filename[0]) splitFileName = filename.split('.') self.fileInFormatLineEdit.setText('.' + splitFileName[-1]) # get the path path = filename[:filename.rfind('/')] # extract the image name imageName = filename[filename.rfind('/') + 1:filename.rfind('.')] while imageName.rfind('.') != -1: imageName = imageName[:imageName.rfind('.')] # get all the file listAllFiles = [ f for f in os.listdir(path) if os.path.isfile(path + '/' + f) ] listFile = [] for i in range(len(listAllFiles)): if listAllFiles[i].rfind(imageName) == 0: listFile.append(listAllFiles[i]) # sort the file in croissant order if len(listFile) > 1: listFile.sort(key=lambda f: int(filter(str.isdigit, f))) # extract only number between .<number>. nbList = [] for nb in listFile: nbList.append(nb[nb.find('.') + 1:nb.rfind('.')]) if len(nbList) > 1: self.startFrame = str(int( nbList[0])) #str(int(filter(str.isdigit, listFile[0]))) self.endFrame = str(int( nbList[-1])) #str(int(filter(str.isdigit, listFile[-1]))) self.fileInInputLineEdit.setText(self.startFrame + '-' + self.endFrame) # extract the padding number pad = nbList[0] if pad == '' or len(pad) == 1: pad = '1' self.fileInPadLineEdit.setText(pad) self.fileInLineEdit.setText(path + '/' + imageName) else: pad.isdigit() self.fileInPadLineEdit.setText(str(len(pad))) self.fileInLineEdit.setText(path + '/' + imageName) self.fileOutNameLineEdit.setFixedSize(len(imageName) * 8, 25) self.fileOutNameLineEdit.setText(imageName) self.fileOutLineEdit.setText(path + '/') else: filename = QFileDialog.getOpenFileName( self, 'Open file', '/s/prodanim/ta', "Image files ( *.mov *.qt)") filename = str(filename[0]) splitFileName = filename.split('.') self.fileInFormatLineEdit.setText('.' + splitFileName[-1]) # get the path path = filename[:filename.rfind('/')] # extract the image name imageName = filename[filename.rfind('/') + 1:filename.rfind('.')] while imageName.rfind('.') != -1: imageName = imageName[:imageName.rfind('.')] # find the nb of subimages i.e end frame buf = oiio.ImageBuf(filename) self.endFrame = str(buf.nsubimages - 1) self.startFrame = '1' self.fileInInputLineEdit.setText(self.startFrame + '-' + self.endFrame) self.fileInLineEdit.setText(filename[:filename.rfind('.')]) # get the path path = filename[:filename.rfind('/')] # extract the image name imageName = filename[filename.rfind('/') + 1:filename.rfind('.')] self.fileOutNameLineEdit.setFixedSize(len(imageName) * 8, 25) self.fileOutNameLineEdit.setText(imageName) self.fileOutLineEdit.setText(path + '/') def convertImages(self): done = False QApplication.setOverrideCursor(Qt.WaitCursor) #__OIIOTOOL__ = 'rez env pyoiio -- oiiotool -v ' __OIIOTOOL__ = 'oiiotool -v ' # find if there is a path in the line edit if self.fileInLineEdit.text() == '': print('no image to convert') else: inSpace = '' outSpace = '' inFrame = str(self.fileInLineEdit.text() + self.fileInFormatLineEdit.text()) outFrame = str(self.fileOutLineEdit.text() + self.fileOutNameLineEdit.text() + '.' + self.fileOutComboBox.currentText()) # if convert color on if self.colorSpaceCheckBox.isChecked(): if self.choiceSpaceComboBox.currentText() != 'custom': choice = str(self.choiceSpaceComboBox.currentText()) inSpace = choice[:choice.find('-')] outSpace = choice[choice.rfind('>') + 1:] else: inSpace = str(self.inColorSpaceComboBox.currentText()) outSpace = str(self.outColorSpaceComboBox.currentText()) # if image mode if self.fileTypeCombo.currentText() == __FILE_TYPE__[0]: if self.useOutSpaceName.isChecked(): outFrame = str(self.fileOutLineEdit.text() + outSpace + '_' + self.fileOutNameLineEdit.text() + '.' + self.fileOutComboBox.currentText()) else: outFrame = str(self.fileOutLineEdit.text() + self.fileOutNameLineEdit.text() + '.' + self.fileOutComboBox.currentText()) if self.colorSpaceCheckBox.isChecked(): __OIIOTOOL__ += inFrame + ' --colorconvert ' + inSpace + ' ' + outSpace + ' -o ' + outFrame os.system(__OIIOTOOL__) else: __OIIOTOOL__ += inFrame + ' -o ' + outFrame os.system(__OIIOTOOL__) done = True # image mode is seqences elif self.fileTypeCombo.currentText() == __FILE_TYPE__[1]: pad = '%0' + str(self.fileInPadLineEdit.text()) + 'd' if self.fileInAllCheckbox.isChecked(): inFrameNb = self.startFrame outFrameNb = self.endFrame frameRange = '.' + inFrameNb + '-' + outFrameNb + pad inFrame = self.fileInLineEdit.text( ) + frameRange + self.fileInFormatLineEdit.text() if self.useOutSpaceName.isChecked(): outFrame = str(self.fileOutLineEdit.text() + outSpace + '_' + self.fileOutNameLineEdit.text() + frameRange + '.' + self.fileOutComboBox.currentText()) else: outFrame = str(self.fileOutLineEdit.text() + self.fileOutNameLineEdit.text() + frameRange + '.' + self.fileOutComboBox.currentText()) if self.colorSpaceCheckBox.isChecked(): __OIIOTOOL__ += inFrame + ' --colorconvert ' + inSpace + ' ' + outSpace + ' -o ' + outFrame os.system(__OIIOTOOL__) else: __OIIOTOOL__ += inFrame + ' -o ' + outFrame os.system(__OIIOTOOL__) else: frameRange = ' --frames ' + str( self.fileInInputLineEdit.text()) + ' ' inFrame = frameRange + self.fileInLineEdit.text( ) + '.' + pad + self.fileInFormatLineEdit.text() if self.useOutSpaceName.isChecked(): outFrame = str(self.fileOutLineEdit.text() + outSpace + '_' + self.fileOutNameLineEdit.text() + '.' + pad + '.' + self.fileOutComboBox.currentText()) else: outFrame = str(self.fileOutLineEdit.text() + self.fileOutNameLineEdit.text() + '.' + pad + '.' + self.fileOutComboBox.currentText()) if self.colorSpaceCheckBox.isChecked(): __OIIOTOOL__ += inFrame + ' --colorconvert ' + inSpace + ' ' + outSpace + ' -o ' + outFrame os.system(__OIIOTOOL__) else: __OIIOTOOL__ += inFrame + ' -o ' + outFrame os.system(__OIIOTOOL__) done = True elif self.fileTypeCombo.currentText() == __FILE_TYPE__[2]: inFrame = self.fileInLineEdit.text( ) + self.fileInFormatLineEdit.text() pad = '' goodListFrame = [] if self.fileOutPadCheck.isChecked(): pad = self.fileOutPadLineEdit.text() if pad == '': pad = '0' else: pad = '0' pad = '%0' + pad + 'd' if self.useOutSpaceName.isChecked(): outFrame = str(self.fileOutLineEdit.text() + outSpace + '_' + self.fileOutNameLineEdit.text() + '.' + pad + '.' + self.fileOutComboBox.currentText()) else: outFrame = str(self.fileOutLineEdit.text() + self.fileOutNameLineEdit.text() + '.' + pad + '.' + self.fileOutComboBox.currentText()) if self.fileInAllCheckbox.isChecked(): inFrameNb = self.startFrame outFrameNb = self.endFrame for i in range(int(inFrameNb), int(outFrameNb) + 1): goodListFrame.append(str(i)) goodListFrame.sort( key=lambda f: int(filter(str.isdigit, f))) # for fn in goodListFrame: # if self.colorSpaceCheckBox.isChecked(): # __OIIOTOOL__ = 'rez env pyoiio -- oiiotool -v ' + inFrame + ' --frames ' + str(fn) + ' --subimage ' + str(fn) + ' --colorconvert ' + inSpace + ' ' + outSpace + ' -o ' + outFrame # print(__OIIOTOOL__) # else: # __OIIOTOOL__= 'rez env pyoiio -- oiiotool -v ' + inFrame + ' --frames ' + str(fn) + ' --subimage ' + str(fn) +' -o ' + outFrame # print(__OIIOTOOL__) else: # split the input in fucntion of ',' listFrame = str(self.fileInInputLineEdit.text()).split(',') # take care of the item with '-' and add the range to the list for i in range(0, len(listFrame)): if listFrame[i].find('-') > 0: group = listFrame[i] start = group[:group.find('-')] end = group[group.find('-') + 1:] for j in range(int(start), int(end) + 1): listFrame.append(str(j)) # get rid of elements with '-' goodListFrame = [] for i in listFrame: if i.find('-') < 0: goodListFrame.append(i) # get rid of duplicate goodListFrame = list(dict.fromkeys(goodListFrame)) # sort the list in croissant order goodListFrame.sort( key=lambda f: int(filter(str.isdigit, f))) for fn in goodListFrame: if self.colorSpaceCheckBox.isChecked(): __OIIOTOOL__ = 'oiiotool -v ' + inFrame + ' --frames ' + str( fn ) + ' --subimage ' + str( fn ) + ' --colorconvert ' + inSpace + ' ' + outSpace + ' -o ' + outFrame os.system(__OIIOTOOL__) else: __OIIOTOOL__ = 'oiiotool -v ' + inFrame + ' --frames ' + str( fn) + ' --subimage ' + str(fn) + ' -o ' + outFrame os.system(__OIIOTOOL__) done = True if done: QApplication.restoreOverrideCursor() print("you're images are cooked enjoy with no moderation")
class MainWidget(QWidget): """Виджет главного окна (включает добавление одежды и генерацию образа)""" def __init__(self, parent): super().__init__(parent=parent) uic.loadUi('widget.ui', self) self.setGeometry(0, 55, 572, 541) self.InitUi() self.type_clothes = [ self.radioButton, self.radioButton_2, self.radioButton_3, self.radioButton_4 ] self.radioButton.setChecked(True) self.weather_season = [ self.radioButton_6, self.radioButton_7, self.radioButton_8, self.radioButton_21 ] self.radioButton_21.setChecked(True) def InitUi(self): self.btn_add_photo.setStyleSheet(ANIMATION_BTN) self.btn_add_photo.clicked.connect(self.add_photo) self.btn_add_clothes.clicked.connect(self.add_clothes_to_db) self.connect_to_db = sqlite3.connect('wardrobe.sqlite') dict_clothes = get_dict_clothes(self.connect_to_db, self.parent().user_id) self.dict_clothes = {} for garment in dict_clothes: self.dict_clothes[garment[1]] = self.dict_clothes.get( garment[1], {}) self.dict_clothes[garment[1]][garment[2]] = self.dict_clothes[garment[1]].get(garment[2], []) + \ [(garment[0], garment[3], garment[4])] self.status = QStatusBar(self.parent()) self.status.move(0, 585) self.status.resize(220, 30) self.pushButton_look.clicked.connect(self.change_widget) self.pushButton_adding.clicked.connect(self.change_widget) self.current_index_widget = 1 self.months = { "01": "Winter", "02": "Winter", "03": "Spring", "04": "Spring", "05": "Spring", "06": "Summer", "07": "Summer", "08": "Summer", "09": "Autumn", "10": "Autumn", "11": "Autumn", "12": "Winter", } self.btn_generate.clicked.connect(self.generate_look_today) self.img_outwear.hide() self.img_underwear.hide() self.img_footwear.hide() self.img_jackets.hide() self.label_10.hide() self.label_11.hide() self.label_12.hide() self.label_13.hide() """Убрать потом""" self.shadow = QGraphicsDropShadowEffect() self.shadow.setBlurRadius(40) self.shadow.setXOffset(4) self.shadow.setYOffset(9) self.shadow.setColor(QColor(0, 0, 0, 30)) self.widget.setGraphicsEffect(self.shadow) self.make_shadow() self.img_outwear.setGraphicsEffect(self.shadow) self.make_shadow() self.img_underwear.setGraphicsEffect(self.shadow) self.make_shadow() self.img_footwear.setGraphicsEffect(self.shadow) self.make_shadow() self.img_jackets.setGraphicsEffect(self.shadow) "0 2px 7px 0 rgba(10,10,10,.05), 3px 27px 54px -34px rgba(0,0,0,.47)" def make_shadow(self): self.shadow = QGraphicsDropShadowEffect() self.shadow.setBlurRadius(25) self.shadow.setXOffset(3) self.shadow.setYOffset(8) self.shadow.setColor(QColor(0, 0, 0, 18)) def change_widget(self): """Смена виджетов (добавление одежды и генерация)""" self.stackedWidget.setCurrentIndex(self.current_index_widget) if self.current_index_widget == 0: self.current_index_widget = 1 else: self.current_index_widget = 0 def change_status(self, msg, color): self.status.setStyleSheet("color: " + color + ";") self.status.showMessage(msg) def add_photo(self): self.fname = QFileDialog.getOpenFileName(self, 'Выбрать фото', '')[0] def find_middle_color_img(self, fname): im = Image.open(fname) pixels = im.load() x, y = im.size rgb = (0, 0, 0) for i in range(x): for j in range(y): now_rgb = pixels[i, j] rgb = [elem + now_rgb[i] for i, elem in enumerate(rgb)] return f"{rgb[0] // (x * y)}, {rgb[1] // (x * y)}, {rgb[2] // (x * y)}" def read_image(self, filename): try: fin = open(filename, "rb") img = fin.read() return img except IOError as e: print("Error %d: %s" % (e.args[0], e.args[1])) sys.exit(1) finally: if fin: fin.close() def add_clothes_to_db(self): """Главная функция добавления одежды""" if self.check_error_in_forms_add_clothes(): text_type_clothes = list( filter(lambda radiobtn: radiobtn.isChecked(), self.type_clothes))[0].text() text_weather_season = list( filter(lambda radiobtn: radiobtn.isChecked(), self.weather_season))[0].text() name_clothes = self.line_name_clothes.text() medium_color_img = self.find_middle_color_img(self.fname) img_for_db = sqlite3.Binary(self.read_image(self.fname)) cur = self.connect_to_db.cursor() userid = self.parent().user_id cur.execute( "INSERT INTO clothes(photo, weather, type, mediumcolor, name, userid) " "VALUES (?, ?, ?, ?, ?, ?)", ( img_for_db, text_weather_season, text_type_clothes, medium_color_img, name_clothes, userid, )) self.connect_to_db.commit() self.line_name_clothes.setText("") self.add_cache(text_weather_season, text_type_clothes, medium_color_img, name_clothes, img_for_db) self.change_status("Successful", "green") def add_cache(self, weather, type, medium_color, name_clothes, img_for_db): """Добавление кэша(вызывается функцией add_clothes_to_db)""" cur = self.connect_to_db.cursor() id_clothes = cur.execute("SELECT id from clothes").fetchall() id_clothes.sort(key=lambda x: x[0]) self.dict_clothes[weather] = self.dict_clothes.get(weather, {}) self.dict_clothes[weather][type] = self.dict_clothes[weather].get( type, []) + [(id_clothes[-1][0], medium_color, name_clothes)] with open(PATH_FOLDER_PHOTO + str(id_clothes[-1][0]) + '.jpg', 'tw', encoding='utf-8') as f: pass f = open(PATH_FOLDER_PHOTO + str(id_clothes[-1][0]) + '.jpg', "wb") f.write(img_for_db) def check_error_in_forms_add_clothes(self): if self.line_name_clothes.text() == "": self.change_status("Name is not filled", "red") return False try: if self.fname: pass except AttributeError: self.change_status("Photo is not filled", "red") return False self.parent().statusBar().showMessage("") return True def generate_look_today(self): """Главная функция генерации образа""" self.show_and_hide_elem_clothes() self.label_not_selected.hide() month = self.months[dt.datetime.now().strftime("%m")] weather_clothes = self.dict_clothes.get(month, False) if not (weather_clothes): self.status.setStyleSheet("color: red;") self.status.showMessage("No suitable clothes") return False self.outerwear_clothes = weather_clothes.get("Outwear", False) self.underwear_clothes = weather_clothes.get("Underwear", False) self.footwear_clothes = weather_clothes.get("Footwear", False) self.jackets_and_coat_clothes = weather_clothes.get( "Jackets, coat", False) if self.check_existence_required_types_clothing(): if self.footwear_clothes and self.jackets_and_coat_clothes: self.display_сlothes_in_widget( ("outwear", choice(self.outerwear_clothes)), ("underwear", choice(self.underwear_clothes)), ("footwear", choice(self.footwear_clothes)), ("jackets", choice(self.jackets_and_coat_clothes))) elif self.footwear_clothes: self.display_сlothes_in_widget( ("outwear", choice(self.outerwear_clothes)), ("underwear", choice(self.underwear_clothes)), ("footwear", choice(self.footwear_clothes))) elif self.jackets_and_coat_clothes: self.display_сlothes_in_widget( ("outwear", choice(self.outerwear_clothes)), ("underwear", choice(self.underwear_clothes)), ("jackets", choice(self.jackets_and_coat_clothes))) else: self.display_сlothes_in_widget( ("outwear", choice(self.outerwear_clothes)), ("underwear", choice(self.underwear_clothes))) def show_and_hide_elem_clothes(self): """Функция, показывающая карточки одежды при нажатии на кнопку для генерации""" self.label_not_selected.hide() self.img_outwear.show() self.img_underwear.show() self.img_footwear.show() self.img_jackets.show() self.label_10.show() self.label_11.show() self.label_12.show() self.label_13.show() def check_existence_required_types_clothing(self): if not (self.outerwear_clothes) or not (self.underwear_clothes): self.change_status("Not clothes for generate look", "red") return False elif not (self.footwear_clothes): self.change_status("Genered imperfect look", "yellow") return True return True def display_сlothes_in_widget(self, *clothes): """Функия, заполняющая карточки изображением и текстом""" for thing in clothes: self.now_pixmap_clothes = self.create_pixmap_clothes(thing[1][0]) if thing[0] == "outwear": self.img_outwear.setPixmap(self.now_pixmap_clothes) self.label_name_outwear.setText(thing[1][2].title()) if thing[0] == "underwear": self.img_underwear.setPixmap(self.now_pixmap_clothes) self.label_name_underwear.setText(thing[1][2].title()) if thing[0] == "footwear": self.img_footwear.setPixmap(self.now_pixmap_clothes) self.label_name_footwear.setText(thing[1][2].title()) if thing[0] == "jackets": self.img_jackets.setPixmap(self.now_pixmap_clothes) self.label_name_jackets.setText(thing[1][2].title()) def create_pixmap_clothes(self, clothes_id: int): self.pixmap = QPixmap(PATH_FOLDER_PHOTO + str(clothes_id) + ".jpg") return self.pixmap.scaled(self.img_outwear.size().width() + 20, self.img_outwear.size().height() - 40)
class InterfaceLogin(AuxWidgets): """ Classe responsável pela criação da interface gráfica da área de login e \ toda configuração que é feita nela. """ def __init__(self) -> None: """[Método Especial] Construtor da classe: Cria os atributos da classe.""" self.root = QWidget() # [Atributo] Widget central: onde vai ser colocado os objetos def __del__(self) -> None: """[Método Especial] Destrutor da classe: Deleta os atributos.""" self.root = None del self.root # Deleta o atributo def setupUi(self, janela_:QMainWindow) -> None: """[Método] Criação da interface""" janela_.resize(200, 145) # Define a altura da jenela janela_.setFixedSize(200, 145) # Deixa como tamanho fixado (não pode mexer nas dimensões da janela) janela_.setCentralWidget(self.root) # Define como widget central janela_.setWindowTitle("LG Login Gados") # Título da janela self.statusbar = QStatusBar(janela_) # Cria uma barra de status janela_.setStatusBar(self.statusbar) # Add na janela ## Nome lblNome = self.lbl("NOME", 17, 10, 47, 20, self.root) # Texto: "Nome" self.entNome = self.lineEdit(70, 10, 113, 20, self.root) # Entrada de texto do nome self.entNome.setMaxLength(10) ## Ip lblIp = self.lbl("IP", 17, 40, 47, 20, self.root) # Texto: "Ip" self.entIp = self.lineEdit(70, 40, 113, 20, self.root) # Entrada de texto do ip self.entIp.setMaxLength(15) ## Porta lblPorta = self.lbl("PORTA", 17, 70, 47, 20, self.root) # Texto: "Porta" self.entPorta = self.lineEdit(70, 70, 113, 20, self.root) # Entrada de texto da porta self.entPorta.setMaxLength(5) self.bt = self.bts("Conectar", 109, 100, 75, 23, self.root) # Botão conectar lblIp = lblNome = lblPorta = None del lblIp, lblNome, lblPorta # Deleta os textos (não vão mais ser usados) def veri(self, t_:int) -> bool: """[Método] Verifica se as entradas inseridas são válidas""" # Se tiver algum campo vazio if (0 in [len(self.entNome.text()), len(self.entIp.text()), len(self.entPorta.text())]): self.setTextStatusBar("Não pode ter espaço em branco", t_) # Mostra pro usuário o erro self.limpaAll() # Limpas as caixas de entradas return False # Se a porta não for numerica if (not self.entPorta.text().isnumeric()): self.setTextStatusBar("Porta inválida", t_) # Mostra pro usuário o erro return False # Se for um usuario do tipo arquivo não pode entrar if (self.entNome == "::file:"): self.setTextStatusBar("Nome de usuário inválido", t_) # Mostra pro usuário o erro return False return True def limpaAll(self) -> None: """[Método] Limpa as caixas de entrada de texto""" self.entNome.clear() self.entIp.clear() self.entPorta.clear() #### POO-ENCAPSULAMENTOS #### def setTextStatusBar(self, s_:str, t_:int): """[Método Especial] Define o texto da barra de status.""" self.statusbar.showMessage(s_, t_) self.statusbar.setStyleSheet("QStatusBar{background: red}") def getDadosConexao(self) -> tuple: """[Método Especial] Retorna os dados necessários para fazer uma conexão com o servidor.""" return (self.entIp.text(), int(self.entPorta.text())) def getDados(self) -> list: """[Método Especial] Retorna os dados inseridos""" return [self.entNome.text(), self.entIp.text(), int(self.entPorta.text())] def setBtAction(self, func_) -> None: """[Método Especial] Define a ação do botão \"conectar\"""" self.bt.clicked.connect(func_) # Define a ação do botão enter da caixa de entrada
class Player(QWidget): """Sub-class of QWidget""" def __init__(self, parent=None, *args, **kwargs): """Initialize class attributes""" super(Player, self).__init__(parent, *args, **kwargs) self.init_ui() def init_ui(self): """Create local components""" # loop self.loop = False # time label text self.time_text = '{:0>2d}:{:0>2d}:{:0>2d}/{:0>2d}:{:0>2d}:{:0>2d}' self.hours = self.minutes = self.seconds = 0 # create media player object self.mediaPlayer = QMediaPlayer(self, QMediaPlayer.VideoSurface) # create videowidget object self.videoWidget = QVideoWidget() # create open button self.btn_size = QSize(16, 16) openButton = Button("Open") openButton.setToolTip("Open Media File") openButton.setStatusTip("Open Media File") openButton.setFixedHeight(24) openButton.setIconSize(self.btn_size) openButton.setIcon( QIcon.fromTheme("document-open", QIcon("Icons/Open.bmp"))) # openButton.setStyleSheet("background-color: #B0C4DE") openButton.clicked.connect(self.abrir) # create play button self.playButton = Button() self.playButton.setEnabled(False) self.playButton.setFixedHeight(24) self.playButton.setIconSize(self.btn_size) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) # self.playButton.setStyleSheet("background-color: #B0C4DE") self.playButton.clicked.connect(self.play) # create slider self.positionSlider = PositionSlider(self.mediaPlayer, Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.setObjectName("positionSlider") # create status bar self.statusBar = QStatusBar() self.statusBar.setFont(QFont("Noto sans", 8)) self.statusBar.setFixedHeight(14) self.statusBar.setStyleSheet('color:#ffffff') # create duration time label self.durationLabel = QLabel() self.durationLabel.setStyleSheet( 'background-color:rgba(255, 255, 255, 0)') self.durationLabel.setText('00:00:00/00:00:00') # create hbox layout controlLayoutWidget = QWidget(self) controlLayout = QHBoxLayout(controlLayoutWidget) controlLayoutWidget.setLayout(controlLayout) controlLayout.setContentsMargins(2, 2, 2, 2) # set widgets to the hbox layout controlLayout.addWidget(openButton) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.positionSlider) controlLayout.addWidget(self.durationLabel) # change hbox color controlLayoutWidget.setStyleSheet( 'background-color:rgba(255, 255, 255, 50)') controlLayoutWidget.setWindowOpacity(0.1) # create vbox layout self.layout = QVBoxLayout() self.layout.setSpacing(0) # set widgets to vbox layout self.layout.addWidget(self.videoWidget) self.layout.addWidget(controlLayoutWidget) self.sub_controls() self.layout.addWidget(self.statusBar) self.setLayout(self.layout) self.mediaPlayer.setVideoOutput(self.videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) self.statusBar.showMessage('{:->33s}{:-<33s}'.format("Have Fun", "")) self.key_bindings() def key_bindings(self): # bind Keys to methods self.onplaypause = self.create_shortcut(Qt.Key_Space, self.videoWidget, self.play) # Space key for self.on_fscreen = self.create_shortcut( Qt.Key_F, self.videoWidget, self.toggle_fullscreen) # F key for fullscreen on self.onforward = self.create_shortcut( Qt.Key_Right, self.videoWidget, self.forward) # Right key for forward self.redvolume = self.create_shortcut( Qt.Key_Down, self.videoWidget, self.red_volume) # Down key reduce volume self.incvolume = self.create_shortcut( Qt.Key_Up, self.videoWidget, self.inc_volume) # Up key increase volume self.onsetloop = self.create_shortcut( "L", self.videoWidget, # L key for repeat on, (lambda self=self: self.repeat.toggle() or self.play_again())) self.onrewind = self.create_shortcut( Qt.Key_Left, self.videoWidget, self.rewind) # Left key for rewind self.volmute = self.create_shortcut(Qt.Key_M, self.videoWidget, self.mute) # M for mute and unmute self.onopen = self.create_shortcut('Ctrl+O', self.videoWidget, self.abrir) # Ctrl+O for open self.onstop = self.create_shortcut(Qt.Key_S, self.videoWidget, self.stop_media) # S key for stop def create_shortcut(self, sequence, widget, obj): """generate key shortcuts""" return QShortcut(QKeySequence(sequence), widget, obj, context=Qt.ApplicationShortcut) def sub_controls(self): """Repeat, volume, and mute controls""" # repeat button self.repeat = Button() self.repeat.setCheckable(True) self.repeat.toggle() self.repeat.setIconSize(self.btn_size) self.repeat.setFixedHeight(24) self.repeat.setFixedWidth(26) self.repeat.setToolTip("repeat") self.repeat.setStatusTip("repeat") # Icons to correspond with button state icon = QIcon() icon.addPixmap(QPixmap(os.path.join(FOLDER, "Icons/repeat(1).png")), QIcon.Normal, QIcon.On) icon.addPixmap(QPixmap(os.path.join(FOLDER, "Icons/repeat(2).png")), QIcon.Active) self.repeat.setIcon(icon) # self.repeat.setStyleSheet("background-color: #B0C4DE; margin: 0px 0px 0px 2px;") self.repeat.clicked.connect(self.play_again) # stop button self.stop = Button() self.stop.setIconSize(self.btn_size) self.stop.setFixedHeight(24) self.stop.setFixedWidth(26) self.stop.setToolTip("Stop playing media") self.stop.setStatusTip("Stop playing media") self.stop.setIcon(self.style().standardIcon(QStyle.SP_MediaStop)) # self.stop.setStyleSheet("background-color: #B0C4DE; margin: 0px 0px 0px 2px;") self.stop.clicked.connect(self.stop_media) # volume slider self.volumeSlider = VolumeSlider(self.mediaPlayer, Qt.Horizontal) self.volumeSlider.setRange(0, 100) self.volumeSlider.setFixedWidth(200) self.mediaPlayer.setVolume(50) self.volumeSlider.sliderMoved.connect(self.set_volume) # volume button self.volume = Button(self) self.volume.setIconSize(self.btn_size) self.volume.setFixedHeight(24) self.volume.setFixedWidth(26) self.volume.setToolTip("Mute or Unmute") self.volume.setStatusTip("Mute or Unmute") self.volume.setIcon(self.style().standardIcon(QStyle.SP_MediaVolume)) # self.volume.setStyleSheet("background-color: #B0C4DE; margin: 0px 0px 0px 2px;") self.volume.clicked.connect(self.mute) # create control widget subControlWidget = QWidget(self) subControlWidget.setStyleSheet( 'background-color:rgba(255, 255, 255, 30)') # create Horizontal Layout subControlLayout = QHBoxLayout(subControlWidget) subControlLayout.setContentsMargins(0, 0, 0, 0) subControlLayout.addWidget(self.repeat, 0, Qt.AlignLeft) subControlLayout.addWidget(self.stop, 1, Qt.AlignLeft) # sub layout for volume control self.sub_layout = QHBoxLayout() self.sub_layout.addWidget(self.volume) self.sub_layout.addWidget(self.volumeSlider) subControlLayout.addLayout(self.sub_layout) subControlLayout.setContentsMargins(2, 2, 2, 2) self.layout.addWidget(subControlWidget) def abrir(self, event=None, url=None): """" Equivalent to open for most GUIs""" fileName = None if self.videoWidget.isFullScreen(): self.toggle_fullscreen() if not url: fileName, _ = QFileDialog.getOpenFileName(self, "Select media") if fileName: self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) else: self.mediaPlayer.setMedia(QMediaContent(QUrl(url))) if url or fileName: self.volumeSlider.setValue(self.mediaPlayer.volume()) self.playButton.setEnabled(True) self.statusBar.showMessage((fileName or url)) if not self.loop: self.play() def play(self): """Start media player""" if self.playButton.isEnabled(): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): """Callback for media player state change""" if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) if state == QMediaPlayer.StoppedState and self.loop: self.play() def positionChanged(self, position): """Callback for media player position change""" if self.mediaPlayer.state() == QMediaPlayer.StoppedState: position = 0 self.positionSlider.setValue(position) hours, position = position // 3600000, position % 3600000 minutes, position = position // 60000, position % 60000 seconds = position // 1000 self.durationLabel.setText( self.time_text.format(hours, minutes, seconds, self.hours, self.minutes, self.seconds)) def durationChanged(self, duration): """Callback for media player duration of media change""" self.positionSlider.setRange(0, duration) self.hours, duration = duration // 3600000, duration % 3600000 self.minutes, duration = duration // 60000, duration % 60000 self.seconds = duration // 1000 self.durationLabel.setText( self.time_text.format(0, 0, 0, self.hours, self.minutes, self.seconds)) def setPosition(self, position): """set media player play position""" self.mediaPlayer.setPosition(position) def handleError(self): """Callback for multiplayer errors""" self.playButton.setEnabled(False) self.statusBar.showMessage("Error: " + self.mediaPlayer.errorString()) def play_again(self): """Set repeat on or off""" self.loop = not self.loop def stop_media(self): """Callback for stop button""" if self.loop: self.loop = False self.repeat.toggle() self.mediaPlayer.stop() def toggle_fullscreen(self): """Toggle in or out of fullscreen mode""" self.videoWidget.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) if self.videoWidget.isFullScreen(): self.videoWidget.setFullScreen(False) self.videoWidget.setWindowState(Qt.WindowNoState) self.videoWidget.setParent(self) self.layout.insertWidget(0, self.videoWidget) self.videoWidget.showNormal() self.show() else: self.videoWidget.setFullScreen(True) self.hide() def rewind(self, lapse=2500): """Rewind the current media file by 1 second""" new_position = self.mediaPlayer.position() - lapse self.setPosition(new_position) def forward(self, lapse=2500): """Forward media file by 1 second""" new_position = self.mediaPlayer.position() + lapse self.setPosition(new_position) def set_volume(self, vol=0): """Set media player volume volume""" if vol: self.mediaPlayer.setVolume(vol) def red_volume(self, vol=1): """Reduce volume by a factor of 0.01""" volume = self.mediaPlayer.volume() if volume >= 0: new_volume = volume - 1 self.volumeSlider.setValue(new_volume) self.set_volume(new_volume) def inc_volume(self, vol=1): """Increase volume by a factor of 0.01""" volume = self.mediaPlayer.volume() if self.mediaPlayer.isMuted(): self.mediaPlayer.setMuted(False) self.volume.setIcon(self.style().standardIcon( QStyle.SP_MediaVolume)) if volume <= 100: new_volume = volume + 1 self.volumeSlider.setValue(new_volume) self.set_volume(new_volume) def mute(self): """Mute media player""" if self.mediaPlayer.isMuted(): self.mediaPlayer.setMuted(False) self.volume.setIcon(self.style().standardIcon( QStyle.SP_MediaVolume)) else: self.mediaPlayer.setMuted(True) self.volume.setIcon(self.style().standardIcon( QStyle.SP_MediaVolumeMuted))
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 MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self.load_ui() self.setup_central_widgets() def load_ui(self): path = os.path.join(os.path.dirname(__file__), "main_form.ui") uic.loadUi(path, self) self.setWindowFlag(Qt.FramelessWindowHint) self.menuopen_button.clicked.connect(lambda x: self._menu_animation(x)) self.minimise_button.clicked.connect( lambda x: self._menu_buttons('minimise')) self.maximise_button.clicked.connect( lambda x: self._menu_buttons('maximise')) self.close_button.clicked.connect( lambda x: self._menu_buttons('close')) self.title_frame.installEventFilter(self) self.installEventFilter(self) self.statusBar = QStatusBar() self.setStatusBar(self.statusBar) self.statusBar.setStyleSheet("background-color:#272935;" "color: rgb(210, 210, 210); " "font-size: 10px; " "font-family: 'Segoe UI'; " "font-weight:400;") self.title_frame.setMouseTracking(True) self.drag_root_position = QPoint() def setup_central_widgets(self): # it is not possible to create an empty stack inside the ui file so we need to delete those two child widgets first self.analyse_widget.deleteLater() self.analyse_widget = None self.engineconfig_widget.deleteLater() self.engineconfig_widget = None # recreating the relevant widgets (add new widgets below) self.analyse_widget = AnalyseWidget() self.engineconfig_widget = EngineConfigWidget() # adding them to the stack self.content_stack.addWidget(self.analyse_widget) self.content_stack.addWidget(self.engineconfig_widget) # binding the buttons self.analyse_button.clicked.connect( lambda x: self.content_stack.setCurrentIndex(0)) self.engineconfig_button.clicked.connect( lambda x: self.content_stack.setCurrentIndex(1)) # binding a change of the current page self.content_stack.currentChanged.connect( lambda x: self._current_page_changed(x)) def _menu_buttons(self, event): if event == 'maximise': self.previousWidth = self.width() if self.isMaximized(): self.showNormal() else: self.showMaximized() if event == 'close': self.close() if event == 'minimise': self.showMinimized() def _menu_animation(self, mode): self.open_menu_anim = QPropertyAnimation(self.menu_frame, b"minimumWidth") self.open_menu_anim.setDuration(300) if mode: self.open_menu_anim.setEndValue(230) else: self.open_menu_anim.setEndValue(70) self.open_menu_anim.setEasingCurve(QEasingCurve.InOutQuart) self.open_menu_anim.start() def _current_page_changed(self, new_index): self.getAnalyseWidget().stop_analysis() self.getAnalyseWidget().reload_engines() def eventFilter(self, source, event): if source == self.title_frame: # check if lmb is pressed if app.mouseButtons() & Qt.LeftButton: # check if the mouse is moving if event.type() == QEvent.MouseMove: if self.ignore_movement: return QMainWindow.eventFilter(self, source, event) if self.isMaximized(): max_width = self.width() cursor_position = QCursor.pos().x() self.showNormal() new_width = self.previousWidth new_x = cursor_position - new_width // 2 new_x = max(+70, new_x) new_x = min(new_x, max_width - new_width + 70) self.drag_root_position.setX(cursor_position - new_x) self.move(new_x, 0) else: if QCursor.pos().y() < 3: self._menu_buttons('maximise') self.ignore_movement = True else: self.move(event.pos() + self.title_frame.mapToGlobal( self.title_frame.pos()) - self.drag_root_position) elif event.type() == 2: # init root position self.drag_root_position = self.title_frame.mapToGlobal( event.pos()) - self.pos() else: self.ignore_movement = False return QMainWindow.eventFilter(self, source, event) def getAnalyseWidget(self): return self.analyse_widget def getEngineConfigWidget(self): return self.engineconfig_widget
class AppView(QMainWindow): def __init__(self): super().__init__() # 700 is base height + (menubar.width + statusbar.width) self.cameraChoice = 0 self.cWidget = QWidget() self.layout = QGridLayout(self.cWidget) self.productManagerFrame = ProductManagerFrame(self) self.settingButtonsFrame = SettingsButtonsFrame(self) self.cameraDisplayFrame = CameraDisplayFrame(self) self.layout.addWidget(self.cameraDisplayFrame, 0, 0, 12, 2) self.layout.addWidget(self.productManagerFrame, 0, 2, 13, 1) self.layout.addWidget(self.settingButtonsFrame, 12, 0, 1, 2) self.setCentralWidget(self.cWidget) self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 1100, 30)) self.settingsMenu = QMenu("Settings", self.menubar) self.applicationMenu = QMenu("Application", self.menubar) self.aboutMenu = QMenu("About", self.menubar) self.setMenuBar(self.menubar) self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.statusbar.setFixedHeight(20) self.statusbar.setStyleSheet("font-size: 10px;") self.statusUser = QLabel() self.statusUser.setGeometry(QRect(0, 0, 20, 20)) self.statusbar.addWidget(self.statusUser) # Actions choices self.selectFolderAction = QAction(parent=self, text="Select Folder") self.showProductsAction = QAction(parent=self, text="Show products (S)") self.photoAction = QAction(parent=self, text="Photo (P)") self.selectCameraAction = QAction(parent=self, text="Change camera") self.changeUserAction = QAction(parent=self, text="Change user") self.createUserAction = QAction(parent=self, text="Create new user") self.authorAction = QAction(parent=self, text="Author") self.scannerModeAction = QAction(parent=self, text="Scanner mode") self.scannerModeAction.setCheckable(True) self.settingsMenu.addAction(self.selectFolderAction) self.settingsMenu.addAction(self.selectCameraAction) self.settingsMenu.addAction(self.scannerModeAction) self.applicationMenu.addAction(self.showProductsAction) self.applicationMenu.addAction(self.photoAction) self.applicationMenu.addAction(self.changeUserAction) self.applicationMenu.addAction(self.createUserAction) self.aboutMenu.addAction(self.authorAction) self.menubar.addAction(self.applicationMenu.menuAction()) self.menubar.addAction(self.settingsMenu.menuAction()) self.menubar.addAction(self.aboutMenu.menuAction()) self.setWindowTitle("STManager 2021 - version 1.0.0") self.setup() def getPhotoDestinationPath(self): return self.saveDestination def updateStatusbar(self): self.statusUser.setText( f"Logged as user {self.controller.getUsername()}") def setup(self): self.controller = AppController(self) self.productManagerFrame.setup() self.settingButtonsFrame.setup() self.cameraDisplayFrame.setup(self.controller.getScannerMode()) self.updateStatusbar() # connecting ui buttons signals self.productManagerFrame.confirmButton.clicked.connect( self.controller.saveCurrentProduct) self.productManagerFrame.cancelButton.clicked.connect( self.controller.deleteCurrentProduct) self.settingButtonsFrame.photoButton.clicked.connect( self.controller.takePhoto) self.settingButtonsFrame.showProductsButton.clicked.connect( self.searchProducts) self.settingButtonsFrame.changeUserButton.clicked.connect( self.controller.switchUser) self.settingButtonsFrame.nextProductButton.clicked.connect( self.controller.nextProduct) self.settingButtonsFrame.prevProductButton.clicked.connect( self.controller.previousProduct) self.productManagerFrame.productBarcode.returnPressed.connect( self.controller.takePhoto) # connecting actions buttons singals self.selectFolderAction.triggered.connect( self.controller.changeSaveUrl) self.showProductsAction.triggered.connect(self.searchProducts) self.photoAction.triggered.connect(self.controller.takePhoto) self.selectCameraAction.triggered.connect(self.showCameraChoice) self.changeUserAction.triggered.connect(self.controller.switchUser) self.createUserAction.triggered.connect(createAccount) self.authorAction.triggered.connect(showInfo) self.scannerModeAction.triggered.connect( self.controller.toggleScannerMode) if self.controller.getScannerMode(): self.scannerModeAction.setChecked(True) def keyPressEvent(self, k): key = k.key() if key == Qt.Key_P: self.controller.takePhoto() elif key == Qt.Key_Enter and self.controller.getScannerMode(): self.controller.saveCurrentProduct() elif key == Qt.Key_Delete: self.controller.deleteCurrentProduct() def setCameraIndex(self, i: int): self.cameraChoice = i def cleanUp(self): """ Slot connected to signal aboutToQuit from QApplication """ self.controller.cleanUp() self.cameraDisplayFrame.turnOffCamera() return 0 def getCameraIndex(self) -> int: return self.cameraChoice def getController(self) -> AppController: return self.controller def searchProducts(self): from utils.ProductSearcher import ProductSearcher p = ProductSearcher() p.exec() def showCameraChoice(self): self.cameraChoice = cameraChoice()
class DatasFilterWindow(QMainWindow): manual_get_coor = pyqtSignal() def __init__(self): super(DatasFilterWindow, self).__init__() self.setObjectName('MainWindow') self.setStyleSheet(StyleTool.readQSS('./style_bright.qss')) self.setWindowTitle('数据筛选') self.resize(650, 600) self.setWindowFlags(Qt.WindowMinimizeButtonHint | Qt.WindowCloseButtonHint) self.setFocus(Qt.MouseFocusReason) self.setup_ui() self.conn = sqlite3.connect('target_company.db') self.signal_slot() self.area = '' self.Id = None self.jobId = None # 标志 self.is_begined = False def setup_ui(self): # 创建布局 layout = QVBoxLayout() layout1 = QHBoxLayout() layout2 = QHBoxLayout() layout3 = QHBoxLayout() layout4 = QHBoxLayout() layout5 = QHBoxLayout() # 创建控件 company_name_tag = QLabel('公司名称') self.company_name = QLabel('') company_addr_tag = QLabel('公司地址') self.company_addr = QLabel('') company_scale_tag = QLabel('公司规模') self.company_scale = QLabel('') company_area_tag = QLabel('所处地区') self.company_area = QLabel('') job_name_tag = QLabel('职位名称') self.job_name = QLabel('') job_url = QLabel('职位链接') self.job_url = QLabel('') coordinate_tag = QLabel('经纬度') self.coordinate = QLineEdit() # QTextBrowser self.company_desc_browser = QTextBrowser() self.job_desc_browser = QTextBrowser() # QLineEdit self.note_ledit = QLineEdit() self.note_ledit.setPlaceholderText('备注') self.possible_ledit = QLineEdit() self.possible_ledit.setFixedWidth(132) self.possible_ledit.setPlaceholderText('可能性') self.keyword_edit = QLineEdit() self.keyword_edit.setFixedWidth(62) self.keyword_edit.setPlaceholderText('城市') # 按钮 self.save_btn = QPushButton('保存') self.save_btn.setContentsMargins(0, 0, 0, 0) self.begin_btn = QPushButton('开始') self.begin_btn.setContentsMargins(0, 0, 0, 0) self.del_btn = QPushButton('删除') self.del_btn.setContentsMargins(0, 0, 0, 0) self.view_final_result_btn = QPushButton('查看筛选结果') # 进度栏 self.process_bar = QProgressBar() self.process_bar.setFormat('%v/%m') # 状态栏 self.status = QStatusBar() self.setStatusBar(self.status) self.status.setStyleSheet('QStatusBar{color:red;}') # 布置布局 layout.addLayout(layout1) layout1.addWidget(job_name_tag) layout1.addWidget(self.job_name) layout1.addStretch(1) layout1.addWidget(self.keyword_edit) layout1.addWidget(self.begin_btn) layout1.addWidget(self.view_final_result_btn) layout.addLayout(layout2) layout2.addWidget(company_name_tag) layout2.addWidget(self.company_name) layout2.addStretch(1) layout2.addWidget(self.note_ledit, 1) layout.addLayout(layout3) layout3.addWidget(company_scale_tag) layout3.addWidget(self.company_scale) layout3.addStretch(1) layout3.addWidget(company_area_tag) layout3.addWidget(self.company_area) layout3.addStretch(3) layout3.addWidget(self.possible_ledit) layout.addLayout(layout4) layout4.addWidget(company_addr_tag) layout4.addWidget(self.company_addr) layout4.addStretch(1) layout4.addWidget(self.save_btn) layout4.addWidget(self.del_btn) layout.addLayout(layout5) layout5.addWidget(job_url) layout5.addWidget(self.job_url) layout5.addStretch(1) layout5.addWidget(coordinate_tag) layout5.addWidget(self.coordinate) layout.addWidget(self.company_desc_browser) layout.addWidget(self.job_desc_browser) layout.addWidget(self.process_bar) center_widget = QWidget() center_widget.setLayout(layout) self.setCentralWidget(center_widget) def signal_slot(self): self.save_btn.clicked.connect(self.save) self.del_btn.clicked.connect(self.delete) self.begin_btn.clicked.connect(self.begin) self.view_final_result_btn.clicked.connect(self.view_final_result) # self.begin_btn.setShortcut(_translate('MainWindow', 'Enter')) self.del_shortcut = QShortcut(QKeySequence('Ctrl+D'), self) self.del_shortcut.activated.connect(self.delete) self.begin_sc = QShortcut(QKeySequence('ctrl+b'), self) self.begin_sc.activated.connect(self.begin) self.quit_sc = QShortcut(QKeySequence('Meta+q'), self) self.quit_sc.activated.connect( lambda: sys.exit(QApplication(sys.argv).exec_())) self.save_sc = QShortcut(QKeySequence('ctrl+s'), self) self.save_sc.activated.connect(self.save) self.manual_get_coor.connect(self.manual_save_coor) def begin(self): c = self.conn.cursor() # 根据输入的城市 获取对应的城市数据 city = self.keyword_edit.text() if city: self.keyword_edit.clearFocus() sql = "select id from areas where area='{}';".format(city) print(sql) try: area_id = c.execute(sql).fetchone()[0] except IndexError: print('该城市数据不存在') except Exception as e: print(e) # 筛选出该区域的所有数据 else: sql = "select id, company_id, job_id from raw_datas where area_id='{}' and is_read=0 order by weight desc;".format( area_id) results = c.execute(sql).fetchall() total = len(results) self.status.showMessage('数据量:{}'.format(total), 10000) self.process_bar.setMaximum(total) # 主要效果 阻塞for循环 通过按钮解除阻塞 self.t = Thread(results) self.t.id_pipLine.connect(self.show_loop) self.t.valueChange.connect(self.process_bar.setValue) self.t.task_finished.connect(self.finished) self.t.start() self.area = city self.is_begined = True print('--') else: print('未输入城市') def show_loop(self, e): """循环显示""" self.Id = e[0] company_id = e[1] self.jobId = e[2] c = self.conn.cursor() sql = "select company_name, company_address, company_scale, company_desc from companies where id={};".format( company_id) self.company_info = c.execute(sql).fetchone() sql = "select job_name, job_desc, job_url from jobs where id={};".format( self.jobId) self.job_info = c.execute(sql).fetchone() # print(self.company_info, '\n', self.job_info, sep='') if self.company_info and self.job_info: self.job_name.setText(self.job_info[0].strip()) self.company_name.setText(self.company_info[0]) self.company_scale.setText(self.company_info[2]) self.company_area.setText(self.area) self.company_addr.setText(self.company_info[1]) self.company_desc_browser.setPlainText(self.company_info[-1]) self.job_desc_browser.setPlainText(self.job_info[1]) # todo:职位链接太长 # self.job_url.setText(self.job_info[2]) def save(self): """ 保存该组数据到新的数据表 并更新地图用数据 并显示下一条""" possible = self.possible_ledit.text() note = self.note_ledit.text() if possible: c = self.conn.cursor() # 获取公司地址的经纬度 addr = self.company_info[1] try: result = get_coordinate(addr) except requests.exceptions.ConnectTimeout: self.status.showMessage('获取坐标超时,请检查网络连接', 5000) return else: print('result', result) if not result: self.status.showMessage('抱歉无法获取该位置定位', 3000) self.manual_get_coor.emit() elif result['precise'] == 0: self.status.showMessage('该位置的坐标准确性未知', 3000) else: # 插入数据到map_datas sql = "insert into map_datas(locate_addr, lat, lng, precise) " \ "values('{}', {}, {}, {});".format(result['locate_addr'], result['lat'], result['lng'], result['precise']) c.execute(sql) # 获取刚刚插入数据的map_id sql = "select max(id) from map_datas;" max_map_id = c.execute(sql).fetchone()[0] # 插入数据到final_datas sql = "insert into final_datas(possible, note, raw_id, map_id) values('{}','{}',{}, {});".format( possible, note, self.Id, max_map_id) c.execute(sql) # 更新raw_datas的is_read值 表示已经筛选过,下次不再显示 sql = "update raw_datas set is_read=1 where id={};".format(self.Id) c.execute(sql) self.conn.commit() # 清除输入控件当前的数据 self.note_ledit.clear() self.possible_ledit.clear() self.coordinate.clear() self.possible_ledit.clearFocus() # 检测当前城市是否还有未筛选的数据组 if self.is_begined and self.process_bar.value( ) < self.process_bar.maximum(): self.t.next() else: print('没有next了') else: # 提醒没有填写可能性 self.status.showMessage('没填可能性', 3000) def delete(self): """删除该组数据 并显示下一条""" c = self.conn.cursor() sql = "delete from raw_datas where id={};".format(self.Id) try: c.execute(sql) except sqlite3.OperationalError: self.status.showMessage('当前没有数据', 3000) return sql = "delete from jobs where id={};".format(self.jobId) c.execute(sql) self.conn.commit() self.note_ledit.clear() self.possible_ledit.clear() if self.is_begined and self.process_bar.value( ) < self.process_bar.maximum(): self.t.next() else: print('没有next了') def finished(self): self.status.showMessage('任务结束', 5000) self.job_name.clear() self.company_name.clear() self.company_scale.clear() self.company_addr.clear() self.company_area.clear() self.note_ledit.clear() self.possible_ledit.clear() self.company_desc_browser.clear() self.job_desc_browser.clear() def get_position(self, addr): """ 百度坐标系获取 :param addr: :return: """ ak = 'ysZHXY6AwYQYcXLuhTCkV2a1YvOk5Dm2' url = 'http://api.map.baidu.com/geocoding/v3/?address={}&output=json&ak={}'.format( addr, ak) return requests.get(url=url).json() def manual_save_coor(self): result = self.coordinate.text() if result: c = self.conn.cursor() # 插入数据到map_datas result = result.split(',') sql = "insert into map_datas(lat, lng) " \ "values('{}', {});".format(float(result[0].strip()), float(result[1].strip())) c.execute(sql) self.conn.commit() self.status.showMessage('已手动定位', 3000) else: return def view_final_result(self): # 使用poltly制图 对应的数据格式整理 save_plotly_map(get_plotly_datas())
class MainWindowUi(QMainWindow): """This class manages the system tray icon of the main program, post-login. """ vpn_connect_section = QVBoxLayout() def __init__(self): super(QMainWindow, self).__init__() # Using a StackedWidget to be able to replace login window # https://stackoverflow.com/questions/13550076 self.cw = QStackedWidget() self.setCentralWidget(self.cw) # Set minimum width of Main Window to 500 pixels self.cw.setMinimumWidth(500) self.setWindowTitle('MerLink - VPN Client for Meraki firewalls') self.link_style = "font-family: verdana, sans-serif; font-style:" \ " normal; font-size: 13px; color: #1795E6;" # Required for Login. Elements should be object variables if they # Could be called by other modules self.username_textfield = QLineEdit() self.password_textfield = QLineEdit() self.guest_user_chkbox = QCheckBox("Use guest account instead") self.password_textfield.setEchoMode(QLineEdit.Password) self.org_dropdown = QComboBox() self.create_vpn_btn = QPushButton("Create VPN Interface") self.create_vpn_tabs = QTabWidget() self.tab_dashboard = QWidget() self.tab_manual = QWidget() self.vpn_opts_layout = QVBoxLayout() def setup_pyqt_slots(self): """Initiate all of the triggers and connects.""" def setup_window(self): """Setup various sections that will be combined.""" self.create_vpn_tabs.addTab(self.tab_dashboard, "Dashboard Setup") self.create_vpn_tabs.addTab(self.tab_manual, "Manual Setup") self.vpn_opts_setup() self.setup_manual_tab() self.setup_dashboard_tab() self.vpn_connect_setup() self.decorate_sections() self.combine_sections_dashboard() # Set the layout once we are done adding elements self.main_window_set_admin_layout() def setup_dashboard_tab(self): """Provide input fields for dashboard-gathered data.""" self.tab_dashboard.layout = QVBoxLayout(self) # Guest users should manually enter their information # Only difference between Guest and Dashboard for UI should be that # Email/pass is prepopulated for dashboard admins (inactivated) email_pass_layout = QVBoxLayout() username_label = QLabel("Email") password_label = QLabel("Password") self.disable_email_pass(True) self.add_all_to_layout( email_pass_layout, [ username_label, self.username_textfield, password_label, self.password_textfield ] ) self.tab_dashboard.layout.addWidget(self.guest_user_chkbox) self.tab_dashboard.layout.addLayout(email_pass_layout) self.tab_dashboard.layout.addLayout(self.vpn_opts_layout) self.tab_dashboard.setLayout(self.tab_dashboard.layout) def disable_email_pass(self, change_to_disabled): """Disable username/password if user should not edit them.""" disable_lineedit(self.username_textfield, change_to_disabled) disable_lineedit(self.password_textfield, change_to_disabled) def vpn_opts_setup(self): """Set up the vpn vars UI region.""" # Create org and network dropdowns so the user can select the firewall # they would like to connect to. org_dropdown = QComboBox() org_dropdown.addItem('-- Select an Organization --') network_dropdown = QComboBox() network_dropdown.setEnabled(False) # Allow the user to change the VPN name vpn_name_layout = QHBoxLayout() vpn_name_label = QLabel("VPN Name:") vpn_name_textfield = QLineEdit() vpn_name_layout.addWidget(vpn_name_label) vpn_name_layout.addWidget(vpn_name_textfield) # Ask the user for int/str values if they want to enter them idle_disconnect_layout = QHBoxLayout() idle_disconnect_chkbox = QCheckBox("Idle disconnect seconds?") idle_disconnect_spinbox = QSpinBox() idle_disconnect_spinbox.setValue(0) # Negative seconds aren't useful here idle_disconnect_spinbox.setMinimum(0) idle_disconnect_layout.addWidget( idle_disconnect_chkbox) idle_disconnect_layout.addWidget( idle_disconnect_spinbox) dns_suffix_layout = QHBoxLayout() dns_suffix_chkbox = QCheckBox("DNS Suffix?") dns_suffix_txtbox = QLineEdit('-') dns_suffix_layout.addWidget(dns_suffix_chkbox) dns_suffix_layout.addWidget(dns_suffix_txtbox) # Boolean asks of the user split_tunneled_chkbox = QCheckBox("Split-Tunnel?") remember_credential_chkbox = QCheckBox("Remember Credentials?") use_winlogon_chkbox = QCheckBox("Use Windows Logon Credentials?") self.add_all_to_layout( self.vpn_opts_layout, [ org_dropdown, network_dropdown, vpn_name_layout, # Add layouts for specialized params idle_disconnect_layout, dns_suffix_layout, # Add checkboxes split_tunneled_chkbox, remember_credential_chkbox, use_winlogon_chkbox, # Ensure that button is at bottom of pane by adding space QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding) ] ) def setup_manual_tab(self): """Gray out options and provide input fields to manually enter data.""" self.tab_manual.layout = QVBoxLayout(self) # User should be able to change email/pass as it's required self.disable_email_pass(False) username_textfield = QLineEdit() password_textfield = QLineEdit() password_textfield.setEchoMode(QLineEdit.Password) username_label = QLabel("Email") password_label = QLabel("Password") vpn_name_label = QLabel("VPN Name") vpn_name_textfield = QLineEdit() server_name_label = QLabel("Server name/IP") server_name_textfield = QLineEdit() shared_secret_label = QLabel("Shared Secret") shared_secret_textfield = QLineEdit() shared_secret_textfield.setEchoMode(QLineEdit.Password) self.add_all_to_layout( self.tab_manual.layout, [ username_label, username_textfield, password_label, password_textfield, vpn_name_label, vpn_name_textfield, server_name_label, server_name_textfield, shared_secret_label, shared_secret_textfield, QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding) ] ) self.tab_manual.setLayout(self.tab_manual.layout) def vpn_connect_setup(self): """Setup the GUI componentst of the right pane.""" vpn_list = QListWidget() ipsum_vpn_interfaces = ['eth', 'wifi'] vpn_list.addItems(ipsum_vpn_interfaces) check_for_probs_cb = QCheckBox( "Check for issues before connecting (recommended)") check_for_probs_cb.setChecked(True) probs_list = QListWidget() problems = ["Forget the milk", "My hovercraft is full of eels"] probs_list.addItems(problems) connect_vpn_btn = QPushButton("Connect") self.add_all_to_layout( self.vpn_connect_section, [ vpn_list, check_for_probs_cb, probs_list, connect_vpn_btn ] ) def decorate_sections(self): """Add a box around each section for readability.""" # Set GroupBox CSS manually because otherwise margins are huge self.setStyleSheet(".QGroupBox { border: 1px solid #ccc;}") def combine_sections_dashboard(self): """Combine left and right panes into a final layout.""" # Create a horizontal line above the status bar to highlight it self.hline = QFrame() self.hline.setFrameShape(QFrame.HLine) self.hline.setFrameShadow(QFrame.Sunken) self.vline = QFrame() self.vline.setFrameShape(QFrame.VLine) self.vline.setFrameShadow(QFrame.Sunken) # Status bar be at bottom and inform user of what the program is doing. self.status = QStatusBar() self.status.showMessage("Status: -") self.status.setStyleSheet("Background:#fff") main_widget = QWidget() main_layout = QVBoxLayout(main_widget) left_pane = QVBoxLayout() left_pane.addWidget(self.create_vpn_tabs) left_pane.addWidget(self.create_vpn_btn) two_pane_layout = QHBoxLayout() two_pane_layout.addLayout(left_pane) two_pane_layout.addWidget(self.vline) two_pane_layout.addLayout(self.vpn_connect_section) main_layout.addLayout(two_pane_layout) main_layout.addWidget(self.hline) main_layout.addWidget(self.status) self.cw.addWidget(main_widget) def main_window_set_admin_layout(self): """Set the dashboard user layout. Hides guest user layout as we will only be connecting with one user. The user will see the username/obfuscated password they entered. """ self.username_textfield.setText( self.login_dict['username']) self.username_textfield.setReadOnly(True) self.password_textfield.setText( self.login_dict['password']) self.password_textfield.setReadOnly(True) def main_window_set_guest_layout(self): """Set the guest user layout. Hides dashboard user layout as we will only be connecting with one user. The user will see blank user/pass text fields where they can enter information for a guest user. """ self.radio_username_textfield.clear() self.radio_username_textfield.setReadOnly(False) self.radio_password_textfield.clear() self.radio_password_textfield.setReadOnly(False) @staticmethod def add_all_to_layout(layout, element_list): """Add all of the elements to the layout.""" for elem in element_list: if isinstance(elem, QWidget): layout.addWidget(elem) elif is_layout(elem): layout.addLayout(elem) elif isinstance(elem, QSpacerItem): layout.addItem(elem) else: print("ERROR: Trying to add illegal element to UI!") exit(1)
class MainWindow(QMainWindow): closeSignal = pyqtSignal() resizeSignal = pyqtSignal() def __init__(self, parent=None): super(MainWindow, self).__init__(parent) desk = QDesktopWidget() screen = desk.screenGeometry() x = screen.width() y = screen.height() """ Main window""" """general""" self.setObjectName("MainWindow") self.setEnabled(True) self.resize(int(0.4 * x), int(0.75 * y)) self.setWindowTitle("Aircraft Recognition") self.show() self.central_widget = QWidget(self) self.central_widget.setObjectName("central_widget") self.group = QVBoxLayout( ) # this layout is gonna be our group container self.central_widget.setLayout(self.group) self.setCentralWidget(self.central_widget) """ Chart""" # creates the main layout for the chart self.layout_picture = QVBoxLayout() # widget which contains the chart , necessary to save the chart as png self.picture = QGroupBox() self.picture.setLayout(self.layout_picture) """Controls""" self.button_next = QToolButtonFocus() self.button_next.setText("Next") self.button_validate = QToolButtonFocus() self.button_validate.setText("Validate") self.layout_controls = QHBoxLayout() self.layout_controls.addWidget(self.button_next) self.layout_controls.addWidget(self.button_validate) self.controls = QGroupBox() self.controls.setLayout(self.layout_controls) """ Status Bar """ # creates a qstatusbar to inform the users self.group_message = QGroupBox("Message :") self.group_message.setFixedHeight(70) self.layout_status = QHBoxLayout() self.group_message.setLayout(self.layout_status) self.layout_status.setAlignment(Qt.AlignBottom) self.status = QStatusBar() self.status.setStyleSheet(""" .QStatusBar { border: 1px solid white; background-color: white; color : red; } """) self.status.setMaximumWidth(500) self.layout_status.addWidget(self.status) self.layout_status.addWidget(self.button_validate) self.layout_status.addWidget(self.button_next) """ add to the main group everything """ # curve and axis config self.layout_config = QVBoxLayout() # chart and button save self.layout_picture = QVBoxLayout() self.layout_picture.addWidget(self.picture) self.layout_picture.addWidget(self.group_message) self.group.addLayout(self.layout_picture) def closeEvent(self, event): self.closeSignal.emit() # emit a close signal super().closeEvent(event) def resizeEvent(self, a0: QResizeEvent) -> None: # super().resizeEvent(a0) self.resizeSignal.emit()
class simpleIpfwGui(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("Simple Firewall GUI for FreeBSD") self.centralWidget = QWidget(self) self.setCentralWidget(self.centralWidget) self.layout = QGridLayout() self.centralWidget.setLayout(self.layout) # firewallEnabled: firewall_enabled=YES in rc.conf, firewallRunningString: ipfw loaded and running (self.firewallEnabled, self.firewallRunningString, self.firewallRunningBool) = self.getFirewallState() self.allowedPorts = self.getAllowedPorts() self.widgets() def widgets(self): self.labelTitle = QLabel("Simple Firewall GUI for FreeBSD") self.labelTitle.setAlignment(Qt.AlignCenter) self.labelcheckBoxIpfwEnable = QLabel("Enable Firewall? ") #self.labelAllowedPorts = QLabel("Allowed incoming ports:") self.checkBoxIpfwEnable = QCheckBox() self.checkBoxIpfwEnable.setToolTip( 'Check this to enable the firewall.') if self.firewallEnabled.lower() == "yes": self.checkBoxIpfwEnable.setChecked(True) #self.editAllowedPorts = QLineEdit() #self.editAllowedPorts.setFixedWidth(500) #self.editAllowedPorts.setText(' '.join(self.allowedPorts)) self.buttonApply = QPushButton("Apply") self.buttonApply.setFixedWidth(120) self.buttonApply.clicked.connect(self.applyChanges) self.buttonQuit = QPushButton("Quit") self.buttonQuit.setFixedWidth(120) self.buttonQuit.clicked.connect(QApplication.instance().quit) #self.buttonClear = QPushButton("Clear") #self.buttonClear.setFixedWidth(120) #self.buttonClear.clicked.connect(self.clearAllowedPorts) self.createTable() self.statusBar = QStatusBar() self.statusBar.showMessage(self.firewallRunningString) self.updateStatusBar() self.setStatusBar(self.statusBar) self.layout.addWidget(self.labelTitle, 0, 1) self.layout.addWidget(self.labelcheckBoxIpfwEnable, 1, 0) self.layout.addWidget(self.checkBoxIpfwEnable, 1, 1) self.layout.addWidget(self.tableWidget, 2, 0, 1, 3) #self.layout.addWidget(self.labelAllowedPorts, 3, 0) #self.layout.addWidget(self.editAllowedPorts, 4, 0, 1, 3) #self.layout.addWidget(self.buttonClear, 5, 0) self.layout.addWidget(self.buttonApply, 5, 1, alignment=Qt.AlignRight) self.layout.addWidget(self.buttonQuit, 5, 2) #self.sanitizeInput(self.editAllowedPorts.text()) self.checkPrivileges() def createTable(self): self.tableWidget = QTableWidget() self.tableContent = self.getListenPorts().strip().decode("utf-8") self.tableWidget.setRowCount(self.tableContent.count("\n")) self.tableWidget.setColumnCount(4) self.tableWidget.setHorizontalHeaderLabels( ["Process", "Protocol", "Port", "Allow"]) self.lineNum = 0 for line in self.tableContent.split("\n"): (self.proc, self.proto, self.port) = line.split() self.tableWidget.setItem(self.lineNum, 0, QTableWidgetItem(self.proc)) self.tableWidget.setItem(self.lineNum, 1, QTableWidgetItem(self.proto)) self.tableWidget.setItem(self.lineNum, 2, QTableWidgetItem(self.port)) self.checkbox = QTableWidgetItem() self.checkbox.setFlags(self.checkbox.flags() | Qt.ItemIsUserCheckable) if str(self.port) + "/" + self.proto.rstrip( "46") in self.allowedPorts: self.checkbox.setCheckState(Qt.Checked) else: self.checkbox.setCheckState(Qt.Unchecked) self.tableWidget.setItem(self.lineNum, 3, self.checkbox) self.lineNum += 1 self.tableWidget.move(0, 0) def applyChanges(self): if not self.checkPrivileges(): return if self.checkBoxIpfwEnable.isChecked() == True: self.fwEnable = "YES" self.serviceAction = "start" else: self.fwEnable = "NO" self.serviceAction = "onestop" # Add enabled checkboxes to the list items = [] for i in range(self.tableWidget.rowCount()): item = self.tableWidget.item(i, 3) if item.checkState() == Qt.Checked: items.append(item) self.allowedPortsNew = [] for it in items: r = it.row() portProto = self.tableWidget.item( r, 2).text() + "/" + self.tableWidget.item( r, 1).text().rstrip('46') self.allowedPortsNew.append(portProto) #self.editAllowedPorts.setText(' '.join(self.allowedPorts)) #self.sanitizeInput(self.editAllowedPorts.text()) self.allowedPortsNew = sorted(self.allowedPortsNew, key=natural_keys) print( check_output([SYSRC_BIN, 'firewall_enable=' + self.fwEnable ]).rstrip().decode("utf-8")) print( check_output([SYSRC_BIN, 'firewall_type=workstation' ]).rstrip().decode("utf-8")) print( check_output([SYSRC_BIN, 'firewall_allowservices=any' ]).rstrip().decode("utf-8")) #print(check_output([SYSRC_BIN, 'firewall_myservices=' + ' '.join(self.editAllowedPorts.text().strip())].decode("utf-8"))) print( check_output([ SYSRC_BIN, 'firewall_myservices=' + ' '.join(self.allowedPortsNew) ])) print(check_output([SERVICE_BIN, 'ipfw', self.serviceAction])) (self.firewallEnabled, self.firewallRunningString, self.firewallRunningBool) = self.getFirewallState() self.updateStatusBar() def getFirewallState(self): self.firewallEnabled = check_output( [SYSRC_BIN, '-n', 'firewall_enable']).rstrip().decode("utf-8") self.firewallRunningString = check_output( SERVICE_BIN + ' ipfw forcestatus; exit 0', shell=True).rstrip().decode("utf-8") if self.firewallRunningString == "ipfw is enabled": self.firewallRunningBool = True else: self.firewallRunningBool = False self.firewallRunningString = self.firewallRunningString.replace( 'enabled', 'running') self.firewallRunningString = self.firewallRunningString.replace( 'ipfw', 'Firewall') return (self.firewallEnabled, self.firewallRunningString, self.firewallRunningBool) def getAllowedPorts(self): return (check_output([SYSRC_BIN, '-n', 'firewall_myservices' ])).strip().decode("utf-8").split(" ") #def clearAllowedPorts(self): # self.editAllowedPorts.setText('') # return #def updateAllowedPorts(self, state): # if state == Qt.Checked: # else: # # self.sanitizeInput(self.editAllowedPorts.text()) # return def checkPrivileges(self): if os.geteuid() != 0: QMessageBox.information( self, "Not enough privileges", "You started the firewall management GUI as a regular user and can only read the firewall settings.\n\nIf you want to edit settings, run the firewall management GUI as root." ) return False else: return True def updateStatusBar(self): if self.firewallRunningBool == True: self.statusBar.setStyleSheet("background-color : lightgreen") else: self.statusBar.setStyleSheet("background-color : pink") self.statusBar.showMessage(self.firewallRunningString) def getListenPorts(self): return (check_output( SOCKSTAT_BIN + ' -46lLwqj0 | tr -s " " | cut -d " " -f 2,5,6 | awk -F\'[ :]\' \'{sub(/\*/, "", $1);sub(/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/, "", $1); conn[$NF] = sprintf("%s %s", $1,$2)} END{for (port in conn){ print conn[port], port}}\' | sort -nk3 | sed \'/\*$/d\'', shell=True))
class Dimili(QMainWindow): def baslat(self, anaPencere): anaPencere.resize(600, 400) anaPencere.setWindowTitle("Dimili-Türkçe Sözlük") anaPencere.setFixedSize(600, 400) icon = QIcon() icon.addPixmap(QPixmap("Dictionary.png"), QIcon.Normal, QIcon.Off) anaPencere.setWindowIcon(icon) zemin = QWidget(anaPencere) zemin.setGeometry(QRect(0, 30, 600, 390)) zemin.setStyleSheet("background-color:rgb(167, 196, 233);") self.araKutu = QLineEdit(anaPencere) self.araKutu.setGeometry(QRect(10, 80, 200, 20)) self.araKutu.textChanged.connect(self.benzerKelimeler) self.kelimeGir = QLabel("Kelimeler:", anaPencere) self.kelimeGir.setGeometry(QRect(10, 110, 141, 21)) self.kelimeGor = QLabel("Kelime Ara", anaPencere) self.kelimeGor.setGeometry(QRect(10, 30, 91, 16)) self.harfGrup = QButtonGroup(anaPencere) aharf = QPushButton("â", anaPencere) aharf.setGeometry(QRect(10, 50, 25, 25)) eharf = QPushButton("é", anaPencere) eharf.setGeometry(QRect(30, 50, 25, 25)) self.DilGrup = QButtonGroup(anaPencere) self.Dil1 = QPushButton("Zazaca-Türkçe", anaPencere) self.Dil1.setGeometry(QRect(230, 80, 91, 23)) self.Dil1.setCheckable(True) self.Dil1.setAutoExclusive(True) self.Dil1.setChecked(True) self.Dil1.setStyleSheet("background-color: rgb(102, 255, 0);") self.Dil2 = QPushButton("Türkçe-Zazaca", anaPencere) self.Dil2.setGeometry(QRect(330, 80, 91, 23)) self.Dil2.setCheckable(True) self.Dil2.setAutoExclusive(True) self.Dil2.setStyleSheet("background-color: rgb(255, 94, 105);") self.DilGrup.addButton(self.Dil1, 1) self.DilGrup.addButton(self.Dil2, 2) self.DilGrup.buttonClicked[int].connect(self.dilSecme) self.kelimeListesi = QListWidget(anaPencere) self.kelimeListesi.setGeometry(QRect(10, 130, 191, 231)) self.kelimeListesi.itemClicked.connect(self.kelimeAcikla) self.kelimeAnlam = QLabel("Kelimenin Anlamı:", anaPencere) self.kelimeAnlam.setGeometry(QRect(230, 110, 131, 21)) self.cumleList1 = QListWidget(anaPencere) self.cumleList1.setGeometry(QRect(230, 130, 351, 51)) self.ornekCumle1 = QLabel("Örnek Zazaca Cümle:", anaPencere) self.ornekCumle1.setGeometry(QRect(230, 200, 101, 21)) self.cumleList2 = QListWidget(anaPencere) self.cumleList2.setGeometry(QRect(230, 220, 351, 51)) self.ornekCumle2 = QLabel("Örnek Türkçe Cümle:", anaPencere) self.ornekCumle2.setGeometry(QRect(230, 290, 111, 16)) self.cumleList3 = QListWidget(anaPencere) self.cumleList3.setGeometry(QRect(230, 310, 351, 51)) self.anaMenu = QMenuBar(anaPencere) self.anaMenu.setGeometry(QRect(0, 0, 600, 21)) self.menuDosya = QMenu("Dosya", self.anaMenu) self.menuDuzenle = QMenu("Düzenle", self.anaMenu) self.menuYardim = QMenu("Yardım", self.anaMenu) anaPencere.setMenuBar(self.anaMenu) self.durum = QStatusBar(zemin) anaPencere.setStatusBar(self.durum) self.durum.setStyleSheet("background-color:white") self.durum.showMessage("Hazır") self.cikis = QAction(QIcon("Exit.ico"), "&Çıkış", anaPencere) self.cikis.setShortcut("Ctrl+X") self.cikis.triggered.connect(anaPencere.close) self.actionHakkinda = QAction("Hakkında", anaPencere) self.actionHakkinda.triggered.connect(self.hakkinda) self.actionSecenekler = QAction("Seçenekler", anaPencere) self.menuDosya.addAction(self.cikis) self.menuDuzenle.addAction(self.actionSecenekler) self.menuYardim.addAction(self.actionHakkinda) self.anaMenu.addAction(self.menuDosya.menuAction()) self.anaMenu.addAction(self.menuDuzenle.menuAction()) self.anaMenu.addAction(self.menuYardim.menuAction()) def kelimeAcikla(self): if self.DilGrup.checkedId() == 1: self.cumleList1.clear() self.cumleList2.clear() self.cumleList3.clear() itemtext = [ str(x.text()) for x in self.kelimeListesi.selectedItems() ] for it in itemtext: itemtext = it self.im.execute("select Tur from DimTur where Zazaca=?", [itemtext]) turliste = [tur[0] for tur in self.im.fetchall()] for tura in turliste: turliste = tura self.im.execute("select Turkce from DimTur where Zazaca=?", [itemtext]) turkAnlam = [tur[0] for tur in self.im.fetchall()] for tr in turkAnlam: self.cumleList1.addItem(itemtext + "(" + turliste + ")" + " : " + tr) self.im.execute( "select OrnekZazacaCumle from DimTur where Zazaca=?", [itemtext]) ornekZaza = [zaza[0] for zaza in self.im.fetchall()] for za in ornekZaza: ornekZaza = za self.cumleList2.addItem(ornekZaza) self.im.execute( "select OrnekTurkceCumle from DimTur where Zazaca=?", [itemtext]) ornekTurk = [turk[0] for turk in self.im.fetchall()] for orn in ornekTurk: ornekTurk = orn self.cumleList3.addItem(ornekTurk) if self.DilGrup.checkedId() == 2: self.cumleList1.clear() self.cumleList2.clear() self.cumleList3.clear() itemtext = [ str(x.text()) for x in self.kelimeListesi.selectedItems() ] for it in itemtext: itemtext = it self.im.execute("select Tur from DimTur where Turkce=?", [itemtext]) turliste = [tur[0] for tur in self.im.fetchall()] for tura in turliste: turliste = tura self.im.execute("select Zazaca from DimTur where Turkce=?", [itemtext]) zazaAnlam = [tur[0] for tur in self.im.fetchall()] for tr in zazaAnlam: self.cumleList1.addItem(itemtext + "(" + turliste + ")" + " : " + tr) self.im.execute( "select OrnekZazacaCumle from DimTur where Turkce=?", [itemtext]) ornekTurk = [turk[0] for turk in self.im.fetchall()] for orn in ornekTurk: ornekTurk = orn self.cumleList2.addItem(ornekTurk) self.im.execute( "select OrnekTurkceCumle from DimTur where Turkce=?", [itemtext]) ornekZaza = [zaza[0] for zaza in self.im.fetchall()] for za in ornekZaza: ornekZaza = za self.cumleList3.addItem(ornekZaza) def benzerKelimeler(self): if self.DilGrup.checkedId() == 1: self.VT = sqlite3.connect("DimiliVT.sqlite") self.im = self.VT.cursor() self.kelimeListesi.clear() kelime = self.araKutu.text() if kelime == "" or kelime == None: self.kelimeListesi.clear() else: self.im.execute( "select Zazaca from DimTur where Zazaca like ? order by Zazaca ", [kelime + '%']) zazaListe = [za[0] for za in self.im.fetchall()] for i in zazaListe: self.kelimeListesi.addItem(i) if self.DilGrup.checkedId() == 2: self.VT = sqlite3.connect("DimiliVT.sqlite") self.im = self.VT.cursor() kelime = self.araKutu.text() self.kelimeListesi.clear() if kelime == "" or kelime == None: self.kelimeListesi.clear() else: self.im.execute( "select Turkce from DimTur where Turkce like ? ", [kelime + '%']) turkListe = [tu[0] for tu in self.im.fetchall()] for i in turkListe: self.kelimeListesi.addItem(i) def dilSecme(self, ind): if ind == 1: self.araKutu.setText("") self.kelimeListesi.clear() self.cumleList1.clear() self.cumleList2.clear() self.cumleList3.clear() self.Dil1.setStyleSheet("background:#66FF00") self.Dil2.setStyleSheet("background-color:#E41841") if ind == 2: self.araKutu.setText("") self.kelimeListesi.clear() self.cumleList1.clear() self.cumleList2.clear() self.cumleList3.clear() self.Dil2.setStyleSheet("background:#66FF00") self.Dil1.setStyleSheet("background-color:#E41841") def hakkinda(self): QMessageBox.about( self, "Program Hakkında", "Bu program <b>bla bla</b> tarafından programlanmıştır. 2015")
class TfrmBase(QMainWindow, TScreenStates): recordCount = 0 def __init__(self, parent=None): super(TfrmBase, self).__init__() self.FOnStateChange = self.onStateChange self.activeState = self.ssInactive self._defaultSettings() self._createWidgets() self._setEvents() def _defaultSettings(self): self.setObjectName("frmBase") self.resize(640, 480) self.setMinimumSize(QSize(640, 480)) def _createWidgets(self): self._createLayout() self._createMenus() self._createToolBar() self._createStatusBar() self._createPages() self._setLayouts() def _createLayout(self): self.clientArea = QWidget() self.clientArea.setSizePolicy( QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) self.clientArea.setMinimumSize(QSize(640, 400)) self.clientArea.setBaseSize(QSize(640, 400)) self.clientArea.setLayoutDirection(Qt.LeftToRight) self.clientArea.setObjectName("clientArea") self.gridLayout = QGridLayout(self.clientArea) self.gridLayout.setContentsMargins(0, 0, 0, 0) self.gridLayout.setSpacing(0) self.gridLayout.setObjectName("gridLayout") def _createMenus(self): # Create a Menu Bar self.mnMenu = self.menuBar() self.mnMenu.setObjectName("mnMenu") # Create all Top Menus self.mnApp = QMenu('&Aplicação') self.mnApp.setObjectName('mnApp') self.mnOpe = QMenu('&Operação') self.mnOpe.setObjectName("mnOperations") self.mnNav = QMenu('&Navegação') self.mnNav.setObjectName("mnNav") # Set Menus to MenuBar self.mnMenu.addMenu(self.mnNav) self.mnMenu.addMenu(self.mnOpe) self.mnMenu.addMenu(self.mnApp) # Crealte all Actions to Application Menu self._createAppActions() self._createOpeActions() self._setMenuActions() self.mnMenu.addAction(self.mnApp.menuAction()) self.mnMenu.addAction(self.mnOpe.menuAction()) self.mnMenu.addAction(self.mnNav.menuAction()) self._settingActionsEvents() def _createAppActions(self): # Exit Program Action self.acExit = QAction( self.getIcon("./resources/exit.ico", QSize(32, 32)), '&Sair') self.acExit.setObjectName("acExit") self.acExit.setShortcut('Ctrl+Q') self.acExit.setStatusTip('Finalizar o Programa') self.acExit.triggered.connect(self.closeApp) def _createOpeActions(self): # Search Action self.acSearch = QAction( self.getIcon("./resources/Search.ico", QSize(32, 32)), '&Pesquisar') self.acSearch.setObjectName("acSearch") self.acSearch.setShortcut('F5,Ctrl+P') self.acSearch.setStatusTip( 'Preenche o Filtro para Selecionar Registros') # List Action self.acList = QAction( self.getIcon("./resources/list.ico", QSize(32, 32)), '&Listar') self.acList.setShortcut('Ctrl+L') self.acList.setStatusTip('Listar todos os Registros') self.acList.setObjectName("acList") # Insert Action self.acInsert = QAction( self.getIcon("./resources/db_add.ico", QSize(32, 32)), '&Inserir') self.acInsert.setShortcut('F2,Ins') self.acInsert.setStatusTip('Incluir Novo Registros') self.acInsert.setObjectName("acInsert") # Update Action self.acUpdate = QAction( self.getIcon("./resources/db_update.ico", QSize(32, 32)), '&Editar') self.acUpdate.setShortcut('Ctrl+U') self.acUpdate.setStatusTip('Editar o Registro Atual') self.acUpdate.setObjectName("acUpdate") # Delete Action self.acDelete = QAction( self.getIcon("./resources/db_remove.ico", QSize(32, 32)), '&Excluir') self.acDelete.setShortcut('Ctrl+Del') self.acDelete.setStatusTip('Exclui o Registro Atual') self.acDelete.setObjectName("acDelete") # Save Action self.acSave = QAction( self.getIcon("./resources/db_commit.ico", QSize(32, 32)), '&Salvar') self.acSave.setShortcut('F10,Ctrl+S') self.acSave.setStatusTip('Salva as Alterações do Registro') self.acSave.setObjectName("acSave") # Cancel Action self.acCancel = QAction( self.getIcon("./resources/cancel.ico", QSize(32, 32)), '&Cancelar') self.acCancel.setShortcut('Esc') self.acCancel.setStatusTip('Cancela as Alterações do Registro') self.acCancel.setObjectName("acCancel") # First Action self.acFirst = QAction( self.getIcon("./resources/start.ico", QSize(32, 32)), '&Início') self.acFirst.setShortcut('Ctrl+Left') self.acFirst.setStatusTip('Vai para o Primeiro Registro') self.acFirst.setObjectName("acFirst") # Prior Action self.acPrior = QAction( self.getIcon("./resources/left.ico", QSize(32, 32)), '&Anterior') self.acPrior.setShortcut('Left') self.acPrior.setStatusTip('Vai para o Registro Anterior') self.acPrior.setObjectName("acPrior") # Next Action self.acNext = QAction( self.getIcon("./resources/right.ico", QSize(32, 32)), '&Próximo') self.acNext.setShortcut('Right') self.acNext.setStatusTip('Vai para o Próximo Registro') self.acNext.setObjectName("acNext") # Last Action self.acLast = QAction( self.getIcon("./resources/end.ico", QSize(32, 32)), '&Último') self.acLast.setShortcut('Ctrl+Right') self.acLast.setStatusTip('Vai para o Último Registro') self.acLast.setObjectName("acLast") # Form Title Action self.dcTitle = QAction() font = QFont() font.setPointSize(14) font.setBold(True) font.setWeight(75) self.dcTitle.setFont(font) self.dcTitle.setObjectName("dcTitle") def getIcon(self, res: str, size: QSize) -> QIcon: icon = QIcon() icon.addPixmap( QPixmap(res).scaled(size.width(), size.height(), Qt.KeepAspectRatio), QIcon.Active, QIcon.On) return icon def _setMenuActions(self): # Set Menu Application Actions self.mnApp.addAction(self.acExit) # Set Menu Operations Actions self.mnOpe.addAction(self.acSearch) self.mnOpe.addAction(self.acList) self.mnOpe.addSeparator() self.mnOpe.addAction(self.acInsert) self.mnOpe.addAction(self.acUpdate) self.mnOpe.addAction(self.acDelete) self.mnOpe.addSeparator() self.mnOpe.addAction(self.acSave) self.mnOpe.addAction(self.acCancel) # Set Menu Navigation Actions self.mnNav.addAction(self.acFirst) self.mnNav.addAction(self.acPrior) self.mnNav.addAction(self.acNext) self.mnNav.addAction(self.acLast) def _settingActionsEvents(self): # Set Menu Operations Trigger onClick self.acSearch.triggered.connect( lambda: self.setFormStatus(self.ssSearch)) self.acList.triggered.connect( lambda: self.setFormStatus(self.ssSearchAll)) self.acInsert.triggered.connect( lambda: self.setFormStatus(self.ssInsert)) self.acUpdate.triggered.connect( lambda: self.setFormStatus(self.ssUpdate)) self.acDelete.triggered.connect( lambda: self.setFormStatus(self.ssDelete)) self.acSave.triggered.connect(lambda: self.setFormStatus(self.ssPost)) self.acCancel.triggered.connect( lambda: self.setFormStatus(self.ssCancel)) # Set Menu Navigation Trigger onClick self.acFirst.triggered.connect( lambda: self.setFormStatus(self.ssFirst)) self.acPrior.triggered.connect( lambda: self.setFormStatus(self.ssPrior)) self.acNext.triggered.connect(lambda: self.setFormStatus(self.ssNext)) self.acLast.triggered.connect(lambda: self.setFormStatus(self.ssLast)) def _createToolBar(self): # Create a tbActions ToolBar self.tbActions = QToolBar() self.tbActions.setMinimumSize(QSize(300, 34)) self.tbActions.setMaximumSize(QSize(16777215, 34)) self.tbActions.setBaseSize(QSize(300, 34)) self.tbActions.setAcceptDrops(False) self.tbActions.setToolTipDuration(3) self.tbActions.setAllowedAreas(Qt.TopToolBarArea) self.tbActions.setObjectName("tbActions") self.addToolBar(Qt.TopToolBarArea, self.tbActions) # Create a tbTitle ToolBar self.tbTitle = QToolBar() self.tbTitle.setMinimumSize(QSize(340, 34)) self.tbTitle.setMaximumSize(QSize(16777215, 34)) self.tbTitle.setBaseSize(QSize(341, 34)) self.tbTitle.setAllowedAreas(Qt.TopToolBarArea) self.tbTitle.setToolButtonStyle(Qt.ToolButtonTextOnly) self.tbTitle.setFloatable(False) self.tbTitle.setObjectName("tbTitle") # self.tbTitle.setLabelAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.addToolBar(Qt.TopToolBarArea, self.tbTitle) # Call Add Actions to ToolBar self._setToolBarActions() def _setToolBarActions(self): # Set ToolBar Actions self.tbActions.addAction(self.acSearch) self.tbActions.addAction(self.acInsert) self.tbActions.addAction(self.acUpdate) self.tbActions.addAction(self.acDelete) self.tbActions.addSeparator() self.tbActions.addAction(self.acSave) self.tbActions.addAction(self.acExit) self.tbTitle.addAction(self.dcTitle) def _createStatusBar(self): self.sbStatus = QStatusBar() self.sbStatus.setMaximumHeight(24) self.sbStatus.setObjectName("sbStatus") self.sbStatus.setStyleSheet(""" .QLabel { background-color: #FFFFFF; color: #000000; } """) self.lbStatus = QLabel(self.sbStatus) self.lbStatus.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.lbStatus.setText('Inactive') self.lbStatus.setMinimumSize(QSize(130, 15)) self.lbStatus.setFrameShape(QFrame.Panel) self.lbStatus.setFrameShadow(QFrame.Sunken) self.sbStatus.addPermanentWidget(self.lbStatus) self.setStatusBar(self.sbStatus) def _createPages(self): self.tabMain = QTabWidget(self.clientArea) self.tabMain.setSizePolicy( QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) self.tabMain.setTabPosition(QTabWidget.South) self.tabMain.setObjectName("tabMain") self.pgList = QWidget(self.tabMain) self.pgList.setObjectName("pgList") self.pgDetail = QWidget(self.tabMain) self.pgDetail.setObjectName("pgDetail") self.tabMain.addTab(self.pgList, "") self.tabMain.addTab(self.pgDetail, "") self._createPageListContent() def _createPageListContent(self): self.treeWidget = QTreeWidget(self.pgList) self.treeWidget.setSizePolicy( QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) self.treeWidget.setFrameShape(QFrame.NoFrame) self.treeWidget.setFrameShadow(QFrame.Plain) self.treeWidget.setColumnCount(3) self.treeWidget.setObjectName("treeWidget") self.treeWidget.headerItem().setText(0, "Campo") self.treeWidget.headerItem().setText(1, "Campo") self.treeWidget.headerItem().setText(2, "Campo") self.treeWidget.setGeometry(QRect(0, 0, 640, 370)) self.treeWidget.setMinimumSize(QSize(640, 370)) self.tabMain.setCurrentIndex(0) def _setLayouts(self): self.gridLayout.addWidget(self.tabMain, 0, Qt.AlignBottom | Qt.AlignRight, 1, 1) self.setCentralWidget(self.clientArea) def translateForm(self): self._translate = QCoreApplication.translate self.setWindowTitle( self._translate("TfrmBase", "Tela de Básica de Cadastros")) self.mnApp.setTitle(self._translate("TfrmBase", "Aplicação")) self.mnOpe.setTitle(self._translate("TfrmBase", "Operações")) self.mnNav.setTitle(self._translate("TfrmBase", "Navegação")) self.sbStatus.setToolTip(self._translate("TfrmBase", "Barra de Status")) self.tbActions.setWindowTitle( self._translate("TfrmBase", "Ferramentas")) self.tbActions.setToolTip( self._translate("TfrmBase", "Barra de Ferramentas")) self.tbTitle.setWindowTitle(self._translate("TfrmBase", "Descrição")) self.acExit.setText(self._translate("TfrmBase", "&Sair")) self.acExit.setToolTip(self._translate("TfrmBase", "Sair do Programa")) self.acSearch.setText(self._translate("TfrmBase", "&Pesquisar")) self.acSearch.setStatusTip( self._translate("TfrmBase", "Procurar Por um Registro")) self.acList.setText(self._translate("TfrmBase", "&Listar Todos")) self.acList.setStatusTip( self._translate("TfrmBase", "Lista todos os Registros")) self.acInsert.setText(self._translate("TfrmBase", "&Inserir")) self.acInsert.setStatusTip( self._translate("TfrmBase", "Adicionar Registro")) self.acUpdate.setText(self._translate("TfrmBase", "&Editar")) self.acUpdate.setStatusTip( self._translate("TfrmBase", "Editar Registro")) self.acDelete.setText(self._translate("TfrmBase", "E&xcluir")) self.acDelete.setStatusTip( self._translate("TfrmBase", "Excluir Registro")) self.acSave.setText(self._translate("TfrmBase", "&Salvar")) self.acSave.setToolTip(self._translate("TfrmBase", "Salvar Registro")) self.acCancel.setText(self._translate("TfrmBase", "&Cancelar")) self.acCancel.setToolTip( self._translate("TfrmBase", "Cencelar Alterações")) self.dcTitle.setText( self._translate("TfrmBase", "Título da Tela de Cadastros")) self.dcTitle.setToolTip( self._translate("TfrmBase", "Título da Tela de Cadastros")) self.tabMain.setTabText( self.tabMain.indexOf(self.pgList), self._translate("TfrmBase", "Lista dos Registros")) self.tabMain.setTabToolTip( self.tabMain.indexOf(self.pgList), self._translate("TfrmBase", "Listagem das Ferramentas")) self.tabMain.setTabText( self.tabMain.indexOf(self.pgDetail), self._translate("TfrmBase", "Detalhes do Registro Selecionando")) @property def activeState(self): return self._activeValue @property def activeStateColor(self): return self.activeValue['FG'] @property def activeStateBackgroud(self): return self.activeValue['BG'] @activeState.setter # Seta a Propriedade _activeState def activeState(self, value: int): self.workValue = value self._activeState = value def setScreenState(self, stt: int): self.acExit.setEnabled(self.inBrowse(stt)) # Set Menu Operations Actions self.acSearch.setEnabled((self.inBrowse(stt) or (self.recordCount == 0))) self.acList.setEnabled((self.inBrowse(stt) or (self.recordCount == 0))) self.acInsert.setEnabled(self.inBrowse(stt)) self.acUpdate.setEnabled((self.inBrowse(stt) and (self.recordCount > 0))) self.acDelete.setEnabled((self.inBrowse(stt) and (self.recordCount > 0))) self.acSave.setEnabled(self.inUpdate(stt)) self.acCancel.setEnabled(self.inUpdate(stt)) # Set Menu Navigation Actions self.acFirst.setEnabled((self.inBrowse(stt) and (self.recordCount > 0))) self.acPrior.setEnabled((self.inBrowse(stt) and (self.recordCount > 0))) self.acNext.setEnabled((self.inBrowse(stt) and (self.recordCount > 0))) self.acLast.setEnabled((self.inBrowse(stt) and (self.recordCount > 0))) # Set tab Main if state in Browse enabled self.tabMain.setEnabled(self.inBrowse(stt)) def _layoutWidgets(self): return (self.frmLayout.itemAt(i) for i in range(self.frmLayout.count())) def _getAllFields(self): arrFields = [] for w in self._layoutWidgets(): if (not (isinstance(w, QLabel))): arrFields.append(w) return arrFields def setEnableFields(self, enable: bool = True): # Enable All Fields for controls in self._layoutWidgets(): QWidget(controls).setEnabled(enable) def clearFields(self): # cliar content of all fileds for controls in self._getAllFields(): QWidget(controls).setText('') def setColorFields(self): # cliar content of all fileds style = ".QWidget { backgroud-color: " + self.activeStateBackgroud + "; }" for controls in self._getAllFields(): QWidget(controls).setStyle(style) def showDataDetails(self): # move data of selected record to fileds if (self.tabMain.currentIndex() == 0): self.tabMain.setCurrentIndex(1) def filterRecord(self): raise NotImplementedError(500) def getFirstRecord(self): raise NotImplementedError(500) def getPriorRecord(self): raise NotImplementedError(500) def getNextRecord(self): raise NotImplementedError(500) def getLastRecord(self): raise NotImplementedError(500) def insertRecord(self): raise NotImplementedError(500) def deleteRecord(self): raise NotImplementedError(500) def updateRecord(self): raise NotImplementedError(500) def postRecord(self): raise NotImplementedError(500) def execOpertations(self, state: int): if ((state == self.ssFilter) or (state == self.ssSearchAll)): self.filterRecord() elif (state == self.ssFirst): self.getFirstRecord() elif (state == self.ssPrior): self.getPriorRecord() elif (state == self.ssNext): self.getNextRecord() elif (state == self.ssLast): self.getLastRecord() elif (state == self.ssInsert): self.insertRecord() elif (state == self.ssDelete): self.deleteRecord() elif (state == self.ssUpdate): self.updateRecord() elif (state == self.ssPost): self.postRecord() else: raise NotImplementedError(401, 'Operação não suportada') @pyqtSlot(int) def setFormStatus(self, state: int): if ((state == self.ssSearch) and (self.activeState != state)): self.clearFields() self.setColorFields() self.showDataDetails() if (self.activeState != state): self.activeState = state if (state == self.ssCancel): self.activeState = self.ssBrowse @pyqtSlot(int, int, dict, str) def onStateChange(self, NewState: int, OldState: int, Result: dict = {}, Err: str = ''): try: # show screen state on status bar state = self.getStateProperties(NewState) style = '.QLabel { background-color: ' + state[ 'BG'] + '; color: ' + state['FG'] + '; }' self.sbStatus.setStyleSheet(style) self.lbStatus.setText(state['Descr']) # call operation into child screen self.execOpertations(NewState) # change buttons states self.setScreenState(NewState) # set result status code and result satatus Message self.setResultStatusCode = 200 self.setResultStatusMessage = '' except Exception as e: self.ResultStatusCode = 200 self.ResultStatusMessage = str(e) QMessageBox.critical(self, self.windowTitle(), self.ResultStatusMessage) return self.result @pyqtSlot() def tabMainChanged(self): self.sbStatus.showMessage('TabMain change tabIndex to (' + str(self.tabMain.currentIndex()) + ')!') if (self.tabMain.currentIndex() == 1): self.showDataDetails() @pyqtSlot() def InsertData(self): # self.sbStatus.showMessage('Prepare to insert data....') pass def _setEvents(self): self.tabMain.blockSignals( True) # just for not showing the initial message self.tabMain.currentChanged.connect(self.tabMainChanged) # changed! self.tabMain.blockSignals(False) # wait signals now @pyqtSlot() def closeApp(self): self.close()
class Window(QMainWindow): # Initialization of the GUI def __init__(self): super(Window, self).__init__() self.setGeometry(50, 50, 800, 500) self.setMinimumSize(600, 450) self.setWindowModified(False) self.setWindowTitle("QC v" + appVersion) self.setStyleSheet(GUI_Style.mainWindow) # This builds the main widget for the GUI window to hold main_widget = QWidget() self.setCentralWidget(main_widget) # Create Threads self.Compiler_Thread = QCompilerThread() self.Progress_Bar_Thread = QProgressBarThread() self.Timer_Thread = QTimeThread() self.monitor_Thread = QMonitorThread() self.network_Thread = QNetworkThread() # Start all threads self.Compiler_Thread.start() self.Progress_Bar_Thread.start() self.Timer_Thread.start() self.monitor_Thread.start() self.network_Thread.start() self.Compiler_Thread.signalThreadSet.connect( self.Progress_Bar_Thread.setPBar) # Start monitoring folder self.monitor_Thread.setCheckFolder(True) self.network_Thread.setCheckFolder(True) # Instantiate GUI Objects self.MainTitle() self.inputFolderName() self.outputFolderName() self.folder_drop() self.Folder_select_GUI() self.Output_select_GUI() self.CreateProgressBar() self.StatusBar() self.ElapsedTime() self.AppliedLogo() self.Start_Btn_GUI() self.setStatusBar(self.statusBar) # Add title and logo to horizontal layout horizontal_title_layout = QHBoxLayout() horizontal_title_layout.addWidget(self.Logo) horizontal_title_layout.addWidget(self.UpperText) horizontal_title_layout.setSpacing(0) horizontal_title_layout.setContentsMargins(0, 0, 0, 0) # Create layout for folder names self.label_V = QVBoxLayout() self.label_V.addWidget(self.InputLabel) self.label_V.addWidget(self.OutputLabel) # Create layout for folder icon buttons self.select_V = QVBoxLayout() self.select_V.addWidget(self.folder_sel) self.select_V.addWidget(self.out_folder_sel) # Add buttons to horizontal layout horizontal_button_layout = QHBoxLayout() horizontal_button_layout.addLayout(self.label_V) horizontal_button_layout.addLayout(self.select_V) horizontal_button_layout.addWidget(self.strt_btn) horizontal_button_layout.setAlignment(Qt.AlignCenter) horizontal_button_layout.setSpacing(50) horizontal_button_layout.setContentsMargins(0, 0, 0, 0) # Add horizontal button layout to vertical layout verticalGUILayout = QVBoxLayout() verticalGUILayout.addLayout(horizontal_title_layout) verticalGUILayout.addLayout(horizontal_button_layout) verticalGUILayout.addWidget(self.drop_location) verticalGUILayout.addWidget(self.progress_bar) verticalGUILayout.setSpacing(20) verticalGUILayout.setContentsMargins(20, 15, 20, 20) # Set Main window layout to GUI central Widget self.centralWidget().setLayout(verticalGUILayout) self.centralWidget().isWindow() self.show() # Create Main Title Text def MainTitle(self): self.UpperText = QLabel(self) self.UpperText.setText("Quartus Compiler") self.UpperText.setStyleSheet(GUI_Style.mainTitle) self.UpperText.setScaledContents(True) self.UpperText.setWordWrap(True) def inputFolderName(self): self.InputLabel = QLabel(self) self.InputLabel.setStyleSheet(GUI_Style.subTitle) self.InputLabel.setText("Choose Folder To Compile:") def outputFolderName(self): self.OutputLabel = QLabel(self) self.OutputLabel.setStyleSheet(GUI_Style.subTitle) self.OutputLabel.setText("Choose Output Directory:") # Create Main Title Logo def AppliedLogo(self): self.Logo = SecretButton(self, "", self.UpperText, self.InputLabel, self.OutputLabel, self.drop_location, self.statusBar) self.Logo.setMaximumSize(150, 75) self.Logo.setMinimumSize(125, 30) self.Logo.setStyleSheet(GUI_Style.logo) self.Logo.pressed.connect(self.Logo.On_Click) self.Logo.released.connect(self.Logo.Un_Click) self.Logo.setIcon(QIcon(Logo_Path)) self.Logo.setIconSize(QSize(150, 75)) # Creating button for folder selection def Folder_select_GUI(self): self.folder_sel = Select_Folder(self, "", self.drop_location) self.folder_sel.setStyleSheet(GUI_Style.folder_btn) self.folder_sel.pressed.connect(self.folder_sel.On_Click) self.folder_sel.released.connect(self.folder_sel.Un_Click) self.folder_sel.setIcon(QIcon(Folder_Icon_Path)) self.folder_sel.setIconSize(QSize(50, 50)) def Output_select_GUI(self): self.out_folder_sel = Select_Output_Folder(self, "", self.drop_location) self.out_folder_sel.setStyleSheet(GUI_Style.folder_btn) self.out_folder_sel.pressed.connect(self.out_folder_sel.On_Click) self.out_folder_sel.released.connect(self.out_folder_sel.Un_Click) self.out_folder_sel.setIcon(QIcon(Folder_Icon_Path)) self.out_folder_sel.setIconSize(QSize(50, 50)) # Creating button for starting procedure def Start_Btn_GUI(self): self.strt_btn = Start_Button(self, "", self.folder_sel, self.drop_location, self.Compiler_Thread, self.out_folder_sel, self.progress_bar, self.elapsed_time, self.statusBar, self.Timer_Thread, self.monitor_Thread, self.Logo, self.network_Thread) self.strt_btn.setIcon(QIcon(playButton_Pressed)) self.strt_btn.setIconSize(QSize(150, 75)) self.strt_btn.pressed.connect(self.strt_btn.On_Click) self.strt_btn.released.connect(self.strt_btn.Un_Click) self.strt_btn.setStyleSheet(GUI_Style.start_btn) self.strt_btn.setMinimumHeight(75) self.strt_btn.setMinimumWidth(100) # Creates textbox area for drag and drop folder paths def folder_drop(self): self.drop_location = FolderDrop(self) self.drop_location.setMinimumSize(400, 125) self.drop_location.setWordWrap(True) self.drop_location.setStyleSheet(GUI_Style.DropBox) # Create Status Bar def StatusBar(self): self.statusBar = QStatusBar() self.statusBar.setStyleSheet(GUI_Style.statusBar) self.statusBar.showMessage("Initializing... ", 5000) def CreateProgressBar(self): self.progress_bar = ProgressBar(self, self.Progress_Bar_Thread) self.progress_bar.setGeometry(200, 80, 270, 20) self.progress_bar.setStyleSheet(GUI_Style.progressBar) self.progress_bar.setTextVisible(True) self.progress_bar.setAlignment(Qt.AlignCenter) def ElapsedTime(self): self.elapsed_time = QElapsedTimer() # Close threads when GUI exits def closeEvent(self, *args, **kwargs): self.Compiler_Thread.Set_Exit_Program(True) self.Compiler_Thread.wait(100) self.Progress_Bar_Thread.Set_Exit_Program(True) self.Progress_Bar_Thread.wait(100)
class CodeEditorTabWidget(QWidget): """ Widget which representing code editor with tabs. """ def __init__(self, parent=None): QWidget.__init__(self, parent) vertical_layout = QVBoxLayout() self.tab_widget = QTabWidget() self.tab_widget.setTabBar(TabBar()) self.tab_widget.setTabsClosable(True) self.tab_widget.setUsesScrollButtons(True) self.tab_widget.setMovable(True) self.tab_widget.tabCloseRequested.connect(self.close_tab) self.tab_widget.currentChanged.connect(self.tab_changed) self.editor_status_bar = QStatusBar(self) self.editor_status_bar.setStyleSheet("QStatusBar{border-bottom: 1px outset grey; border-left: 1px outset grey; border-right: 1px outset grey;}") self.editor_status_bar.hide() vertical_layout.setSpacing(0) vertical_layout.setContentsMargins(5, 22, 0, 0) vertical_layout.addWidget(self.tab_widget) vertical_layout.addWidget(self.editor_status_bar) self.setLayout(vertical_layout) self.opened_tabs = 0 def open_file(self, file_path: str) -> None: """ Open file in new tab. Args: file_path(str): file path """ with open(file_path, 'r') as f: code_editor = CodeEditorWidget(self) code_editor.load_file(f) code_editor.file_saved = True code_editor.opened_file = f.name self.add_tab(code_editor, os.path.basename(f.name)) def new_file(self) -> None: """ Create new tab / file """ code_editor = CodeEditorWidget(self) code_editor.file_saved = False self.add_tab(code_editor, "NoName") def save_file(self, file_path: str = None) -> None: """ Save current file(as). Args: file_path(str): if file path is not None. Save as method called """ file = file_path or self.get_current_file() current_widget = self.get_current_widget() with open(file, 'w') as f: f.write(current_widget.get_plain_text()) current_widget.opened_file = file current_widget.file_saved = True self.tab_changed() self.set_tab_text(os.path.basename(file)) def add_tab(self, code_editor: CodeEditorWidget, file_name: str) -> None: """ Add new tab to the widget. Args: code_editor(CodeEditorWidget): code editor widget in new tab file_name(str): name of new tab - file name """ new_index = self.tab_widget.count() self.tab_widget.addTab(code_editor, file_name) self.tab_widget.setCurrentIndex(new_index) self.opened_tabs += 1 def tab_changed(self) -> None: """ Change hide/show information in editor status bar. Update line and column in main status bar. This method is called when currentChanged signal is emitted. """ current_widget = self.get_current_widget() if not current_widget: self.editor_status_bar.hide() return else: self.editor_status_bar.showMessage(self.get_current_file() or "File not saved") self.editor_status_bar.show() current_widget.main_window.set_new_cursor_position(current_widget.get_cursor()) def set_tab_text(self, text: str, index: int = None) -> None: """ Set new text of current tab Args: text(str): new text index(int): index of tab. If None -> use current """ current_index = index or self.tab_widget.currentIndex() self.tab_widget.setTabText(current_index, text) def close_tab(self, index: int) -> None: """ Close tab at index. Args: index(int): index of tab """ self.tab_widget.removeTab(index) self.opened_tabs -= 1 def is_file_saved(self) -> bool: """ Return if file in current widget is saved. Returns: bool: True if file is save else False """ current_tab = self.get_current_widget() return current_tab.file_saved def get_current_widget(self) -> CodeEditorWidget: """ Return widget in current active tab Returns: CodeEditorWidget: Code editor in current tab """ return self.tab_widget.currentWidget() def get_current_file(self) -> str: """ Return file path of file in current active tab Returns: str: file path of file in active tab """ return self.get_current_widget().opened_file
class MainInterface(QMainWindow): def __init__(self, screen_scale_rate, user): super(MainInterface, self).__init__() self.rate = screen_scale_rate # 屏幕缩放比例 self.lock_sign = 0 self.user = user self.get_settin() self.init_ui() self._padding = 5 # 设置边界宽度为5 # 设置鼠标跟踪判断扳机默认值 # reference: https://blog.csdn.net/qq_38528972/article/details/78573591 self._move_drag = False self._corner_drag = False self._bottom_drag = False self._right_drag = False self._right_rect = [] self._bottom_rect = [] self._corner_rect = [] self.image = None self.load_local_img = False self.load_local_img_path = folder_path self.save_result_path = [folder_path] # 写成list, 传入方式为引用, 便于修改 def init_ui(self): # 窗口尺寸 self.resize(800 * self.rate, 120 * self.rate) self.setMouseTracking(True) # 设置widget鼠标跟踪 # 窗口无标题栏、窗口置顶、窗口透明 self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint) # Mac系统下隐藏标题栏同时窗口透明会造成窗口不能伸缩 self.setAttribute(Qt.WA_TranslucentBackground) # self.setWindowOpacity(0.7) # 窗口图标 self.icon = QIcon() self.icon.addPixmap(QPixmap(folder_path + "/config/logo.ico"), QIcon.Normal, QIcon.On) self.setWindowIcon(self.icon) # 系统托盘 self.tray = QSystemTrayIcon(self) self.tray.setIcon(self.icon) self.tray.activated.connect(self.show) self.tray.show() # 鼠标样式 # self.pixmap = QPixmap(folder_path + '/config/光标.png') # self.cursor = QCursor(self.pixmap, 0, 0) # self.setCursor(self.cursor) # 工具栏标签 self.titleLabel = QLabel(self) self.titleLabel.setGeometry(0, 0, 800 * self.rate, 30 * self.rate) self.titleLabel.setStyleSheet( "background-color:rgba(62, 62, 62, 0.01)") self.Font = QFont() self.Font.setFamily("华康方圆体W7") self.Font.setPointSize(15) # 翻译框 self.translateText = QTextBrowser(self) self.translateText.setGeometry(0, 30 * self.rate, 1500 * self.rate, 90 * self.rate) self.translateText.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.translateText.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.translateText.setStyleSheet("border-width:0;\ border-style:outset;\ border-top:0px solid #e8f3f9;\ color:white;\ font-weight: bold;\ background-color:rgba(62, 62, 62, %s)" % (self.horizontal)) self.translateText.setFont(self.Font) # 翻译框加入描边文字 self.format = QTextCharFormat() self.format.setTextOutline( QPen(QColor('#1E90FF'), 0.7, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.translateText.mergeCurrentCharFormat(self.format) self.translateText.append("欢迎~ 么么哒~") self.format.setTextOutline( QPen(QColor('#FF69B4'), 0.7, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.translateText.mergeCurrentCharFormat(self.format) self.translateText.append("点击设置修改待识别语言类型") self.format.setTextOutline( QPen(QColor('#674ea7'), 0.7, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.translateText.mergeCurrentCharFormat(self.format) self.translateText.append("点击截屏按钮选择识图区域") # 翻译框根据内容自适应大小 self.document = self.translateText.document() self.document.contentsChanged.connect(self.textAreaChanged) # 此Label用于当鼠标进入界面时给出颜色反应 self.dragLabel = QLabel(self) self.dragLabel.setObjectName("dragLabel") self.dragLabel.setGeometry(0, 0, 4000 * self.rate, 2000 * self.rate) # 截屏范围按钮 self.RangeButton = QPushButton(qticon('fa.crop', color='white'), "", self) self.RangeButton.setIconSize(QSize(20, 20)) self.RangeButton.setGeometry( QRect(193 * self.rate, 5 * self.rate, 20 * self.rate, 20 * self.rate)) self.RangeButton.setToolTip( '<b>截屏识别图片 ScreenShot Range</b><br>框选要识别的区域') self.RangeButton.setStyleSheet("background-color:rgba(62, 62, 62, 0);") self.RangeButton.setCursor(QCursor(Qt.PointingHandCursor)) self.RangeButton.hide() # 运行按钮 self.StartButton = QPushButton(qticon('fa.play', color='white'), "", self) self.StartButton.setIconSize(QSize(20, 20)) self.StartButton.setGeometry( QRect(233 * self.rate, 5 * self.rate, 20 * self.rate, 20 * self.rate)) self.StartButton.setToolTip( '<b>识别 Recognize</b><br>点击开始(手动)<br>开始/停止(自动)') self.StartButton.setStyleSheet("background: transparent") self.StartButton.clicked.connect(self.start_login) self.StartButton.setCursor(QCursor(Qt.PointingHandCursor)) self.StartButton.hide() # 手动打开文件按钮 self.OpenButton = QPushButton( qticon('fa.folder-open-o', color='white'), "", self) self.OpenButton.setIconSize(QSize(20, 20)) self.OpenButton.setGeometry( QRect(273 * self.rate, 5 * self.rate, 20 * self.rate, 20 * self.rate)) self.OpenButton.setToolTip('<b>打开识别图片 Open image</b><br> 识别本地图片') self.OpenButton.setStyleSheet("background-color:rgba(62, 62, 62, 0);") self.OpenButton.setCursor(QCursor(Qt.PointingHandCursor)) self.OpenButton.clicked.connect(self.open_image) self.OpenButton.hide() # 复制按钮 self.CopyButton = QPushButton(qticon('fa.copy', color='white'), "", self) self.CopyButton.setIconSize(QSize(20, 20)) self.CopyButton.setGeometry( QRect(313 * self.rate, 5 * self.rate, 20 * self.rate, 20 * self.rate)) self.CopyButton.setToolTip('<b>复制 Copy</b><br>将当前识别到的文本<br>复制至剪贴板') self.CopyButton.setStyleSheet("background-color:rgba(62, 62, 62, 0);") self.CopyButton.setCursor(QCursor(Qt.PointingHandCursor)) self.CopyButton.clicked.connect(lambda: copy(self.original)) self.CopyButton.hide() # 朗读原文按钮 self.playVoiceButton = QPushButton(qticon('fa.music', color='white'), "", self) self.playVoiceButton.setIconSize(QSize(20, 20)) self.playVoiceButton.setGeometry( QRect(353 * self.rate, 5 * self.rate, 20 * self.rate, 20 * self.rate)) self.playVoiceButton.setToolTip('<b>朗读原文 Play Voice</b><br>朗读识别到的原文') self.playVoiceButton.setStyleSheet("background: transparent") self.playVoiceButton.clicked.connect(self.play_voice) self.playVoiceButton.setCursor(QCursor(Qt.PointingHandCursor)) self.playVoiceButton.hide() # 翻译模式按钮 self.switchBtn = SwitchBtn(self) self.switchBtn.setGeometry(393 * self.rate, 5 * self.rate, 50 * self.rate, 20 * self.rate) self.switchBtn.setToolTip('<b>模式 Mode</b><br>手动识别/自动识别') self.switchBtn.checkedChanged.connect(self.getState) self.switchBtn.setCursor(QCursor(Qt.PointingHandCursor)) self.switchBtn.hide() # 识别原文字类型提示框 languageFont = QFont() languageFont.setFamily("华康方圆体W7") languageFont.setPointSize(10) self.languageText = QPushButton(self) self.languageText.setIconSize(QSize(20, 20)) self.languageText.setGeometry( QRect(463 * self.rate, 5 * self.rate, 45 * self.rate, 20 * self.rate)) self.languageText.setToolTip( '<b>待识别的原文类型 </b><br>Original Language Type') self.languageText.setStyleSheet("border-width:0;\ border-style:outset;\ border-top:0px solid #e8f3f9;\ color:white;\ background-color:rgba(143, 143, 143, 0)" ) self.languageText.setCursor(QCursor(Qt.PointingHandCursor)) self.languageText.setText( config.letter_chinese_dict[self.data["language"]]) self.languageText.setFont(languageFont) self.languageText.hide() # 设置按钮 self.SettinButton = QPushButton(qticon('fa.cog', color='white'), "", self) self.SettinButton.setIconSize(QSize(20, 20)) self.SettinButton.setGeometry( QRect(518 * self.rate, 5 * self.rate, 20 * self.rate, 20 * self.rate)) self.SettinButton.setToolTip('<b>设置 Settin</b>') self.SettinButton.setStyleSheet( "background-color:rgba(62, 62, 62, 0);") self.SettinButton.setCursor(QCursor(Qt.PointingHandCursor)) self.SettinButton.hide() # 锁按钮 self.LockButton = QPushButton(qticon('fa.lock', color='white'), "", self) self.LockButton.setIconSize(QSize(20, 20)) self.LockButton.setGeometry( QRect(562 * self.rate, 5 * self.rate, 20 * self.rate, 20 * self.rate)) self.LockButton.setToolTip('<b>锁定翻译界面 Lock</b>') self.LockButton.setStyleSheet("background-color:rgba(62, 62, 62, 0);") self.LockButton.setCursor(QCursor(Qt.PointingHandCursor)) self.LockButton.clicked.connect(self.lock) self.LockButton.hide() # 最小化按钮 self.MinimizeButton = QPushButton(qticon('fa.minus', color='white'), "", self) self.MinimizeButton.setIconSize(QSize(20, 20)) self.MinimizeButton.setGeometry( QRect(602 * self.rate, 5 * self.rate, 20 * self.rate, 20 * self.rate)) self.MinimizeButton.setToolTip('<b>最小化 Minimize</b>') self.MinimizeButton.setStyleSheet( "background-color:rgba(62, 62, 62, 0);") self.MinimizeButton.setCursor(QCursor(Qt.PointingHandCursor)) self.MinimizeButton.clicked.connect(self.showMinimized) self.MinimizeButton.hide() # 退出按钮 self.QuitButton = QPushButton(qticon('fa.times', color='white'), "", self) self.QuitButton.setIconSize(QSize(20, 20)) self.QuitButton.setGeometry( QRect(642 * self.rate, 5 * self.rate, 20 * self.rate, 20 * self.rate)) self.QuitButton.setToolTip('<b>退出程序 Quit</b>') self.QuitButton.setStyleSheet("background-color:rgba(62, 62, 62, 0);") self.QuitButton.setCursor(QCursor(Qt.PointingHandCursor)) self.QuitButton.hide() # 右下角用于拉伸界面的控件 mac系统应该注释掉 self.statusbar = QStatusBar(self) self.statusbar.setStyleSheet("background-color:rgba(62, 62, 62, 0);") self.setStatusBar(self.statusbar) # 锁定界面 def lock(self): try: if self.lock_sign == 0: self.LockButton.setIcon(qticon('fa.unlock', color='white')) self.dragLabel.hide() self.lock_sign = 1 if self.horizontal == 0.01: self.horizontal = 0 else: self.LockButton.setIcon(qticon('fa.lock', color='white')) self.LockButton.setStyleSheet( "background-color:rgba(62, 62, 62, 0);") self.dragLabel.show() self.lock_sign = 0 if self.horizontal == 0: self.horizontal = 0.01 self.translateText.setStyleSheet("border-width:0;\ border-style:outset;\ border-top:0px solid #e8f3f9;\ color:white;\ font-weight: bold;\ background-color:rgba(62, 62, 62, %s)" % (self.horizontal)) except Exception: write_error(format_exc()) # 当翻译内容改变时界面自适应窗口大小 def textAreaChanged(self): newHeight = self.document.size().height() width = self.width() self.resize(width, newHeight + 30 * self.rate) self.translateText.setGeometry(0, 30 * self.rate, width, newHeight) # 判断翻译模式键状态 def getState(self, checked): if checked: self.mode = True else: self.mode = False with open(folder_path + '/config/settin.json') as file: data = load(file) data["sign"] = 1 with open(folder_path + '/config/settin.json', 'w') as file: dump(data, file, indent=2) self.StartButton.setIcon(qticon('fa.play', color='white')) # 鼠标移动事件 def mouseMoveEvent(self, e: QMouseEvent): if self.lock_sign == 1: return try: self._endPos = e.pos() - self._startPos self.move(self.pos() + self._endPos) except Exception: write_error(format_exc()) # 鼠标移动事件 mac # def mouseMoveEvent(self, QMouseEvent): # if self.lock_sign == 1: # return # # # 判断鼠标位置切换鼠标手势 # if QMouseEvent.pos() in self._corner_rect: # self.setCursor(Qt.SizeFDiagCursor) # elif QMouseEvent.pos() in self._bottom_rect: # self.setCursor(Qt.SizeVerCursor) # elif QMouseEvent.pos() in self._right_rect: # self.setCursor(Qt.SizeHorCursor) # else: # self.setCursor(self.cursor) # # self.setCursor(Qt.ArrowCursor) # # # 当鼠标左键点击不放及满足点击区域的要求后,分别实现不同的窗口调整 # if Qt.LeftButton and self._right_drag: # # 右侧调整窗口宽度 # self.resize(QMouseEvent.pos().x(), self.height()) # QMouseEvent.accept() # elif Qt.LeftButton and self._bottom_drag: # # 下侧调整窗口高度 # self.resize(self.width(), QMouseEvent.pos().y()) # QMouseEvent.accept() # elif Qt.LeftButton and self._corner_drag: # # 右下角同时调整高度和宽度 # self.resize(QMouseEvent.pos().x(), QMouseEvent.pos().y()) # QMouseEvent.accept() # elif Qt.LeftButton and self._move_drag: # # 标题栏拖放窗口位置 # self.move(QMouseEvent.globalPos() - self.move_drag_position) # QMouseEvent.accept() # # 鼠标按下事件 def mousePressEvent(self, e: QMouseEvent): if self.lock_sign == 1: return try: if e.button() == Qt.LeftButton: self._isTracking = True self._startPos = QPoint(e.x(), e.y()) except Exception: write_error(format_exc()) # 鼠标按下事件 mac # def mousePressEvent(self, event): # # if self.lock_sign == 1: # return # # try: # # 重写鼠标点击的事件 # if (event.button() == Qt.LeftButton) and (event.pos() in self._corner_rect): # # 鼠标左键点击右下角边界区域 # self._corner_drag = True # event.accept() # elif (event.button() == Qt.LeftButton) and (event.pos() in self._right_rect): # # 鼠标左键点击右侧边界区域 # self._right_drag = True # event.accept() # elif (event.button() == Qt.LeftButton) and (event.pos() in self._bottom_rect): # # 鼠标左键点击下侧边界区域 # self._bottom_drag = True # event.accept() # elif (event.button() == Qt.LeftButton) and (event.y() < self.height()): # # 鼠标左键点击区域 # self._move_drag = True # self.move_drag_position = event.globalPos() - self.pos() # event.accept() # except Exception: # write_error(format_exc()) # # 鼠标松开事件 def mouseReleaseEvent(self, e: QMouseEvent): if self.lock_sign == 1: return try: if e.button() == Qt.LeftButton: self._isTracking = False self._startPos = None self._endPos = None except Exception: write_error(format_exc()) # 鼠标松开事件 mac # def mouseReleaseEvent(self, e: QMouseEvent): # if self.lock_sign == 1: # return # # try: # if e.button() == Qt.LeftButton: # self._isTracking = False # self._startPos = None # self._endPos = None # # # 鼠标释放后,各扳机复位 # self._move_drag = False # self._corner_drag = False # self._bottom_drag = False # self._right_drag = False # except Exception: # write_error(format_exc()) # 鼠标进入控件事件 def enterEvent(self, QEvent): if self.lock_sign == 1: self.LockButton.show() self.LockButton.setStyleSheet( "background-color:rgba(62, 62, 62, 0.7);") return try: # 显示所有顶部工具栏控件 self.switchBtn.show() self.StartButton.show() self.SettinButton.show() self.RangeButton.show() self.OpenButton.show() self.CopyButton.show() self.QuitButton.show() self.MinimizeButton.show() self.playVoiceButton.show() self.LockButton.show() self.languageText.show() self.setStyleSheet( 'QLabel#dragLabel {background-color:rgba(62, 62, 62, 0.3)}') except Exception: write_error(format_exc()) def resizeEvent(self, QResizeEvent): # 重新调整边界范围以备实现鼠标拖放缩放窗口大小,采用三个列表生成式生成三个列表 self._right_rect = [ QPoint(x, y) for x in range(self.width() - self._padding, self.width() + 1) for y in range(1, self.height() - self._padding) ] self._bottom_rect = [ QPoint(x, y) for x in range(1, self.width() - self._padding) for y in range(self.height() - self._padding, self.height() + 1) ] self._corner_rect = [ QPoint(x, y) for x in range(self.width() - self._padding, self.width() + 1) for y in range(self.height() - self._padding, self.height() + 1) ] # 鼠标离开控件事件 def leaveEvent(self, QEvent): try: # 重置所有控件的位置和大小 width = (self.width() * 213) / 800 height = self.height() - 30 self.RangeButton.setGeometry( QRect(width - 20 * self.rate, 5 * self.rate, 20 * self.rate, 20 * self.rate)) self.StartButton.setGeometry( QRect(width + 20 * self.rate, 5 * self.rate, 20 * self.rate, 20 * self.rate)) self.OpenButton.setGeometry( QRect(width + 60 * self.rate, 5 * self.rate, 20 * self.rate, 20 * self.rate)) self.CopyButton.setGeometry( QRect(width + 100 * self.rate, 5 * self.rate, 20 * self.rate, 20 * self.rate)) self.playVoiceButton.setGeometry( QRect(width + 140 * self.rate, 5 * self.rate, 20 * self.rate, 20 * self.rate)) self.switchBtn.setGeometry( QRect(width + 180 * self.rate, 5 * self.rate, 50 * self.rate, 20 * self.rate)) self.languageText.setGeometry(width + 250 * self.rate, 5 * self.rate, 45 * self.rate, 20 * self.rate) self.SettinButton.setGeometry( QRect(width + 305 * self.rate, 5 * self.rate, 20 * self.rate, 20 * self.rate)) self.LockButton.setGeometry( QRect(width + 345 * self.rate, 5 * self.rate, 24 * self.rate, 20 * self.rate)) self.MinimizeButton.setGeometry( QRect(width + 389 * self.rate, 5 * self.rate, 20 * self.rate, 20 * self.rate)) self.QuitButton.setGeometry( QRect(width + 429 * self.rate, 5 * self.rate, 20 * self.rate, 20 * self.rate)) self.translateText.setGeometry(0, 30 * self.rate, self.width(), height * self.rate) # 隐藏所有顶部工具栏控件 self.switchBtn.hide() self.StartButton.hide() self.SettinButton.hide() self.RangeButton.hide() self.OpenButton.hide() self.CopyButton.hide() self.QuitButton.hide() self.MinimizeButton.hide() self.playVoiceButton.hide() self.LockButton.hide() self.languageText.hide() self.setStyleSheet('QLabel#dragLabel {background-color:none}') except Exception: write_error(format_exc()) # 获取界面预设参数 def get_settin(self): with open(folder_path + '/config/settin.json') as file: self.data = load(file) # 翻译模式预设 self.mode = False # 原文预设值 self.original = '' # 透明度预设 self.horizontal = (self.data["horizontal"]) / 100 if self.horizontal == 0: self.horizontal = 0.01 # 各翻译源线程状态标志 self.thread_state = 0 def start_login(self): with open(folder_path + '/config/settin.json') as file: data = load(file) if data["sign"] % 2 == 0: data["sign"] += 1 with open(folder_path + '/config/settin.json', 'w') as file: dump(data, file, indent=2) self.StartButton.setIcon(qticon('fa.play', color='white')) else: thread = TranslateThread(self, self.mode) thread.use_translate_signal.connect(self.use_translate) thread.start() thread.exec() # 创造翻译线程 def creat_thread(self, fun, original, data, translate_type): self.thread_state += 1 # 线程开始,增加线程数 translation_source = UseTranslateThread(fun, original, data, translate_type) thread = Thread(target=translation_source.run) thread.setDaemon(True) translation_source.use_translate_signal.connect(self.display_text) thread.start() # 并发执行所有翻译源 def use_translate(self, signal_list, original, data, result_with_location, translate_result): # 翻译界面清屏 self.translateText.clear() # 设定翻译时的字体类型和大小 self.Font.setFamily(data["fontType"]) self.Font.setPointSize(data["fontSize"]) self.translateText.setFont(self.Font) if "original" in signal_list or "error" in signal_list: if data["vis_result"] == "True": self.vis_res = VisResult(np_img=self.image, result=result_with_location, configs=data, translate_result=translate_result, save_path=self.save_result_path) self.vis_res.result_signal.connect(self.display_modify_text) self.vis_res.show() if translate_result == '': self.creat_thread(None, original, data, "original") else: if data['showOriginal'] == "True": self.creat_thread(None, original, data, "original") self.creat_thread(None, translate_result, data, "translated") # 将翻译结果打印 def display_text(self, result, data, translate_type): try: if data["showColorType"] == "False": self.format.setTextOutline( QPen(QColor(data["fontColor"][translate_type]), 0.7, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.translateText.mergeCurrentCharFormat(self.format) self.translateText.append(result) else: self.translateText.append( "<font color=%s>%s</font>" % (data["fontColor"][translate_type], result)) # 保存译文 self.save_text(result, translate_type) self.thread_state -= 1 # 线程结束,减少线程数 except Exception: write_error(format_exc()) # 将修改后的结果打印 def display_modify_text(self, result, data, translate_type, translate_result): self.translateText.clear() if data["showColorType"] == "False": if translate_result == '': self.format.setTextOutline( QPen(QColor(data["fontColor"][translate_type]), 0.7, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.translateText.mergeCurrentCharFormat(self.format) self.translateText.append(result) else: if data["showOriginal"] == "True": self.format.setTextOutline( QPen(QColor(data["fontColor"][translate_type]), 0.7, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.translateText.mergeCurrentCharFormat(self.format) self.translateText.append(result) self.format.setTextOutline( QPen(QColor(data["fontColor"]['translated']), 0.7, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.translateText.mergeCurrentCharFormat(self.format) self.translateText.append(translate_result) else: if translate_result == '': self.translateText.append( "<font color=%s>%s</font>" % (data["fontColor"][translate_type], result)) else: if data["showOriginal"] == "True": self.translateText.append( "<font color=%s>%s</font>" % (data["fontColor"][translate_type], result)) self.translateText.append( "<font color=%s>%s</font>" % (data["fontColor"]['translated'], translate_result)) self.original = result # 语音朗读 def play_voice(self): if not self.original: return try: # thread = Thread(target=Voice, args=(self.original,)) # thread.setDaemon(True) # thread.start() self.player = None flag, voice_file = Voice(self.original).save_voice() if flag: file = QUrl.fromLocalFile(voice_file) content = QMediaContent(file) self.player = QMediaPlayer() self.player.setMedia(content) self.player.play() except Exception: write_error(format_exc()) def save_text(self, text, translate_type): if translate_type == "caiyunPrivate": content = "\n[私人翻译]\n%s" % text else: content = "" with open(folder_path + "/config/识别结果.txt", "a+", encoding="utf-8") as file: file.write(content) def open_image(self): file_choose, file_type = QFileDialog.getOpenFileName( self, "选取文件", self.load_local_img_path, "jpg (*.jpg);; png (*.png);; jpeg (*.jpeg);;All Files (*)") img = imread(file_choose) if img is not None: self.load_local_img_path = dirname(file_choose) self.image = img self.load_local_img = True self.start_login()
class Window(QMainWindow): def __init__(self): super().__init__() uic.loadUi('playerone.ui', self) self.zcopy = self.pix.pixmap().copy() self.ask_seem() self.ansln.hide() self.ansbtn.hide() self.ansbtntext.hide() self.ansbtnpix.hide() self.hintCheck.hide() self.restartbtn.hide() self.restartbtntext.hide() self.restartbtnpix.hide() self.exitbtn.hide() self.exitbtnpix.hide() self.exitbtntext.hide() self.image = QImage(681, 431, QImage.Format_RGB32) self.image.fill(Qt.white) self.pix.setPixmap(QPixmap(self.image)) self.start_brush() self.count = 1800 self.start = True timer = QTimer(self) timer.timeout.connect(self.showTime) timer.start(100) self.setColorbtn.clicked.connect(self.choose_color) self.setSizebtn.clicked.connect(self.choose_size) self.nextbtn.clicked.connect(self.next) self.ansbtn.clicked.connect(self.checkans) self.hintCheck.stateChanged.connect(self.showhint) self.restartbtn.clicked.connect(self.restar) self.exitbtn.clicked.connect(self.stop) def ask_seem(self): # создание вариантов выбора темы и слова con = sqlite3.connect('krokodile.db') cur = con.cursor() result = cur.execute("""SELECT seem FROM 'seems'""").fetchall() result = list(map(lambda x: x[0], result)) self.seem = QInputDialog.getItem(self, 'Выбор темы', 'Выберети тему', result) sem = cur.execute( f"""SELECT id FROM 'seems' WHERE seem = '{self.seem[0]}'""" ).fetchall() self.seem = self.seem[0] result = cur.execute( f"""SELECT word FROM 'words' WHERE seemId = {sem[0][0]}""" ).fetchall() result = sample(result, 3) con.close() result = list(map(lambda x: x[0], result)) self.word = QInputDialog.getItem(self, 'Выбор слова', 'Выберети слово', result) self.word = self.word[0] self.tema.setText(self.tema.text() + self.seem) self.slovo.setText(self.slovo.text() + self.word) def start_brush(self): # стартовые настройки кисти self.drawing = False self.brushSize = 3 self.brushColor = Qt.black self.lastPoint = QPoint() def keyPressEvent(self, event): # настройка горячих клавиш if int(event.modifiers()) == 67108864: if event.key() == Qt.Key_Z: self.pix.setPixmap(self.zcopy) self.image = self.zcopy.toImage() if event.key() == Qt.Key_S: self.choose_size() if event.key() == Qt.Key_C: self.choose_color() def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.zcopy = self.pix.pixmap().copy() self.drawing = True point = QPoint() point.setX(event.pos().x() - 10) point.setY(event.pos().y() - 50) self.lastPoint = point def showTime(self): # функции таймера if self.start: self.count -= 1 if self.count == 0: self.start = False self.next() if self.start: text = str(self.count / 10) + " s" self.timer.setText(text) def mouseMoveEvent(self, event): if (event.buttons() and Qt.LeftButton) and self.drawing: painter = QPainter(self.image) painter.setPen( QPen(self.brushColor, self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) point = QPoint() point.setX(event.pos().x() - 10) point.setY(event.pos().y() - 50) painter.drawLine(self.lastPoint, point) self.lastPoint = point self.pix.setPixmap(QPixmap(self.image)) def mouseReleaseEvent(self, event): if event.button() == Qt.LeftButton: self.drawing = False def choose_color(self): self.brushColor = QColorDialog.getColor() def choose_size(self): self.brushSize = QInputDialog.getInt(self, "Выберети цвет", "", 3, 2, 30, 1)[0] def next(self): self.tema.hide() self.hintstate = True self.slovo.hide() self.setSizebtn.hide() self.nextbtn.hide() self.nextbtntext.hide() self.nextbtnpix.hide() self.timer.hide() self.setColorbtn.hide() self.ansln.show() self.ansbtn.show() self.ansbtntext.show() self.ansbtnpix.show() self.hintCheck.show() def checkans(self): self.statusBar = QStatusBar() self.setStatusBar(self.statusBar) if self.ansln.text().lower() == self.word.lower(): self.statusBar.showMessage('Вы угадали') self.statusBar.setStyleSheet('background-color : green') self.restartbtn.show() self.restartbtntext.show() self.restartbtnpix.show() self.exitbtn.show() self.exitbtnpix.show() self.exitbtntext.show() else: self.statusBar.showMessage('Попробуйте еще') self.statusBar.setStyleSheet('background-color : red') def showhint(self): if self.hintstate: self.tema.show() else: self.tema.hide() self.hintstate = not (self.hintstate) def restar(self): os.system('python "main.py"') app.quit() self.close() def stop(self): exit()
class Window(QMainWindow): # Initialization of the GUI def __init__(self): super(Window, self).__init__() # ~ self.setGeometry(50, 50, 1100, 750) self.setWindowTitle("Battery TF") self.setStyleSheet(GUI_Style.mainWindow) # ~ self.setMinimumSize(1100, 750) self.setWindowIcon(QIcon(Icon_Path)) # -------------------------------------------------------------- # -------------------- Initialize ----------------------------- # -------------------------------------------------------------- # GPIO Configuration GPIO.setmode(GPIO.BCM) GPIO.setup(Relay1_40, GPIO.OUT) GPIO.setup(Relay1_60, GPIO.OUT) GPIO.setup(Relay1_500, GPIO.OUT) GPIO.setup(Relay1_1k, GPIO.OUT) GPIO.setup(Relay2_40, GPIO.OUT) GPIO.setup(Relay2_60, GPIO.OUT) GPIO.setup(Relay2_500, GPIO.OUT) GPIO.setup(Relay2_1k, GPIO.OUT) # -------------------------------------------------------------- # ---------------- Instantiate All Threads -------------------- # -------------------------------------------------------------- self.GPIO_ch1 = GPIO_Ch1_Thread(GPIO) self.GPIO_ch2 = GPIO_Ch2_Thread(GPIO) # -------------------------------------------------------------- # ---------------- Start All Threads --------------------------- # -------------------------------------------------------------- self.GPIO_ch1.start() self.GPIO_ch2.start() self.GPIO_ch1.setAllLow(True) self.GPIO_ch2.setAllLow(True) # -------------------------------------------------------------- # ---------------- Create Main Widget -------------------------- # -------------------------------------------------------------- main_widget = QWidget() self.setCentralWidget(main_widget) # -------------------------------------------------------------- # ---------------- Create Tabs --------------------------------- # -------------------------------------------------------------- self.tabWidget() # -------------------------------------------------------------- # -------------- Create Bottom Status Bar----------------------- # -------------------------------------------------------------- self.StatusBar() self.setStatusBar(self.statusBar) # -------------------------------------------------------------- # ------------- Create Main Window Layouts --------------------- # -------------------------------------------------------------- # Instantiate GUI objects self.MainTitle() self.Console_Log() self.MainLogoButton() self.inputCommandPrompt() self.sendCommandButton() # Add title/ logo to the main title layout Main_Title_Layout = QHBoxLayout() Main_Title_Layout.addWidget(self.Logo_btn, 0, Qt.AlignRight) Main_Title_Layout.addWidget(self.MainTitleText, 0, Qt.AlignLeft) Main_Title_Layout.setSpacing(20) Main_Title_Layout.setContentsMargins(0, 0, 50, 0) # Layout command prompt and send button promptLayout = QHBoxLayout() promptLayout.addWidget(self.commandPrompt) promptLayout.addWidget(self.send_btn) promptLayout.setSpacing(20) # Layout right side of GUI window commandWindowLayout = QVBoxLayout() commandWindowLayout.addLayout(promptLayout) commandWindowLayout.addWidget(self.ConsoleLog) commandWindowLayout.setSpacing(20) # Create Layout for tab widget and console window horizontalWindow_layout = QHBoxLayout() horizontalWindow_layout.addWidget(self.MyTabs) horizontalWindow_layout.addLayout(commandWindowLayout) horizontalWindow_layout.setSpacing(20) # Add tabs and video stream to main window layout Full_Window_layout = QVBoxLayout() Full_Window_layout.addLayout(Main_Title_Layout) Full_Window_layout.addLayout(horizontalWindow_layout) Full_Window_layout.setSpacing(20) Full_Window_layout.setContentsMargins(20, 20, 20, 20) # -------------------------------------------------------------- # ------------- Create Battery 1 Tab Layout -------------------- # -------------------------------------------------------------- # Instantiate Battery 1 GUI Objects self.remainingCapaAlarm_1() self.batteryMode_1() self.voltage_1() self.current_1() self.averageCurrent_1() self.relativeStatOfCharge_1() self.absoluteStatOfCharge_1() self.remainingCapacity_1() self.fullChargeCapacity_1() self.runTimeToEmpty_1() self.averageTimeToEmpty_1() self.averageTimeToFull_1() self.chargingCurrent_1() self.chargingVoltage_1() self.Battery_Status_1() self.Cycle_Count_1() self.Serial_Number_1() self.Device_Name_1() self.Cell_Voltage4_1() self.Cell_Voltage3_1() self.Cell_Voltage2_1() self.Cell_Voltage1_1() # Arrange Layout to go on Battery 1 tab vertical_battery1_LeftLayout = QVBoxLayout() vertical_battery1_LeftLayout.addLayout(self.battMode_Layout1) vertical_battery1_LeftLayout.addLayout(self.serialNumLayout1) vertical_battery1_LeftLayout.addLayout(self.deviceNameLayout1) vertical_battery1_LeftLayout.addLayout(self.charging_Current_Layout1) vertical_battery1_LeftLayout.addLayout(self.charging_Voltag_Layout1) vertical_battery1_LeftLayout.addLayout(self.batteryStatusLayout1) vertical_battery1_LeftLayout.addLayout(self.cycleCountLayout1) vertical_battery1_LeftLayout.addLayout(self.cellVoltage4_Layout1) vertical_battery1_LeftLayout.addLayout(self.cellVoltage3_Layout1) vertical_battery1_LeftLayout.addLayout(self.cellVoltage2_Layout1) vertical_battery1_LeftLayout.addLayout(self.cellVoltage1_Layout1) vertical_battery1_LeftLayout.setSpacing(10) vertical_battery1_RightLayout = QVBoxLayout() vertical_battery1_RightLayout.addLayout(self.remCapAlarm_Layout1) vertical_battery1_RightLayout.addLayout(self.voltage_Layout1) vertical_battery1_RightLayout.addLayout(self.current_Layout1) vertical_battery1_RightLayout.addLayout(self.avgCurr_Layout1) vertical_battery1_RightLayout.addLayout(self.relStateCharge_Layout1) vertical_battery1_RightLayout.addLayout(self.absStateCharge_Layout1) vertical_battery1_RightLayout.addLayout(self.remCap_Layout1) vertical_battery1_RightLayout.addLayout(self.fullCharge_Layout1) vertical_battery1_RightLayout.addLayout(self.runTimeToEmpty_Layout1) vertical_battery1_RightLayout.addLayout(self.avgTimeToEmpty_Layout1) vertical_battery1_RightLayout.addLayout(self.avgTimeToFull_Layout1) vertical_battery1_RightLayout.setSpacing(10) battery1Tab_layout = QHBoxLayout() battery1Tab_layout.addLayout(vertical_battery1_LeftLayout) battery1Tab_layout.addLayout(vertical_battery1_RightLayout) battery1Tab_layout.setSpacing(12) # Add final layout to main tab layout self.Battery1_Tab.setLayout(battery1Tab_layout) # -------------------------------------------------------------- # ------------- Create Battery 2 Tab Layout -------------------- # -------------------------------------------------------------- # Instantiate Battery 2 GUI Objects self.remainingCapaAlarm_2() self.batteryMode_2() self.voltage_2() self.current_2() self.averageCurrent_2() self.relativeStatOfCharge_2() self.absoluteStatOfCharge_2() self.remainingCapacity_2() self.fullChargeCapacity_2() self.runTimeToEmpty_2() self.averageTimeToEmpty_2() self.averageTimeToFull_2() self.chargingCurrent_2() self.chargingVoltage_2() self.Battery_Status_2() self.Cycle_Count_2() self.Serial_Number_2() self.Device_Name_2() self.Cell_Voltage4_2() self.Cell_Voltage3_2() self.Cell_Voltage2_2() self.Cell_Voltage1_2() # Arrange Layout to go on Battery 2 tab vertical_battery2_LeftLayout = QVBoxLayout() vertical_battery2_LeftLayout.addLayout(self.battMode_Layout2) vertical_battery2_LeftLayout.addLayout(self.serialNumLayout2) vertical_battery2_LeftLayout.addLayout(self.deviceNameLayout2) vertical_battery2_LeftLayout.addLayout(self.charging_Current_Layout2) vertical_battery2_LeftLayout.addLayout(self.charging_Voltag_Layout2) vertical_battery2_LeftLayout.addLayout(self.batteryStatusLayout2) vertical_battery2_LeftLayout.addLayout(self.cycleCountLayout2) vertical_battery2_LeftLayout.addLayout(self.cellVoltage4_Layout2) vertical_battery2_LeftLayout.addLayout(self.cellVoltage3_Layout2) vertical_battery2_LeftLayout.addLayout(self.cellVoltage2_Layout2) vertical_battery2_LeftLayout.addLayout(self.cellVoltage1_Layout2) vertical_battery2_LeftLayout.setSpacing(10) vertical_battery2_RightLayout = QVBoxLayout() vertical_battery2_RightLayout.addLayout(self.remCapAlarm_Layout2) vertical_battery2_RightLayout.addLayout(self.voltage_Layout2) vertical_battery2_RightLayout.addLayout(self.current_Layout2) vertical_battery2_RightLayout.addLayout(self.avgCurr_Layout2) vertical_battery2_RightLayout.addLayout(self.relStateCharge_Layout2) vertical_battery2_RightLayout.addLayout(self.absStateCharge_Layout2) vertical_battery2_RightLayout.addLayout(self.remCap_Layout2) vertical_battery2_RightLayout.addLayout(self.fullCharge_Layout2) vertical_battery2_RightLayout.addLayout(self.runTimeToEmpty_Layout2) vertical_battery2_RightLayout.addLayout(self.avgTimeToEmpty_Layout2) vertical_battery2_RightLayout.addLayout(self.avgTimeToFull_Layout2) vertical_battery2_RightLayout.setSpacing(10) battery2Tab_layout = QHBoxLayout() battery2Tab_layout.addLayout(vertical_battery2_LeftLayout) battery2Tab_layout.addLayout(vertical_battery2_RightLayout) battery2Tab_layout.setSpacing(12) # Add final layout to main tab layout self.Battery2_Tab.setLayout(battery2Tab_layout) # -------------------------------------------------------------- # ------------ Add Final Layout to Main Window ----------------- # -------------------------------------------------------------- # Set Main window layout to GUI central Widget self.centralWidget().setLayout(Full_Window_layout) self.centralWidget().isWindow() self.handleButtons() # Connect Signals self.GPIO_ch1.doneFlag1.connect(self.handle.ch1Buttons) self.GPIO_ch2.doneFlag2.connect(self.handle.ch2Buttons) # Display GUI Objects # ~ self.show() #~ self.showFullScreen() self.showMaximized() # -------------------------------------------------------------------------------------------------------------- # ----------------------------- GUI Objects/ Functions --------------------------------------------------------- # -------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------ # ------------------- Keyboard Key Functions ----------------------- # ------------------------------------------------------------------ def keyPressEvent(self, event): key = event.key() if key == Qt.Key_Return: # Send button self.send_btn.Un_Click() # ------------------------------------------------------------------ # ------------------- Handlers ------------------------------------- # ------------------------------------------------------------------ def handleButtons(self): self.handle = handlers(self.relay1_40, self.relay1_60, self.relay1_500, self.relay1_1k, self.relay2_40, self.relay2_60, self.relay2_500, self.relay2_1k, self.GPIO_ch1, self.GPIO_ch2) # ------------------------------------------------------------------ # ------------------- Main Title Function -------------------------- # ------------------------------------------------------------------ def MainTitle(self): self.MainTitleText = QLabel(self) self.MainTitleText.setText("Battery Test Fixture") self.MainTitleText.setStyleSheet(GUI_Style.mainTitle) def MainLogoButton(self): self.Logo_btn = Logo_Button(self, "", self.ConsoleLog) self.Logo_btn.setStyleSheet(GUI_Style.startButton) self.Logo_btn.pressed.connect(self.Logo_btn.On_Click) self.Logo_btn.released.connect(self.Logo_btn.Un_Click) self.Logo_btn.setIcon(QIcon(Mediatech_Path)) self.Logo_btn.setIconSize(QSize(300, 80)) # ------------------------------------------------------------------ # ------------------- Create Console Log -------------------------- # ------------------------------------------------------------------ def Console_Log(self): self.ConsoleLog = QTextEdit(self) #self.ConsoleLog.setMaximumHeight(100) self.ConsoleLog.setStyleSheet(GUI_Style.consoleLog) self.ConsoleLog.setPlaceholderText("Console Log") self.ConsoleLog.setReadOnly(True) self.ConsoleLog.setLineWrapMode(True) self.ConsoleLog.setAlignment(Qt.AlignTop) # ------------------------------------------------------------------ # ---------------- Create Input Command Prompt -------------------- # ------------------------------------------------------------------ def inputCommandPrompt(self): self.commandPrompt = QLineEdit(self) self.commandPrompt.setStyleSheet(GUI_Style.commandBox) self.commandPrompt.setPlaceholderText("Enter Command") # ------------------------------------------------------------------ # ------------------- Create Send Button -------------------------- # ------------------------------------------------------------------ def sendCommandButton(self): self.send_btn = Send_Command_Button(self, "Send", self.ConsoleLog, self.commandPrompt) self.send_btn.setMaximumSize(125, 30) self.send_btn.setMinimumSize(125, 30) self.send_btn.setStyleSheet(GUI_Style.sendButton) self.send_btn.pressed.connect(self.send_btn.On_Click) self.send_btn.released.connect(self.send_btn.Un_Click) # ------------------------------------------------------------------ # --------------------- Create Tab Widget -------------------------- # ------------------------------------------------------------------ def tabWidget(self): self.MyTabs = QTabWidget() self.MyTabs.setStyleSheet(GUI_Style.tabs) self.MyTabs.setMaximumWidth(500) # Create each individual tabs self.Battery1_Tab = QWidget() self.Battery2_Tab = QWidget() # Add Tabs and Tab Icon to tab widget self.MyTabs.addTab(self.Battery1_Tab, ' Battery 1') self.MyTabs.addTab(self.Battery2_Tab, ' Battery 2') # ------------------------------------------------------------------ # ----------- Create Battery 1 Tab GUI Objects -------------------- # ------------------------------------------------------------------ def remainingCapaAlarm_1(self): # create label self.remCapAlarm1 = QLabel(self) self.remCapAlarm1.setText("Remaining Capacity Alarm") self.remCapAlarm1.setStyleSheet(GUI_Style.nameLabel) self.remCapAlarm1.setWordWrap(True) # create input box self.remCapAlarmBox1 = QLineEdit(self) self.remCapAlarmBox1.setStyleSheet(GUI_Style.updateField) self.remCapAlarmBox1.setMaximumWidth(50) # create layout self.remCapAlarm_Layout1 = QHBoxLayout() self.remCapAlarm_Layout1.addWidget(self.remCapAlarm1) self.remCapAlarm_Layout1.addWidget(self.remCapAlarmBox1) def batteryMode_1(self): # create label self.battMode1 = QLabel(self) self.battMode1.setText("Battery Mode") self.battMode1.setStyleSheet(GUI_Style.nameLabel) self.battMode1.setWordWrap(True) # create input box self.battModeBox1 = QLineEdit(self) self.battModeBox1.setStyleSheet(GUI_Style.updateField) self.battModeBox1.setMaximumWidth(50) # create layout self.battMode_Layout1 = QHBoxLayout() self.battMode_Layout1.addWidget(self.battMode1) self.battMode_Layout1.addWidget(self.battModeBox1) def voltage_1(self): # create label self.voltage1 = QLabel(self) self.voltage1.setText("Voltage") self.voltage1.setStyleSheet(GUI_Style.nameLabel) self.voltage1.setWordWrap(True) # create input box self.voltageBox1 = QLineEdit(self) self.voltageBox1.setStyleSheet(GUI_Style.updateField) self.voltageBox1.setMaximumWidth(50) # create layout self.voltage_Layout1 = QHBoxLayout() self.voltage_Layout1.addWidget(self.voltage1) self.voltage_Layout1.addWidget(self.voltageBox1) def current_1(self): # create label self.current1 = QLabel(self) self.current1.setText("Current") self.current1.setStyleSheet(GUI_Style.nameLabel) self.current1.setWordWrap(True) # create input box self.currentBox1 = QLineEdit(self) self.currentBox1.setStyleSheet(GUI_Style.updateField) self.currentBox1.setMaximumWidth(50) # create layout self.current_Layout1 = QHBoxLayout() self.current_Layout1.addWidget(self.current1) self.current_Layout1.addWidget(self.currentBox1) def averageCurrent_1(self): # create label self.avgCurr1 = QLabel(self) self.avgCurr1.setText("Average Current") self.avgCurr1.setStyleSheet(GUI_Style.nameLabel) self.avgCurr1.setWordWrap(True) # create input box self.avgCurrBox1 = QLineEdit(self) self.avgCurrBox1.setStyleSheet(GUI_Style.updateField) self.avgCurrBox1.setMaximumWidth(50) # create layout self.avgCurr_Layout1 = QHBoxLayout() self.avgCurr_Layout1.addWidget(self.avgCurr1) self.avgCurr_Layout1.addWidget(self.avgCurrBox1) def relativeStatOfCharge_1(self): # create label self.relStateCharge1 = QLabel(self) self.relStateCharge1.setText("Relative State Of Charge") self.relStateCharge1.setStyleSheet(GUI_Style.nameLabel) self.relStateCharge1.setWordWrap(True) # create input box self.relStateChargeBox1 = QLineEdit(self) self.relStateChargeBox1.setStyleSheet(GUI_Style.updateField) self.relStateChargeBox1.setMaximumWidth(50) # create layout self.relStateCharge_Layout1 = QHBoxLayout() self.relStateCharge_Layout1.addWidget(self.relStateCharge1) self.relStateCharge_Layout1.addWidget(self.relStateChargeBox1) def absoluteStatOfCharge_1(self): # create label self.absStateCharge1 = QLabel(self) self.absStateCharge1.setText("Absolute State Of Charge") self.absStateCharge1.setStyleSheet(GUI_Style.nameLabel) self.absStateCharge1.setWordWrap(True) # create input box self.absStateChargeBox1 = QLineEdit(self) self.absStateChargeBox1.setStyleSheet(GUI_Style.updateField) self.absStateChargeBox1.setMaximumWidth(50) # create layout self.absStateCharge_Layout1 = QHBoxLayout() self.absStateCharge_Layout1.addWidget(self.absStateCharge1) self.absStateCharge_Layout1.addWidget(self.absStateChargeBox1) def remainingCapacity_1(self): # create label self.remainingCapacity1 = QLabel(self) self.remainingCapacity1.setText("Remaining Capacity") self.remainingCapacity1.setStyleSheet(GUI_Style.nameLabel) self.remainingCapacity1.setWordWrap(True) # create input box self.remainingCapacityBox1 = QLineEdit(self) self.remainingCapacityBox1.setStyleSheet(GUI_Style.updateField) self.remainingCapacityBox1.setMaximumWidth(50) # create layout self.remCap_Layout1 = QHBoxLayout() self.remCap_Layout1.addWidget(self.remainingCapacity1) self.remCap_Layout1.addWidget(self.remainingCapacityBox1) def fullChargeCapacity_1(self): # create label self.fullChargeCapacity1 = QLabel(self) self.fullChargeCapacity1.setText("Full Charge Capacity") self.fullChargeCapacity1.setStyleSheet(GUI_Style.nameLabel) self.fullChargeCapacity1.setWordWrap(True) # create input box self.fullChargeCapacityBox1 = QLineEdit(self) self.fullChargeCapacityBox1.setStyleSheet(GUI_Style.updateField) self.fullChargeCapacityBox1.setMaximumWidth(50) # create layout self.fullCharge_Layout1 = QHBoxLayout() self.fullCharge_Layout1.addWidget(self.fullChargeCapacity1) self.fullCharge_Layout1.addWidget(self.fullChargeCapacityBox1) def runTimeToEmpty_1(self): # create label self.runTimeToEmpty1 = QLabel(self) self.runTimeToEmpty1.setText("Run Time To Empty") self.runTimeToEmpty1.setStyleSheet(GUI_Style.nameLabel) self.runTimeToEmpty1.setWordWrap(True) # create input box self.runTimeToEmptyBox1 = QLineEdit(self) self.runTimeToEmptyBox1.setStyleSheet(GUI_Style.updateField) self.runTimeToEmptyBox1.setMaximumWidth(50) # create layout self.runTimeToEmpty_Layout1 = QHBoxLayout() self.runTimeToEmpty_Layout1.addWidget(self.runTimeToEmpty1) self.runTimeToEmpty_Layout1.addWidget(self.runTimeToEmptyBox1) def averageTimeToEmpty_1(self): # create label self.avgTimeToEmpty1 = QLabel(self) self.avgTimeToEmpty1.setText("Average Time To Empty") self.avgTimeToEmpty1.setStyleSheet(GUI_Style.nameLabel) self.avgTimeToEmpty1.setWordWrap(True) # create input box self.avgTimeToEmptyBox1 = QLineEdit(self) self.avgTimeToEmptyBox1.setStyleSheet(GUI_Style.updateField) self.avgTimeToEmptyBox1.setMaximumWidth(50) # create layout self.avgTimeToEmpty_Layout1 = QHBoxLayout() self.avgTimeToEmpty_Layout1.addWidget(self.avgTimeToEmpty1) self.avgTimeToEmpty_Layout1.addWidget(self.avgTimeToEmptyBox1) def averageTimeToFull_1(self): # create label self.avgTimeToFull1 = QLabel(self) self.avgTimeToFull1.setText("Average Time To Full") self.avgTimeToFull1.setStyleSheet(GUI_Style.nameLabel) self.avgTimeToFull1.setWordWrap(True) self.avgTimeToFull1.setWordWrap(True) # create input box self.avgTimeToFullBox1 = QLineEdit(self) self.avgTimeToFullBox1.setStyleSheet(GUI_Style.updateField) self.avgTimeToFullBox1.setMaximumWidth(50) # create layout self.avgTimeToFull_Layout1 = QHBoxLayout() self.avgTimeToFull_Layout1.addWidget(self.avgTimeToFull1) self.avgTimeToFull_Layout1.addWidget(self.avgTimeToFullBox1) def chargingCurrent_1(self): # create label self.chargingCurrent1 = QLabel(self) self.chargingCurrent1.setText("Charging Current") self.chargingCurrent1.setStyleSheet(GUI_Style.nameLabel) self.chargingCurrent1.setWordWrap(True) # create input box self.chargingCurrentBox1 = QLineEdit(self) self.chargingCurrentBox1.setStyleSheet(GUI_Style.updateField) self.chargingCurrentBox1.setMaximumWidth(50) # create layout self.charging_Current_Layout1 = QHBoxLayout() self.charging_Current_Layout1.addWidget(self.chargingCurrent1) self.charging_Current_Layout1.addWidget(self.chargingCurrentBox1) def chargingVoltage_1(self): # create label self.chargingVoltage1 = QLabel(self) self.chargingVoltage1.setText("Charging Voltage") self.chargingVoltage1.setStyleSheet(GUI_Style.nameLabel) self.chargingVoltage1.setWordWrap(True) # create input box self.chargingVoltageBox1 = QLineEdit(self) self.chargingVoltageBox1.setStyleSheet(GUI_Style.updateField) self.chargingVoltageBox1.setMaximumWidth(50) # create layout self.charging_Voltag_Layout1 = QHBoxLayout() self.charging_Voltag_Layout1.addWidget(self.chargingVoltage1) self.charging_Voltag_Layout1.addWidget(self.chargingVoltageBox1) def Battery_Status_1(self): # create label self.batteryStatus1 = QLabel(self) self.batteryStatus1.setText("Battery Status") self.batteryStatus1.setStyleSheet(GUI_Style.nameLabel) self.batteryStatus1.setWordWrap(True) # create input box self.batteryStatusBox1 = QLineEdit(self) self.batteryStatusBox1.setStyleSheet(GUI_Style.updateField) self.batteryStatusBox1.setMaximumWidth(50) # create layout self.batteryStatusLayout1 = QHBoxLayout() self.batteryStatusLayout1.addWidget(self.batteryStatus1) self.batteryStatusLayout1.addWidget(self.batteryStatusBox1) def Cycle_Count_1(self): # create label self.cycleCount1 = QLabel(self) self.cycleCount1.setText("Cycle Count") self.cycleCount1.setStyleSheet(GUI_Style.nameLabel) self.cycleCount1.setWordWrap(True) # create input box self.cycleCountBox1 = QLineEdit(self) self.cycleCountBox1.setStyleSheet(GUI_Style.updateField) self.cycleCountBox1.setMaximumWidth(50) # create layout self.cycleCountLayout1 = QHBoxLayout() self.cycleCountLayout1.addWidget(self.cycleCount1) self.cycleCountLayout1.addWidget(self.cycleCountBox1) def Serial_Number_1(self): # create label self.serNum1 = QLabel(self) self.serNum1.setText("Serial Number") self.serNum1.setStyleSheet(GUI_Style.nameLabel) self.serNum1.setWordWrap(True) # create input box self.serNumBox1 = QLineEdit(self) self.serNumBox1.setStyleSheet(GUI_Style.updateField) self.serNumBox1.setMaximumWidth(50) # create layout self.serialNumLayout1 = QHBoxLayout() self.serialNumLayout1.addWidget(self.serNum1) self.serialNumLayout1.addWidget(self.serNumBox1) def Device_Name_1(self): # create label self.devName1 = QLabel(self) self.devName1.setText("Device Name") self.devName1.setStyleSheet(GUI_Style.nameLabel) # create input box self.devNameBox1 = QLineEdit(self) self.devNameBox1.setStyleSheet(GUI_Style.updateField) self.devNameBox1.setMaximumWidth(50) # create layout self.deviceNameLayout1 = QHBoxLayout() self.deviceNameLayout1.addWidget(self.devName1) self.deviceNameLayout1.addWidget(self.devNameBox1) def Cell_Voltage4_1(self): # create label self.cellVolt4_1 = QLabel(self) self.cellVolt4_1.setText("Cell Voltage 4") self.cellVolt4_1.setStyleSheet(GUI_Style.nameLabel) # create input box self.cellVolt4Box1 = QLineEdit(self) self.cellVolt4Box1.setStyleSheet(GUI_Style.updateField) self.cellVolt4Box1.setMaximumWidth(50) # create layout self.cellVoltage4_Layout1 = QHBoxLayout() self.cellVoltage4_Layout1.addWidget(self.cellVolt4_1) self.cellVoltage4_Layout1.addWidget(self.cellVolt4Box1) def Cell_Voltage3_1(self): # create label self.cellVolt3_1 = QLabel(self) self.cellVolt3_1.setText("Cell Voltage 3") self.cellVolt3_1.setStyleSheet(GUI_Style.nameLabel) # create input box self.cellVolt3Box1 = QLineEdit(self) self.cellVolt3Box1.setStyleSheet(GUI_Style.updateField) self.cellVolt3Box1.setMaximumWidth(50) # create layout self.cellVoltage3_Layout1 = QHBoxLayout() self.cellVoltage3_Layout1.addWidget(self.cellVolt3_1) self.cellVoltage3_Layout1.addWidget(self.cellVolt3Box1) def Cell_Voltage2_1(self): # create label self.cellVolt2_1 = QLabel(self) self.cellVolt2_1.setText("Cell Voltage 2") self.cellVolt2_1.setStyleSheet(GUI_Style.nameLabel) # create input box self.cellVolt2Box1 = QLineEdit(self) self.cellVolt2Box1.setStyleSheet(GUI_Style.updateField) self.cellVolt2Box1.setMaximumWidth(50) # create layout self.cellVoltage2_Layout1 = QHBoxLayout() self.cellVoltage2_Layout1.addWidget(self.cellVolt2_1) self.cellVoltage2_Layout1.addWidget(self.cellVolt2Box1) def Cell_Voltage1_1(self): # create label self.cellVolt1_1 = QLabel(self) self.cellVolt1_1.setText("Cell Voltage 1") self.cellVolt1_1.setStyleSheet(GUI_Style.nameLabel) # create input box self.cellVolt1Box1 = QLineEdit(self) self.cellVolt1Box1.setStyleSheet(GUI_Style.updateField) self.cellVolt1Box1.setMaximumWidth(50) # create layout self.cellVoltage1_Layout1 = QHBoxLayout() self.cellVoltage1_Layout1.addWidget(self.cellVolt1_1) self.cellVoltage1_Layout1.addWidget(self.cellVolt1Box1) ## ------------------------------------------------------------------ ## ----------- Create Battery 2 Tab GUI Objects -------------------- ## ------------------------------------------------------------------ def remainingCapaAlarm_2(self): # create label self.remCapAlarm2 = QLabel(self) self.remCapAlarm2.setText("Remaining Capacity Alarm") self.remCapAlarm2.setStyleSheet(GUI_Style.nameLabel) self.remCapAlarm2.setWordWrap(True) # create input box self.remCapAlarmBox2 = QLineEdit(self) self.remCapAlarmBox2.setStyleSheet(GUI_Style.updateField) self.remCapAlarmBox2.setMaximumWidth(50) # create layout self.remCapAlarm_Layout2 = QHBoxLayout() self.remCapAlarm_Layout2.addWidget(self.remCapAlarm2) self.remCapAlarm_Layout2.addWidget(self.remCapAlarmBox2) def batteryMode_2(self): # create label self.battMode2 = QLabel(self) self.battMode2.setText("Battery Mode") self.battMode2.setStyleSheet(GUI_Style.nameLabel) # create input box self.battModeBox2 = QLineEdit(self) self.battModeBox2.setStyleSheet(GUI_Style.updateField) self.battModeBox2.setMaximumWidth(50) # create layout self.battMode_Layout2 = QHBoxLayout() self.battMode_Layout2.addWidget(self.battMode2) self.battMode_Layout2.addWidget(self.battModeBox2) def voltage_2(self): # create label self.voltage2 = QLabel(self) self.voltage2.setText("Voltage") self.voltage2.setStyleSheet(GUI_Style.nameLabel) # create input box self.voltageBox2 = QLineEdit(self) self.voltageBox2.setStyleSheet(GUI_Style.updateField) self.voltageBox2.setMaximumWidth(50) # create layout self.voltage_Layout2 = QHBoxLayout() self.voltage_Layout2.addWidget(self.voltage2) self.voltage_Layout2.addWidget(self.voltageBox2) def current_2(self): # create label self.current2 = QLabel(self) self.current2.setText("Current") self.current2.setStyleSheet(GUI_Style.nameLabel) # create input box self.currentBox2 = QLineEdit(self) self.currentBox2.setStyleSheet(GUI_Style.updateField) self.currentBox2.setMaximumWidth(50) # create layout self.current_Layout2 = QHBoxLayout() self.current_Layout2.addWidget(self.current2) self.current_Layout2.addWidget(self.currentBox2) def averageCurrent_2(self): # create label self.avgCurr2 = QLabel(self) self.avgCurr2.setText("Average Current") self.avgCurr2.setStyleSheet(GUI_Style.nameLabel) # create input box self.avgCurrBox2 = QLineEdit(self) self.avgCurrBox2.setStyleSheet(GUI_Style.updateField) self.avgCurrBox2.setMaximumWidth(50) # create layout self.avgCurr_Layout2 = QHBoxLayout() self.avgCurr_Layout2.addWidget(self.avgCurr2) self.avgCurr_Layout2.addWidget(self.avgCurrBox2) def relativeStatOfCharge_2(self): # create label self.relStateCharge2 = QLabel(self) self.relStateCharge2.setText("Relative State Of Charge") self.relStateCharge2.setStyleSheet(GUI_Style.nameLabel) self.relStateCharge2.setWordWrap(True) # create input box self.relStateChargeBox2 = QLineEdit(self) self.relStateChargeBox2.setStyleSheet(GUI_Style.updateField) self.relStateChargeBox2.setMaximumWidth(50) # create layout self.relStateCharge_Layout2 = QHBoxLayout() self.relStateCharge_Layout2.addWidget(self.relStateCharge2) self.relStateCharge_Layout2.addWidget(self.relStateChargeBox2) def absoluteStatOfCharge_2(self): # create label self.absStateCharge2 = QLabel(self) self.absStateCharge2.setText("Absolute State Of Charge") self.absStateCharge2.setStyleSheet(GUI_Style.nameLabel) self.absStateCharge2.setWordWrap(True) # create input box self.absStateChargeBox2 = QLineEdit(self) self.absStateChargeBox2.setStyleSheet(GUI_Style.updateField) self.absStateChargeBox2.setMaximumWidth(50) # create layout self.absStateCharge_Layout2 = QHBoxLayout() self.absStateCharge_Layout2.addWidget(self.absStateCharge2) self.absStateCharge_Layout2.addWidget(self.absStateChargeBox2) def remainingCapacity_2(self): # create label self.remainingCapacity2 = QLabel(self) self.remainingCapacity2.setText("Remaining Capacity") self.remainingCapacity2.setStyleSheet(GUI_Style.nameLabel) self.remainingCapacity2.setWordWrap(True) # create input box self.remainingCapacityBox2 = QLineEdit(self) self.remainingCapacityBox2.setStyleSheet(GUI_Style.updateField) self.remainingCapacityBox2.setMaximumWidth(50) # create layout self.remCap_Layout2 = QHBoxLayout() self.remCap_Layout2.addWidget(self.remainingCapacity2) self.remCap_Layout2.addWidget(self.remainingCapacityBox2) def fullChargeCapacity_2(self): # create label self.fullChargeCapacity2 = QLabel(self) self.fullChargeCapacity2.setText("Full Charge Capacity") self.fullChargeCapacity2.setStyleSheet(GUI_Style.nameLabel) self.fullChargeCapacity2.setWordWrap(True) # create input box self.fullChargeCapacityBox2 = QLineEdit(self) self.fullChargeCapacityBox2.setStyleSheet(GUI_Style.updateField) self.fullChargeCapacityBox2.setMaximumWidth(50) # create layout self.fullCharge_Layout2 = QHBoxLayout() self.fullCharge_Layout2.addWidget(self.fullChargeCapacity2) self.fullCharge_Layout2.addWidget(self.fullChargeCapacityBox2) def runTimeToEmpty_2(self): # create label self.runTimeToEmpty2 = QLabel(self) self.runTimeToEmpty2.setText("Run Time To Empty") self.runTimeToEmpty2.setStyleSheet(GUI_Style.nameLabel) self.runTimeToEmpty2.setWordWrap(True) # create input box self.runTimeToEmptyBox2 = QLineEdit(self) self.runTimeToEmptyBox2.setStyleSheet(GUI_Style.updateField) self.runTimeToEmptyBox2.setMaximumWidth(50) # create layout self.runTimeToEmpty_Layout2 = QHBoxLayout() self.runTimeToEmpty_Layout2.addWidget(self.runTimeToEmpty2) self.runTimeToEmpty_Layout2.addWidget(self.runTimeToEmptyBox2) def averageTimeToEmpty_2(self): # create label self.avgTimeToEmpty2 = QLabel(self) self.avgTimeToEmpty2.setText("Average Time To Empty") self.avgTimeToEmpty2.setStyleSheet(GUI_Style.nameLabel) self.avgTimeToEmpty2.setWordWrap(True) # create input box self.avgTimeToEmptyBox2 = QLineEdit(self) self.avgTimeToEmptyBox2.setStyleSheet(GUI_Style.updateField) self.avgTimeToEmptyBox2.setMaximumWidth(50) # create layout self.avgTimeToEmpty_Layout2 = QHBoxLayout() self.avgTimeToEmpty_Layout2.addWidget(self.avgTimeToEmpty2) self.avgTimeToEmpty_Layout2.addWidget(self.avgTimeToEmptyBox2) def averageTimeToFull_2(self): # create label self.avgTimeToFull2 = QLabel(self) self.avgTimeToFull2.setText("Average Time To Full") self.avgTimeToFull2.setStyleSheet(GUI_Style.nameLabel) self.avgTimeToFull2.setWordWrap(True) # create input box self.avgTimeToFullBox2 = QLineEdit(self) self.avgTimeToFullBox2.setStyleSheet(GUI_Style.updateField) self.avgTimeToFullBox2.setMaximumWidth(50) # create layout self.avgTimeToFull_Layout2 = QHBoxLayout() self.avgTimeToFull_Layout2.addWidget(self.avgTimeToFull2) self.avgTimeToFull_Layout2.addWidget(self.avgTimeToFullBox2) def chargingCurrent_2(self): # create label self.chargingCurrent2 = QLabel(self) self.chargingCurrent2.setText("Charging Current") self.chargingCurrent2.setStyleSheet(GUI_Style.nameLabel) # create input box self.chargingCurrentBox2 = QLineEdit(self) self.chargingCurrentBox2.setStyleSheet(GUI_Style.updateField) self.chargingCurrentBox2.setMaximumWidth(50) # create layout self.charging_Current_Layout2 = QHBoxLayout() self.charging_Current_Layout2.addWidget(self.chargingCurrent2) self.charging_Current_Layout2.addWidget(self.chargingCurrentBox2) def chargingVoltage_2(self): # create label self.chargingVoltage2 = QLabel(self) self.chargingVoltage2.setText("Charging Voltage") self.chargingVoltage2.setStyleSheet(GUI_Style.nameLabel) # create input box self.chargingVoltageBox2 = QLineEdit(self) self.chargingVoltageBox2.setStyleSheet(GUI_Style.updateField) self.chargingVoltageBox2.setMaximumWidth(50) # create layout self.charging_Voltag_Layout2 = QHBoxLayout() self.charging_Voltag_Layout2.addWidget(self.chargingVoltage2) self.charging_Voltag_Layout2.addWidget(self.chargingVoltageBox2) def Battery_Status_2(self): # create label self.batteryStatus2 = QLabel(self) self.batteryStatus2.setText("Battery Status") self.batteryStatus2.setStyleSheet(GUI_Style.nameLabel) # create input box self.batteryStatusBox2 = QLineEdit(self) self.batteryStatusBox2.setStyleSheet(GUI_Style.updateField) self.batteryStatusBox2.setMaximumWidth(50) # create layout self.batteryStatusLayout2 = QHBoxLayout() self.batteryStatusLayout2.addWidget(self.batteryStatus2) self.batteryStatusLayout2.addWidget(self.batteryStatusBox2) def Cycle_Count_2(self): # create label self.cycleCount2 = QLabel(self) self.cycleCount2.setText("Cycle Count") self.cycleCount2.setStyleSheet(GUI_Style.nameLabel) # create input box self.cycleCountBox2 = QLineEdit(self) self.cycleCountBox2.setStyleSheet(GUI_Style.updateField) self.cycleCountBox2.setMaximumWidth(50) # create layout self.cycleCountLayout2 = QHBoxLayout() self.cycleCountLayout2.addWidget(self.cycleCount2) self.cycleCountLayout2.addWidget(self.cycleCountBox2) def Serial_Number_2(self): # create label self.serNum2 = QLabel(self) self.serNum2.setText("Serial Number") self.serNum2.setStyleSheet(GUI_Style.nameLabel) # create input box self.serNumBox2 = QLineEdit(self) self.serNumBox2.setStyleSheet(GUI_Style.updateField) self.serNumBox2.setMaximumWidth(50) # create layout self.serialNumLayout2 = QHBoxLayout() self.serialNumLayout2.addWidget(self.serNum2) self.serialNumLayout2.addWidget(self.serNumBox2) def Device_Name_2(self): # create label self.devName2 = QLabel(self) self.devName2.setText("Device Name") self.devName2.setStyleSheet(GUI_Style.nameLabel) # create input box self.devNameBox2 = QLineEdit(self) self.devNameBox2.setStyleSheet(GUI_Style.updateField) self.devNameBox2.setMaximumWidth(50) # create layout self.deviceNameLayout2 = QHBoxLayout() self.deviceNameLayout2.addWidget(self.devName2) self.deviceNameLayout2.addWidget(self.devNameBox2) def Cell_Voltage4_2(self): # create label self.cellVolt4_2 = QLabel(self) self.cellVolt4_2.setText("Cell Voltage 4") self.cellVolt4_2.setStyleSheet(GUI_Style.nameLabel) # create input box self.cellVolt4Box2 = QLineEdit(self) self.cellVolt4Box2.setStyleSheet(GUI_Style.updateField) self.cellVolt4Box2.setMaximumWidth(50) # create layout self.cellVoltage4_Layout2 = QHBoxLayout() self.cellVoltage4_Layout2.addWidget(self.cellVolt4_2) self.cellVoltage4_Layout2.addWidget(self.cellVolt4Box2) def Cell_Voltage3_2(self): # create label self.cellVolt3_2 = QLabel(self) self.cellVolt3_2.setText("Cell Voltage 3") self.cellVolt3_2.setStyleSheet(GUI_Style.nameLabel) # create input box self.cellVolt3Box2 = QLineEdit(self) self.cellVolt3Box2.setStyleSheet(GUI_Style.updateField) self.cellVolt3Box2.setMaximumWidth(50) # create layout self.cellVoltage3_Layout2 = QHBoxLayout() self.cellVoltage3_Layout2.addWidget(self.cellVolt3_2) self.cellVoltage3_Layout2.addWidget(self.cellVolt3Box2) def Cell_Voltage2_2(self): # create label self.cellVolt2_2 = QLabel(self) self.cellVolt2_2.setText("Cell Voltage 2") self.cellVolt2_2.setStyleSheet(GUI_Style.nameLabel) # create input box self.cellVolt2Box2 = QLineEdit(self) self.cellVolt2Box2.setStyleSheet(GUI_Style.updateField) self.cellVolt2Box2.setMaximumWidth(50) # create layout self.cellVoltage2_Layout2 = QHBoxLayout() self.cellVoltage2_Layout2.addWidget(self.cellVolt2_2) self.cellVoltage2_Layout2.addWidget(self.cellVolt2Box2) def Cell_Voltage1_2(self): # create label self.cellVolt1_2 = QLabel(self) self.cellVolt1_2.setText("Cell Voltage 1") self.cellVolt1_2.setStyleSheet(GUI_Style.nameLabel) # create input box self.cellVolt1Box2 = QLineEdit(self) self.cellVolt1Box2.setStyleSheet(GUI_Style.updateField) self.cellVolt1Box2.setMaximumWidth(50) # create layout self.cellVoltage1_Layout2 = QHBoxLayout() self.cellVoltage1_Layout2.addWidget(self.cellVolt1_2) self.cellVoltage1_Layout2.addWidget(self.cellVolt1Box2) # ------------------------------------------------------------------ # ---------------- Create Status Bar Widgets ----------------------- # ------------------------------------------------------------------ def StatusBar(self): self.statusBar = QStatusBar() self.statusBar.setStyleSheet(GUI_Style.statusBarWhite) self.relay1_40 = Relay_1_40_Ohm(self, "40\u03A9 Relay 1", self.GPIO_ch1) self.relay1_40.setStyleSheet(GUI_Style.buttonPressed) self.relay1_40.pressed.connect(self.relay1_40.On_Click) self.relay1_40.released.connect(self.relay1_40.Un_Click) self.relay1_60 = Relay_1_60_Ohm(self, "60\u03A9 Relay 1", self.GPIO_ch1) self.relay1_60.setStyleSheet(GUI_Style.buttonPressed) self.relay1_60.pressed.connect(self.relay1_60.On_Click) self.relay1_60.released.connect(self.relay1_60.Un_Click) self.relay1_500 = Relay_1_500_Ohm(self, "500\u03A9 Relay 1", self.GPIO_ch1) self.relay1_500.setStyleSheet(GUI_Style.buttonPressed) self.relay1_500.pressed.connect(self.relay1_500.On_Click) self.relay1_500.released.connect(self.relay1_500.Un_Click) self.relay1_1k = Relay_1_1k_Ohm(self, "1k\u03A9 Relay 1", self.GPIO_ch1) self.relay1_1k.setStyleSheet(GUI_Style.buttonPressed) self.relay1_1k.pressed.connect(self.relay1_1k.On_Click) self.relay1_1k.released.connect(self.relay1_1k.Un_Click) self.relay2_40 = Relay_2_40_Ohm(self, "40\u03A9 Relay 2", self.GPIO_ch2) self.relay2_40.setStyleSheet(GUI_Style.buttonPressed) self.relay2_40.pressed.connect(self.relay2_40.On_Click) self.relay2_40.released.connect(self.relay2_40.Un_Click) self.relay2_60 = Relay_2_60_Ohm(self, "60\u03A9 Relay 2", self.GPIO_ch2) self.relay2_60.setStyleSheet(GUI_Style.buttonPressed) self.relay2_60.pressed.connect(self.relay2_60.On_Click) self.relay2_60.released.connect(self.relay2_60.Un_Click) self.relay2_500 = Relay_2_500_Ohm(self, "500\u03A9 Relay 2", self.GPIO_ch2) self.relay2_500.setStyleSheet(GUI_Style.buttonPressed) self.relay2_500.pressed.connect(self.relay2_500.On_Click) self.relay2_500.released.connect(self.relay2_500.Un_Click) self.relay2_1k = Relay_2_1k_Ohm(self, "1k\u03A9 Relay 2", self.GPIO_ch2) self.relay2_1k.setStyleSheet(GUI_Style.buttonPressed) self.relay2_1k.pressed.connect(self.relay2_1k.On_Click) self.relay2_1k.released.connect(self.relay2_1k.Un_Click) self.statusBar.addPermanentWidget(self.relay1_40, 0) self.statusBar.addPermanentWidget(self.relay1_60, 0) self.statusBar.addPermanentWidget(self.relay1_500, 0) self.statusBar.addPermanentWidget(self.relay1_1k, 0) self.statusBar.addPermanentWidget(self.relay2_40, 0) self.statusBar.addPermanentWidget(self.relay2_60, 0) self.statusBar.addPermanentWidget(self.relay2_500, 0) self.statusBar.addPermanentWidget(self.relay2_1k, 0) self.statusBar.showMessage("Starting Up... ", 4000) # ------------------------------------------------------------------ # ----------- Close All Threads at app closure --------------------- # ------------------------------------------------------------------ # Stop all threads when GUI is closed def closeEvent(self, *args, **kwargs): GPIO.cleanup() self.GPIO_ch1.Set_Exit_Program(True) self.GPIO_ch1.wait(100) self.GPIO_ch2.Set_Exit_Program(True) self.GPIO_ch2.wait(100)
class mywindow2(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self): super(mywindow2, self).__init__() self.setupUi(self) self.file_name = r'./2020竞赛公开题库.CSV' self.statars = 'C' # 当前单选 self.conts1 = int(sums) # 历史答题记录 self.correct_sum = 0 # 答对汇总 self.dati = 0 # 现答题数 self.num_answ = 0 # 总答题数 self.error_sum = 0 # 答错汇总 self.down.clicked.connect(self.down1) # 按钮按下槽函数 self.up.clicked.connect(self.up1) self.randoms.clicked.connect(self.randoms1) self.order.clicked.connect(self.order1) self.rorder.clicked.connect(self.rorder1) self.search.clicked.connect(self.search1) self.statusBar = QStatusBar() # 状态栏添加进度条 self.statusBar.setStyleSheet('QStatusBar::item {border: none;}') self.setStatusBar(self.statusBar) self.progressBar = QProgressBar() self.progressBar.setGeometry(QtCore.QRect(-10, 490, 761, 23)) self.statusBar.addPermanentWidget(self.progressBar) self.contenta.clicked.connect(partial(self.onButtonClick, 'A')) # 单选按钮槽函数 self.contentb.clicked.connect(partial(self.onButtonClick, 'B')) self.contentc.clicked.connect(partial(self.onButtonClick, 'C')) self.contentd.clicked.connect(partial(self.onButtonClick, 'D')) self.Question_order, self.Question_type, self.topic, self.A, self.B, self.C, self.D, self.answer, self.Difficulty = self.readti( ) self.progressBar.setProperty( "value", self.conts1 / len(self.Question_order) * 100) self.Question_order = list(range(len(self.Question_order))) self.dispy() self.contentc.setFocus() self.contentc.setChecked(True) def dispy(self): a, b, c, d = 'A\t', 'B\t', 'C\t', 'D\t' self.label.setText( 'No.%s\t\tDifficulty:%s\t\tQtypes:%s\t\tNum:%s' % (self.conts1 + 1, degree[self.Difficulty[self.Question_order[self.conts1]]], types[self.Question_type[self.Question_order[self.conts1]]], len(self.Question_order))) self.topics.setText('题目:<font color="red">%s</font>' % (self.topic[self.Question_order[self.conts1]])) self.contenta.setText('%s%s' % (a, self.A[self.Question_order[self.conts1]])) self.contentb.setText('%s%s' % (b, self.B[self.Question_order[self.conts1]])) self.contentc.setText('%s%s' % (c, self.C[self.Question_order[self.conts1]])) self.contentd.setText('%s%s' % (d, self.D[self.Question_order[self.conts1]])) def down1(self): global flag if flag: flag = False self.contenta.setStyleSheet('background-color: #E6E9ED') self.contentb.setStyleSheet('background-color: #E6E9ED') self.contentc.setStyleSheet('background-color: #E6E9ED') self.contentd.setStyleSheet('background-color: #E6E9ED') else: if self.conts1 >= len(self.Question_order): self.statusBar.showMessage('没有下一题', 2000) return else: if self.contenta.isChecked() | self.contentb.isChecked( ) | self.contentc.isChecked() | self.contentd.isChecked(): if id(self.statars) == id( self.answer[self.Question_order[self.conts1]]): self.statusBar.showMessage('答题正确', 2000) self.progressBar.setProperty( "value", self.conts1 / len(self.Question_order) * 100) self.correct_sum += 1 self.dati += 1 else: self.statusBar.showMessage( '答题错误,正确答案为%s' % self.answer[self.Question_order[self.conts1]], 2000) self.progressBar.setProperty( "value", self.conts1 / len(self.Question_order) * 100) self.error_sum += 1 # 搭错计总 self.dati += 1 # 现答题数量计总 flag = True if self.answer[self.conts1] == 'A': self.contenta.setStyleSheet( "background-color: #E5B751") # 4C3C3C elif self.answer[self.conts1] == 'B': self.contentb.setStyleSheet( "background-color: #E5B751") elif self.answer[self.conts1] == 'C': self.contentc.setStyleSheet( "background-color: #E5B751") elif self.answer[self.conts1] == 'D': self.contentd.setStyleSheet( "background-color: #E5B751") return else: self.statusBar.showMessage('选择不能为空', 2000) return self.conts1 += 1 # 答题数量计总 self.statars = 'C' self.dispy() self.contentc.setFocus() self.contentc.setChecked(True) def up1(self): if self.conts1 <= 0: self.statusBar.showMessage('没有上一题', 2000) else: if self.contenta.isChecked() | self.contentb.isChecked( ) | self.contentc.isChecked() | self.contentd.isChecked(): self.conts1 -= 1 self.progressBar.setProperty( "value", self.conts1 / len(self.Question_order) * 100) self.dispy() if self.answer[self.conts1] == 'A': self.contenta.setChecked(True) self.statars = 'A' elif self.answer[self.conts1] == 'B': self.contentb.setChecked(True) self.statars = 'B' elif self.answer[self.conts1] == 'C': self.contentc.setChecked(True) self.statars = 'C' elif self.answer[self.conts1] == 'D': self.contentd.setChecked(True) self.statars = 'D' else: self.statusBar.showMessage('选择不能为空', 2000) def randoms1(self): random.shuffle(self.Question_order) # 随机顺序 self.num_answ += self.dati self.conts1 = 0 self.progressBar.setProperty( "value", self.conts1 / len(self.Question_order) * 100) self.dispy() self.contentb.setFocus() self.contentb.setChecked(True) def order1(self): self.Question_order.sort() # 正序 self.num_answ += self.dati self.conts1 = 0 self.progressBar.setProperty( "value", self.conts1 / len(self.Question_order) * 100) self.dispy() self.contentb.setFocus() self.contentb.setChecked(True) def rorder1(self): self.Question_order.sort(reverse=True) # 反序 self.num_answ += self.dati self.conts1 = 0 self.progressBar.setProperty( "value", self.conts1 / len(self.Question_order) * 100) self.dispy() self.contentb.setFocus() self.contentb.setChecked(True) def readti(self): # 题目 cop = re.compile("[^a-z^A-Z^0-9]") with open(self.file_name, 'r', errors='ignore') as f: reader = csv.reader(f) Question_order = [] Question_type = [] topic = [] A = [] B = [] C = [] D = [] answer = [] Difficulty = [] for row in reader: try: if grade == row[8]: # 题目难易程度 continue elif grade == row[8]: continue if row[1] in cop.sub('', subject): continue Question_order.append(row[0]) Question_type.append(row[1]) topic.append(row[2]) A.append(row[3]) B.append(row[4]) C.append(row[5]) D.append(row[6]) answer.append(row[7]) Difficulty.append(row[8]) except: pass f.close() return Question_order[2:], Question_type[2:], topic[2:], A[2:], B[ 2:], C[2:], D[2:], answer[2:], Difficulty[2:] def onButtonClick(self, n): # 赋值被按下的单选按钮 self.statars = n self.down.setFocus() def search1(self): url = 'https://cn.bing.com/search?q=%s' % self.topic[ self.Question_order[self.conts1]] webbrowser.open(url) self.contentb.setFocus() self.contentb.setChecked(True) def closeEvent(self, QCloseEvent): # 关闭事件函数 cf.set("config", "sum", str(self.conts1)) cf.write(open('./config.ini', "w")) self.num_answ += self.dati if self.dati > 0: QtWidgets.QMessageBox.information( self, "", "答题数量:%s\n正确量:%s\n错误量:%s" % (self.num_answ, self.correct_sum, self.error_sum), QtWidgets.QMessageBox.Yes)
class MainWindow(QtWidgets.QMainWindow): """ This class is the main window of the program, containing all the graphics objects such as the toolbar, the state bar, the menu and the canvas scene. Attributes ---------- SYSNAME : str The application name displayed in the window. nav_menu_bar : QMenuBar Menu bar of the window, containing different menus. status_bar : QStatusBar Status bar of the window. toolbar : BlocksToolbar Toolbar appearing on the left of the window, showing several buttons to add elements to the canvas. parameters : ParamToolbar Fixed toolbar on the right of the window, displaying details about a certain block. canvas : Canvas Central view of the window, containing a blank space in which the blocks appear. Methods ---------- connect_events() Connects to all signals of the elements. init_menu_bar() Sets all menus of the menu bar and their actions. update_status() Changes the status bar displaying on it the canvas mode and the selected items. change_draw_mode(DrawingMode) Changes the drawing mode of the canvas. create_from(NodeButton) Draws in the canvas the block corresponding to the button pressed. reset() Clears both graphical and logical network. open() Procedure to open an existing network. save(bool) Saves the current network in a new file or in the opened one. """ def __init__(self): super(MainWindow, self).__init__() # Init window appearance self.SYSNAME = "NeVer 2" self.setWindowTitle(self.SYSNAME) self.setWindowIcon(QtGui.QIcon(ROOT_DIR + '/res/icons/logo.png')) self.setStyleSheet("background-color: " + style.GREY_1) # Navigation menu self.nav_menu_bar = self.menuBar() self.init_nav_menu_bar() # Blocks toolbar self.toolbar = BlocksToolbar(ROOT_DIR + '/res/json/blocks.json') # Parameters toolbar self.parameters = ParamToolbar() # Drawing Canvas self.canvas = Canvas(self.toolbar.blocks) # Status bar self.status_bar = QStatusBar() self.status_bar.setSizeGripEnabled(False) self.setStatusBar(self.status_bar) self.status_bar.setStyleSheet(style.STATUS_BAR_STYLE) self.status_bar_mode_label = CustomLabel() self.status_bar_mode_label.setStyleSheet(style.STATUS_BAR_WIDGET_STYLE) self.status_bar_selections_label = CustomLabel() self.status_bar_selections_label.setStyleSheet(style.STATUS_BAR_WIDGET_STYLE) self.status_bar.addPermanentWidget(self.status_bar_selections_label) self.status_bar.addPermanentWidget(self.status_bar_mode_label) # And adding them to the window self.addDockWidget(Qt.RightDockWidgetArea, self.parameters, Qt.Vertical) self.addToolBar(QtCore.Qt.ToolBarArea.LeftToolBarArea, self.toolbar) self.setCentralWidget(self.canvas.view) self.connect_events() def connect_events(self): """ Associate the various events coming from button signals and other graphical objects to the correct actions. """ # Block buttons for b in itertools.chain(self.toolbar.b_buttons.values(), self.toolbar.p_buttons.values()): b.clicked.connect(self.create_from(b)) # Draw line button self.toolbar.f_buttons["draw_line"].clicked \ .connect(lambda: self.change_draw_mode(DrawingMode.DRAW_LINE)) # Insert block button self.toolbar.f_buttons["insert_block"].clicked \ .connect(lambda: self.change_draw_mode(DrawingMode.DRAW_BLOCK)) # Parameters box appearing self.canvas.param_requested \ .connect(lambda: self.parameters.display(self.canvas.block_to_show)) # State bar updating self.canvas.scene.has_changed_mode \ .connect(lambda: self.update_status()) self.canvas.scene.selectionChanged \ .connect(lambda: self.update_status()) def init_nav_menu_bar(self): """ This method creates the navigation bar by adding the menus and corresponding actions. """ self.nav_menu_bar.setStyleSheet(style.MENU_BAR_STYLE) self.setContextMenuPolicy(Qt.PreventContextMenu) actions_dict = dict() with open(ROOT_DIR + '/res/json/menu.json') as json_menu: menu = json.loads(json_menu.read()) for menu_item, actions in menu.items(): entry = self.nav_menu_bar.addMenu(menu_item) entry.setStyleSheet(style.MENU_BAR_STYLE) for a, v in actions.items(): action_item = QAction(a, self) if "Shortcut" in v.keys(): action_item.setShortcut(v["Shortcut"]) if v["checkable"] == "True": action_item.setCheckable(True) action_item.setChecked(True) entry.addAction(action_item) actions_dict[f"{menu_item}:{a}"] = action_item # Triggers connection actions_dict["File:New..."].triggered.connect(lambda: self.reset()) actions_dict["File:Open..."].triggered.connect(lambda: self.open()) actions_dict["File:Load property..."].triggered.connect(lambda: self.canvas.project.open_property()) actions_dict["File:Save"].triggered.connect(lambda: self.save(False)) actions_dict["File:Save as..."].triggered.connect(lambda: self.save()) actions_dict["File:Exit"].triggered.connect(lambda: self.close()) actions_dict["Edit:Copy"].triggered.connect(lambda: self.canvas.copy_selected()) actions_dict["Edit:Paste"].triggered.connect(lambda: self.canvas.paste_selected()) actions_dict["Edit:Cut"].triggered.connect(lambda: self.canvas.cut_selected()) actions_dict["Edit:Delete"].triggered.connect(lambda: self.canvas.delete_selected()) actions_dict["Edit:Clear canvas"].triggered.connect(lambda: self.clear()) actions_dict["Edit:Draw connection"].triggered.connect(lambda: self.change_draw_mode(DrawingMode.DRAW_LINE)) actions_dict["Edit:Edit node"].triggered.connect( lambda: self.canvas.scene.edit_node(self.edit_action_validation())) actions_dict["View:Zoom in"].triggered.connect(lambda: self.canvas.zoom_in()) actions_dict["View:Zoom out"].triggered.connect(lambda: self.canvas.zoom_out()) actions_dict["View:Dimensions"].toggled.connect(lambda: self.canvas.scene.switch_dim_visibility()) actions_dict["View:Tools"].toggled.connect(lambda: self.toolbar.change_tools_mode()) actions_dict["View:Blocks"].toggled.connect(lambda: self.toolbar.change_blocks_mode()) actions_dict["View:Parameters"].triggered.connect( lambda: self.canvas.show_parameters(self.parameters_action_validation())) actions_dict["Learning:Train..."].triggered.connect(lambda: self.canvas.train_network()) actions_dict["Learning:Prune..."].triggered.connect(lambda: self.temp_window()) actions_dict["Verification:Verify..."].triggered.connect(lambda: self.canvas.verify_network()) actions_dict["Verification:Repair..."].triggered.connect(lambda: self.temp_window()) actions_dict["Help:Show guide"].triggered.connect(lambda: self.show_help()) @staticmethod def temp_window(): dialog = MessageDialog("Work in progress...", MessageType.MESSAGE) dialog.exec() def create_from(self, button: QPushButton): """ This method draws on the canvas the block corresponding to the pressed BlockButton. Parameters ---------- button : CustomButton The pressed button. """ def pressed(): if isinstance(button, NodeButton): self.canvas.draw_node(button.node_type) elif isinstance(button, PropertyButton): if self.canvas.project.network.nodes: self.canvas.draw_property(button.name) return pressed def update_status(self): """ This method updates the widget in the status bar, displaying the items selected and the current drawing mode. """ # Show the canvas drawing mode if self.canvas.scene.mode == DrawingMode.DRAW_LINE: self.status_bar_mode_label.setText("GraphicLine drawing") elif self.canvas.scene.mode == DrawingMode.DRAW_BLOCK: self.status_bar_mode_label.setText("Block insertion") else: self.status_bar_mode_label.setText("") # Show the selected items, if any if not self.canvas.scene.selectedItems(): self.status_bar_selections_label.setText("") else: selections = "" semicolons = ["; " for _ in range(len(self.canvas.scene.selectedItems()))] semicolons[-1] = "" # No semicolon for the last element in the selections list for counter, item in enumerate(self.canvas.scene.selectedItems()): if type(item) is QGraphicsRectItem: # If the item is a rect, prev_node_id is written selections += self.canvas.scene.blocks[item].block_id selections += semicolons[counter] elif type(item) is GraphicLine: # If the item is a line, origin and destination ids are written origin = self.canvas.scene.blocks[item.origin].block_id destination = self.canvas.scene.blocks[item.destination].block_id selections += origin + "->" + destination selections += semicolons[counter] self.status_bar_selections_label.setText(selections) def change_draw_mode(self, newmode: DrawingMode = None): """ This method changes the drawing mode of the canvas when the user clicks on the corresponding button. The mode changes depending on the previous one. Parameters ---------- newmode : DrawingMode, optional Specifies the new DrawingMode to use. (Default: None) """ if newmode is None: self.canvas.scene.set_mode(DrawingMode.IDLE) else: curmode = self.canvas.scene.mode if newmode == curmode: self.canvas.scene.set_mode(DrawingMode.IDLE) else: self.canvas.scene.set_mode(newmode) def clear(self): """ Utility for deleting the content of the window. Before taking effect, it prompts the user to confirm. """ if self.canvas.num_nodes > 0: alert_dialog = ConfirmDialog("Clear workspace", "The network will be erased and your work will be lost.\n" "Do you wish to continue?") alert_dialog.exec() if alert_dialog.confirm: self.canvas.clear_scene() self.canvas.scene.has_changed_mode.connect(lambda: self.update_status()) self.canvas.scene.selectionChanged.connect(lambda: self.update_status()) self.update_status() self.setWindowTitle(self.SYSNAME) else: self.canvas.clear_scene() self.canvas.scene.has_changed_mode.connect(lambda: self.update_status()) self.canvas.scene.selectionChanged.connect(lambda: self.update_status()) self.update_status() self.setWindowTitle(self.SYSNAME) def reset(self): """ This method clears the scene and the network, stops to work on the file and restarts from scratch. """ self.clear() self.canvas.project.file_name = ("", "") self.setWindowTitle(self.SYSNAME) def open(self): """ This method handles the opening of a file. """ if self.canvas.renderer.disconnected_network: # If there is already a network in the canvas, it is asked to the # user if continuing with opening. confirm_dialog = ConfirmDialog("Open network", "A new network will be opened " "cancelling the current nodes.\n" "Do you wish to continue?") confirm_dialog.exec() # If the user clicks on "yes", the canvas is cleaned, a net is # opened and the window title is updated. if confirm_dialog is not None: if confirm_dialog.confirm: # The canvas is cleaned self.canvas.clear_scene() self.canvas.scene.has_changed_mode.connect(lambda: self.update_status()) self.canvas.scene.selectionChanged.connect(lambda: self.update_status()) self.update_status() # A file is opened self.canvas.project.open() if self.canvas.project.network is not None: self.setWindowTitle(self.SYSNAME + " - " + self.canvas.project.network.identifier) else: # If the canvas was already empty, the opening function is directly # called self.canvas.project.open() if self.canvas.project.network is not None: self.setWindowTitle(self.SYSNAME + " - " + self.canvas.project.network.identifier) def save(self, _as: bool = True): """ This method saves the current network if the format is correct Parameters ---------- _as : bool, optional This attribute distinguishes between "save" and "save as". If _as is True the network will be saved in a new file, while if _as is False the network will overwrite the current one. (Default: True) """ if len(self.canvas.renderer.NN.nodes) == 0 or \ len(self.canvas.renderer.NN.edges) == 0: # Limit case: one disconnected node -> new network with one node if len(self.canvas.renderer.disconnected_network) == 1: for node in self.canvas.renderer.disconnected_network: try: self.canvas.renderer.add_node_to_nn(node) self.canvas.project.save(_as) self.setWindowTitle(self.SYSNAME + " - " + self.canvas.project.network.identifier) except Exception as e: error_dialog = MessageDialog(str(e), MessageType.ERROR) error_dialog.exec() # More than one disconnected nodes cannot be saved elif len(self.canvas.renderer.disconnected_network) > 1: not_sequential_dialog = MessageDialog("The network is not sequential, and " "cannot be saved.", MessageType.ERROR) not_sequential_dialog.exec() else: # Network is empty message = MessageDialog("The network is empty!", MessageType.MESSAGE) message.exec() elif self.canvas.renderer.is_nn_sequential(): # If there are logical nodes, the network is sequential every_node_connected = True # every node has to be in the nodes dictionary for node in self.canvas.renderer.disconnected_network: if node not in self.canvas.project.network.nodes: every_node_connected = False break if every_node_connected: self.canvas.project.save(_as) if self.canvas.project.network is not None: self.setWindowTitle(self.SYSNAME + " - " + self.canvas.project.network.identifier) else: # If there are disconnected nodes, a message is displayed to the # user to choose if saving only the connected network confirm_dialog = ConfirmDialog("Save network", "All the nodes outside the " "sequential network will lost.\n" "Do you wish to continue?") confirm_dialog.exec() if confirm_dialog.confirm: self.canvas.project.save(_as) if self.canvas.project.network is not None: self.setWindowTitle(self.SYSNAME + " - " + self.canvas.project.network.identifier) else: # If the network is not sequential, it cannot be saved. not_sequential_dialog = MessageDialog("The network is not sequential and " "cannot be saved.", MessageType.ERROR) not_sequential_dialog.exec() def edit_action_validation(self) -> Optional[NodeBlock]: """ This method performs a check on the object on which the edit action is called, in order to prevent unwanted operations. Returns ---------- NodeBlock The graphic wrapper of the NetworkNode selected, if present. """ if self.canvas.scene.selectedItems(): if type(self.canvas.scene.selectedItems()[0]) is QGraphicsRectItem: # Return block graphic object return self.canvas.scene.blocks[self.canvas.scene.selectedItems()[0]] elif type(self.canvas.scene.selectedItems()[0]) is GraphicLine: msg_dialog = MessageDialog("Can't edit edges, please select a block instead.", MessageType.ERROR) msg_dialog.exec() else: err_dialog = MessageDialog("No block selected.", MessageType.MESSAGE) err_dialog.exec() def parameters_action_validation(self) -> Optional[NodeBlock]: """ This method performs a check on the object on which the parameters action is called, in order to prevent unwanted operations. Returns ---------- NodeBlock The graphic wrapper of the NetworkNode selected, if present. """ if self.canvas.scene.selectedItems(): if type(self.canvas.scene.selectedItems()[0]) is QGraphicsRectItem: # Return block graphic object return self.canvas.scene.blocks[self.canvas.scene.selectedItems()[0]] elif type(self.canvas.scene.selectedItems()[0]) is GraphicLine: msg_dialog = MessageDialog("No parameters available for connections.", MessageType.ERROR) msg_dialog.exec() else: err_dialog = MessageDialog("No block selected.", MessageType.MESSAGE) err_dialog.exec() @staticmethod def show_help(): help_dialog = HelpDialog() help_dialog.exec()
class Ahsoka(QWidget): def __init__(self): super().__init__() self.init() self.place() self.show() def init(self): self.setWindowTitle('Ahsoka') self.setWindowIcon(QIcon(imgPath('icon.png'))) self.urlLabel = QLabel('Ссылка:') self.nameLabel = QLabel('Название:') self.urlEdit = QLineEdit() self.nameEdit = QLineEdit() self.downloadBtn = QPushButton('Скачать') self.updateBtn = QPushButton('Обновить') self.gamesList = QListWidget() self.enginesBox = QGroupBox('Движки') self.playBtn = QPushButton('Играть') self.delBtn = QPushButton('Удалить') self.statusBar = QStatusBar() self.connectAll() def successMessage(self, message): self.statusBar.setStyleSheet('color: green') self.statusBar.showMessage(message) def errorMessage(self, message): self.statusBar.setStyleSheet('color: red') self.statusBar.showMessage(message) def connectAll(self): self.downloadBtn.clicked.connect(self.downloadGame) self.updateBtn.clicked.connect(self.setGames) self.gamesList.setVerticalScrollBar(QScrollBar()) self.setEngines() self.setGames() self.playBtn.clicked.connect(self.play) self.delBtn.clicked.connect(self.delGame) self.successMessage('Добро пожаловать в лучший лаунчер флешек Ahsoka') def place(self): self.grid = QGridLayout() self.grid.setSpacing(5) self.grid.addWidget(self.urlLabel, 0, 0, 1, 1) self.grid.addWidget(self.urlEdit, 0, 1, 1, 1) self.grid.addWidget(self.nameLabel, 1, 0, 1, 1) self.grid.addWidget(self.nameEdit, 1, 1, 1, 1) self.grid.addWidget(self.downloadBtn, 0, 2, 1, 1) self.grid.addWidget(self.updateBtn, 1, 2, 1, 1) self.grid.addWidget(self.gamesList, 2, 0, 1, 2) self.grid.addWidget(self.enginesBox, 2, 2, 1, 1) self.grid.addWidget(self.playBtn, 3, 0, 1, 2) self.grid.addWidget(self.delBtn, 3, 2, 1, 1) self.grid.addWidget(self.statusBar, 4, 0, 1, 3) self.setLayout(self.grid) def setGames(self): self.gamesList.clear() for game in sorted(listdir('games')): self.gamesList.addItem(game[:-4].title()) def setEngines(self): enginesLayout = QVBoxLayout() for engine in ['flashplayer']: btn = QRadioButton(engine.capitalize()) if 'flashplayer' in engine: btn.setChecked(True) enginesLayout.addWidget(btn) self.enginesBox.setLayout(enginesLayout) def wget(self, *args, **kwargs): download(*args, **kwargs) self.setGames() self.urlEdit.clear() self.nameEdit.clear() self.successMessage('Загрузка завершена') def downloadGame(self): try: url = swf = self.urlEdit.text().strip() name = self.nameEdit.text().strip() if not url.endswith('.swf'): req = get(url) self.statusBar.showMessage(str(req)) try: html = req.content.decode('utf-8') except: html = req.content.decode('cp1251') swf = findall(r'\".[^"]+\.swf\"', html)[0][1:-1] swf = urljoin(url, swf) print(swf) self.successMessage('Скачивание...') args = swf, kwargs = { 'out': 'games/' } if not name else { 'out': getGamePath(name) } Thread(target=self.wget, args=args, kwargs=kwargs).start() except Exception as Exc: print(Exc) self.urlEdit.clear() self.errorMessage('Попробуйте другую ссылку') def delGame(self): game = self.gamesList.currentItem() if game is None: return remove(getGamePath(game.text())) self.setGames() self.successMessage('Игра удалена') def play(self): game = self.gamesList.currentItem() if game is None: return engine = libPath( ('flashplayer' if sys.platform == 'linux' else 'flashplayer.exe')) args = f'{engine} \"{getGamePath(game.text())}\"', self.statusBar.showMessage('Игра запущена') Thread(target=popen, args=args).start()
class ModelTestsTab(StandardTab): data_type = "Test" def __init__(self): StandardTab.__init__(self) self.dataTable = None self.statusBar = QStatusBar() self.horizontalLayout_2.insertWidget(0, self.statusBar) @QtCore.pyqtSlot() def addItemSlot(self, dialog=None): model_test = ModelTest() if dialog is None: dialog = EditModelTestDialog(self) dialog.set_test(model_test, self.model) status = dialog.exec_() if status: self.dataTable.update_row_from_item(model_test) self.model.add_test(model_test) @QtCore.pyqtSlot() def deleteItemSlot(self): if self.confirmDeletion(): selected_tests = self.dataView.get_selected_items() self.model.gem_remove_tests(selected_tests) @QtCore.pyqtSlot() def editItemSlot(self, *args, dialog=None): selected_indices = self.dataView.get_selected_indexes() if selected_indices: # Display result if only an item from the second column was selected if len(selected_indices) == 1 and selected_indices[0].column() == 1: solution = self.dataTable.itemFromIndex(selected_indices[0]).link if solution: solution.method = "fba" dialog = factory_solution(self.model, solution) self.model.dialogs.add(dialog) dialog.show() return if dialog is None: dialog = EditModelTestDialog(self) row_index = selected_indices[0].row() solution = self.dataTable.item(row_index, 1).link dialog.set_test(self.dataTable.item_from_row(row_index), self.model, solution) status = dialog.exec_() if status: self.dataTable.update_row_from_link(row_index) self.dataView.clearSelection() def set_datatable(self): """ Set the datatable for the proxy model """ if self.model is not None: self.dataTable = self.model.QtTestsTable self.proxyModel.setSourceModel(self.dataTable) self.restore_view_state() @QtCore.pyqtSlot() def run_selected(self): selected_tests = self.dataView.get_selected_items() self.run_tests(selected_tests) @QtCore.pyqtSlot() def run_tests(self, selected=()): if not self.model.tests: return elif not selected: # Run all tests if no selection specified selected = self.model.tests with ProgressDialog(title="Running tests..") as progress: try: test_results = run_tests(selected, self.model, progress) except Exception as e: LOGGER.exception("Error running tests") QMessageBox().critical(None, "Error", "The following error occured " "while running the tests:\n{}".format(str(e))) return mapping = self.dataTable.get_item_to_row_mapping() num_passed = 0 self.dataTable.blockSignals(True) for testcase, result in test_results.items(): row = mapping[testcase] status, solution = result if status: num_passed += 1 self.dataTable.set_status(row, solution, status) self.dataTable.blockSignals(False) self.dataTable.all_data_changed() if num_passed == 0: self.statusBar.setStyleSheet("color: red; font-weight: bold;") elif num_passed == len(test_results): self.statusBar.setStyleSheet("color: green; font-weight: bold;") else: self.statusBar.setStyleSheet("color: orange; font-weight: bold;") self.statusBar.showMessage("{0!s} out of {1!s} tests passed!".format(num_passed, len(test_results)), 4000) @QtCore.pyqtSlot() def copy_testcase(self): selected_tests = self.dataView.get_selected_items() try: copy = selected_tests[0].copy() except: QMessageBox().critical(self, "Error", "Could not copy testcase.") LOGGER.exception("Error copying testcase") else: self.dataTable.update_row_from_item(copy) self.model.add_test(copy) @QtCore.pyqtSlot(QtCore.QPoint) def showContextMenu(self, pos): menu = QMenu() self.add_standard_menu_actions(menu) actions_to_add =[] if len(self.dataView.selectedIndexes()) == 1: menu.addSeparator() action_copy = QAction("Copy testcase") action_copy.triggered.connect(self.copy_testcase) menu.addAction(action_copy) menu.addSeparator() if self.dataView.selectedIndexes(): run_selected_action = QAction(self.tr("Run selected"), menu) run_selected_action.triggered.connect(self.run_selected) actions_to_add.append(run_selected_action) if self.dataTable.rowCount() > 0: run_all_action = QAction(self.tr("Run all"), menu) run_all_action.triggered.connect(self.run_tests) actions_to_add.append(run_all_action) if actions_to_add: menu.addSeparator() menu.addActions(actions_to_add) menu.exec_(self.dataView.viewport().mapToGlobal(pos))
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.patient_id = '' self.result_list = [] self.title_lb = QPushButton() self.exit_bt = QPushButton() self.logo_bt = QPushButton() self.main_widget = QWidget() self.main_layout = QVBoxLayout() self.left_widget = QWidget() self.left_layout = QGridLayout() self.right_widget = QStackedWidget() self.mid_widget = QWidget() self.mid_layout = QHBoxLayout() self.bottom_layout = QHBoxLayout() self.bottom_widget = QWidget() # self.status_bar = QPushButton() # self.status_bar.set # self.stack1 = QWidget() self.stack_system_intro = SystemIntro() self.stack_border_map_intro = BorderMapIntro() self.stack_datapreprocessUI = DataPreprocessUI() self.stack_clusterUI = ClusterUI() self.stack_load_electrode_picUI = LoadElectrodePic() self.stack_generate_border_mapUI = GenerateBorderMap() self.stack_property_map_intro = PropertyMapIntro() self.stack_load_cortex_pic = LoadCortexPic() self.stack_generate_property_map = GeneratePropertyMap() self.stack_function_map_intro = FunctionMapIntro() self.stack_generate_function_map = GenerateFunctionMap() self.left_close = QPushButton("") # 关闭按钮 self.left_visit = QPushButton("") # 空白按钮 self.left_mini = QPushButton("") # 最小化按钮 self.left_close.setFixedSize(15, 15) # 设置关闭按钮的大小 self.left_visit.setFixedSize(15, 15) # 设置按钮大小 self.left_mini.setFixedSize(15, 15) # 设置最小化按钮大小 self.left_close.setStyleSheet( '''QPushButton{background:#F76677;border-radius:5px;}QPushButton:hover{background:red;}''' ) self.left_visit.setStyleSheet( '''QPushButton{background:#F7D674;border-radius:5px;}QPushButton:hover{background:yellow;}''' ) self.left_mini.setStyleSheet( '''QPushButton{background:#6DDF6D;border-radius:5px;}QPushButton:hover{background:green;}''' ) self.left_label_1 = QPushButton("功能区边界聚类算法") self.left_label_1.clicked.connect(self.show_click_meg) self.left_label_1.clicked.connect(self.on_border_map_bt_clicked) self.left_label_1.setObjectName('left_label') self.left_label_2 = QPushButton("功能区属性分类算法") self.left_label_2.clicked.connect(self.show_click_meg) self.left_label_2.clicked.connect(self.on_property_map_bt_clicked) self.left_label_2.setObjectName('left_label') self.left_label_3 = QPushButton("基于聚类和分类的定位算法") self.left_label_3.clicked.connect(self.show_click_meg) self.left_label_3.clicked.connect(self.on_function_map_bt_clicked) self.left_label_3.setObjectName('left_label') self.left_button_1 = QPushButton( qtawesome.icon('fa.music', color='white'), "导入数据") self.left_button_1.clicked.connect(self.on_load_data_bt_clicked) self.left_button_1.clicked.connect(self.show_click_meg) self.left_button_1.setObjectName('left_button') self.left_button_2 = QPushButton( qtawesome.icon('fa.sellsy', color='white'), "预处理及特征提取") self.left_button_2.clicked.connect(self.on_preprocessing_bt_clicked) self.left_button_2.setObjectName('left_button') self.left_button_2.clicked.connect(self.show_click_meg) self.left_button_3 = QPushButton( qtawesome.icon('fa.film', color='white'), "模型加载与识别") self.left_button_3.clicked.connect(self.on_load_model_bt_clicked) self.left_button_3.setObjectName('left_button') self.left_button_3.clicked.connect(self.show_click_meg) self.left_button_4 = QPushButton( qtawesome.icon('fa.home', color='white '), "导入电极分布图") self.left_button_4.clicked.connect(self.on_load_pic_bt_clicked) self.left_button_4.setObjectName('left_button') self.left_button_4.clicked.connect(self.show_click_meg) self.left_button_5 = QPushButton( qtawesome.icon('fa.download', color='white'), "边界定位图") self.left_button_5.clicked.connect( self.on_generate_border_map_bt_clicked) self.left_button_5.setObjectName('left_button') self.left_button_5.clicked.connect(self.show_click_meg) self.left_button_6 = QPushButton( qtawesome.icon('fa.heart', color='white'), "加载皮质图片") self.left_button_6.clicked.connect(self.on_load_cortex_bt_clicked) self.left_button_6.setObjectName('left_button') self.left_button_6.clicked.connect(self.show_click_meg) self.left_button_7 = QPushButton( qtawesome.icon('fa.comment', color='white'), "属性定位图") self.left_button_7.clicked.connect( self.on_generate_property_map_bt_clicked) self.left_button_7.setObjectName('left_button') self.left_button_7.clicked.connect(self.show_click_meg) self.left_button_8 = QPushButton( qtawesome.icon('fa.star', color='white'), "功能区地形图") self.left_button_8.clicked.connect( self.on_generate_function_map_bt_clicked) self.left_button_8.setObjectName('left_button') self.left_button_8.clicked.connect(self.show_click_meg) self.statusBar = QStatusBar() self.setupUI() self.raw_data = 0 self.data_path = '' self.pic_path = '' self.border_pic_path = None self.feature_sample = None def setupUI(self): self.resize(1000, 800) self.setWindowTitle('基于静息态ECoG聚类和分类的术中脑功能定位系统') self.title_lb.setText('基于静息态ECoG聚类和分类的术中脑功能定位系统') # self.title_lb.setStyleSheet("QLabel{background-color:black; font-size:20px}") self.setStatusBar(self.statusBar) self.statusBar.setStyleSheet("QStatusBar{font-size:15px}") # 调大状态栏的字体 # self.statusBar.setStyleSheet("QStatusBar{background-color:gray; font-size:20px}") # 改状态栏的颜色与背景颜色一致 # self.statusBar.setVisible(True) # 最下面额外增加一栏状态栏 self.statusBar.showMessage('就绪!') self.title_lb.clicked.connect(self.on_title_bt_clicked) self.title_lb.clicked.connect(self.show_click_meg) self.title_lb.setFixedSize(750, 70) self.title_lb.setStyleSheet( 'QPushButton{color:rgb(0, 0, 0, 255);border:none;font-size:30px;font-family: \ "Helvetica Neue", Helvetica, Arial, sans-serif;}\ QPushButton:hover{border-left:4px solid red;font-weight:700;}') self.exit_bt.setText('退出') self.exit_bt.setFixedSize(100, 50) self.exit_bt.setStyleSheet( 'QPushButton{color:rgb(0, 0, 0, 255);border:none;font-size:25px;font-family: \ "Helvetica Neue", Helvetica, Arial, sans-serif;}\ QPushButton:hover{border-left:4px solid red;font-weight:700;}') self.exit_bt.clicked.connect(self.exit_bt_clicked) self.logo_bt.setText('copyright@SCUT-BME-504') self.logo_bt.setFixedSize(300, 30) self.logo_bt.clicked.connect(self.show_click_meg) self.logo_bt.setStyleSheet( 'QPushButton{color:rgb(0, 0, 0, 255);border:none;font-size:15px;font-family: \ "Helvetica Neue", Helvetica, Arial, sans-serif;}\ QPushButton:hover{border-left:4px solid red;font-weight:700;}') # self.bottom_layout.addWidget(self.status_bar, alignment=Qt.AlignLeft) self.bottom_layout.addStretch(2) self.bottom_layout.addWidget(self.logo_bt, alignment=Qt.AlignLeft) self.bottom_layout.addStretch(1) self.bottom_layout.addWidget(self.exit_bt, alignment=Qt.AlignRight) self.bottom_widget.setLayout(self.bottom_layout) self.stack_datapreprocessUI.setStyleSheet( 'QLabel{color:black;font-size:20px;font-family:Arial; \ header:None}') self.main_widget.setLayout(self.main_layout) self.left_widget.setObjectName('left_widget') self.left_widget.setLayout(self.left_layout) self.right_widget.setObjectName('right_widget') self.left_layout.addWidget(self.left_mini, 0, 0, 1, 1) self.left_layout.addWidget(self.left_close, 0, 2, 1, 1) self.left_layout.addWidget(self.left_visit, 0, 1, 1, 1) self.left_layout.addWidget(self.left_label_1, 1, 0, 1, 3) self.left_layout.addWidget(self.left_button_1, 2, 0, 1, 3) self.left_layout.addWidget(self.left_button_2, 3, 0, 1, 3) self.left_layout.addWidget(self.left_button_3, 4, 0, 1, 3) self.left_layout.addWidget(self.left_button_4, 5, 0, 1, 3) self.left_layout.addWidget(self.left_button_5, 6, 0, 1, 3) self.left_layout.addWidget(self.left_label_2, 7, 0, 1, 3) self.left_layout.addWidget(self.left_button_6, 8, 0, 1, 3) self.left_layout.addWidget(self.left_button_7, 9, 0, 1, 3) self.left_layout.addWidget(self.left_label_3, 10, 0, 1, 3) self.left_layout.addWidget(self.left_button_8, 11, 0, 1, 3) # self.left_layout.setSpacing(0) # self.stack = QStackedWidget() self.right_widget.addWidget(self.stack_system_intro) self.right_widget.addWidget(self.stack_border_map_intro) self.right_widget.addWidget(self.stack_datapreprocessUI) self.right_widget.addWidget(self.stack_clusterUI) self.right_widget.addWidget(self.stack_load_electrode_picUI) self.right_widget.addWidget(self.stack_generate_border_mapUI) self.right_widget.addWidget(self.stack_property_map_intro) self.right_widget.addWidget(self.stack_load_cortex_pic) self.right_widget.addWidget(self.stack_generate_property_map) self.right_widget.addWidget(self.stack_function_map_intro) self.right_widget.addWidget(self.stack_generate_function_map) self.mid_layout.addWidget(self.left_widget, stretch=1) self.mid_layout.addWidget(self.right_widget, stretch=3) self.mid_widget.setFixedSize(1000, 650) self.mid_layout.setSpacing(0) self.mid_widget.setLayout(self.mid_layout) self.main_widget.setObjectName('main_widget') self.main_layout.addWidget(self.title_lb, alignment=Qt.AlignCenter, stretch=1) self.main_layout.addWidget(self.mid_widget, stretch=7) self.main_layout.addWidget(self.bottom_widget, stretch=1) self.main_layout.setSpacing(0) # 设置窗口的样式 main_widget_stylesheet = ''' QWidget#main_widget{ background:gray; } QPushButton#left_button{border:none;color:white;} QPushButton#left_label{ border:none; border-bottom:1px solid white; font-size:18px; font-weight:700; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } QWidget#left_widget{ background:grey; border-top:1px solid white; border-bottom:1px solid white; border-left:1px solid white; border-top-left-radius:10px; border-bottom-left-radius:10px; } QWidget#right_widget{ color:#232C51; background:white; border-top:1px solid darkGray; border-bottom:1px solid darkGray; border-right:1px solid darkGray; border-top-right-radius:10px; border-bottom-right-radius:10px; } QPushButton#left_button:hover{border-left:4px solid red;font-weight:700;} QPushButton#left_label:hover{border-left:4px solid red;font-weight:700;} ''' self.main_widget.setStyleSheet(main_widget_stylesheet) self.setCentralWidget(self.main_widget) # 一定要有要句代码,要不然主窗口不显示 self.setWindowOpacity(1) # 设置窗口透明度 # self.setAttribute(Qt.WA_TranslucentBackground) # 设置窗口背景透明 加上的话状态栏不显示。 self.right_widget.setCurrentWidget(self.stack_system_intro) # self.setWindowFlag(Qt.FramelessWindowHint) # 隐藏边框 def on_title_bt_clicked(self): self.right_widget.setCurrentWidget(self.stack_system_intro) def on_border_map_bt_clicked(self): self.right_widget.setCurrentWidget(self.stack_border_map_intro) def on_load_data_bt_clicked(self): self.stack_datapreprocessUI.status_signal.connect( self.show_process_msg) self.right_widget.setCurrentWidget(self.stack_datapreprocessUI) def on_preprocessing_bt_clicked(self): self.feature_sample = self.stack_datapreprocessUI.feature_extract() self.stack_datapreprocessUI.status_signal.connect( self.show_process_msg) if self.feature_sample: self.right_widget.setCurrentWidget(self.stack_datapreprocessUI) else: if not self.raw_data: QMessageBox.information(self, '消息', '请先加载数据', QMessageBox.Ok) else: self.feature_sample = self.stack_datapreprocessUI.feature_extract( ) def on_load_model_bt_clicked(self): self.stack_clusterUI.get_feature_sample(self.feature_sample) self.stack_clusterUI.status_signal.connect(self.show_process_msg) self.right_widget.setCurrentWidget(self.stack_clusterUI) def on_load_pic_bt_clicked(self): self.pic_path = self.stack_datapreprocessUI.trans_pic_path() self.stack_load_electrode_picUI.get_pic_path(self.pic_path) self.right_widget.setCurrentWidget(self.stack_load_electrode_picUI) def on_generate_border_map_bt_clicked(self): self.stack_generate_border_mapUI.get_pic_path(self.pic_path) self.result_list = self.stack_clusterUI.trans_result_list() self.stack_generate_border_mapUI.get_result_list(self.result_list) self.stack_generate_border_mapUI.status_signal.connect( self.show_process_msg) self.right_widget.setCurrentWidget(self.stack_generate_border_mapUI) def on_property_map_bt_clicked(self): self.right_widget.setCurrentWidget(self.stack_property_map_intro) def on_load_cortex_bt_clicked(self): self.right_widget.setCurrentWidget(self.stack_load_cortex_pic) def on_generate_property_map_bt_clicked(self): self.right_widget.setCurrentWidget(self.stack_generate_property_map) def on_function_map_bt_clicked(self): self.right_widget.setCurrentWidget(self.stack_function_map_intro) def on_generate_function_map_bt_clicked(self): self.right_widget.setCurrentWidget(self.stack_generate_function_map) def exit_bt_clicked(self): # sender是发送信号的对象,这里获得的是按钮的名称 sender = self.sender() # 以文本的形式输出按钮的名称 print(sender.text() + ' 被按下了') # 获取QApplication类的对象 q_app = QApplication.instance() # 退出 q_app.quit() def show_click_meg(self): sender = self.sender() self.statusBar.showMessage(sender.text(), 3000) def show_process_msg(self, msg): self.statusBar.showMessage(msg)
class PcerWindow(QWidget): experiment = None vbox = None statusBar = None start = None def __init__(self, experiment): super(PcerWindow, self).__init__() if self.start is None: self.start = time.time() self.experiment = experiment self.vbox = QVBoxLayout() self.statusBar = QStatusBar() self.setParticipantIdGroupInStatusBar(experiment.participant_id, experiment.participant_group) self.initBaseUI() self.initUI() # invokes method in subclass self.setStatusBar() self.setLayout(self.vbox) def initBaseUI(self): self.setWindowFlags(QtCore.Qt.FramelessWindowHint) with open("config.yml", "r") as stream: try: self.config = yaml.safe_load(stream) except yaml.YAMLError as exc: print(exc) self.width = self.config['window_size']['width'] self.height = self.config['window_size']['height'] self.setFixedSize(self.width, self.height) self.centerOnScreen() def setStatusBar(self): self.statusBar.setSizeGripEnabled(False) self.vbox.addWidget(self.statusBar) self.statusBar.setStyleSheet("background: rgba(250, 250, 250)") def setParticipantIdGroupInStatusBar(self, id, group): self.statusBar.showMessage("[ID: " + str(id) + " - Group: " + str(group) + "]") def addTimer(self, timer): self.statusBar.insertPermanentWidget(0, timer) timer.show() def centerOnScreen(self): resolution = QDesktopWidget().screenGeometry() self.move((resolution.width() / 2) - (self.frameSize().width() / 2), (resolution.height() / 2) - (self.frameSize().height() / 2)) print("Monitor resolution: %d (w) x %d (h)" % (resolution.width(), resolution.height())) def popUpWarning(self, msg): warning = QMessageBox() warning.setIcon(QMessageBox.Warning) warning.setText(msg) warning.setWindowTitle('Warning') warning.setStandardButtons(QMessageBox.Ok) warning.exec_()
class Thermochem(ToolInstance): """tool for calculating free energy corrections based on frequencies and energies associated with FileReaders there are two tabs: absolute and relative the absolute tab can be used to combine the thermo corrections from one FileReader with the energy of another the relative tab can do the same, but it prints the energies relative to those of another FileReader multiple molecule groups can be added (i.e. for reactions with multiple reactants and products) each molecule group can have multiple conformers the energies of these conformers are boltzmann weighted, and the boltzmann-weighted energy is used to calculate the energy of either the reference group or the 'other' group""" SESSION_ENDURING = False SESSION_SAVE = False help = "https://github.com/QChASM/SEQCROW/wiki/Process-Thermochemistry-Tool" theory_helper = { "Grimme's Quasi-RRHO": "https://doi.org/10.1002/chem.201200497", "Truhlar's Quasi-Harmonic": "https://doi.org/10.1021/jp205508z" } def __init__(self, session, name): super().__init__(session, name) self.display_name = "Thermochemistry" self.tool_window = MainToolWindow(self) self.settings = _ComputeThermoSettings(self.session, name) self.nrg_fr = {} self.thermo_fr = {} self.thermo_co = {} self._build_ui() self.set_sp() self.set_thermo_mdl() self.calc_relative_thermo() 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 calc_relative_thermo(self, *args): """changes the values on the 'relative' tab called when the tool is opened and whenever something changes on the relative tab""" def calc_free_energies(nrg_list, co_list, T, w0): """returns lists for ZPVE, H, RRHO G, QRRHO G, and QHARM G for the items in nrg_list and co_list at temperature T and frequency parameter w0""" ZPVEs = [] Hs = [] Gs = [] RRHOG = [] QHARMG = [] for i in range(0, len(nrg_list)): ZPVEs.append([]) Hs.append([]) Gs.append([]) RRHOG.append([]) QHARMG.append([]) for nrg, co in zip(nrg_list[i], co_list[i]): ZPVE = co.ZPVE ZPVEs[-1].append(nrg + ZPVE) dH = co.therm_corr(T, w0, CompOutput.RRHO)[1] Hs[-1].append(nrg + dH) dG = co.calc_G_corr(temperature=T, v0=w0, method=CompOutput.RRHO) Gs[-1].append(nrg + dG) dQRRHOG = co.calc_G_corr(temperature=T, v0=w0, method=CompOutput.QUASI_RRHO) RRHOG[-1].append(nrg + dQRRHOG) dQHARMG = co.calc_G_corr(temperature=T, v0=w0, method=CompOutput.QUASI_HARMONIC) QHARMG[-1].append(nrg + dQHARMG) return ZPVEs, Hs, Gs, RRHOG, QHARMG def boltzmann_weight(energies1, energies2, T): """ energies - list of lists list axis 0 - molecule groups axis 1 - energies of conformers boltzmann weight energies for conformers combine energies for molecule groups return the difference""" totals1 = [] totals2 = [] beta = UNIT.HART_TO_JOULE / (PHYSICAL.KB * T) for energy_group in energies1: if len(energy_group) == 0: continue rezero = min(energy_group) rel_nrgs = [(x - rezero) for x in energy_group] weights = [np.exp(-beta * nrg) for nrg in rel_nrgs] totals1.append(-PHYSICAL.BOLTZMANN * T * np.log(sum(weights)) + rezero * UNIT.HART_TO_KCAL) for energy_group in energies2: if len(energy_group) == 0: continue rezero = min(energy_group) rel_nrgs = [(x - rezero) for x in energy_group] weights = [np.exp(-beta * nrg) for nrg in rel_nrgs] totals2.append(-PHYSICAL.BOLTZMANN * T * np.log(sum(weights)) + rezero * UNIT.HART_TO_KCAL) return sum(totals2) - sum(totals1) ref_Es = self.ref_group.energies() ref_cos = self.ref_group.compOutputs() empty_groups = [] for i, group in enumerate(ref_cos): if len(group) == 0: empty_groups.append(i) for ndx in empty_groups[::-1]: ref_Es.pop(ndx) ref_cos.pop(ndx) other_Es = self.other_group.energies() other_cos = self.other_group.compOutputs() empty_groups = [] for i, group in enumerate(other_cos): if len(group) == 0: empty_groups.append(i) for ndx in empty_groups[::-1]: other_Es.pop(ndx) other_cos.pop(ndx) if any( len(x) == 0 or all(len(x) == 0 for y in x) for x in [ref_Es, other_Es, ref_cos, other_cos]): self.relative_dE.setText("") self.relative_dZPVE.setText("") self.relative_dH.setText("") self.relative_dG.setText("") self.relative_dQRRHOG.setText("") self.relative_dQHARMG.setText("") return T = self.relative_temperature.value() self.settings.rel_temp = T w0 = self.relative_v0.value() if w0 != self.settings.w0: self.settings.w0 = w0 ref_ZPVEs, ref_Hs, ref_Gs, ref_QRRHOGs, ref_QHARMGs = calc_free_energies( ref_Es, ref_cos, T, w0) other_ZPVEs, other_Hs, other_Gs, other_QRRHOGs, other_QHARMGs = calc_free_energies( other_Es, other_cos, T, w0) rel_E = boltzmann_weight(ref_Es, other_Es, T) rel_ZPVE = boltzmann_weight(ref_ZPVEs, other_ZPVEs, T) rel_H = boltzmann_weight(ref_Hs, other_Hs, T) rel_G = boltzmann_weight(ref_Gs, other_Gs, T) rel_QRRHOG = boltzmann_weight(ref_QRRHOGs, other_QRRHOGs, T) rel_QHARMG = boltzmann_weight(ref_QHARMGs, other_QHARMGs, T) self.relative_dE.setText("%.1f" % rel_E) self.relative_dZPVE.setText("%.1f" % rel_ZPVE) self.relative_dH.setText("%.1f" % rel_H) self.relative_dG.setText("%.1f" % rel_G) self.relative_dQRRHOG.setText("%.1f" % rel_QRRHOG) self.relative_dQHARMG.setText("%.1f" % rel_QHARMG) def open_link(self, theory): """open the oft-cited QRRHO or QHARM reference""" link = self.theory_helper[theory] run(self.session, "open %s" % link) def save_csv(self): """save data on current tab to CSV file""" filename, _ = QFileDialog.getSaveFileName(filter="CSV Files (*.csv)") if filename: s = self.get_csv() with open(filename, 'w') as f: f.write(s.strip()) self.session.logger.status("saved to %s" % filename) def copy_csv(self): """put CSV data for current tab on the clipboard""" app = QApplication.instance() clipboard = app.clipboard() csv = self.get_csv() clipboard.setText(csv) self.session.logger.status("copied to clipboard") def get_csv(self): """get CSV data for the current tab""" if self.settings.delimiter == "comma": delim = "," elif self.settings.delimiter == "space": delim = " " elif self.settings.delimiter == "tab": delim = "\t" elif self.settings.delimiter == "semicolon": delim = ";" if self.tab_widget.currentIndex() == 0: if self.settings.include_header: s = delim.join(["E" , "ZPE", "H(RRHO)", "G(RRHO)", "G(Quasi-RRHO)", "G(Quasi-harmonic)", \ "dZPE", "dH(RRHO)", "dG(RRHO)", "dG(Quasi-RRHO)", "dG(Quasi-harmonic)", \ "SP File", "Thermo File"]) s += "\n" else: s = "" float_fmt = "%.12f" + delim str_dmt = "%s" + delim + "%s" fmt = 11 * float_fmt + str_dmt + "\n" E = float(self.sp_nrg_line.text()) dZPE = float(self.zpe_line.text()) dH = float(self.enthalpy_line.text()) rrho_dG = float(self.rrho_g_line.text()) qrrho_dG = float(self.qrrho_g_line.text()) qharm_dG = float(self.qharm_g_line.text()) ZPE = float(self.zpe_sum_line.text()) H = float(self.h_sum_line.text()) rrho_G = float(self.rrho_g_sum_line.text()) qrrho_G = float(self.qrrho_g_sum_line.text()) qharm_G = float(self.qharm_g_sum_line.text()) sp_mdl = self.sp_selector.currentData() sp_name = sp_mdl.name therm_mdl = self.thermo_selector.currentData() therm_name = therm_mdl.name s += fmt % (E, ZPE, H, rrho_G, qrrho_G, qharm_G, dZPE, dH, rrho_dG, qrrho_dG, qharm_dG, sp_name, therm_name) elif self.tab_widget.currentIndex() == 1: if self.settings.include_header: s = delim.join([ "ΔE", "ΔZPE", "ΔH(RRHO)", "ΔG(RRHO)", "ΔG(Quasi-RRHO)", "ΔG(Quasi-Harmonic)" ]) s += "\n" else: s = "" float_fmt = "%.1f" + delim fmt = 6 * float_fmt try: dE = float(self.relative_dE.text()) dZPVE = float(self.relative_dZPVE.text()) dH = float(self.relative_dH.text()) dG = float(self.relative_dG.text()) dQRRHOG = float(self.relative_dQRRHOG.text()) dQHARMG = float(self.relative_dQHARMG.text()) s += fmt % (dE, dZPVE, dH, dG, dQRRHOG, dQHARMG) except ValueError: pass return s def header_check(self, state): """user has [un]checked the 'include header' option on the menu""" if state: self.settings.include_header = True else: self.settings.include_header = False def set_sp(self): """set energy entry for when sp model changes""" if self.sp_selector.currentIndex() >= 0: fr = self.sp_selector.currentData() self.check_geometry_rmsd("SP") self.sp_nrg_line.setText("%.6f" % fr.other['energy']) else: self.sp_nrg_line.setText("") self.update_sum() def set_thermo_mdl(self): """frequencies filereader has changed on the absolute tab also changes the temperature option (on the absolute tab only)""" if self.thermo_selector.currentIndex() >= 0: fr = self.thermo_selector.currentData() self.check_geometry_rmsd("THERM") if 'temperature' in fr.other: self.temperature_line.setValue(fr.other['temperature']) self.set_thermo() def check_geometry_rmsd(self, *args): """check RMSD between energy and frequency filereader on the absolute tab if the RMSD is > 10^-5 or the number of atoms is different, put a warning in the status bar""" if self.thermo_selector.currentIndex( ) >= 0 and self.sp_selector.currentIndex() >= 0: fr = self.sp_selector.currentData() fr2 = self.thermo_selector.currentData() if len(fr.atoms) != len(fr2.atoms): self.status.showMessage( "structures are not the same: different number of atoms") return geom = Geometry(fr) geom2 = Geometry(fr2) rmsd = geom.RMSD(geom2) if not isclose(rmsd, 0, atol=10**-5): rmsd = geom.RMSD(geom2, sort=True) if not isclose(rmsd, 0, atol=10**-5): self.status.showMessage( "structures might not be the same - RMSD = %.4f" % rmsd) else: self.status.showMessage("") def set_thermo(self): """computes thermo corrections and sets thermo entries for when thermo model changes""" #index of combobox is -1 when combobox has no entries if self.thermo_selector.currentIndex() >= 0: fr = self.thermo_selector.currentData() if fr not in self.thermo_co: self.thermo_co[fr] = CompOutput(fr) co = self.thermo_co[fr] v0 = self.v0_edit.value() if v0 != self.settings.w0: self.settings.w0 = v0 T = self.temperature_line.value() if not T: return dZPE = co.ZPVE #compute enthalpy and entropy at this temperature #AaronTools uses Grimme's Quasi-RRHO, but this is the same as RRHO when w0=0 dE, dH, s = co.therm_corr(temperature=T, v0=0, method="RRHO") rrho_dg = dH - T * s #compute G with quasi entropy treatments qrrho_dg = co.calc_G_corr(v0=v0, temperature=T, method="QRRHO") qharm_dg = co.calc_G_corr(v0=v0, temperature=T, method="QHARM") self.zpe_line.setText("%.6f" % dZPE) self.enthalpy_line.setText("%.6f" % dH) self.rrho_g_line.setText("%.6f" % rrho_dg) self.qrrho_g_line.setText("%.6f" % qrrho_dg) self.qharm_g_line.setText("%.6f" % qharm_dg) else: self.zpe_line.setText("") self.enthalpy_line.setText("") self.rrho_g_line.setText("") self.qrrho_g_line.setText("") self.qharm_g_line.setText("") self.update_sum() def update_sum(self): """updates the sum of energy and thermo corrections""" dZPE = self.zpe_line.text() dH = self.enthalpy_line.text() dG = self.rrho_g_line.text() dG_qrrho = self.qrrho_g_line.text() dG_qharm = self.qharm_g_line.text() nrg = self.sp_nrg_line.text() if len(dH) == 0 or len(nrg) == 0: self.zpe_sum_line.setText("") self.h_sum_line.setText("") self.rrho_g_sum_line.setText("") self.qrrho_g_sum_line.setText("") self.qharm_g_sum_line.setText("") return else: dZPE = float(dZPE) dH = float(dH) dG = float(dG) dG_qrrho = float(dG_qrrho) dG_qharm = float(dG_qharm) nrg = float(nrg) zpe = nrg + dZPE enthalpy = nrg + dH rrho_g = nrg + dG qrrho_g = nrg + dG_qrrho qharm_g = nrg + dG_qharm self.zpe_sum_line.setText("%.6f" % zpe) self.h_sum_line.setText("%.6f" % enthalpy) self.rrho_g_sum_line.setText("%.6f" % rrho_g) self.qrrho_g_sum_line.setText("%.6f" % qrrho_g) self.qharm_g_sum_line.setText("%.6f" % qharm_g) def display_help(self): """Show the help for this tool in the help viewer.""" from chimerax.core.commands import run run(self.session, 'open %s' % self.help if self.help is not None else "") def delete(self): #overload because closing a tool window doesn't destroy any widgets on it self.settings.ref_col_1 = self.ref_group.tree.columnWidth(0) self.settings.ref_col_2 = self.ref_group.tree.columnWidth(1) self.settings.other_col_1 = self.other_group.tree.columnWidth(0) self.settings.other_col_2 = self.other_group.tree.columnWidth(1) self.sp_selector.deleteLater() self.thermo_selector.deleteLater() self.ref_group.deleteLater() self.other_group.deleteLater() return super().delete() def close(self): #overload because closing a tool window doesn't destroy any widgets on it self.settings.ref_col_1 = self.ref_group.tree.columnWidth(0) self.settings.ref_col_2 = self.ref_group.tree.columnWidth(1) self.settings.other_col_1 = self.other_group.tree.columnWidth(0) self.settings.other_col_2 = self.other_group.tree.columnWidth(1) self.sp_selector.deleteLater() self.thermo_selector.deleteLater() self.ref_group.deleteLater() self.other_group.deleteLater() return super().close()