mirror of
https://github.com/bec-project/bec_widgets.git
synced 2026-10-21 16:16:16 +02:00
fix(dock_area): skip superseded deferred layout ratio requests
This commit is contained in:
1 parent
7ce6bf2a5a
commit
4cfb49ff95
2 files changed
+33
-1
No files matched your search
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import inspect
|
||||
import itertools
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Callable, Literal, Mapping, Sequence, cast
|
||||
|
||||
@@ -26,6 +27,11 @@ from bec_widgets.widgets.containers.qt_ads import (
|
||||
|
||||
logger = bec_logger.logger
|
||||
|
||||
# Dynamic property tagging a splitter with its latest layout-ratio request; deferred applies of
|
||||
# older requests compare against it and skip themselves.
|
||||
_RATIO_REQUEST_PROPERTY = "_bec_layout_ratio_request"
|
||||
_ratio_requests = itertools.count(1)
|
||||
|
||||
|
||||
class DockSettingsDialog(QDialog):
|
||||
"""Generic settings editor shown from dock title bar actions."""
|
||||
@@ -746,7 +752,9 @@ class DockAreaWidget(BECWidget, QWidget):
|
||||
|
||||
The deferred callback is bound to the splitter as context object, so Qt drops it
|
||||
if the splitter is deleted (e.g. by ADS while the layout changes) before it runs.
|
||||
While the splitter has no usable size, the ratios wait for its next resize.
|
||||
While the splitter has no usable size, the ratios wait for its next resize. Every request
|
||||
tags the splitter, so a deferred apply of an older request skips itself once a newer one
|
||||
for the same splitter exists.
|
||||
|
||||
Args:
|
||||
splitter(QtAds.CDockSplitter): Target splitter.
|
||||
@@ -759,7 +767,12 @@ class DockAreaWidget(BECWidget, QWidget):
|
||||
if not ratios:
|
||||
return
|
||||
|
||||
request = next(_ratio_requests)
|
||||
splitter.setProperty(_RATIO_REQUEST_PROPERTY, request)
|
||||
|
||||
def apply():
|
||||
if splitter.property(_RATIO_REQUEST_PROPERTY) != request:
|
||||
return # superseded by a newer request for this splitter
|
||||
count = splitter.count()
|
||||
if count != len(ratios):
|
||||
return
|
||||
|
||||
@@ -433,6 +433,12 @@ class TestBasicDockArea:
|
||||
def findChildren(self, *_args, **_kwargs):
|
||||
return []
|
||||
|
||||
def setProperty(self, name, value):
|
||||
self.__dict__[name] = value
|
||||
|
||||
def property(self, name):
|
||||
return self.__dict__.get(name)
|
||||
|
||||
splitter = DummySplitter()
|
||||
|
||||
basic_dock_area._schedule_splitter_weights(splitter, [1, 2, 1])
|
||||
@@ -647,6 +653,19 @@ class TestBasicDockArea:
|
||||
assert left_px > 2 * right_px
|
||||
assert root.findChildren(basic_dock_module._ResizeWatcher) == []
|
||||
|
||||
def test_layout_ratios_superseded_request_does_not_apply(self, collapsed_dock_area, qtbot):
|
||||
"""An older request still queued when a newer one arrives must not win either."""
|
||||
outer, area, root = collapsed_dock_area
|
||||
area.set_layout_ratios(horizontal=[1, 3])
|
||||
# The area gets its width back between the two queued applies.
|
||||
QTimer.singleShot(0, outer, lambda: outer.setSizes([400, 400]))
|
||||
area.set_layout_ratios(horizontal=[3, 1])
|
||||
qtbot.waitUntil(lambda: root.width() > 0)
|
||||
qtbot.wait(50)
|
||||
|
||||
left_px, right_px = root.sizes()
|
||||
assert left_px > 2 * right_px
|
||||
|
||||
def test_first_dock_title_bar_preference_survives_second_dock(self, basic_dock_area):
|
||||
first = QWidget(parent=basic_dock_area)
|
||||
first.setObjectName("first_panel")
|
||||
|
||||
Reference in new issue
Block a user