Exemple #1
0
class AutomatonStateManager(QWidget):
    signalStateIdsRequest = Signal()
    signalSetStartingStateRequest = Signal(str)
    signalSetCurrentStateRequest = Signal(str)

    def __init__(self, parent):
        super(AutomatonStateManager, self).__init__(parent)

        self.startingStateButton = QPushButton('Set starting state: ', self)
        self.startingStateButton.clicked.connect(self.setStartingState)
        self.startingSelect = QComboBox(self)

        self.currentStateButton = QPushButton('Set current state: ', self)
        self.currentStateButton.clicked.connect(self.setCurrentState)
        self.currentSelect = QComboBox(self)
        self.signalStateIdsRequest.emit()

        layout = QHBoxLayout()
        layout.addWidget(self.startingStateButton)
        layout.addWidget(self.startingSelect)
        layout.addWidget(self.currentStateButton)
        layout.addWidget(self.currentSelect)
        layout.setSizeConstraint(QLayout.SetMaximumSize)
        self.setLayout(layout)

    @Slot(list)
    def populateStateSelect(self, stateIds):
        self.startingSelect.clear()
        self.currentSelect.clear()
        for stateId in stateIds:
            self.startingSelect.addItem('q{}'.format(stateIds.index(stateId)),
                                        stateId)
            self.currentSelect.addItem('q{}'.format(stateIds.index(stateId)),
                                       stateId)
        self.startingSelect.setCurrentIndex(0)
        self.currentSelect.setCurrentIndex(0)

    @Slot()
    def setStartingState(self):
        stateId = self.startingSelect.currentData()
        self.signalSetStartingStateRequest.emit(stateId)

    @Slot()
    def setCurrentState(self):
        stateId = self.currentSelect.currentData()
        self.signalSetCurrentStateRequest.emit(stateId)

    @Slot()
    def disableEdit(self):
        self.startingSelect.setDisabled(True)
        self.startingStateButton.setDisabled(True)
        self.currentSelect.setDisabled(True)
        self.currentStateButton.setDisabled(True)

    @Slot()
    def enableEdit(self):
        self.startingSelect.setDisabled(False)
        self.startingStateButton.setDisabled(False)
        self.currentSelect.setDisabled(False)
        self.currentStateButton.setDisabled(False)
Exemple #2
0
class WdParameterValueEdit(WdParameterEditBase):
    def __init__(self, parent=None):
        super().__init__('val', parent)
        self.edit_widget = QLineEdit()
        self.combo_widget = QComboBox()
        self.add_subwidget(self.edit_widget)
        self.add_subwidget(self.combo_widget)
        self.combo_widget.setVisible(False)
        self.edit_widget.editingFinished.connect(self.on_text_edited)
        self.combo_widget.activated.connect(self.on_combo_selected)

    def set_parameter(self, parameter: Parameter):
        use_combo = parameter.help_val is not None
        self.combo_widget.setVisible(use_combo)
        self.edit_widget.setVisible(not use_combo)
        if use_combo:
            vals, labels = parameter.values_choice()
            self.combo_widget.clear()
            self.combo_widget.addItems(labels)
        else:
            self.combo_widget.clear()
        super().set_parameter(parameter)

    @Slot()
    def on_text_edited(self):
        if self.wdparameter is not None:
            try:
                val = self.wdparameter.scan_str(self.edit_widget.text())
            except:
                self.update_from_model()
                return
            self.set_model_value(val)

    @Slot(int)
    def on_combo_selected(self, index: int):
        if self.wdparameter is not None:
            vals, labels = self.wdparameter.values_choice()
            val = list(vals)[index]
            self.set_model_value(val)

    def set_view_value(self, value):
        if value is None:
            value = ''
        if not isinstance(value, str):
            vals, labels = self.wdparameter.values_choice()
            if labels:
                try:
                    index = vals.index(value)
                except ValueError:
                    index = -1
                self.combo_widget.setCurrentIndex(index)
            else:
                if isinstance(self.wdparameter, IntParameter):
                    value = f'{value:.0f}'
                else:
                    value = f'{value:g}'
                self.edit_widget.setText(value)
        else:
            self.edit_widget.setText(value)
            self.combo_widget.setEditText(value)
Exemple #3
0
class IccTableEditorYearSpecificView(IccTableEditorView):
    """
    Eine von IccTableEditorView abgeleitete Klasse, die in der Toolbar neben dem Speichern-Button eine Jahr-Combobox
    hat. Sie wird mit den Methoden addJahr, addJahre, setCurrentJahr und clearJahre bedient.
    Wird das Jahr geändert, wird ein yearChanged-Signal gesendet.
    """
    yearChanged = Signal(int)

    def __init__(self, model: XBaseTableModel = None):
        IccTableEditorView.__init__(self, model)
        self._cboYear = QComboBox()
        self._cboYear.setFont(QFont("Arial", 14, weight=QFont.Bold))
        self._cboYear.currentTextChanged.connect(self.onCurrentYearChanged)
        self.addTool(self._cboYear)

    def addJahr(self, jahr: int):
        self._cboYear.addItem(str(jahr))

    def addJahre(self, jahre: List[int]):
        self._cboYear.addItems([str(j) for j in jahre])

    def setCurrentJahr(self, jahr: int):
        self._cboYear.setCurrentText(str(jahr))

    def clearJahre(self):
        self._cboYear.clear()

    def onCurrentYearChanged(self, sJahrNeu: str):
        self.yearChanged.emit(int(sJahrNeu))
Exemple #4
0
    def add_supplier_list_to_combo(self, combo: QComboBox):
        # clear QComboBox
        combo.clear()
        combo.clearEditText()

        if self.parent.sheets is None:
            combo.setEnabled(False)
            return

        if self.db is None:
            self.flag_db = False
            combo.setEnabled(False)
            return

        # DB Query and update QConboBox
        sql = "SELECT name_supplier_short FROM supplier;"
        out = self.db.get(sql)
        for supplier in out:
            combo.addItem(supplier[0])

        name = self.get_supplier_name()
        index = combo.findText(name)
        if index >= 0:
            combo.setCurrentIndex(index)
            combo.setEnabled(False)
        else:
            combo.setEnabled(True)
Exemple #5
0
class Voyage(QWidget):

    def __init__(self, parent=None):
        super(Voyage, self).__init__(parent)
        self.data = np.loadtxt(open("DS_P6_Voyage_Data.txt", "r"), delimiter=";", skiprows=1, dtype='str')

        self.cbCompagnie = QComboBox()
        self.cbCompagnie.currentIndexChanged.connect(self.updateDestinations)
        self.cbDestination = QComboBox()
        self.cbDestination.currentIndexChanged.connect(self.updateCourbe)
        self.imgCourbe = QLabel()
        self.imgCourbe.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        genLayout = QHBoxLayout()
        layoutCombo = QVBoxLayout()

        layoutCombo.addWidget(self.cbCompagnie)
        layoutCombo.addWidget(self.cbDestination)

        genLayout.addLayout(layoutCombo)
        genLayout.addWidget(self.imgCourbe)
        self.setLayout(genLayout)

        self.updateCompagnie()


    def updateCompagnie(self):
        companies = np.unique(self.data[:,0])
        self.cbCompagnie.addItems(companies)

    def updateDestinations(self):
        print("updateDestinations")
        self.cbDestination.clear()                      # vide la comboBox pour y afficher du nouveau contenu après
        companie = self.cbCompagnie.currentText()

        filtre1 = self.data[self.data[:,0]==companie]   # conserve tous les éléments sur lignes contenant la compagnie selectionnée
        destinations = filtre1[:, 4]
        self.cbDestination.addItems(np.unique(destinations))
        self.updateCourbe()

    def updateCourbe(self):
        companie = self.cbCompagnie.currentText()
        filtre1 = self.data[self.data[:, 0] == companie]

        destination = self.cbDestination.currentText()
        filtre2 = filtre1[filtre1[:,4]==destination]

        tarifs = filtre2[:,1]

        plt.plot(tarifs)

        plt.savefig('tutu.png', format='png')           # creation d'un fichier temporaire
        self.imgCourbe.setPixmap('tutu.png')
        plt.clf()
class Voyage(QWidget):

    def __init__(self, parent=None):
        super(Voyage, self).__init__(parent)
        self.data = np.loadtxt(open("voyage.csv", "r"), delimiter=";", skiprows=1, dtype='str')

        self.cbCompagnie = QComboBox()
        self.cbCompagnie.currentIndexChanged.connect(self.updateDestinations)
        self.cbDestination = QComboBox()
        self.cbDestination.currentIndexChanged.connect(self.updateCourbe)
        self.imgCourbe = QLabel()
        self.imgCourbe.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        genLayout = QHBoxLayout()
        layoutCombo = QVBoxLayout()

        layoutCombo.addWidget(self.cbCompagnie)
        layoutCombo.addWidget(self.cbDestination)

        genLayout.addLayout(layoutCombo)
        genLayout.addWidget(self.imgCourbe)
        self.setLayout(genLayout)

        self.updateCompagnie()


    def updateCompagnie(self):
        companies = np.unique(self.data[:,0])
        self.cbCompagnie.addItems(companies)

    def updateDestinations(self):
        print("updateDestinations")
        self.cbDestination.clear()
        companie = self.cbCompagnie.currentText()

        filtre1 = self.data[self.data[:,0]==companie]
        destinations = filtre1[:, 4]
        self.cbDestination.addItems(np.unique(destinations))
        self.updateCourbe()

    def updateCourbe(self):
        companie = self.cbCompagnie.currentText()
        filtre1 = self.data[self.data[:, 0] == companie]

        destination = self.cbDestination.currentText()
        filtre2 = filtre1[filtre1[:,4]==destination]

        tarifs = filtre2[:,1]

        plt.plot(tarifs)

        plt.savefig('tutu.png', format='png')
        self.imgCourbe.setPixmap('tutu.png')
        plt.clf()
Exemple #7
0
class Code(QWidget):
    TRIAL_STATUS = ('on', 'off')

    def __init__(self, callback):
        super().__init__()

        self.callback = callback

        trial_label = QLabel('Trial:')
        self.trial_box = QSpinBox()
        self.trial_box.setFixedWidth(64)
        self.trial_box.setValue(1)
        #self.trial_box.setFocusPolicy(Qt.NoFocus)

        trial_status_label = QLabel('Trial Status:')
        self.trial_status = QComboBox()
        self.trial_status.addItems(self.TRIAL_STATUS)
        self.trial_status.setFocusPolicy(Qt.NoFocus)

        response_label = QLabel('Response:')
        self.response_box = QComboBox()
        self.response_box.setFocusPolicy(Qt.NoFocus)

        self.record_button = QPushButton('Record Event')
        self.record_button.clicked.connect(self.record_event)
        self.record_button.setEnabled(False)
        self.record_button.setFocusPolicy(Qt.NoFocus)

        layout = QHBoxLayout()
        layout.addWidget(trial_label)
        layout.addWidget(self.trial_box)
        layout.addWidget(trial_status_label)
        layout.addWidget(self.trial_status)
        layout.addWidget(response_label)
        layout.addWidget(self.response_box)
        layout.addStretch()
        layout.addWidget(self.record_button)

        self.setLayout(layout)

    def set_responses(self, responses):
        self.response_box.clear()
        self.response_box.addItems(responses)

    def record_event(self):
        event = Event(trial=self.trial_box.value(),
                      status=self.trial_status.currentText() == 'on',
                      response=self.response_box.currentText())
        if self.trial_status.currentText() == 'off':
            self.trial_box.setValue(self.trial_box.value() + 1)
            self.trial_status.setCurrentText('on')
        self.callback(event)
Exemple #8
0
    def get_filelist(self, combo: QComboBox):
        combo.clear()
        combo.clearEditText()

        # SQLite
        con = sqlite3.connect(self.dbname)
        cur = con.cursor()
        cur.execute("SELECT name_file FROM file;")
        out = cur.fetchall()
        con.close()

        # add list of file to QComboBox
        for name_file in out:
            combo.addItem(name_file[0])
Exemple #9
0
class StateManager(QWidget):
    signalStateIdsRequest = Signal()
    signalStateAdded = Signal()
    signalStateRemoveRequest = Signal(object)

    def __init__(self, parent):
        super(StateManager, self).__init__(parent)
        self.addButton = QPushButton('Add state...', self)
        self.addButton.clicked.connect(self.addState)

        self.removeButton = QPushButton('Remove state: ', self)
        self.removeButton.clicked.connect(self.removeState)
        self.stateSelect = QComboBox(self)

        layout = QHBoxLayout()
        layout.addWidget(self.addButton)
        layout.addWidget(self.removeButton)
        layout.addWidget(self.stateSelect)
        layout.setSizeConstraint(QLayout.SetMaximumSize)
        self.setLayout(layout)

    @Slot(list)
    def populateStateSelect(self, stateIds):
        self.stateSelect.clear()
        for stateId in stateIds:
            self.stateSelect.addItem('q{}'.format(stateIds.index(stateId)),
                                     stateId)
        self.stateSelect.setCurrentIndex(0)

    @Slot()
    def addState(self):
        self.signalStateAdded.emit()

    @Slot()
    def removeState(self):
        stateId = self.stateSelect.currentData()
        self.signalStateRemoveRequest.emit(stateId)

    @Slot()
    def disableEdit(self):
        self.stateSelect.setDisabled(True)
        self.addButton.setDisabled(True)
        self.removeButton.setDisabled(True)

    @Slot()
    def enableEdit(self):
        self.stateSelect.setDisabled(False)
        self.addButton.setDisabled(False)
        self.removeButton.setDisabled(False)
