Example #1
0
    def insert_new_item(self, bypass_save_enable=False) -> None:
        self.warning_updates_disabled = True

        self.warnings_table.removeRow(self.warnings_table.rowCount() - 1)
        self.warnings_table.setRowCount(self.warnings_table.rowCount() + 1)

        button = QPushButton("-", self)
        button.setFixedSize(QSize(25, 25))

        row: int = self.warnings_table.rowCount() - 1

        self.warnings_table.setCellWidget(row, 0, button)
        button.clicked.connect(lambda: self.remove_table_row(row))

        self.insert_helper_item()

        self.warnings.append({i: '' for i in self.header_list if i})

        self.warning_updates_disabled = False
        self.check_for_save_update()
Example #2
0
    def insert_helper_item(self, bypass_save_enable=False) -> None:
        button = QPushButton("+", self)

        self.warnings_table.setRowCount(self.warnings_table.rowCount() + 1)
        self.warnings_table.setCellWidget(self.warnings_table.rowCount() - 1,
                                          0, button)

        for i in range(self.warnings_table.columnCount()):
            item = self.warnings_table.item(self.warnings_table.rowCount() - 1,
                                            i)

            if item is None:
                item = QTableWidgetItem()
                self.warnings_table.setItem(self.warnings_table.rowCount() - 1,
                                            i, item)

            item.setFlags(item.flags() ^ Qt.ItemFlag.ItemIsEnabled)

        button.setFixedSize(QSize(25, 25))
        button.clicked.connect(
            lambda: self.insert_new_item(bypass_save_enable))
Example #3
0
    def update_table_items(self, bypass_save_enable=False) -> None:
        self.__warnings_table.clearContents()
        self.__warnings_table.setRowCount(len(self.warnings))

        for i in range(len(self.warnings)):
            for header in self.header_list:
                if len(header) == 0:
                    button = QPushButton("-", self)
                    button.setFixedSize(QSize(25, 25))

                    self.warnings_table.setCellWidget(i, 0, button)
                    button.clicked.connect(lambda: self.remove_table_row(i))
                    continue

                item: QTableWidgetItem = QTableWidgetItem()
                item.setText(self.warnings[i][header])

                self.warnings_table.setItem(i, self.header_list.index(header),
                                            item)

        self.insert_helper_item(bypass_save_enable)
Example #4
0
    def __init__(self):
        app = QApplication(sys.argv)
        super().__init__()

        self.setWindowTitle('PyQt6 simple button example')
        self.setGeometry(100, 100, 360, 140)

        button = QPushButton('PyQt6 Push Button', self)
        button.setToolTip('Click button to change window status message.')
        #
        # Not too sure about setting the fixed size of the button.
        # But I did that to keep the button from stretching across the width of
        # the window. Must be a way to have the button fit the size of it's text.
        #
        button.clicked.connect(self.on_click)
        button.setFixedSize(150, 30)

        widget = QWidget()
        layout = QHBoxLayout(widget)
        layout.addWidget(button)
        self.setCentralWidget(widget)
        self.statusBar().showMessage('Operational')
        self.show()
        sys.exit(app.exec())
Example #5
0
 def __init__(self):
     super().__init__()
     self.logger = logging.getLogger(__name__)
     formatter = logging.Formatter(
         fmt="%(asctime)s-%(levelname)s-%(message)s",
         datefmt="%Y-%m-%d %H:%M:%S")
     filehandler = logging.FileHandler(filename="logs.log",
                                       mode="w",
                                       encoding="utf-8")
     handler = QLogger(update_signal=self.update_signal)
     handler.setLevel(logging.INFO)
     filehandler.setLevel(logging.INFO)
     self.logger.setLevel(logging.INFO)
     if os.path.exists("config.json") == False:
         self.gen_conf()
     with open(file="config.json", mode="r",
               encoding="utf-8") as conf_reader:
         conf = json.loads(conf_reader.read())
     debug = bool(conf["debug"])
     if debug == True:
         handler.setLevel(logging.DEBUG)
         filehandler.setLevel(logging.DEBUG)
         self.logger.setLevel(logging.DEBUG)
     handler.setFormatter(formatter)
     filehandler.setFormatter(formatter)
     self.logger.addHandler(handler)
     self.logger.addHandler(filehandler)
     self.logger.debug("当前调试状态:%s" % debug)
     self.resize(1024, 768)
     self.setWindowOpacity(0.9)
     self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
     self.setWindowFlag(Qt.WindowFlags.FramelessWindowHint)
     self.setAutoFillBackground(True)
     self.work = Work(show_qr_signal=self.show_qr_signal,
                      finish_signal=self.finish_signal,
                      close_qr_signal=self.close_qr_signal)
     self.work_thread = QThread()
     self.work.moveToThread(self.work_thread)
     self.main_layout = QGridLayout()
     self.setLayout(self.main_layout)
     self.title = QLabel("ChinaUniOnlineGUI")
     self.title.setStyleSheet(
         "QLabel{border:none;border-radius:5px;background:transparent;color:#9AD3BC;font-size:60px;}"
     )
     self.title.setAlignment(Qt.Alignment.AlignCenter)
     handler.widget.setStyleSheet(
         "QPlainTextEdit{font-family:Microsoft YaHei;background:#F3EAC2;border:none;border-radius:5px;}QScrollBar:vertical,QScrollBar::handle:vertical{background:#F3EAC2;border:none;border-radius:8px;width:16px;}QScrollBar::handle:vertical:hover{background:#F5B461;}QScrollBar::add-page:vertical,QScrollBar::sub-page:vertical{background:#FFFDF9;border:none;border-radius:8px;width:16px;}QScrollBar::down-arrow:vertical,QScrollBar::up-arrow:vertical{background:#F5B461;border:none;border-radius:8px;width:16px;height:16px;}QScrollBar::sub-line:vertical,QScrollBar::add-line:vertical{background:transparent;border:none;}"
     )
     self.control = QVBoxLayout()
     self.control_close = QPushButton()
     self.control_close.setToolTip("关闭")
     self.control_close.setStyleSheet(
         "QPushButton{background:#FFE3ED;border-radius:5px;border:none;}QPushButton:hover{background:#EC524B;}"
     )
     self.contron_max = QPushButton()
     if self.isMaximized() == False:
         self.contron_max.setToolTip("最大化")
     else:
         self.contron_max.setToolTip("还原")
     self.contron_max.setStyleSheet(
         "QPushButton{background:#FFFDF9;border-radius:5px;border:none;}QPushButton:hover{background:#F5B461;}"
     )
     self.control_min = QPushButton()
     self.control_min.setToolTip("最小化")
     self.control_min.setStyleSheet(
         "QPushButton{background:#BEEBE9;border-radius:5px;border:none;}QPushButton:hover{background:#F3EAC2;}"
     )
     self.start_button = QPushButton("开始(&S)")
     self.start_button.setStyleSheet(
         "QPushButton{background:#9BE3DE;border:none;border-radius:5px;font-size:20px;font-family:DengXian;}QPushButton:hover{background:#9AD3BC;}"
     )
     self.start_button.setToolTip("开始")
     self.start_button.setFixedSize(120, 60)
     self.start_button.setDefault(True)
     setting_button = QPushButton("设置")
     setting_button.setToolTip("设置")
     setting_button.setFixedSize(60, 60)
     setting_button.setStyleSheet(
         "QPushButton{background:#9BE3DE;border:none;border-radius:5px;font-size:20px;font-family:DengXian;}QPushButton:hover{background:#9AD3BC;}"
     )
     setting_button.clicked.connect(self.setting_callback)
     start = QHBoxLayout()
     start.addWidget(self.start_button, 2)
     start.addWidget(setting_button, 1)
     self.control_close.clicked.connect(self.close)
     self.control_min.clicked.connect(self.min_callback)
     self.contron_max.clicked.connect(self.max_callback)
     self.start_button.clicked.connect(self.start_callback)
     self.work_thread.started.connect(self.work.start)
     self.finish_signal.connect(self.finish_callback)
     self.close_qr_signal.connect(self.close_qr)
     self.control.addWidget(self.control_min)
     self.control.addWidget(self.contron_max)
     self.control.addWidget(self.control_close)
     self.main_layout.addLayout(self.control, 0, 0)
     self.main_layout.addWidget(self.title, 0, 1)
     self.main_layout.addLayout(start, 0, 2)
     self.main_layout.addWidget(handler.widget, 1, 1)
     self.update_signal.connect(handler.widget.appendPlainText)
     handler.widget.textChanged.connect(handler.scroll_widget_to_bottom)
     self.show_qr_signal.connect(self.show_qr)
     self.logger.debug("已初始化UI")
