def __init__(self, cover_path, figure_info, figure_title,
                 figure_score, figure_desc, figure_count, video_url, cover_url, img_path, *args, **kwargs):
        super(ItemWidget, self).__init__(*args, **kwargs)
        self.setMaximumSize(220, 380)
        self.setMaximumSize(220, 380)
        self.img_path = img_path
        self.cover_url = cover_url
        layout = QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        # 图片label
        self.clabel = CoverLabel(cover_path, figure_info, video_url, self)
        layout.addWidget(self.clabel)

        # 片名和分数
        flayout = QHBoxLayout()
        flayout.addWidget(QLabel(figure_title, self))
        flayout.addItem(QSpacerItem(
            20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
        flayout.addWidget(QLabel(figure_score, self, styleSheet="color: red;"))
        layout.addLayout(flayout)

        # 主演
        layout.addWidget(
            QLabel(figure_desc, self, styleSheet="color: #999999;", openExternalLinks=True))

        # 播放量
        blayout = QHBoxLayout()
        count_icon = QSvgWidget(self)
        count_icon.setMaximumSize(16, 16)
        count_icon.load(Svg_icon_play_sm)
        blayout.addWidget(count_icon)
        blayout.addWidget(
            QLabel(figure_count, self, styleSheet="color: #999999;"))
        layout.addLayout(blayout)
class MissevanKit(QMainWindow, Ui_mainWindow):
    def __init__(self, parent=None):
        super(MissevanKit, self).__init__(parent)
        self.setupUi(self)
        # self.set_style()
        self.center()
        self.setTab1()
        self.setTab2()
        self.setTab3()
        self.setTab4()
        self.gen_data_thread = None
        self.collect_thread = None
        self.tab_1_log = gen_date_filename(APP_LogPath, "数据采集日志.txt")
        self.tab_2_log = gen_date_filename(APP_LogPath, "数据处理日志.txt")

    # self.tabWidget.setCurrentIndex(0)

    def center(self):  # 实现窗体在屏幕中央
        screen = QDesktopWidget().screenGeometry()
        size = self.geometry()  # 同上
        self.move((screen.width() - size.width()) / 2,
                  (screen.height() - size.height()) / 4)

    def setTab1(self):
        self.pushButton.clicked.connect(self.start_collect)
        self.pushButton_2.clicked.connect(lambda: self.collect_progress(STOP))
        self.pushButton_9.clicked.connect(self.set_choose_rect_brower)
        # self.pushButton_4.clicked.connect(lambda: self.set_browser_collapse(self.textBrowser_3))

    def gen_tab1_config(self):
        # worktime
        # 是否只是工作日抓取
        GLOBAL_CONFIG[ONLY_WORK_DAY] = False
        if self.checkBox.isChecked():
            GLOBAL_CONFIG[ONLY_WORK_DAY] = True
        if self.radioButton_5.isChecked():
            if self.textEdit.toPlainText():
                try:
                    GLOBAL_CONFIG[WORK_TIME] = [
                        int(i) for i in self.textEdit.toPlainText().split()
                    ]
                except:
                    self.echo_error('抓取的时间点输入格式不对,24小时制,用空格分隔')
                    return False
            else:
                self.echo_error('抓取的时间点(小时)为空,请检查')
                return False
        elif self.radioButton_4.isChecked():
            GLOBAL_CONFIG[WORK_TIME] = [i for i in range(24)]
        elif self.radioButton_3.isChecked():
            GLOBAL_CONFIG[WORK_TIME] = [i for i in range(7, 9)
                                        ] + [i for i in range(17, 19)]
        elif self.radioButton_2.isChecked():
            GLOBAL_CONFIG[WORK_TIME] = [i for i in range(17, 19)]
        elif self.radioButton.isChecked():
            GLOBAL_CONFIG[WORK_TIME] = [i for i in range(7, 9)]

        if self.textEdit_left.toPlainText():
            # 左下角换到左上角
            left_p = self.textEdit_left.toPlainText().split(',')
            right_p = self.textEdit_right.toPlainText().split(',')
            GLOBAL_CONFIG[LEFT_POINT] = [left_p[0], right_p[1]]
            GLOBAL_CONFIG[RIGHT_POINT] = [right_p[0], left_p[1]]
        else:
            self.echo_error('矩形区域为空,请检查')
            return False

        if self.textEdit_9.toPlainText():
            try:
                spacing_time = int(self.textEdit_9.toPlainText())
                if spacing_time < 0:
                    self.echo_error('间隔时间不能小于0,请重新输入')
                    return False
                GLOBAL_CONFIG[SPACING_TIME] = spacing_time
            except:
                self.echo_error('间隔时间输入错误,请检查')

        else:
            self.echo_error('间隔时间为空,请检查')
            return False
        return True

    def start_collect(self):
        if self.gen_tab1_config():
            write_to_log(self.tab_1_log, "程序开始运行...")
            write_to_log(self.tab_1_log, GLOBAL_CONFIG)
            # 初始化
            if self.collect_thread:
                self.collect_thread.terminate()
                self.collect_thread = None
            self.collect_thread = CollectThread()
            self.collect_thread.sinOut.connect(self.collect_progress)
            self.collect_thread.start()
            # 循环滚动
            self.progressBar.setMaximum(0)
            self.pushButton.setEnabled(False)
            self.pushButton_2.setEnabled(True)

    def collect_progress(self, flag):
        # 向列表控件中添加条目
        if flag == STOP:
            write_to_log(self.tab_1_log, "用户终止程序")
            self.collect_thread.terminate()
            GLOBAL_CONFIG[THREAD_FLAG] = False
            self.pushButton.setEnabled(True)
            self.pushButton_2.setEnabled(False)
            self.progressBar.setMaximum(100)
        elif flag == ERROR:
            write_to_log(self.tab_1_log, "系统发生错误,请检查")
            self.collect_thread.terminate()
            GLOBAL_CONFIG[THREAD_FLAG] = False
            self.pushButton.setEnabled(True)
            self.pushButton_2.setEnabled(False)

            self.progressBar.setMaximum(100)
        else:
            write_to_log(self.tab_1_log, flag)

    def set_date_time(self):
        # datetime = Qcommon_roadDateTime.currentDateTime()
        pass

    def set_choose_rect_brower(self):
        map_win = MapWindow(self)
        map_win.rectSignal.connect(self.getRect)
        map_win.exec_()

    def set_browser_collapse(self, browser):
        if browser.isVisible():
            browser.setVisible(False)
            browser.clear()
        else:
            browser.setVisible(True)

    def getRect(self, rect):
        if rect:
            leftb = rect.split(' ')[0]
            right = rect.split(' ')[1]

            self.textEdit_left.setText(leftb)
            self.textEdit_right.setText(right)

    def setTab2(self):
        self.pushButton_14.clicked.connect(self.start_gen_data)
        self.pushButton_7.clicked.connect(self.choose_data_dir)
        # self.pushButton_choose_road.clicked.connect(self.choose_road_dialog)
        self.pushButton_13.clicked.connect(
            lambda: self.gen_data_progress(STOP))
        # self.textEdit_red.selectionChanged.connect(self.change_green_threshold)

    def change_green_threshold(self):
        try:
            red = float(self.textEdit_red.toPlainText())
            yellow = float(self.textEdit_yellow.toPlainText())
            green = float(self.textEdit_green.toPlainText())
            if is_float(red) and is_float(yellow) and is_float(green):
                if not red > yellow > green:
                    self.echo_error("输入错误,拥堵比例关系应该是红点大于橙黄点大于黄色")
                    return False
                GLOBAL_CONFIG[RED_THRESHOLD] = red
                GLOBAL_CONFIG[YELLOW_THRESHOLD] = yellow
                GLOBAL_CONFIG[GREEN_THRESHOLD] = green
                return True
            else:
                self.echo_error("输入错误 ,需要为(0-1)的小数")
                return False

        except:
            self.echo_error("输入错误,需要为(0-1)的小数")
            return False

    def gen_tab2_config(self):
        if not self.change_green_threshold():
            return False

        if self.radioButton_9.isChecked():
            GLOBAL_CONFIG[GEN_ROAD_TYPE] = ALL_ROAD
        elif self.radioButton_10.isChecked():
            GLOBAL_CONFIG[GEN_ROAD_TYPE] = FAST_ROAD
        elif self.radioButton_11.isChecked():
            GLOBAL_CONFIG[GEN_ROAD_TYPE] = COMMON_ROAD
        data_dir = self.textEdit_7.toPlainText()
        if data_dir:
            flag = False
            for roots, dirs, files in os.walk(data_dir):
                for f in files:
                    if f.endswith('npz'):
                        flag = True
            if not flag:
                self.echo_error('数据所在路径中没有所需要的数据文件,请检查')
                return False
            if data_dir.endswith(os.sep):
                GLOBAL_CONFIG[DATA_DIR] = data_dir
            else:
                GLOBAL_CONFIG[DATA_DIR] = data_dir + os.sep
        else:
            self.echo_error('数据所在路径不能为空,请检查')
            return False

        return True

    def choose_road_dialog(self):
        road, ok = QInputDialog.getItem(self, "选择指定道路", "'全部'代表所有道路\n\n请选择道路:",
                                        ROAD_DATAS, 1, True)
        if ok:
            if road:
                self.textEdit_11.setText(road)
                if road == ROAD_DATAS[0]:
                    pass

    def start_gen_data(self):
        if self.gen_tab2_config():
            print(GLOBAL_CONFIG)
            write_to_log(self.tab_2_log, "程序开始运行...")
            write_to_log(self.tab_2_log, GLOBAL_CONFIG)
            self.pushButton_14.setEnabled(False)
            self.pushButton_13.setEnabled(True)
            if self.gen_data_thread:
                self.gen_data_thread.terminate()
                self.gen_data_thread = None
            self.progressBar_3.setValue(0)
            self.gen_data_thread = GenDataThread()
            self.gen_data_thread.sinOut.connect(self.gen_data_progress)
            self.gen_data_thread.start()

    def gen_data_progress(self, flag):
        if flag == STOP:
            write_to_log(self.tab_2_log, "用户终止程序")
            self.gen_data_thread.terminate()
            GLOBAL_CONFIG[THREAD_FLAG] = False
            self.pushButton_14.setEnabled(True)
            self.pushButton_13.setEnabled(False)

            self.progressBar_3.setValue(0)

        elif flag == ERROR:
            write_to_log(self.tab_2_log, "系统崩溃,请查明原因")
            self.echo("系统崩溃,请查明原因")
            self.gen_data_thread.terminate()
            GLOBAL_CONFIG[THREAD_FLAG] = False
            self.pushButton_14.setEnabled(True)
            self.pushButton_13.setEnabled(False)
            self.progressBar_3.setValue(0)

        elif flag == SUCCESS:
            write_to_log(self.tab_2_log, "数据生成完成,可进入识别或评价标签进行处理")
            self.echo("数据生成完成,可进入识别或评价标签进行处理")
            self.webview.reload()
            GLOBAL_CONFIG[THREAD_FLAG] = False
            self.pushButton_14.setEnabled(True)
            self.pushButton_13.setEnabled(False)

            self.progressBar_3.setValue(100)

        else:
            try:
                flag = int(flag)
                self.progressBar_3.setValue(flag)
            except:
                write_to_log(self.tab_2_log, flag)

    def choose_data_dir(self):
        dir = QFileDialog.getExistingDirectory(self, "选择数据文件夹", APP_DirPath)
        if dir:
            self.textEdit_7.setText(dir)

    def setTab3(self):
        self.setLoading()
        self.setBrower()

    def setLoading(self):
        self.loadWidget = QSvgWidget()
        self.loadWidget.setMaximumSize(QSize(60, 60))
        self.loadWidget.load(Svg_icon_loading)
        self.gridLayout_2.addWidget(self.loadWidget)
        self.loadWidget.setVisible(False)

    def setLoadStarted(self):
        self.loadWidget.setVisible(True)
        print('开始')

    def setLoadFinished(self, ):
        self.webview.setVisible(True)
        self.loadWidget.setVisible(False)

    def setBrower(self):
        self.webview = QWebEngineView()
        html_path = APP_HtmlPath + os.sep + "index.html"
        self.webview.load(QUrl.fromLocalFile(html_path))
        self.gridLayout_2.addWidget(self.webview)
        self.webview.setVisible(False)
        self.webview.page().loadStarted.connect(self.setLoadStarted)
        self.webview.page().loadFinished.connect(self.setLoadFinished)

    def setTab4(self):
        self.pushButton_16.clicked.connect(self.export_excel)
        self.pushButton_15.clicked.connect(self.gen_table)

    def gen_table(self):

        time_weight = self.textEdit_timeweight.toPlainText()
        if time_weight:
            time_weight = float(time_weight)
        else:
            self.echo_error('拥堵时长权重不能为空,请检查')
            return False
        length_weight = self.textEdit_lengthweight.toPlainText()
        if length_weight:
            length_weight = float(length_weight)
        else:
            self.echo_error('拥堵距离权重不能为空,请检查')
            return False
        # 表格处理要完全清除
        self.tableWidget.clear()
        self.tableWidget.setRowCount(0)
        self.tableWidget.setColumnCount(0)
        self.tableWidget.setSortingEnabled(True)
        self.tableWidget.horizontalHeader().setStyleSheet(
            "background-color: gray")
        self.tableWidget.setSelectionBehavior(1)
        self.tableWidget.horizontalHeader().setStretchLastSection(True)
        self.tableWidget.horizontalHeader().setSectionResizeMode(1)
        self.tableWidget.setShowGrid(True)

        file = open(JSON_FILE_PATH, 'r', encoding='utf-8')
        json_datas = json.load(file)
        time_max = max([float(x['jam_time']) for x in json_datas])
        length_max = max([float(x['distance']) for x in json_datas])
        json_datas.sort(
            key=lambda x: time_weight * float(x['jam_time']) / time_max +
            length_weight * float(x['distance']) / length_max,
            reverse=True)
        self.tableWidget.setColumnCount(len(TITLE_ROW))
        self.tableWidget.setRowCount(len(json_datas))
        self.tableWidget.setHorizontalHeaderLabels(TITLE_ROW)
        for row_index, json_data in enumerate(json_datas):
            no = json_data[JSON_NO]
            distance = json_data[JSON_DISTANCE]
            jam_time = json_data[JSON_JAM_TIME]
            start_point = json_data[JSON_START_POINT]
            start_place = json_data[JSON_START_PLACE]
            end_point = json_data[JSON_END_POINT]
            end_place = json_data[JSON_END_PLACE]
            # TODO
            date_type = json_data[JSON_DAY]
            jam_type = json_data[JSON_TYPE]
            if jam_type == 'red':
                color = '红色'
            elif jam_type == 'yellow':
                color = '橙黄'
            else:
                color = '黄色'
            if date_type == 'morning':
                day = '早高峰'
            else:
                day = '晚高峰'
            row_data = [
                no, day, start_place,
                str(start_point).replace('[', '').replace(']', ''), end_place,
                str(end_point).replace('[', '').replace(']', ''),
                float(distance), color, jam_time
            ]
            for col_index, item in enumerate(row_data):
                qitem = QTableWidgetItem()
                qitem.setTextAlignment(Qt.AlignCenter)
                # set data好,不然text排序只按字符串排
                qitem.setData(0, item)
                self.tableWidget.setItem(row_index, col_index, qitem)

    def export_excel(self):

        dir = QFileDialog.getExistingDirectory(self, "EXCEL文件保存到")
        if dir:
            file_path = gen_date_filename(dir, '-拥堵分析.xlsx')
            workbook = xw.Book()
            worksheet = workbook.sheets[0]
            rows = self.tableWidget.rowCount()
            cols = self.tableWidget.columnCount()
            rows_data = []
            for row in range(rows):
                row_data = []
                for col in range(cols):
                    data = self.tableWidget.item(row, col).text()
                    row_data.append(data)
                rows_data.append(row_data)
            worksheet.range('A1').value = EXCEL_TITLE_ROW
            worksheet.range('A2').value = rows_data
            workbook.save(file_path)
            workbook.close()
            self.echo(f"导出完成,EXCEL文件所在路径:\n{file_path}")
        else:
            self.echo_error("EXCEL文件存储路径不能为空")
            return False

    def echo(self, value):
        '''显示对话框返回值'''
        box = QMessageBox(self)
        box.information(self, "操作成功", "{}\n".format(value), QMessageBox.Ok)

    def echo_error(self, value):
        box = QMessageBox(self)
        box.warning(self, "错误", "{}\n".format(value), QMessageBox.Ok)
示例#3
0
class Ui_GpsoDisplayWindow(object):
    def setupUi(self, GpsoDisplayWindow):
        GpsoDisplayWindow.setObjectName("GpsoDisplayWindow")
        GpsoDisplayWindow.resize(1165, 626)
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(GpsoDisplayWindow)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.line = QtWidgets.QFrame(GpsoDisplayWindow)
        self.line.setFrameShape(QtWidgets.QFrame.VLine)
        self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line.setObjectName("line")
        self.horizontalLayout.addWidget(self.line)
        self.svg_widget = QSvgWidget(GpsoDisplayWindow)
        self.svg_widget.setMinimumSize(QtCore.QSize(500, 500))
        self.svg_widget.setMaximumSize(QtCore.QSize(500, 500))
        self.svg_widget.setObjectName("svg_widget")
        self.horizontalLayout.addWidget(self.svg_widget)
        self.verticalLayout_5 = QtWidgets.QVBoxLayout()
        self.verticalLayout_5.setObjectName("verticalLayout_5")
        self.verticalLayout_7 = QtWidgets.QVBoxLayout()
        self.verticalLayout_7.setObjectName("verticalLayout_7")
        self.line_3 = QtWidgets.QFrame(GpsoDisplayWindow)
        self.line_3.setFrameShape(QtWidgets.QFrame.HLine)
        self.line_3.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_3.setObjectName("line_3")
        self.verticalLayout_7.addWidget(self.line_3)
        self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_5.setObjectName("horizontalLayout_5")
        self.verticalLayout_13 = QtWidgets.QVBoxLayout()
        self.verticalLayout_13.setObjectName("verticalLayout_13")
        self.toggle_series_label = QtWidgets.QLabel(GpsoDisplayWindow)
        self.toggle_series_label.setObjectName("toggle_series_label")
        self.verticalLayout_13.addWidget(self.toggle_series_label)
        self.horizontalLayout_21 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_21.setObjectName("horizontalLayout_21")
        spacerItem = QtWidgets.QSpacerItem(13, 25, QtWidgets.QSizePolicy.Fixed,
                                           QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_21.addItem(spacerItem)
        self.bst_checkbox = QtWidgets.QCheckBox(GpsoDisplayWindow)
        self.bst_checkbox.setChecked(True)
        self.bst_checkbox.setObjectName("bst_checkbox")
        self.horizontalLayout_21.addWidget(self.bst_checkbox)
        self.verticalLayout_13.addLayout(self.horizontalLayout_21)
        self.horizontalLayout_22 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_22.setObjectName("horizontalLayout_22")
        spacerItem1 = QtWidgets.QSpacerItem(13, 25,
                                            QtWidgets.QSizePolicy.Fixed,
                                            QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_22.addItem(spacerItem1)
        self.wst_checkbox = QtWidgets.QCheckBox(GpsoDisplayWindow)
        self.wst_checkbox.setChecked(True)
        self.wst_checkbox.setObjectName("wst_checkbox")
        self.horizontalLayout_22.addWidget(self.wst_checkbox)
        self.verticalLayout_13.addLayout(self.horizontalLayout_22)
        self.horizontalLayout_23 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_23.setObjectName("horizontalLayout_23")
        spacerItem2 = QtWidgets.QSpacerItem(13, 25,
                                            QtWidgets.QSizePolicy.Fixed,
                                            QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_23.addItem(spacerItem2)
        self.avg_checkbox = QtWidgets.QCheckBox(GpsoDisplayWindow)
        self.avg_checkbox.setChecked(True)
        self.avg_checkbox.setObjectName("avg_checkbox")
        self.horizontalLayout_23.addWidget(self.avg_checkbox)
        self.verticalLayout_13.addLayout(self.horizontalLayout_23)
        self.horizontalLayout_24 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_24.setObjectName("horizontalLayout_24")
        spacerItem3 = QtWidgets.QSpacerItem(13, 25,
                                            QtWidgets.QSizePolicy.Fixed,
                                            QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_24.addItem(spacerItem3)
        self.std_checkbox = QtWidgets.QCheckBox(GpsoDisplayWindow)
        self.std_checkbox.setChecked(True)
        self.std_checkbox.setObjectName("std_checkbox")
        self.horizontalLayout_24.addWidget(self.std_checkbox)
        self.verticalLayout_13.addLayout(self.horizontalLayout_24)
        self.horizontalLayout_5.addLayout(self.verticalLayout_13)
        self.horizontalLayout_11 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_11.setObjectName("horizontalLayout_11")
        self.line_5 = QtWidgets.QFrame(GpsoDisplayWindow)
        self.line_5.setFrameShape(QtWidgets.QFrame.VLine)
        self.line_5.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_5.setObjectName("line_5")
        self.horizontalLayout_11.addWidget(self.line_5)
        self.verticalLayout_3 = QtWidgets.QVBoxLayout()
        self.verticalLayout_3.setObjectName("verticalLayout_3")
        self.label_2 = QtWidgets.QLabel(GpsoDisplayWindow)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
                                           QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.label_2.sizePolicy().hasHeightForWidth())
        self.label_2.setSizePolicy(sizePolicy)
        self.label_2.setObjectName("label_2")
        self.verticalLayout_3.addWidget(self.label_2)
        self.horizontalLayout_12 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_12.setObjectName("horizontalLayout_12")
        self.n_pop_label = QtWidgets.QLabel(GpsoDisplayWindow)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
                                           QtWidgets.QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.n_pop_label.sizePolicy().hasHeightForWidth())
        self.n_pop_label.setSizePolicy(sizePolicy)
        self.n_pop_label.setAutoFillBackground(False)
        self.n_pop_label.setObjectName("n_pop_label")
        self.horizontalLayout_12.addWidget(self.n_pop_label)
        self.n_pop_indicator = QtWidgets.QLabel(GpsoDisplayWindow)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
                                           QtWidgets.QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.n_pop_indicator.sizePolicy().hasHeightForWidth())
        self.n_pop_indicator.setSizePolicy(sizePolicy)
        font = QtGui.QFont()
        font.setPointSize(8)
        font.setBold(False)
        font.setWeight(50)
        self.n_pop_indicator.setFont(font)
        self.n_pop_indicator.setAutoFillBackground(False)
        self.n_pop_indicator.setObjectName("n_pop_indicator")
        self.horizontalLayout_12.addWidget(self.n_pop_indicator)
        spacerItem4 = QtWidgets.QSpacerItem(104, 19,
                                            QtWidgets.QSizePolicy.Expanding,
                                            QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_12.addItem(spacerItem4)
        self.verticalLayout_3.addLayout(self.horizontalLayout_12)
        self.horizontalLayout_15 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_15.setObjectName("horizontalLayout_15")
        self.n_shape_label = QtWidgets.QLabel(GpsoDisplayWindow)
        self.n_shape_label.setAutoFillBackground(False)
        self.n_shape_label.setObjectName("n_shape_label")
        self.horizontalLayout_15.addWidget(self.n_shape_label)
        self.n_shape_indicator = QtWidgets.QLabel(GpsoDisplayWindow)
        font = QtGui.QFont()
        font.setPointSize(8)
        font.setBold(False)
        font.setWeight(50)
        self.n_shape_indicator.setFont(font)
        self.n_shape_indicator.setAutoFillBackground(False)
        self.n_shape_indicator.setObjectName("n_shape_indicator")
        self.horizontalLayout_15.addWidget(self.n_shape_indicator)
        spacerItem5 = QtWidgets.QSpacerItem(345, 25,
                                            QtWidgets.QSizePolicy.Expanding,
                                            QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_15.addItem(spacerItem5)
        self.verticalLayout_3.addLayout(self.horizontalLayout_15)
        self.horizontalLayout_13 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_13.setObjectName("horizontalLayout_13")
        self.fitness_label = QtWidgets.QLabel(GpsoDisplayWindow)
        self.fitness_label.setMaximumSize(QtCore.QSize(55, 16777215))
        self.fitness_label.setAutoFillBackground(False)
        self.fitness_label.setObjectName("fitness_label")
        self.horizontalLayout_13.addWidget(self.fitness_label)
        self.fitness_indicator = QtWidgets.QLabel(GpsoDisplayWindow)
        font = QtGui.QFont()
        font.setPointSize(8)
        font.setBold(False)
        font.setWeight(50)
        self.fitness_indicator.setFont(font)
        self.fitness_indicator.setAutoFillBackground(False)
        self.fitness_indicator.setObjectName("fitness_indicator")
        self.horizontalLayout_13.addWidget(self.fitness_indicator)
        spacerItem6 = QtWidgets.QSpacerItem(3, 22,
                                            QtWidgets.QSizePolicy.Expanding,
                                            QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_13.addItem(spacerItem6)
        self.verticalLayout_3.addLayout(self.horizontalLayout_13)
        self.horizontalLayout_16 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_16.setObjectName("horizontalLayout_16")
        self.distance_label = QtWidgets.QLabel(GpsoDisplayWindow)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
                                           QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.distance_label.sizePolicy().hasHeightForWidth())
        self.distance_label.setSizePolicy(sizePolicy)
        self.distance_label.setMaximumSize(QtCore.QSize(100, 16777215))
        self.distance_label.setAutoFillBackground(False)
        self.distance_label.setObjectName("distance_label")
        self.horizontalLayout_16.addWidget(self.distance_label)
        self.distance_indicator = QtWidgets.QLabel(GpsoDisplayWindow)
        font = QtGui.QFont()
        font.setPointSize(8)
        font.setBold(False)
        font.setWeight(50)
        self.distance_indicator.setFont(font)
        self.distance_indicator.setAutoFillBackground(False)
        self.distance_indicator.setObjectName("distance_indicator")
        self.horizontalLayout_16.addWidget(self.distance_indicator)
        spacerItem7 = QtWidgets.QSpacerItem(3, 22,
                                            QtWidgets.QSizePolicy.Expanding,
                                            QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_16.addItem(spacerItem7)
        self.verticalLayout_3.addLayout(self.horizontalLayout_16)
        self.horizontalLayout_17 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_17.setObjectName("horizontalLayout_17")
        self.iter_label = QtWidgets.QLabel(GpsoDisplayWindow)
        font = QtGui.QFont()
        font.setPointSize(8)
        font.setBold(False)
        font.setWeight(50)
        self.iter_label.setFont(font)
        self.iter_label.setAutoFillBackground(False)
        self.iter_label.setObjectName("iter_label")
        self.horizontalLayout_17.addWidget(self.iter_label)
        self.iter_indicator = QtWidgets.QLabel(GpsoDisplayWindow)
        font = QtGui.QFont()
        font.setPointSize(8)
        font.setBold(False)
        font.setWeight(50)
        self.iter_indicator.setFont(font)
        self.iter_indicator.setAutoFillBackground(False)
        self.iter_indicator.setObjectName("iter_indicator")
        self.horizontalLayout_17.addWidget(self.iter_indicator)
        spacerItem8 = QtWidgets.QSpacerItem(40, 25,
                                            QtWidgets.QSizePolicy.Expanding,
                                            QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_17.addItem(spacerItem8)
        self.verticalLayout_3.addLayout(self.horizontalLayout_17)
        self.horizontalLayout_18 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_18.setObjectName("horizontalLayout_18")
        self.update_label = QtWidgets.QLabel(GpsoDisplayWindow)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
                                           QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.update_label.sizePolicy().hasHeightForWidth())
        self.update_label.setSizePolicy(sizePolicy)
        self.update_label.setMaximumSize(QtCore.QSize(180, 16777215))
        self.update_label.setSizeIncrement(QtCore.QSize(180, 0))
        self.update_label.setAutoFillBackground(False)
        self.update_label.setObjectName("update_label")
        self.horizontalLayout_18.addWidget(self.update_label)
        self.isi_indicator = QtWidgets.QLabel(GpsoDisplayWindow)
        font = QtGui.QFont()
        font.setPointSize(8)
        font.setBold(False)
        font.setWeight(50)
        self.isi_indicator.setFont(font)
        self.isi_indicator.setAutoFillBackground(False)
        self.isi_indicator.setObjectName("isi_indicator")
        self.horizontalLayout_18.addWidget(self.isi_indicator)
        spacerItem9 = QtWidgets.QSpacerItem(50, 22,
                                            QtWidgets.QSizePolicy.Expanding,
                                            QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_18.addItem(spacerItem9)
        self.verticalLayout_3.addLayout(self.horizontalLayout_18)
        self.horizontalLayout_11.addLayout(self.verticalLayout_3)
        self.horizontalLayout_5.addLayout(self.horizontalLayout_11)
        self.line_11 = QtWidgets.QFrame(GpsoDisplayWindow)
        self.line_11.setFrameShape(QtWidgets.QFrame.VLine)
        self.line_11.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_11.setObjectName("line_11")
        self.horizontalLayout_5.addWidget(self.line_11)
        self.verticalLayout_7.addLayout(self.horizontalLayout_5)
        self.line_10 = QtWidgets.QFrame(GpsoDisplayWindow)
        self.line_10.setFrameShape(QtWidgets.QFrame.HLine)
        self.line_10.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_10.setObjectName("line_10")
        self.verticalLayout_7.addWidget(self.line_10)
        self.MplDisplay = GpsoFigureWidget(GpsoDisplayWindow)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                           QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.MplDisplay.sizePolicy().hasHeightForWidth())
        self.MplDisplay.setSizePolicy(sizePolicy)
        self.MplDisplay.setMinimumSize(QtCore.QSize(500, 250))
        self.MplDisplay.setMaximumSize(QtCore.QSize(700, 16777215))
        self.MplDisplay.setObjectName("MplDisplay")
        self.verticalLayout_7.addWidget(self.MplDisplay)
        self.message_label = QtWidgets.QLabel(GpsoDisplayWindow)
        self.message_label.setFrameShape(QtWidgets.QFrame.NoFrame)
        self.message_label.setFrameShadow(QtWidgets.QFrame.Plain)
        self.message_label.setLineWidth(0)
        self.message_label.setText("")
        self.message_label.setObjectName("message_label")
        self.verticalLayout_7.addWidget(self.message_label)
        self.verticalLayout_5.addLayout(self.verticalLayout_7)
        self.line_2 = QtWidgets.QFrame(GpsoDisplayWindow)
        self.line_2.setFrameShape(QtWidgets.QFrame.HLine)
        self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_2.setObjectName("line_2")
        self.verticalLayout_5.addWidget(self.line_2)
        self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_4.setObjectName("horizontalLayout_4")
        self.pause_button = QtWidgets.QPushButton(GpsoDisplayWindow)
        self.pause_button.setObjectName("pause_button")
        self.horizontalLayout_4.addWidget(self.pause_button)
        self.save_button = QtWidgets.QPushButton(GpsoDisplayWindow)
        self.save_button.setObjectName("save_button")
        self.horizontalLayout_4.addWidget(self.save_button)
        self.exit_button = QtWidgets.QPushButton(GpsoDisplayWindow)
        self.exit_button.setObjectName("exit_button")
        self.horizontalLayout_4.addWidget(self.exit_button)
        self.verticalLayout_5.addLayout(self.horizontalLayout_4)
        self.horizontalLayout.addLayout(self.verticalLayout_5)
        self.horizontalLayout_2.addLayout(self.horizontalLayout)

        self.retranslateUi(GpsoDisplayWindow)
        QtCore.QMetaObject.connectSlotsByName(GpsoDisplayWindow)

    def retranslateUi(self, GpsoDisplayWindow):
        _translate = QtCore.QCoreApplication.translate
        GpsoDisplayWindow.setWindowTitle(
            _translate("GpsoDisplayWindow", "𝕀mage𝔼vo"))
        self.toggle_series_label.setText(
            _translate("GpsoDisplayWindow", "Toggle series:"))
        self.bst_checkbox.setText(
            _translate("GpsoDisplayWindow", "Global best"))
        self.wst_checkbox.setText(
            _translate("GpsoDisplayWindow", "Global worst"))
        self.avg_checkbox.setText(
            _translate("GpsoDisplayWindow", "Average (x̄)"))
        self.std_checkbox.setText(_translate("GpsoDisplayWindow", "Std. (±σ)"))
        self.label_2.setText(_translate("GpsoDisplayWindow", "Stats:"))
        self.n_pop_label.setToolTip(
            _translate(
                "GpsoDisplayWindow",
                "<html><head/><body><p>The number of individuals in the population.</p></body></html>"
            ))
        self.n_pop_label.setText(
            _translate(
                "GpsoDisplayWindow",
                "<html><head/><body><p><span style=\" color:#000000;\">Population size:</span></p></body></html>"
            ))
        self.n_pop_indicator.setText(
            _translate(
                "GpsoDisplayWindow",
                "<html><head/><body><p><span style=\" font-weight:400; color:#000000;\">0</span></p></body></html>"
            ))
        self.n_shape_label.setToolTip(
            _translate(
                "GpsoDisplayWindow",
                "<html><head/><body><p>The number of shapes possessed by an individual solution.</p></body></html>"
            ))
        self.n_shape_label.setText(
            _translate(
                "GpsoDisplayWindow",
                "<html><head/><body><p><span style=\" color:#000000;\">n_shape:</span></p></body></html>"
            ))
        self.n_shape_indicator.setText(
            _translate(
                "GpsoDisplayWindow",
                "<html><head/><body><p><span style=\" font-weight:400; color:#000000;\">0</span></p></body></html>"
            ))
        self.fitness_label.setText(
            _translate(
                "GpsoDisplayWindow",
                "<html><head/><body><p><span style=\" color:#000000;\">Fitness:</span></p></body></html>"
            ))
        self.fitness_indicator.setText(
            _translate(
                "GpsoDisplayWindow",
                "<html><head/><body><p><span style=\" font-weight:400; color:#000000;\">0</span></p></body></html>"
            ))
        self.distance_label.setToolTip(
            _translate(
                "GpsoDisplayWindow",
                "<html><head/><body><p>The distance (squared euclidean) between the globals best and original image.</p></body></html>"
            ))
        self.distance_label.setText(
            _translate(
                "GpsoDisplayWindow",
                "<html><head/><body><p><span style=\" color:#000000;\">Distance:</span></p></body></html>"
            ))
        self.distance_indicator.setText(
            _translate(
                "GpsoDisplayWindow",
                "<html><head/><body><p><span style=\" font-weight:400; color:#000000;\">0</span></p></body></html>"
            ))
        self.iter_label.setToolTip(
            _translate(
                "GpsoDisplayWindow",
                "<html><head/><body><p>Number of iterations of the algorithm since it was instantiated.</p></body></html>"
            ))
        self.iter_label.setText(
            _translate(
                "GpsoDisplayWindow",
                "<html><head/><body><p><span style=\" color:#000000;\">Iterations:</span></p></body></html>"
            ))
        self.iter_indicator.setText(
            _translate(
                "GpsoDisplayWindow",
                "<html><head/><body><p><span style=\" font-weight:400; color:#000000;\">0</span></p></body></html>"
            ))
        self.update_label.setToolTip(
            _translate(
                "GpsoDisplayWindow",
                "<html><head/><body><p>The number of iterations since a new global best was achieved.</p></body></html>"
            ))
        self.update_label.setText(
            _translate(
                "GpsoDisplayWindow",
                "<html><head/><body><p><span style=\" color:#000000;\">Iter. since improvement:</span></p></body></html>"
            ))
        self.isi_indicator.setText(
            _translate(
                "GpsoDisplayWindow",
                "<html><head/><body><p><span style=\" font-weight:400; color:#000000;\">0</span></p></body></html>"
            ))
        self.pause_button.setText(_translate("GpsoDisplayWindow", "Pause"))
        self.save_button.setText(_translate("GpsoDisplayWindow", "Save state"))
        self.exit_button.setText(_translate("GpsoDisplayWindow", "Exit"))
示例#4
0
class Emulator(QWidget, ui_emulator.Ui_Emulator):
    game_found = QtCore.pyqtSignal(int, dict, str, int)
    games_loaded = QtCore.pyqtSignal()

    def __init__(self, data):
        super(Emulator, self).__init__()
        self.setupUi(self)
        self.data = data

        self.processes = { }
        self.roms = [ ]

        self.settings = QSettings('SanderTheDragon', 'Qtendo')
        self.settings_prefix = 'emulation/emulator/' + self.data['name'].lower().replace(' ', '_')

        self.config_files = self.get_config_files()

        self.settings_dialog = emulator_settings.EmulatorSettingsDialog(parent=self, data=self.data)
        self.settings_dialog.accepted.connect(lambda: self.reload_settings())
        self.settings_dialog.setWindowTitle(self.data['name'] + ' Settings')

        self.ui_create()
        self.ui_connect()

        Thread(target=self.find_games, daemon=True).start()



    def ui_create(self):
        self.pathLabel.setText(self.settings.value(self.settings_prefix + '/path', self.data['path'], type=str))

        name = self.nameLabel.text()
        name = name.replace('{NAME}', self.data['name'])
        name = name.replace('{URL}', self.data['site'])

        version = self.data['version']
        if version == 'Not Found' and len(self.pathLabel.text()) > 0:
            version_ = self.data['get_version'](self.pathLabel.text())
            if len(version) > 0:
                version = version_
        self.version_pos = name.find('{VERSION}')
        name = name[:self.version_pos] + version

        self.nameLabel.setText(name)

        if self.data['icon'].endswith('.svg'):
            self.svgWidget = QSvgWidget()
            self.svgWidget.load(':' + self.data['icon'])
            self.svgWidget.setMaximumSize(QSize(24, 24))
            self.gridLayout.addWidget(self.svgWidget, 0, 0)
        else:
            self.iconLabel = QLabel()
            self.iconLabel.setPixmap(QPixmap(':' + self.data['icon']).scaled(24, 24))
            self.gridLayout.addWidget(self.iconLabel, 0, 0)

        platformText = ''
        for platform in self.data['platforms'].keys():
            platformText += '&nbsp;&nbsp;&nbsp;&nbsp;• ' + platform + ' (' + ', '.join(self.data['platforms'][platform]) + ')<br/>'

        self.platformLabel.setText(self.platformLabel.text().replace('{PLATFORMS}', platformText))

        self.gameList.insertColumn(0)
        self.gameList.insertColumn(1)
        self.gameList.insertColumn(2)
        self.gameList.insertColumn(3)
        self.gameList.insertColumn(4)
        self.gameList.setHorizontalHeaderLabels([ 'Platform', 'ID', 'Title', 'Region', 'Path' ])
        self.gameList.horizontalHeader().setStretchLastSection(True)

        self.gameList.setContextMenuPolicy(Qt.CustomContextMenu)


    def ui_connect(self):
        self.game_found.connect(self.add_game)
        self.games_loaded.connect(self.done_loading)

        self.gameList.customContextMenuRequested.connect(lambda position: self.game_list_context_menu(position))
        self.gameList.cellDoubleClicked.connect(lambda row, column: self.launch_game(self.gameList.item(row, 4).text()))
        self.refreshButton.pressed.connect(lambda: ( self.reset_list(), Thread(target=self.find_games, daemon=True).start() ))
        self.settingsButton.pressed.connect(lambda: self.settings_dialog.exec_())
        self.filterEdit.textChanged.connect(lambda text: self.search())



    def find_games(self):
        file_types = [ ]
        for platform in self.data['platforms'].keys():
            file_types += self.data['platforms'][platform]

        logging.debug('[' + self.data['name'] + '] Searching for ( ' + ', '.join(file_types) + ' ) files')

        paths = self.settings.value('emulation/roms/paths', [ ], type=str)
        games_length = 0
        for path in paths:
            if not os.path.isdir(path):
                continue

            possible_games = utils.find_files(path, file_types)
            games_length = len(possible_games)
            logging.debug('[' + self.data['name'] + '] Found ' + str(games_length) + ' possible ROM' + ('s' if games_length != 1 else ''))
            for game in possible_games:
                index = self.gameList.rowCount()

                try:
                    rom_ = rom.Rom(game, self.data['platforms'])
                    if rom_.is_rom:
                        logging.debug('[' + self.data['name'] + '] \'' + game + '\' is a valid ROM')
                        self.roms.append(rom_)
                        info = rom_.module.get_info(game)
                        self.game_found.emit(index, info, game, games_length)
                    else:
                        logging.debug('[' + self.data['name'] + '] \'' + game + '\' is not a valid ROM')
                        games_length -= 1
                except:
                    traceback.print_exc()

        logging.debug('[' + self.data['name'] + '] Found ' + str(games_length) + ' ROM' + ('s' if games_length != 1 else ''))
        self.games_loaded.emit()


    def add_game(self, index, info, path, count):
        self.gameList.insertRow(index)

        if len(info.keys()) > 0:
            self.gameList.setItem(index, 0, QTableWidgetItem(info['platform']))
            self.gameList.setItem(index, 1, QTableWidgetItem(info['id']))
            self.gameList.setItem(index, 2, QTableWidgetItem(info['title']))
            self.gameList.setItem(index, 3, QTableWidgetItem(info['region'] + '(' + info['region_code'] + ')'))

        self.gameList.setItem(index, 4, QTableWidgetItem(path))
        self.gameList.resizeColumnsToContents()

        self.progressBar.setValue(int(100.0 / float(count) * float(index + 1)))


    def reset_list(self):
        self.refreshButton.setEnabled(False)
        self.progressBar.setValue(0)
        self.progressBar.setVisible(True)
        self.gameList.setSortingEnabled(False)
        self.gameList.setRowCount(0)
        self.roms.clear()


    def done_loading(self):
        self.gameList.setSortingEnabled(True)
        self.gameList.sortItems(1)
        self.progressBar.setVisible(False)
        self.refreshButton.setEnabled(True)
        self.search()


    def launch_game(self, path):
        if path in self.processes:
            return

        command = self.settings.value(self.settings_prefix + '/command', '{EXEC} {ARGS} {ROM}', type=str)
        command = command.replace('{EXEC}', self.settings.value(self.settings_prefix + '/path', self.data['path'], type=str))
        command = command.replace('{ARGS}', ' '.join(self.data['arguments']))
        command = command.replace('{ROM}', shlex.quote(path))
        logging.info('[' + self.data['name'] + '] Launching: `' + command + '`')

        process = QProcess(self)
        process.finished.connect(functools.partial(self.end_game, path))

        if self.settings.value('emulation/log/stdout', True, type=bool):
            process.readyReadStandardOutput.connect(functools.partial(lambda path: self.log_game(path, bytes(self.processes[path].readAllStandardOutput()).decode('utf-8')), path))

        if self.settings.value('emulation/log/stderr', True, type=bool):
            process.readyReadStandardError.connect(functools.partial(lambda path: self.log_game(path, bytes(self.processes[path].readAllStandardError()).decode('utf-8'), logging.error), path))
            process.errorOccurred.connect(functools.partial(lambda path, error: self.log_game(path, str(error), logging.error), path))

        args = shlex.split(command)
        self.processes[path] = process
        self.processes[path].start(args[0], args[1:])


    def log_game(self, path, message, method=logging.info):
        if '\n' in message:
            for line in message.split('\n'):
                self.log_game(path, line, method)
        else:
            message = utils.ansi_trim(message.strip())
            if len(message) == 0:
                return

            method('[' + self.data['name'] + ':' + path[path.rfind('/') + 1:] + '] ' + message)


    def end_game(self, path, code, status):
        if code == 0:
            logging.info('[' + self.data['name'] + '] Process for \'' + path + '\' exited')
        else:
            logging.error('[' + self.data['name'] + '] Process for \'' + path + '\' exited with non-zero code: ' + str(code))

        del self.processes[path]


    def reload_settings(self):
        self.pathLabel.setText(self.settings.value(self.settings_prefix + '/path', self.data['path'], type=str))

        name = self.nameLabel.text()
        version = self.data['get_version'](self.pathLabel.text())
        if len(version) > 0:
            name = name[:self.version_pos] + version
        self.nameLabel.setText(name)

        self.data['reload_settings']()


    def game_list_context_menu(self, position):
        menu = QMenu()
        launchAction = menu.addAction("Launch")
        menu.addSeparator()

        action = menu.exec_(self.gameList.mapToGlobal(position))

        if action == launchAction:
             self.launch_game(self.gameList.item(self.gameList.selectionModel().selectedRows()[0].row(), 4).text())


    def search(self):
        text = self.filterEdit.text()
        for i in range(self.gameList.rowCount()):
            if text.lower() in self.gameList.item(i, 2).text().lower():
                self.gameList.showRow(i)
            else:
                self.gameList.hideRow(i)