aboutsummaryrefslogtreecommitdiffstats
path: root/src/quicktemplates
diff options
context:
space:
mode:
Diffstat (limited to 'src/quicktemplates')
-rw-r--r--src/quicktemplates/qquickabstractbutton.cpp9
-rw-r--r--src/quicktemplates/qquickcontainer.cpp40
-rw-r--r--src/quicktemplates/qquickmenu.cpp18
-rw-r--r--src/quicktemplates/qquickmenubar.cpp3
-rw-r--r--src/quicktemplates/qquickmonthgrid.cpp3
-rw-r--r--src/quicktemplates/qquickoverlay.cpp33
-rw-r--r--src/quicktemplates/qquickpopup.cpp27
-rw-r--r--src/quicktemplates/qquickshortcutcontext.cpp6
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;