From 0bfa9262921ba22e9ff43dea243dc3831f600240 Mon Sep 17 00:00:00 2001 From: Mike Sullivan Date: Wed, 13 Nov 2024 17:13:30 +0000 Subject: [PATCH 1/7] allow more than one Live Viewer window to open with different Paths --- mantidimaging/gui/windows/live_viewer/view.py | 2 +- mantidimaging/gui/windows/main/view.py | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/mantidimaging/gui/windows/live_viewer/view.py b/mantidimaging/gui/windows/live_viewer/view.py index c7d31c88058..b88846873c0 100644 --- a/mantidimaging/gui/windows/live_viewer/view.py +++ b/mantidimaging/gui/windows/live_viewer/view.py @@ -28,9 +28,9 @@ class LiveViewerWindowView(BaseMainWindowView): def __init__(self, main_window: MainWindowView, live_dir_path: Path) -> None: super().__init__(None, 'gui/ui/live_viewer_window.ui') - self.setWindowTitle("Mantid Imaging - Live Viewer") self.main_window = main_window self.path = live_dir_path + self.setWindowTitle(f"Mantid Imaging - Live Viewer - {str(self.path)}") self.presenter = LiveViewerWindowPresenter(self, main_window) self.live_viewer = LiveViewWidget() self.imageLayout.addWidget(self.live_viewer) diff --git a/mantidimaging/gui/windows/main/view.py b/mantidimaging/gui/windows/main/view.py index 7cce5eeab41..b783f260685 100644 --- a/mantidimaging/gui/windows/main/view.py +++ b/mantidimaging/gui/windows/main/view.py @@ -474,13 +474,17 @@ def live_view_choose_directory(self) -> None: self.show_live_viewer(Path(live_data_directory)) def show_live_viewer(self, live_data_path: Path) -> None: - if not self.live_viewer: - self.live_viewer = LiveViewerWindowView(self, live_data_path) - self.live_viewer.show() - else: - self.live_viewer.activateWindow() - self.live_viewer.raise_() - self.live_viewer.show() + # if not self.live_viewer: + # self.live_viewer = LiveViewerWindowView(self, live_data_path) + # self.live_viewer.show() + # else: + # self.live_viewer.activateWindow() + # self.live_viewer.raise_() + # self.live_viewer.show() + self.live_viewer = LiveViewerWindowView(self, live_data_path) + self.live_viewer.activateWindow() + self.live_viewer.raise_() + self.live_viewer.show() @property def stack_list(self) -> list[StackId]: From 974085e982912776e20e116680322edf460100b5 Mon Sep 17 00:00:00 2001 From: Mike Sullivan Date: Wed, 13 Nov 2024 17:21:26 +0000 Subject: [PATCH 2/7] remove comments --- mantidimaging/gui/windows/main/view.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/mantidimaging/gui/windows/main/view.py b/mantidimaging/gui/windows/main/view.py index b783f260685..c9596ffa7f6 100644 --- a/mantidimaging/gui/windows/main/view.py +++ b/mantidimaging/gui/windows/main/view.py @@ -474,13 +474,6 @@ def live_view_choose_directory(self) -> None: self.show_live_viewer(Path(live_data_directory)) def show_live_viewer(self, live_data_path: Path) -> None: - # if not self.live_viewer: - # self.live_viewer = LiveViewerWindowView(self, live_data_path) - # self.live_viewer.show() - # else: - # self.live_viewer.activateWindow() - # self.live_viewer.raise_() - # self.live_viewer.show() self.live_viewer = LiveViewerWindowView(self, live_data_path) self.live_viewer.activateWindow() self.live_viewer.raise_() From 9632e947d2791a55b5b30a7c95fb1e78a29df7e6 Mon Sep 17 00:00:00 2001 From: Mike Sullivan Date: Wed, 13 Nov 2024 17:23:08 +0000 Subject: [PATCH 3/7] release note --- docs/release_notes/next/feature-2361-multiple-live-viewers | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/release_notes/next/feature-2361-multiple-live-viewers diff --git a/docs/release_notes/next/feature-2361-multiple-live-viewers b/docs/release_notes/next/feature-2361-multiple-live-viewers new file mode 100644 index 00000000000..9ebdedb2b33 --- /dev/null +++ b/docs/release_notes/next/feature-2361-multiple-live-viewers @@ -0,0 +1 @@ +#2361: Multiple Live Viewers can now be opened and pointed to different directories simultaneously \ No newline at end of file From c0db0d3b3cf382be0f31bcd5cfaf45c0f9d581e3 Mon Sep 17 00:00:00 2001 From: Mike Sullivan Date: Fri, 15 Nov 2024 11:19:05 +0000 Subject: [PATCH 4/7] LV references stored in list and closed properly --- mantidimaging/gui/windows/live_viewer/view.py | 7 +++++-- mantidimaging/gui/windows/main/view.py | 15 ++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/mantidimaging/gui/windows/live_viewer/view.py b/mantidimaging/gui/windows/live_viewer/view.py index b88846873c0..2f76f298a91 100644 --- a/mantidimaging/gui/windows/live_viewer/view.py +++ b/mantidimaging/gui/windows/live_viewer/view.py @@ -88,8 +88,11 @@ def set_image_index(self, index: int) -> None: def closeEvent(self, e) -> None: """Close the window and remove it from the main window list""" - self.main_window.live_viewer = None - self.presenter.close() + for live_viewer in self.main_window.live_viewer_list: + if live_viewer.path == self.path: + if live_viewer.presenter: + live_viewer.presenter.close() + live_viewer.close() self.live_viewer.handle_deleted() super().closeEvent(e) self.presenter = None # type: ignore # View instance to be destroyed -type can be inconsistent diff --git a/mantidimaging/gui/windows/main/view.py b/mantidimaging/gui/windows/main/view.py index c9596ffa7f6..0d485c8f4f8 100644 --- a/mantidimaging/gui/windows/main/view.py +++ b/mantidimaging/gui/windows/main/view.py @@ -101,7 +101,7 @@ class MainWindowView(BaseMainWindowView): filters: FiltersWindowView | None = None recon: ReconstructWindowView | None = None spectrum_viewer: SpectrumViewerWindowView | None = None - live_viewer: LiveViewerWindowView | None = None + live_viewer_list: list[LiveViewerWindowView] = [] settings_window: SettingsWindowView | None = None image_load_dialog: ImageLoadDialog | None = None @@ -474,10 +474,11 @@ def live_view_choose_directory(self) -> None: self.show_live_viewer(Path(live_data_directory)) def show_live_viewer(self, live_data_path: Path) -> None: - self.live_viewer = LiveViewerWindowView(self, live_data_path) - self.live_viewer.activateWindow() - self.live_viewer.raise_() - self.live_viewer.show() + live_viewer = LiveViewerWindowView(self, live_data_path) + self.live_viewer_list.append(live_viewer) + self.live_viewer_list[-1].activateWindow() + self.live_viewer_list[-1].raise_() + self.live_viewer_list[-1].show() @property def stack_list(self) -> list[StackId]: @@ -560,8 +561,8 @@ def closeEvent(self, event) -> None: # Close additional windows which do not have the MainWindow as parent if self.recon: self.recon.close() - if self.live_viewer: - self.live_viewer.close() + if self.live_viewer_list: + [live_viewer.close() for live_viewer in self.live_viewer_list] if self.spectrum_viewer: self.spectrum_viewer.close() if self.filters: From 49c4cb463129bc06de8d615ce4eca986e44d1ba6 Mon Sep 17 00:00:00 2001 From: Mike Sullivan Date: Fri, 15 Nov 2024 12:24:06 +0000 Subject: [PATCH 5/7] Only close LV model if it exists --- mantidimaging/gui/windows/live_viewer/presenter.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mantidimaging/gui/windows/live_viewer/presenter.py b/mantidimaging/gui/windows/live_viewer/presenter.py index 34984d032b0..b26391c58b9 100644 --- a/mantidimaging/gui/windows/live_viewer/presenter.py +++ b/mantidimaging/gui/windows/live_viewer/presenter.py @@ -46,7 +46,8 @@ def __init__(self, view: LiveViewerWindowView, main_window: MainWindowView): def close(self) -> None: """Close the window.""" - self.model.close() + if self.model is not None: + self.model.close() self.model = None # type: ignore # Presenter instance to be destroyed -type can be inconsistent self.view = None # type: ignore # Presenter instance to be destroyed -type can be inconsistent From 5a699bad749abed336c28758a7d6ae2109dea12a Mon Sep 17 00:00:00 2001 From: Mike Sullivan Date: Mon, 18 Nov 2024 17:04:18 +0000 Subject: [PATCH 6/7] simplify closeEvent of LV windows and LV in MainWindow --- mantidimaging/gui/windows/live_viewer/view.py | 7 ++----- mantidimaging/gui/windows/main/view.py | 7 ++++--- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/mantidimaging/gui/windows/live_viewer/view.py b/mantidimaging/gui/windows/live_viewer/view.py index 2f76f298a91..e9aa5836a7e 100644 --- a/mantidimaging/gui/windows/live_viewer/view.py +++ b/mantidimaging/gui/windows/live_viewer/view.py @@ -88,11 +88,8 @@ def set_image_index(self, index: int) -> None: def closeEvent(self, e) -> None: """Close the window and remove it from the main window list""" - for live_viewer in self.main_window.live_viewer_list: - if live_viewer.path == self.path: - if live_viewer.presenter: - live_viewer.presenter.close() - live_viewer.close() + self.main_window.live_viewer_list.remove(self) + self.presenter.close() self.live_viewer.handle_deleted() super().closeEvent(e) self.presenter = None # type: ignore # View instance to be destroyed -type can be inconsistent diff --git a/mantidimaging/gui/windows/main/view.py b/mantidimaging/gui/windows/main/view.py index 0d485c8f4f8..8aa2329f245 100644 --- a/mantidimaging/gui/windows/main/view.py +++ b/mantidimaging/gui/windows/main/view.py @@ -476,8 +476,8 @@ def live_view_choose_directory(self) -> None: def show_live_viewer(self, live_data_path: Path) -> None: live_viewer = LiveViewerWindowView(self, live_data_path) self.live_viewer_list.append(live_viewer) - self.live_viewer_list[-1].activateWindow() - self.live_viewer_list[-1].raise_() + # self.live_viewer_list[-1].activateWindow() + # self.live_viewer_list[-1].raise_() self.live_viewer_list[-1].show() @property @@ -562,7 +562,8 @@ def closeEvent(self, event) -> None: if self.recon: self.recon.close() if self.live_viewer_list: - [live_viewer.close() for live_viewer in self.live_viewer_list] + while self.live_viewer_list: + self.live_viewer_list[-1].close() if self.spectrum_viewer: self.spectrum_viewer.close() if self.filters: From 41686852bceae67dd70ab83e6c79ca3f03b304a9 Mon Sep 17 00:00:00 2001 From: Mike Sullivan Date: Tue, 19 Nov 2024 10:41:36 +0000 Subject: [PATCH 7/7] live viewer eyes test fix eyes test fix small fixes --- .../eyes_tests/live_viewer_window_test.py | 16 ++++++++-------- mantidimaging/gui/windows/main/view.py | 7 ++----- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/mantidimaging/eyes_tests/live_viewer_window_test.py b/mantidimaging/eyes_tests/live_viewer_window_test.py index 7d9b49bea06..81a21eaf0a4 100644 --- a/mantidimaging/eyes_tests/live_viewer_window_test.py +++ b/mantidimaging/eyes_tests/live_viewer_window_test.py @@ -54,7 +54,7 @@ def _make_simple_dir(self, directory: Path): @mock.patch("time.time", return_value=4000.0) def test_live_view_opens_without_data(self, _mock_time, _mock_image_watcher): self.imaging.show_live_viewer(self.live_directory) - self.check_target(widget=self.imaging.live_viewer) + self.check_target(widget=self.imaging.live_viewer_list[-1]) @mock.patch('mantidimaging.gui.windows.live_viewer.presenter.LiveViewerWindowPresenter.load_image') @mock.patch('mantidimaging.gui.windows.live_viewer.model.ImageWatcher') @@ -64,8 +64,8 @@ def test_live_view_opens_with_data(self, _mock_time, _mock_image_watcher, mock_l image_list = [Image_Data(path) for path in file_list] mock_load_image.return_value = self._generate_image() self.imaging.show_live_viewer(self.live_directory) - self.imaging.live_viewer.presenter.model._handle_image_changed_in_list(image_list) - self.check_target(widget=self.imaging.live_viewer) + self.imaging.live_viewer_list[-1].presenter.model._handle_image_changed_in_list(image_list) + self.check_target(widget=self.imaging.live_viewer_list[-1]) @mock.patch('mantidimaging.gui.windows.live_viewer.presenter.LiveViewerWindowPresenter.load_image') @mock.patch('mantidimaging.gui.windows.live_viewer.model.ImageWatcher') @@ -75,8 +75,8 @@ def test_live_view_opens_with_bad_data(self, _mock_time, _mock_image_watcher, mo image_list = [Image_Data(path) for path in file_list] mock_load_image.side_effect = ValueError self.imaging.show_live_viewer(self.live_directory) - self.imaging.live_viewer.presenter.model._handle_image_changed_in_list(image_list) - self.check_target(widget=self.imaging.live_viewer) + self.imaging.live_viewer_list[-1].presenter.model._handle_image_changed_in_list(image_list) + self.check_target(widget=self.imaging.live_viewer_list[-1]) @mock.patch('mantidimaging.gui.windows.live_viewer.presenter.LiveViewerWindowPresenter.load_image') @mock.patch('mantidimaging.gui.windows.live_viewer.model.ImageWatcher') @@ -86,6 +86,6 @@ def test_rotate_operation_rotates_image(self, _mock_time, _mock_image_watcher, m image_list = [Image_Data(path) for path in file_list] mock_load_image.return_value = self._generate_image() self.imaging.show_live_viewer(self.live_directory) - self.imaging.live_viewer.presenter.model._handle_image_changed_in_list(image_list) - self.imaging.live_viewer.rotate_angles_group.actions()[1].trigger() - self.check_target(widget=self.imaging.live_viewer) + self.imaging.live_viewer_list[-1].presenter.model._handle_image_changed_in_list(image_list) + self.imaging.live_viewer_list[-1].rotate_angles_group.actions()[1].trigger() + self.check_target(widget=self.imaging.live_viewer_list[-1]) diff --git a/mantidimaging/gui/windows/main/view.py b/mantidimaging/gui/windows/main/view.py index 8aa2329f245..6bc0e4bf95c 100644 --- a/mantidimaging/gui/windows/main/view.py +++ b/mantidimaging/gui/windows/main/view.py @@ -476,8 +476,6 @@ def live_view_choose_directory(self) -> None: def show_live_viewer(self, live_data_path: Path) -> None: live_viewer = LiveViewerWindowView(self, live_data_path) self.live_viewer_list.append(live_viewer) - # self.live_viewer_list[-1].activateWindow() - # self.live_viewer_list[-1].raise_() self.live_viewer_list[-1].show() @property @@ -561,9 +559,8 @@ def closeEvent(self, event) -> None: # Close additional windows which do not have the MainWindow as parent if self.recon: self.recon.close() - if self.live_viewer_list: - while self.live_viewer_list: - self.live_viewer_list[-1].close() + while self.live_viewer_list: + self.live_viewer_list[-1].close() if self.spectrum_viewer: self.spectrum_viewer.close() if self.filters: