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)
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"))
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 += ' • ' + 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)