diff options
Diffstat (limited to 'src/quicktemplates')
| -rw-r--r-- | src/quicktemplates/qquickabstractbutton.cpp | 9 | ||||
| -rw-r--r-- | src/quicktemplates/qquickcontainer.cpp | 40 | ||||
| -rw-r--r-- | src/quicktemplates/qquickmenu.cpp | 18 | ||||
| -rw-r--r-- | src/quicktemplates/qquickmenubar.cpp | 3 | ||||
| -rw-r--r-- | src/quicktemplates/qquickmonthgrid.cpp | 3 | ||||
| -rw-r--r-- | src/quicktemplates/qquickoverlay.cpp | 33 | ||||
| -rw-r--r-- | src/quicktemplates/qquickpopup.cpp | 27 | ||||
| -rw-r--r-- | src/quicktemplates/qquickshortcutcontext.cpp | 6 |
8 files changed, 91 insertions, 48 deletions
diff --git a/src/quicktemplates/qquickabstractbutton.cpp b/src/quicktemplates/qquickabstractbutton.cpp index 61c13d749e..733fbf9bb2 100644 --- a/src/quicktemplates/qquickabstractbutton.cpp +++ b/src/quicktemplates/qquickabstractbutton.cpp @@ -15,6 +15,9 @@ #if QT_CONFIG(shortcut) # include <QtGui/private/qshortcutmap_p.h> #endif +#if QT_CONFIG(accessibility) +#include <QtGui/private/qaccessiblehelper_p.h> +#endif #include <QtGui/private/qguiapplication_p.h> #include <QtGui/qpa/qplatformtheme.h> #include <QtQuick/private/qquickevents_p_p.h> @@ -1193,7 +1196,9 @@ void QQuickAbstractButton::buttonChange(ButtonChange change) break; case ButtonTextChange: { const QString txt = text(); - maybeSetAccessibleName(txt); +#if QT_CONFIG(accessibility) + maybeSetAccessibleName(qt_accStripAmp(txt)); +#endif #if QT_CONFIG(shortcut) setShortcut(QKeySequence::mnemonic(txt)); #endif @@ -1232,7 +1237,7 @@ void QQuickAbstractButton::accessibilityActiveChanged(bool active) Q_D(QQuickAbstractButton); if (active) { - maybeSetAccessibleName(text()); + maybeSetAccessibleName(qt_accStripAmp(text())); setAccessibleProperty("pressed", d->pressed); setAccessibleProperty("checked", d->checked); setAccessibleProperty("checkable", d->checkable); diff --git a/src/quicktemplates/qquickcontainer.cpp b/src/quicktemplates/qquickcontainer.cpp index 9d48f3b3a1..499fd621d6 100644 --- a/src/quicktemplates/qquickcontainer.cpp +++ b/src/quicktemplates/qquickcontainer.cpp @@ -299,15 +299,37 @@ void QQuickContainerPrivate::reorderItems() if (!contentItem) return; - QList<QQuickItem *> siblings = effectiveContentItem(contentItem)->childItems(); - - int to = 0; - for (int i = 0; i < siblings.size(); ++i) { - QQuickItem* sibling = siblings.at(i); - if (QQuickItemPrivate::get(sibling)->isTransparentForPositioner()) - continue; - int index = contentModel->indexOf(sibling, nullptr); - q->moveItem(index, to++); + // The item view eventually reparents all the items of the content model + // from the container. At this stage (during component complete), however, due + // to optimisation strategies in the item views, this doesn't happen when the + // visible area of the item view is less than the total content width of the items + // within the content model. This can cause issues while reordering. Thus, it's + // better to skip reordering the item within the content model once it's known + // that it will be reparented to the item views. + bool allowReorder = true; + if (!qobject_cast<QQuickFlickable *>(contentItem)) { + for (int index = 0; index < contentModel->count(); index++) { + if (const auto *item = qobject_cast<QQuickItem *>(contentModel->get(index))) { + const auto *parentItem = item->parentItem(); + if (parentItem && !qobject_cast<QQuickItemView *>(parentItem->parentItem())) { + allowReorder = false; + break; + } + } + } + } + + if (allowReorder) { + QList<QQuickItem *> siblings = effectiveContentItem(contentItem)->childItems(); + int to = 0; + for (int i = 0; i < siblings.size(); ++i) { + QQuickItem* sibling = siblings.at(i); + if (QQuickItemPrivate::get(sibling)->isTransparentForPositioner()) + continue; + const int index = contentModel->indexOf(sibling, nullptr); + if (index >= 0) + q->moveItem(index, to++); + } } } diff --git a/src/quicktemplates/qquickmenu.cpp b/src/quicktemplates/qquickmenu.cpp index f53e9a9091..44a9a67cd3 100644 --- a/src/quicktemplates/qquickmenu.cpp +++ b/src/quicktemplates/qquickmenu.cpp @@ -26,6 +26,8 @@ #include <private/qqmlobjectmodel_p.h> #include <QtQuick/private/qquickitem_p.h> #include <QtQuick/private/qquickitemchangelistener_p.h> +#include <QtQuick/private/qquickitemview_p_p.h> +#include <QtQuick/private/qquicklistview_p.h> #include <QtQuick/private/qquickevents_p_p.h> #include <QtQuick/private/qquickwindow_p.h> @@ -437,6 +439,22 @@ bool QQuickMenuPrivate::prepareEnterTransition() // the right, it flips on the other side of the parent menu. allowHorizontalFlip = cascade && parentMenu; + // Enter transitions may want to animate the Menu's height based on its implicitHeight. + // The Menu's implicitHeight is typically based on the ListView's contentHeight, + // among other things. The docs for ListView's forceLayout function say: + // "Responding to changes in the model is usually batched to happen only once per frame." + // As e.g. NumberAnimation's from and to values are set before any polishes happen, + // any re-evaluation of their bindings happen too late, and the starting height can be + // out-dated when menu items are added after component completion + // (QQuickItemView::componentComplete does a layout, so items declared as children aren't + // affected by this). To account for this, we force a layout before the transition starts. + // We try to avoid unnecessary re-layouting if we can avoid it. + auto *contentItemAsListView = qobject_cast<QQuickListView *>(contentItem); + if (contentItemAsListView) { + if (QQuickItemViewPrivate::get(contentItemAsListView)->currentChanges.hasPendingChanges()) + contentItemAsListView->forceLayout(); + } + if (!QQuickPopupPrivate::prepareEnterTransition()) return false; diff --git a/src/quicktemplates/qquickmenubar.cpp b/src/quicktemplates/qquickmenubar.cpp index d8ecbb6626..5aa68556c2 100644 --- a/src/quicktemplates/qquickmenubar.cpp +++ b/src/quicktemplates/qquickmenubar.cpp @@ -247,7 +247,8 @@ QQuickMenu *QQuickMenuBarPrivate::menus_at(QQmlListProperty<QQuickMenu> *prop, q void QQuickMenuBarPrivate::menus_clear(QQmlListProperty<QQuickMenu> *prop) { QQuickMenuBar *menuBar = static_cast<QQuickMenuBar *>(prop->object); - QQuickMenuBarPrivate::get(menuBar)->contentModel->clear(); + for (int count = menuBar->count(); count > 0; count = menuBar->count()) + menuBar->takeMenu(count - 1); } QPalette QQuickMenuBarPrivate::defaultPalette() const diff --git a/src/quicktemplates/qquickmonthgrid.cpp b/src/quicktemplates/qquickmonthgrid.cpp index 957c9b8f93..037f8cfaf7 100644 --- a/src/quicktemplates/qquickmonthgrid.cpp +++ b/src/quicktemplates/qquickmonthgrid.cpp @@ -45,7 +45,8 @@ QT_BEGIN_NAMESPACE \snippet qtquickcontrols-monthgrid-localization.qml 1 - \sa DayOfWeekRow, WeekNumberColumn, CalendarModel + \sa DayOfWeekRow, WeekNumberColumn, CalendarModel, + {Qt Quick Controls - Event Calendar} */ /*! diff --git a/src/quicktemplates/qquickoverlay.cpp b/src/quicktemplates/qquickoverlay.cpp index 091b2f8fb3..c9d3cf9892 100644 --- a/src/quicktemplates/qquickoverlay.cpp +++ b/src/quicktemplates/qquickoverlay.cpp @@ -97,32 +97,9 @@ bool QQuickOverlayPrivate::startDrag(QEvent *event, const QPointF &pos) return false; } -static QQuickItem *findRootOfOverlaySubtree(QQuickItem *source, const QQuickOverlay *overlay) -{ - QQuickItem *sourceAncestor = source; - while (sourceAncestor) { - QQuickItem *parentItem = sourceAncestor->parentItem(); - if (parentItem == overlay) - return sourceAncestor; - sourceAncestor = parentItem; - } - // Not an ancestor of the overlay. - return nullptr; -} - bool QQuickOverlayPrivate::handlePress(QQuickItem *source, QEvent *event, QQuickPopup *target) { - Q_Q(const QQuickOverlay); if (target) { - // childMouseEventFilter will cause this function to get called for each active popup. - // If any of those active popups block inputs, the delivery agent won't send the press event to source. - // A popup will block input, if it's modal, and the item isn't an ancestor of the popup's popup item. - // If source doesn't belong to a popup, but exists in an overlay subtree, it makes sense to not filter the event. - const QList<QQuickItem *> childItems = paintOrderChildItems(); - if (childItems.indexOf(findRootOfOverlaySubtree(source, q)) - > childItems.indexOf(QQuickPopupPrivate::get(target)->popupItem)) - return false; - if (target->overlayEvent(source, event)) { setMouseGrabberPopup(target); return true; @@ -166,17 +143,7 @@ bool QQuickOverlayPrivate::handleMove(QQuickItem *source, QEvent *event, QQuickP bool QQuickOverlayPrivate::handleRelease(QQuickItem *source, QEvent *event, QQuickPopup *target) { - Q_Q(const QQuickOverlay); if (target) { - // childMouseEventFilter will cause this function to get called for each active popup. - // If any of those active popups block inputs, the delivery agent won't send the press event to source. - // A popup will block input, if it's modal, and the item isn't an ancestor of the popup's popup item. - // If source doesn't belong to a popup, but exists in an overlay subtree, it makes sense to not filter the event. - const QList<QQuickItem *> childItems = paintOrderChildItems(); - if (childItems.indexOf(findRootOfOverlaySubtree(source, q)) - > childItems.indexOf(QQuickPopupPrivate::get(target)->popupItem)) - return false; - setMouseGrabberPopup(nullptr); if (target->overlayEvent(source, event)) { setMouseGrabberPopup(nullptr); diff --git a/src/quicktemplates/qquickpopup.cpp b/src/quicktemplates/qquickpopup.cpp index deb5651391..207b0a365a 100644 --- a/src/quicktemplates/qquickpopup.cpp +++ b/src/quicktemplates/qquickpopup.cpp @@ -2803,6 +2803,20 @@ void QQuickPopup::mouseUngrabEvent() d->handleUngrab(); } + +static QQuickItem *findRootOfOverlaySubtree(QQuickItem *source, const QQuickOverlay *overlay) +{ + QQuickItem *sourceAncestor = source; + while (sourceAncestor) { + QQuickItem *parentItem = sourceAncestor->parentItem(); + if (parentItem == overlay) + return sourceAncestor; + sourceAncestor = parentItem; + } + // Not an ancestor of the overlay. + return nullptr; +} + /*! \internal @@ -2818,6 +2832,17 @@ void QQuickPopup::mouseUngrabEvent() bool QQuickPopup::overlayEvent(QQuickItem *item, QEvent *event) { Q_D(QQuickPopup); + + // The overlay will normally call this function for each active popup, assuming there is no active mouse grabber. + // If \a item doesn't belong to any of these popups, but exists in an overlay subtree, we shouldn't filter the event, + // since the item is supposed to be independent of any active popups. + auto *overlay = QQuickOverlay::overlay(d->window); + const QList<QQuickItem *> paintOrderChildItems = QQuickOverlayPrivate::get(overlay)->paintOrderChildItems(); + const qsizetype targetItemPaintOrderIndex = paintOrderChildItems.indexOf(findRootOfOverlaySubtree(item, overlay)); + const qsizetype popupItemPaintOrderIndex = paintOrderChildItems.indexOf(d->popupItem); + if (targetItemPaintOrderIndex > popupItemPaintOrderIndex) + return false; + switch (event->type()) { case QEvent::KeyPress: case QEvent::KeyRelease: @@ -2851,7 +2876,7 @@ bool QQuickPopup::overlayEvent(QQuickItem *item, QEvent *event) void QQuickPopup::touchEvent(QTouchEvent *event) { Q_D(QQuickPopup); - d->handleTouchEvent(d->popupItem, event); + event->setAccepted(d->handleTouchEvent(d->popupItem, event)); } void QQuickPopup::touchUngrabEvent() diff --git a/src/quicktemplates/qquickshortcutcontext.cpp b/src/quicktemplates/qquickshortcutcontext.cpp index 2d07eb44f9..7f04583fe4 100644 --- a/src/quicktemplates/qquickshortcutcontext.cpp +++ b/src/quicktemplates/qquickshortcutcontext.cpp @@ -57,8 +57,12 @@ bool QQuickShortcutContext::matcher(QObject *obj, Qt::ShortcutContext context) // so that actions within it can grab shortcuts. if (auto *menu = qobject_cast<QQuickMenu *>(popup)) { auto parentMenu = QQuickMenuPrivate::get(menu)->parentMenu; - while (!obj && parentMenu) + while (parentMenu) { obj = parentMenu->window(); + if (obj) + break; + parentMenu = QQuickMenuPrivate::get(parentMenu)->parentMenu; + } } } break; |
