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)
Beispiel #2
0
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("空闲")
Beispiel #3
0
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
Beispiel #4
0
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)
Beispiel #6
0
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")
Beispiel #7
0
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")
Beispiel #8
0
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)
Beispiel #9
0
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
Beispiel #10
0
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))
Beispiel #11
0
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)
Beispiel #12
0
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
Beispiel #13
0
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()
Beispiel #14
0
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())
Beispiel #15
0
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)
Beispiel #16
0
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()
Beispiel #17
0
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))
Beispiel #18
0
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")
Beispiel #19
0
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)
Beispiel #21
0
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
Beispiel #22
0
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()
Beispiel #23
0
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()
Beispiel #24
0
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)
Beispiel #26
0
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()
Beispiel #27
0
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()
Beispiel #28
0
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))
Beispiel #29
0
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)
Beispiel #30
0
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_()
Beispiel #31
0
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()