class OpenposeGUI(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("OpencvGUI") self.setWindowIcon(QIcon("icon/logo.png")) # QAction self.action_autosave = QAction(QIcon("icon/autosave.png"), "自动保存", self) self.action_save = QAction(QIcon("icon/save.png"), "保存", self) self.action_image = QAction(QIcon("icon/image.png"), "打开图片", self) self.action_video = QAction(QIcon("icon/video.png"), "打开视频", self) self.action_camera = QAction(QIcon("icon/camera.png"), "打开摄像头", self) self.action_folder = QAction(QIcon("icon/folder.png"), "打开文件夹", self) self.action_setting = QAction(QIcon("icon/setting.png"), "设置", self) self.action_filetree = QAction(QIcon("icon/filetree.png"), "目录树", self) self.action_camera.setCheckable(True) self.action_video.setCheckable(True) self.action_setting.setCheckable(True) self.action_filetree.setCheckable(True) self.action_autosave.setCheckable(True) # 菜单栏 self.menu_bar = QMenuBar() self.menu_open = self.menu_bar.addMenu("Open") self.menu_open.addAction(self.action_image) self.menu_open.addAction(self.action_video) self.menu_open.addAction(self.action_camera) self.menu_view = self.menu_bar.addMenu("View") self.menu_view.addAction(self.action_setting) self.menu_view.addAction(self.action_filetree) self.menu_function = self.menu_bar.addMenu("Function") self.action_background = self.menu_function.addAction( "Black/RGB Blackground") self.action_geture = self.menu_function.addAction( "Gesture Recognition") self.setMenuBar(self.menu_bar) # 工具栏 self.tool_bar = QToolBar() self.tool_bar.addAction(self.action_save) self.tool_bar.addAction(self.action_autosave) self.tool_bar.addSeparator() self.tool_bar.addAction(self.action_folder) self.tool_bar.addAction(self.action_camera) self.tool_bar.addAction(self.action_image) self.tool_bar.addAction(self.action_video) self.tool_bar.addSeparator() self.tool_bar.addAction(self.action_setting) self.tool_bar.addAction(self.action_filetree) self.addToolBar(self.tool_bar) # 状态栏 self.status_bar = QStatusBar() self.status_fps = QLabel("FPS:00.0") self.status_bar.addPermanentWidget(self.status_fps) self.setStatusBar(self.status_bar) # 组件 self.timer = QTimer() self.camera = Camera(self) self.setting_widget = SettingWidget(self) self.label_frame = LabelFrame(self) self.file_system_tree = FileSystemTreeView(self) self.openpose_model = OpenposeModel(self) self.media_control = MediaControl(self) self.save_widget = SaveWidget() self.gesture_model = GestureModel() # 设置dock self.dock_filetree = QDockWidget(self) self.dock_filetree.setWidget(self.file_system_tree) self.dock_file_label = QLabel("Current Directory") self.dock_file_label.setMinimumHeight(25) self.dock_file_label.setAlignment(Qt.AlignCenter | Qt.AlignHCenter) self.dock_filetree.setTitleBarWidget(self.dock_file_label) self.dock_filetree.setFeatures(QDockWidget.AllDockWidgetFeatures) self.dock_filetree.hide() self.dock_setting = QDockWidget(self) self.dock_setting.setWidget(self.setting_widget) self.dock_setting_label = QLabel("Openpose Settings") self.dock_setting_label.setMinimumHeight(25) self.dock_setting_label.setAlignment(Qt.AlignCenter | Qt.AlignHCenter) self.dock_setting.setTitleBarWidget(self.dock_setting_label) self.dock_setting.setFeatures(QDockWidget.AllDockWidgetFeatures) self.dock_setting.hide() self.dock_media = QDockWidget(self) self.dock_media.setWidget(self.media_control) self.dock_media.setFeatures(QDockWidget.NoDockWidgetFeatures) self.dock_media.hide() self.setCentralWidget(self.label_frame) self.addDockWidget(Qt.LeftDockWidgetArea, self.dock_setting) self.addDockWidget(Qt.LeftDockWidgetArea, self.dock_filetree) self.addDockWidget(Qt.BottomDockWidgetArea, self.dock_media) # 信号与槽 self.setting_widget.horizontalSlider_Body.sliderReleased.connect( self.change_body_threshold) self.setting_widget.horizontalSlider_Face.sliderReleased.connect( self.change_face_threshold) self.setting_widget.horizontalSlider_Hand.sliderReleased.connect( self.change_hand_threshold) self.setting_widget.checkBox_body.stateChanged.connect( self.check_body) # 状态改变触发check_box_changed函数 self.setting_widget.checkBox_hand.stateChanged.connect( self.check_hand) # 状态改变触发check_box_changed函数 self.setting_widget.checkBox_face.stateChanged.connect( self.check_face) # 状态改变触发check_box_changed函数 self.setting_widget.radioButton_black.toggled.connect( self.change_background) self.setting_widget.comboBox_resolution.currentIndexChanged.connect( self.change_resolution) self.media_control.play_button.toggled.connect(self.play_media) self.action_image.triggered.connect(self.open_image) self.action_video.triggered.connect(self.open_video) self.action_folder.triggered.connect(self.open_folder) self.action_camera.triggered.connect(self.open_camera) self.action_filetree.triggered.connect(self.show_filetree) self.action_setting.triggered.connect(self.show_setting) self.action_autosave.triggered.connect(self.auto_save) self.action_save.triggered.connect(self.save_current) self.action_setting.triggered.connect(self.setting_widget.show) self.file_system_tree.doubleClicked.connect(self.open_image) self.camera.timer.timeout.connect(self.update) self.timer.timeout.connect(self.save_current) def update(self): start_time = time.time() frame = self.camera.frame() self.media_control.update(self.camera.frame_pos, self.camera.frame_count) if frame is None: return None result, keypoints = self.openpose_model(frame) result, keypoints = self.gesture_recognition(result, keypoints) message = self.generate_message(keypoints) self.label_frame.update_frame(result) fps = 1 / (time.time() - start_time) self.status_fps.setText("FPS:{:.1f}".format(fps)) self.status_bar.showMessage(message, 2000) return result, keypoints def gesture_recognition(self, result, keypoints): """实现手势识别""" if self.setting_widget.gesture_on(): hands = keypoints[1] person_num = hands[0].shape[0] for i in range(person_num): for hand in hands: rect = self.gesture_model.hand_bbox(hand[i]) gesture = self.gesture_model(hand[i]) if rect: print(rect) x, y, w, h = rect cv2.rectangle(result, (x, y), (x + w, y + h), (255, 255, 255)) cv2.putText(result, gesture, (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255)) return result, keypoints def generate_message(self, keypoints): """获取识别结果信息""" if keypoints[0].size != 1: person_num = keypoints[0].shape[0] message = "person: {}".format(person_num) for i in range(person_num): message += " | person{}(".format(i + 1) if self.setting_widget.body_on(): pose_keypoints = keypoints[0][i, :, 2] pose_detected = pose_keypoints[ pose_keypoints > self.setting_widget.body_threshold()] message += "pose: {:>2d}/{}".format(pose_detected.size, 25) if self.setting_widget.hand_on(): right_hand_keypoinys = keypoints[1][0][i, :, 2] left_hand_keypoinys = keypoints[1][1][i, :, 2] right_hand_detected = right_hand_keypoinys[ right_hand_keypoinys > self.setting_widget.hand_threshold()] left_hand_detected = left_hand_keypoinys[ left_hand_keypoinys > self.setting_widget.hand_threshold()] message += " | right hand: {:>2d}/{}".format( right_hand_detected.size, 21) message += " | left hand: {:>2d}/{}".format( left_hand_detected.size, 21) message += ")" else: message = "person: {}".format(0) return message def save_current(self): if not self.label_frame.pixmap(): QMessageBox.warning(self, "Note", "No data in frame", QMessageBox.Yes) return pixmap = self.label_frame.cvimg2pixmap( self.openpose_model.get_rendered_image()) body_keypoints, hand_keypoints, face_keypoints = self.openpose_model.get_keypoints( ) body_keypoints = copy.deepcopy( body_keypoints) if self.setting_widget.body_on() else None hand_keypoints = copy.deepcopy( hand_keypoints) if self.setting_widget.hand_on() else None face_keypoints = copy.deepcopy( face_keypoints) if self.setting_widget.face_on() else None keypoints = (body_keypoints, hand_keypoints, face_keypoints) if self.timer.isActive(): self.save_widget.save(pixmap.copy(), *keypoints) else: message = self.generate_message(keypoints) self.save_widget.setFrame(pixmap.copy(), *keypoints, message) self.save_widget.show() def auto_save(self): if not self.camera.is_open(): self.action_autosave.setChecked(False) if self.action_autosave.isChecked(): self.timer.start(self.setting_widget.save_interval() * 1000) else: self.timer.stop() def update_setting(self): pass def update_openpose(self, key, value): pass # 槽函数 # 参数 def check_body(self, status): # 姿态估计 flag = True if status == Qt.Checked else False render_pose = 1 if status == Qt.Checked else 0 self.setting_widget.horizontalSlider_Body.setEnabled(flag) self.setting_widget.radioButton_black.setEnabled(flag) self.setting_widget.radioButton_rgb.setEnabled(flag) self.openpose_model.update_wrapper("render_pose", render_pose) def check_hand(self, status): # 手部估计 flag = True if status == Qt.Checked else False self.setting_widget.horizontalSlider_Hand.setEnabled(flag) self.setting_widget.checkBox_gesture.setEnabled(flag) self.openpose_model.update_wrapper("hand", flag) def check_face(self, status): # 脸部估计 flag = True if status == Qt.Checked else False self.setting_widget.horizontalSlider_Face.setEnabled(flag) self.setting_widget.checkBox_emotion.setEnabled(flag) self.openpose_model.update_wrapper("face", flag) def change_body_threshold(self): # 姿态估计阈值 value = self.setting_widget.body_threshold() self.setting_widget.label_threshold_body.setText(str(value * 100)) self.openpose_model.update_wrapper("render_threshold", value) def change_hand_threshold(self): # 手部估计阈值 value = self.setting_widget.hand_threshold() self.setting_widget.label_threshold_hand.setText(str(value * 100)) self.openpose_model.update_wrapper("hand_render_threshold", value) def change_face_threshold(self): # 脸部估计阈值 value = self.setting_widget.face_threshold() self.setting_widget.label_threshold_face.setText(str(value * 100)) self.openpose_model.update_wrapper("face_render_threshold", value) def change_resolution(self): resolution = self.setting_widget.net_resolution() self.openpose_model.update_wrapper("net_resolution", resolution) def change_background(self): # 背景 self.openpose_model.update_wrapper( "disable_blending", self.setting_widget.black_background()) # 功能 def show_setting(self): if self.dock_setting.isHidden(): self.dock_setting.show() else: self.dock_setting.hide() def show_filetree(self): if self.dock_filetree.isHidden(): self.dock_filetree.show() else: self.dock_filetree.hide() def open_image(self, file_index=None): if file_index: file = self.file_system_tree.fileSystemModel.filePath(file_index) else: file, _ = QFileDialog.getOpenFileName( self, '请选择图片', './', 'Image files(*.jpg *.png *.JPG *.PNG)') # 可设置默认路径 if not file or not file.endswith((".jpg", ".png", ".JPG", ".PNG")): return False image = cv2.imread(file) result, keypoints = self.openpose_model(image) message = self.generate_message(keypoints) # self.label_frame.resize(*image.shape[:2]) self.label_frame.update_frame(result) self.status_bar.showMessage(message) def open_video(self): if self.action_video.isChecked(): file, _ = QFileDialog.getOpenFileName( self, '请选择视频', './', 'Video files(*.mp4 *.avi)') # 可设置默认路径 if not file: self.action_video.setChecked(False) return self.camera.start(file) self.label_frame.resize(*self.camera.resolution) self.action_video.setIcon(QIcon('icon/stop.png')) self.update() # 初始化画面 self.camera.is_pause = True self.media_control.pause() self.dock_media.show() else: self.label_frame.clear() self.camera.stop() self.status_fps.setText("FPS:00.0") self.action_video.setIcon(QIcon("icon/video.png")) self.media_control.play() self.dock_media.hide() def open_folder(self): new_foler = QFileDialog.getExistingDirectory(self, '请选择目录', './') # 可设置默认路径 if not new_foler: return self.file_system_tree.alter_dir(new_foler) self.dock_filetree.show() self.status_bar.showMessage("current folder: {}".format(new_foler), 3000) def open_camera(self): if self.action_camera.isChecked(): self.camera.start() self.action_camera.setIcon(QIcon('icon/stop.png')) else: self.label_frame.clear() self.camera.stop() self.status_fps.setText("FPS:00.0") self.action_camera.setIcon(QIcon("icon/camera.png")) def play_media(self): if not self.media_control.is_play(): self.media_control.pause() self.camera.is_pause = True else: self.media_control.play() self.camera.is_pause = False
class pyviViewerWindow(QtGui.QMainWindow): def __init__(self, flowchart): QtGui.QMainWindow.__init__(self) self.resize(1000, 800) self.setWindowTitle('Viewer') self.fc = flowchart self.fc.sigChartChanged.connect(self.nodeEvent) self.fc.sigChartLoaded.connect(self.loadChartEvent) self.fc.widget().resize(1000, 800) self.pyviwin = SimpleWindow() ## http://blog.qt.io/blog/2013/02/19/introducing-qwidgetcreatewindowcontainer/ pyvi_widget = QWidget.createWindowContainer(self.pyviwin) pyvi_widget.setMinimumSize(200, 200) pyvi_widget.resize(800, 800) self.setCentralWidget(pyvi_widget) self.layerDockWidget = QDockWidget('Layers') self.layerDockWidget.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.layerDockWidget.setWidget(self.pyviwin.layerWidget) self.pyviwin.layerWidget.resize(200, 500) self.addDockWidget(Qt.RightDockWidgetArea, self.layerDockWidget) self.plotDockWidget = QDockWidget('Plot') self.plotDockWidget.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetClosable) self.plotWidget = PlotWidget() self.plotDockWidget.setWidget(self.plotWidget) self.plotWidget.resize(100, 100) # self.plotDockWidget.show() # self.addDockWidget(Qt.RightDockWidgetArea, self.plotDockWidget) self.plotList = {'plot 1': self.plotWidget} self.plot3DDockWidget = QDockWidget('Plot3D') self.plot3DDockWidget.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetClosable) self.pyviwin_plot = SimpleWindow() pyviwin_plot_widget = QWidget.createWindowContainer(self.pyviwin_plot) pyviwin_plot_widget.setMinimumSize(100, 100) pyviwin_plot_widget.resize(200, 200) self.plot3DDockWidget.setWidget(pyviwin_plot_widget) self.plot3DDockWidget.show() # self.plot3D.resize(100,100) self.plotLayerDockWidget = QDockWidget('Plot Layers') self.plotLayerDockWidget.setFeatures(QDockWidget.DockWidgetFloatable | QDockWidget.DockWidgetMovable) self.plotLayerDockWidget.setWidget(self.pyviwin_plot.layerWidget) self.pyviwin_plot.layerWidget.resize(200, 500) self.addDockWidget(Qt.RightDockWidgetArea, self.plotLayerDockWidget) # self.dockWidgetDict = {} self.createActions() self.createMenus() self.show() self.fc.widget().show() def save(self): try: self.fc.saveFile() except: raise def open(self): self.fc.loadFile() def createActions(self): self.saveAct = QAction("&Save...", self, shortcut=QtGui.QKeySequence.Save, statusTip="Save the current form letter", triggered=self.save) self.openAct = QAction("&Open...", self, shortcut=QtGui.QKeySequence.Open, statusTip="Save the current form letter", triggered=self.open) self.reloadAct = QAction("&Reload nodelibs...", self, shortcut=QtGui.QKeySequence.Refresh, statusTip="Reload nodelibraries", triggered=self.fc.widget().reloadLibrary) self.quitAct = QAction("&Quit", self, shortcut=QtGui.QKeySequence.Quit, statusTip="Quit the application", triggered=self.close) self.toggleViewerAct = QAction("&Toggle Viewer", self, statusTip="Toggle viewer window", triggered=self.toggleViewer) self.toggleFlowchartAct = QAction("&Toggle Flowchart", self, statusTip="Toggle flowchart window", triggered=self.toggleFlowchart) self.togglePlotterAct = QAction("&Toggle Plotter", self, statusTip="Toggle plot window", triggered=self.togglePlotter) def toggleViewer(self): if self.isHidden(): self.show() else: self.hide() def togglePlotter(self): if self.plotDockWidget.isHidden(): self.plotDockWidget.show() else: self.plotDockWidget.hide() def toggleFlowchart(self): if self.fc.widget().isHidden(): self.fc.widget().show() else: self.fc.widget().hide() def createMenus(self): self.fileMenu = self.menuBar().addMenu("&File") self.fileMenu.addAction(self.openAct) self.fileMenu.addAction(self.saveAct) self.fileMenu.addAction(self.reloadAct) # self.fileMenu.addSeparator() # self.fileMenu.addAction(self.quitAct) # self.editMenu = self.menuBar().addMenu("&Edit") # self.editMenu.addAction(self.undoAct) self.viewMenu = self.menuBar().addMenu("&View") self.viewMenu.addAction(self.toggleViewerAct) self.viewMenu.addAction(self.toggleFlowchartAct) self.viewMenu.addAction(self.togglePlotterAct) def loadChartEvent(self): # self.clearDock() for node in self.fc.nodes().values(): self.addNode(node) def nodeEvent(self, flowchart, action, node): if action == 'add': self.addNode(node) elif action == 'remove': self.removeNode(node) elif action == 'rename': pass # try: # self.dockWidgetDict[node].setWindowTitle(node.name()) # except KeyError: # pass def addNode(self, node): # ctrlWidget = node.ctrlWidget() # if ctrlWidget: # dock = QDockWidget(node.name(), self) # dock.setWidget(node.ctrlWidget()) # dock.hide() # # nodeDock.hideTitleBar() # # self.da.addDock(nodeDock, 'right', ) # self.addDockWidget(Qt.RightDockWidgetArea, dock) # self.viewMenu.addAction(dock.toggleViewAction()) # self.dockWidgetDict[node] = dock if type(node) is pvWindowNode: node.setPyViWindow(self.pyviwin, self.pyviwin_plot) elif type(node) is PlotWidgetNode: node.setPlotList(self.plotList) node.setPlot(self.plotWidget) def removeNode(self, node): print("removing...", node)
class GUIWindow(QMainWindow): def __init__(self, app, pipeline=Pipeline()): super().__init__() self._app = app self._logger = logging.getLogger(self.__class__.__name__) self._is_initialized = False self.init_basic(pipeline) self.init_ui() self.init_controls() self.setWindowTitle("Cognigraph") self.setWindowIcon(QIcon(':/cognigraph_icon.png')) def init_basic(self, pipeline): self._pipeline = pipeline # type: Pipeline self._updater = AsyncUpdater(self._app, pipeline) self._pipeline._signal_sender.long_operation_started.connect( self._show_progress_dialog) self._pipeline._signal_sender.long_operation_finished.connect( self._hide_progress_dialog) self._pipeline._signal_sender.request_message.connect( self._show_message) self._pipeline._signal_sender.node_widget_added.connect( self._on_node_widget_added) self._controls = Controls(pipeline=self._pipeline) self._controls.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding) self._controls.tree_widget.node_removed.connect(self._on_node_removed) if hasattr(self, "central_widget"): for w in self.central_widget.subWindowList(): self.central_widget.removeSubWindow(w) def init_controls(self): self.controls_dock.setWidget(self._controls) self.run_toggle_action.triggered.disconnect() self.run_toggle_action.triggered.connect(self._updater.toggle) self._updater._sender.run_toggled.connect(self._on_run_button_toggled) self._updater._sender.errored.connect(self._show_message) self.is_initialized = False def init_ui(self): self.central_widget = QMdiArea() self.setCentralWidget(self.central_widget) # -------- controls widget -------- # self.controls_dock = QDockWidget("Processing pipeline setup", self) self.controls_dock.setObjectName("Controls") self.controls_dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.controls_dock.visibilityChanged.connect( self._update_pipeline_tree_widget_action_text) self.addDockWidget(Qt.LeftDockWidgetArea, self.controls_dock) # self._controls.setMinimumWidth(800) # --------------------------------- # file_menu = self.menuBar().addMenu("&File") # file menu load_pipeline_action = self._createAction("&Load pipeline", self._load_pipeline) save_pipeline_action = self._createAction("&Save pipeline", self._save_pipeline) file_menu.addAction(load_pipeline_action) file_menu.addAction(save_pipeline_action) # -------- view menu & toolbar -------- # tile_windows_action = self._createAction( "&Tile windows", self.central_widget.tileSubWindows) view_menu = self.menuBar().addMenu("&View") view_menu.addAction(tile_windows_action) view_toolbar = self.addToolBar("View") view_toolbar.addAction(tile_windows_action) # ------------------------------------- # edit_menu = self.menuBar().addMenu("&Edit") self._toggle_pipeline_tree_widget_action = self._createAction( "&Hide pipeline settings", self._toggle_pipeline_tree_widget) edit_menu.addAction(self._toggle_pipeline_tree_widget_action) edit_toolbar = self.addToolBar("Edit") edit_toolbar.setObjectName("edit_toolbar") edit_toolbar.addAction(self._toggle_pipeline_tree_widget_action) # -------- run menu & toolbar -------- # self.run_toggle_action = self._createAction( "&Start", self._on_run_button_toggled) run_menu = self.menuBar().addMenu("&Run") self.initialize_pipeline = self._createAction("&Initialize pipeline", self.initialize) run_menu.addAction(self.run_toggle_action) run_menu.addAction(self.initialize_pipeline) run_toolbar = self.addToolBar("Run") run_toolbar.setObjectName("run_toolbar") run_toolbar.addAction(self.run_toggle_action) run_toolbar.addAction(self.initialize_pipeline) # ------------------------------------ # def _toggle_pipeline_tree_widget(self): if self.controls_dock.isHidden(): self.controls_dock.show() else: self.controls_dock.hide() def _update_pipeline_tree_widget_action_text(self, is_visible): if is_visible: self._toggle_pipeline_tree_widget_action.setText( "&Hide pipelne settings") else: self._toggle_pipeline_tree_widget_action.setText( "&Show pipelne settings") def _load_pipeline(self): file_dialog = QFileDialog(caption="Select pipeline file", directory=PIPELINES_DIR) ext_filter = "JSON file (*.json);; All files (*.*)" pipeline_path = file_dialog.getOpenFileName(filter=ext_filter)[0] if pipeline_path: self._logger.info("Loading pipeline configuration from %s" % pipeline_path) if not self._updater.is_paused: self.run_toggle_action.trigger() with open(pipeline_path, "r") as db: try: params_dict = json.load(db) except json.decoder.JSONDecodeError as e: self._show_message("Bad pipeline configuration file", detailed_text=str(e)) pipeline = self.assemble_pipeline(params_dict, "Pipeline") self.init_basic(pipeline) self.init_controls() # self.resize(self.sizeHint()) else: return def _save_pipeline(self): self._logger.info("Saving pipeline") file_dialog = QFileDialog(caption="Select pipeline file", directory=PIPELINES_DIR) ext_filter = "JSON file (*.json);; All files (*.*)" pipeline_path = file_dialog.getSaveFileName(filter=ext_filter)[0] if pipeline_path: self._logger.info("Saving pipeline configuration to %s" % pipeline_path) try: self._pipeline.save_pipeline(pipeline_path) except Exception as exc: self._show_message( "Cant`t save pipeline configuration to %s" % pipeline_path, detailed_text=str(exc), ) self._logger.exception(exc) def assemble_pipeline(self, d, class_name): node_class = getattr(nodes, class_name) node = node_class(**d["init_args"]) for child_class_name in d["children"]: child = self.assemble_pipeline(d["children"][child_class_name], child_class_name) node.add_child(child) return node def initialize(self): is_paused = self._updater.is_paused if not is_paused: self._updater.stop() self._logger.info("Initializing all nodes") async_initer = AsyncPipelineInitializer(pipeline=self._pipeline, parent=self) async_initer.no_blocking_execution() for node in self._pipeline.all_nodes: if hasattr(node, "widget"): if not node.widget.parent(): # widget not added to QMdiArea self._add_subwindow(node.widget, repr(node)) self.central_widget.tileSubWindows() self.run_toggle_action.setDisabled(False) if not is_paused: self._updater.start() def _finish_initialization(self): self.progress_dialog.hide() self.progress_dialog.deleteLater() for node in self._pipeline.all_nodes: if hasattr(node, "widget"): self._add_subwindow(node.widget, repr(node)) self.central_widget.tileSubWindows() def _add_subwindow(self, widget, title): sw = _HookedSubWindow(self.central_widget) sw.setWidget(widget) sw.setWindowTitle(title) widget.show() def _show_progress_dialog(self, text): # -------- setup progress dialog -------- # self.progress_dialog = QProgressDialog(self) self.progress_dialog.setLabelText(text) self.progress_dialog.setCancelButtonText(None) self.progress_dialog.setRange(0, 0) self.progress_dialog.show() def _hide_progress_dialog(self): self.progress_dialog.hide() self.progress_dialog.deleteLater() def _on_subwindow_close(self, close_event): pass def _on_node_widget_added(self, widget, widget_name): self._add_subwindow(widget, widget_name) self.central_widget.tileSubWindows() def _on_node_removed(self, tree_item): if hasattr(tree_item.node, "widget"): try: self.central_widget.removeSubWindow( tree_item.node.widget.parent()) except AttributeError: pass except Exception as exc: self._show_message( "Can`t remove widget for %s" % tree_item.node, detailed_text=str(exc), ) self._logger.exception(exc) def _show_message(self, text, detailed_text=None, level="error"): if level == "error": icon = QMessageBox.Critical elif level == "warning": icon = QMessageBox.Warning elif level == "info": icon = QMessageBox.Information msg = QMessageBox(self) msg.setIcon(icon) msg.setText(text) msg.setDetailedText(detailed_text) msg.show() def _createAction( self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, ): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/%s.png" % icon)) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: action.triggered.connect(slot) if checkable: action.setCheckable(True) return action def moveEvent(self, event): return super(GUIWindow, self).moveEvent(event) def _on_run_button_toggled(self, is_paused=True): if is_paused: self.run_toggle_action.setText("Start") else: self.run_toggle_action.setText("Pause") @property def is_initialized(self): return self._is_initialized @is_initialized.setter def is_initialized(self, value): if value: self.run_toggle_action.setDisabled(False) else: self.run_toggle_action.setDisabled(True) self._is_initialized = value @property def _node_widgets(self) -> List[QWidget]: node_widgets = list() for node in self._pipeline.all_nodes: try: node_widgets.append(node.widget) except AttributeError: pass return node_widgets