From bacbe7d13a2bb80b98671c2300d6d3c75401100e Mon Sep 17 00:00:00 2001 From: Michael Dolan Date: Tue, 23 Jul 2024 01:16:31 -0400 Subject: [PATCH] Fix mode viewer context switching Signed-off-by: Michael Dolan --- src/apps/ocioview/ocioview/main_window.py | 37 ++---------- src/apps/ocioview/ocioview/viewer_dock.py | 56 ++++++++++++++++--- .../ocioview/ocioview/widgets/combo_box.py | 2 + 3 files changed, 56 insertions(+), 39 deletions(-) diff --git a/src/apps/ocioview/ocioview/main_window.py b/src/apps/ocioview/ocioview/main_window.py index 6db2938c83..76520becf3 100644 --- a/src/apps/ocioview/ocioview/main_window.py +++ b/src/apps/ocioview/ocioview/main_window.py @@ -20,7 +20,6 @@ from .settings import settings from .undo import undo_stack from .utils import get_glyph_icon, SignalsBlocked -from .viewer import EditImageViewer, PreviewImageViewer from .viewer_dock import ViewerDock from .widgets import EnumComboBox @@ -74,17 +73,7 @@ def __init__( self.config_dock = ConfigDock() # Central widget - self._viewer_docks = {} - self._viewer_docks[OCIOViewMode.Edit] = ViewerDock( - self.recent_images_menu, EditImageViewer - ) - self._viewer_docks[OCIOViewMode.Preview] = ViewerDock( - self.recent_images_menu, PreviewImageViewer - ) - - self.viewer_stack = QtWidgets.QStackedWidget() - self.viewer_stack.addWidget(self._viewer_docks[OCIOViewMode.Edit]) - self.viewer_stack.addWidget(self._viewer_docks[OCIOViewMode.Preview]) + self.viewer_dock = ViewerDock(self.recent_images_menu) # Main menu self.file_menu = QtWidgets.QMenu("File") @@ -113,13 +102,13 @@ def __init__( self.file_menu.addSeparator() self.file_menu.addAction( "Load Image...", - lambda: self._get_viewer_dock().load_image(), + lambda: self.viewer_dock.load_image(), QtGui.QKeySequence("Ctrl+I"), ) self.file_menu.addMenu(self.recent_images_menu) self.file_menu.addAction( "Load Image in New Tab...", - lambda: self._get_viewer_dock().load_image(new_tab=True), + lambda: self.viewer_dock.load_image(new_tab=True), QtGui.QKeySequence("Ctrl+Shift+I"), ) self.file_menu.addSeparator() @@ -185,14 +174,14 @@ def __init__( self.setCorner(corner, QtCore.Qt.RightDockWidgetArea) # Layout - self.setCentralWidget(self.viewer_stack) + self.setCentralWidget(self.viewer_dock) self.addDockWidget(QtCore.Qt.BottomDockWidgetArea, self.inspect_dock) self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.config_dock) # Connections signal_router = SignalRouter.get_instance() signal_router.config_changed.connect( - lambda: self._get_viewer_dock().update_current_viewer() + lambda: self.viewer_dock.update_current_viewer() ) signal_router.config_reloaded.connect(self._update_window_title) @@ -233,9 +222,7 @@ def reset(self) -> None: self.config_dock.reset() self.inspect_dock.reset() - - for mode, viewer_dock in self._viewer_docks.items(): - viewer_dock.reset() + self.viewer_dock.reset() def closeEvent(self, event: QtGui.QCloseEvent) -> None: if self._can_close_config(): @@ -653,22 +640,11 @@ def _init_config_tracking(self) -> None: ReferenceSpaceManager.init_reference_spaces() self._update_cache_id() - def _get_viewer_dock(self) -> ViewerDock: - """Get the viewer dock for the current mode.""" - return self._viewer_docks[OCIOViewMode.current_mode()] - - def _update_viewer_dock(self) -> None: - """Show viewer dock for the current mode.""" - viewer_dock = self._viewer_docks[OCIOViewMode.current_mode()] - self.viewer_stack.setCurrentWidget(viewer_dock) - viewer_dock.update_current_viewer() - @QtCore.Slot(int) def _on_mode_box_index_changed(self, index: int) -> None: """Called when the application mode has been manually changed.""" with SignalsBlocked(self.mode_box): OCIOViewMode.set_current_mode(self.mode_box.member()) - self._update_viewer_dock() def _on_mode_changed_external(self) -> None: """ @@ -678,4 +654,3 @@ def _on_mode_changed_external(self) -> None: mode = OCIOViewMode.current_mode() if mode != self.mode_box.member(): self.mode_box.set_member(mode) - self._update_viewer_dock() diff --git a/src/apps/ocioview/ocioview/viewer_dock.py b/src/apps/ocioview/ocioview/viewer_dock.py index 3b41716218..7e59c60340 100644 --- a/src/apps/ocioview/ocioview/viewer_dock.py +++ b/src/apps/ocioview/ocioview/viewer_dock.py @@ -7,10 +7,12 @@ from PySide6 import QtCore, QtWidgets +from .mode import OCIOViewMode from .settings import settings +from .signal_router import SignalRouter from .transform_manager import TransformManager from .utils import get_glyph_icon -from .viewer import BaseImageViewer +from .viewer import BaseImageViewer, EditImageViewer, PreviewImageViewer from .widgets.structure import TabbedDockWidget @@ -26,7 +28,6 @@ class ViewerDock(TabbedDockWidget): def __init__( self, recent_images_menu: QtWidgets.QMenu, - image_viewer_type: type[BaseImageViewer], parent: Optional[QtCore.QObject] = None, ): super().__init__( @@ -36,7 +37,6 @@ def __init__( ) self._recent_images_menu = recent_images_menu - self._image_viewer_type = image_viewer_type self.setAllowedAreas(QtCore.Qt.NoDockWidgetArea) self.tabs.setTabPosition(QtWidgets.QTabWidget.West) @@ -45,6 +45,9 @@ def __init__( self._tab_bar = self.tabs.tabBar() self._tab_bar.installEventFilter(self) + signal_router = SignalRouter.get_instance() + signal_router.mode_changed.connect(self._on_mode_changed) + # Widgets self._viewers = defaultdict(list) self.add_image_viewer() @@ -88,14 +91,16 @@ def load_image( the current or first available image viewer. :return: Image viewer instance """ - if new_tab or not self._viewers.get(self._image_viewer_type): + image_viewer_type = self._current_image_viewer_type() + + if new_tab or not self._viewers.get(image_viewer_type): image_viewer = self.add_image_viewer() else: current_viewer = self.tabs.currentWidget() - if isinstance(current_viewer, self._image_viewer_type): + if isinstance(current_viewer, image_viewer_type): image_viewer = current_viewer else: - image_viewer = self._viewers[self._image_viewer_type][0] + image_viewer = self._viewers[image_viewer_type][0] self.tabs.setCurrentWidget(image_viewer) @@ -124,8 +129,9 @@ def add_image_viewer(self) -> BaseImageViewer: :return: Image viewer instance """ - image_viewer = self._image_viewer_type() - self._viewers[self._image_viewer_type].append(image_viewer) + image_viewer_type = self._current_image_viewer_type() + image_viewer = image_viewer_type() + self._viewers[image_viewer_type].append(image_viewer) self.add_tab( image_viewer, @@ -152,6 +158,13 @@ def reset(self) -> None: TransformManager.reset() + def _current_image_viewer_type(self) -> type[BaseImageViewer]: + """Get current mode-specific image viewer type.""" + if OCIOViewMode.current_mode() == OCIOViewMode.Preview: + return PreviewImageViewer + else: # Edit + return EditImageViewer + def _on_tab_changed(self, index: int) -> None: """ Track GL context with the current viewer. @@ -175,6 +188,33 @@ def _on_tab_close_requested(self, index: int) -> None: if viewer in self._viewers[viewer_type]: self._viewers[viewer_type].remove(viewer) + def _on_mode_changed(self) -> None: + """ + Called when the application mode is changed, to toggle + mode-specific viewer visibility. + """ + image_viewer_type = self._current_image_viewer_type() + + for viewer_type, viewers in self._viewers.items(): + if issubclass(viewer_type, BaseImageViewer): + for viewer in viewers: + tab_index = self.tabs.indexOf(viewer) + if tab_index != -1: + self.tabs.setTabVisible( + tab_index, viewer_type == image_viewer_type + ) + viewer.update() + + if image_viewer_type not in self._viewers: + self.add_image_viewer() + + current_index = self.tabs.currentIndex() + if not self.tabs.isTabVisible(current_index): + for i in range(self.tabs.count()): + if self.tabs.isTabVisible(i): + self.tabs.setCurrentIndex(i) + break + def _get_image_dir(self, image_path: Optional[Path] = None) -> str: """ Infer an image load directory from an existing image path or diff --git a/src/apps/ocioview/ocioview/widgets/combo_box.py b/src/apps/ocioview/ocioview/widgets/combo_box.py index 892b623857..07b1506f3c 100644 --- a/src/apps/ocioview/ocioview/widgets/combo_box.py +++ b/src/apps/ocioview/ocioview/widgets/combo_box.py @@ -282,6 +282,8 @@ def set_color_space( action = self._color_space_actions.get(color_space_name) if action is None: return False + else: + action.setChecked(True) # Complete selection self._commit_value(color_space_name, action.text())