diff --git a/MDANSE_GUI/Src/MDANSE_GUI/TabbedWindow.py b/MDANSE_GUI/Src/MDANSE_GUI/TabbedWindow.py
index eb624f3eff..1b11e8b9f9 100644
--- a/MDANSE_GUI/Src/MDANSE_GUI/TabbedWindow.py
+++ b/MDANSE_GUI/Src/MDANSE_GUI/TabbedWindow.py
@@ -161,6 +161,21 @@ def __init__(
self._tabs["Instruments"]._visualiser.instrument_details_changed.connect(
self._tabs["Actions"].update_action_after_instrument_change
)
+ self._tabs["Plot Holder"]._visualiser.current_tab_index.connect(
+ self._tabs["Plot Creator"]._visualiser.new_target_plot_index
+ )
+ self._tabs["Plot Holder"]._visualiser.current_tab_count.connect(
+ self._tabs["Plot Creator"]._visualiser.new_target_plot_count
+ )
+ self._tabs["Plot Holder"]._visualiser.datasets_in_plot.connect(
+ self._tabs["Plot Creator"]._visualiser.new_dataset_count_in_target
+ )
+ self._tabs["Plot Holder"]._visualiser.plot_widget_type.connect(
+ self._tabs["Plot Creator"]._visualiser.new_plot_widget_type
+ )
+ self._tabs["Plot Holder"].connect_external_view(
+ self._tabs["Plot Creator"]._visualiser.preview_table
+ )
# connect signal to the tab
self.signal_recent_trajectory_file.connect(
self._tabs["Trajectories"].load_trajectory
diff --git a/MDANSE_GUI/Src/MDANSE_GUI/Tabs/PlotTab.py b/MDANSE_GUI/Src/MDANSE_GUI/Tabs/PlotTab.py
index 2e1346e2e6..605d0e6c3e 100644
--- a/MDANSE_GUI/Src/MDANSE_GUI/Tabs/PlotTab.py
+++ b/MDANSE_GUI/Src/MDANSE_GUI/Tabs/PlotTab.py
@@ -29,7 +29,7 @@
from MDANSE_GUI.Widgets.PlotSettingsDialog import PlotSettingsEditor
if TYPE_CHECKING:
- from qtpy.QtWidgets import QDialog, QWidget
+ from qtpy.QtWidgets import QAbstractItemView, QDialog, QWidget
from MDANSE_GUI.Session.Session import Session
@@ -66,6 +66,12 @@ def __init__(self, *args, **kwargs):
)
self.matplotlib_dialog.values_changed.connect(self._visualiser.update_plots)
self._core.add_button("Change matplotlib settings", self.edit_matplotlib)
+ self.connected_views = [self._view]
+
+ def connect_external_view(self, new_view: QAbstractItemView):
+ if new_view not in self.connected_views:
+ self.connected_views.append(new_view)
+ new_view.setModel(self.model)
def launch_dialog(self, dialog: QDialog) -> None:
if dialog.isVisible():
@@ -127,7 +133,10 @@ def accept_external_data(self, data_model):
LOG.error(f"Visualiser failed to plot data: {e2}")
else:
self.tab_notification()
+ self._visualiser.send_plot_info()
@Slot(int)
def switch_model(self, tab_id):
- self._view.setModel(self.model)
+ for view in self.connected_views:
+ view.setModel(self.model)
+ self._visualiser.send_plot_info()
diff --git a/MDANSE_GUI/Src/MDANSE_GUI/Tabs/Visualisers/DataPlotter.py b/MDANSE_GUI/Src/MDANSE_GUI/Tabs/Visualisers/DataPlotter.py
index c714257e4e..1e80d8aeea 100644
--- a/MDANSE_GUI/Src/MDANSE_GUI/Tabs/Visualisers/DataPlotter.py
+++ b/MDANSE_GUI/Src/MDANSE_GUI/Tabs/Visualisers/DataPlotter.py
@@ -17,7 +17,9 @@
from qtpy.QtCore import Signal, Slot
from qtpy.QtWidgets import (
+ QGroupBox,
QHBoxLayout,
+ QLabel,
QMessageBox,
QPushButton,
QTableView,
@@ -47,31 +49,95 @@ class DataPlotter(QWidget):
def __init__(self, *args, unit_lookup=None, **kwargs):
super().__init__(*args, **kwargs)
-
+ self.tab_index, self.tab_count = 0, 1
+ self.dataset_count = 0
+ self.plotter_type = "PlotWidget"
self._unit_lookup = unit_lookup
layout = QVBoxLayout(self)
- button_bar = QWidget(self)
- button_layout = QHBoxLayout(button_bar)
+ control_bar = QWidget(self)
+ bar_layout = QHBoxLayout(control_bar)
self._selection_viewer = QTableView(self)
layout.addWidget(self._selection_viewer)
- layout.addWidget(button_bar)
- buttons = [
- ("Plot Data", self.plot_data),
- ("Clear", self.clear),
- ("New Plot", self.new_plot),
- ("New Data View (Text)", self.new_text),
- ]
- for name, function in buttons:
- button = QPushButton(name, button_bar)
- button_layout.addWidget(button)
- if function is not None:
- button.clicked.connect(function)
+ layout.addWidget(control_bar)
+ button_bar = self.create_buttons()
+ bar_layout.addWidget(button_bar)
+ plotter_preview = self.create_preview()
+ bar_layout.addWidget(plotter_preview)
self._model = PlottingContext(
unit_lookup=self._unit_lookup,
)
self._selection_viewer.setModel(self._model)
self.hide_columns()
+ def create_buttons(self) -> QWidget:
+ button_bar = QWidget(self)
+ button_layout = QVBoxLayout(button_bar)
+ button_groups = {
+ "Empty plot creation": [
+ ("New empty plot", self.new_plot),
+ ("New empty text view", self.new_text),
+ ],
+ "Current data selection": [
+ ("Send data to plotter", self.plot_data),
+ ("Clear data selection", self.clear),
+ ],
+ }
+ for group_name, buttons in button_groups.items():
+ subgroup = QGroupBox(group_name, button_bar)
+ sublayout = QVBoxLayout(subgroup)
+ for name, function in buttons:
+ button = QPushButton(name, button_bar)
+ sublayout.addWidget(button)
+ if function is not None:
+ button.clicked.connect(function)
+ button_layout.addWidget(subgroup)
+ return button_bar
+
+ def create_preview(self) -> QWidget:
+ previewer = QWidget(self)
+ previewer_layout = QVBoxLayout(previewer)
+ self.target_label = QLabel("Target plot in next tab.")
+ self.target_label.setWordWrap(True)
+ previewer_layout.addWidget(self.target_label)
+ info_label = QLabel(
+ f"Contents of the currently selected {self.plotter_type} in the next tab:"
+ )
+ previewer_layout.addWidget(info_label)
+ self.preview_table = QTableView(previewer)
+ previewer_layout.addWidget(self.preview_table)
+ self.update_target_plot_label()
+ return previewer
+
+ def update_target_plot_label(self):
+ self.target_label.setText(
+ "Datasets listed above will be sent to the Plot Holder tab.
"
+ f"They will appear in tab {self.tab_index + 1} out of {self.tab_count}.
"
+ f"It is a {self.plotter_type}, currently containing {self.dataset_count} datasets."
+ )
+ for col_num in range(4, 10):
+ self.preview_table.hideColumn(col_num)
+ self.preview_table.resizeColumnsToContents()
+
+ @Slot(int)
+ def new_target_plot_index(self, new_index: int):
+ self.tab_index = new_index
+ self.update_target_plot_label()
+
+ @Slot(int)
+ def new_target_plot_count(self, new_count: int):
+ self.tab_count = new_count
+ self.update_target_plot_label()
+
+ @Slot(int)
+ def new_dataset_count_in_target(self, new_dataset_count: int):
+ self.dataset_count = new_dataset_count
+ self.update_target_plot_label()
+
+ @Slot(str)
+ def new_plot_widget_type(self, new_plot_widget_type: str):
+ self.plotter_type = new_plot_widget_type
+ self.update_target_plot_label()
+
@Slot(object)
def add_dataset(self, dataset: SingleDataset):
"""Append a dataset to the current model."""
diff --git a/MDANSE_GUI/Src/MDANSE_GUI/Tabs/Visualisers/PlotHolder.py b/MDANSE_GUI/Src/MDANSE_GUI/Tabs/Visualisers/PlotHolder.py
index 1a1f1360b2..0a9ea91652 100644
--- a/MDANSE_GUI/Src/MDANSE_GUI/Tabs/Visualisers/PlotHolder.py
+++ b/MDANSE_GUI/Src/MDANSE_GUI/Tabs/Visualisers/PlotHolder.py
@@ -34,6 +34,10 @@ class PlotHolder(QTabWidget):
error = Signal(str)
new_entry = Signal()
+ current_tab_index = Signal(int)
+ current_tab_count = Signal(int)
+ datasets_in_plot = Signal(int)
+ plot_widget_type = Signal(str)
def __init__(self, *args, unit_lookup=None, **kwargs):
super().__init__(*args, **kwargs)
@@ -75,6 +79,7 @@ def new_plot(self, tab_name: str) -> int:
self._plotter.append(plotter)
self.setCurrentIndex(tab_id)
self.new_entry.emit()
+ self.send_plot_info()
return tab_id
@Slot(str)
@@ -91,6 +96,7 @@ def new_text(self, ignored_name: str) -> int:
self._plotter.append(plotter)
self.setCurrentIndex(tab_id)
self.new_entry.emit()
+ self.send_plot_info()
return tab_id
@Slot(int)
@@ -108,9 +114,10 @@ def clean_up_closed_tab(self, tab_id: int):
self._current_id = valid_id_values[0]
self.setCurrentIndex(self._current_id)
self.removeTab(tab_id)
+ self.send_plot_info()
@property
- def model(self):
+ def model(self) -> PlottingContext:
tab_id = self.currentIndex()
try:
pc = self._context[tab_id]
@@ -122,7 +129,7 @@ def model(self):
return pc
@property
- def plotter(self):
+ def plotter(self) -> DataWidget:
tab_id = self.currentIndex()
try:
return self._plotter[tab_id]
@@ -164,3 +171,11 @@ def update_plot(self, plot_number: int):
except Exception:
LOG.error("Plotting failed: %s", traceback.format_exc())
plotter.plot_blank()
+ else:
+ self.send_plot_info()
+
+ def send_plot_info(self):
+ self.current_tab_count.emit(len(self._plotter))
+ self.current_tab_index.emit(self.currentIndex())
+ self.datasets_in_plot.emit(self.model.rowCount())
+ self.plot_widget_type.emit(type(self.plotter).__name__)