diff options
author | J-P Nurmi <jpnurmi@qt.io> | 2017-12-13 13:35:52 +0100 |
---|---|---|
committer | J-P Nurmi <jpnurmi@qt.io> | 2017-12-14 07:16:20 +0000 |
commit | 3ec6d04d976249d162f6ec92666d9008f4c21c34 (patch) | |
tree | 2faeeae7d2c3fb5e086c91ccd5c1c9bda834005c /src/quicktemplates2/qquickcombobox.cpp | |
parent | 1c265b23ef7494abc6a00094e781a8e48de87121 (diff) |
ComboBox: use deferred execution
As a special case, ComboBox defers the execution of the popup until
the popup is either accessed or made visible. This gives a nice boost
in creation time benchmarks (20->25, ~25%). The old optimization of
setting the delegate model only when the popup is visible is no longer
needed.
Task-number: QTBUG-50992
Change-Id: Ifeaceb759ab676bb54c6bc09dc97810eade72ca1
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src/quicktemplates2/qquickcombobox.cpp')
-rw-r--r-- | src/quicktemplates2/qquickcombobox.cpp | 106 |
1 files changed, 80 insertions, 26 deletions
diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp index d22e09d5..dde27e2a 100644 --- a/src/quicktemplates2/qquickcombobox.cpp +++ b/src/quicktemplates2/qquickcombobox.cpp @@ -38,6 +38,7 @@ #include "qquickcontrol_p_p.h" #include "qquickabstractbutton_p.h" #include "qquickpopup_p_p.h" +#include "qquickdeferredexecute_p_p.h" #include <QtCore/qregexp.h> #include <QtCore/qabstractitemmodel.h> @@ -252,6 +253,11 @@ public: void handleRelease(const QPointF &point) override; void handleUngrab() override; + QQuickItem *getContentItem() override; + + void executeIndicator(bool complete = false); + void executePopup(bool complete = false); + bool flat; bool down; bool hasDown; @@ -268,8 +274,8 @@ public: QQuickItem *pressedItem; QQmlInstanceModel *delegateModel; QQmlComponent *delegate; - QQuickItem *indicator; - QQuickPopup *popup; + QQuickDeferredPointer<QQuickItem> indicator; + QQuickDeferredPointer<QQuickPopup> popup; struct ExtraData { ExtraData() @@ -313,6 +319,9 @@ bool QQuickComboBoxPrivate::isPopupVisible() const void QQuickComboBoxPrivate::showPopup() { + if (!popup) + executePopup(true); + if (popup && !popup->isVisible()) popup->open(); } @@ -330,13 +339,10 @@ void QQuickComboBoxPrivate::hidePopup(bool accept) void QQuickComboBoxPrivate::togglePopup(bool accept) { - if (!popup) - return; - - if (popup->isVisible()) - hidePopup(accept); - else + if (!popup || !popup->isVisible()) showPopup(); + else + hidePopup(accept); } void QQuickComboBoxPrivate::popupVisibleChanged() @@ -366,8 +372,11 @@ void QQuickComboBoxPrivate::createdItem(int index, QObject *object) { Q_Q(QQuickComboBox); QQuickItem *item = qobject_cast<QQuickItem *>(object); - if (popup && item && !item->parentItem()) { - item->setParentItem(popup->contentItem()); + if (item && !item->parentItem()) { + if (popup) + item->setParentItem(popup->contentItem()); + else + item->setParentItem(q); QQuickItemPrivate::get(item)->setCulled(true); } @@ -662,6 +671,41 @@ void QQuickComboBoxPrivate::handleUngrab() q->setPressed(false); } +QQuickItem *QQuickComboBoxPrivate::getContentItem() +{ + if (!contentItem) + executeContentItem(); + return contentItem; +} + +static inline QString indicatorName() { return QStringLiteral("indicator"); } + +void QQuickComboBoxPrivate::executeIndicator(bool complete) +{ + Q_Q(QQuickComboBox); + if (indicator.wasExecuted()) + return; + + if (!indicator) + quickBeginDeferred(q, indicatorName(), indicator); + if (complete) + quickCompleteDeferred(q, indicatorName(), indicator); +} + +static inline QString popupName() { return QStringLiteral("popup"); } + +void QQuickComboBoxPrivate::executePopup(bool complete) +{ + Q_Q(QQuickComboBox); + if (popup.wasExecuted()) + return; + + if (!popup) + quickBeginDeferred(q, popupName(), popup); + if (complete) + quickCompleteDeferred(q, popupName(), popup); +} + QQuickComboBox::QQuickComboBox(QQuickItem *parent) : QQuickControl(*(new QQuickComboBoxPrivate), parent) { @@ -677,14 +721,13 @@ QQuickComboBox::QQuickComboBox(QQuickItem *parent) QQuickComboBox::~QQuickComboBox() { Q_D(QQuickComboBox); - // Disconnect visibleChanged() to avoid a spurious highlightedIndexChanged() signal - // emission during the destruction of the (visible) popup. (QTBUG-57650) - QObjectPrivate::disconnect(d->popup, &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::popupVisibleChanged); - - // Delete the popup directly instead of calling setPopup(nullptr) to avoid calling - // destroyDelegate(popup) and potentially accessing a destroyed QML context. (QTBUG-50992) - delete d->popup; - d->popup = nullptr; + if (d->popup) { + // Disconnect visibleChanged() to avoid a spurious highlightedIndexChanged() signal + // emission during the destruction of the (visible) popup. (QTBUG-57650) + QObjectPrivate::disconnect(d->popup.data(), &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::popupVisibleChanged); + delete d->popup; + d->popup = nullptr; + } } /*! @@ -969,7 +1012,9 @@ void QQuickComboBox::setDelegate(QQmlComponent* delegate) */ QQuickItem *QQuickComboBox::indicator() const { - Q_D(const QQuickComboBox); + QQuickComboBoxPrivate *d = const_cast<QQuickComboBoxPrivate *>(d_func()); + if (!d->indicator) + d->executeIndicator(); return d->indicator; } @@ -979,13 +1024,14 @@ void QQuickComboBox::setIndicator(QQuickItem *indicator) if (d->indicator == indicator) return; - QQuickControlPrivate::destroyDelegate(d->indicator, this); + delete d->indicator; d->indicator = indicator; if (indicator) { if (!indicator->parentItem()) indicator->setParentItem(this); } - emit indicatorChanged(); + if (!d->indicator.isExecuting()) + emit indicatorChanged(); } /*! @@ -1003,7 +1049,9 @@ void QQuickComboBox::setIndicator(QQuickItem *indicator) */ QQuickPopup *QQuickComboBox::popup() const { - Q_D(const QQuickComboBox); + QQuickComboBoxPrivate *d = const_cast<QQuickComboBoxPrivate *>(d_func()); + if (!d->popup) + d->executePopup(isComponentComplete()); return d->popup; } @@ -1014,8 +1062,8 @@ void QQuickComboBox::setPopup(QQuickPopup *popup) return; if (d->popup) { - QObjectPrivate::disconnect(d->popup, &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::popupVisibleChanged); - QQuickControlPrivate::destroyDelegate(d->popup, this); + QObjectPrivate::disconnect(d->popup.data(), &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::popupVisibleChanged); + delete d->popup; } if (popup) { QQuickPopupPrivate::get(popup)->allowVerticalFlip = true; @@ -1023,7 +1071,8 @@ void QQuickComboBox::setPopup(QQuickPopup *popup) QObjectPrivate::connect(popup, &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::popupVisibleChanged); } d->popup = popup; - emit popupChanged(); + if (!d->popup.isExecuting()) + emit popupChanged(); } /*! @@ -1494,7 +1543,7 @@ void QQuickComboBox::keyReleaseEvent(QKeyEvent *event) { Q_D(QQuickComboBox); QQuickControl::keyReleaseEvent(event); - if (!d->popup || event->isAutoRepeat()) + if (event->isAutoRepeat()) return; switch (event->key()) { @@ -1541,6 +1590,11 @@ void QQuickComboBox::wheelEvent(QWheelEvent *event) void QQuickComboBox::componentComplete() { Q_D(QQuickComboBox); + d->executeIndicator(true); + d->executeBackground(true); + d->executeContentItem(true); + if (d->popup) + d->executePopup(true); QQuickControl::componentComplete(); if (d->delegateModel && d->ownModel) |