refactor: drop the camera-region splitter, side columns fixed again

User decision: the drag-resize bars beside the Sample camera view are
not wanted - the side panels don't need resizing. Back to the plain
HBox with zoom-scaled fixed column widths; the View-menu collapse
toggles and the camera minimum-width clamp stay.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-16 14:37:19 +02:00
co-authored by Claude Fable 5
parent 26fbe2ca42
commit 33239bf51f
2 changed files with 15 additions and 35 deletions
+12 -30
View File
@@ -54,7 +54,6 @@ from PySide6.QtWidgets import (
QScrollArea,
QSizePolicy,
QSlider,
QSplitter,
QTabWidget,
QToolBar,
QToolTip,
@@ -448,24 +447,13 @@ class MainWindow(QMainWindow):
self.left_column_layout.addWidget(self.left_column_tabs)
self.left_column_layout.addStretch()
# Splitter instead of a plain HBox: the side columns kept their fixed
# widths while the camera region could only grow vertically; dragging
# the handles now resizes the camera width too. Collapsing to zero is
# off — the View-menu toggles are the collapse feature.
# No local handle styling: the app stylesheet's QSplitter::handle rule
# already paints the same line as the QMainWindow::separator between
# docks, so both resize bars share the one definition in styles.py.
self.center_splitter = QSplitter(Qt.Orientation.Horizontal, top_widget)
self.center_splitter.setChildrenCollapsible(False)
top_widget_layout.addWidget(self.center_splitter)
self.center_splitter.addWidget(self.collection_controls_scroll)
# Plain HBox, no splitter: drag-resizing the side columns was tried
# and rejected (user: the panels don't need resizing — the View-menu
# toggles collapse them, and the camera takes whatever is left).
top_widget_layout.addWidget(self.collection_controls_scroll)
self.collection_controls_scroll.setWidget(self.left_column)
# AsNeeded (was AlwaysOff): the splitter can now make the viewport
# narrower than the fixed-width column, and clipped controls must
# stay reachable.
self.collection_controls_scroll.setHorizontalScrollBarPolicy(
Qt.ScrollBarPolicy.ScrollBarAsNeeded
Qt.ScrollBarPolicy.ScrollBarAlwaysOff
)
self.collection_controls_scroll.setWidgetResizable(True)
# No frame: its border drew a line above the tab bar (Dewar tabs have
@@ -517,7 +505,7 @@ class MainWindow(QMainWindow):
# The camera region's natural minimum (~284px) came from the widest
# page's controls row (title + refresh button) and the tab labels —
# not from the video views, which rescale freely like they do in
# height. Clamp to 1/3 so the splitter can shrink all four camera
# height. Clamp to 1/3 so a narrow window can shrink all four camera
# views that far; past the natural width the tab bar scrolls and the
# controls rows clip.
self.video_tab.setMinimumWidth(self.video_tab.minimumSizeHint().width() // 3)
@@ -529,24 +517,21 @@ class MainWindow(QMainWindow):
# self.secondary_beamline_view_panel.refresh_requested.connect(self.refresh_axis_cameras)
# self.video_tab.addTab(self.secondary_beamline_view_panel, "Secondary view")
self.center_splitter.addWidget(self.video_tab)
top_widget_layout.addWidget(self.video_tab, 1)
self._start_axis_camera_threads()
self.beamline_controls_scroll = NoWheelScrollArea(top_widget)
self.beamline = BeamlineControls(self.beamline_controls_scroll)
self.center_splitter.addWidget(self.beamline_controls_scroll)
top_widget_layout.addWidget(self.beamline_controls_scroll)
self.beamline_controls_scroll.setWidget(self.beamline)
# Resizable so the column shrinks when panels collapse; without it the
# scrollbar keeps dead range below the collapsed panels.
self.beamline_controls_scroll.setWidgetResizable(True)
self.beamline_controls_scroll.setHorizontalScrollBarPolicy(
Qt.ScrollBarPolicy.ScrollBarAsNeeded
Qt.ScrollBarPolicy.ScrollBarAlwaysOff
)
# Only the camera region absorbs a window resize; the side columns
# keep whatever width the user dragged.
self.center_splitter.setStretchFactor(1, 1)
# Gutter math per column (10px scrollbar + frame) lives here too.
# Gutter math per column (10px scrollbar + frame) lives here.
self._apply_zoom_widths()
self.tell_samples = TellSamplePanel(samples=SampleShortInfoList(s=[]))
@@ -1769,13 +1754,10 @@ class MainWindow(QMainWindow):
left = round(self.data_collection.set_width * s)
self.data_collection.setFixedWidth(left)
self.left_column.setFixedWidth(left)
self.collection_controls_scroll.setMaximumWidth(left + 10)
self.collection_controls_scroll.setFixedWidth(left + 10)
right = round(self.beamline.set_width * s)
self.beamline.setFixedWidth(right)
self.beamline_controls_scroll.setMaximumWidth(right + 12)
# Re-seat the splitter: open both columns to their (new) full width,
# the camera region takes the rest.
self.center_splitter.setSizes([left + 10, 10_000, right + 12])
self.beamline_controls_scroll.setFixedWidth(right + 12)
@Slot()
def use_legacy_theme(self) -> None:
+3 -5
View File
@@ -73,11 +73,9 @@ def test_main_window_init(qtbot, mock_ui_state, daq_status_factory):
win.data_collection._emit_change_energy()
assert sent and abs(sent[0] - 12400.0) < 1e-6
# Side panels collapse from the View menu (no on-screen buttons), and
# the camera region sits in a splitter so its width is drag-resizable.
assert win.center_splitter.widget(1) is win.video_tab
# The clamp lets the splitter shrink the camera region well below the
# natural minimum the tab labels + controls rows would demand.
# Side panels collapse from the View menu (no on-screen buttons).
# The clamp lets a narrow window shrink the camera region well below
# the natural minimum the tab labels + controls rows would demand.
assert 0 < win.video_tab.minimumWidth() < win.video_tab.minimumSizeHint().width()
win._show_left_panel_action.trigger()
assert win.collection_controls_scroll.isHidden()