Example #6
0
class UI(QWidget):
    update_signal = pyqtSignal(str)
    show_qr_signal = pyqtSignal(bytes)
    finish_signal = pyqtSignal()
    close_qr_signal = pyqtSignal()

    def __init__(self):
        super().__init__()
        self.logger = logging.getLogger(__name__)
        formatter = logging.Formatter(
            fmt="%(asctime)s-%(levelname)s-%(message)s",
            datefmt="%Y-%m-%d %H:%M:%S")
        filehandler = logging.FileHandler(filename="logs.log",
                                          mode="w",
                                          encoding="utf-8")
        handler = QLogger(update_signal=self.update_signal)
        handler.setLevel(logging.INFO)
        filehandler.setLevel(logging.INFO)
        self.logger.setLevel(logging.INFO)
        if os.path.exists("config.json") == False:
            self.gen_conf()
        with open(file="config.json", mode="r",
                  encoding="utf-8") as conf_reader:
            conf = json.loads(conf_reader.read())
        debug = bool(conf["debug"])
        if debug == True:
            handler.setLevel(logging.DEBUG)
            filehandler.setLevel(logging.DEBUG)
            self.logger.setLevel(logging.DEBUG)
        handler.setFormatter(formatter)
        filehandler.setFormatter(formatter)
        self.logger.addHandler(handler)
        self.logger.addHandler(filehandler)
        self.logger.debug("当前调试状态:%s" % debug)
        self.resize(1024, 768)
        self.setWindowOpacity(0.9)
        self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
        self.setWindowFlag(Qt.WindowFlags.FramelessWindowHint)
        self.setAutoFillBackground(True)
        self.work = Work(show_qr_signal=self.show_qr_signal,
                         finish_signal=self.finish_signal,
                         close_qr_signal=self.close_qr_signal)
        self.work_thread = QThread()
        self.work.moveToThread(self.work_thread)
        self.main_layout = QGridLayout()
        self.setLayout(self.main_layout)
        self.title = QLabel("ChinaUniOnlineGUI")
        self.title.setStyleSheet(
            "QLabel{border:none;border-radius:5px;background:transparent;color:#9AD3BC;font-size:60px;}"
        )
        self.title.setAlignment(Qt.Alignment.AlignCenter)
        handler.widget.setStyleSheet(
            "QPlainTextEdit{font-family:Microsoft YaHei;background:#F3EAC2;border:none;border-radius:5px;}QScrollBar:vertical,QScrollBar::handle:vertical{background:#F3EAC2;border:none;border-radius:8px;width:16px;}QScrollBar::handle:vertical:hover{background:#F5B461;}QScrollBar::add-page:vertical,QScrollBar::sub-page:vertical{background:#FFFDF9;border:none;border-radius:8px;width:16px;}QScrollBar::down-arrow:vertical,QScrollBar::up-arrow:vertical{background:#F5B461;border:none;border-radius:8px;width:16px;height:16px;}QScrollBar::sub-line:vertical,QScrollBar::add-line:vertical{background:transparent;border:none;}"
        )
        self.control = QVBoxLayout()
        self.control_close = QPushButton()
        self.control_close.setToolTip("关闭")
        self.control_close.setStyleSheet(
            "QPushButton{background:#FFE3ED;border-radius:5px;border:none;}QPushButton:hover{background:#EC524B;}"
        )
        self.contron_max = QPushButton()
        if self.isMaximized() == False:
            self.contron_max.setToolTip("最大化")
        else:
            self.contron_max.setToolTip("还原")
        self.contron_max.setStyleSheet(
            "QPushButton{background:#FFFDF9;border-radius:5px;border:none;}QPushButton:hover{background:#F5B461;}"
        )
        self.control_min = QPushButton()
        self.control_min.setToolTip("最小化")
        self.control_min.setStyleSheet(
            "QPushButton{background:#BEEBE9;border-radius:5px;border:none;}QPushButton:hover{background:#F3EAC2;}"
        )
        self.start_button = QPushButton("开始(&S)")
        self.start_button.setStyleSheet(
            "QPushButton{background:#9BE3DE;border:none;border-radius:5px;font-size:20px;font-family:DengXian;}QPushButton:hover{background:#9AD3BC;}"
        )
        self.start_button.setToolTip("开始")
        self.start_button.setFixedSize(120, 60)
        self.start_button.setDefault(True)
        setting_button = QPushButton("设置")
        setting_button.setToolTip("设置")
        setting_button.setFixedSize(60, 60)
        setting_button.setStyleSheet(
            "QPushButton{background:#9BE3DE;border:none;border-radius:5px;font-size:20px;font-family:DengXian;}QPushButton:hover{background:#9AD3BC;}"
        )
        setting_button.clicked.connect(self.setting_callback)
        start = QHBoxLayout()
        start.addWidget(self.start_button, 2)
        start.addWidget(setting_button, 1)
        self.control_close.clicked.connect(self.close)
        self.control_min.clicked.connect(self.min_callback)
        self.contron_max.clicked.connect(self.max_callback)
        self.start_button.clicked.connect(self.start_callback)
        self.work_thread.started.connect(self.work.start)
        self.finish_signal.connect(self.finish_callback)
        self.close_qr_signal.connect(self.close_qr)
        self.control.addWidget(self.control_min)
        self.control.addWidget(self.contron_max)
        self.control.addWidget(self.control_close)
        self.main_layout.addLayout(self.control, 0, 0)
        self.main_layout.addWidget(self.title, 0, 1)
        self.main_layout.addLayout(start, 0, 2)
        self.main_layout.addWidget(handler.widget, 1, 1)
        self.update_signal.connect(handler.widget.appendPlainText)
        handler.widget.textChanged.connect(handler.scroll_widget_to_bottom)
        self.show_qr_signal.connect(self.show_qr)
        self.logger.debug("已初始化UI")

    def min_callback(self):
        if self.isMinimized() == False:
            self.showMinimized()

    def max_callback(self):
        if self.isMaximized() == False:
            self.showMaximized()
            self.contron_max.setToolTip("还原")
        else:
            self.showNormal()
            self.contron_max.setToolTip("最大化")

    def start_callback(self):
        self.start_time = time.time()
        self.work_thread.start()
        self.start_button.setEnabled(False)
        self.start_button.setText("执行中...")

    def finish_callback(self):
        self.start_button.setEnabled(True)
        self.start_button.setText("开始")
        passed_time = time.time() - self.start_time
        mins, secs = divmod(passed_time, 60)
        hours, mins = divmod(mins, 60)
        self.logger.info("执行完成,共计用时 {:0>2d}:{:0>2d}:{:0>2d}".format(
            int(hours), int(mins), int(secs)))

    def show_qr(self, qr: bytes):
        title_label = QLabel("请使用微信扫描小程序码完成登陆")
        title_label.setStyleSheet(
            "QLabel{color:#ffe3ed;border:none;background-color:transparent;border-radius:5px;}"
        )
        title_label.setAlignment(Qt.Alignment.AlignCenter)
        title_label.setFixedHeight(20)
        qr_label = QLabel()
        pixmap = QPixmap()
        pixmap.loadFromData(qr)
        qr_label.setPixmap(pixmap)
        qr_label.setStyleSheet(
            "QLabel{color:#ffe3ed;border:none;background-color:transparent;border-radius:5px;}"
        )
        layout_ = QVBoxLayout()
        layout_.addWidget(title_label, 1)
        layout_.addWidget(qr_label, 9)
        self.qr_dialog = QWidget(self)
        self.qr_dialog.setLayout(layout_)
        self.main_layout.addWidget(self.qr_dialog, 1, 1,
                                   Qt.Alignment.AlignCenter)
        self.qr_dialog.show()

    def close_qr(self):
        self.qr_dialog.close()

    def setting_callback(self):
        setting = SettingWindow(parent=self)
        setting.setStyleSheet(
            "QDialog{border:none;border-radius:5px;background:#F3EAC2;}")
        setting.show()

    def gen_conf(self):
        default_conf = {
            "debug": False,
            "hero": {
                "title": "英雄篇",
                "enabled": True,
                "times": 1
            },
            "revival": {
                "title": "复兴篇",
                "enabled": True,
                "times": 1
            },
            "creation": {
                "title": "创新篇",
                "enabled": True,
                "times": 1
            },
            "belief": {
                "title": "信念篇",
                "enabled": True,
                "times": 1
            },
            "limit_time": {
                "title": "限时赛",
                "enabled": True,
                "times": 1
            },
            "rob": {
                "title": "抢十赛",
                "enabled": True,
                "times": 1
            }
        }
        with open(file="config.json", mode="w",
                  encoding="utf-8") as conf_writer:
            conf_writer.write(
                json.dumps(default_conf,
                           indent=4,
                           sort_keys=True,
                           ensure_ascii=False))
        self.logger.info("已生成默认配置文件")

    def mousePressEvent(self, event: QMouseEvent):
        self.logger.debug("触发鼠标按压事件")
        super().mousePressEvent(event)
        self.setFocus()
        self.m_flag = True
        if event.button() == Qt.MouseButtons.LeftButton and self.isMaximized(
        ) == False and self.hasFocus() == True:
            self.old_pos = event.globalPosition()  #获取鼠标相对窗口的位置
            self.logger.debug("已获取鼠标位置")
            self.setCursor(QtGui.QCursor(
                Qt.CursorShape.SizeAllCursor))  #更改鼠标图标

    def mouseMoveEvent(self, event: QMouseEvent):
        self.logger.debug("触发鼠标移动事件")
        super().mouseMoveEvent(event)
        if self.m_flag == True:
            delta_x = int(event.globalPosition().x() - self.old_pos.x())
            delta_y = int(event.globalPosition().y() - self.old_pos.y())
            self.move(self.x() + delta_x, self.y() + delta_y)  #更改窗口位置
            self.logger.debug("已更改窗口位置")
            self.old_pos = event.globalPosition()

    def mouseReleaseEvent(self, event: QMouseEvent):
        self.logger.debug("触发鼠标释放事件")
        super().mouseReleaseEvent(event)
        self.m_flag = False
        self.setCursor(QtGui.QCursor(Qt.CursorShape.ArrowCursor))
Example #7
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setFixedSize(800, 410)
        self.setWindowTitle("PyLX16A Servo Testing Software")

        self.port_selection_box = QComboBox(self)
        self.port_selection_box.setFixedSize(200, 27)
        self.port_selection_box.move(30, 65)
        port_selection_box_label = QLabel("Select Port:", self)
        port_selection_box_label.move(30, 35)

        self.port_selection_box_refresh_button = QPushButton("Refresh", self)
        self.port_selection_box_refresh_button.setFixedSize(60, 23)
        self.port_selection_box_refresh_button.move(170, 38)

        self.id_selection_box = QListWidget(self)
        self.id_selection_box.setFixedSize(200, 200)
        self.id_selection_box.move(30, 135)
        id_selection_box_label = QLabel("Connected Servos:", self)
        id_selection_box_label.setFixedWidth(200)
        id_selection_box_label.move(30, 105)

        self.id_selection_box_refresh_button = QPushButton("Refresh", self)
        self.id_selection_box_refresh_button.setFixedSize(60, 23)
        self.id_selection_box_refresh_button.move(170, 108)

        self.set_id_line_edit = QLineEdit(self)
        self.set_id_line_edit.setFixedSize(50, 27)
        self.set_id_line_edit.move(80, 355)
        set_id_line_edit_label = QLabel("Set ID:", self)
        set_id_line_edit_label.move(30, 355)
        set_id_line_edit_label.setFixedSize(50, 27)

        self.set_id_button = QPushButton("Change ID!", self)
        self.set_id_button.setFixedSize(85, 27)
        self.set_id_button.move(145, 355)

        self.position_slider = QSlider(Qt.Orientation.Horizontal, self)
        self.position_slider.setMinimum(0)
        self.position_slider.setMaximum(240)
        self.position_slider.setFixedWidth(200)
        self.position_slider.move(300, 55)
        self.position_slider_readout = QLabel("0.00°", self)
        self.position_slider_readout.setFixedWidth(50)
        self.position_slider_readout.move(450, 30)
        self.position_slider_readout.setAlignment(
            Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
        position_slider_label = QLabel("Angle (degrees):", self)
        position_slider_label.move(300, 30)

        self.position_offset_slider = QSlider(Qt.Orientation.Horizontal, self)
        self.position_offset_slider.setMinimum(-30)
        self.position_offset_slider.setMaximum(30)
        self.position_offset_slider.setFixedWidth(200)
        self.position_offset_slider.move(300, 125)
        self.position_offset_slider_readout = QLabel("0.00°", self)
        self.position_offset_slider_readout.setFixedWidth(50)
        self.position_offset_slider_readout.move(450, 100)
        self.position_offset_slider_readout.setAlignment(
            Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
        position_offset_slider_label = QLabel("Angle offset (degrees):", self)
        position_offset_slider_label.setFixedWidth(200)
        position_offset_slider_label.move(300, 100)

        self.angle_lower_limit_textentry = QLineEdit(self)
        self.angle_lower_limit_textentry.setFixedWidth(50)
        self.angle_lower_limit_textentry.move(450, 175)
        self.angle_lower_limit_textentry.setValidator(
            QIntValidator(0, 240, self))
        self.angle_upper_limit_textentry = QLineEdit(self)
        self.angle_upper_limit_textentry.setFixedWidth(50)
        self.angle_upper_limit_textentry.move(450, 210)
        self.angle_upper_limit_textentry.setValidator(
            QIntValidator(0, 240, self))
        self.angle_lower_limit_textentry_label = QLabel(
            "Lower Limit (degrees):", self)
        self.angle_lower_limit_textentry_label.move(300, 175)
        self.angle_lower_limit_textentry_label.setFixedWidth(150)
        self.angle_upper_limit_textentry_label = QLabel(
            "Upper Limit (degrees):", self)
        self.angle_upper_limit_textentry_label.move(300, 210)
        self.angle_upper_limit_textentry_label.setFixedWidth(150)

        self.vin_lower_limit_textentry = QLineEdit(self)
        self.vin_lower_limit_textentry.setFixedWidth(50)
        self.vin_lower_limit_textentry.move(450, 265)
        self.vin_lower_limit_textentry.setValidator(
            QIntValidator(4500, 12000, self))
        self.vin_upper_limit_textentry = QLineEdit(self)
        self.vin_upper_limit_textentry.setFixedWidth(50)
        self.vin_upper_limit_textentry.move(450, 300)
        self.vin_upper_limit_textentry.setValidator(
            QIntValidator(4500, 12000, self))
        self.vin_lower_limit_textentry_label = QLabel(
            "Voltage Lower Limit (mV):", self)
        self.vin_lower_limit_textentry_label.move(300, 265)
        self.vin_lower_limit_textentry_label.setFixedWidth(150)
        self.vin_upper_limit_textentry_label = QLabel(
            "Voltage Upper Limit (mV):", self)
        self.vin_upper_limit_textentry_label.move(300, 300)
        self.vin_upper_limit_textentry_label.setFixedWidth(150)

        self.temp_limit_textentry = QLineEdit(self)
        self.temp_limit_textentry.setFixedWidth(50)
        self.temp_limit_textentry.move(450, 355)
        self.temp_limit_textentry.setValidator(QIntValidator(50, 100, self))
        self.temp_limit_textentry_label = QLabel("Temp Limit (°C):", self)
        self.temp_limit_textentry_label.move(300, 355)
        self.temp_limit_textentry_label.setFixedWidth(150)

        self.servo_mode_radio_button = QRadioButton("Servo Mode", self)
        self.servo_mode_radio_button.move(565, 50)
        self.motor_mode_radio_button = QRadioButton("Motor Mode", self)
        self.motor_mode_radio_button.move(565, 75)

        self.motor_speed_slider = QSlider(Qt.Orientation.Horizontal, self)
        self.motor_speed_slider.setMinimum(-1000)
        self.motor_speed_slider.setMaximum(1000)
        self.motor_speed_slider.setFixedWidth(200)
        self.motor_speed_slider.move(565, 125)
        motor_speed_slider_label = QLabel("Motor Speed:", self)
        motor_speed_slider_label.move(565, 100)

        self.torque_enabled_checkbox = QCheckBox("Torque Enabled", self)
        self.torque_enabled_checkbox.move(565, 175)
        self.torque_enabled_checkbox.setFixedWidth(200)

        self.led_enabled_checkbox = QCheckBox("LED Enabled", self)
        self.led_enabled_checkbox.move(565, 210)
        self.led_enabled_checkbox.setFixedWidth(200)

        self.led_over_temp_checkbox = QCheckBox("LED Over Temperature", self)
        self.led_over_temp_checkbox.move(565, 258)
        self.led_over_temp_checkbox.setFixedWidth(200)
        self.led_over_voltage_checkbox = QCheckBox("LED Over Voltage", self)
        self.led_over_voltage_checkbox.move(565, 283)
        self.led_over_voltage_checkbox.setFixedWidth(200)
        self.led_rotor_locked_checkbox = QCheckBox("LED Rotor Locked", self)
        self.led_rotor_locked_checkbox.move(565, 308)
        self.led_rotor_locked_checkbox.setFixedWidth(200)

        self.physical_position_readout = QLabel("--°", self)
        self.physical_position_readout.move(565, 367)
        self.physical_position_readout.setFixedWidth(200)
        self.physical_position_readout_label = QLabel("Position", self)
        self.physical_position_readout_label.move(565, 347)

        self.temperature_readout = QLabel("-- °C", self)
        self.temperature_readout.move(635, 367)
        self.temperature_readout.setFixedWidth(200)
        self.temperature_readout_label = QLabel("Temperature", self)
        self.temperature_readout_label.move(635, 347)

        self.voltage_readout = QLabel("-- V", self)
        self.voltage_readout.move(730, 367)
        self.voltage_readout.setFixedWidth(200)
        self.voltage_readout_label = QLabel("Voltage", self)
        self.voltage_readout_label.move(730, 347)

        self.readout_update_timer = QTimer(self)
        self.readout_update_timer.timeout.connect(self.update_readouts)
        self.readout_update_timer.start(250)

        self.active_servo: LX16A = None

        self.position_slider.setValue(0)
        self.position_offset_slider.setValue(0)
        self.motor_speed_slider.setValue(0)
        self.id_selection_box_refresh_button.setEnabled(False)
        self.disable_widgets()

        self.port_selection_box.currentTextChanged.connect(
            self.port_selection_box_changed)
        self.port_selection_box_refresh_button.clicked.connect(
            self.port_refresh_button_clicked)
        self.id_selection_box.currentTextChanged.connect(
            self.id_selection_box_changed)
        self.id_selection_box_refresh_button.clicked.connect(
            self.id_refresh_button_clicked)
        self.set_id_button.pressed.connect(self.id_updated)
        self.position_slider.sliderMoved.connect(self.position_slider_updated)
        self.position_offset_slider.sliderMoved.connect(
            self.position_offset_slider_updated)
        self.angle_lower_limit_textentry.textChanged.connect(
            self.angle_lower_limit_updated)
        self.angle_upper_limit_textentry.textChanged.connect(
            self.angle_upper_limit_updated)
        self.vin_lower_limit_textentry.textChanged.connect(
            self.vin_lower_limit_updated)
        self.vin_upper_limit_textentry.textChanged.connect(
            self.vin_upper_limit_updated)
        self.temp_limit_textentry.textChanged.connect(self.temp_limit_updated)
        self.servo_mode_radio_button.toggled.connect(
            self.servo_mode_radio_button_toggled)
        self.motor_mode_radio_button.toggled.connect(
            self.motor_mode_radio_button_toggled)
        self.motor_speed_slider.valueChanged.connect(
            self.motor_speed_slider_updated)
        self.torque_enabled_checkbox.stateChanged.connect(
            self.torque_enabled_checkbox_toggled)
        self.led_enabled_checkbox.stateChanged.connect(
            self.led_enabled_checkbox_toggled)
        self.led_over_temp_checkbox.stateChanged.connect(
            self.led_error_triggers_checkbox_toggled)
        self.led_over_voltage_checkbox.stateChanged.connect(
            self.led_error_triggers_checkbox_toggled)
        self.led_rotor_locked_checkbox.stateChanged.connect(
            self.led_error_triggers_checkbox_toggled)

        self.scan_for_ports()

    def disable_widgets(self):
        self.set_id_line_edit.setEnabled(False)
        self.position_slider.setEnabled(False)
        self.position_offset_slider.setEnabled(False)
        self.angle_lower_limit_textentry.setEnabled(False)
        self.angle_upper_limit_textentry.setEnabled(False)
        self.vin_lower_limit_textentry.setEnabled(False)
        self.vin_upper_limit_textentry.setEnabled(False)
        self.temp_limit_textentry.setEnabled(False)
        self.servo_mode_radio_button.setEnabled(False)
        self.motor_mode_radio_button.setEnabled(False)
        self.motor_speed_slider.setEnabled(False)
        self.torque_enabled_checkbox.setEnabled(False)
        self.led_enabled_checkbox.setEnabled(False)
        self.led_over_temp_checkbox.setEnabled(False)
        self.led_over_voltage_checkbox.setEnabled(False)
        self.led_rotor_locked_checkbox.setEnabled(False)

    def enable_widgets(self):
        self.set_id_line_edit.setEnabled(True)
        self.position_slider.setEnabled(True)
        self.position_offset_slider.setEnabled(True)
        self.angle_lower_limit_textentry.setEnabled(True)
        self.angle_upper_limit_textentry.setEnabled(True)
        self.vin_lower_limit_textentry.setEnabled(True)
        self.vin_upper_limit_textentry.setEnabled(True)
        self.temp_limit_textentry.setEnabled(True)
        self.servo_mode_radio_button.setEnabled(True)
        self.motor_mode_radio_button.setEnabled(True)
        self.motor_speed_slider.setEnabled(True)
        self.torque_enabled_checkbox.setEnabled(True)
        self.led_enabled_checkbox.setEnabled(True)
        self.led_over_temp_checkbox.setEnabled(True)
        self.led_over_voltage_checkbox.setEnabled(True)
        self.led_rotor_locked_checkbox.setEnabled(True)

    def clear_servo(self):
        self.active_servo = None

    @catch_disconnection
    def set_servo_id(self, id_):
        if not id_.isdigit():
            return

        self.active_servo = LX16A(int(id_))
        self.active_servo.enable_torque()

        self.position_slider.setValue(
            int(self.active_servo.get_physical_angle()))
        self.position_slider_readout.setText(
            f"{int(self.active_servo.get_physical_angle() * 25 / 6) * 6 / 25:0.2f}°"
        )
        self.position_offset_slider.setValue(
            int(self.active_servo.get_angle_offset()))
        self.position_offset_slider_readout.setText(
            f"{int(self.active_servo.get_angle_offset() * 25 / 6) * 6 / 25:0.2f}°"
        )
        self.angle_lower_limit_textentry.setText(
            str(int(self.active_servo.get_angle_limits()[0])))
        self.angle_upper_limit_textentry.setText(
            str(int(self.active_servo.get_angle_limits()[1])))
        self.vin_lower_limit_textentry.setText(
            str(self.active_servo.get_vin_limits()[0]))
        self.vin_upper_limit_textentry.setText(
            str(self.active_servo.get_vin_limits()[1]))
        self.temp_limit_textentry.setText(
            str(self.active_servo.get_temp_limit()))
        self.motor_speed_slider.setValue(self.active_servo.get_motor_speed(
        ) if self.active_servo.is_motor_mode() else 0)
        if self.active_servo.is_motor_mode():
            self.motor_mode_radio_button.setChecked(True)
        else:
            self.servo_mode_radio_button.setChecked(True)
        self.motor_speed_slider.setEnabled(self.active_servo.is_motor_mode())
        self.torque_enabled_checkbox.setChecked(
            self.active_servo.is_torque_enabled())
        self.led_enabled_checkbox.setChecked(
            self.active_servo.is_led_power_on())
        self.led_over_temp_checkbox.setChecked(
            self.active_servo.get_led_error_triggers()[0])
        self.led_over_voltage_checkbox.setChecked(
            self.active_servo.get_led_error_triggers()[1])
        self.led_rotor_locked_checkbox.setChecked(
            self.active_servo.get_led_error_triggers()[2])

    @catch_disconnection
    def scan_for_servos(self, port):
        self.setCursor(Qt.CursorShape.WaitCursor)

        LX16A.initialize(port)

        self.id_selection_box.clear()

        for i in range(0, 254):
            try:
                servo = LX16A(i)
                self.id_selection_box.addItem(str(i))
            except:
                pass

        self.setCursor(Qt.CursorShape.ArrowCursor)

    @catch_disconnection
    def scan_for_ports(self):
        ports = serial.tools.list_ports.comports()
        for port in ports:
            self.port_selection_box.addItem(port.device)

    @catch_disconnection
    def update_readouts(self):
        if self.active_servo is None:
            return

        try:
            self.physical_position_readout.setText(
                f"{self.active_servo.get_physical_angle():0.2f}°")
            self.temperature_readout.setText(
                f"{self.active_servo.get_temp()} °C")
            self.voltage_readout.setText(
                f"{self.active_servo.get_vin() / 1000} V")
        except (ServoTimeoutError, ServoChecksumError):
            pass

    @catch_disconnection
    def id_updated(self):
        new_id = self.set_id_line_edit.text()

        try:
            servo = LX16A(int(new_id))
        except ServoTimeoutError:
            # Meaning this ID is not taken
            self.active_servo.set_id(int(new_id))
            self.id_selection_box.item(
                self.id_selection_box.currentRow()).setText(new_id)

            return

        QMessageBox.warning(None, "Error", "ID already taken")

    @catch_disconnection
    def position_slider_updated(self, pos):
        if float(self.voltage_readout.text()[:-2]) < 5:
            QMessageBox.warning(
                None,
                "Error",
                "The voltage going through the servo is too low. Is your battery powered on?",
            )

            return
        self.active_servo.move(pos)
        self.position_slider_readout.setText(
            f"{int(pos * 25 / 6) * 6 / 25:0.2f}°")

    @catch_disconnection
    def position_offset_slider_updated(self, pos):
        self.active_servo.set_angle_offset(pos)
        self.position_offset_slider_readout.setText(
            f"{int(pos * 25 / 6) * 6 / 25:0.2f}°")

    @catch_disconnection
    def angle_lower_limit_updated(self, text):
        if (QIntValidator(0, 240, self).validate(text, 0) !=
                QIntValidator.State.Acceptable):
            return

        if int(text) > int(self.angle_upper_limit_textentry.text()):
            return

        self.active_servo.set_angle_limits(
            int(text), int(self.angle_upper_limit_textentry.text()))

    @catch_disconnection
    def angle_upper_limit_updated(self, text):
        if (QIntValidator(0, 240, self).validate(text, 0) !=
                QIntValidator.State.Acceptable):
            return

        if int(text) < int(self.angle_lower_limit_textentry.text()):
            return

        self.active_servo.set_angle_limits(
            int(self.angle_lower_limit_textentry.text()), int(text))

    @catch_disconnection
    def vin_lower_limit_updated(self, text):
        if (QIntValidator(4500, 12000, self).validate(text, 0) !=
                QIntValidator.State.Acceptable):
            return

        if int(text) > int(self.vin_upper_limit_textentry.text()):
            return

        self.active_servo.set_vin_limits(
            int(text), int(self.vin_upper_limit_textentry.text()))

    @catch_disconnection
    def vin_upper_limit_updated(self, text):
        if (QIntValidator(4500, 12000, self).validate(text, 0) !=
                QIntValidator.State.Acceptable):
            return

        if int(text) < int(self.vin_lower_limit_textentry.text()):
            return

        self.active_servo.set_vin_limits(
            int(self.vin_lower_limit_textentry.text()), int(text))

    @catch_disconnection
    def temp_limit_updated(self, text):
        if (QIntValidator(50, 100, self).validate(text, 0) !=
                QIntValidator.State.Acceptable):
            return

        self.active_servo.set_temp_limit(int(text))

    @catch_disconnection
    def servo_mode_radio_button_toggled(self, checked):
        if checked:
            self.active_servo.servo_mode()
            self.motor_speed_slider.setEnabled(False)
            self.position_slider.setEnabled(True)
            self.position_offset_slider.setEnabled(True)
        else:
            self.active_servo.motor_mode(int(self.motor_speed_slider.value()))
            self.motor_speed_slider.setEnabled(True)
            self.position_slider.setEnabled(False)
            self.position_offset_slider.setEnabled(False)

    @catch_disconnection
    def motor_mode_radio_button_toggled(self, checked):
        if checked:
            self.active_servo.motor_mode(int(self.motor_speed_slider.value()))
            self.motor_speed_slider.setEnabled(True)
            self.position_slider.setEnabled(False)
            self.position_offset_slider.setEnabled(False)
        else:
            self.active_servo.servo_mode()
            self.motor_speed_slider.setEnabled(False)
            self.position_slider.setEnabled(True)
            self.position_offset_slider.setEnabled(True)

    @catch_disconnection
    def motor_speed_slider_updated(self, pos):
        self.active_servo.motor_mode(pos)

    @catch_disconnection
    def torque_enabled_checkbox_toggled(self, checked):
        if checked:
            self.active_servo.enable_torque()
        else:
            self.active_servo.disable_torque()

        self.position_slider.setEnabled(checked)
        self.position_offset_slider.setEnabled(checked)
        self.servo_mode_radio_button.setEnabled(checked)
        self.motor_mode_radio_button.setEnabled(checked)
        self.motor_speed_slider.setEnabled(checked)

    @catch_disconnection
    def led_enabled_checkbox_toggled(self, checked):
        if checked:
            self.active_servo.led_power_on()
        else:
            self.active_servo.led_power_off()

    @catch_disconnection
    def led_error_triggers_checkbox_toggled(self):
        self.active_servo.set_led_error_triggers(
            self.led_over_voltage_checkbox.isChecked(),
            self.led_over_temp_checkbox.isChecked(),
            self.led_rotor_locked_checkbox.isChecked(),
        )

    @catch_disconnection
    def port_refresh_button_clicked(self, value):
        self.id_selection_box_refresh_button.setEnabled(False)
        self.disable_widgets()
        self.port_selection_box.clear()
        self.id_selection_box.clear()
        self.scan_for_ports()

    @catch_disconnection
    def id_refresh_button_clicked(self, value):
        self.disable_widgets()
        self.id_selection_box.clear()
        self.scan_for_servos(self.port_selection_box.currentText())

    @catch_disconnection
    def port_selection_box_changed(self, text):
        if text == "":
            return

        self.id_selection_box_refresh_button.setEnabled(True)
        self.disable_widgets()
        self.id_selection_box.clear()
        self.clear_servo()
        self.scan_for_servos(text)

    @catch_disconnection
    def id_selection_box_changed(self, text):
        if text == "":
            return

        self.enable_widgets()
        self.set_servo_id(text)
Example #8
0
class Ui_TrainPanel(object):
    def setupUi(self, TrainPanel):
        self.parent = TrainPanel
        self.mainLayout = QHBoxLayout(TrainPanel)

        self.bigFont = QLabel().font()
        self.bigFont.setPointSize(13)

        self.actionsLayout = QHBoxLayout(TrainPanel)
        # self.checkRecording = QCheckBox(TrainPanel)
        self.calibrateButton = QPushButton("Calibrate", parent=TrainPanel)
        self.calibrateButton.setFont(self.bigFont)
        self.calibrateButton.setStyleSheet(CustomQStyles.buttonStyle)
        self.calibrateButton.setMinimumHeight(50)
        self.calibrateButton.setMaximumWidth(170)
        self.calibrateButton.setMinimumWidth(120)

        self.sessionButton = QPushButton("Session", parent=TrainPanel)
        self.sessionButton.setFont(self.bigFont)
        self.sessionButton.setStyleSheet(CustomQStyles.outlineButtonStyle)
        self.sessionButton.setMinimumHeight(50)
        self.sessionButton.setMaximumWidth(170)
        self.sessionButton.setMinimumWidth(120)

        self.listFiles = QListWidget(TrainPanel)
        self.listFiles.setFont(self.bigFont)
        self.label = QLabel('or select', parent=TrainPanel)
        self.subjectLayout = QVBoxLayout(TrainPanel)
        print("init")

        self.box1 = QGroupBox(parent=TrainPanel)
        self.box2 = QGroupBox(parent=TrainPanel)
        self.wizard = CalibrateWizard(parent=TrainPanel)

        self.setPatientsBox(TrainPanel)  # right panel
        self.setActionsBox(TrainPanel)  # left panel

        self.mainLayout.addWidget(self.box1, stretch=2)
        self.mainLayout.addWidget(self.box2, stretch=3)
        # self.mainLayout.setAlignment(self.box2, Qt.Alignment.AlignCenter)

    # Display progress bar, checkbox - to record new gestures or not, start train
    def setActionsBox(self, TrainPanel):
        hLayout = QVBoxLayout()
        hLayout.addWidget(self.calibrateButton)
        hLayout.addWidget(self.sessionButton)
        hLayout.setAlignment(self.calibrateButton, Qt.Alignment.AlignCenter)
        hLayout.setAlignment(self.sessionButton, Qt.Alignment.AlignCenter)
        self.box2.setLayout(hLayout)

    # Display list of subjects, or new subject
    def setPatientsBox(self, TrainPanel):

        # Button to create new patient
        self.addPatient = QPushButton('Create Patient')
        self.addPatient.setFixedSize(120, 35)
        self.addPatient.setStyleSheet(CustomQStyles.outlineButtonStyle)

        self.label.setSizePolicy(QSizePolicy.Policy.Expanding,
                                 QSizePolicy.Policy.Expanding)
        self.label.setAlignment(QtCore.Qt.Alignment.AlignCenter)

        self.loadPatientList()

        self.listFiles.setStyleSheet(CustomQStyles.listStyle)
        self.listFiles.setFocusPolicy(Qt.FocusPolicy.NoFocus)

        self.subjectLayout.addWidget(self.addPatient)
        self.subjectLayout.setAlignment(self.addPatient,
                                        Qt.Alignment.AlignCenter)
        self.subjectLayout.addWidget(self.label)
        self.subjectLayout.addWidget(self.listFiles)

        self.box1.setLayout(self.subjectLayout)

    def loadPatientList(self):
        self.listFiles.clear()
        self.parent.patients.clear()
        files = [
            f for f in listdir(PATIENTS_PATH) if isfile(join(PATIENTS_PATH, f))
        ]
        for x, ind in zip(files, range(0, len(files))):
            item = QListWidgetItem(x.split('.')[0])
            item.setTextAlignment(Qt.Alignment.AlignHCenter)
            self.listFiles.addItem(item)
            with open(PATIENTS_PATH + x, 'r') as f:
                person_dict = json.load(f)
                patient = Patient(person_dict['Name'], person_dict['Age'],
                                  person_dict['Exercises'])
                self.parent.patients.append(patient)

        print(self.parent.patients)

    def deleteItemsOfLayout(self, layout):
        if layout is not None:
            while layout.count():
                item = layout.takeAt(0)
                widget = item.widget()
                if widget is not None:
                    widget.setParent(None)
                else:
                    self.deleteItemsOfLayout(item.layout())
Example #9
0
class CalibrateWizard(QWizard):
    def __init__(self, parent):
        super().__init__(parent)
        self.parent = parent
        self.setWizardStyle(QWizard.WizardStyle.ModernStyle)

        # CREATE PAGE 1, LINE EDIT, TITLES
        buttons_layout = [QWizard.WizardButton.NextButton]
        self.page1 = QWizardPage()
        self.page1.setTitle('Select the exercises you wish to do later')
        self.page1.setSubTitle(
            'Below are listed all the available and selected exercises by you.'
        )
        self.listSelection = TwoListSelection()
        # listSelection.addAvailableItems(["item-{}".format(i) for i in range(5)])
        hLayout1 = QHBoxLayout(self.page1)
        hLayout1.addWidget(self.listSelection)

        # CREATE PAGE 2, LABEL, TITLES
        self.page2 = QWizardPage()
        self.page2.setFinalPage(True)
        self.setButtonLayout(buttons_layout)
        self.page2.setTitle('Calibrate every exercise')
        self.page2.setSubTitle(
            'Do every exercise once, record after pressing button.')
        self.contentLayout = QVBoxLayout(self.page2)
        self.hLayout2 = QHBoxLayout()

        # Create progress bar, buttons
        self.actionsLayout = QHBoxLayout()
        self.finishButton = QPushButton('Ready')
        self.finishButton.setStyleSheet(CustomQStyles.buttonStyle)
        self.finishButton.setFixedSize(120, 35)

        self.progress = QProgressBar()
        self.progress.setRange(0, 1)
        self.actionsLayout.addWidget(self.progress)
        self.actionsLayout.setAlignment(self.progress,
                                        Qt.Alignment.AlignBottom)
        self.actionsLayout.addWidget(self.finishButton)
        self.actionsLayout.setAlignment(self.finishButton,
                                        Qt.Alignment.AlignBottom)

        self.contentLayout.addLayout(self.hLayout2)
        self.contentLayout.addLayout(self.actionsLayout)
        self.actionsLayout.setContentsMargins(15, 35, 15, 0)
        itemsTextList = [
            str(self.listSelection.mInput.item(i).text())
            for i in range(self.listSelection.mInput.count())
        ]
        print("items:", itemsTextList)

        self.button(QWizard.WizardButton.NextButton).clicked.connect(
            self.onWizardNextButton)
        self.finishButton.clicked.connect(self.onWizardFinishButton)

        self.addPage(self.page1)
        self.addPage(self.page2)

        # Recording data
        self.buttons = []
        self.images = []
        self.labels = []
        self.exerciseLayouts = []
        self.recordReady = []
        self.recordThread = RecordThread(self.parent.classifyExercises)

        # Training recorded data
        self.trained = False
        self.trainThread = TrainThread(self.parent.classifyExercises)
        self.trainThread.taskFinished.connect(self.onTrainFinished)

    # Send list to next page
    def onWizardNextButton(self):
        self.setPage(1, self.page1)
        self.trained = False
        itemsTextList = [
            str(self.listSelection.mInput.item(i).text())
            for i in range(self.listSelection.mInput.count())
        ]
        # Update list
        if self.parent.classifyExercises is not None:
            self.parent.classifyExercises.UpdateExerciseList(itemsTextList)

        # Set elements on UI
        self.setMinimumWidth(len(itemsTextList) * 200)
        self.deleteItemsOfLayout(self.hLayout2)
        self.images.clear()
        self.labels.clear()
        self.buttons.clear()
        self.recordReady.clear()
        for x, i in zip(itemsTextList, range(len(itemsTextList))):
            self.exerciseLayouts.append(QVBoxLayout())
            self.buttons.append(QPushButton('Record'))
            self.recordReady.append(False)
            image = QLabel()
            image.setPixmap(
                QPixmap(os.getcwd() + "/resources/images/" + itemsTextList[i] +
                        ".png"))
            self.labels.append(QLabel(itemsTextList[i]))
            self.images.append(image)
            self.buttons[i].setFixedSize(100, 35)
            self.buttons[i].clicked.connect(
                functools.partial(self.onRecordExerciseButtonClicked, x, i))
            self.buttons[i].setStyleSheet(CustomQStyles.outlineButtonStyle)
            self.exerciseLayouts[i].addWidget(self.labels[i])
            self.exerciseLayouts[i].addWidget(self.images[i])
            self.exerciseLayouts[i].addWidget(self.buttons[i])
            self.exerciseLayouts[i].setAlignment(self.labels[i],
                                                 Qt.Alignment.AlignCenter)
            self.exerciseLayouts[i].setAlignment(self.images[i],
                                                 Qt.Alignment.AlignCenter)
            self.exerciseLayouts[i].setAlignment(self.buttons[i],
                                                 Qt.Alignment.AlignCenter)
            self.hLayout2.addLayout(self.exerciseLayouts[i])

    def onRecordExerciseButtonClicked(self, exercise, ind):
        print("Recording - ", exercise)
        if self.parent.classifyExercises is not None:
            self.recordThread.exercise = exercise
            self.recordThread.taskFinished.connect(
                functools.partial(self.recordFinished, exercise, ind),
                Qt.ConnectionType.SingleShotConnection)
            self.recordThread.start()
            self.recordReady[ind] = False
            self.buttons[ind].setStyleSheet(CustomQStyles.recordButtonStyle)
            self.images[ind].setPixmap(
                QPixmap(os.getcwd() + "/resources/images/" + exercise +
                        ".png"))

    def recordFinished(self, exercise, index):
        imagePath = os.getcwd() + "/resources/images/" + exercise + ".png"
        if self.recordThread.result == 0:
            imagePath = os.getcwd(
            ) + "/resources/images/" + exercise + "-fail.png"
        elif self.recordThread.result == 1:
            imagePath = os.getcwd(
            ) + "/resources/images/" + exercise + "-success.png"
            self.recordReady[index] = True
        else:
            print("None.")
        self.images[index].setPixmap(QPixmap(imagePath))
        self.buttons[index].setStyleSheet(CustomQStyles.outlineButtonStyle)
        print(self.recordReady)

    def onWizardFinishButton(self):
        if all(x == True for x in self.recordReady):
            print("All recorded!")
            if not self.trained:
                if self.parent.classifyExercises is not None:
                    self.progress.setRange(0, 0)  # indefinite progress bar
                    self.parent.classifyExercises.SaveProcessedData()
                    self.parent.classifyExercises.SavePatientData()
                    self.parent.ui.loadPatientList()
                    self.trainThread.start()

            else:
                self.close()

        else:
            print("Not all recorded!")

    def onTrainFinished(self):
        self.progress.setRange(0, 1)
        self.progress.setValue(1)
        self.trained = True
        CustomMessage.showDialog("Message", "Training model finished!",
                                 QMessageBox.StandardButtons.Ok)
        self.finishButton.setText('Finish')

    def deleteItemsOfLayout(self, layout):
        if layout is not None:
            while layout.count():
                item = layout.takeAt(0)
                widget = item.widget()
                if widget is not None:
                    widget.setParent(None)
                else:
                    self.deleteItemsOfLayout(item.layout())