Exemple #10
0
class ComboPlotWidget(PlotWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.combo = QComboBox()
        self.combo.setFixedWidth(150)
        self.lay.insertWidget(0, self.combo, alignment=QtCore.Qt.AlignCenter)
        self.lay.setMargin(0)
        self.lay.setSpacing(0)

    @Slot(list)
    def update_combo_box(self, data):
        self.combo.clear()
        for item in data:
            self.combo.addItem(item)
class ComboBox(QWidget):
    def __init__(self, parent=None, items=[]):
        super(ComboBox, self).__init__(parent)

        layout = QHBoxLayout()
        self.cb = QComboBox()
        self.items = items
        self.cb.addItems(self.items)

        self.cb.currentIndexChanged.connect(parent.comboSelectionChanged)

        layout.addWidget(self.cb)
        self.setLayout(layout)

    def update_items(self, items):
        self.items = items

        self.cb.clear()
        self.cb.addItems(self.items)
class DataTabel(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.combo_file = QComboBox()
        label1 = QLabel("Input:")
        self.data_models = {}
        self.table_view = QTableView()

        layout1 = QHBoxLayout()
        layout1.addWidget(label1)
        layout1.addWidget(self.combo_file)
        layout1.setStretch(1, 1)

        self.layout2 = QVBoxLayout()
        self.layout2.addLayout(layout1)
        self.layout2.addWidget(self.table_view)

        self.setLayout(self.layout2)
        self.combo_file.currentIndexChanged.connect(self.update_model)

    def initialize(self, data_sets):
        self.combo_file.clear()
        for (file_name, data_frame) in data_sets.items():
            self.combo_file.addItem(file_name)
            model = DataModel(data_frame)
            self.data_models[file_name] = model
        if (self.combo_file.count() != 0):
            self.combo_file.setCurrentIndex(self.combo_file.count() - 1)
        self.update_model()

    def update_model(self):
        if (self.combo_file.currentText() in self.data_models):
            self.table_view.setModel(
                self.data_models[self.combo_file.currentText()])
        else:
            self.table_view.setModel(DataModel())

    def current_file(self):
        return self.combo_file.currentText()
Exemple #13
0
class Widget(QWidget):
    """
    主窗口内的控件
    """
    def __init__(self, success_window):
        super().__init__()
        self.success_window = success_window
        self.sheetnames = ""

        # 左上的软件说明
        self.description = QLabel('''软件说明:
处理Excel表格工具合集(校务数据中心自家用)
已实现功能:
    1. 解除合并单元格并填充
    2. 中式表头表格转换(转置)
    3. 中式表头表格转换(只处理上表头)
    4. 去除前后特定字符
    5. 基于SHA256的文件加密
    6. 表头转拼音首字母
    7. 数据脱敏''')
        self.description.setGeometry(QRect(328, 240, 329, 27 * 4))
        self.description.setWordWrap(True)
        self.description.setAlignment(Qt.AlignTop)

        # 右边的程序输出信息框
        self.output_info = QTextEdit()
        self.output_info.setReadOnly(True)

        # 左下的文件读取路径
        self.file_path_text = QLabel("表格所在位置:")
        self.file_path = QLineEdit()
        self.file_path.setReadOnly(True)
        self.file_path_button = QPushButton("打开")
        self.file_path_button.clicked.connect(self.open_file)

        # 左下的工作表名称
        self.sheet_name_text = QLabel("工作表名称:")
        self.sheet_name_box = QComboBox()

        # 左下的工具按钮
        self.unmerge_tool_button = QPushButton("解除合并单元格")
        self.unmerge_tool_button.clicked.connect(self.unmerge)
        self.transform_tool1_button = QPushButton("行列转置")
        self.transform_tool2_button = QPushButton("只处理上表头")
        self.strip_button = QPushButton("去除前后特定字符")
        self.encrypt_button = QPushButton("文件加密解密")
        self.pinyin_button = QPushButton("表头转拼音")
        self.pinyin_button.clicked.connect(self.pinyin)
        self.desensitize_button = QPushButton("数据脱敏")

        # 布局
        self.layout = QHBoxLayout()
        self.file_path_layout = QHBoxLayout()
        self.button_layout1 = QHBoxLayout()
        self.button_layout2 = QHBoxLayout()
        self.left_layout = QVBoxLayout()
        self.sheet_name_layout = QHBoxLayout()

        # 将工具加入到布局
        self.button_layout1.addWidget(self.unmerge_tool_button)
        self.button_layout1.addWidget(self.transform_tool1_button)
        self.button_layout1.addWidget(self.transform_tool2_button)
        self.button_layout2.addWidget(self.strip_button)
        self.button_layout2.addWidget(self.encrypt_button)
        self.button_layout2.addWidget(self.pinyin_button)
        self.button_layout2.addWidget(self.desensitize_button)
        self.file_path_layout.addWidget(self.file_path_text)
        self.file_path_layout.addWidget(self.file_path)
        self.file_path_layout.addWidget(self.file_path_button)
        self.sheet_name_layout.addWidget(self.sheet_name_text)
        self.sheet_name_layout.addWidget(self.sheet_name_box)
        self.left_layout.addWidget(self.description)
        self.left_layout.addLayout(self.file_path_layout)
        self.left_layout.addLayout(self.sheet_name_layout)
        self.left_layout.addLayout(self.button_layout1)
        self.left_layout.addLayout(self.button_layout2)
        self.layout.addLayout(self.left_layout)
        self.layout.addWidget(self.output_info)

        # 应用layout
        self.setLayout(self.layout)

    @Slot()
    def open_file(self):
        excel_file, _ = QFileDialog.getOpenFileName(self, 'Open file', '.',
                                                    'All Files (*)')
        if excel_file != "":
            logging.info("打开" + excel_file)
            self.file_path.setText(excel_file)
            file_type = excel_file.split('.')[-1]
            self.sheet_name_box.clear()
            if file_type == 'xlsx':
                self.sheetnames = show_sheetnames(excel_file)
                self.sheet_name_box.addItems(self.sheetnames)
                output = "打开{}\n工作表名称:\n".format(excel_file)
                for sheetname in self.sheetnames:
                    output += sheetname + "\n"
                self.show_text(output)
            else:
                output = "打开" + excel_file + '\n'
                self.show_text(output)

    @Slot()
    def unmerge(self):
        filename = self.file_path.text()
        sheetname = self.sheet_name_box.currentText()
        if ExistUtil.check_exists(filename, sheetname):
            excel_loader = ExcelLoader(filename, sheetname)
            workbook, worksheet = excel_loader.load_excel()
            logging.info("读取{}成功!".format(filename))
            self.show_text("读取{}成功!".format(filename))
            unmerge_tool = UnmergeTool(workbook, worksheet)
            new_workbook, new_worksheet = unmerge_tool.excute()
            new_workbook.save(
                filename.split('/')[-1].replace(
                    ".xlsx", "_" + sheetname + "_unmerged.xlsx"))
            logging.info("解除合并单元格成功!")
            self.show_text("解除合并单元格成功!")
            self.show_text("--------------------")
            self.success_window.show()

    @Slot()
    def pinyin(self):
        filename = self.file_path.text()
        sheetname = self.sheet_name_box.currentText()
        if ExistUtil.check_exists(filename, sheetname):
            excel_loader = ExcelLoader(filename, sheetname)
            workbook, worksheet = excel_loader.load_excel()
            logging.info("读取{}成功!".format(filename))
            self.show_text("读取{}成功!".format(filename))
            transformTool3 = TransformTool3(workbook, worksheet)
            new_workbook = transformTool3.excute()
            new_workbook.save(
                filename.split('/')[-1].replace(
                    ".xlsx", "_" + sheetname + "(表头转拼音).xlsx"))
            logging.info("表头转拼音成功!")
            self.show_text("表头转拼音成功!")
            self.show_text("--------------------")
            self.success_window.show()

    def show_text(self, info: str):
        temp = self.output_info.toPlainText() + info + '\n'
        self.output_info.setPlainText(temp)
class QFileDescriptorViewer(QFrame):
    """
    embeded in `StateInspector`
    Display content of a file descriptor ( include stdin/stdout/stderr ) for the selected state.
    """
    STD = {
        0: "stdin",
        1: "stdout",
        2: "stderr",
    }

    def __init__(self, state, parent, workspace):
        super().__init__(parent)

        self._state = state  # type: SimState
        self.workspace = workspace

        self.select_fd = None
        self._current_fd = None
        self.textedit = None

        self._state.am_subscribe(self._watch_state)

    def dump_fd(self, fd):
        # Clean up when nothing is selected
        if fd == -1:
            self._current_fd = None
            self.textedit.setPlainText("")
            return

        if self._state.am_none:
            return
        self._current_fd = fd
        self.textedit.setPlainText(
            self._state.posix.dumps(fd).decode("ascii", "ignore").replace(
                "\x00", "\\x00"))

    def save_as(self):
        if self._state.am_none or self._current_fd is None:
            return
        filename, folder = QFileDialog.getSaveFileName(self,
                                                       "Save content to ...",
                                                       "", "Any file (*);")
        if filename and folder:
            save_to = os.path.join(folder, filename)
            open(save_to,
                 "wb").write(self._state.posix.dumps(self._current_fd))

    def _init_widgets(self):
        layout = QVBoxLayout()
        self.select_fd = QComboBox(self)
        self.select_fd.currentIndexChanged.connect(self.dump_fd)
        layout.addWidget(self.select_fd)

        self.textedit = QTextEdit(self)
        self.textedit.setAcceptRichText(False)
        self.textedit.setReadOnly(True)
        layout.addWidget(self.textedit)

        save_as = QPushButton("Save as...", self)
        save_as.clicked.connect(self.save_as)
        layout.addWidget(save_as)

        self.setLayout(layout)

    def _watch_state(self, **kwargs):  # pylint: disable=unused-argument
        if self._state.am_none:
            return
        if self.select_fd is None:
            self._init_widgets()
        self.select_fd.clear()
        for fd, simfile in self._state.posix.fd.items():
            if fd in self.STD:
                self.select_fd.addItem(self.STD[fd])
            elif isinstance(simfile, SimFileDescriptor):
                self.select_fd.addItem(str(simfile.file.name))
            else:
                self.select_fd.addItem(str(simfile))
class GraphFormWidget(QWidget):
    def __init__(self):
        QWidget.__init__(self)        

        self.layout = self.CreateLayout() 
        self.setLayout(self.layout)

    #Layout design
    def CreateLayout(self):
        globalLayout = QVBoxLayout()
        
        label_cat = QLabel("Category : ")
        self.cb_cat = QComboBox()
        self.cb_cat.addItems(["Active", "Control", "Death"])
        self.cb_cat.currentIndexChanged.connect(self.cb_category_index_changed)

        label_patient = QLabel("Patient : ")
        self.cb_patient = QComboBox()
        self.cb_patient.addItems(GraphFormWidget.FindPatients(self.cb_cat.currentText()))
        
        label_electrode = QLabel("Electrode : ")
        self.cb_electrode = QComboBox()
        self.cb_electrode.addItems(getElectrodesList())

        label_wave = QLabel("Wave type : ")
        self.cb_wave = QComboBox()
        self.cb_wave.addItems(["Alpha", "Beta", "Theta", "Delta"])

        firstRowLayout = QHBoxLayout()
        firstRowLayout.setMargin(10)
        firstRowLayout.setSpacing(10)
        firstRowLayout.addWidget(label_cat)
        firstRowLayout.addWidget(self.cb_cat)
        firstRowLayout.addWidget(label_patient)
        firstRowLayout.addWidget(self.cb_patient)
        firstRowLayout.addWidget(label_electrode)
        firstRowLayout.addWidget(self.cb_electrode)
        firstRowLayout.addWidget(label_wave)
        firstRowLayout.addWidget(self.cb_wave)

        DefineLayoutChildAlignment(firstRowLayout, Qt.AlignHCenter)

        globalLayout.addItem(firstRowLayout)

        self.heatMapBtn = QPushButton("Show heatmap") 
        self.heatMapBtn.clicked.connect(self.heatMapBtnClick)

        showBtn = QPushButton("Show graph")
        showBtn.clicked.connect(self.showBtnClick)
        
        secondRowLayout = QHBoxLayout()
        secondRowLayout.setMargin(10)
        secondRowLayout.setSpacing(10)
        secondRowLayout.addWidget(self.heatMapBtn)
        secondRowLayout.addWidget(showBtn)
        
        DefineLayoutChildAlignment(secondRowLayout, Qt.AlignHCenter)

        globalLayout.addItem(secondRowLayout)

        self.graphWidget = GraphWidget()
        globalLayout.addWidget(self.graphWidget)                

        return globalLayout

    #Get list of patients
    def FindPatients(directory):
       return os.listdir('./Datas/' + directory)

    #Update list of patients when combobox changed
    def cb_category_index_changed(self, index):
        self.cb_patient.clear()
        self.cb_patient.addItems(GraphFormWidget.FindPatients(self.cb_cat.currentText()))

    #Load graph
    def showBtnClick(self):
        datas = getRawDatas(self.cb_patient.currentText(), self.cb_cat.currentText(), self.cb_wave.currentText())
        datas = [datas['t'], datas[self.cb_electrode.currentText()]]
        self.graphWidget.Load(datas)   

    #Load heatmap
    def heatMapBtnClick(self):
        self.htmapwidget = HeatMapWidget()
        self.htmapwidget.Load(self.cb_patient.currentText(), self.cb_cat.currentText(), self.cb_wave.currentText())
        self.htmapwidget.show()
Exemple #16
0
class CreationContainer(QWidget):
    """
    Apparently just another level of parent class for social link display.
    Man I was stupid.
    Still am luigi2hands

    :param MainFrame mainframe: application mainframe
    :param QWidget op: parent widget
    :param int load: index to load maybe?
    """
    def __init__(self, mainframe, op, load):
        QWidget.__init__(self)
        self.mainframe = mainframe
        self.op = op
        self.op.cc = self
        self.load = load

        # View initializers...
        self.actions = None
        self.window = None

        self.initUI()
        self.op.grid.addWidget(self, 0, 0, 2, 10)

    def initUI(self):
        """
        Initialize the GUI.
        Does lots of stuff.
        """
        self.grid = QGridLayout()
        self.setLayout(self.grid)

        self.actions = self.op.link.getIDs()
        self.actions.append("New element")
        types = ["Info", "Speak", "Camera Change", "Movement"]

        self.save = QPushButton(self, text="Save")
        self.grid.addWidget(self.save, 3, 0)

        self.existing_connections = QListWidget(self)
        self.populateExistingConnections()
        self.grid.addWidget(self.existing_connections, 1, 5, 2, 1)

        self.next = QComboBox(self)
        self.next.addItems(self.actions)
        self.next.setMaximumWidth(150)
        if self.load != 0:
            self.next.setCurrentIndex(self.op.i)
        self.grid.addWidget(self.next, 3, 2)

        self.window = None

        self.actOM = QComboBox(self)
        self.actOM.addItems(types)
        self.actOM.activated.connect(self.changeFrame)
        self.grid.addWidget(self.actOM, 0, 0, 1, 2)

        self.connect()
        self.next.setCurrentIndex(self.next.count() - 1)

        self.backB = QPushButton(self, text="Back to List Menu")
        self.backB.clicked.connect(self.back)
        self.grid.addWidget(self.backB, 3, 4)

        self.lead = QLabel(self, text="Leads to:")
        self.lead.setAlignment(Qt.AlignRight)
        self.grid.addWidget(self.lead, 3, 1)

        self.connectB = QPushButton(self, text="Connect")
        self.connectB.clicked.connect(self.lightConnect)
        self.grid.addWidget(self.connectB, 3, 3)

        self.follow_path = QPushButton(self, text="Enter linked element")
        self.follow_path.clicked.connect(self.follow)
        self.grid.addWidget(self.follow_path, 0, 6, 2, 1)

        self.rmvRel = QPushButton(self, text="Remove this connection")
        self.rmvRel.clicked.connect(self.removeRelation)
        self.grid.addWidget(self.rmvRel, 1, 6, 2, 1)

        self.conLab = QLabel(self, text="This action connects to:")
        self.grid.addWidget(self.conLab, 0, 5)

    def removeRelation(self):
        """
        Remove a relation, which will also delete the uniquely dependant subtree.
        """
        if not self.existing_connections.currentItem() or \
           not popup("Are you sure you want to remove this relation? Any elements with a unique dependancy "
                     "on this relation will also be deleted.\nIt is highly recommended you take a look at "
                     "the graphical view of the tree in order to see the potential effects of the deletion.",
                     "Warning"):
            return
        self.op.link.delRelation(
            self.op.i,
            self.actions.index(self.existing_connections.currentItem().text()))
        self.populateExistingConnections()
        self.updateElementList()
        self.op.linkstored.save()

    def populateExistingConnections(self):
        """
        Display all the existing connections of the current node.
        """
        self.existing_connections.clear()
        for relation in self.op.link.getRelations(self.op.i):
            self.existing_connections.addItem(
                self.op.link.getOneID(self.op.link.getItem(relation)))

    def back(self):
        """
        Return to the higher-level cutscene container view...
        """
        if not popup("Return to list main menu?\n(Lose any unsaved changes)",
                     "Warning"):
            return
        self.close()
        self.op.cc = None
        self.op.viewF(False)

    def follow(self):
        """
        Move on to the edit view of the selected relationship.
        """
        if not self.existing_connections.currentItem() or \
           self.existing_connections.currentItem().text() == "":
            return
        self.next.setCurrentIndex([
            self.next.itemText(i) for i in range(self.next.count())
        ].index(self.existing_connections.currentItem().text()))
        self.op.i = self.actions.index(self.next.currentText())
        self.connect()
        self.next.setCurrentIndex(self.next.count() - 1)

    def lightConnect(self):
        """
        Create a relationship between the current action and another.
        """
        if not self.checkCached():
            popup("Please save this action before linking it to a new one",
                  "Information")
            return
        if self.next.currentText() == "New element":
            self.op.link.addRelation(self.op.i, self.op.link.size())
            print("Linked to index " + str(self.op.link.size()))
            self.op.i = self.op.link.size()
            self.load = 0
            self.changeFrame(0)
            self.updateElementList()
        else:
            self.op.link.addRelation(
                self.op.i, self.actions.index(self.next.currentText()))
            print("Linked to index " +
                  str(self.actions.index(self.next.currentText())))
        self.populateExistingConnections()

    def connect(self):
        """
        Create a relationship between the current action and another, and enter the edit view of the
        relationship.

        :raises Exception: if the requested new action's type can't be processed (should never happen)
        """
        print(self.next.currentText())
        if self.next.currentText() == "New element":
            self.load = 0
            self.changeFrame(0)
        else:
            if isinstance(
                    self.op.link.getItem(
                        self.actions.index(self.next.currentText())), Info):
                self.actOM.setCurrentIndex(0)
            elif isinstance(
                    self.op.link.getItem(
                        self.actions.index(self.next.currentText())), Speak):
                self.actOM.setCurrentIndex(1)
            elif isinstance(
                    self.op.link.getItem(
                        self.actions.index(self.next.currentText())), Camera):
                self.actOM.setCurrentIndex(2)
            elif isinstance(
                    self.op.link.getItem(
                        self.actions.index(self.next.currentText())),
                    Movement):
                self.actOM.setCurrentIndex(3)
            else:
                raise Exception("Not a type!")
            self.load = self.op.link.getItem(
                self.actions.index(self.next.currentText()))
            self.changeFrame(0)

    def checkCached(self):
        """
        Check if the current element has been saved before.

        :returns: if the element has been saved
        :rtype: bool
        """
        print(len(self.op.link.items) - 1)
        print(self.op.i)
        if self.op.link.getItem(self.op.i) == []:
            return False
        return True

    def updateElementList(self):
        """
        Update the relationships list, I think.
        """
        self.next.clear()
        self.actions = self.op.link.getIDs()
        self.actions.append("New element")
        self.next.addItems(self.actions)
        self.next.setCurrentIndex(len(self.actions) - 1)

    def changeFrame(self, _):
        """
        Change view to edit a certain type of action.

        :param objct _: unused, but required by caller
        """
        print("Changed to " + self.actOM.currentText())
        try:
            self.window.close()
        except AttributeError:
            pass  # No window open
        if self.actOM.currentText() == "Speak":
            self.window = SpeakFrame(self, self.load)
        elif self.actOM.currentText() == "Camera Change":
            self.window = CameraFrame(self, self.load)
        elif self.actOM.currentText() == "Movement":
            self.window = MoveFrame(self, self.load)
        else:  # self.actOM.currentText() == "Info":
            self.window = InfoFrame(self, self.load)
        try:
            self.save.clicked.disconnect()
        except:  #pylint: disable=bare-except
            pass
        self.save.clicked.connect(self.window.save)
        self.populateExistingConnections()
        self.updateElementList()
Exemple #17
0
class NGL_HKLViewer(QWidget):
    def __init__(self, parent=None):
        super(NGL_HKLViewer, self).__init__(parent)

        self.verbose = 0
        self.UseOSbrowser = False
        self.jscriptfname = ""
        self.devmode = False
        for e in sys.argv:
            if "verbose" in e:
                self.verbose = e.split("verbose=")[1]
            if "UseOSbrowser" in e:
                self.UseOSbrowser = e.split("UseOSbrowser=")[1]
            if "jscriptfname" in e:
                self.jscriptfname = e.split("jscriptfname=")[1]
            if "devmode" in e:
                self.devmode = True

        self.zmq_context = None
        self.bufsize = 20000

        self.originalPalette = QApplication.palette()

        self.openFileNameButton = QPushButton("Load reflection file")
        self.openFileNameButton.setDefault(True)
        self.openFileNameButton.clicked.connect(self.OpenReflectionsFile)

        self.debugbutton = QPushButton("Debug")
        self.debugbutton.clicked.connect(self.DebugInteractively)

        self.settingsbtn = QPushButton("Settings")
        self.settingsbtn.clicked.connect(self.SettingsDialog)

        self.mousemoveslider = QSlider(Qt.Horizontal)
        self.mousemoveslider.setMinimum(0)
        self.mousemoveslider.setMaximum(300)
        self.mousemoveslider.setValue(0)
        self.mousemoveslider.sliderReleased.connect(
            self.onFinalMouseSensitivity)
        self.mousemoveslider.valueChanged.connect(self.onMouseSensitivity)
        self.mousesensitxtbox = QLineEdit('')
        self.mousesensitxtbox.setReadOnly(True)
        self.fontspinBox = QDoubleSpinBox()
        self.fontspinBox.setSingleStep(1)
        self.fontspinBox.setRange(4, 50)
        self.font = QFont()
        self.font.setFamily(self.font.defaultFamily())
        self.fontspinBox.setValue(self.font.pointSize())
        #self.fontspinBox.setValue(self.font.pixelSize())
        self.fontspinBox.valueChanged.connect(self.onFontsizeChanged)
        self.Fontsize_labeltxt = QLabel()
        self.Fontsize_labeltxt.setText("Font size:")

        self.cameraPerspectCheckBox = QCheckBox()
        self.cameraPerspectCheckBox.setText("Perspective camera")
        self.cameraPerspectCheckBox.clicked.connect(self.onCameraPerspect)
        self.cameraPerspectCheckBox.setCheckState(Qt.Unchecked)

        self.settingsform = SettingsForm(self)

        self.MillerComboBox = QComboBox()
        self.MillerComboBox.activated.connect(self.onMillerComboSelchange)
        #self.MillerComboBox.setSizeAdjustPolicy(QComboBox.AdjustToContents)

        self.MillerLabel = QLabel()
        self.MillerLabel.setText("Selected HKL Scene")

        self.HKLnameedit = QLineEdit('')
        self.HKLnameedit.setReadOnly(True)
        self.textInfo = QTextEdit()
        self.textInfo.setLineWrapMode(QTextEdit.NoWrap)
        self.textInfo.setReadOnly(True)

        labels = [
            "Label", "Type", "no. of HKLs", "Span of HKLs", "Min Max data",
            "Min Max sigmas", "d_min, d_max", "Symmetry unique", "Anomalous"
        ]
        self.millertable = QTableWidget(0, len(labels))
        self.millertable.setHorizontalHeaderLabels(labels)
        self.millertable.horizontalHeader().setDefaultAlignment(Qt.AlignLeft)
        # don't allow editing this table
        self.millertable.setEditTriggers(QTableWidget.NoEditTriggers)

        self.createExpansionBox()
        self.createFileInfoBox()
        self.CreateSliceTabs()
        self.createRadiiScaleGroupBox()
        self.createBinsBox()
        self.CreateFunctionTabs()

        mainLayout = QGridLayout()
        mainLayout.addWidget(self.FileInfoBox, 0, 0)
        mainLayout.addWidget(self.MillerLabel, 1, 0)
        mainLayout.addWidget(self.MillerComboBox, 2, 0)
        mainLayout.addWidget(self.functionTabWidget, 3, 0)
        mainLayout.addWidget(self.settingsbtn, 4, 0, 1, 1)

        #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) )
        if self.UseOSbrowser == False:
            self.BrowserBox = QWebEngineView()
            mainLayout.addWidget(self.BrowserBox, 0, 1, 5, 3)
            self.BrowserBox.setUrl("https://cctbx.github.io/")
            #self.BrowserBox.setUrl("https://webglreport.com/")
            #self.BrowserBox.loadFinished.connect(self.onLoadFinished)
            mainLayout.setColumnStretch(2, 1)

        mainLayout.setRowStretch(0, 1)
        mainLayout.setRowStretch(1, 0)
        mainLayout.setRowStretch(2, 1)
        mainLayout.setRowStretch(3, 1)
        mainLayout.setColumnStretch(4, 0)
        self.setLayout(mainLayout)

        self.setWindowTitle("HKL-Viewer")
        self.cctbxproc = None
        self.LaunchCCTBXPython()
        self.out = None
        self.err = None
        self.comboviewwidth = 0
        self.hklscenes_arrays = []
        self.array_infotpls = []
        self.matching_arrays = []
        self.bin_infotpls = None
        self.bin_opacities = None
        self.html_url = ""
        self.spacegroups = []
        self.info = []
        self.infostr = ""
        self.fileisvalid = False
        self.NewFileLoaded = False
        self.NewHKLscenes = False
        self.updatingNbins = False
        self.binstableitemchanges = False

        self.show()

    def SettingsDialog(self):
        self.settingsform.show()

    def update(self):
        if self.cctbxproc:
            if self.cctbxproc.stdout:
                print(self.cctbxproc.stdout.read().decode("utf-8"))
            if self.cctbxproc.stderr:
                print(self.cctbxproc.stderr.read().decode("utf-8"))
        if self.out:
            print(self.out.decode("utf-8"))
        if self.err:
            print(self.err.decode("utf-8"))
        if self.zmq_context:
            try:
                msg = self.socket.recv(
                    flags=zmq.NOBLOCK
                )  #To empty the socket from previous messages
                msgstr = msg.decode()
                self.infodict = eval(msgstr)
                #print("received from cctbx: " + str(self.infodict))
                if self.infodict:

                    if self.infodict.get("hklscenes_arrays"):
                        self.hklscenes_arrays = self.infodict.get(
                            "hklscenes_arrays", [])

                    if self.infodict.get("array_infotpls"):
                        self.array_infotpls = self.infodict.get(
                            "array_infotpls", [])

                    if self.infodict.get("bin_data_label"):
                        self.BinDataComboBox.setCurrentText(
                            self.infodict["bin_data_label"])

                    if self.infodict.get("bin_infotpls"):
                        self.bin_infotpls = self.infodict["bin_infotpls"]

                        self.nbins = len(self.bin_infotpls)
                        self.updatingNbins = True
                        self.Nbins_spinBox.setValue(self.nbins)
                        self.updatingNbins = False
                        self.binstable.clearContents()
                        self.binstable.setRowCount(self.nbins)
                        for row, bin_infotpl in enumerate(self.bin_infotpls):
                            for col, elm in enumerate(bin_infotpl):
                                # only allow changing the last column with opacity values
                                if col != 3:
                                    item = QTableWidgetItem(str(elm))
                                else:
                                    item = QTableWidgetItem()
                                    item.setFlags(Qt.ItemIsUserCheckable
                                                  | Qt.ItemIsEnabled)
                                    item.setCheckState(Qt.Checked)
                                item.setFlags(item.flags() ^ Qt.ItemIsEditable)
                                self.binstable.setItem(row, col, item)
                        if self.bin_opacities:
                            self.update_table_opacities()

                    if self.infodict.get("bin_opacities"):
                        self.bin_opacities = self.infodict["bin_opacities"]
                        if self.binstable.rowCount() > 0:
                            self.update_table_opacities()

                    if self.infodict.get("html_url"):
                        self.html_url = self.infodict["html_url"]
                        if self.UseOSbrowser == False:
                            self.BrowserBox.setUrl(self.html_url)
                            # workaround for background colour bug in chromium
                            # https://bugreports.qt.io/browse/QTBUG-41960
                            self.BrowserBox.page().setBackgroundColor(
                                QColor(100, 100, 100, 1.0))

                    if self.infodict.get("spacegroups"):
                        self.spacegroups = self.infodict.get("spacegroups", [])
                        self.SpaceGroupComboBox.clear()
                        self.SpaceGroupComboBox.addItems(self.spacegroups)

                    if self.infodict.get("merge_data"):
                        self.mergedata = self.infodict["merge_data"]

                    currentinfostr = ""
                    if self.infodict.get("info"):
                        currentinfostr = self.infodict.get("info", [])

                    if self.infodict.get("NewFileLoaded"):
                        self.NewFileLoaded = self.infodict.get(
                            "NewFileLoaded", False)

                    if self.infodict.get("NewHKLscenes"):
                        self.NewHKLscenes = self.infodict.get(
                            "NewHKLscenes", False)

                    self.fileisvalid = True
                    #print("ngl_hkl_infodict: " + str(ngl_hkl_infodict))

                    if currentinfostr:
                        #print(currentinfostr)
                        self.infostr += currentinfostr + "\n"
                        # display no more than self.bufsize bytes of text
                        self.infostr = self.infostr[-self.bufsize:]
                        self.textInfo.setPlainText(self.infostr)
                        self.textInfo.verticalScrollBar().setValue(
                            self.textInfo.verticalScrollBar().maximum())

                    if self.NewFileLoaded and self.NewHKLscenes:
                        #if self.mergedata == True : val = Qt.CheckState.Checked
                        #if self.mergedata == None : val = Qt.CheckState.PartiallyChecked
                        #if self.mergedata == False : val = Qt.CheckState.Unchecked
                        #self.mergecheckbox.setCheckState(val )
                        #print("got hklscenes: " + str(self.hklscenes_arrays))

                        self.MillerComboBox.clear()
                        self.MillerComboBox.addItems(
                            [e[3] for e in self.hklscenes_arrays])
                        self.MillerComboBox.setCurrentIndex(
                            -1)  # unselect the first item in the list
                        self.comboviewwidth = 0
                        for e in self.hklscenes_arrays:
                            self.comboviewwidth = max(
                                self.comboviewwidth,
                                self.MillerComboBox.fontMetrics().width(e[3]))
                        self.MillerComboBox.view().setMinimumWidth(
                            self.comboviewwidth)

                        self.millertable.clearContents()
                        self.millertable.setRowCount(len(
                            self.hklscenes_arrays))
                        for n, millarr in enumerate(self.array_infotpls):
                            for m, elm in enumerate(millarr):
                                self.millertable.setItem(
                                    n, m, QTableWidgetItem(str(elm)))
                        self.functionTabWidget.setDisabled(True)
                        self.NewFileLoaded = False

                    if self.NewHKLscenes:
                        self.BinDataComboBox.clear()
                        self.BinDataComboBox.addItems(
                            ["Resolution"] +
                            [e[3] for e in self.hklscenes_arrays])
                        self.BinDataComboBox.view().setMinimumWidth(
                            self.comboviewwidth)
                        #self.BinDataComboBox.setCurrentIndex(-1) # unselect the first item in the list
                        self.NewHKLscenes = False

            except Exception as e:
                errmsg = str(e)
                if "Resource temporarily unavailable" not in errmsg:
                    print(errmsg + traceback.format_exc(limit=10))
                pass

    def onFinalMouseSensitivity(self):
        val = self.mousemoveslider.value() / 100.0
        self.NGL_HKL_command(
            'NGL_HKLviewer.viewer.NGL.mouse_sensitivity = %f' % val)

    def onMouseSensitivity(self):
        val = self.mousemoveslider.value() / 100.0
        self.mousesensitxtbox.setText("%2.2f" % val)

    def onFontsizeChanged(self, val):
        font = app.font()
        font.setPointSize(val)
        app.setFont(font)
        self.settingsform.setFixedSize(self.settingsform.sizeHint())

    def onCameraPerspect(self, val):
        if self.cameraPerspectCheckBox.isChecked():
            self.NGL_HKL_command("NGL_HKLviewer.camera_type = perspective")
        else:
            self.NGL_HKL_command("NGL_HKLviewer.camera_type = orthographic")

    def MergeData(self):
        if self.mergecheckbox.checkState() == Qt.CheckState.Checked:
            self.NGL_HKL_command('NGL_HKLviewer.mergedata = True')
        if self.mergecheckbox.checkState() == Qt.CheckState.PartiallyChecked:
            self.NGL_HKL_command('NGL_HKLviewer.mergedata = None')
        if self.mergecheckbox.checkState() == Qt.CheckState.Unchecked:
            self.NGL_HKL_command('NGL_HKLviewer.mergedata = False')

    def ExpandToP1(self):
        if self.expandP1checkbox.isChecked():
            self.NGL_HKL_command('NGL_HKLviewer.viewer.expand_to_p1 = True')
        else:
            self.NGL_HKL_command('NGL_HKLviewer.viewer.expand_to_p1 = False')

    def ExpandAnomalous(self):
        if self.expandAnomalouscheckbox.isChecked():
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.expand_anomalous = True')
        else:
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.expand_anomalous = False')

    def showSysAbsent(self):
        if self.sysabsentcheckbox.isChecked():
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.show_systematic_absences = True')
        else:
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.show_systematic_absences = False')

    def showMissing(self):
        if self.missingcheckbox.isChecked():
            self.NGL_HKL_command('NGL_HKLviewer.viewer.show_missing = True')
        else:
            self.NGL_HKL_command('NGL_HKLviewer.viewer.show_missing = False')

    def showOnlyMissing(self):
        if self.onlymissingcheckbox.isChecked():
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.show_only_missing = True')
        else:
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.show_only_missing = False')

    def showSlice(self):
        if self.showslicecheckbox.isChecked():
            self.NGL_HKL_command('NGL_HKLviewer.viewer.slice_mode = True')
            if self.expandP1checkbox.isChecked():
                self.NGL_HKL_command("""NGL_HKLviewer.viewer {
                                                       expand_to_p1 = True
                                                       inbrowser = False
                                                    }
                             """)
            if self.expandAnomalouscheckbox.isChecked():
                self.NGL_HKL_command("""NGL_HKLviewer.viewer {
                                                       expand_anomalous = True
                                                       inbrowser = False
                                                     }
                             """)
        else:
            self.NGL_HKL_command("""NGL_HKLviewer.viewer {
                                                      slice_mode = False
                                                      inbrowser = True
                                                    }
                            """)

    def onSliceComboSelchange(self, i):
        rmin = self.array_infotpls[self.MillerComboBox.currentIndex()][3][0][i]
        rmax = self.array_infotpls[self.MillerComboBox.currentIndex()][3][1][i]
        self.sliceindexspinBox.setRange(rmin, rmax)
        self.NGL_HKL_command("NGL_HKLviewer.viewer.slice_axis = %s" %
                             self.sliceaxis[i])

    def onSliceIndexChanged(self, val):
        self.sliceindex = val
        self.NGL_HKL_command("NGL_HKLviewer.viewer.slice_index = %d" %
                             self.sliceindex)

    def onBindataComboSelchange(self, i):
        if self.BinDataComboBox.currentText():
            if self.BinDataComboBox.currentIndex() > 0:
                bin_scene_label = str(self.BinDataComboBox.currentIndex() - 1)
            else:
                bin_scene_label = "Resolution"
            self.NGL_HKL_command("NGL_HKLviewer.bin_scene_label = %s" %
                                 bin_scene_label)

    def update_table_opacities(self, allalpha=None):
        bin_opacitieslst = eval(self.bin_opacities)
        self.binstable_isready = False
        for binopacity in bin_opacitieslst:
            if not allalpha:
                alpha = float(binopacity.split(",")[0])
            else:
                alpha = allalpha
            bin = int(binopacity.split(",")[1])
            item = QTableWidgetItem()
            item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
            if alpha < 0.5:
                item.setCheckState(Qt.Unchecked)
            else:
                item.setCheckState(Qt.Checked)
            item.setFlags(item.flags() ^ Qt.ItemIsEditable)
            self.binstable.setItem(bin, 3, item)
        self.binstable_isready = True

    def SetOpaqueAll(self):
        if self.binstableitemchanges:
            return
        bin_opacitieslst = eval(self.bin_opacities)
        nbins = len(bin_opacitieslst)
        sum = 0
        for binopacity in bin_opacitieslst:
            sum += float(binopacity.split(",")[0])
        if sum >= nbins:
            self.OpaqueAllCheckbox.setCheckState(Qt.Checked)
        if sum == 0:
            self.OpaqueAllCheckbox.setCheckState(Qt.Unchecked)
        if sum > 0.0 and sum < nbins:
            self.OpaqueAllCheckbox.setCheckState(Qt.PartiallyChecked)

    def onBinsTableItemChanged(self, item):
        row = item.row()
        column = item.column()
        try:
            if item.checkState() == Qt.Unchecked:
                newval = 0
            else:
                newval = 1.0
            if column == 3 and self.binstable_isready:  # changing opacity
                assert (newval <= 1.0 and newval >= 0.0)
                bin_opacitieslst = eval(self.bin_opacities)
                bin_opacitieslst[row] = str(newval) + ', ' + str(row)
                self.bin_opacities = str(bin_opacitieslst)
                self.SetOpaqueAll()
                self.NGL_HKL_command(
                    'NGL_HKLviewer.viewer.NGL.bin_opacities = "%s"' %
                    self.bin_opacities)
        except Exception as e:
            print(str(e))
            #self.binstable.currentItem().setText( self.currentSelectedBinsTableVal)

    def onBinsTableItemSelectionChanged(self):
        row = self.binstable.currentItem().row()
        column = self.binstable.currentItem().column()
        self.currentSelectedBinsTableVal = self.binstable.currentItem().text()
        #print( "in itemSelectionChanged " + self.currentSelectedBinsTableVal)

    def onOpaqueAll(self):
        self.binstableitemchanges = True
        bin_opacitieslst = eval(self.bin_opacities)
        nbins = len(bin_opacitieslst)
        bin_opacitieslst = []
        self.binstable_isready = False
        if self.OpaqueAllCheckbox.isChecked():
            for i in range(nbins):
                bin_opacitieslst.append("1.0, %d" % i)
        else:
            for i in range(nbins):
                bin_opacitieslst.append("0.0, %d" % i)
        self.bin_opacities = str(bin_opacitieslst)
        self.NGL_HKL_command('NGL_HKLviewer.viewer.NGL.bin_opacities = "%s"' %
                             self.bin_opacities)
        self.binstableitemchanges = False
        self.binstable_isready = True

    """
  def onLoadFinished(self, val):
    pass
    #print("web page finished loading now")


  def onBinsTableitemActivated(self, item):
    row = item.row()
    column = item.column()
    currentval = item.text()
    #print( "in itemActivated " + currentval)


  def onBinsTableCellentered(self, row, col):
    pass
    #print( "in Cellentered " + self.binstable.currentItem().text() )


  def onBinsTableCellPressed(self, row, col):
    pass
    #print( "in CellPressed " + self.binstable.currentItem().text() )
  """

    def onNbinsChanged(self, val):
        self.nbins = val
        if not self.updatingNbins:  # avoid possible endless loop to cctbx
            self.NGL_HKL_command("NGL_HKLviewer.nbins = %d" % self.nbins)

    def onRadiiScaleChanged(self, val):
        self.radii_scale = val
        self.NGL_HKL_command("""
      NGL_HKLviewer.viewer {
        nth_power_scale_radii = %f
        scale = %f
      }
      """ % (self.nth_power_scale, self.radii_scale))

    def onPowerScaleChanged(self, val):
        self.nth_power_scale = val
        self.NGL_HKL_command("""
      NGL_HKLviewer.viewer {
        nth_power_scale_radii = %f
        scale = %f
      }
      """ % (self.nth_power_scale, self.radii_scale))

    def onManualPowerScale(self):
        if self.ManualPowerScalecheckbox.isChecked():
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.nth_power_scale_radii = %f' %
                self.nth_power_scale)
            self.power_scale_spinBox.setEnabled(True)
        else:
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.nth_power_scale_radii = -1.0')
            self.power_scale_spinBox.setEnabled(False)
            self.nth_power_scale = -1.0

    def OpenReflectionsFile(self):
        options = QFileDialog.Options()
        fileName, filtr = QFileDialog.getOpenFileName(
            self, "Load reflections file", "",
            "All Files (*);;MTZ Files (*.mtz);;CIF (*.cif)", "", options)
        if fileName:
            self.HKLnameedit.setText(fileName)
            #self.infostr = ""
            self.textInfo.setPlainText("")
            self.fileisvalid = False
            self.NGL_HKL_command('NGL_HKLviewer.filename = "%s"' % fileName)
            self.MillerComboBox.clear()
            self.BinDataComboBox.clear()

    def createExpansionBox(self):
        self.SpaceGroupComboBox = QComboBox()
        self.SpaceGroupComboBox.activated.connect(self.SpacegroupSelchange)

        self.SpacegroupLabel = QLabel()
        self.SpacegroupLabel.setText("Space Subgroups")

        self.mergecheckbox = QCheckBox()
        self.mergecheckbox.setText("Merge data")
        #self.mergecheckbox.setTristate (True)
        self.mergecheckbox.clicked.connect(self.MergeData)

        self.expandP1checkbox = QCheckBox()
        self.expandP1checkbox.setText("Expand to P1")
        self.expandP1checkbox.clicked.connect(self.ExpandToP1)

        self.expandAnomalouscheckbox = QCheckBox()
        self.expandAnomalouscheckbox.setText("Show Friedel pairs")
        self.expandAnomalouscheckbox.clicked.connect(self.ExpandAnomalous)

        self.sysabsentcheckbox = QCheckBox()
        self.sysabsentcheckbox.setText("Show Systematic Absences")
        self.sysabsentcheckbox.clicked.connect(self.showSysAbsent)

        self.missingcheckbox = QCheckBox()
        self.missingcheckbox.setText("Show Missing")
        self.missingcheckbox.clicked.connect(self.showMissing)

        self.onlymissingcheckbox = QCheckBox()
        self.onlymissingcheckbox.setText("Only Show Missing")
        self.onlymissingcheckbox.clicked.connect(self.showOnlyMissing)

        self.ExpansionBox = QGroupBox("Expansions")
        layout = QGridLayout()
        layout.addWidget(self.SpacegroupLabel, 0, 0)
        layout.addWidget(self.SpaceGroupComboBox, 0, 1)
        #layout.addWidget(self.mergecheckbox,             1, 0)
        layout.addWidget(self.expandP1checkbox, 1, 0)
        layout.addWidget(self.expandAnomalouscheckbox, 1, 1)
        layout.addWidget(self.sysabsentcheckbox, 2, 0)
        layout.addWidget(self.missingcheckbox, 3, 0)
        layout.addWidget(self.onlymissingcheckbox, 3, 1)
        layout.setRowStretch(0, 0)
        layout.setRowStretch(1, 0)
        layout.setRowStretch(2, 0)
        layout.setRowStretch(3, 1)
        self.ExpansionBox.setLayout(layout)

    def CreateSliceTabs(self):
        self.showslicecheckbox = QCheckBox()
        self.showslicecheckbox.setText("Show Slice")
        self.showslicecheckbox.clicked.connect(self.showSlice)

        self.sliceindexspinBox = QDoubleSpinBox()
        self.sliceindex = 0
        self.sliceindexspinBox.setValue(self.sliceindex)
        self.sliceindexspinBox.setDecimals(0)
        self.sliceindexspinBox.setSingleStep(1)
        self.sliceindexspinBox.setRange(0, 20)
        self.sliceindexspinBox.valueChanged.connect(self.onSliceIndexChanged)

        self.SliceLabelComboBox = QComboBox()
        self.SliceLabelComboBox.activated.connect(self.onSliceComboSelchange)
        self.sliceaxis = ["h", "k", "l"]
        self.SliceLabelComboBox.addItems(self.sliceaxis)

        self.sliceTabWidget = QTabWidget()
        tab1 = QWidget()
        layout1 = QGridLayout()
        layout1.addWidget(self.showslicecheckbox, 0, 0, 1, 1)
        layout1.addWidget(self.SliceLabelComboBox, 0, 1, 1, 1)
        layout1.addWidget(self.sliceindexspinBox, 0, 2, 1, 1)
        tab1.setLayout(layout1)

        tab2 = QWidget()
        layout2 = QGridLayout()

        self.hvec_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.hvecval = 2.0
        self.hvec_spinBox.setValue(self.hvecval)
        self.hvec_spinBox.setDecimals(2)
        self.hvec_spinBox.setSingleStep(0.5)
        self.hvec_spinBox.setRange(-100.0, 10.0)
        self.hvec_spinBox.valueChanged.connect(self.onHvecChanged)
        self.hvec_Label = QLabel()
        self.hvec_Label.setText("H")
        layout2.addWidget(self.hvec_Label, 0, 0, 1, 1)
        layout2.addWidget(self.hvec_spinBox, 0, 1, 1, 1)

        self.kvec_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.kvecval = 0.0
        self.kvec_spinBox.setValue(self.kvecval)
        self.kvec_spinBox.setDecimals(2)
        self.kvec_spinBox.setSingleStep(0.5)
        self.kvec_spinBox.setRange(-100.0, 100.0)
        self.kvec_spinBox.valueChanged.connect(self.onKvecChanged)
        self.kvec_Label = QLabel()
        self.kvec_Label.setText("K")
        layout2.addWidget(self.kvec_Label, 1, 0, 1, 1)
        layout2.addWidget(self.kvec_spinBox, 1, 1, 1, 1)

        self.lvec_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.lvecval = 0.0
        self.lvec_spinBox.setValue(self.lvecval)
        self.lvec_spinBox.setDecimals(2)
        self.lvec_spinBox.setSingleStep(0.5)
        self.lvec_spinBox.setRange(-100.0, 100.0)
        self.lvec_spinBox.valueChanged.connect(self.onLvecChanged)
        self.lvec_Label = QLabel()
        self.lvec_Label.setText("L")
        layout2.addWidget(self.lvec_Label, 2, 0, 1, 1)
        layout2.addWidget(self.lvec_spinBox, 2, 1, 1, 1)

        self.hkldist_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.hkldistval = 0.0
        self.hkldist_spinBox.setValue(self.hkldistval)
        self.hkldist_spinBox.setDecimals(2)
        self.hkldist_spinBox.setSingleStep(0.5)
        self.hkldist_spinBox.setRange(-100.0, 100.0)
        self.hkldist_spinBox.valueChanged.connect(self.onHKLdistChanged)
        self.hkldist_Label = QLabel()
        self.hkldist_Label.setText("Distance from Origin")
        layout2.addWidget(self.hkldist_Label, 3, 0, 1, 1)
        layout2.addWidget(self.hkldist_spinBox, 3, 1, 1, 1)

        self.clipwidth_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.clipwidthval = 0.5
        self.clipwidth_spinBox.setValue(self.clipwidthval)
        self.clipwidth_spinBox.setDecimals(2)
        self.clipwidth_spinBox.setSingleStep(0.05)
        self.clipwidth_spinBox.setRange(0.0, 100.0)
        self.clipwidth_spinBox.valueChanged.connect(self.onClipwidthChanged)
        self.clipwidth_Label = QLabel()
        self.clipwidth_Label.setText("Clip Plane Width")
        layout2.addWidget(self.clipwidth_Label, 4, 0, 1, 1)
        layout2.addWidget(self.clipwidth_spinBox, 4, 1, 1, 1)

        self.ClipBox = QGroupBox("Normal Vector to Clip Plane")
        self.ClipBox.setLayout(layout2)

        layout3 = QGridLayout()
        self.ClipPlaneChkBox = QCheckBox(self.sliceTabWidget)
        self.ClipPlaneChkBox.setText(
            "Use clip plane normal to HKL vector pointing out")
        self.ClipPlaneChkBox.clicked.connect(self.onClipPlaneChkBox)

        layout3.addWidget(self.ClipPlaneChkBox, 0, 0)
        layout3.addWidget(self.ClipBox, 1, 0)
        tab2.setLayout(layout3)
        self.sliceTabWidget.addTab(tab1, "Explicit Slicing")
        self.sliceTabWidget.addTab(tab2, "Clip Plane Slicing")
        self.ClipBox.setDisabled(True)

    def onClipPlaneChkBox(self):
        if self.ClipPlaneChkBox.isChecked():
            self.ClipBox.setDisabled(False)
            philstr = """NGL_HKLviewer.normal_clip_plane {
  h = %s
  k = %s
  l = %s
  hkldist = %s
  clipwidth = %s
}
  NGL_HKLviewer.viewer.NGL.fixorientation = %s

      """ %(self.hvecval, self.kvecval, self.lvecval, self.hkldistval, self.clipwidthval, \
                                    str(self.fixedorientcheckbox.isChecked()) )
            self.NGL_HKL_command(philstr)
        else:
            self.ClipBox.setDisabled(True)
            self.NGL_HKL_command(
                "NGL_HKLviewer.normal_clip_plane.clipwidth = None")

    def onClipwidthChanged(self, val):
        self.clipwidthval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.clipwidth = %f" %
                             self.clipwidthval)

    def onHKLdistChanged(self, val):
        self.hkldistval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.hkldist = %f" %
                             self.hkldistval)

    def onHvecChanged(self, val):
        self.hvecval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.h = %f" %
                             self.hvecval)

    def onKvecChanged(self, val):
        self.kvecval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.k = %f" %
                             self.kvecval)

    def onLvecChanged(self, val):
        self.lvecval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.l = %f" %
                             self.lvecval)

    def onFixedorient(self):
        self.NGL_HKL_command('NGL_HKLviewer.viewer.NGL.fixorientation = %s' \
                                        %str(self.fixedorientcheckbox.isChecked()))

    def onMillerComboSelchange(self, i):
        self.NGL_HKL_command("NGL_HKLviewer.scene_id = %d" % i)
        #self.MillerComboBox.setCurrentIndex(i)
        if self.MillerComboBox.currentText():
            self.functionTabWidget.setEnabled(True)
            self.expandAnomalouscheckbox.setEnabled(True)
            # don' allow anomalous expansion for data that's already anomalous
            for arrayinfo in self.array_infotpls:
                isanomalous = arrayinfo[-1]
                label = arrayinfo[0]
                if isanomalous and label == self.MillerComboBox.currentText(
                )[:len(label)]:
                    self.expandAnomalouscheckbox.setDisabled(True)
        else:
            self.functionTabWidget.setDisabled(True)

        self.SpaceGroupComboBox.clear()
        self.SpaceGroupComboBox.addItems(self.spacegroups)
        # need to supply issymunique flag in infotuple
        #if self.hklscenes_arrays[ i ][6] == 0:
        #  self.mergecheckbox.setEnabled(True)
        #else:
        #  self.mergecheckbox.setEnabled(False)

    def createFileInfoBox(self):
        self.FileInfoBox = QGroupBox("Reflection File Information")
        layout = QGridLayout()
        layout.addWidget(self.openFileNameButton, 0, 0, 1, 2)
        if self.devmode:
            layout.addWidget(self.debugbutton, 0, 2, 1, 1)
        layout.addWidget(self.HKLnameedit, 1, 0, 1, 3)
        layout.addWidget(self.millertable, 2, 0, 1, 3)
        layout.addWidget(self.textInfo, 3, 0, 1, 3)
        #layout.setColumnStretch(1, 2)
        self.FileInfoBox.setLayout(layout)

    def createRadiiScaleGroupBox(self):
        self.RadiiScaleGroupBox = QGroupBox("Radii Size of HKL Spheres")

        self.ManualPowerScalecheckbox = QCheckBox()
        self.ManualPowerScalecheckbox.setText(
            "Manual Power Scaling of Sphere Radii")
        self.ManualPowerScalecheckbox.clicked.connect(self.onManualPowerScale)

        self.power_scale_spinBox = QDoubleSpinBox(self.RadiiScaleGroupBox)
        self.nth_power_scale = 0.5
        self.power_scale_spinBox.setValue(self.nth_power_scale)
        self.power_scale_spinBox.setDecimals(2)
        self.power_scale_spinBox.setSingleStep(0.05)
        self.power_scale_spinBox.setRange(0.0, 1.0)
        self.power_scale_spinBox.valueChanged.connect(self.onPowerScaleChanged)
        self.power_scale_spinBox.setEnabled(False)
        self.powerscaleLabel = QLabel()
        self.powerscaleLabel.setText("Power scale Factor")

        self.radii_scale_spinBox = QDoubleSpinBox(self.RadiiScaleGroupBox)
        self.radii_scale = 1.0
        self.radii_scale_spinBox.setValue(self.radii_scale)
        self.radii_scale_spinBox.setDecimals(1)
        self.radii_scale_spinBox.setSingleStep(0.1)
        self.radii_scale_spinBox.setRange(0.2, 2.0)
        self.radii_scale_spinBox.valueChanged.connect(self.onRadiiScaleChanged)
        self.radiiscaleLabel = QLabel()
        self.radiiscaleLabel.setText("Linear Scale Factor")

        layout = QGridLayout()
        layout.addWidget(self.ManualPowerScalecheckbox, 1, 0, 1, 2)
        layout.addWidget(self.powerscaleLabel, 2, 0, 1, 2)
        layout.addWidget(self.power_scale_spinBox, 2, 1, 1, 2)
        layout.addWidget(self.radiiscaleLabel, 3, 0, 1, 2)
        layout.addWidget(self.radii_scale_spinBox, 3, 1, 1, 2)
        layout.setColumnStretch(0, 1)
        layout.setColumnStretch(1, 0)
        self.RadiiScaleGroupBox.setLayout(layout)

    def createBinsBox(self):
        self.binstable = QTableWidget(0, 4)
        self.binstable_isready = False
        labels = [
            "no. of HKLs", "lower bin value", "upper bin value", "opacity"
        ]
        self.binstable.setHorizontalHeaderLabels(labels)
        self.binstable.horizontalHeader().setDefaultAlignment(Qt.AlignLeft)
        self.bindata_labeltxt = QLabel()
        self.bindata_labeltxt.setText("Data binned:")
        self.Nbins_spinBox = QSpinBox()
        self.Nbins_spinBox.setSingleStep(1)
        self.Nbins_spinBox.setRange(1, 40)
        self.Nbins_spinBox.valueChanged.connect(self.onNbinsChanged)
        self.Nbins_labeltxt = QLabel()
        self.Nbins_labeltxt.setText("Number of bins:")

        self.OpaqueAllCheckbox = QCheckBox()
        #self.OpaqueAllCheckbox.setTristate()
        self.OpaqueAllCheckbox.setText("Show all data in bins")
        self.OpaqueAllCheckbox.clicked.connect(self.onOpaqueAll)

        self.binstable.itemChanged.connect(self.onBinsTableItemChanged)
        self.binstable.itemSelectionChanged.connect(
            self.onBinsTableItemSelectionChanged)
        self.BinDataComboBox = QComboBox()
        self.BinDataComboBox.activated.connect(self.onBindataComboSelchange)
        self.BinsGroupBox = QGroupBox("Bins")
        layout = QGridLayout()
        layout.addWidget(self.bindata_labeltxt, 0, 0)
        layout.addWidget(self.BinDataComboBox, 0, 1)
        layout.addWidget(self.Nbins_labeltxt, 0, 2)
        layout.addWidget(self.Nbins_spinBox, 0, 3)
        layout.addWidget(self.OpaqueAllCheckbox, 1, 2)
        layout.addWidget(self.binstable, 2, 0, 1, 4)
        layout.setColumnStretch(0, 0)
        layout.setColumnStretch(1, 2)
        layout.setColumnStretch(3, 1)
        self.BinsGroupBox.setLayout(layout)

    def DebugInteractively(self):
        import code, traceback
        code.interact(local=locals(),
                      banner="".join(traceback.format_stack(limit=10)))

    def CreateFunctionTabs(self):
        self.functionTabWidget = QTabWidget()
        tab1 = QWidget()
        layout1 = QGridLayout()
        layout1.addWidget(self.ExpansionBox, 0, 0)
        layout1.setRowStretch(0, 0)
        tab1.setLayout(layout1)

        tab2 = QWidget()
        layout2 = QGridLayout()

        self.fixedorientcheckbox = QCheckBox(self.sliceTabWidget)
        self.fixedorientcheckbox.setText(
            "Fix orientation but allow zoom and translation")
        self.fixedorientcheckbox.clicked.connect(self.onFixedorient)
        layout2.addWidget(self.fixedorientcheckbox, 0, 0)

        layout2.addWidget(self.sliceTabWidget, 1, 0)
        tab2.setLayout(layout2)

        tab3 = QWidget()
        layout3 = QGridLayout()
        layout3.addWidget(self.RadiiScaleGroupBox, 0, 0)
        tab3.setLayout(layout3)

        tab4 = QWidget()
        layout4 = QGridLayout()
        layout4.addWidget(self.BinsGroupBox, 0, 0)
        tab4.setLayout(layout4)

        self.functionTabWidget.addTab(tab1, "Expand")
        self.functionTabWidget.addTab(tab2, "Slice")
        self.functionTabWidget.addTab(tab3, "Size")
        self.functionTabWidget.addTab(tab4, "Bins")
        self.functionTabWidget.setDisabled(True)

    def SpacegroupSelchange(self, i):
        self.NGL_HKL_command("NGL_HKLviewer.spacegroup_choice = %d" % i)

    def find_free_port(self):
        import socket
        s = socket.socket()
        s.bind(('', 0))  # Bind to a free port provided by the host.
        port = s.getsockname()[1]
        s.close()
        return port

    def LaunchCCTBXPython(self):
        self.sockport = self.find_free_port()
        self.zmq_context = zmq.Context()
        self.socket = self.zmq_context.socket(zmq.PAIR)
        self.socket.bind("tcp://127.0.0.1:%s" % self.sockport)
        try:
            msg = self.socket.recv(
                flags=zmq.NOBLOCK)  #To empty the socket from previous messages
        except Exception as e:
            pass
        cmdargs = 'cctbx.python.bat -i -c "from crys3d.hklview import cmdlineframes;' \
         + ' myHKLview = cmdlineframes.HKLViewFrame(useGuiSocket=%s, high_quality=True,' %self.sockport \
         + ' jscriptfname = \'%s\', ' %self.jscriptfname \
         + ' verbose=%s, UseOSBrowser= %s )"\n' %(self.verbose, str(self.UseOSbrowser))
        self.cctbxproc = subprocess.Popen(cmdargs,
                                          shell=True,
                                          stdin=subprocess.PIPE,
                                          stdout=sys.stdout,
                                          stderr=sys.stderr)
        #time.sleep(1)

    def NGL_HKL_command(self, cmdstr):
        #print("sending:\n" + cmdstr)
        self.socket.send(bytes(cmdstr, "utf-8"))
