From 3517f0b3cd972c40277ec8a8887e457a82534547 Mon Sep 17 00:00:00 2001 From: Sergio Martins Date: Mon, 15 Apr 2024 12:30:51 +0100 Subject: [PATCH 1/3] tests: Don't annonymize internal dock widgets Specially the central persistent widget. --- tests/anonymize_layout.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/anonymize_layout.dart b/tests/anonymize_layout.dart index 625737ac4..c7fdc54d1 100644 --- a/tests/anonymize_layout.dart +++ b/tests/anonymize_layout.dart @@ -48,6 +48,10 @@ main(List args) { return; } + /// Skip internals + if (["-persistentCentralDockWidget", "_kddw_internal_dummy", "_kddw_internal_dummy2"].contains(name)) + continue; + contents = contents.replaceAll(name, "dockwidget_tests_$i"); i++; } From 7301248e1ff4af1fe83d656be8e469812752b569 Mon Sep 17 00:00:00 2001 From: Sergio Martins Date: Mon, 15 Apr 2024 13:50:08 +0100 Subject: [PATCH 2/3] test: Test that json can contain invalid item percentage they get corrected at runtime --- tests/layouts/invalidPercentages.json | 733 ++++++++++++++++++++++++++ tests/qtwidgets/tst_qtwidgets.cpp | 23 + tests/test_resources.qrc | 1 + 3 files changed, 757 insertions(+) create mode 100644 tests/layouts/invalidPercentages.json diff --git a/tests/layouts/invalidPercentages.json b/tests/layouts/invalidPercentages.json new file mode 100644 index 000000000..3cf64a7f5 --- /dev/null +++ b/tests/layouts/invalidPercentages.json @@ -0,0 +1,733 @@ +{ + "allDockWidgets": [ + { + "lastCloseReason": 0, + "lastPosition": { + "lastFloatingGeometry": { + "height": 0, + "width": 0, + "x": 0, + "y": 0 + }, + "lastOverlayedGeometries": [], + "placeholders": [ + { + "isFloatingWindow": false, + "itemIndex": 4, + "mainWindowUniqueName": "mainWindowId1" + } + ], + "tabIndex": -1, + "wasFloating": false + }, + "uniqueName": "-persistentCentralDockWidget" + }, + { + "lastCloseReason": 0, + "lastPosition": { + "lastFloatingGeometry": { + "height": 0, + "width": 0, + "x": 0, + "y": 0 + }, + "lastOverlayedGeometries": [], + "placeholders": [ + { + "isFloatingWindow": false, + "itemIndex": 5, + "mainWindowUniqueName": "mainWindowId1" + } + ], + "tabIndex": 0, + "wasFloating": false + }, + "uniqueName": "_kddw_internal_dummy" + }, + { + "lastCloseReason": 0, + "lastPosition": { + "lastFloatingGeometry": { + "height": 0, + "width": 0, + "x": 0, + "y": 0 + }, + "lastOverlayedGeometries": [], + "placeholders": [ + { + "isFloatingWindow": false, + "itemIndex": 0, + "mainWindowUniqueName": "mainWindowId1" + } + ], + "tabIndex": 0, + "wasFloating": false + }, + "uniqueName": "_kddw_internal_dummy2" + }, + { + "lastCloseReason": 0, + "lastPosition": { + "lastFloatingGeometry": { + "height": 0, + "width": 0, + "x": 0, + "y": 0 + }, + "lastOverlayedGeometries": [], + "placeholders": [ + { + "isFloatingWindow": false, + "itemIndex": 1, + "mainWindowUniqueName": "mainWindowId1" + } + ], + "tabIndex": 0, + "wasFloating": false + }, + "uniqueName": "dockwidget_tests_6" + }, + { + "lastCloseReason": 0, + "lastPosition": { + "lastFloatingGeometry": { + "height": 0, + "width": 0, + "x": 0, + "y": 0 + }, + "lastOverlayedGeometries": [], + "placeholders": [ + { + "isFloatingWindow": false, + "itemIndex": 2, + "mainWindowUniqueName": "mainWindowId1" + } + ], + "tabIndex": 0, + "wasFloating": false + }, + "uniqueName": "dockwidget_tests_3" + }, + { + "lastCloseReason": 1, + "lastPosition": { + "lastFloatingGeometry": { + "height": 0, + "width": 0, + "x": 0, + "y": 0 + }, + "lastOverlayedGeometries": [], + "placeholders": [ + { + "isFloatingWindow": false, + "itemIndex": 10, + "mainWindowUniqueName": "mainWindowId1" + } + ], + "tabIndex": 0, + "wasFloating": false + }, + "uniqueName": "dockwidget_tests_4" + }, + { + "lastCloseReason": 0, + "lastPosition": { + "lastFloatingGeometry": { + "height": 0, + "width": 0, + "x": 0, + "y": 0 + }, + "lastOverlayedGeometries": [], + "placeholders": [ + { + "isFloatingWindow": false, + "itemIndex": 6, + "mainWindowUniqueName": "mainWindowId1" + } + ], + "tabIndex": 0, + "wasFloating": false + }, + "uniqueName": "dockwidget_tests_7" + }, + { + "lastCloseReason": 0, + "lastPosition": { + "lastFloatingGeometry": { + "height": 0, + "width": 0, + "x": 0, + "y": 0 + }, + "lastOverlayedGeometries": [], + "placeholders": [ + { + "isFloatingWindow": false, + "itemIndex": 7, + "mainWindowUniqueName": "mainWindowId1" + } + ], + "tabIndex": 0, + "wasFloating": false + }, + "uniqueName": "dockwidget_tests_2" + }, + { + "lastCloseReason": 0, + "lastPosition": { + "lastFloatingGeometry": { + "height": 0, + "width": 0, + "x": 0, + "y": 0 + }, + "lastOverlayedGeometries": [], + "placeholders": [ + { + "isFloatingWindow": false, + "itemIndex": 3, + "mainWindowUniqueName": "mainWindowId1" + } + ], + "tabIndex": -1, + "wasFloating": false + }, + "uniqueName": "dockwidget_tests_0" + }, + { + "lastCloseReason": 0, + "lastPosition": { + "lastFloatingGeometry": { + "height": 0, + "width": 0, + "x": 0, + "y": 0 + }, + "lastOverlayedGeometries": [], + "placeholders": [ + { + "isFloatingWindow": false, + "itemIndex": 11, + "mainWindowUniqueName": "mainWindowId1" + } + ], + "tabIndex": 0, + "wasFloating": false + }, + "uniqueName": "dockwidget_tests_8" + }, + { + "lastCloseReason": 0, + "lastPosition": { + "lastFloatingGeometry": { + "height": 0, + "width": 0, + "x": 0, + "y": 0 + }, + "lastOverlayedGeometries": [], + "placeholders": [ + { + "isFloatingWindow": false, + "itemIndex": 8, + "mainWindowUniqueName": "mainWindowId1" + } + ], + "tabIndex": 0, + "wasFloating": false + }, + "uniqueName": "dockwidget_tests_5" + }, + { + "lastCloseReason": 0, + "lastPosition": { + "lastFloatingGeometry": { + "height": 0, + "width": 0, + "x": 0, + "y": 0 + }, + "lastOverlayedGeometries": [], + "placeholders": [ + { + "isFloatingWindow": false, + "itemIndex": 9, + "mainWindowUniqueName": "mainWindowId1" + } + ], + "tabIndex": 0, + "wasFloating": false + }, + "uniqueName": "dockwidget_tests_1" + } + ], + "closedDockWidgets": [ + "_kddw_internal_dummy", + "_kddw_internal_dummy2", + "dockwidget_tests_6", + "dockwidget_tests_3", + "dockwidget_tests_4", + "dockwidget_tests_7", + "dockwidget_tests_2", + "dockwidget_tests_8", + "dockwidget_tests_5", + "dockwidget_tests_1" + ], + "floatingWindows": [], + "mainWindows": [ + { + "affinities": null, + "geometry": { + "height": 1001, + "width": 1920, + "x": 0, + "y": 29 + }, + "isVisible": true, + "multiSplitterLayout": { + "frames": { + "4758": { + "currentTabIndex": 0, + "dockWidgets": [ + "dockwidget_tests_0" + ], + "geometry": { + "height": 908, + "width": 403, + "x": 0, + "y": 0 + }, + "id": "4758", + "isNull": false, + "mainWindowUniqueName": "mainWindowId1", + "objectName": "dockwidget_tests_0", + "options": 0 + }, + "9": { + "currentTabIndex": 0, + "dockWidgets": [ + "-persistentCentralDockWidget" + ], + "geometry": { + "height": 908, + "width": 1510, + "x": 408, + "y": 0 + }, + "id": "9", + "isNull": false, + "mainWindowUniqueName": "mainWindowId1", + "objectName": "-persistentCentralDockWidget", + "options": 10 + } + }, + "layout": { + "children": [ + { + "children": [ + { + "children": [ + { + "isContainer": false, + "isVisible": false, + "sizingInfo": { + "geometry": { + "height": 480, + "width": 317, + "x": 0, + "y": 0 + }, + "maxSizeHint": { + "height": 16777215, + "width": 16777215 + }, + "minSize": { + "height": 90, + "width": 80 + }, + "percentageWithinParent": 0.0 + } + }, + { + "isContainer": false, + "isVisible": false, + "sizingInfo": { + "geometry": { + "height": 90, + "width": 200, + "x": 0, + "y": 0 + }, + "maxSizeHint": { + "height": 16777215, + "width": 16777215 + }, + "minSize": { + "height": 90, + "width": 80 + }, + "percentageWithinParent": 0.0 + } + }, + { + "isContainer": false, + "isVisible": false, + "sizingInfo": { + "geometry": { + "height": 90, + "width": 200, + "x": 0, + "y": 0 + }, + "maxSizeHint": { + "height": 16777215, + "width": 16777215 + }, + "minSize": { + "height": 90, + "width": 80 + }, + "percentageWithinParent": 0.0 + } + }, + { + "guestId": "4758", + "isContainer": false, + "isVisible": true, + "sizingInfo": { + "geometry": { + "height": 908, + "width": 403, + "x": 0, + "y": 0 + }, + "maxSizeHint": { + "height": 524330, + "width": 524293 + }, + "minSize": { + "height": 143, + "width": 106 + }, + "percentageWithinParent": 1.0 + } + } + ], + "isContainer": true, + "isVisible": false, + "orientation": 2, + "sizingInfo": { + "geometry": { + "height": 908, + "width": 403, + "x": 0, + "y": 0 + }, + "maxSizeHint": { + "height": 524330, + "width": 524293 + }, + "minSize": { + "height": 143, + "width": 106 + }, + "percentageWithinParent": 0.22066387872451647 + } + }, + { + "guestId": "9", + "isContainer": false, + "isVisible": true, + "sizingInfo": { + "geometry": { + "height": 908, + "width": 1510, + "x": 408, + "y": 0 + }, + "maxSizeHint": { + "height": 524287, + "width": 524293 + }, + "minSize": { + "height": 90, + "width": 166 + }, + "percentageWithinParent": 0.7893361212754836 + } + }, + { + "children": [ + { + "isContainer": false, + "isVisible": false, + "sizingInfo": { + "geometry": { + "height": 480, + "width": 317, + "x": 0, + "y": 0 + }, + "maxSizeHint": { + "height": 16777215, + "width": 16777215 + }, + "minSize": { + "height": 90, + "width": 80 + }, + "percentageWithinParent": 0.0 + } + }, + { + "isContainer": false, + "isVisible": false, + "sizingInfo": { + "geometry": { + "height": 90, + "width": 200, + "x": 0, + "y": 0 + }, + "maxSizeHint": { + "height": 16777215, + "width": 16777215 + }, + "minSize": { + "height": 90, + "width": 80 + }, + "percentageWithinParent": 0.0 + } + }, + { + "isContainer": false, + "isVisible": false, + "sizingInfo": { + "geometry": { + "height": 90, + "width": 200, + "x": 0, + "y": 0 + }, + "maxSizeHint": { + "height": 16777215, + "width": 16777215 + }, + "minSize": { + "height": 90, + "width": 80 + }, + "percentageWithinParent": 0.0 + } + }, + { + "isContainer": false, + "isVisible": false, + "sizingInfo": { + "geometry": { + "height": 90, + "width": 200, + "x": 0, + "y": 0 + }, + "maxSizeHint": { + "height": 16777215, + "width": 16777215 + }, + "minSize": { + "height": 90, + "width": 80 + }, + "percentageWithinParent": 0.0 + } + }, + { + "isContainer": false, + "isVisible": false, + "sizingInfo": { + "geometry": { + "height": 90, + "width": 200, + "x": 0, + "y": 0 + }, + "maxSizeHint": { + "height": 16777215, + "width": 16777215 + }, + "minSize": { + "height": 90, + "width": 80 + }, + "percentageWithinParent": 0.0 + } + } + ], + "isContainer": true, + "isVisible": false, + "orientation": 2, + "sizingInfo": { + "geometry": { + "height": 0, + "width": 0, + "x": 0, + "y": 0 + }, + "maxSizeHint": { + "height": 16777215, + "width": 16777215 + }, + "minSize": { + "height": 90, + "width": 80 + }, + "percentageWithinParent": 0.0 + } + } + ], + "isContainer": true, + "isVisible": false, + "orientation": 1, + "sizingInfo": { + "geometry": { + "height": 908, + "width": 1918, + "x": 0, + "y": 0 + }, + "maxSizeHint": { + "height": 524287, + "width": 1048591 + }, + "minSize": { + "height": 143, + "width": 277 + }, + "percentageWithinParent": 1.0 + } + }, + { + "children": [ + { + "isContainer": false, + "isVisible": false, + "sizingInfo": { + "geometry": { + "height": 200, + "width": 1918, + "x": 0, + "y": 0 + }, + "maxSizeHint": { + "height": 524227, + "width": 524236 + }, + "minSize": { + "height": 90, + "width": 80 + }, + "percentageWithinParent": 1.0 + } + }, + { + "isContainer": false, + "isVisible": false, + "sizingInfo": { + "geometry": { + "height": 200, + "width": 80, + "x": 0, + "y": 0 + }, + "maxSizeHint": { + "height": 16777215, + "width": 16777215 + }, + "minSize": { + "height": 90, + "width": 80 + }, + "percentageWithinParent": 0.0 + } + } + ], + "isContainer": true, + "isVisible": false, + "orientation": 1, + "sizingInfo": { + "geometry": { + "height": 0, + "width": 0, + "x": 0, + "y": 0 + }, + "maxSizeHint": { + "height": 16777215, + "width": 16777215 + }, + "minSize": { + "height": 90, + "width": 80 + }, + "percentageWithinParent": 0.0 + } + } + ], + "isContainer": true, + "isVisible": false, + "orientation": 2, + "sizingInfo": { + "geometry": { + "height": 908, + "width": 1918, + "x": 0, + "y": 0 + }, + "maxSizeHint": { + "height": 16777215, + "width": 16777215 + }, + "minSize": { + "height": 90, + "width": 80 + }, + "percentageWithinParent": 0.0 + } + } + }, + "normalGeometry": { + "height": 668, + "width": 956, + "x": 640, + "y": 275 + }, + "options": 5, + "screenIndex": 0, + "screenSize": { + "height": 1080, + "width": 1920 + }, + "uniqueName": "mainWindowId1", + "windowState": 2 + } + ], + "screenInfo": [ + { + "devicePixelRatio": 1.0, + "geometry": { + "height": 1080, + "width": 1920, + "x": 0, + "y": 0 + }, + "index": 0, + "name": "\\\\.\\DISPLAY1" + } + ], + "serializationVersion": 3 +} diff --git a/tests/qtwidgets/tst_qtwidgets.cpp b/tests/qtwidgets/tst_qtwidgets.cpp index 637a561b0..f4e0039a7 100644 --- a/tests/qtwidgets/tst_qtwidgets.cpp +++ b/tests/qtwidgets/tst_qtwidgets.cpp @@ -216,6 +216,7 @@ private Q_SLOTS: void tst_tabBarIcons(); void tst_debugWidgetViewer(); void tst_addDockWidgetToContainingWindowNested(); + void tst_restoreInvalidPercentages(); // And fix these void tst_floatingWindowDeleted(); @@ -2949,6 +2950,28 @@ void TestQtWidgets::tst_indicatorsNotShowing() dc->programmaticStopDrag(); } +void TestQtWidgets::tst_restoreInvalidPercentages() +{ + EnsureTopLevelsDeleted e; + + auto m = createMainWindow(Size(500, 500), MainWindowOption_HasCentralWidget, "mainWindowId1"); + + createDockWidget("_kddw_internal_dummy", Platform::instance()->tests_createView({ true })); + createDockWidget("_kddw_internal_dummy2", Platform::instance()->tests_createView({ true })); + for (int i = 0; i <= 8; ++i) { + new QtWidgets::DockWidget(QStringLiteral("dockwidget_tests_%1").arg(i)); + } + + bool ok = false; + LayoutSaver restorer; + const QByteArray data = Platform::instance()->readFile(":/layouts/invalidPercentages.json", /*by-ref*/ ok); + QVERIFY(ok); + QVERIFY(restorer.restoreLayout(data)); + + LayoutSaver saver; + QVERIFY(!saver.serializeLayout().isEmpty()); +} + int main(int argc, char *argv[]) { #ifdef KDDW_HAS_SPDLOG diff --git a/tests/test_resources.qrc b/tests/test_resources.qrc index 2d1c7dbe6..1343aa26e 100644 --- a/tests/test_resources.qrc +++ b/tests/test_resources.qrc @@ -11,6 +11,7 @@ layouts/invalidCurrentTab.json layouts/sidebar_restore.json layouts/minimizeBug.json + layouts/invalidPercentages.json main.qml main2.qml main465.qml From fe17c73b51f8d0622c12fbd40611c7e44ba8a53e Mon Sep 17 00:00:00 2001 From: Sergio Martins Date: Mon, 15 Apr 2024 15:01:48 +0100 Subject: [PATCH 3/3] Recover better from invalid percentages in old layouts We were already trying to recover, but we were returning false. Return true if we recovered. --- src/core/layouting/Item.cpp | 27 +++++++++++++++++++-------- src/core/layouting/Item_p.h | 1 + 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/core/layouting/Item.cpp b/src/core/layouting/Item.cpp index 43153f215..d8f828bfd 100644 --- a/src/core/layouting/Item.cpp +++ b/src/core/layouting/Item.cpp @@ -1186,6 +1186,21 @@ int ItemBoxContainer::numSideBySide_recursive(Qt::Orientation o) const return num; } +bool ItemBoxContainer::percentagesAreSane() const +{ + const Item::List visibleChildren = this->visibleChildren(); + const Vector percentages = d->childPercentages(); + const double totalPercentage = std::accumulate(percentages.begin(), percentages.end(), 0.0); + const double expectedPercentage = visibleChildren.isEmpty() ? 0.0 : 1.0; + if (!fuzzyCompare(totalPercentage, expectedPercentage)) { + root()->dumpLayout(); + KDDW_ERROR("Percentages don't add up", totalPercentage, percentages, ( void * )this); + return false; + } + + return true; +} + bool ItemBoxContainer::checkSanity() { d->m_checkSanityScheduled = false; @@ -1280,15 +1295,11 @@ bool ItemBoxContainer::checkSanity() return false; } - const Vector percentages = d->childPercentages(); - const double totalPercentage = std::accumulate(percentages.begin(), percentages.end(), 0.0); - const double expectedPercentage = visibleChildren.isEmpty() ? 0.0 : 1.0; - if (!fuzzyCompare(totalPercentage, expectedPercentage)) { - root()->dumpLayout(); - KDDW_ERROR("Percentages don't add up", totalPercentage, percentages, ( void * )this); + if (!percentagesAreSane()) { + // Percentages might be broken due to buggy old layouts. Try to fix them: const_cast(this)->d->updateSeparators_recursive(); - KDDW_ERROR("percentages={}", d->childPercentages()); - return false; + if (!percentagesAreSane()) + return false; } } diff --git a/src/core/layouting/Item_p.h b/src/core/layouting/Item_p.h index 9d5eb6b80..f6f5d8705 100644 --- a/src/core/layouting/Item_p.h +++ b/src/core/layouting/Item_p.h @@ -444,6 +444,7 @@ class DOCKS_EXPORT ItemBoxContainer : public ItemContainer Size minSize() const override; Size maxSizeHint() const override; Size availableSize() const; + bool percentagesAreSane() const; Q_REQUIRED_RESULT bool checkSanity() override; void dumpLayout(int level = 0, bool printSeparators = true) override; void setSize_recursive(