diff options
author | Mitch Curtis <mitch.curtis@qt.io> | 2023-08-22 18:17:50 +0800 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-08-28 11:47:49 +0000 |
commit | e0e618bc36400ba230efdf17cee81d4eb3732b9d (patch) | |
tree | 3de3b1d510766e2cf763f0941d8b1fee1855be9f | |
parent | 742c8bd1291040b23a1eecd3257a05686023e009 (diff) |
Fix child popup palette inheritance
Qt Quick Controls Popups are always top-level popups, even if declared
as a child of another popup. Therefore, e.g. a font set on a parent
popup should not propagate to a child popup. The same behavior applies
to palettes, but we regressed with this in
1875ad7f92cad270cc5857d71096a4b46c27c562 and/or
31f5c21ddb571d744efd1885c0687816b3a12225.
This patch fixes the regression by returning the window's palette in
QQuickPaletteProviderPrivateBase<I, Impl>::parentPalette() if I is
a QQuickPopup.
Fixes: QTBUG-115707
Change-Id: Ib89852787dd45e3edc9e846b6c182340c052f0fd
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
(cherry picked from commit 950cd5888e3098bc4c04fc0af4beabe265c78a6e)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
3 files changed, 89 insertions, 10 deletions
diff --git a/src/quick/items/qquickpaletteproviderprivatebase_p.h b/src/quick/items/qquickpaletteproviderprivatebase_p.h index a0e0302ea9..f374b64e30 100644 --- a/src/quick/items/qquickpaletteproviderprivatebase_p.h +++ b/src/quick/items/qquickpaletteproviderprivatebase_p.h @@ -230,9 +230,9 @@ template<class Impl, class I> decltype(auto) getPrivateImpl(I &t) { return Impl: template <class T> decltype(auto) getPrivate(T &item) { - if constexpr (std::is_same_v<T, QQuickWindow>) { + if constexpr (std::is_base_of_v<T, QQuickWindow>) { return getPrivateImpl<QQuickWindowPrivate>(item); - } else if constexpr (std::is_same_v<T, QQuickItem>) { + } else if constexpr (std::is_base_of_v<T, QQuickItem>) { return getPrivateImpl<QQuickItemPrivate>(item); } else { static_assert (dependent_false<T>::value, "Extend please."); @@ -257,12 +257,15 @@ template<class I, class Impl> QPalette QQuickPaletteProviderPrivateBase<I, Impl>::parentPalette(const QPalette &fallbackPalette) const { if constexpr (!isRootWindow<I>()) { - for (auto parentItem = itemWithPalette()->parentItem(); parentItem; - parentItem = parentItem->parentItem()) { - - // Don't allocate a new palette here. Use only if it's already pre allocated - if (parentItem && getPrivate(*parentItem)->providesPalette()) { - return getPrivate(*parentItem)->palette()->toQPalette(); + // Popups should always inherit from their window, even child popups: QTBUG-115707. + if (!std::is_base_of_v<QQuickPopup, I>) { + for (auto parentItem = itemWithPalette()->parentItem(); parentItem; + parentItem = parentItem->parentItem()) { + + // Don't allocate a new palette here. Use only if it's already pre allocated + if (parentItem && getPrivate(*parentItem)->providesPalette()) { + return getPrivate(*parentItem)->palette()->toQPalette(); + } } } @@ -279,7 +282,7 @@ const QQuickItem* rootItem(const I &item) { if constexpr (isRootWindow<I>()) { return item.contentItem(); - } else if constexpr (std::is_same_v<QQuickPopup, I>) { + } else if constexpr (std::is_base_of_v<QQuickPopup, I>) { return nullptr; } else { return &item; diff --git a/tests/auto/quickcontrols/palette/data/childPopupInheritance.qml b/tests/auto/quickcontrols/palette/data/childPopupInheritance.qml new file mode 100644 index 0000000000..4c160db092 --- /dev/null +++ b/tests/auto/quickcontrols/palette/data/childPopupInheritance.qml @@ -0,0 +1,40 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Controls + +ApplicationWindow { + id: window + + Popup { + id: parentPopup + objectName: "parentPopup" + palette.windowText: "#ffdead" + + Label { + text: "parentPopupLabel" + objectName: text + } + + Popup { + id: childPopup + objectName: "childPopup" + + Label { + text: "childPopupLabel" + objectName: text + } + + Popup { + id: grandchildPopup + objectName: "grandchildPopup" + + Label { + text: "grandchildPopupLabel" + objectName: text + } + } + } + } +} diff --git a/tests/auto/quickcontrols/palette/tst_palette.cpp b/tests/auto/quickcontrols/palette/tst_palette.cpp index e3a53f0c21..52f2502bf0 100644 --- a/tests/auto/quickcontrols/palette/tst_palette.cpp +++ b/tests/auto/quickcontrols/palette/tst_palette.cpp @@ -7,6 +7,7 @@ #include <QtQml/qqmlengine.h> #include <QtQml/qqmlcomponent.h> #include <QtQuickTestUtils/private/qmlutils_p.h> +#include <QtQuickControlsTestUtils/private/controlstestutils_p.h> #include <QtQuick/private/qquickitem_p.h> #include <QtQuickTemplates2/private/qquickapplicationwindow_p.h> #include <QtQuickTemplates2/private/qquickcontrol_p.h> @@ -17,7 +18,7 @@ #include <QtQuickTemplates2/private/qquickbutton_p.h> #include <QtQuickControls2/qquickstyle.h> -//using namespace QQuickVisualTestUtils; +using namespace QQuickControlsTestUtils; // Need a more descriptive failure message: QTBUG-87039 #define COMPARE_PALETTES(actualPalette, expectedPalette) \ @@ -40,6 +41,7 @@ private slots: void inheritance_data(); void inheritance(); + void childPopupInheritance(); void defaultPalette_data(); void defaultPalette(); @@ -203,6 +205,40 @@ void tst_palette::inheritance() QCOMPARE(grandChildPalette->window(), windowPalette->window()); } +// The child popups in inheritance() don't test actual nested child popups, +// only popups that are children of items and the items within those popups. +// We need to specifically test this to prevent QTBUG-115707 from happening again. +void tst_palette::childPopupInheritance() +{ + QQuickControlsApplicationHelper helper(this, QLatin1String("childPopupInheritance.qml")); + QVERIFY2(helper.ready, helper.failureMessage()); + + const auto *windowPrivate = QQuickWindowPrivate::get(helper.window); + const auto windowsWindowTextColor = windowPrivate->palette()->toQPalette().color(QPalette::WindowText); + + // parentPopup sets windowText explicitly, so its label should use that color. + auto *parentPopup = helper.appWindow->findChild<QQuickPopup *>("parentPopup"); + QVERIFY(parentPopup); + parentPopup->open(); + QTRY_VERIFY(parentPopup->isOpened()); + auto *parentPopupLabel = helper.appWindow->findChild<QObject *>("parentPopupLabel"); + QVERIFY(parentPopupLabel); + QCOMPARE(parentPopupLabel->property("color").value<QColor>(), "#ffdead"); + + // All other child popups don't set anything explicitly, and should inherit from their window. + auto *childPopup = helper.appWindow->findChild<QQuickPopup *>("childPopup"); + QVERIFY(childPopup); + auto *childPopupLabel = helper.appWindow->findChild<QObject *>("childPopupLabel"); + QVERIFY(childPopupLabel); + QCOMPARE(childPopupLabel->property("color").value<QColor>(), windowsWindowTextColor); + + auto *grandchildPopup = helper.appWindow->findChild<QQuickPopup *>("grandchildPopup"); + QVERIFY(grandchildPopup); + auto *grandchildPopupLabel = helper.appWindow->findChild<QObject *>("grandchildPopupLabel"); + QVERIFY(grandchildPopupLabel); + QCOMPARE(grandchildPopupLabel->property("color").value<QColor>(), windowsWindowTextColor); +} + class TestTheme : public QQuickTheme { public: |