class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        # 设置时间
        self.__time = QDateTime()

        # 创建图形界面
        self.__SetupUI()

        self.__ConfigureFileToolBar()

        self.__ConfigureTranslateToolBar()

        self.__ConfigureMainLayout()

        # 设置ComboBox的显示内容
        self.__ConfigureComboBox()

        # 设置保存文件的信息
        self.__currentPath = QDir.currentPath()

        self.__ConfigureSysIniFile()

        self.__ConfigureHistoryFile()

        salt = random.randint(1466000000, 1467000000)
        self.__salt = str(salt)

        self.__httpClient = None

        self.__statusBar.showMessage(
            self.__GetCurrentTime() + " - Please choose a file or enter data!",
            2000)

        self.show()

    def __del__(self):
        self.__historyFile.close()

    def __SetupUI(self):
        self.__mainWidget = QWidget()
        self.setCentralWidget(self.__mainWidget)

        self.__fileToolBar = QToolBar("File")
        self.addToolBar(self.__fileToolBar)
        self.__translateToolBar = QToolBar("Translate")
        self.addToolBar(self.__translateToolBar)

        self.__statusBar = QStatusBar()
        self.setStatusBar(self.__statusBar)

        self.setWindowIcon(QIcon("./image/translate.png"))

    def __ConfigureFileToolBar(self):
        self.__openFileAction = QAction(QIcon("./image/open.png"), "Open File")
        self.__fileToolBar.addAction(self.__openFileAction)
        self.__openFileAction.triggered.connect(
            self.__on_triggered_openFileAction)

        self.__saveFileAction = QAction(QIcon("./image/save.png"), "Save File")
        self.__fileToolBar.addAction(self.__saveFileAction)
        self.__saveFileAction.triggered.connect(
            self.__on_triggered_saveFileAction)

    def __ConfigureTranslateToolBar(self):
        self.__translateAction = QAction(QIcon("./image/translate.png"),
                                         "Translate")
        self.__translateToolBar.addAction(self.__translateAction)
        self.__translateAction.triggered.connect(
            self.__on_triggered_translateAction)

        self.__clearAction = QAction(QIcon("./image/clear.png"), "Clear")
        self.__translateToolBar.addAction(self.__clearAction)
        self.__clearAction.triggered.connect(self.__on_triggered_clearAction)

    def __ConfigureMainLayout(self):
        self.__appIDLabel = QLabel("AppID:")
        self.__appIDLineEdit = QLineEdit(self)
        self.__appIDLineEdit.returnPressed.connect(
            self.__on_returnPressed_appIDLineEdit)

        self.__keyLabel = QLabel("Key:")
        self.__keyLineEdit = QLineEdit(self)
        self.__keyLineEdit.returnPressed.connect(
            self.__on_returnPressed_keyLineEdit)

        self.__fromLabel = QLabel("From:")
        self.__fromComboBox = QComboBox(self)
        self.__toLabel = QLabel("To:")
        self.__toComboBox = QComboBox(self)

        self.__srcLabel = QLabel("Src Text:")
        self.__srcTextEdit = QTextEdit(self)

        self.__translateLabel = QLabel("Translate Text:")
        self.__translateTextEdit = QTextEdit(self)

        self.__mainLayout = QGridLayout()
        self.__mainLayout.addWidget(self.__appIDLabel, 0, 0)
        self.__mainLayout.addWidget(self.__appIDLineEdit, 0, 1, 1, 3)
        self.__mainLayout.addWidget(self.__keyLabel, 1, 0)
        self.__mainLayout.addWidget(self.__keyLineEdit, 1, 1, 1, 3)
        self.__mainLayout.addWidget(self.__fromLabel, 2, 0)
        self.__mainLayout.addWidget(self.__fromComboBox, 2, 1)
        self.__mainLayout.addWidget(self.__toLabel, 2, 2)
        self.__mainLayout.addWidget(self.__toComboBox, 2, 3)
        self.__mainLayout.addWidget(self.__srcLabel, 3, 0)
        self.__mainLayout.addWidget(self.__srcTextEdit, 3, 1, 1, 3)
        self.__mainLayout.addWidget(self.__translateLabel, 4, 0)
        self.__mainLayout.addWidget(self.__translateTextEdit, 4, 1, 1, 3)

        self.__mainWidget.setLayout(self.__mainLayout)

    def __ConfigureComboBox(self):
        self.__fromComboBox.clear()
        self.__fromComboBox.addItem("English", "en")
        self.__fromComboBox.addItem("Chinese", "zh")
        self.__fromComboBox.addItem("Auto", "auto")
        self.__fromComboBox.setCurrentIndex(2)

        self.__toComboBox.clear()
        self.__toComboBox.addItem("English", "en")
        self.__toComboBox.addItem("Chinese", "zh")
        self.__toComboBox.setCurrentIndex(1)

    def __ConfigureSysIniFile(self):
        iniFile = QFile("info.ini")

        if iniFile.exists():
            self.__infoSettings = QSettings("info.ini", QSettings.IniFormat)

            self.__appIDLineEdit.setText(
                self.__infoSettings.value("info/appid"))
            self.__keyLineEdit.setText(self.__infoSettings.value("info/key"))

        else:
            if iniFile.open(QFile.ReadWrite):
                self.__infoSettings = QSettings("info.ini",
                                                QSettings.IniFormat)

                self.__infoSettings.beginGroup("info")

                self.__infoSettings.setValue("appid", "00000000000000000")
                self.__infoSettings.setValue("key", "00000000000000000")
                self.__infoSettings.endGroup()

                iniFile.close()

                self.__appIDLineEdit.setText("00000000000000000")
                self.__keyLineEdit.setText("00000000000000000")

    def __ConfigureHistoryFile(self):
        self.__historyFile = QFile("history.txt")
        if self.__historyFile.open(QFile.ReadWrite or QFile.Append):
            self.__historyFileStream = QTextStream(self.__historyFile)

        else:
            self.__statusBar.showMessage(
                self.__GetCurrentTime() + " - History fie create failed!",
                2000)

    def __GetCurrentTime(self, format="hh:mm:ss"):
        return self.__time.currentDateTime().toString(format)

    def __GetSign(self, srcData, appid, key):
        sign = appid + srcData + self.__salt + key
        mymd5 = hashlib.md5(sign.encode()).hexdigest()
        return mymd5

    def __on_triggered_openFileAction(self):
        filePath = QFileDialog.getOpenFileName(self, "open",
                                               self.__currentPath, "* txt")
        if filePath[0].strip():
            file = QFile(filePath[0])
            if file.open(QFile.ReadOnly):

                readData = str(file.readAll())
                fileData = readData[2:readData.__len__() - 1].replace(
                    r"\r\n", r" ")
                self.__srcTextEdit.insertPlainText(fileData)
            else:
                self.__statusBar.showMessage(
                    self.__GetCurrentTime() + " - open file failed!", 2000)
        else:
            self.__statusBar.showMessage(
                self.__GetCurrentTime() + " - Choose file failed!", 2000)
            return

    def __on_triggered_saveFileAction(self):
        self.__historyFile.close()
        self.__historyFile.open(QFile.ReadWrite or QFile.Append)

        self.__statusBar.showMessage(
            self.__GetCurrentTime() + " - Save file successful!", 2000)

    def __on_triggered_translateAction(self):
        srcData = self.__srcTextEdit.toPlainText()
        if srcData.strip():
            self.__translateTextEdit.clear()
            self.__translateTextEdit.document().clear()

            dstData = srcData.replace("\n", " ")

        else:
            self.__statusBar.showMessage(
                self.__GetCurrentTime() + " - There is no data!", 2000)
            return

        myurl = "/api/trans/vip/translate"

        appid = self.__appIDLineEdit.text()
        key = self.__keyLineEdit.text()
        strFrom = self.__fromComboBox.currentData()
        strTo = self.__toComboBox.currentData()
        mymd5 = self.__GetSign(dstData, appid, key)

        myurl = myurl + "?appid=" + appid + "&q=" + urllib.parse.quote(
            srcData
        ) + "&from=" + strFrom + "&to=" + strTo + "&salt=" + self.__salt + "&sign=" + mymd5

        httpClient = http.client.HTTPConnection("api.fanyi.baidu.com")
        httpClient.request("GET", myurl)

        response = httpClient.getresponse()
        jsonResponse = response.read().decode("utf-8")

        js = json.loads(jsonResponse)
        translate = str(js["trans_result"][0]["dst"])

        self.__translateTextEdit.insertPlainText(translate)
        self.__historyFileStream << translate + "\r\n"

        self.__statusBar.showMessage(
            self.__GetCurrentTime() + " - Translate successful!", 2000)

    def __on_triggered_clearAction(self):
        self.__srcTextEdit.clear()
        self.__translateTextEdit.clear()

        self.__statusBar.showMessage(
            self.__GetCurrentTime() + " - Clear successful!", 2000)

    def __on_returnPressed_appIDLineEdit(self):
        appid = self.__appIDLineEdit.text()
        if not appid.strip():
            self.__statusBar.showMessage(
                self.__GetCurrentTime() + " - There is no appid!", 2000)
            return

        self.__infoSettings.beginGroup("info")
        self.__infoSettings.setValue("appid", appid)
        self.__infoSettings.endGroup()
        self.__statusBar.showMessage(
            self.__GetCurrentTime() + " - Enter appid successful!", 2000)

    def __on_returnPressed_keyLineEdit(self):
        key = self.__keyLineEdit.text()
        if not key.strip():
            self.__statusBar.showMessage(
                self.__GetCurrentTime() + " - There is no key!", 2000)
            return

        self.__infoSettings.beginGroup("info")
        self.__infoSettings.setValue("key", key)
        self.__infoSettings.endGroup()
        self.__statusBar.showMessage(
            self.__GetCurrentTime() + " - Enter key successful!", 2000)
