diff options
author | Liang Qi <liang.qi@qt.io> | 2018-10-15 14:51:00 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2018-10-15 15:15:22 +0200 |
commit | 2876332ad911b3c0402006ca9116af66cecdb8eb (patch) | |
tree | 70971ccda91a100edc39aac18a82dbff5ca04eaf | |
parent | 567a2de8cd493aabe0055d6dbc367b39447e70dd (diff) | |
parent | d56c193eb4ceb640611d66f22e1f26aae91cd7d1 (diff) |
Merge remote-tracking branch 'origin/5.11' into 5.12v5.12.0-beta3
Conflicts:
src/quicktemplates2/qquickmenubar.cpp
src/quicktemplates2/qquickmenubar_p.h
src/quicktemplates2/qquickmenubar_p_p.h
Change-Id: I5c2115f05826f68f1b1f5ce6762273cd91e6997e
-rw-r--r-- | src/quicktemplates2/qquickcontainer.cpp | 25 | ||||
-rw-r--r-- | src/quicktemplates2/qquickcontainer_p_p.h | 2 | ||||
-rw-r--r-- | src/quicktemplates2/qquickmenubar.cpp | 41 | ||||
-rw-r--r-- | src/quicktemplates2/qquickmenubar_p.h | 1 | ||||
-rw-r--r-- | src/quicktemplates2/qquickmenubar_p_p.h | 2 | ||||
-rw-r--r-- | src/quicktemplates2/qquickpopuppositioner.cpp | 2 | ||||
-rw-r--r-- | tests/auto/qquickmenubar/data/delegateFromSeparateComponent.qml | 79 | ||||
-rw-r--r-- | tests/auto/qquickmenubar/tst_qquickmenubar.cpp | 27 |
8 files changed, 166 insertions, 13 deletions
diff --git a/src/quicktemplates2/qquickcontainer.cpp b/src/quicktemplates2/qquickcontainer.cpp index c4af6151..8217a3ff 100644 --- a/src/quicktemplates2/qquickcontainer.cpp +++ b/src/quicktemplates2/qquickcontainer.cpp @@ -336,6 +336,21 @@ void QQuickContainerPrivate::reorderItems() } } +// Helper function needed for derived classes such as QQuickMenuBarPrivate. +void QQuickContainerPrivate::addObject(QObject *obj) +{ + Q_Q(QQuickContainer); + QQuickItem *item = qobject_cast<QQuickItem *>(obj); + if (item) { + if (QQuickItemPrivate::get(item)->isTransparentForPositioner()) + item->setParentItem(effectiveContentItem(contentItem)); + else if (contentModel->indexOf(item, nullptr) == -1) + q->addItem(item); + } else { + contentData.append(obj); + } +} + void QQuickContainerPrivate::_q_currentIndexChanged() { Q_Q(QQuickContainer); @@ -379,15 +394,7 @@ void QQuickContainerPrivate::contentData_append(QQmlListProperty<QObject> *prop, { QQuickContainer *q = static_cast<QQuickContainer *>(prop->object); QQuickContainerPrivate *p = QQuickContainerPrivate::get(q); - QQuickItem *item = qobject_cast<QQuickItem *>(obj); - if (item) { - if (QQuickItemPrivate::get(item)->isTransparentForPositioner()) - item->setParentItem(effectiveContentItem(p->contentItem)); - else if (p->contentModel->indexOf(item, nullptr) == -1) - q->addItem(item); - } else { - p->contentData.append(obj); - } + p->addObject(obj); } int QQuickContainerPrivate::contentData_count(QQmlListProperty<QObject> *prop) diff --git a/src/quicktemplates2/qquickcontainer_p_p.h b/src/quicktemplates2/qquickcontainer_p_p.h index 16e9c9f6..5ddf298a 100644 --- a/src/quicktemplates2/qquickcontainer_p_p.h +++ b/src/quicktemplates2/qquickcontainer_p_p.h @@ -73,6 +73,8 @@ public: void removeItem(int index, QQuickItem *item); void reorderItems(); + void addObject(QObject *obj); + void _q_currentIndexChanged(); void itemChildAdded(QQuickItem *item, QQuickItem *child) override; diff --git a/src/quicktemplates2/qquickmenubar.cpp b/src/quicktemplates2/qquickmenubar.cpp index 6016e70d..62205b6e 100644 --- a/src/quicktemplates2/qquickmenubar.cpp +++ b/src/quicktemplates2/qquickmenubar.cpp @@ -76,6 +76,25 @@ QT_BEGIN_NAMESPACE {Focus Management in Qt Quick Controls 2} */ +void QQuickMenuBarPrivate::createItems() +{ + // removeItem() will remove stuff from contentData, so we have to make a copy of it. + const auto originalContentData = QQuickContainerPrivate::contentData; + // Sanity check that there aren't any items we don't know about. + Q_ASSERT(contentModel->count() == 0); + + for (QObject *object : originalContentData) { + if (QQuickMenu *menu = qobject_cast<QQuickMenu *>(object)) { + // It's a QQuickMenu; create a QQuickMenuBarItem for it. + QQuickItem *menuItem = createItem(menu); + addObject(menuItem); + } else if (qobject_cast<QQuickMenuBarItem *>(object)) { + addObject(object); + } + // If it's neither, skip it because we don't care about it. + } +} + QQuickItem *QQuickMenuBarPrivate::beginCreateItem() { Q_Q(QQuickMenuBar); @@ -254,9 +273,18 @@ void QQuickMenuBarPrivate::itemImplicitHeightChanged(QQuickItem *item) void QQuickMenuBarPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObject *obj) { QQuickMenuBar *menuBar = static_cast<QQuickMenuBar *>(prop->object); - if (QQuickMenu *menu = qobject_cast<QQuickMenu *>(obj)) - obj = QQuickMenuBarPrivate::get(menuBar)->createItem(menu); - QQuickContainerPrivate::contentData_append(prop, obj); + QQuickMenuBarPrivate *menuBarPrivate = QQuickMenuBarPrivate::get(menuBar); + if (!menuBarPrivate->componentComplete) { + // Don't add items until we're complete, as the delegate could change in the meantime. + // We'll add it to contentData and create it when we're complete. + menuBarPrivate->QQuickContainerPrivate::contentData.append(obj); + return; + } + + if (QQuickMenu *menu = qobject_cast<QQuickMenu *>(obj)) { + QQuickItem *menuItem = menuBarPrivate->createItem(menu); + menuBarPrivate->addObject(menuItem); + } } void QQuickMenuBarPrivate::menus_append(QQmlListProperty<QQuickMenu> *prop, QQuickMenu *obj) @@ -454,6 +482,13 @@ QQmlListProperty<QObject> QQuickMenuBarPrivate::contentData() QQuickContainerPrivate::contentData_clear); } +void QQuickMenuBar::componentComplete() +{ + Q_D(QQuickMenuBar); + QQuickContainer::componentComplete(); + d->createItems(); +} + bool QQuickMenuBar::eventFilter(QObject *object, QEvent *event) { return QObject::eventFilter(object, event); diff --git a/src/quicktemplates2/qquickmenubar_p.h b/src/quicktemplates2/qquickmenubar_p.h index af37d0f2..983bb578 100644 --- a/src/quicktemplates2/qquickmenubar_p.h +++ b/src/quicktemplates2/qquickmenubar_p.h @@ -81,6 +81,7 @@ Q_SIGNALS: void menusChanged(); protected: + void componentComplete() override; bool eventFilter(QObject *object, QEvent *event) override; void keyPressEvent(QKeyEvent *event) override; void keyReleaseEvent(QKeyEvent *event) override; diff --git a/src/quicktemplates2/qquickmenubar_p_p.h b/src/quicktemplates2/qquickmenubar_p_p.h index 75fbed73..4d5e61e6 100644 --- a/src/quicktemplates2/qquickmenubar_p_p.h +++ b/src/quicktemplates2/qquickmenubar_p_p.h @@ -69,6 +69,8 @@ public: QQmlListProperty<QQuickMenu> menus(); QQmlListProperty<QObject> contentData(); + void createItems(); + QQuickItem *beginCreateItem(); void completeCreateItem(); diff --git a/src/quicktemplates2/qquickpopuppositioner.cpp b/src/quicktemplates2/qquickpopuppositioner.cpp index 69a57674..ebd8ff29 100644 --- a/src/quicktemplates2/qquickpopuppositioner.cpp +++ b/src/quicktemplates2/qquickpopuppositioner.cpp @@ -300,7 +300,7 @@ void QQuickPopupPositioner::addAncestorListeners(QQuickItem *item) QQuickItem *p = item; while (p) { - QQuickItemPrivate::get(p)->addItemChangeListener(this, AncestorChangeTypes); + QQuickItemPrivate::get(p)->updateOrAddItemChangeListener(this, AncestorChangeTypes); p = p->parentItem(); } } diff --git a/tests/auto/qquickmenubar/data/delegateFromSeparateComponent.qml b/tests/auto/qquickmenubar/data/delegateFromSeparateComponent.qml new file mode 100644 index 00000000..9d58e8c6 --- /dev/null +++ b/tests/auto/qquickmenubar/data/delegateFromSeparateComponent.qml @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.11 +import QtQuick.Controls 2.4 + +ApplicationWindow { + width: 800 + height: 800 + + Component { + id: menuBarItemComponent + + MenuBarItem { + contentItem: Text { + text: parent.text + color: "blue" + } + background: Rectangle { + color: "#00ff00" + } + } + } + + menuBar: MenuBar { + delegate: menuBarItemComponent + + Menu { + title: "Menu" + } + } +} diff --git a/tests/auto/qquickmenubar/tst_qquickmenubar.cpp b/tests/auto/qquickmenubar/tst_qquickmenubar.cpp index 3d6c2bbf..cfcdee5e 100644 --- a/tests/auto/qquickmenubar/tst_qquickmenubar.cpp +++ b/tests/auto/qquickmenubar/tst_qquickmenubar.cpp @@ -63,6 +63,7 @@ private slots: void keys(); void mnemonics(); void addRemove(); + void delegateFromSeparateComponent(); }; void tst_qquickmenubar::delegate() @@ -578,6 +579,32 @@ void tst_qquickmenubar::addRemove() QVERIFY(menuBarItem1.isNull()); } +// QTBUG-67559 +// Test that Menus declared as children of a MenuBar have the +// correct delegate when it is declared outside of the MenuBar as a Component. +void tst_qquickmenubar::delegateFromSeparateComponent() +{ + QQuickApplicationHelper helper(this, QLatin1String("delegateFromSeparateComponent.qml")); + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window)); + + const QColor green = QColor::fromRgb(0x00ff00); + + QQuickMenuBar *menuBar = window->property("menuBar").value<QQuickMenuBar*>(); + QVERIFY(menuBar); + + QQuickMenu *menu = qobject_cast<QQuickMenu*>(menuBar->menuAt(0)); + QVERIFY(menu); + + QQuickMenuBarItem *menuBarItem = qobject_cast<QQuickMenuBarItem *>(menu->parentItem()); + QVERIFY(menuBarItem); + + QQuickItem *menuBarItemBg = menuBarItem->property("background").value<QQuickItem*>(); + QVERIFY(menuBarItemBg); + QCOMPARE(menuBarItemBg->property("color").value<QColor>(), green); +} + QTEST_QUICKCONTROLS_MAIN(tst_qquickmenubar) #include "tst_qquickmenubar.moc" |