Exemple #19
0
class LoadDatasetDialog(QDialog):
    dataset_loaded = Signal(GrainSizeDataset)

    def __init__(self, parent=None):
        super().__init__(parent=parent, f=Qt.Window)
        self.setWindowTitle(self.tr("Dataset Loader"))
        self.initialize_ui()
        self.file_dialog = QFileDialog(parent=self)
        self.filename = None  # type: str
        self.workbook = None  # type: typing.Union[openpyxl.Workbook, xlrd.Book]
        self.dataset = None  # type: GrainSizeDataset

    def initialize_ui(self):
        self.setAttribute(Qt.WA_StyledBackground, True)
        self.main_layout = QGridLayout(self)

        self.filename_label = QLabel(self.tr("Filename:"))
        self.filename_display = QLabel(self.tr("Unknown"))
        self.main_layout.addWidget(self.filename_label, 0, 0)
        self.main_layout.addWidget(self.filename_display, 0, 1, 1, 2)
        self.select_button = QPushButton(qta.icon("mdi.file-table"),
                                         self.tr("Select"))
        self.select_button.clicked.connect(self.on_select_clicked)
        self.main_layout.addWidget(self.select_button, 0, 3)
        self.sheet_label = QLabel(self.tr("Sheet:"))
        self.sheet_combo_box = QComboBox()
        self.sheet_combo_box.addItem(self.tr("Empty"))
        self.main_layout.addWidget(self.sheet_label, 1, 0)
        self.main_layout.addWidget(self.sheet_combo_box, 1, 1, 1, 3)

        self.classes_row_label = QLabel(
            self.tr("Row With Grain-size Classes:"))
        self.classes_row_input = QSpinBox()
        self.classes_row_input.setRange(1, 999)
        self.main_layout.addWidget(self.classes_row_label, 2, 0, 1, 3)
        self.main_layout.addWidget(self.classes_row_input, 2, 3)
        self.sample_names_column_label = QLabel(
            self.tr("Column With Sample Names:"))
        self.sample_names_column_input = QSpinBox()
        self.sample_names_column_input.setRange(1, 999)
        self.main_layout.addWidget(self.sample_names_column_label, 3, 0, 1, 3)
        self.main_layout.addWidget(self.sample_names_column_input, 3, 3)
        self.distribution_start_row_label = QLabel(
            self.tr("Distribution Start Row:"))
        self.distribution_start_row_input = QSpinBox()
        self.distribution_start_row_input.setRange(2, 999999)
        self.main_layout.addWidget(self.distribution_start_row_label, 4, 0, 1,
                                   3)
        self.main_layout.addWidget(self.distribution_start_row_input, 4, 3)
        self.distribution_start_column_label = QLabel(
            self.tr("Distribution Start Column:"))
        self.distribution_start_column_input = QSpinBox()
        self.distribution_start_column_input.setRange(2, 999999)
        self.main_layout.addWidget(self.distribution_start_column_label, 5, 0,
                                   1, 3)
        self.main_layout.addWidget(self.distribution_start_column_input, 5, 3)

        self.try_load_button = QPushButton(qta.icon("fa5s.book-reader"),
                                           self.tr("Try Load"))
        self.try_load_button.clicked.connect(self.on_try_load_clicked)
        self.try_load_button.setEnabled(False)
        self.main_layout.addWidget(self.try_load_button, 6, 0, 1, 4)

        self.info_display = QTextEdit()
        self.info_display.setReadOnly(True)
        self.main_layout.addWidget(self.info_display, 7, 0, 1, 4)

    @property
    def sheet_index(self) -> int:
        sheet_index = self.sheet_combo_box.currentIndex()
        return sheet_index

    @property
    def sheet_name(self) -> str:
        sheet_name = self.sheet_combo_box.currentText()
        return sheet_name

    @property
    def data_layout(self):
        classes_row = self.classes_row_input.value() - 1
        sample_names_column = self.sample_names_column_input.value() - 1
        distribution_start_row = self.distribution_start_row_input.value() - 1
        distribution_start_column = self.distribution_start_column_input.value(
        ) - 1
        try:
            layout = DataLayoutSetting(
                classes_row=classes_row,
                sample_names_column=sample_names_column,
                distribution_start_row=distribution_start_row,
                distribution_start_column=distribution_start_column)
            return layout
        except DataLayoutError as e:
            self.show_error(
                f"The current setting is invalid.\n    {e.__str__()}")
            return None

    def on_select_clicked(self):
        filename, _ = self.file_dialog.getOpenFileName(\
            self, self.tr("Select a file"), None,
            self.tr("Excel (*.xlsx);;97-2003 Excel (*.xls);;CSV (*.csv)"))
        if filename is None or filename == "":
            self.show_warning(f"No file was selected.")
            return
        self.filename = filename
        file_type = get_type_by_name(filename)
        self.show_info(f"Data file [{file_type}] was selected: [{filename}].")
        if file_type == ReadFileType.CSV:
            sheet_names = [os.path.basename(filename)]
        elif file_type == ReadFileType.XLS:
            self.workbook = xlrd.open_workbook(filename)
            sheet_names = self.workbook.sheet_names()
        elif file_type == ReadFileType.XLSX:
            self.workbook = openpyxl.load_workbook(filename,
                                                   read_only=True,
                                                   data_only=True)
            sheet_names = self.workbook.sheetnames
        else:
            raise NotImplementedError(file_type)

        if file_type != ReadFileType.CSV:
            self.show_info(
                f"It has {len(sheet_names)} sheet(s), please select one.")
        self.filename_display.setText(os.path.basename(filename))
        self.sheet_combo_box.clear()
        self.sheet_combo_box.addItems(sheet_names)
        self.try_load_button.setEnabled(True)

    def show_info(self, text: str):
        self.info_display.append(
            f'<font size="3" color="black">[{datetime.datetime.now()}] - {text}</font>\n'
        )

    def show_warning(self, text: str):
        self.info_display.append(
            f'<font size="3" color="#fed71a">[{datetime.datetime.now()}] - {text}</font>\n'
        )

    def show_error(self, text: str):
        self.info_display.append(
            f'<font size="3" color="#f03752">[{datetime.datetime.now()}] - {text}</font>\n'
        )

    def show_success(self, text: str):
        self.info_display.append(
            f'<font size="3" color="#2c9678">[{datetime.datetime.now()}] - {text}</font>\n'
        )

    def on_try_load_clicked(self):
        try:
            self.try_load()
        except Exception as e:
            self.show_error(f"Error raised while loading.\n    {e.__str__()}")

    def try_load(self):
        layout = self.data_layout
        if layout is None:
            return
        assert self.filename is not None
        file_type = get_type_by_name(self.filename)
        self.show_info("Start to load raw data from the file.")
        QCoreApplication.processEvents()
        if file_type == ReadFileType.CSV:
            try:
                with open(self.filename, encoding="utf-8") as f:
                    reader = csv.reader(f)
                    raw_data = [row for row in reader]
            except Exception as e:
                self.show_error(
                    f"Exception rasised when reading {file_type} file.\n    {e.__str__()}"
                )
                return
        elif file_type == ReadFileType.XLS:
            sheet = self.workbook.sheet_by_index(self.sheet_index)
            raw_data = [sheet.row_values(row) for row in range(sheet.nrows)]
        elif file_type == ReadFileType.XLSX:
            sheet = self.workbook[self.sheet_name]
            raw_data = [[value for value in row] for row in sheet.values]
        else:
            raise NotImplementedError(file_type)
        self.show_success(f"Raw data has been loaded from the file.")
        QCoreApplication.processEvents()
        try:
            classes_μm = np.array(raw_data[layout.classes_row]
                                  [layout.distribution_start_column:],
                                  dtype=np.float64)
        except Exception as e:
            self.show_error(
                f"Can not convert the row of classes to a numerical array, it may contains invalid values (e.g. text or empty cell).\n    {e.__str__()}"
            )
            return
        self.show_info(
            f"Grain-size classes in μm: [{','.join([f'{x: 0.4f}' for x in classes_μm[:3]])}, ...,{','.join([f'{x: 0.4f}' for x in classes_μm[-3:]])}]."
        )
        GrainSizeDataset.validate_classes_μm(classes_μm)
        self.show_success("Validation of grain-size classes passed.")
        QCoreApplication.processEvents()

        names = []
        distributions = []
        i = layout.distribution_start_row + 1
        for row_values in raw_data[layout.distribution_start_row:]:
            # check if it's a empty row, i.e. the values all are empty string
            is_empty_row = True
            for distribution_value in row_values[layout.
                                                 distribution_start_column:]:
                if distribution_value != "" and distribution_value is not None:
                    is_empty_row = False
                    break
            # if it's a empty row, jump this row to process the next one
            if is_empty_row:
                self.show_warning(f"This row is empty, jump to next.")
                continue

            sample_name = row_values[layout.sample_name_column]
            self.show_info(
                f"Processing the {i} row, sample name is [{sample_name}].")
            if sample_name is None:
                sample_name = "NONE"
                self.show_warning(
                    f"The sample name is invalid, use 'NONE' instead.")
            # users may use pure number as the sample name
            elif type(sample_name) != str:
                sample_name = str(sample_name)
                self.show_warning(
                    f"The sample name is not text (may be a number), convert it to text."
                )
            elif sample_name == "":
                sample_name = "EMPTY"
                self.show_warning(
                    f"The sample name is a empty text, use 'EMPTY' instead.")

            try:
                distribution = np.array(
                    row_values[layout.distribution_start_column:],
                    dtype=np.float64)
            except Exception as e:
                self.show_error(
                    f"Can not convert the distribution values at row [{i}] to a numerical array, it may contains invalid values (e.g. text or empty cell).\n    {e.__str__()}"
                )
                return
            try:
                GrainSizeDataset.validate_distribution(distribution)
            except Exception as e:
                self.show_error(
                    f"Validation of the distribution array of sample [{sample_name}] did not pass.\n    {e.__str__()}"
                )
                return
            names.append(sample_name)
            distributions.append(distribution)
            i += 1
            self.show_info(f"Validation of sample {sample_name} passed.")
            QCoreApplication.processEvents()

        self.show_success(
            "All data has been convert to array. Next to do the final validation."
        )
        dataset = GrainSizeDataset()
        dataset.add_batch(classes_μm, names, distributions)
        self.dataset = dataset
        self.show_success(
            "Dataset has been loaded successfully, you can close this dialog now."
        )
        self.dataset_loaded.emit(dataset)
Exemple #20
0
class assSelect(QDialog):
    assSummary = Signal(list)

    def __init__(self):
        super().__init__()
        self.subDict = {
            '': {
                'Fontname': '',
                'Fontsize': '',
                'PrimaryColour': '',
                'SecondaryColour': '',
                'OutlineColour': '',
                'BackColour': '',
                'Bold': '',
                'Italic': '',
                'Underline': '',
                'StrikeOut': '',
                'ScaleX': '',
                'ScaleY': '',
                'Spacing': '',
                'Angle': '',
                'BorderStyle': '',
                'Outline': '',
                'Shadow': '',
                'Alignment': '',
                'MarginL': '',
                'MarginR': '',
                'MarginV': '',
                'Encoding': '',
                'Tableview': [],
                'Events': []
            }
        }
        self.resize(950, 800)
        self.setWindowTitle('选择要导入的ass字幕轨道')
        layout = QGridLayout()
        self.setLayout(layout)
        layout.addWidget(QLabel('检测到字幕样式:'), 0, 0, 1, 1)
        layout.addWidget(QLabel(''), 0, 1, 1, 1)
        self.subCombox = QComboBox()
        self.subCombox.currentTextChanged.connect(self.selectChange)
        layout.addWidget(self.subCombox, 0, 2, 1, 1)
        self.subTable = QTableWidget()
        self.subTable.setEditTriggers(QAbstractItemView.NoEditTriggers)
        layout.addWidget(self.subTable, 1, 0, 6, 3)
        self.confirm = QPushButton('导入')
        self.confirm.clicked.connect(self.sendSub)
        layout.addWidget(self.confirm, 7, 0, 1, 1)
        self.confirmStyle = QPushButton('导入样式')
        self.confirmStyle.clicked.connect(self.sendSubStyle)
        layout.addWidget(self.confirmStyle, 7, 1, 1, 1)
        self.cancel = QPushButton('取消')
        self.cancel.clicked.connect(self.hide)
        layout.addWidget(self.cancel, 7, 2, 1, 1)

    def setDefault(self, subtitlePath='', index=0):
        if subtitlePath:
            self.assCheck(subtitlePath)
            self.index = index

    def selectChange(self, styleName):
        self.subTable.clear()
        self.subTable.setRowCount(
            len(self.subDict[styleName]) +
            len(self.subDict[styleName]['Tableview']) - 2)
        self.subTable.setColumnCount(4)
        for col in range(3):
            self.subTable.setColumnWidth(col, 160)
        self.subTable.setColumnWidth(3, 350)
        y = 0
        for k, v in self.subDict[styleName].items():
            if k not in ['Tableview', 'Events']:
                self.subTable.setItem(y, 0, QTableWidgetItem(k))
                self.subTable.setItem(y, 1, QTableWidgetItem(v))
                y += 1
            elif k == 'Tableview':
                preConflict = False  # 上一条字幕时轴有重叠
                for cnt, line in enumerate(v):
                    nextConflict = False
                    start = calSubTime(line[0])
                    end = calSubTime(line[1])
                    if cnt < len(v) - 1:
                        nextStart = calSubTime(v[cnt + 1][0])
                        if end > nextStart:
                            nextConflict = True
                        else:
                            nextConflict = False
                    delta = end - start
                    if delta < 500 or delta > 8000:  # 持续时间小于500ms或大于8s
                        deltaError = 2
                    elif delta > 4500:  # 持续时间大于4.5s且小于8s
                        deltaError = 1
                    else:
                        deltaError = 0
                    s, ms = divmod(delta, 1000)
                    ms = ('%03d' % ms)[:2]
                    delta = '持续 %s.%ss' % (s, ms)
                    self.subTable.setItem(y, 0,
                                          QTableWidgetItem(line[0]))  # 开始时间
                    if preConflict:
                        self.subTable.item(y, 0).setBackground(
                            QColor('#B22222'))  # 红色警告
                    self.subTable.setItem(y, 1,
                                          QTableWidgetItem(line[1]))  # 结束时间
                    if nextConflict:
                        self.subTable.item(y, 1).setBackground(
                            QColor('#B22222'))  # 红色警告
                    self.subTable.setItem(y, 2,
                                          QTableWidgetItem(delta))  # 持续时间
                    if deltaError == 2:
                        self.subTable.item(y, 2).setBackground(
                            QColor('#B22222'))  # 红色警告
                    elif deltaError == 1:
                        self.subTable.item(y, 2).setBackground(
                            QColor('#FA8072'))  # 橙色警告
                    self.subTable.setItem(y, 3,
                                          QTableWidgetItem(line[2]))  # 字幕文本
                    y += 1
                    preConflict = nextConflict  # 将重叠信号传递给下一条轴

    def sendSub(self):
        self.assSummary.emit([
            self.index,
            self.subCombox.currentText(),
            self.subDict[self.subCombox.currentText()]
        ])
        self.hide()

    def sendSubStyle(self):
        subData = self.subDict[self.subCombox.currentText()]
        subData['Events'] = {}
        self.assSummary.emit(
            [self.index, self.subCombox.currentText(), subData])
        self.hide()

    def assCheck(self, subtitlePath):
        self.subDict = {
            '': {
                'Fontname': '',
                'Fontsize': '',
                'PrimaryColour': '',
                'SecondaryColour': '',
                'OutlineColour': '',
                'BackColour': '',
                'Bold': '',
                'Italic': '',
                'Underline': '',
                'StrikeOut': '',
                'ScaleX': '',
                'ScaleY': '',
                'Spacing': '',
                'Angle': '',
                'BorderStyle': '',
                'Outline': '',
                'Shadow': '',
                'Alignment': '',
                'MarginL': '',
                'MarginR': '',
                'MarginV': '',
                'Encoding': '',
                'Tableview': [],
                'Events': {}
            }
        }
        ass = codecs.open(subtitlePath, 'r', 'utf_8_sig')
        f = ass.readlines()
        ass.close()
        V4Token = False
        styleFormat = []
        styles = []
        eventToken = False
        eventFormat = []
        events = []
        for line in f:
            if '[V4+ Styles]' in line:
                V4Token = True
            elif V4Token and 'Format:' in line:
                styleFormat = line.replace(' ',
                                           '').strip().split(':')[1].split(',')
            elif V4Token and 'Style:' in line and styleFormat:
                styles.append(line.strip().split(':')[1].split(','))
            elif '[Events]' in line:
                eventToken = True
                V4Token = False
            elif eventToken and 'Format:' in line:
                eventFormat = line.strip().split(':')[1].split(',')
            elif eventToken and 'Comment:' in line and eventFormat:
                events.append(line.strip().split('Comment:')[1].split(
                    ',',
                    len(eventFormat) - 1))
            elif eventToken and 'Dialogue:' in line and eventFormat:
                events.append(line.strip().split('Dialogue:')[1].split(
                    ',',
                    len(eventFormat) - 1))

        for cnt, _format in enumerate(eventFormat):
            _format = _format.replace(' ', '')
            if _format == 'Start':
                Start = cnt
            elif _format == 'End':
                End = cnt
            elif _format == 'Style':
                Style = cnt
            elif _format == 'Text':
                Text = cnt

        for style in styles:
            styleName = style[0]
            self.subDict[styleName] = {
                'Fontname': '',
                'Fontsize': '',
                'PrimaryColour': '',
                'SecondaryColour': '',
                'OutlineColour': '',
                'BackColour': '',
                'Bold': '',
                'Italic': '',
                'Underline': '',
                'StrikeOut': '',
                'ScaleX': '',
                'ScaleY': '',
                'Spacing': '',
                'Angle': '',
                'BorderStyle': '',
                'Outline': '',
                'Shadow': '',
                'Alignment': '',
                'MarginL': '',
                'MarginR': '',
                'MarginV': '',
                'Encoding': '',
                'Tableview': [],
                'Events': {}
            }
            for cnt, _format in enumerate(styleFormat):
                if _format in self.subDict[styleName]:
                    self.subDict[styleName][_format] = style[cnt]
            for line in events:
                if styleName.replace(' ', '') == line[Style].replace(' ', ''):
                    start = calSubTime(line[Start]) // 10 * 10
                    delta = calSubTime(line[End]) - start // 10 * 10
                    self.subDict[styleName]['Tableview'].append(
                        [line[Start], line[End], line[Text]])
                    self.subDict[styleName]['Events'][start] = [
                        delta, line[Text]
                    ]

        self.subCombox.clear()
        combox = []
        for style in self.subDict.keys():
            if style:
                combox.append(style)
        self.subCombox.addItems(combox)
Exemple #21
0
class MainPage(qt.QWidget):
    def __init__(self, db_session, **kwargs):
        super(MainPage, self).__init__()
        self.db_session = db_session

        # Create central widget that will contain everything
        # (Bit odd design decision from QT, I would say, to separate widgets and
        # layouts. Now we need to have central _widget_ to contain layout to contain
        # widgets)
        central_widget = QWidget()
        central_widget.setStyleSheet("background: white;")

        # Add central widget to main window

        # Create main grid layout that will organize everything
        main_grid = qt.QGridLayout(central_widget)

        self.setLayout(main_grid)

        main_grid.setSpacing(0)
        main_grid.setMargin(0)

        # Yet again interesting design decision. On QT you cannot set style for layout.
        # Thus, we create widget that will contain layout and now we can set style for the widget.

        widget_that_would_not_be_needed_if_qt_would_not_be_so_stupid = QWidget(
        )

        widget_that_would_not_be_needed_if_qt_would_not_be_so_stupid.setStyleSheet(
            '''
            QObject { background: #FF005AA1; }
            QPushButton {
                background: #FF005AA1;
                color: white;
                text-align: center;
                border: none;
                font-weight: 500;
                font-size: 15px;
                height: 48px;
                width: 120px;
            }
            QPushButton:hover {
               background-color: #FF014a82;
            }
            QPushButton:checked {
            background: #FF01508c;
            }
            QPushButton:pressed {
                color: #FF005AA1;
                background: white;
            }
            QWidget{
                background: #FF005AA1;
            }
            ''')

        # On left side we will have some (or at least one) button
        left_side_buttons = QVBoxLayout(
            widget_that_would_not_be_needed_if_qt_would_not_be_so_stupid)

        left_side_buttons.setSpacing(0)
        left_side_buttons.setMargin(0)

        # And add it to main box the left most cell
        main_grid.addWidget(
            widget_that_would_not_be_needed_if_qt_would_not_be_so_stupid, 0, 0)

        main_grid.setRowStretch(0, 1)

        # Column 0 must not stretch
        main_grid.setColumnStretch(0, 0)

        # Column 1 must stretch
        main_grid.setColumnStretch(1, 1)

        # Separator line
        line = qt.QFrame()
        line.setFrameShape(qt.QFrame.HLine)
        line.setFrameShadow(qt.QFrame.Sunken)

        # Add scan button
        self.scan_button = qt.QPushButton("Luo laskut")
        self.scan_button.clicked.connect(self.luo_lasku_pressed_handler)

        # Add widgets to container
        left_side_buttons.addWidget(self.scan_button)

        # Add separator line
        line = qt.QFrame()
        line.setFrameShape(qt.QFrame.HLine)
        line.setFrameShadow(qt.QFrame.Sunken)

        left_side_buttons.addWidget(line)

        # Add stretch that will stretch to fill rest of the space
        left_side_buttons.addStretch()

        self.list_of_visits = qt.QTreeWidget()

        self.list_of_visits.setColumnCount(3)
        self.list_of_visits.setHeaderLabels(
            ["Käyntipäivä", "Nimi", "Terapian laji", "Lisätiedot"])
        self.list_of_visits.setSortingEnabled(True)

        # Allow multiselect
        self.list_of_visits.setSelectionMode(
            qt.QAbstractItemView.ExtendedSelection)

        third_stupid_widget = QWidget()

        right_side_layout = qt.QVBoxLayout(third_stupid_widget)

        main_grid.addWidget(third_stupid_widget, 0, 1)

        new_visit_date = QDateEdit(datetime.datetime.now())
        new_visit_date.setCalendarPopup(True)
        new_visit_date.setDisplayFormat('dd.MM.yyyy')
        self.new_visit_customers_combobox = QComboBox()
        new_visit_type = QLineEdit()
        new_visit_type.setText("Terapia")

        self.update_page()

        self.new_visit_button = qt.QPushButton("Lisää käynti")

        second_stupid_widget = QWidget()
        new_visit_layout = QHBoxLayout(second_stupid_widget)
        right_side_layout.addWidget(second_stupid_widget)
        new_visit_layout.addWidget(new_visit_date)
        new_visit_layout.addWidget(self.new_visit_customers_combobox)
        new_visit_layout.addWidget(new_visit_type)
        new_visit_layout.addWidget(self.new_visit_button)

        right_side_layout.addWidget(self.list_of_visits)

        # Add properties view
        # main_grid.addWidget(qt.QPlainTextEdit(), 0, 2)

        def new_visit_handler():
            for _customer in self.customers:
                if _customer.name == self.new_visit_customers_combobox.currentText(
                ):
                    _customer.new_visit(
                        cost=_customer.hour_price,
                        visit_length_min=45,
                        visit_date=new_visit_date.date().toPython(),
                        visit_type=new_visit_type.text(),
                    )
                    self.update_page()
                    db_session.commit()

        self.new_visit_button.clicked.connect(new_visit_handler)
        # create context menu
        self.popMenu = qt.QMenu(self)
        self.popMenu.addAction(
            qt.QAction('Poista käynti',
                       self.list_of_visits,
                       triggered=self._delete_visit))

        # set button context menu policy
        self.list_of_visits.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.list_of_visits.customContextMenuRequested.connect(
            self.on_context_menu)

    def on_context_menu(self, point):
        # show context menu
        self.popMenu.exec_(QtGui.QCursor.pos())

    def luo_lasku_pressed_handler(self):

        import pdf_writer
        import therapist

        billed_customers = []
        customers = self.db_session.query(customer.Customer).all()
        therapist = self.db_session.query(therapist.Therapist).first()
        for cust in customers:
            if cust.unbilled_visits():
                billed_customers.append(cust)
                pdf_writer.write_invoice(therapist, cust)

        if billed_customers:
            pdf_writer.write_tilitys(therapist, billed_customers)

        for cust in customers:
            for _visit in cust.unbilled_visits():
                _visit.billed = datetime.date.today()

        # Commit billed visits
        self.db_session.commit()
        self.update_page()

    def update_page(self):
        self.list_of_visits.clear()
        self.new_visit_customers_combobox.clear()
        self.customers = self.db_session.query(customer.Customer).group_by(
            customer.Customer.name)

        for _customer in self.customers:
            self.add_visits_for_customer(_customer)
            self.new_visit_customers_combobox.addItem(_customer.name)

    def add_visits_for_customer(self, _customer):

        for _visit in _customer.unbilled_visits():
            cell_objects = {
                0: 'visit_date',
                1: 'NO_EDIT',
                2: 'visit_type',
                3: 'notes'
            }

            MyTreeWidget(self.list_of_visits, [
                _visit.visit_date.strftime("%d.%m.%Y"),
                _customer.name,
                _visit.visit_type,
                _visit.notes,
            ],
                         cell_objects=cell_objects,
                         db_session=self.db_session,
                         id=_visit.id,
                         class_item=visit.Visit,
                         class_instance=_visit)

    def _delete_visit(self):
        for _visit in self.list_of_visits.selectedItems():
            _visit.delete()

        self.update_page()
Exemple #22
0
class ViewStudentListToolbar(QToolBar):
    def __init__(self):
        """
        Toolbar for the students list side panel tab
        """
        QToolBar.__init__(self)
        self.current_group: str = None
        self.__config_mode = False

        # Widgets
        self.combo_groups = QComboBox()
        self.create_field = ViewAddLine()
        self.config_action_menu = ViewMenuButton(
            "Actions", self.create_field.show_field,
            [(tr("grp_action_import_csv"), "import_csv"),
             (tr("grp_action_create_group"), "create_group"),
             (tr("grp_action_del_group"), "delete_group"), 'sep',
             (tr("grp_action_create_student"), "create_student"),
             (tr("grp_action_del_student"), "killstudent"), 'sep',
             (tr("grp_action_auto_placement"), "auto_place")])

        self.sort_actions_menu = ViewMenuButton(
            "Tri", self.create_field.show_field, [
                (tr("grp_action_sort_asc"), "sort_asc"),
                (tr("grp_action_sort_desc"), "sort_desc"),
                (tr("grp_action_sort_by_place") + " Z", "sort_desks_Z"),
                (tr("grp_action_sort_by_place") + " 2", "sort_desks_2"),
                (tr("grp_action_sort_by_place") + " U", "sort_desks_U"),
            ])

        # Signals
        self.sig_combo_changed: Signal = None
        self.combo_groups.activated.connect(self.on_group_changed)

        # Layout
        self.a_combo = self.addWidget(self.combo_groups)
        self.a_conf_menu = self.addWidget(self.config_action_menu)
        self.a_sort_menu = self.addWidget(self.sort_actions_menu)
        self.addWidget(self.create_field)

        self.__set_style()

    def __set_style(self) -> None:
        """
        Inits the stylesheet of this widget
        """
        # Toolbar
        self.setStyleSheet(get_stylesheet("toolbar"))

    def edit_student(self, student_id: int, student_data: str) -> None:
        """
        Shows the creation field, with the student data (last name + first name) that can be edited.

        :param student_id: student id
        :param student_data: student last name + first name
        """
        if self.__config_mode:
            self.create_field.show_field(str(student_id), student_data)

    def switch_config_mode(self, is_config_mode: bool) -> None:
        self.__config_mode = is_config_mode

        self.a_combo.setVisible(self.__config_mode)
        self.a_conf_menu.setVisible(self.__config_mode)
        self.a_sort_menu.setVisible(not self.__config_mode)

    def on_group_changed(self) -> None:
        """
        Triggered when the combo selection changed, emits the signal if the selected group was updated.
        """
        text = self.combo_groups.currentText()

        if text and text != self.current_group:
            self.current_group = text
            self.sig_combo_changed.emit(text)

    def init_groups(self, groups: list) -> None:
        """
        Resets the combo box before adding all the groups to the combo.

        :param groups: groups names list
        :type groups: list
        """
        self.reset_groups()
        self.__add_groups(groups)
        self.repaint()

    def __add_groups(self, list_groups: list) -> None:
        """
        Adds the list of all specified groups inside the combo.

        :param list_groups: All the groups to add
        :type list_groups: list
        """
        self.combo_groups.addItems(list_groups)

    def reset_groups(self) -> None:
        """
        Resets the groups combo (clears it)
        """
        self.combo_groups.clear()
Exemple #23
0
class View(QMainWindow):

    current_mac = Signal(str)

    def __init__(self, model, pacer):
        super().__init__()

        self.setWindowTitle("OpenHRV")
        self.setWindowIcon(QIcon("./logo.png"))
        self.setGeometry(50, 50, 1750, 750)

        self.model = model
        self.pacer = pacer
        self.threadpool = QThreadPool()

        self.scanner = SensorScanner()
        self.scanner.mac_update.connect(self.model.set_mac_addresses)

        self.sensor = SensorClient()
        self.current_mac.connect(self.sensor.start)
        self.sensor.ibi_update.connect(self.model.set_ibis_buffer)

        self.ibis_plot = pg.PlotWidget()
        self.ibis_plot.setBackground("w")
        self.ibis_plot.setLabel("left", "Inter-Beat-Interval (msec)",
                                **{"font-size": "25px"})
        self.ibis_plot.setLabel("bottom", "Seconds", **{"font-size": "25px"})
        self.ibis_plot.showGrid(y=True)
        self.ibis_plot.setYRange(300, 1500, padding=0)
        self.ibis_plot.setMouseEnabled(x=False, y=False)

        self.ibis_signal = pg.PlotCurveItem()
        pen = pg.mkPen(color=(0, 191, 255), width=7.5)
        self.ibis_signal.setPen(pen)
        self.ibis_signal.setData(self.model.seconds, self.model.ibis_buffer)
        self.ibis_plot.addItem(self.ibis_signal)

        self.pacer_plot = pg.PlotWidget()
        self.pacer_plot.setBackground("w")
        self.pacer_plot.setAspectLocked(lock=True, ratio=1)
        self.pacer_plot.setMouseEnabled(x=False, y=False)
        self.pacer_plot.disableAutoRange()
        self.pacer_plot.setXRange(-1, 1, padding=0)
        self.pacer_plot.setYRange(-1, 1, padding=0)
        self.pacer_plot.hideAxis("left")
        self.pacer_plot.hideAxis("bottom")

        self.pacer_disc = pg.PlotCurveItem()
        brush = pg.mkBrush(color=(135, 206, 250))
        self.pacer_disc.setBrush(brush)
        self.pacer_disc.setFillLevel(1)
        self.pacer_plot.addItem(self.pacer_disc)

        self.pacer_rate = QSlider(Qt.Horizontal)
        self.pacer_rate.setRange(3, 10)
        self.pacer_rate.valueChanged.connect(self.model.set_breathing_rate)
        self.pacer_rate.setSliderPosition(self.model.breathing_rate)

        self.pacer_label = QLabel(
            f"Breathing Rate: {self.model.breathing_rate}")
        self.pacer_label.setFont(QFont("Arial", 25))

        self.scan_button = QPushButton("Scan")
        self.scan_button.clicked.connect(self.scanner.scan)

        self.mac_menu = QComboBox()

        self.start_button = QPushButton("Start")
        self.start_button.clicked.connect(self.start_sensor)

        self.stop_button = QPushButton("Stop")
        self.stop_button.clicked.connect(self.stop_sensor)

        self.hrv_label = QLabel("Current HRV:")
        self.hrv_label.setFont(QFont("Arial", 25))

        self.hrv_display = QLabel()
        self.hrv_display.setText("0")
        self.hrv_display.setFont(QFont("Arial", 50))

        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)

        self.hlayout0 = QHBoxLayout(self.central_widget)
        self.hlayout1 = QHBoxLayout()
        self.hlayout2 = QHBoxLayout()

        self.vlayout0 = QVBoxLayout()
        self.vlayout1 = QVBoxLayout()

        self.hlayout0.addLayout(self.vlayout0, stretch=75)
        self.hlayout0.addLayout(self.vlayout1, stretch=25)

        self.vlayout0.addWidget(self.ibis_plot)
        self.vlayout0.addLayout(self.hlayout1)
        self.vlayout0.addLayout(self.hlayout2)

        self.hlayout1.addWidget(self.scan_button)
        self.hlayout1.addWidget(self.mac_menu)

        self.hlayout2.addWidget(self.start_button)
        self.hlayout2.addWidget(self.stop_button)
        self.hlayout2.addWidget(self.hrv_label)
        self.hlayout2.addWidget(self.hrv_display)

        self.vlayout1.addWidget(self.pacer_plot, stretch=70)
        self.vlayout1.addWidget(self.pacer_rate, stretch=15)
        self.vlayout1.addWidget(self.pacer_label, stretch=15)

        self.model.ibis_buffer_update.connect(self.plot_ibis)
        self.model.ibis_buffer_update.connect(self.compute_local_hrv)
        self.model.hrv_buffer_update.connect(self.plot_local_hrv)
        self.model.mac_addresses_update.connect(self.list_macs)
        self.model.pacer_disk_update.connect(self.plot_pacer_disk)
        self.model.pacer_rate_update.connect(self.update_pacer_label)

        self.pacer.start()

        self.scanner_thread = QThread(self)
        self.scanner.moveToThread(self.scanner_thread)
        self.scanner_thread.start()

        self.sensor_thread = QThread(self)
        self.sensor.moveToThread(self.sensor_thread)
        self.sensor_thread.start()

    def start_sensor(self):
        if self.sensor.loop.is_running():
            print("Client already running.")
            return
        mac = self.mac_menu.currentText()
        # TODO: return in case of invalid mac
        self.current_mac.emit(mac)  # starts sensor

    def stop_sensor(self):
        if not self.sensor.loop.is_running():
            print("No client running.")
            return
        self.sensor.stop()

    def compute_local_hrv(self, ibis):  # TODO: move to model

        current_ibi_phase = np.sign(
            ibis[-1] -
            ibis[-2])  # 1: IBI rises, -1: IBI falls, 0: IBI constant
        if current_ibi_phase == 0:
            return
        if current_ibi_phase != self.model.last_ibi_phase:

            current_ibi_extreme = ibis[-2]
            local_hrv = abs(self.model.last_ibi_extreme - current_ibi_extreme)

            # potentially enforce constraints on local power here
            updated_hrv_buffer = self.model.hrv_buffer  # copy avoids emission of model.hrv_buffer_update
            updated_hrv_buffer = np.roll(updated_hrv_buffer, -1)
            updated_hrv_buffer[-1] = local_hrv
            self.model.hrv_buffer = updated_hrv_buffer

            print(f"Local hrv: {local_hrv}!")

            self.model.last_ibi_extreme = current_ibi_extreme
            self.model.last_ibi_phase = current_ibi_phase

    def plot_ibis(self, ibis):
        self.ibis_signal.setData(self.model.seconds, ibis)

    def plot_local_hrv(self, hrv):
        self.hrv_display.setText(str(hrv[-1]))

    def list_macs(self, macs):
        self.mac_menu.clear()
        self.mac_menu.addItems(macs)

    def plot_pacer_disk(self, coordinates):
        self.pacer_disc.setData(*coordinates)

    def update_pacer_label(self, rate):
        self.pacer_label.setText(f"Breathing Rate: {rate}")
Exemple #24
0
Fichier : app.py Projet : jkjh8/lmd
class Main(QMainWindow):
    send = Signal()
    play = Signal(str, int)
    stop = Signal()
    get = Signal()
    channelIdx = Signal(int)

    def __init__(self):
        super().__init__()
        self.setWindowTitle('Test Window')
        self.setGeometry(200, 300, 400, 200)
        # self.TcpClient = TcpClient(('127.0.0.1', 10000))

        # self.TcpClient.start()

        self.qb = QComboBox(self)
        self.qb.resize(250, 28)
        self.qb.move(10, 11)
        self.btnGet = QPushButton('Get', self)
        self.btnGet.move(260, 10)

        self.qb1 = QComboBox(self)
        self.qb1.resize(100, 28)
        self.qb1.move(10, 50)

        self.channel = [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11],
                        [12, 13], [14, 15]]
        self.qb1.addItems(
            ['1,2', '3,4', '5,6', '7,8', '9,10', '11,12', '13,14', '15,16'])

        self.btnOpen = QPushButton('Open', self)
        self.btnOpen.move(10, 90)
        self.btnPlay = QPushButton('Play', self)
        self.btnPlay.move(110, 90)
        self.btnStop = QPushButton('Stop', self)
        self.btnStop.move(210, 90)

        self.Player = Player()
        self.play.connect(self.Player.play)
        self.stop.connect(self.Player.stop)
        self.btnOpen.clicked.connect(self.showDialog)
        self.btnPlay.clicked.connect(self.playFile)
        self.btnStop.clicked.connect(self.Player.stop)
        self.btnGet.clicked.connect(self.Player.get_devices)

        self.Player.audio_devices.connect(self.updateDevices)
        self.qb.currentIndexChanged.connect(self.changeDevice)
        self.qb1.currentIndexChanged.connect(self.changeChannel)

        self.channelIdx.connect(self.Player.changeChannel)

        self.Player.start()
        self.deviceNum = 0
        self.asioChannel = [0, 1]
        self.show()

    def showDialog(self):
        self.file = QFileDialog.getOpenFileName(self, 'Open file', './')
        print(self.file[0])

    def changeChannel(self):
        idx = self.qb1.currentIndex()
        self.asioChannel = self.channel[idx]
        self.channelIdx.emit(idx)

    def changeDevice(self):
        self.deviceNum = self.qb.currentIndex()

    @Slot(list)
    def updateDevices(self, devices):
        print(devices)
        self.qb.clear()
        self.qb.addItems(devices)

    def click(self):
        self.send.emit()

    def playFile(self):
        print('play')
        if self.file:
            self.play.emit(self.file[0], self.deviceNum)
Exemple #25
0
class MainWindow(QMainWindow):  # Main window
    def __init__(self):
        super().__init__()
        self.setWindowTitle = 'DD烤肉机'
        self.resize(1870, 820)
        self.mainWidget = QWidget()
        self.mainLayout = QGridLayout()  # Grid layout
        self.mainLayout.setSpacing(10)
        self.mainWidget.setLayout(self.mainLayout)
        self.duration = 60000
        self.bitrate = 2000
        self.fps = 60

        self.initProcess = InitProcess()
        self.previewSubtitle = PreviewSubtitle()
        self.dnldWindow = YoutubeDnld()
        self.exportWindow = exportSubtitle()
        self.videoDecoder = VideoDecoder()
        self.exportWindow.exportArgs.connect(self.exportSubtitle)
        self.stack = QStackedWidget()
        self.stack.setFixedWidth(1300)
        self.mainLayout.addWidget(self.stack, 0, 0, 10, 8)
        buttonWidget = QWidget()
        buttonLayout = QHBoxLayout()
        buttonWidget.setLayout(buttonLayout)
        self.playButton = QPushButton('从本地打开')
        self.playButton.clicked.connect(self.open)
        self.playButton.setFixedWidth(400)
        self.playButton.setFixedHeight(75)
        self.dnldButton = QPushButton('Youtube下载器')
        self.dnldButton.clicked.connect(self.popDnld)
        self.dnldButton.setFixedWidth(400)
        self.dnldButton.setFixedHeight(75)
        buttonLayout.addWidget(self.playButton)
        buttonLayout.addWidget(self.dnldButton)
        self.stack.addWidget(buttonWidget)

        self.videoPath = ''
        self.videoWidth = 1920
        self.videoHeight = 1080
        self.globalInterval = 200
        self.setPlayer()
        self.setSubtitle()
        self.setToolBar()
        self.setCentralWidget(self.mainWidget)
        self.playStatus = False
        self.volumeStatus = True
        self.volumeValue = 100
        self.subSelectedTxt = ''
        self.subReplayTime = 1
        self.clipBoard = []
        self.grabKeyboard()
        self.show()

    def setPlayer(self):
        self.playerWidget = QGraphicsVideoItem()
        self.scene = QGraphicsScene()
        self.view = QGraphicsView(self.scene)
        self.view.resize(1280, 730)
        self.scene.addItem(self.playerWidget)
        self.stack.addWidget(self.view)
        self.player = QMediaPlayer(self, QMediaPlayer.VideoSurface)
        self.player.setVideoOutput(self.playerWidget)
        self.view.installEventFilter(self)
        self.view.show()
        self.srtTextItemDict = {0: QGraphicsTextItem(), 1: QGraphicsTextItem(), 2: QGraphicsTextItem(), 3: QGraphicsTextItem(), 4: QGraphicsTextItem()}
        for _, srtTextItem in self.srtTextItemDict.items():
            self.scene.addItem(srtTextItem)

    def setSubtitle(self):
        self.subtitleDict = {x: {-1: [100, '']} for x in range(5)}
        self.subTimer = QTimer()
        self.subTimer.setInterval(100)
        self.subtitle = QTableWidget()
        self.subtitle.setAutoScroll(False)
        self.subtitle.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.mainLayout.addWidget(self.subtitle, 0, 8, 10, 12)
        self.subtitle.setColumnCount(5)
        self.subtitle.selectRow(0)
        self.subtitle.setHorizontalHeaderLabels(['%s' % (i + 1) for i in range(5)])
        self.subtitle.setVerticalHeaderLabels([cnt2Time2(i, self.globalInterval) for i in range(self.subtitle.rowCount())])
        for index in range(5):
            self.subtitle.setColumnWidth(index, 130)
        self.subtitle.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
        self.subtitle.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.subtitle.horizontalHeader().sectionClicked.connect(self.addSubtitle)
        self.subtitle.doubleClicked.connect(self.releaseKeyboard)
        self.subtitle.cellChanged.connect(self.subEdit)
        self.subtitle.verticalHeader().sectionClicked.connect(self.subHeaderClick)
        self.subtitle.setContextMenuPolicy(Qt.CustomContextMenu)
        self.subtitle.customContextMenuRequested.connect(self.popTableMenu)
        self.initSubtitle()

    def initSubtitle(self):
        self.initProcess.show()
        self.subtitle.cellChanged.disconnect(self.subEdit)
        for x in range(self.subtitle.columnCount()):
            for y in range(self.subtitle.rowCount()):
                self.subtitle.setSpan(y, x, 1, 1)
        self.subtitle.setRowCount(self.duration // self.globalInterval + 1)
        for x in range(self.subtitle.columnCount()):
            for y in range(self.subtitle.rowCount()):
                self.subtitle.setItem(y, x, QTableWidgetItem(''))
                self.subtitle.item(y, x).setBackground(QBrush(QColor('#232629')))
        self.subtitle.setVerticalHeaderLabels([cnt2Time2(i, self.globalInterval) for i in range(self.subtitle.rowCount())])
        self.subtitle.cellChanged.connect(self.subEdit)
        self.initProcess.hide()

    def addSubtitle(self, index):
        subtitlePath = QFileDialog.getOpenFileName(self, "请选择字幕", None, "字幕文件 (*.srt *.vtt *.ass *.ssa)")[0]
        if subtitlePath:
            self.initProcess.show()
            self.subtitle.cellChanged.disconnect(self.subEdit)
            if subtitlePath.endswith('.ass') or subtitlePath.endswith('.ssa'):
                p = subprocess.Popen(['utils/ffmpeg.exe', '-y', '-i', subtitlePath, 'temp_sub.srt'])
                p.wait()
                subtitlePath = 'temp_sub.srt'
            subData = {}
            with open(subtitlePath, 'r', encoding='utf-8') as f:
                f = f.readlines()
            subText = ''
            YoutubeAutoSub = False
            for l in f:
                if '<c>' in l:
                    YoutubeAutoSub = True
                    break
            for cnt, l in enumerate(f):
                if '<c>' in l:
                    lineData = l.split('c>')
                    if len(lineData) > 3:
                        subText, start, _ = lineData[0].split('<')
                        start = calSubTime(start[:-1]) // self.globalInterval * self.globalInterval
                        if start not in self.subtitleDict[index]:
                            end = calSubTime(lineData[-3][1:-2]) // self.globalInterval * self.globalInterval
                            for i in range(len(lineData) // 2):
                                subText += lineData[i * 2 + 1][:-2]
                            subData[start] = [end - start, subText]
                    else:
                        subText, start, _ = lineData[0].split('<')
                        start = calSubTime(start[:-1]) // self.globalInterval * self.globalInterval
                        if start not in self.subtitleDict[index]:
                            subText += lineData[1][:-2]
                            subData[start] = [self.globalInterval, subText]
                elif '-->' in l and f[cnt + 2].strip() and '<c>' not in f[cnt + 2]:
                    subText = f[cnt + 2][:-1]
                    start = calSubTime(l[:12]) // self.globalInterval * self.globalInterval
                    if start not in self.subtitleDict[index]:
                        end = calSubTime(l[17:29]) // self.globalInterval * self.globalInterval
                        subData[start] = [end - start, subText]
                if '-->' in l and f[cnt + 1].strip() and not YoutubeAutoSub:
                    start = calSubTime(l[:12]) // self.globalInterval * self.globalInterval
                    if start not in self.subtitleDict[index]:
                        end = calSubTime(l[17:29]) // self.globalInterval * self.globalInterval
                        delta = end - start
                        if delta > 10:
                            if '<b>' in f[cnt + 1]:
                                subData[start] = [delta, f[cnt + 1].split('<b>')[1].split('<')[0]]
                            else:
                                subData[start] = [delta, f[cnt + 1][:-1]]
            self.subtitleDict[index].update(subData)
            maxRow = 0
            for _, v in self.subtitleDict.items():
                startMax = max(v.keys())
                rowCount = (startMax + v[startMax][0]) // self.globalInterval
                if rowCount > maxRow:
                    maxRow = rowCount
            if maxRow < self.duration // self.globalInterval + 1:
                maxRow = self.duration // self.globalInterval
            else:
                self.duration = maxRow * self.globalInterval
            self.subtitle.setRowCount(maxRow)
            self.subtitle.setVerticalHeaderLabels([cnt2Time2(i, self.globalInterval) for i in range(self.subtitle.rowCount())])
            for start, rowData in subData.items():
                startRow = start // self.globalInterval
                endRow = startRow + rowData[0] // self.globalInterval
                for row in range(startRow, endRow):
                    self.subtitle.setItem(row, index, QTableWidgetItem(rowData[1]))
                    self.subtitle.item(row, index).setBackground(QBrush(QColor('#35545d')))
                self.subtitle.setSpan(startRow, index, endRow - startRow, 1)
            self.refreshComboBox()
            self.subtitle.cellChanged.connect(self.subEdit)
            self.initProcess.hide()

    def subTimeOut(self):
        fontColor = self.previewSubtitle.fontColor
        fontSize = (self.previewSubtitle.fontSize + 5) / 2.5
        fontBold = self.previewSubtitle.bold
        fontItalic = self.previewSubtitle.italic
        fontShadowOffset = self.previewSubtitle.shadowOffset
        for _, srtTextItem in self.srtTextItemDict.items():
            srtTextItem.setDefaultTextColor(fontColor)
            font = QFont()
            font.setFamily("微软雅黑")
            font.setPointSize(fontSize)
            font.setBold(fontBold)
            font.setItalic(fontItalic)
            srtTextItem.setFont(font)
            srtTextShadow = QGraphicsDropShadowEffect()
            srtTextShadow.setOffset(fontShadowOffset)
            srtTextItem.setGraphicsEffect(srtTextShadow)
        try:
            selected = self.subtitle.selectionModel().selection().indexes()
            for x, i in enumerate(selected):
                if self.subtitle.item(i.row(), x):
                    txt = self.subtitle.item(i.row(), x).text()
                    if txt:
                        self.srtTextItemDict[x].setPlainText('#%s:' % (x + 1) + txt)
                        txtSize = self.srtTextItemDict[x].boundingRect().size()
                        posY = self.playerWidget.size().height() - txtSize.height() * (x + 1)
                        posX = (self.playerWidget.size().width() - txtSize.width()) / 2
                        self.srtTextItemDict[x].setPos(posX, posY)
                    else:
                        self.srtTextItemDict[x].setPlainText('')
                else:
                    self.srtTextItemDict[x].setPlainText('')
        except:
            pass

    def subHeaderClick(self, index):
        if self.player.duration():
            position = index * self.globalInterval
            self.player.setPosition(position)
            self.videoSlider.setValue(position * 1000 // self.player.duration())
            self.setTimeLabel()

    def subEdit(self, row, index):
        repeat = self.subtitle.rowSpan(row, index)
        self.setSubtitleDict(row, index, repeat, self.subtitle.item(row, index).text())
        self.subtitle.cellChanged.disconnect(self.subEdit)
        for cnt in range(repeat):
            if self.subtitle.item(row + cnt, index).text():
                self.subtitle.item(row, index).setBackground(QBrush(QColor('#35545d')))
            else:
                self.subtitle.item(row, index).setBackground(QBrush(QColor('#232629')))
        self.subtitle.cellChanged.connect(self.subEdit)

    def setSubtitleDict(self, row, index, num, text):
        self.subtitleDict[index][row * self.globalInterval] = [num * self.globalInterval, text]

    def popTableMenu(self, pos):
        self.subtitle.cellChanged.disconnect(self.subEdit)
        pos = QPoint(pos.x() + 55, pos.y() + 30)
        menu = QMenu()
        copy = menu.addAction('复制')
        paste = menu.addAction('粘贴')
        setSpan = menu.addAction('合并')
        clrSpan = menu.addAction('拆分')
        addSub = menu.addAction('导入字幕')
        cutSub = menu.addAction('裁剪字幕')
        action = menu.exec_(self.subtitle.mapToGlobal(pos))
        selected = self.subtitle.selectionModel().selection().indexes()
        yList = [selected[0].row(), selected[-1].row()]
        xSet = set()
        for i in range(len(selected)):
            xSet.add(selected[i].column())
        if action == copy:
            for x in xSet:
                self.clipBoard = []
                for y in range(yList[0], yList[1] + 1):
                    if self.subtitle.item(y, x):
                        self.clipBoard.append(self.subtitle.item(y, x).text())
                    else:
                        self.clipBoard.append('')
                break
        elif action == paste:
            self.subtitle.cellChanged.connect(self.subEdit)
            for x in xSet:
                for cnt, text in enumerate(self.clipBoard):
                    self.subtitle.setItem(yList[0] + cnt, x, QTableWidgetItem(text))
                    self.subtitleDict[x][(yList[0] + cnt) * self.globalInterval] = [self.globalInterval, text]
            self.subtitle.cellChanged.disconnect(self.subEdit)
        elif action == setSpan:
            for x in xSet:
                if not self.subtitle.item(yList[0], x):
                    firstItem = ''
                else:
                    firstItem = self.subtitle.item(yList[0], x).text()
                for y in range(yList[0], yList[1] + 1):
                    self.subtitle.setSpan(y, x, 1, 1)
                    self.subtitle.setItem(y, x, QTableWidgetItem(firstItem))
                    self.subtitle.item(y, x).setBackground(QBrush(QColor('#35545d')))
                    if y * self.globalInterval in self.subtitleDict[x]:
                        del self.subtitleDict[x][y * self.globalInterval]
            for x in xSet:
                self.subtitle.setSpan(yList[0], x, yList[1] - yList[0] + 1, 1)
            self.setSubtitleDict(yList[0], x, yList[1] - yList[0] + 1, firstItem)
        elif action == clrSpan:
            for x in xSet:
                if not self.subtitle.item(yList[0], x):
                    firstItem = ''
                else:
                    firstItem = self.subtitle.item(yList[0], x).text()
                for cnt, y in enumerate(range(yList[0], yList[1] + 1)):
                    self.subtitle.setSpan(y, x, 1, 1)
                    if not cnt:
                        self.subtitle.setItem(yList[0], x, QTableWidgetItem(firstItem))
                        if firstItem:
                            self.subtitle.item(y, x).setBackground(QBrush(QColor('#35545d')))
                        else:
                            self.subtitle.item(y, x).setBackground(QBrush(QColor('#232629')))
                    else:
                        self.subtitle.setItem(y, x, QTableWidgetItem(''))
                        self.subtitle.item(y, x).setBackground(QBrush(QColor('#232629')))
                    self.setSubtitleDict(yList[0], x, yList[1] - yList[0] + 1, firstItem)
                break
        elif action == addSub:
            self.subtitle.cellChanged.connect(self.subEdit)
            for x in xSet:
                self.addSubtitle(x)
            self.subtitle.cellChanged.disconnect(self.subEdit)
        elif action == cutSub:
            for x in xSet:
                start = yList[0] * self.globalInterval
                end = yList[1] * self.globalInterval
                self.exportSubWindow(start, end, x + 1)
        self.subtitle.cellChanged.connect(self.subEdit)

    def setToolBar(self):
        '''
        menu bar, file menu, play menu, tool bar.
        '''
        toolBar = QToolBar()
        self.setContextMenuPolicy(Qt.NoContextMenu)
        self.addToolBar(toolBar)
        fileMenu = self.menuBar().addMenu('&文件')
        openAction = QAction(QIcon.fromTheme('document-open'), '&打开...', self, shortcut=QKeySequence.Open, triggered=self.open)
        fileMenu.addAction(openAction)
        downloadAction = QAction(QIcon.fromTheme('document-open'), '&Youtube下载器', self, triggered=self.popDnld)
        fileMenu.addAction(downloadAction)
        exitAction = QAction(QIcon.fromTheme('application-exit'), '&退出', self, shortcut='Ctrl+Q', triggered=self.close)
        fileMenu.addAction(exitAction)

        playMenu = self.menuBar().addMenu('&功能')
        self.playIcon = self.style().standardIcon(QStyle.SP_MediaPlay)
        self.pauseIcon = self.style().standardIcon(QStyle.SP_MediaPause)
        self.playAction = toolBar.addAction(self.playIcon, '播放')
        self.playAction.triggered.connect(self.mediaPlay)
        self.volumeIcon = self.style().standardIcon(QStyle.SP_MediaVolume)
        self.volumeMuteIcon = self.style().standardIcon(QStyle.SP_MediaVolumeMuted)
        self.volumeAction = toolBar.addAction(self.volumeIcon, '静音')
        self.volumeAction.triggered.connect(self.volumeMute)
        previewAction = QAction(QIcon.fromTheme('document-open'), '&设置预览字幕', self, triggered=self.popPreview)
        playMenu.addAction(previewAction)

        decodeMenu = self.menuBar().addMenu('&输出')
        decodeAction = QAction(QIcon.fromTheme('document-open'), '&输出字幕及视频', self, triggered=self.decode)
        decodeMenu.addAction(decodeAction)

        self.volSlider = Slider()
        self.volSlider.setOrientation(Qt.Horizontal)
        self.volSlider.setMinimum(0)
        self.volSlider.setMaximum(100)
        self.volSlider.setFixedWidth(120)
        self.volSlider.setValue(self.player.volume())
        self.volSlider.setToolTip(str(self.volSlider.value()))
        self.volSlider.pointClicked.connect(self.setVolume)
        toolBar.addWidget(self.volSlider)

        self.videoPositionEdit = LineEdit('00:00')
        self.videoPositionEdit.setAlignment(Qt.AlignRight)
        self.videoPositionEdit.setFixedWidth(75)
        self.videoPositionEdit.setFont(QFont('Timers', 14))
        self.videoPositionEdit.clicked.connect(self.mediaPauseOnly)
        self.videoPositionEdit.editingFinished.connect(self.mediaPlayOnly)
        self.videoPositionLabel = QLabel(' / 00:00  ')
        self.videoPositionLabel.setFont(QFont('Timers', 14))
        toolBar.addWidget(QLabel('    '))
        toolBar.addWidget(self.videoPositionEdit)
        toolBar.addWidget(self.videoPositionLabel)

        self.timer = QTimer()
        self.timer.setInterval(100)
        self.videoSlider = Slider()
        self.videoSlider.setEnabled(False)
        self.videoSlider.setOrientation(Qt.Horizontal)
        self.videoSlider.setMinimum(0)
        self.videoSlider.setMaximum(1000)
        self.videoSlider.setFixedWidth(1000)
        self.videoSlider.sliderMoved.connect(self.timeStop)
        self.videoSlider.sliderReleased.connect(self.timeStart)
        self.videoSlider.pointClicked.connect(self.videoSliderClick)
        toolBar.addWidget(self.videoSlider)

        toolBar.addWidget(QLabel('   '))
        self.globalIntervalComBox = QComboBox()
        self.globalIntervalComBox.addItems(['间隔 100ms', '间隔 200ms', '间隔 500ms', '间隔 1s'])
        self.globalIntervalComBox.setCurrentIndex(1)
        self.globalIntervalComBox.currentIndexChanged.connect(self.setGlobalInterval)
        toolBar.addWidget(self.globalIntervalComBox)
        toolBar.addWidget(QLabel('  '))
        self.subEditComBox = QComboBox()
        self.refreshComboBox()
        toolBar.addWidget(self.subEditComBox)
        toolBar.addWidget(QLabel('  '))
        moveForward = QPushButton('- 1')
        moveForward.setFixedWidth(50)
        toolBar.addWidget(moveForward)
        toolBar.addWidget(QLabel('  '))
        moveAfterward = QPushButton('+ 1')
        moveAfterward.setFixedWidth(50)
        toolBar.addWidget(moveAfterward)
        toolBar.addWidget(QLabel('  '))
        clearSub = QPushButton('清空')
        clearSub.setFixedWidth(50)
        toolBar.addWidget(clearSub)
        toolBar.addWidget(QLabel('  '))
        outputSub = QPushButton('裁剪')
        outputSub.setFixedWidth(50)
        toolBar.addWidget(outputSub)
        moveForward.clicked.connect(self.moveForward)
        moveAfterward.clicked.connect(self.moveAfterward)
        clearSub.clicked.connect(self.clearSub)
        outputSub.clicked.connect(self.exportSubWindow)

    def setGlobalInterval(self, index):
        if not self.playStatus:
            self.mediaPlay()
        self.globalInterval = {0: 100, 1: 200, 2: 500, 3: 1000}[index]
        self.initSubtitle()
        self.initProcess.show()
        self.subtitle.cellChanged.disconnect(self.subEdit)
        for index, subData in self.subtitleDict.items():
            for start, rowData in subData.items():
                startRow = start // self.globalInterval
                deltaRow = rowData[0] // self.globalInterval
                if deltaRow:
                    endRow = startRow + deltaRow
                    for row in range(startRow, endRow):
                        self.subtitle.setItem(row, index, QTableWidgetItem(rowData[1]))
                        if row >= 0:
                            self.subtitle.item(row, index).setBackground(QBrush(QColor('#35545d')))
                    self.subtitle.setSpan(startRow, index, endRow - startRow, 1)
        self.subtitle.cellChanged.connect(self.subEdit)
        self.initProcess.hide()

    def moveForward(self):
        self.initProcess.show()
        self.subtitle.cellChanged.disconnect(self.subEdit)
        index = self.subEditComBox.currentIndex()
        for y in range(self.subtitle.rowCount()):
            self.subtitle.setSpan(y, index, 1, 1)
            self.subtitle.setItem(y, index, QTableWidgetItem(''))
            self.subtitle.item(y, index).setBackground(QBrush(QColor('#232629')))
        tmpDict = self.subtitleDict[index]
        self.subtitleDict[index] = {}
        for start, rowData in tmpDict.items():
            self.subtitleDict[index][start - self.globalInterval] = rowData
        for start, rowData in self.subtitleDict[index].items():
            startRow = start // self.globalInterval
            endRow = startRow + rowData[0] // self.globalInterval
            for row in range(startRow, endRow):
                self.subtitle.setItem(row, index, QTableWidgetItem(rowData[1]))
                self.subtitle.item(row, index).setBackground(QBrush(QColor('#35545d')))
            self.subtitle.setSpan(startRow, index, endRow - startRow, 1)
        self.subtitle.cellChanged.connect(self.subEdit)
        self.initProcess.hide()

    def moveAfterward(self):
        self.initProcess.show()
        self.subtitle.cellChanged.disconnect(self.subEdit)
        index = self.subEditComBox.currentIndex()
        for y in range(self.subtitle.rowCount()):
            self.subtitle.setSpan(y, index, 1, 1)
            self.subtitle.setItem(y, index, QTableWidgetItem(''))
            self.subtitle.item(y, index).setBackground(QBrush(QColor('#232629')))
        tmpDict = self.subtitleDict[index]
        self.subtitleDict[index] = {}
        for start, rowData in tmpDict.items():
            self.subtitleDict[index][start + self.globalInterval] = rowData
        for start, rowData in self.subtitleDict[index].items():
            startRow = start // self.globalInterval
            endRow = startRow + rowData[0] // self.globalInterval
            for row in range(startRow, endRow):
                self.subtitle.setItem(row, index, QTableWidgetItem(rowData[1]))
                self.subtitle.item(row, index).setBackground(QBrush(QColor('#35545d')))
            self.subtitle.setSpan(startRow, index, endRow - startRow, 1)
        self.subtitle.cellChanged.connect(self.subEdit)
        self.initProcess.hide()

    def clearSub(self):
        index = self.subEditComBox.currentIndex()
        reply = QMessageBox.information(self, '清空字幕', '清空第 %s 列字幕条?' % (index + 1), QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes:
            self.initProcess.show()
            self.subtitle.cellChanged.disconnect(self.subEdit)
            self.subtitleDict[index] = {0: [self.globalInterval, '']}
            for i in range(self.subtitle.rowCount()):
                self.subtitle.setSpan(i, index, 1, 1)
                self.subtitle.setItem(i, index, QTableWidgetItem(''))
                self.subtitle.item(i, index).setBackground(QBrush(QColor('#232629')))
                self.subtitle.setHorizontalHeaderItem(index, QTableWidgetItem('%s' % (index + 1)))
            self.subtitle.cellChanged.connect(self.subEdit)
            self.initProcess.hide()

    def exportSubWindow(self, start=0, end=0, index=None):
        self.releaseKeyboard()
        self.exportWindow.hide()
        self.exportWindow.show()
        start = '00:00.0' if not start else self.splitTime(start)
        end = self.splitTime(self.duration) if not end else self.splitTime(end)
        if not index:
            index = self.subEditComBox.currentIndex() + 1
        self.exportWindow.setDefault(start, end, index)

    def exportSubtitle(self, exportArgs):
        start = calSubTime2(exportArgs[0])
        end = calSubTime2(exportArgs[1])
        subStart = calSubTime2(exportArgs[2])
        index = exportArgs[3] - 1
        subData = self.subtitleDict[index]
        rowList = sorted(subData.keys())
        exportRange = []
        for t in rowList:
            if t >= start and t <= end:
                exportRange.append(t)
        subNumber = 1
        with open(exportArgs[-1], 'w', encoding='utf-8') as exportFile:
            for t in exportRange:
                text = subData[t][1]
                if text:
                    start = ms2Time(t + subStart)
                    end = ms2Time(t + subStart + subData[t][0])
                    exportFile.write('%s\n%s --> %s\n%s\n\n' % (subNumber, start, end, text))
                    subNumber += 1
        QMessageBox.information(self, '导出字幕', '导出完成', QMessageBox.Yes)
        self.exportWindow.hide()

    def refreshComboBox(self):
        self.subEditComBox.clear()
        for i in range(self.subtitle.columnCount()):
            self.subEditComBox.addItem('字幕 ' + str(i + 1))

    def open(self):
        self.videoPath = QFileDialog.getOpenFileName(self, "请选择视频文件", None, "MP4格式 (*.mp4);;所有文件(*.*)")[0]
        if self.videoPath:
            cmd = ['utils/ffmpeg.exe', '-i', self.videoPath]
            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            p.wait()
            for l in p.stdout.readlines():
                l = l.decode('utf8')
                if 'Duration' in l:
                    self.duration = calSubTime(l.split(' ')[3][:-1])
                if 'Stream' in l and 'DAR' in l:
                    self.videoWidth, self.videoHeight = map(int, l.split(' [')[0].split(' ')[-1].split('x'))
                    args = l.split(',')
                    for cnt, arg in enumerate(args):
                        if 'kb' in arg:
                            self.bitrate = int(arg.split('kb')[0])
                            self.fps = int(args[cnt + 1].split('fps')[0])
                            break
                    break
            self.initProcess.show()
            self.subtitle.cellChanged.disconnect(self.subEdit)
            self.subtitle.setRowCount(self.duration // self.globalInterval + 1)
            self.subtitle.setVerticalHeaderLabels([cnt2Time2(i, self.globalInterval) for i in range(self.subtitle.rowCount())])
            self.subtitle.cellChanged.connect(self.subEdit)
            self.initProcess.hide()
            url = QUrl.fromLocalFile(self.videoPath)
            self.stack.setCurrentIndex(1)
            self.playerWidget.setSize(QSizeF(1280, 720))
            self.player.setMedia(url)
            self.playStatus = True
            self.videoSlider.setEnabled(True)
            self.mediaPlay()
            self.timer.start()
            self.timer.timeout.connect(self.timeOut)
            self.subTimer.start()
            self.subTimer.timeout.connect(self.subTimeOut)

    def popDnld(self):
        self.releaseKeyboard()
        self.dnldWindow.hide()
        self.dnldWindow.show()

    def popPreview(self):
        self.releaseKeyboard()
        self.previewSubtitle.hide()
        self.previewSubtitle.show()

    def decode(self):
        self.releaseKeyboard()
        self.videoDecoder.setDefault(self.videoPath, self.videoWidth, self.videoHeight, self.duration, self.bitrate, self.fps, self.subtitleDict)
        self.videoDecoder.hide()
        self.videoDecoder.show()

    def mediaPlay(self):
        if self.playStatus:
            self.player.play()
            self.grabKeyboard()
            self.timeStart()
            self.playStatus = False
            self.playAction.setIcon(self.pauseIcon)
            self.playAction.setText('暂停')
        else:
            self.player.pause()
            self.timeStop()
            self.playStatus = True
            self.playAction.setIcon(self.playIcon)
            self.playAction.setText('播放')

    def mediaPlayOnly(self):
        self.grabKeyboard()
        try:
            timeText = self.videoPositionEdit.text().split(':')
            m, s = timeText[:2]
            if not m:
                m = '00'
            if not s:
                s = '00'
            if len(m) > 3:
                m = m[:3]
            if len(s) > 2:
                s = s[:2]
            if m.isdigit():
                m = int(m)
            if s.isdigit():
                s = int(s)
            if s > 60:
                s = 60
            total_m = self.player.duration() // 60000
            if m > total_m:
                m = total_m
            self.player.setPosition(m * 60000 + s * 1000)
            self.videoSlider.setValue(self.player.position() * 1000 / self.player.duration())
        except:
            pass
        self.videoPositionEdit.setReadOnly(True)
        self.timeStart()

    def mediaPauseOnly(self):
        self.releaseKeyboard()
        self.videoPositionEdit.setReadOnly(False)
        self.player.pause()
        self.timeStop()
        self.playStatus = True
        self.playAction.setIcon(self.playIcon)
        self.playAction.setText('播放')

    def splitTime(self, playTime):
        playTime = playTime // 1000
        m = str(playTime // 60)
        s = playTime % 60
        s = ('0%s' % s)[-2:]
        if len(m) > 2:
            t = '%3s:%2s' % (m, s)
        else:
            t = '%2s:%2s' % (m, s)
        return t

    def timeOut(self):
        row = self.player.position() // self.globalInterval
        self.subtitle.selectRow(row)
        self.subtitle.verticalScrollBar().setValue(row - 10)
        if self.dnldWindow.isHidden() or self.exportWindow.isHidden() or self.videoDecoder.isHidden():
            self.grabKeyboard()
        try:
            self.videoSlider.setValue(self.player.position() * 1000 / self.player.duration())
            self.setTimeLabel()
        except:
            pass

    def timeStop(self):
        self.timer.stop()

    def timeStart(self):
        self.timer.start()

    def videoSliderClick(self, p):
        self.videoSlider.setValue(p.x())
        self.player.setPosition(p.x() * self.player.duration() // 1000)
        self.setTimeLabel()

    def setVolume(self, p):
        self.volumeValue = p.x()
        if self.volumeValue > 100:
            self.volumeValue = 100
        if self.volumeValue < 0:
            self.volumeValue = 0
        self.volSlider.setValue(self.volumeValue)
        self.player.setVolume(self.volumeValue)
        self.volSlider.setToolTip(str(self.volSlider.value()))
        if self.volumeValue:
            self.volumeStatus = True
            self.volumeAction.setIcon(self.volumeIcon)
        else:
            self.volumeStatus = False
            self.volumeAction.setIcon(self.volumeMuteIcon)

    def volumeMute(self):
        if self.volumeStatus:
            self.volumeStatus = False
            self.old_volumeValue = self.player.volume()
            self.player.setVolume(0)
            self.volSlider.setValue(0)
            self.volumeAction.setIcon(self.volumeMuteIcon)
        else:
            self.volumeStatus = True
            self.player.setVolume(self.old_volumeValue)
            self.volSlider.setValue(self.old_volumeValue)
            self.volumeAction.setIcon(self.volumeIcon)

    def setTimeLabel(self):
        now = self.player.position()
        total = self.player.duration()
        now = self.splitTime(now)
        total = self.splitTime(total)
        self.videoPositionEdit.setText(now)
        self.videoPositionLabel.setText(' / %s  ' % total)

    def eventFilter(self, obj, event):
        if obj == self.view:
            if event.type() == QEvent.MouseButtonPress:
                self.mediaPlay()
        return QMainWindow.eventFilter(self, obj, event)

    def keyPressEvent(self, QKeyEvent):
        key = QKeyEvent.key()
        if key == Qt.Key_Left:
            if self.videoSlider.isEnabled():
                self.player.setPosition(self.player.position() - 5000)
                self.videoSlider.setValue(self.player.position() * 1000 / self.player.duration())
                self.setTimeLabel()
        elif key == Qt.Key_Right:
            if self.videoSlider.isEnabled():
                self.player.setPosition(self.player.position() + 5000)
                self.videoSlider.setValue(self.player.position() * 1000 / self.player.duration())
                self.setTimeLabel()
        elif key == Qt.Key_Up:
            self.volumeValue += 10
            if self.volumeValue > 100:
                self.volumeValue = 100
            self.volSlider.setValue(self.volumeValue)
            self.player.setVolume(self.volumeValue)
        elif key == Qt.Key_Down:
            self.volumeValue -= 10
            if self.volumeValue < 0:
                self.volumeValue = 0
            self.volSlider.setValue(self.volumeValue)
            self.player.setVolume(self.volumeValue)
        elif key == Qt.Key_Space:
            self.mediaPlay()
Exemple #26
0
class MyGui(QWidget, GitCmd):
    def __init__(self, title="Create By ZZZ", path=DEFAULT_GIT_REPO):
        super(MyGui, self).__init__()
        GitCmd.__init__(self, path)  # 初始化命令
        self.show_info = None
        self.cmd_history = None
        self.cmd_history_cmd_list = list()
        # 复选框
        self.check_box_select_all = None
        self.check_box = list()
        self.check_box_button = None
        # 默认值
        self.show_log_num = DEFAULT_GIT_LOG_NUM
        self.file_list = DEFAULT_GIT_ADD_LIST
        self.gridLayout = QGridLayout(self)
        self.setGeometry(100, 100, 800, 700)
        self.setWindowTitle(title)
        # 记录当前widget最大行号
        self.max_line_no = 0

    # - - - - - - - - -  - - - - - - - - -  - - - - - - - - -  - - - - - - - - -
    # 显示信息相关
    def add_info_text(self):
        # 添加消息显示框,我们使用列表方式显示
        self.show_info = QListWidget()
        self.show_info.setFixedSize(800, 600)
        self.gridLayout.addWidget(self.show_info, 0, 0, 1, 4)
        # 单击触发绑定的槽函数
        self.show_info.itemClicked.connect(self.text_block_clicked)

        # 命令行显示,我们使用下拉框
        self.cmd_history = QComboBox()
        self.gridLayout.addWidget(self.cmd_history, 1, 0, 1, 4)
        # 设置行号
        self.max_line_no = 2

    def add_cmd(self, cmd):
        if len(self.cmd_history_cmd_list) < 10:
            self.cmd_history_cmd_list.append(cmd)
        else:
            self.cmd_history_cmd_list = self.cmd_history_cmd_list[1:].append(cmd)
        self.cmd_history.clear()
        self.cmd_history.addItems(reversed(self.cmd_history_cmd_list))

    def update_cmd(self, extra: str):
        cur_cmd = self.cmd_history.currentText().split(" ")
        new_cmd = cur_cmd[:2] + [extra]  # 拆分出来git和后面的命令,拼接参数
        if cur_cmd:
            self.cmd_history.setItemText(0, " ".join(new_cmd))

    # 对每一行都进行上色
    def my_print(self, text_list: list, background: list):
        # self.show_info.clear() 这个可以清空显示
        self.show_info.addItems([".  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . .  .  .  .  .  .  .  .  "
                                 ".  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . .  .  .  .  .  .  .  .  "])
        for ind in range(len(text_list)):
            item = QListWidgetItem('%s' % text_list[ind])
            item.setBackground(QColor(background[ind]))  # 上色
            self.show_info.addItem(item)
        self.show_info.scrollToBottom()  # 自动到最后行

    @staticmethod
    def text_block_clicked(item):
        # 这里没有什么要做的
        # QMessageBox.information(self, "命令历史", "你选择了: " + item.text())
        pass
    # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

    # - - - - - - - - -  - - - - - - - - -  - - - - - - - - -  - - - - - - - - -
    # 添加按钮
    def add_git_button(self):
        cmd_add = QPushButton('Git Add')
        cmd_reset = QPushButton('Git Reset')
        cmd_status = QPushButton('Git Status')
        cmd_log = QPushButton('Git Log')
        cmd_run = QPushButton('Run Cmd')
        line_no = self.max_line_no
        self.gridLayout.addWidget(cmd_add, line_no, 0)
        self.gridLayout.addWidget(cmd_reset, line_no, 1)
        self.gridLayout.addWidget(cmd_status, line_no, 2)
        self.gridLayout.addWidget(cmd_log, line_no, 3)
        self.gridLayout.addWidget(cmd_run, line_no + 1, 0)
        self.max_line_no = self.max_line_no + 2
        cmd_log.clicked.connect(self.git_log)
        cmd_add.clicked.connect(self.git_add)
        cmd_reset.clicked.connect(self.git_reset)
        cmd_status.clicked.connect(self.git_status)
        cmd_run.clicked.connect(self.run_git)

    def run_git(self):
        cur_cmd = self.cmd_history.currentText()
        # 执行代码
        if cur_cmd.startswith("git add"):
            result, background = self.cmd_git_add(self.file_list)
            self.my_print(result, background)
        elif cur_cmd.startswith("git status"):
            result, background = self.cmd_git_status()
            self.my_print(result, background)
        elif cur_cmd.startswith("git log"):
            result, background = self.cmd_git_log(self.show_log_num)
            self.my_print(result, background)
        elif cur_cmd.startswith("git reset"):
            result, background = self.cmd_git_reset(self.file_list)
            self.my_print(result, background)

    def git_log(self):
        # 日常清理
        self.cleanup()
        # 记录命令
        self.add_cmd("git log -" + self.show_log_num)
        # 可以直接运行
        self.run_git()

    def git_add(self):
        # 日常清理
        self.cleanup()
        # 文件选择
        files = self.get_file_list_by_status()
        self.create_check_box(files)
        # 记录命令
        self.add_cmd("git add .")

    def git_status(self):
        # 日常清理
        self.cleanup()
        # 记录命令
        self.add_cmd("git status")
        # 可以直接运行
        self.run_git()

    def git_reset(self):
        # 日常清理
        self.cleanup()
        # 文件选择
        files = self.get_file_list_by_status()
        self.create_check_box(files)
        # 记录命令
        self.add_cmd("git reset .")

    # - - - - - - - - -  - - - - - - - - -  - - - - - - - - -  - - - - - - - - -
    # 创建复选框
    def create_check_box(self, opt_list: list):
        # 创建
        self.check_box_select_all = QCheckBox('全选')
        # lambda可以传参:lambda: self.check_box_changes_all(<参数>)
        self.check_box_select_all.stateChanged.connect(lambda: self.check_box_changes_all())
        for ind in range(len(opt_list)):
            self.check_box.append(QCheckBox(opt_list[ind]))
            self.check_box[ind].stateChanged.connect(lambda: self.check_box_changes())
        # self.check_box_button = QPushButton('提交')
        # 布局
        ind = self.max_line_no
        self.gridLayout.addWidget(self.check_box_select_all, ind, 0)
        ind = ind + 1
        for check_box in self.check_box:
            self.gridLayout.addWidget(check_box, ind, 0)
            ind = ind + 1
        # self.gridLayout.addWidget(self.check_box_button, ind, 0)
        # 添加按钮回调
        # self.check_box_button.clicked.connect(self.check_box_ok)
        # 更新行号
        # self.max_line_no = ind + 1
        self.max_line_no = ind

    def check_box_ok(self):
        # 清除小部件
        if self.check_box:
            self.file_list.clear()
            for check_box in self.check_box:
                # 更新列表
                # if check_box.checkState() == Qt.Checked:
                #     self.file_list.append(check_box.text())
                # 清除
                check_box.deleteLater()
            self.check_box.clear()
        if self.check_box_select_all:
            self.check_box_select_all.deleteLater()
            self.check_box_select_all = None
        if self.check_box_button:
            self.check_box_button.deleteLater()
            self.check_box_button = None

    def check_box_changes_all(self):
        if self.check_box_select_all.checkState() == Qt.Checked:
            for check_box in self.check_box:
                check_box.setChecked(True)
        elif self.check_box_select_all.checkState() == Qt.Unchecked:
            for check_box in self.check_box:
                check_box.setChecked(False)

    def check_box_changes(self):
        all_checked = True
        # one_checked = False
        self.file_list.clear()
        for check_box in self.check_box:
            if not check_box.isChecked():
                all_checked = False  # 只要有一个没勾选
            else:
                self.file_list.append(check_box.text())  # 更新列表
            # else:
            #     one_checked = True  # 只要有一个勾选
        if all_checked:
            self.check_box_select_all.setCheckState(Qt.Checked)
        # elif one_checked:
            # self.check_box_select_all.setTristate()  # 设置为3态选择框
            # self.check_box_select_all.setCheckState(Qt.PartiallyChecked)
        # else:
        #   self.check_box_select_all.setTristate()  # 设置为3态选择框
        #   self.check_box_select_all.setCheckState(Qt.Unchecked)

        # 更新命令
        files = " ".join(self.file_list)
        self.update_cmd(files)

    # - - - - - - - - -  - - - - - - - - -  - - - - - - - - -  - - - - - - - - -
    # 清理临时的小部件
    def cleanup(self):
        self.check_box_ok()

    # - - - - - - - - -  - - - - - - - - -  - - - - - - - - -  - - - - - - - - -
    # 例子
    def addButtonExample(self):
        # 创建一些小部件放在顶级窗口中
        btn = QPushButton('press me')
        text = QLineEdit('enter text')
        listw = QListWidget()
        listw.addItems(["aa", "bb", "cc"])
        # self.gridLayout = QGridLayout(self)
        # 将部件添加到布局中的适当位置,
        # addWidget参数:Widget实例, 起始row, 起始column, 占多少行(高度),占多少列(宽度)
        self.gridLayout.addWidget(btn, 0, 0)
        self.gridLayout.addWidget(text, 1, 0)
        self.gridLayout.addWidget(listw, 2, 0)
        # self.setLayout(self.gridLayout)

    # 画图1
    def linePlot(self):
        plt1 = pg.PlotWidget()
        plt1.plot([i for i in range(10)], [i * i for i in range(10)])
        self.gridLayout.addWidget(plt1, 0, 1, 1, 1)

    # 画图2
    def scatterPlot(self):
        plt2 = pg.PlotWidget()
        x = np.random.normal(size=1000)
        y = np.random.normal(size=1000)
        plt2.plot(x, y, pen=None, symbol="o")
        self.gridLayout.addWidget(plt2, 1, 1, 1, 1)

    # 画图3
    def three_curves(self):
        plt3 = pg.PlotWidget(title="Three plot curves")
        x = np.arange(1000)
        y = np.random.normal(size=(3, 1000))
        for i in range(3):
            plt3.plot(x, y[i], pen=(i, 3))  # setting pen=(i,3) 自动创建3个不同颜色的笔
        self.gridLayout.addWidget(plt3, 2, 1, 1, 1)
Exemple #27
0
class SonstigeAusgabenView(IccView):
    def __init__(self, parent=None):
        IccView.__init__(self)
        #self.setWindowTitle( "Sonstige Ausgaben: Rechnungen, Abgaben, Gebühren etc." )
        self._mainLayout = QtWidgets.QGridLayout(self)
        self._toolbarLayout = QHBoxLayout()
        self._summenLayout = QHBoxLayout()
        self._btnSave = QPushButton(self)
        self._btnComplexSort = QPushButton()
        self._editSearch = QLineEdit(self)
        self._btnSearchFwd = QPushButton(self)
        self._btnDbSearch = QPushButton(self)

        self._cboBuchungsjahr = QtWidgets.QComboBox(self)
        self._tvAuszahlungen = TableViewExt(self)

        self._buchungsdatumLayout = QHBoxLayout()
        self._sdBuchungsdatum = SmartDateEdit(self)
        self._btnAddDay = QPushButton(self)
        self._btnClearBuchungsdatum = QPushButton(self)

        self._objektRefLayout = QHBoxLayout()
        self._cboMasterobjekt = QComboBox(self)
        self._cboMietobjekt = QComboBox(self)

        self._editRechnungLineLayout = QHBoxLayout()
        self._cboKreditor = EditableCombo(self)
        self._cboBuchungstext = EditableCombo(self)
        self._sdRechnungsdatum = SmartDateEdit(self)
        self._feBetrag = FloatEdit(self)
        self._cboKostenart = QComboBox(self)
        self._cbUmlegbar = QCheckBox(self)
        self._cbWerterhaltend = QCheckBox(self)
        self._teBemerkung = QTextEdit(self)
        self._btnOk = QPushButton(self)
        self._btnClear = QPushButton(self)
        # Callbacks
        self._buchungsjahrChangedCallback = None
        self._saveActionCallback = None
        self._searchActionCallback = None
        self._dbSearchActionCallback = None
        self._masterobjektChangedCallback = None
        self._mietobjektChangedCallback = None
        self._kreditorChangedCallback = None
        self._submitChangesCallback = None
        self._justEditing: XSonstAus = None
        self._suspendCallbacks = False

        self._createGui()

    def _createGui(self):
        self._assembleToolbar()
        self._mainLayout.addLayout(self._toolbarLayout,
                                   0,
                                   0,
                                   alignment=Qt.AlignLeft)
        #self._assembleSummen()
        # self._toolbarLayout.addStretch( 50 )
        # self._toolbarLayout.addLayout( self._summenLayout )
        ### tableView
        tv = self._tvAuszahlungen
        tv.setSelectionBehavior(QAbstractItemView.SelectRows)
        tv.setAlternatingRowColors(True)
        tv.verticalHeader().setVisible(False)
        tv.horizontalHeader().setMinimumSectionSize(0)
        self._mainLayout.addWidget(tv, 1, 0, 1, 1)
        self._assembleBuchungsUndRechnungsdatum()
        self._mainLayout.addLayout(self._buchungsdatumLayout,
                                   2,
                                   0,
                                   alignment=Qt.AlignLeft)
        self._assembleObjektReference()
        self._mainLayout.addLayout(self._objektRefLayout,
                                   3,
                                   0,
                                   alignment=Qt.AlignLeft)
        self._assembleRechnungsdaten()
        self._mainLayout.addLayout(self._editRechnungLineLayout,
                                   4,
                                   0,
                                   alignment=Qt.AlignLeft)

    def _assembleToolbar(self):
        #### Combobox Buchungsjahr
        font = QFont("Arial", 14, weight=QFont.Bold)
        self._cboBuchungsjahr.setFont(font)
        self._cboBuchungsjahr.setToolTip(
            "Das hier eingestellte Jahr bestimmt die Rechnungen, die in der Tabelle angezeigt werden."
        )
        self._cboBuchungsjahr.currentIndexChanged.connect(
            self.onBuchungsjahrChanged)
        self._toolbarLayout.addWidget(self._cboBuchungsjahr,
                                      stretch=0,
                                      alignment=Qt.AlignLeft)

        #### save button
        btn = self._btnSave
        btn.clicked.connect(self.onSave)
        btn.setFlat(True)
        btn.setEnabled(False)
        btn.setToolTip("Änderungen dieser View speichern")
        icon = QIcon(ICON_DIR + "save_30.png")
        btn.setIcon(icon)
        size = QSize(30, 30)
        btn.setFixedSize(size)
        iconsize = QSize(30, 30)
        btn.setIconSize(iconsize)
        self._toolbarLayout.addWidget(btn, stretch=0)

        ### complex sort button
        btn = self._btnComplexSort
        btn.clicked.connect(self.onSortComplex)
        btn.setFlat(True)
        btn.setEnabled(True)
        btn.setToolTip(
            "Nach Master, Kostenart, Kreditor, Mietobjekt, Buchungsdatum  sortieren"
        )
        icon = QIcon(ICON_DIR + "sort.png")
        btn.setIcon(icon)
        size = QSize(30, 30)
        btn.setFixedSize(size)
        iconsize = QSize(30, 30)
        btn.setIconSize(iconsize)
        self._toolbarLayout.addWidget(btn, stretch=0)

        ### search field for tableview search
        edi = self._editSearch
        edi.setPlaceholderText("Suche in Tabelle")
        edi.returnPressed.connect(self._onSearch)
        edi.setToolTip("Suchbegriff eingeben")
        self._toolbarLayout.addWidget(edi, stretch=0)
        btn = self._btnSearchFwd
        btn.clicked.connect(self._onSearch)
        size = QSize(30, 30)
        btn.setFixedSize(size)
        btn.setToolTip("Suche nach eingegebenem Begriff")
        icon = QIcon(ICON_DIR + "arrow_dn_30.png")
        btn.setIcon(icon)
        btn.setEnabled(True)
        self._toolbarLayout.addWidget(btn, stretch=0)

    def _assembleBuchungsUndRechnungsdatum(self):
        lbl = QLabel(self, text="Buchungsdatum: ")
        lbl.setFixedWidth(150)
        self._buchungsdatumLayout.addWidget(lbl)
        self._sdBuchungsdatum.setFixedWidth(85)
        self._sdBuchungsdatum.setToolTip(
            "Buchungsdatum. Kann leer bleiben, wenn Buchung noch nicht erfolgt ist"
        )
        self._buchungsdatumLayout.addWidget(self._sdBuchungsdatum)
        size = QSize(25, 25)
        self._btnAddDay.setIcon(QIcon(ICON_DIR + "plus.png"))
        self._btnAddDay.setFixedSize(size)
        self._btnAddDay.setToolTip("Buchungsdatum um 1 Tag erhöhen")
        self._btnAddDay.clicked.connect(self.onAddDayToBuchungsdatum)
        self._buchungsdatumLayout.addWidget(self._btnAddDay)
        self._btnClearBuchungsdatum.setIcon(QIcon(ICON_DIR + "cancel.png"))
        self._btnClearBuchungsdatum.setFixedSize(size)
        self._btnClearBuchungsdatum.setToolTip("Buchungsdatum löschen")
        self._btnClearBuchungsdatum.clicked.connect(self.onClearBuchungsdatum)
        self._buchungsdatumLayout.addWidget(self._btnClearBuchungsdatum)

        self._sdRechnungsdatum.setPlaceholderText("Datum Rg.")
        self._sdRechnungsdatum.setMaximumWidth(85)
        self._sdRechnungsdatum.setToolTip("optional: Datum der Rechnung")
        self._buchungsdatumLayout.addSpacing(10)
        lbl = QLabel(text="Rechnungsdatum (optional): ")
        lbl.setFixedWidth(200)
        self._buchungsdatumLayout.addWidget(lbl)
        self._buchungsdatumLayout.addWidget(self._sdRechnungsdatum)

    def _assembleObjektReference(self):
        lbl = QLabel(self, text="Betroffenes Objekt: ")
        lbl.setFixedWidth(150)
        self._objektRefLayout.addWidget(lbl)
        self._cboMasterobjekt.setFixedWidth(155)
        self._cboMasterobjekt.setPlaceholderText("Haus")
        self._cboMasterobjekt.setToolTip(
            "Haus, auf das sich die Zahlung bezieht")
        self._cboMasterobjekt.currentIndexChanged.connect(
            self.onMasterobjektChanged)
        self._objektRefLayout.addWidget(self._cboMasterobjekt)
        self._cboMietobjekt.setPlaceholderText("Wohnung")
        self._cboMietobjekt.setToolTip(
            "optional: Wohnung, auf die sich die Zahlung bezieht")
        self._cboMietobjekt.currentIndexChanged.connect(
            self.onMietobjektChanged)
        self._objektRefLayout.addWidget(self._cboMietobjekt)

    def _assembleRechnungsdaten(self):
        self._cboKreditor.setToolTip("Kreditor")
        self._cboKreditor.setFixedWidth(200)
        self._cboKreditor.currentIndexChanged.connect(self.onKreditorChanged)
        self._editRechnungLineLayout.addWidget(self._cboKreditor)
        self._cboBuchungstext.setToolTip(
            "Identifikation der Zahlung durch Rechnungsnummer oder Buchungstext"
        )
        self._cboBuchungstext.setMinimumWidth(100)
        self._editRechnungLineLayout.addWidget(self._cboBuchungstext,
                                               stretch=2)

        #Button for DB-Search
        btn = self._btnDbSearch
        btn.clicked.connect(self._onDbSearch)
        size = QSize(30, 30)
        btn.setFixedSize(size)
        btn.setToolTip("Suche Buchungstext in der DB")
        icon = QIcon(ICON_DIR + "search_30.png")
        btn.setIcon(icon)
        btn.setEnabled(True)
        self._editRechnungLineLayout.addWidget(btn)

        # Betragsfeld
        self._feBetrag.setPlaceholderText("Betrag")
        self._feBetrag.setMaximumWidth(70)
        self._feBetrag.setToolTip(
            "Positive Beträge sind Aus-, negative Einzahlungen (Gutschriften)")
        self._editRechnungLineLayout.addWidget(self._feBetrag,
                                               stretch=0,
                                               alignment=Qt.AlignLeft)

        # Combobox Kostenart
        self._cboKostenart.setPlaceholderText("Kostenart")
        self._cboKostenart.setFixedWidth(120)
        self._cboKostenart.setToolTip("Kostenart einstellen")
        self._editRechnungLineLayout.addWidget(self._cboKostenart,
                                               stretch=0,
                                               alignment=Qt.AlignLeft)

        vbox = QVBoxLayout()
        vbox.setSpacing(0)
        self._cbUmlegbar.setText("uml")
        self._cbUmlegbar.setToolTip(
            "Ob die Auszahlung auf den/die Mieter umlegbar sind")
        vbox.addWidget(self._cbUmlegbar)
        self._cbWerterhaltend.setText("wert")
        self._cbWerterhaltend.setToolTip(
            "Ob die Auszahlung der Werterhaltung der Wohnung dient")
        vbox.addWidget(self._cbWerterhaltend)
        self._editRechnungLineLayout.addLayout(vbox)

        self._teBemerkung.setPlaceholderText("Bemerkung zur Auszahlung")
        self._teBemerkung.setMaximumSize(QtCore.QSize(16777215, 50))
        self._editRechnungLineLayout.addWidget(self._teBemerkung, stretch=1)

        vbox = QVBoxLayout()
        self._btnOk.setIcon(QIcon(ICON_DIR + "checked.png"))
        self._btnOk.setDefault(True)
        self._btnOk.setToolTip(
            "Neue oder geänderte Daten in Tabelle übernehmen (kein Speichern)")
        self._btnOk.clicked.connect(self.onOkEditFields)
        vbox.addWidget(self._btnOk)
        self._btnClear.setIcon(QIcon(ICON_DIR + "cancel.png"))
        self._btnClear.setToolTip("Änderungen verwerfen und Felder leeren")
        self._btnClear.clicked.connect(self.onClearEditFields)
        vbox.addWidget(self._btnClear)
        self._editRechnungLineLayout.addLayout(vbox)

    # def setContextMenuActions( self, actions:List[QAction] ) -> None:
    #     self._contextMenuActions = actions

    def getSummen(self) -> XSonstAusSummen:
        summen = XSonstAusSummen()
        summen.summe_aus = self._idSummeAus.getIntValue()
        summen.summe_werterhaltend = self._idSummeW.getIntValue()
        summen.summe_umlegbar = self._idSummeU.getIntValue()
        return summen

    def onAddDayToBuchungsdatum(self):
        val = self._sdBuchungsdatum.getDate()
        if val:
            dt = getQDateFromIsoString(val)
            dt = dt.addDays(1)
            self._sdBuchungsdatum.setDate(dt.year(), dt.month(), dt.day())

    def onClearBuchungsdatum(self):
        self._sdBuchungsdatum.clear()

    def setSaveButtonEnabled(self, enable: bool = True):
        self._btnSave.setEnabled(enable)

    def onSave(self):
        if self._saveActionCallback:
            self._saveActionCallback()

    def onSortComplex(self):
        sortoption1 = ("master_name", "kostenart", "kreditor", "mobj_id",
                       "buchungsdatum")
        tm: SonstAusTableModel = self.getModel()
        tm.sortComplex(sortoption1)

    def _onSearch(self):
        if self._searchActionCallback:
            self._searchActionCallback(self._editSearch.text())

    def _onDbSearch(self):
        if self._dbSearchActionCallback:
            #self._dbSearchActionCallback( self._editDbSearch.text() )
            searchstring = self._cboBuchungstext.currentText()
            if searchstring:
                self._dbSearchActionCallback(searchstring)

    def onBuchungsjahrChanged(self, newindex):
        """
        Slot für die Änderung des Buchungsjahrs.
        :param newindex:
        :return:
        """
        if self._buchungsjahrChangedCallback:
            jahr = int(self._cboBuchungsjahr.currentText())
            self._buchungsjahrChangedCallback(jahr)

    def onMasterobjektChanged(self, newindex: int):
        if self._masterobjektChangedCallback and not self._suspendCallbacks:
            self._masterobjektChangedCallback(
                self._cboMasterobjekt.currentText())

    def onMietobjektChanged(self, newindex: int):
        pass

    def onKreditorChanged(self, newindex: int):
        if self._kreditorChangedCallback and not self._suspendCallbacks:
            self._kreditorChangedCallback(self._cboMasterobjekt.currentText(),
                                          self._cboMietobjekt.currentText(),
                                          self._cboKreditor.currentText())

    def onOkEditFields(self, arg):
        """
        OK gedrückt. Änderungen an Callback-Funktion melden.
        :param arg:
        :return:
        """
        if self._submitChangesCallback:
            x: XSonstAus = self._getEditedXSonstAus()
            ok: bool = self._submitChangesCallback(x)
            if ok:
                self._tvAuszahlungen.clearSelection()
                if x.saus_id <= 0:  # neuer Eintrag in Tabelle, nach unten scrollen
                    self._tvAuszahlungen.scrollToBottom()

    def _getEditedXSonstAus(self) -> XSonstAus:
        x: XSonstAus = self._justEditing if self._justEditing else XSonstAus()
        x.buchungsjahr = int(self._cboBuchungsjahr.currentText())
        x.buchungsdatum = self._sdBuchungsdatum.getDate()
        idx = self._cboMasterobjekt.currentIndex()
        x.master_name = "" if idx < 0 else self._cboMasterobjekt.currentText()
        idx = self._cboMietobjekt.currentIndex()
        x.mobj_id = "" if idx < 0 else self._cboMietobjekt.currentText()
        x.kreditor = self._cboKreditor.currentText()
        x.buchungstext = self._cboBuchungstext.currentText()
        x.rgdatum = self._sdRechnungsdatum.getDate()
        x.betrag = self._feBetrag.getFloatValue() * (-1)
        x.kostenart_lang = self._cboKostenart.currentText()
        x.umlegbar = self._cbUmlegbar.isChecked()
        x.werterhaltend = self._cbWerterhaltend.isChecked()
        x.rgtext = self._teBemerkung.toPlainText()
        return x

    def onClearEditFields(self, arg):
        self.clearEditFields()
        self._tvAuszahlungen.clearSelection()

    def getAuszahlungenTableView(self) -> QTableView:
        return self._tvAuszahlungen

    def setAuszahlungenTableModel(self, tm: SonstAusTableModel):
        self._tvAuszahlungen.setModel(tm)
        self._tvAuszahlungen.resizeColumnsToContents()
        #self._tvAuszahlungen.setColumnWidth( 0, 10 )
        #self._tvAuszahlungen.setColumnWidth( 1, 10 )

    def setBuchungsjahre(self, jahre: List[int]):
        """
        setzt die Liste der auswählbaren Jahre für die Buchungsjahr-Combobox
        :param jahre:
        :return:
        """
        for jahr in jahre:
            self._cboBuchungsjahr.addItem(str(jahr))

    def setBuchungsjahr(self, jahr: int) -> None:
        """
        setzt das Jahr, das in der Buchungsjahr-Combobox anzuzeigen ist
        :param jahr:
        :return:
        """
        self._cboBuchungsjahr.setCurrentText(str(jahr))

    def setBuchungsdatum(self, tag: int, monat: str):
        """
        setzt Buchungstag und -monat.
        Das Jahr ergibt sich aus dem eingestellten Buchungsjahr
        :param tag:
        :param monat:
        :return:
        """
        # self._sbTag.setValue( tag )
        # self._cboMonat.setCurrentText( monat )
        self._sdBuchungsdatum.\
            setDate( int(self._cboBuchungsjahr.currentText()), getMonthIndex( monat ), tag )

    def setMasterobjekte(self, masterobjekte: List[str]):
        for obj in masterobjekte:
            self._cboMasterobjekt.addItem(obj)

    def setMietobjekte(self, mietobjekte: List[str]):
        self._cboMietobjekt.clear()
        for obj in mietobjekte:
            self._cboMietobjekt.addItem(obj)
        self._cboMietobjekt.setCurrentIndex(0)

    def selectMietobjekt(self, mobj_id: str):
        self._cboMietobjekt.setCurrentText(mobj_id)

    def clearMietobjekte(self):
        self._cboMietobjekt.clear()

    def setKreditoren(self, kreditoren: List[str]):
        self._cboKreditor.clear()
        for k in kreditoren:
            self._cboKreditor.addItem(k)
        self._cboKreditor.setCurrentIndex(-1)

    def selectKreditor(self, kreditor: str):
        self._cboKreditor.setCurrentText(kreditor)

    def setLeistungsidentifikationen(self, idents: List[str]):
        self._cboBuchungstext.clear()
        for i in idents:
            self._cboBuchungstext.addItem(i)
        #self._cboRechnungsIdent.showPopup()

    def setCurrentLeistungsidentifikation(self, leistident: str) -> None:
        self._cboBuchungstext.setCurrentText(leistident)

    def getCurrentMasterobjekt(self) -> str:
        return self._cboMasterobjekt.currentText()

    def getCurrentMietobjekt(self) -> str:
        return self._cboMietobjekt.currentText()

    def getCurrentKreditor(self) -> str:
        return self._cboKreditor.currentText()

    def setCurrentKreditor(self, kreditor: str) -> None:
        self._cboKreditor.setCurrentText(kreditor)

    def getCurrentLeistungsidentifikation(self) -> str:
        return self._cboBuchungstext.currentText()

    def resetKreditoren(self):
        self._cboKreditor.setCurrentIndex(-1)

    def clearKreditoren(self):
        self._cboKreditor.clear()

    def setKostenarten(self, kostenarten: List[str]):
        self._cboKostenart.clear()
        for k in kostenarten:
            self._cboKostenart.addItem(k)
        self._cboKostenart.setCurrentIndex(-1)

    def getCurrentKostenart(self) -> str:
        return self._cboKostenart.currentText()

    def selectKostenart(self, kostenart: str):
        self._cboKostenart.setCurrentText(kostenart)

    def resetKostenart(self):
        self._cboKostenart.setCurrentIndex(-1)

    def clearEditFields(self):
        self._suspendCallbacks = True
        self._sdBuchungsdatum.clear()
        self._cboMasterobjekt.setCurrentIndex(-1)
        self._cboMietobjekt.setCurrentIndex(-1)
        self._cboKreditor.setCurrentIndex(-1)
        self._cboBuchungstext.setCurrentIndex(-1)
        self._sdRechnungsdatum.clear()
        self._feBetrag.clear()
        self._cboKostenart.setCurrentIndex(-1)
        self._cbUmlegbar.setChecked(False)
        self._cbWerterhaltend.setChecked(False)
        self._teBemerkung.clear()
        self._justEditing = None
        self._suspendCallbacks = False

    def provideEditFieldsPartly(self, umlegbar: bool, master_id: int,
                                master_name: str, mobj_id: str, kreditor: str,
                                kostenart_lang: str, buchungstext: str):
        self._cbUmlegbar.setChecked(umlegbar)
        self._cboMasterobjekt.setCurrentText(master_name)
        self._cboMietobjekt.setCurrentText(mobj_id)
        self._cboKreditor.setCurrentText(kreditor)
        self._cboBuchungstext.setCurrentText(buchungstext)
        self._cboKostenart.setCurrentText(kostenart_lang)
        #todo: weitermachen

    def provideEditFields(self, x: XSonstAus):
        self.clearEditFields()
        #self._suspendCallbacks = True
        self._justEditing = x
        if x.buchungsdatum:
            y, m, d = getDateParts(x.buchungsdatum)
            self._sdBuchungsdatum.setDate(y, m, d)
        else:
            self._sdBuchungsdatum.clear()
        if x.master_id is not None and x.master_id >= 0:  #master_id kann auch 0 sein! (**alle**)
            self._cboMasterobjekt.setCurrentText(x.master_name)
        if x.mobj_id:
            self._cboMietobjekt.setCurrentText(x.mobj_id)
        if x.kreditor:
            self._cboKreditor.setCurrentText(x.kreditor)
        if x.kostenart:
            self._cboKostenart.setCurrentText(x.kostenart_lang)
        if x.buchungstext:
            self._cboBuchungstext.setCurrentText(x.buchungstext)
        if x.rgdatum:
            y, m, d = getDateParts(x.rgdatum)
            self._sdRechnungsdatum.setDate(y, m, d)
        self._feBetrag.setText(str(x.betrag * (-1)))
        self._cbUmlegbar.setChecked(x.umlegbar)
        self._cbWerterhaltend.setChecked(x.werterhaltend)
        self._teBemerkung.setText(x.rgtext)
        self._suspendCallbacks = False

    def getModel(self) -> IccTableModel:
        return self._tvAuszahlungen.model()

    def showException(self, title: str, exception: str, moretext: str = None):
        # todo: show Qt-Errordialog
        msgbox = QtWidgets.QMessageBox()
        msgbox.setWindowTitle(title)
        msgbox.setIcon(QMessageBox.Critical)
        msgbox.setText(exception)
        if moretext:
            msgbox.setInformativeText(moretext)
        msgbox.exec_()

    ################# SET CALLBACKS  ############################

    def setBuchungsjahrChangedCallback(self, cbfnc) -> None:
        """
        Die callback-Funktion muss als Argument das neu eingestellte Jahr als integer akzeptieren
        :param cbfnc:
        :return:
        """
        self._buchungsjahrChangedCallback = cbfnc

    def setSaveActionCallback(self, cbfnc) -> None:
        """
        Die callback-FUnktion braucht keine Parameter empfangen.
        :param cbfnc:
        :return:
        """
        self._saveActionCallback = cbfnc

    def setSearchActionCallback(self, cbfnc) -> None:
        """
        Die callback-Funktion muss den Searchstring als Parameter empfangen.
        :param cbfnc:
        :return:
        """
        self._searchActionCallback = cbfnc

    def setDbSearchActionCallback(self, cbfnc) -> None:
        """
       Die callback-Funktion muss den Searchstring als Parameter empfangen.
       :param cbfnc:
       :return:
       """
        self._dbSearchActionCallback = cbfnc

    def setMasterobjektChangedCallback(self, cbfnc):
        """
        Die callback-Funktion muss einen String als Argument akzeptieren (Name des MAsterobjekts)
        :param cbfnc:
        :return:
        """
        self._masterobjektChangedCallback = cbfnc

    def setMietobjektChangedCallback(self, cbfnc):
        """
        Die callback-Funktion muss einen String als Argument akzeptieren (mobj_id)
        :param cbfnc:
        :return:
        """
        self._mietobjektChangedCallback = cbfnc

    def setKreditorChangedCallback(self, cbfnc):
        """
        Die callback Funktion muss 3 Argumente entgegennehmen können:
        master_name, mobj_id, neuer kreditor
        :param cbfnc:
        :return:
        """
        self._kreditorChangedCallback = cbfnc

    def setSubmitChangesCallback(self, cbfnc):
        """
        sets the one and only callback when the user hits the OK button in the
        edit fields area.
        The given callback function has to accept the edited XSonstAus object,
        :param cbfnc:
        :return:
        """
        self._submitChangesCallback = cbfnc
Exemple #28
0
class Form(QDialog):
    def __init__(self, parent=None):
        super(Form, self).__init__(parent)
        self.setWindowTitle("Chat Smasher")
        # Create Widgets

        self.edit = QLineEdit("Welcome")
        self.button = QPushButton("Load Files")
        self.stopButton = QPushButton("Stop")
        self.box1 = QComboBox()  # Holds name of files
        self.filePreview = QTextBrowser()  # Preview Files
        self.loadingBar = QProgressBar(self)

        self.preview = QTextBrowser()
        self.champBox = QComboBox()
        self.ConfirmButton = QPushButton("Start")
        # Create layout and add widgets
        layout = QVBoxLayout()

        self.label2 = QLabel()
        self.label2.setText("Caleb's Chat Smasher")
        self.label2.setStyleSheet(
            "QLabel { background-color : green; color : white; font-size: 20px; text-align : "
            "center; }")

        self.label = QLabel()
        pixmap = QPixmap('lek.png')
        self.timer = QBasicTimer()
        self.step = 0
        self.label.setPixmap(pixmap)

        layout.addWidget(self.label2)
        layout.addWidget(self.label)

        #layout.addWidget(self.edit)
        self.champBox = QComboBox()
        # layout.addWidget(self.champBox)
        layout.addWidget(self.button)
        layout.addWidget(self.box1)

        layout.addWidget(self.filePreview)
        layout.addWidget(self.ConfirmButton)
        layout.addWidget(self.stopButton)
        self.loadingBar.setStyleSheet(
            "QProgressBar::chunk {background-color: red}")

        layout.addWidget(self.loadingBar)

        #self.file
        # Set layout
        self.setLayout(layout)
        p = self.palette()
        p.setColor(self.foregroundRole(), QColor(10, 10, 10, 127))
        p.setColor(self.backgroundRole(), QColor(0, 0, 0, 127))

        self.setPalette(p)
        self.setFixedWidth(450)
        self.setFixedHeight(700)

        #make connections
        self.button.clicked.connect(self.imclicked)
        self.ConfirmButton.clicked.connect(self.newStart)
        self.stopButton.clicked.connect(self.stop)
        self.box1.activated.connect(self.updatePreview)

    def start(self):
        print("Ready to Go")
        myFile = pathlib.Path.cwd() / 'copypastas' / self.box1.currentText()
        clicking.type_page(myFile)
        self.loadingBar.setStyleSheet(
            "QProgressBar::chunk {background-color: green } QProgressBar {text-align: center}"
        )

    def stop(self):
        self.timer.stop()
        #self.loadingBar.setValue(0)

    def imclicked(self):
        self.updatelist()

    def newStart(self):
        global stepper
        stepper = 0
        self.loadingBar.setValue(0)
        self.loadingBar.setStyleSheet(
            "QProgressBar::chunk {background-color: red;} QProgressBar {text-align: center}"
        )
        self.startTracking()

    def updatelist(self):
        self.box1.clear()
        fileNames = fileHandling.getFileNames()
        for names in fileNames:
            self.box1.addItem(names)
        self.updatePreview()

    def updatePreview(self):
        self.filePreview.clear()
        myFile = pathlib.Path.cwd() / 'copypastas' / self.box1.currentText()
        with open(myFile, 'r') as pageRead:
            for line in pageRead:
                self.filePreview.append(line)

    def startTracking(self):
        self.timer.start(80, self)

    def timerEvent(self, event):
        global stepper
        stepper += 1
        self.loadingBar.setValue(stepper)
        if self.loadingBar.value() == 100:
            self.start()
            self.timer.stop()
Exemple #29
0
 def update_combobox(box: QComboBox, labels: List[str]) -> None:
     """Update the combobox menu."""
     box.blockSignals(True)
     box.clear()
     box.insertItems(0, labels)
     box.blockSignals(False)
Exemple #30
0
class CamView(AbstractView):
    def __init__(self,
                 name: str = "CAM_NONE",
                 log_handlers: [StreamHandler] = None):
        self._logger = getLogger(__name__)
        if log_handlers:
            for h in log_handlers:
                self._logger.addHandler(h)
        self._logger.debug("Initializing")
        super().__init__(name)
        """ Min size for cam window """
        self._subwindow_height = 222
        self._subwindow_width = 518

        self._initialization_bar_frame = EasyFrame()
        self._initialization_bar_frame.setMouseTracking(True)
        self._initialization_bar_frame.setMaximumHeight(70)
        self._initialization_bar_layout = QVBoxLayout(
            self._initialization_bar_frame)

        self._initialization_bar_label = QLabel(self._initialization_bar_frame)
        self._initialization_bar_label.setMouseTracking(True)
        self._initialization_bar = QProgressBar(self._initialization_bar_frame)
        self._initialization_bar.setMouseTracking(True)
        self._initialization_bar.setMaximumHeight(15)
        self._initialization_bar.setTextVisible(True)
        self._initialization_bar.setAlignment(Qt.AlignHCenter)

        self._initialization_bar_layout.addWidget(
            self._initialization_bar_label)
        self._initialization_bar_layout.addWidget(self._initialization_bar)

        self._cam_settings_frame = EasyFrame()
        self._cam_settings_layout = QGridLayout(self._cam_settings_frame)

        self._resolution_selector_label = QLabel(self._cam_settings_frame)
        self._resolution_selector_label.setAlignment(Qt.AlignLeft)

        self._resolution_selector = QComboBox(self._cam_settings_frame)
        self._resolution_selector.setMaximumHeight(22)

        self._cam_settings_layout.addWidget(self._resolution_selector_label, 0,
                                            0)
        self._cam_settings_layout.addWidget(self._resolution_selector, 0, 1)

        self._fps_selector_label = QLabel(self._cam_settings_frame)
        self._fps_selector_label.setAlignment(Qt.AlignLeft)

        self._fps_selector = QComboBox(self._cam_settings_frame)
        self._fps_selector.setMaximumHeight(22)

        self._cam_settings_layout.addWidget(self._fps_selector_label, 1, 0)
        self._cam_settings_layout.addWidget(self._fps_selector, 1, 1)

        self._show_feed_checkbox_label = QLabel(self._cam_settings_frame)
        self._show_feed_checkbox_label.setAlignment(Qt.AlignLeft)

        self._show_feed_checkbox = QCheckBox()
        self._show_feed_checkbox.setChecked(True)
        self._show_feed_checkbox.setLayoutDirection(Qt.RightToLeft)

        self._cam_settings_layout.addWidget(self._show_feed_checkbox_label, 2,
                                            0)
        self._cam_settings_layout.addWidget(self._show_feed_checkbox, 2, 1)

        self._use_cam_checkbox_label = QLabel(self._cam_settings_frame)
        self._use_cam_checkbox_label.setAlignment(Qt.AlignLeft)

        self._use_cam_checkbox = QCheckBox()
        self._use_cam_checkbox.setChecked(True)
        self._use_cam_checkbox.setLayoutDirection(Qt.RightToLeft)

        self._cam_settings_layout.addWidget(self._use_cam_checkbox_label, 3, 0)
        self._cam_settings_layout.addWidget(self._use_cam_checkbox, 3, 1)

        self._use_overlay_checkbox_label = QLabel(self._cam_settings_frame)
        self._use_overlay_checkbox_label.setAlignment(Qt.AlignLeft)

        self._use_overlay_checkbox = QCheckBox()
        self._use_overlay_checkbox.setChecked(True)
        self._use_overlay_checkbox.setLayoutDirection(Qt.RightToLeft)

        self._cam_settings_layout.addWidget(self._use_overlay_checkbox_label,
                                            4, 0)
        self._cam_settings_layout.addWidget(self._use_overlay_checkbox, 4, 1)

        self._image_display_frame = EasyFrame()
        self._image_display_layout = QVBoxLayout(self._image_display_frame)

        self._image_display_label = QLabel(self._image_display_frame)
        self._image_display_label.setAlignment(Qt.AlignHCenter)
        self._image_display = QLabel(self._image_display_frame)
        self._image_display.setAlignment(Qt.AlignCenter)
        self._image_display.setMouseTracking(True)
        self._image_display_layout.addWidget(self._image_display_label)
        self._image_display_layout.addWidget(self._image_display)

        spacer = QSpacerItem(1, 1, vData=QSizePolicy.Expanding)

        self._dev_sets_frame = EasyFrame()
        self._dev_sets_layout = QVBoxLayout(self._dev_sets_frame)

        self.config_button = ClickAnimationButton()
        self.config_button.clicked.connect(self._config_button_handler)

        self.layout().addWidget(self.config_button, 0, 0,
                                Qt.AlignTop | Qt.AlignRight)
        self.config_button.setFixedSize(30, 25)
        self.config_button.setStyleSheet(
            "background-color: rgba(200, 200, 200, 50%)")

        self._dev_sets_layout.addWidget(self._cam_settings_frame)
        self._dev_sets_layout.addItem(spacer)
        self.layout().addWidget(self._image_display, 0, 0)
        self.layout().addWidget(self._initialization_bar_frame, 0, 0)

        self._config_items = [
            self._resolution_selector,
            self._fps_selector,
            self._use_cam_checkbox,
            self._show_feed_checkbox,
            self._use_overlay_checkbox,
        ]

        config_win_w = 350
        config_win_h = len(self._config_items) * 30

        self.config_button.raise_()

        self._config_win = ConfigPopUp()
        self._config_win.setLayout(self._dev_sets_layout)
        self._config_win.setFixedSize(config_win_w, config_win_h)

        self._rec_label = QLabel()
        self._rec_label.setStyleSheet(
            "background-color: rgba(0, 0, 0, 0%); color: red; font: 20px")
        self._rec_label.hide()

        self.layout().addWidget(self._rec_label, 0, 0,
                                Qt.AlignBottom | Qt.AlignRight)

        self.layout().setMargin(0)

        self._window_changing = False
        self._showing_images = False
        self._hidden = False
        w = 320
        self._aspect_ratio = 9 / 16
        self.resize(w, self.heightForWidth(w))
        self._strings = dict()
        self._lang_enum = LangEnum.ENG
        self.setMinimumSize(self._subwindow_width, self._subwindow_height)
        self.old_size = QSize(self.width(), self.height())

        self._logger.debug("Initialized")

    def set_show_feed_button_handler(self, func) -> None:
        """
        Add handler for show camera selector.
        :param func: The handler.
        :return None:
        """
        self._logger.debug("running")
        self._show_feed_checkbox.toggled.connect(func)
        self._logger.debug("done")

    def set_resolution_selector_handler(self, func) -> None:
        """
        Add handler for resolution selector.
        :param func: The handler.
        :return None:
        """
        self._logger.debug("running")
        self._resolution_selector.activated.connect(func)
        self._logger.debug("done")

    def set_fps_selector_handler(self, func) -> None:
        """
        Add handler for resolution selector.
        :param func: The handler.
        :return None:
        """
        self._logger.debug("running")
        self._fps_selector.activated.connect(func)
        self._logger.debug("done")

    def set_use_cam_button_handler(self, func) -> None:
        """
        Add handler for use camera selector.
        :param func: The handler.
        :return None:
        """
        self._logger.debug("running")
        self._use_cam_checkbox.toggled.connect(func)
        self._logger.debug("done")

    def set_use_overlay_button_handler(self, func) -> None:
        """
        Add handler for use camera selector.
        :param func: The handler.
        :return None:
        """
        self._logger.debug("running")
        self._use_overlay_checkbox.toggled.connect(func)
        self._logger.debug("done")

    def _config_button_handler(self) -> None:
        """
        Show config pop up.
        :return None:
        """
        self._logger.debug("running")
        self.config_button.setStyleSheet(
            "background-color: rgba(200, 200, 200, 50%)")
        self._config_win.exec_()
        self._logger.debug("done")

    @property
    def language(self) -> LangEnum:
        """
        :return: The current lang enum being used.
        """
        return self._lang_enum

    @language.setter
    def language(self, lang: LangEnum) -> None:
        """
        Set the language for this view object.
        :param lang: The language to use.
        :return None:
        """
        self._logger.debug("running")
        self._lang_enum = lang
        self._strings = strings[lang]
        self._set_texts()
        self._set_tooltips()
        self._logger.debug("done")

    @property
    def resolution_list(self) -> list:
        """
        Get list of resolutions.
        :return list: The list of resolutions.
        """
        ret = list()
        return ret

    @resolution_list.setter
    def resolution_list(self, res_list: list) -> None:
        """
        Set list of resolutions available to res_list.
        :param res_list: The list of available resolutions.
        :return None:
        """
        self._logger.debug("running")
        self._resolution_selector.clear()
        for item in res_list:
            self._resolution_selector.addItem(str(item))
        self._logger.debug("done")

    @property
    def resolution(self) -> str:
        """
        Get the current resolution selection.
        :return str: The current resolution.
        """
        return self._resolution_selector.currentText()

    @resolution.setter
    def resolution(self, res: str) -> None:
        """
        Set the current resolution selection.
        :param res: The resolution to set to.
        :return None:
        """
        self._resolution_selector.setCurrentIndex(
            self._resolution_selector.findText(res))

    @property
    def fps_list(self) -> list:
        """
        Get list of fps options.
        :return list: The list of fps options.
        """
        ret = list()
        return ret

    @fps_list.setter
    def fps_list(self, fps_list: list) -> None:
        """
        Set list of available fps to fps_list.
        :param fps_list:
        :return None:
        """
        self._logger.debug("running")
        self._fps_selector.clear()
        for item in fps_list:
            self._fps_selector.addItem(str(item))
        self._logger.debug("done")

    @property
    def fps(self) -> str:
        """
        Get the current fps selection.
        :return str: The current fps selection.
        """
        return self._fps_selector.currentText()

    @fps.setter
    def fps(self, fps: str) -> None:
        """
        Set the current fps selection.
        :param fps: The fps to set to.
        :return None:
        """
        self._logger.debug("running")
        self._fps_selector.setCurrentIndex(self._fps_selector.findText(fps))
        self._logger.debug("done")

    @property
    def use_feed(self) -> bool:
        """
        Get the current use_cam setting.
        :return bool: User selection for using cam.
        """
        return self._show_feed_checkbox.isChecked()

    @use_feed.setter
    def use_feed(self, useable: bool) -> None:
        """
        Set use_cam setting.
        :param useable: The setting to set to.
        :return None:
        """
        self._logger.debug("running")
        self._show_feed_checkbox.setChecked(useable)
        self._logger.debug("Done")

    @property
    def use_cam(self) -> bool:
        """
        Get the current use_cam setting.
        :return bool: User selection for using cam.
        """
        return self._use_cam_checkbox.isChecked()

    @use_cam.setter
    def use_cam(self, useable: bool) -> None:
        """
        Set use_cam setting.
        :param useable: The setting to set to.
        :return None:
        """
        self._logger.debug("running")
        self._use_cam_checkbox.setChecked(useable)
        self._logger.debug("Done")

    @property
    def use_overlay(self) -> bool:
        """
        Get the current use_overlay setting.
        :return bool: User selection for using overlay.
        """
        return self._use_overlay_checkbox.isChecked()

    @use_overlay.setter
    def use_overlay(self, useable: bool) -> None:
        """
        Set use_overlay setting.
        :param useable: The setting to set to.
        :return None:
        """
        self._logger.debug("running")
        self._use_overlay_checkbox.setChecked(useable)
        self._logger.debug("Done")

    def heightForWidth(self, w: int) -> int:
        return int(w * self._aspect_ratio)

    def widthForHeight(self, h: int) -> int:
        return int(h / self._aspect_ratio)

    def hideEvent(self, hideEvent: QHideEvent):
        """
        Track minimize event.
        :param hideEvent:
        :return None:
        """
        self._hidden = True

    def showEvent(self, showEvent: QShowEvent):
        """
        Track restore event.
        :param showEvent:
        :return None:
        """
        self._hidden = False

    def update_image(self, image: QPixmap = None, msg: str = None) -> None:
        """
        Update image viewer with new image.
        :param image: The new image to show.
        :param msg: The text to show if no image.
        :return None:
        """
        self._logger.debug("running")
        if not self._window_changing:
            if image is not None:
                temp_image_w = image.scaledToWidth(self.width() - 15)
                temp_image_h = image.scaledToHeight(self.height() - 35)
                if temp_image_w.height() > self.height() - 35:
                    self._image_display.setPixmap(temp_image_h)
                else:
                    self._image_display.setPixmap(temp_image_w)
            elif msg is not None:
                self._image_display.setText(msg)
        self._logger.debug("done")

    def show_images(self) -> None:
        """
        Show image display and hide initialization bar.
        :return None:
        """
        self._logger.debug("running")
        geo = self.geometry()
        self._showing_images = True
        self._initialization_bar_frame.hide()
        self._image_display.show()
        self.config_button.show()
        self.setStyleSheet("background-color: black")
        self.setGeometry(geo)
        self._logger.debug("done")

    def show_initialization(self) -> None:
        """
        Show initialization bar and hide image display.
        :return None:
        """
        self._logger.debug("running")
        self._showing_images = False
        self._image_display.hide()
        self.config_button.hide()
        self._initialization_bar_frame.show()
        self._logger.debug("done")

    def update_init_bar(self, progress: int) -> None:
        """
        set progress bar value to progress.
        :param progress: The value to set progress bar to.
        :return None:
        """
        self._logger.debug("running")
        if progress > 100:
            progress = 100
        elif progress < 0:
            progress = 0
        self._initialization_bar.setValue(progress)
        self._logger.debug("done")

    def set_config_active(self, is_active: bool) -> None:
        """
        Set whether this camera config options are usable.
        :param is_active: Usable.
        :return None:
        """
        self._logger.debug("running")
        if self._showing_images:
            if is_active:
                self._rec_label.hide()
            elif self.use_cam:
                self._rec_label.show()
        for item in self._config_items:
            item.setEnabled(is_active)
        self._logger.debug("done")

    def _set_texts(self) -> None:
        """
        Set the texts in this view object.
        :return None:
        """
        self._logger.debug("running")
        self._initialization_bar_label.setText(
            self._strings[StringsEnum.INITIALIZATION_BAR_LABEL])
        self._initialization_bar.setValue(0)
        self._image_display_label.setText(
            self._strings[StringsEnum.IMAGE_DISPLAY_LABEL])
        self._image_display.setText(self._strings[StringsEnum.IMAGE_DISPLAY])
        self._show_feed_checkbox_label.setText(
            self._strings[StringsEnum.SHOW_FEED_CHECKBOX_LABEL])
        self._use_cam_checkbox_label.setText(
            self._strings[StringsEnum.USE_CAM_CHECKBOX_LABEL])
        self._use_overlay_checkbox_label.setText(
            self._strings[StringsEnum.USE_OVERLAY_CHECKBOX_LABEL])
        self._resolution_selector_label.setText(
            self._strings[StringsEnum.RESOLUTION_SELECTOR_LABEL])
        self._fps_selector_label.setText(
            self._strings[StringsEnum.FPS_SELECTOR_LABEL])
        self._config_win.setWindowTitle(
            self.get_name() + " " +
            self._strings[StringsEnum.CONFIG_TAB_LABEL])
        self.config_button.setText("...")
        self._rec_label.setText("rec ●")
        self._logger.debug("done")

    def _set_tooltips(self) -> None:
        """
        Set the tooltips in this view object.
        :return None:
        """
        self._logger.debug("running")
        self._resolution_selector_label.setToolTip(
            self._strings[StringsEnum.RESOLUTION_SELECTOR_TOOLTIP])
        self._resolution_selector.setToolTip(
            self._strings[StringsEnum.RESOLUTION_SELECTOR_TOOLTIP])
        self._fps_selector_label.setToolTip(
            self._strings[StringsEnum.FPS_SELECTOR_TOOLTIP])
        self._fps_selector.setToolTip(
            self._strings[StringsEnum.FPS_SELECTOR_TOOLTIP])
        self._show_feed_checkbox_label.setToolTip(
            self._strings[StringsEnum.SHOW_FEED_CHECKBOX_TOOLTIP])
        self._show_feed_checkbox.setToolTip(
            self._strings[StringsEnum.SHOW_FEED_CHECKBOX_TOOLTIP])
        self._use_cam_checkbox_label.setToolTip(
            self._strings[StringsEnum.USE_CAM_CHECKBOX_TOOLTIP])
        self._use_cam_checkbox.setToolTip(
            self._strings[StringsEnum.USE_CAM_CHECKBOX_TOOLTIP])
        self._use_overlay_checkbox_label.setToolTip(
            self._strings[StringsEnum.USE_OVERLAY_TOOLTIP])
        self._use_overlay_checkbox.setToolTip(
            self._strings[StringsEnum.USE_OVERLAY_TOOLTIP])
        self._image_display.setToolTip(
            self._strings[StringsEnum.IMAGE_DISPLAY_TOOLTIP])
        self._logger.debug("done")