diff options
Diffstat (limited to 'src/quicktemplates2')
28 files changed, 537 insertions, 46 deletions
diff --git a/src/quicktemplates2/accessible/accessible.pri b/src/quicktemplates2/accessible/accessible.pri new file mode 100644 index 00000000..93660b9f --- /dev/null +++ b/src/quicktemplates2/accessible/accessible.pri @@ -0,0 +1,5 @@ +HEADERS += \ + $$PWD/qaccessiblequickpage_p.h + +SOURCES += \ + $$PWD/qaccessiblequickpage.cpp diff --git a/src/quicktemplates2/accessible/qaccessiblequickpage.cpp b/src/quicktemplates2/accessible/qaccessiblequickpage.cpp new file mode 100644 index 00000000..90ac49f9 --- /dev/null +++ b/src/quicktemplates2/accessible/qaccessiblequickpage.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qaccessiblequickpage_p.h" +#include "qquickpage_p.h" + +QT_BEGIN_NAMESPACE + +QAccessibleQuickPage::QAccessibleQuickPage(QQuickPage *page) + : QAccessibleQuickItem(page) +{ +} + +QAccessibleInterface *QAccessibleQuickPage::child(int index) const +{ + const QList<QQuickItem*> kids = orderedChildItems(); + if (QQuickItem *item = kids.value(index)) + return QAccessible::queryAccessibleInterface(item); + return nullptr; +} + +int QAccessibleQuickPage::indexOfChild(const QAccessibleInterface *iface) const +{ + const QList<QQuickItem*> kids = orderedChildItems(); + return (int)kids.indexOf(static_cast<QQuickItem*>(iface->object())); +} + +QList<QQuickItem *> QAccessibleQuickPage::orderedChildItems() const +{ + // Just ensures that the header is first, and footer is last. Other existing order is kept. + const QQuickPage *p = page(); + QList<QQuickItem*> kids = childItems(); + const qsizetype hidx = kids.indexOf(p->header()); + if (hidx != -1) + kids.move(hidx, 0); + const qsizetype fidx = kids.indexOf(p->footer()); + if (fidx != -1) + kids.move(fidx, kids.count() - 1); + return kids; +} + +QQuickPage *QAccessibleQuickPage::page() const +{ + return static_cast<QQuickPage*>(object()); +} + +QT_END_NAMESPACE + diff --git a/src/quicktemplates2/accessible/qaccessiblequickpage_p.h b/src/quicktemplates2/accessible/qaccessiblequickpage_p.h new file mode 100644 index 00000000..9b208c14 --- /dev/null +++ b/src/quicktemplates2/accessible/qaccessiblequickpage_p.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QACCESSIBLEQUICKPAGE_H +#define QACCESSIBLEQUICKPAGE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtQuick/private/qaccessiblequickitem_p.h> + +QT_BEGIN_NAMESPACE + +class QQuickPage; + +class QAccessibleQuickPage : public QAccessibleQuickItem +{ +public: + QAccessibleQuickPage(QQuickPage *page); + QAccessibleInterface *child(int index) const override; + int indexOfChild(const QAccessibleInterface *iface) const override; +private: + QQuickPage *page() const; + QList<QQuickItem *> orderedChildItems() const; +}; + +QT_END_NAMESPACE + +#endif // QACCESSIBLEQUICKPAGE_H diff --git a/src/quicktemplates2/qquickabstractbutton.cpp b/src/quicktemplates2/qquickabstractbutton.cpp index 950e4e09..20cf59c1 100644 --- a/src/quicktemplates2/qquickabstractbutton.cpp +++ b/src/quicktemplates2/qquickabstractbutton.cpp @@ -215,8 +215,20 @@ bool QQuickAbstractButtonPrivate::acceptKeyClick(Qt::Key key) const bool QQuickAbstractButtonPrivate::isPressAndHoldConnected() { Q_Q(QQuickAbstractButton); - const auto signal = &QQuickAbstractButton::pressAndHold; - const QMetaMethod method = QMetaMethod::fromSignal(signal); + static const QMetaMethod method = [&]() { + const auto signal = &QQuickAbstractButton::pressAndHold; + return QMetaMethod::fromSignal(signal); + }(); + return q->isSignalConnected(method); +} + +bool QQuickAbstractButtonPrivate::isDoubleClickConnected() +{ + Q_Q(QQuickAbstractButton); + static const QMetaMethod method = [&]() { + const auto signal = &QQuickAbstractButton::doubleClicked; + return QMetaMethod::fromSignal(signal); + }(); return q->isSignalConnected(method); } @@ -387,6 +399,17 @@ void QQuickAbstractButtonPrivate::itemImplicitHeightChanged(QQuickItem *item) emit q->implicitIndicatorHeightChanged(); } +void QQuickAbstractButtonPrivate::itemDestroyed(QQuickItem *item) +{ + Q_Q(QQuickAbstractButton); + QQuickControlPrivate::itemDestroyed(item); + if (item == indicator) { + indicator = nullptr; + emit q->implicitIndicatorWidthChanged(); + emit q->implicitIndicatorHeightChanged(); + } +} + QQuickAbstractButton *QQuickAbstractButtonPrivate::findCheckedButton() const { Q_Q(const QQuickAbstractButton); @@ -1086,9 +1109,11 @@ void QQuickAbstractButton::mousePressEvent(QMouseEvent *event) void QQuickAbstractButton::mouseDoubleClickEvent(QMouseEvent *event) { Q_D(QQuickAbstractButton); - QQuickControl::mouseDoubleClickEvent(event); - emit doubleClicked(); - d->wasDoubleClick = true; + if (d->isDoubleClickConnected()) { + QQuickControl::mouseDoubleClickEvent(event); + emit doubleClicked(); + d->wasDoubleClick = true; + } } void QQuickAbstractButton::timerEvent(QTimerEvent *event) diff --git a/src/quicktemplates2/qquickabstractbutton_p_p.h b/src/quicktemplates2/qquickabstractbutton_p_p.h index 9291c1a8..907790dc 100644 --- a/src/quicktemplates2/qquickabstractbutton_p_p.h +++ b/src/quicktemplates2/qquickabstractbutton_p_p.h @@ -80,6 +80,7 @@ public: virtual bool acceptKeyClick(Qt::Key key) const; bool isPressAndHoldConnected(); + bool isDoubleClickConnected(); void startPressAndHold(); void stopPressAndHold(); @@ -109,6 +110,7 @@ public: void itemImplicitWidthChanged(QQuickItem *item) override; void itemImplicitHeightChanged(QQuickItem *item) override; + void itemDestroyed(QQuickItem *item) override; // copied from qabstractbutton.cpp static const int AUTO_REPEAT_DELAY = 300; diff --git a/src/quicktemplates2/qquickaction.cpp b/src/quicktemplates2/qquickaction.cpp index 2041e774..8610cdfa 100644 --- a/src/quicktemplates2/qquickaction.cpp +++ b/src/quicktemplates2/qquickaction.cpp @@ -145,7 +145,7 @@ int QQuickActionPrivate::ShortcutEntry::shortcutId() const void QQuickActionPrivate::ShortcutEntry::grab(const QKeySequence &shortcut, bool enabled) { - if (shortcut.isEmpty()) + if (shortcut.isEmpty() || m_shortcutId) return; Qt::ShortcutContext context = Qt::WindowShortcut; // TODO diff --git a/src/quicktemplates2/qquickapplicationwindow.cpp b/src/quicktemplates2/qquickapplicationwindow.cpp index 903de676..a9a4ad72 100644 --- a/src/quicktemplates2/qquickapplicationwindow.cpp +++ b/src/quicktemplates2/qquickapplicationwindow.cpp @@ -48,6 +48,7 @@ #include "qquickdeferredpointer_p_p.h" #include <QtCore/private/qobject_p.h> +#include <QtCore/qscopedvaluerollback.h> #include <QtQuick/private/qquickitem_p.h> #include <QtQuick/private/qquickitemchangelistener_p.h> @@ -174,6 +175,7 @@ public: QPalette palette; QQuickItem *activeFocusControl = nullptr; QQuickApplicationWindow *q_ptr = nullptr; + bool insideRelayout = false; }; static void layoutItem(QQuickItem *item, qreal y, qreal width) @@ -192,9 +194,10 @@ static void layoutItem(QQuickItem *item, qreal y, qreal width) void QQuickApplicationWindowPrivate::relayout() { Q_Q(QQuickApplicationWindow); - if (!complete) + if (!complete || insideRelayout) return; + QScopedValueRollback<bool> guard(insideRelayout, true); QQuickItem *content = q->contentItem(); qreal hh = header && header->isVisible() ? header->height() : 0; qreal fh = footer && footer->isVisible() ? footer->height() : 0; @@ -650,6 +653,8 @@ QQuickOverlay *QQuickApplicationWindow::overlay() const if (!d->overlay) { d->overlay = new QQuickOverlay(QQuickWindow::contentItem()); + // make the overlay discoverable by the virtual keyboard + d->q_ptr->setProperty("_q_QQuickOverlay", QVariant::fromValue<QQuickItem*>(d->overlay)); d->overlay->stackAfter(QQuickApplicationWindow::contentItem()); } return d->overlay; diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp index 3b87e489..e7d99a5d 100644 --- a/src/quicktemplates2/qquickcombobox.cpp +++ b/src/quicktemplates2/qquickcombobox.cpp @@ -234,6 +234,7 @@ public: void updateCurrentText(); void updateCurrentValue(); void updateCurrentTextAndValue(); + void updateAcceptableInput(); bool isValidIndex(int index) const; @@ -265,6 +266,8 @@ public: void itemImplicitWidthChanged(QQuickItem *item) override; void itemImplicitHeightChanged(QQuickItem *item) override; + void setInputMethodHints(Qt::InputMethodHints hints, bool force = false); + static void hideOldPopup(QQuickPopup *popup); bool flat = false; @@ -288,6 +291,7 @@ public: QQmlComponent *delegate = nullptr; QQuickDeferredPointer<QQuickItem> indicator; QQuickDeferredPointer<QQuickPopup> popup; + bool m_acceptableInput = true; struct ExtraData { bool editable = false; @@ -476,6 +480,26 @@ void QQuickComboBoxPrivate::updateCurrentTextAndValue() updateCurrentValue(); } +void QQuickComboBoxPrivate::updateAcceptableInput() +{ + Q_Q(QQuickComboBox); + + if (!contentItem) + return; + + const QQuickTextInput *textInputContentItem = qobject_cast<QQuickTextInput *>(contentItem); + + if (!textInputContentItem) + return; + + const bool newValue = textInputContentItem->hasAcceptableInput(); + + if (m_acceptableInput != newValue) { + m_acceptableInput = newValue; + emit q->acceptableInputChanged(); + } +} + bool QQuickComboBoxPrivate::isValidIndex(int index) const { return delegateModel && index >= 0 && index < delegateModel->count(); @@ -770,6 +794,16 @@ void QQuickComboBoxPrivate::itemImplicitWidthChanged(QQuickItem *item) emit q->implicitIndicatorWidthChanged(); } +void QQuickComboBoxPrivate::setInputMethodHints(Qt::InputMethodHints hints, bool force) +{ + Q_Q(QQuickComboBox); + if (!force && hints == q->inputMethodHints()) + return; + + extra.value().inputMethodHints = hints; + emit q->inputMethodHintsChanged(); +} + void QQuickComboBoxPrivate::itemImplicitHeightChanged(QQuickItem *item) { Q_Q(QQuickComboBox); @@ -804,7 +838,8 @@ QQuickComboBox::QQuickComboBox(QQuickItem *parent) #if QT_CONFIG(cursor) setCursor(Qt::ArrowCursor); #endif - setInputMethodHints(Qt::ImhNoPredictiveText); + Q_D(QQuickComboBox); + d->setInputMethodHints(Qt::ImhNoPredictiveText, true); } QQuickComboBox::~QQuickComboBox() @@ -1437,11 +1472,7 @@ Qt::InputMethodHints QQuickComboBox::inputMethodHints() const void QQuickComboBox::setInputMethodHints(Qt::InputMethodHints hints) { Q_D(QQuickComboBox); - if (hints == inputMethodHints()) - return; - - d->extra.value().inputMethodHints = hints; - emit inputMethodHintsChanged(); + d->setInputMethodHints(hints); } /*! @@ -1476,7 +1507,7 @@ bool QQuickComboBox::isInputMethodComposing() const bool QQuickComboBox::hasAcceptableInput() const { Q_D(const QQuickComboBox); - return d->contentItem && d->contentItem->property("acceptableInput").toBool(); + return d->m_acceptableInput; } /*! @@ -1731,7 +1762,11 @@ void QQuickComboBox::focusInEvent(QFocusEvent *event) { Q_D(QQuickComboBox); QQuickControl::focusInEvent(event); - if (d->contentItem && isEditable()) + // Setting focus on TextField should not be done when drop down indicator was clicked + // That is why, if focus is not set with key reason, it should not be passed to textEdit by default. + // Focus on Edit Text should be set only intentionally by user. + if ((event->reason() == Qt::TabFocusReason || event->reason() == Qt::BacktabFocusReason || + event->reason() == Qt::ShortcutFocusReason) && d->contentItem && isEditable()) d->contentItem->forceActiveFocus(event->reason()); } @@ -1913,7 +1948,7 @@ void QQuickComboBox::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) QObjectPrivate::disconnect(oldInput, &QQuickTextInput::accepted, d, &QQuickComboBoxPrivate::acceptInput); QObjectPrivate::disconnect(oldInput, &QQuickTextInput::textChanged, d, &QQuickComboBoxPrivate::updateEditText); disconnect(oldInput, &QQuickTextInput::inputMethodComposingChanged, this, &QQuickComboBox::inputMethodComposingChanged); - disconnect(oldInput, &QQuickTextInput::acceptableInputChanged, this, &QQuickComboBox::acceptableInputChanged); + QObjectPrivate::disconnect(oldInput, &QQuickTextInput::acceptableInputChanged, d, &QQuickComboBoxPrivate::updateAcceptableInput); } } if (newItem && isEditable()) { @@ -1922,12 +1957,14 @@ void QQuickComboBox::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) QObjectPrivate::connect(newInput, &QQuickTextInput::accepted, d, &QQuickComboBoxPrivate::acceptInput); QObjectPrivate::connect(newInput, &QQuickTextInput::textChanged, d, &QQuickComboBoxPrivate::updateEditText); connect(newInput, &QQuickTextInput::inputMethodComposingChanged, this, &QQuickComboBox::inputMethodComposingChanged); - connect(newInput, &QQuickTextInput::acceptableInputChanged, this, &QQuickComboBox::acceptableInputChanged); + QObjectPrivate::connect(newInput, &QQuickTextInput::acceptableInputChanged, d, &QQuickComboBoxPrivate::updateAcceptableInput); } #if QT_CONFIG(cursor) newItem->setCursor(Qt::IBeamCursor); #endif } + + d->updateAcceptableInput(); } void QQuickComboBox::localeChange(const QLocale &newLocale, const QLocale &oldLocale) diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp index bbbd0e62..a719efd3 100644 --- a/src/quicktemplates2/qquickcontrol.cpp +++ b/src/quicktemplates2/qquickcontrol.cpp @@ -177,11 +177,19 @@ bool QQuickControlPrivate::acceptTouch(const QTouchEvent::TouchPoint &point) return true; } - // If the control is on a Flickable that has a pressDelay, then the press is never - // sent as a touch event, therefore we need to check for this case. - if (touchId == -1 && pressWasTouch && point.state() == Qt::TouchPointReleased && - point.pos() == previousPressPos) { - return true; + // If the control is on a Flickable that has a pressDelay, the press is sent + // as a mouse event rather than touch; so it detect and deal with it. + if (touchId == -1 && pressWasTouch) { + const auto delta = QVector2D(point.pos() - previousPressPos); + const bool overThreshold = QQuickWindowPrivate::dragOverThreshold(delta); + if (point.state() == Qt::TouchPointReleased && !overThreshold) { + // touchpoint was released near the press position: don't expect any more events, but just handle the release + return true; + } else if (point.state() == Qt::TouchPointMoved && overThreshold) { + // touchpoint was dragged over the drag threshold: accept it, and remember to handle all moves from now on + touchId = point.id(); + return true; + } } return false; } @@ -845,6 +853,13 @@ void QQuickControlPrivate::executeBackground(bool complete) quickCompleteDeferred(q, backgroundName(), background); } +/* + \internal + + Hides an item that was replaced by a newer one, rather than + deleting it, as the item is typically created in QML and hence + we don't own it. +*/ void QQuickControlPrivate::hideOldItem(QQuickItem *item) { if (!item) @@ -863,6 +878,29 @@ void QQuickControlPrivate::hideOldItem(QQuickItem *item) #endif } +/* + \internal + + Named "unhide" because it's used for cases where an item + that was previously hidden by \l hideOldItem() wants to be + shown by a control again, such as a ScrollBar in ScrollView. +*/ +void QQuickControlPrivate::unhideOldItem(QQuickControl *control, QQuickItem *item) +{ + Q_ASSERT(item); + qCDebug(lcItemManagement) << "unhiding old item" << item; + + item->setVisible(true); + item->setParentItem(control); + +#if QT_CONFIG(accessibility) + // Add the item back in to the accessibility tree. + QQuickAccessibleAttached *accessible = accessibleAttached(item); + if (accessible) + accessible->setIgnored(false); +#endif +} + void QQuickControlPrivate::updateBaselineOffset() { Q_Q(QQuickControl); diff --git a/src/quicktemplates2/qquickcontrol_p_p.h b/src/quicktemplates2/qquickcontrol_p_p.h index fa06c97f..a6e624c9 100644 --- a/src/quicktemplates2/qquickcontrol_p_p.h +++ b/src/quicktemplates2/qquickcontrol_p_p.h @@ -122,7 +122,7 @@ public: void setRightInset(qreal value, bool reset = false); void setBottomInset(qreal value, bool reset = false); - void resizeBackground(); + virtual void resizeBackground(); virtual void resizeContent(); virtual QQuickItem *getContentItem(); @@ -173,6 +173,7 @@ public: virtual void executeBackground(bool complete = false); static void hideOldItem(QQuickItem *item); + static void unhideOldItem(QQuickControl *control, QQuickItem *item); void updateBaselineOffset(); diff --git a/src/quicktemplates2/qquickdial.cpp b/src/quicktemplates2/qquickdial.cpp index b64d8d6e..906f952a 100644 --- a/src/quicktemplates2/qquickdial.cpp +++ b/src/quicktemplates2/qquickdial.cpp @@ -41,6 +41,8 @@ #include <QtQuick/private/qquickflickable_p.h> #include <QtQuickTemplates2/private/qquickcontrol_p_p.h> +#include <cmath> + QT_BEGIN_NAMESPACE /*! @@ -116,25 +118,37 @@ public: void cancelHandle(); void executeHandle(bool complete = false); + void updateAllValuesAreInteger(); + qreal from = 0; qreal to = 1; qreal value = 0; qreal position = 0; qreal angle = startAngle; qreal stepSize = 0; - bool pressed = false; QPointF pressPoint; qreal positionBeforePress = 0; QQuickDial::SnapMode snapMode = QQuickDial::NoSnap; QQuickDial::InputMode inputMode = QQuickDial::Circular; + QQuickDeferredPointer<QQuickItem> handle; bool wrap = false; bool live = true; - QQuickDeferredPointer<QQuickItem> handle; + bool pressed = false; + bool allValuesAreInteger = false; }; qreal QQuickDialPrivate::valueAt(qreal position) const { - return from + (to - from) * position; + qreal value = from + (to - from) * position; + + /* play nice with users expecting that integer from, to and stepSize leads to + integer values - given that we are using floating point internally (and in + the API of value), this does not hold, but it is easy enough to handle + */ + if (allValuesAreInteger) + value = qRound(value); + + return value; } qreal QQuickDialPrivate::snapPosition(qreal position) const @@ -308,6 +322,16 @@ void QQuickDialPrivate::executeHandle(bool complete) quickCompleteDeferred(q, handleName(), handle); } +static bool areRepresentableAsInteger(qreal num1, qreal num2, qreal num3) { + auto check = [](qreal number) -> bool { return std::nearbyint(number) == number; }; + return check(num1) && check(num2) && check(num3); +} + +void QQuickDialPrivate::updateAllValuesAreInteger() +{ + allValuesAreInteger = areRepresentableAsInteger(to, from, stepSize) && stepSize != 0.0; +} + QQuickDial::QQuickDial(QQuickItem *parent) : QQuickControl(*(new QQuickDialPrivate), parent) { @@ -342,6 +366,7 @@ void QQuickDial::setFrom(qreal from) d->from = from; emit fromChanged(); + d->updateAllValuesAreInteger(); if (isComponentComplete()) { setValue(d->value); d->updatePosition(); @@ -369,6 +394,7 @@ void QQuickDial::setTo(qreal to) return; d->to = to; + d->updateAllValuesAreInteger(); emit toChanged(); if (isComponentComplete()) { setValue(d->value); @@ -468,6 +494,7 @@ void QQuickDial::setStepSize(qreal step) return; d->stepSize = step; + d->updateAllValuesAreInteger(); emit stepSizeChanged(); } diff --git a/src/quicktemplates2/qquickmenu.cpp b/src/quicktemplates2/qquickmenu.cpp index 9fd63587..0043dddd 100644 --- a/src/quicktemplates2/qquickmenu.cpp +++ b/src/quicktemplates2/qquickmenu.cpp @@ -295,8 +295,8 @@ QQuickItem *QQuickMenuPrivate::beginCreateItem() QQuickItem *item = qobject_cast<QQuickItem *>(object); if (!item) delete object; - - QQml_setParent_noEvent(item, q); + else + QQml_setParent_noEvent(item, q); return item; } diff --git a/src/quicktemplates2/qquickoverlay.cpp b/src/quicktemplates2/qquickoverlay.cpp index b8d417f2..91bd5918 100644 --- a/src/quicktemplates2/qquickoverlay.cpp +++ b/src/quicktemplates2/qquickoverlay.cpp @@ -471,22 +471,27 @@ bool QQuickOverlay::childMouseEventFilter(QQuickItem *item, QEvent *event) // background dimming OR over another popup underneath, in case the popup // does not have background dimming. if (item == p->dimmer || !p->popupItem->isAncestorOf(item)) { + bool handled = false; switch (event->type()) { #if QT_CONFIG(quicktemplates2_multitouch) case QEvent::TouchBegin: case QEvent::TouchUpdate: case QEvent::TouchEnd: - return d->handleTouchEvent(item, static_cast<QTouchEvent *>(event), popup); + handled = d->handleTouchEvent(item, static_cast<QTouchEvent *>(event), popup); + break; #endif case QEvent::MouseButtonPress: case QEvent::MouseMove: case QEvent::MouseButtonRelease: - return d->handleMouseEvent(item, static_cast<QMouseEvent *>(event), popup); + handled = d->handleMouseEvent(item, static_cast<QMouseEvent *>(event), popup); + break; default: break; } + if (handled) + return true; } } return false; diff --git a/src/quicktemplates2/qquickpage.cpp b/src/quicktemplates2/qquickpage.cpp index 0a72bad7..bc27740b 100644 --- a/src/quicktemplates2/qquickpage.cpp +++ b/src/quicktemplates2/qquickpage.cpp @@ -244,6 +244,9 @@ QQuickPage::~QQuickPage() The title is often displayed at the top of a page to give the user context about the page they are viewing. + Page does not render the title itself, but instead relies + on the application to do so. For example: + \code ApplicationWindow { visible: true diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index 7130d2ea..7df80a04 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -51,6 +51,8 @@ QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcDimmer, "qt.quick.controls.popup.dimmer") + /*! \qmltype Popup \inherits QtObject @@ -215,6 +217,19 @@ QT_BEGIN_NAMESPACE To ensure that the popup is positioned within the bounds of the enclosing window, the \l margins property can be set to a non-negative value. + \section1 Popup Transitions + + Since Qt 5.15.3 the following properties are restored to their original values from before + the enter transition after the exit transition is completed. + + \list + \li \l opacity + \li \l scale + \endlist + + This allows the built-in styles to animate on these properties without losing any explicitly + defined value. + \sa {Popup Controls}, {Customizing Popup}, ApplicationWindow */ @@ -441,6 +456,9 @@ bool QQuickPopupPrivate::prepareEnterTransition() popupItem->setVisible(true); getPositioner()->setParentItem(parentItem); emit q->visibleChanged(); + + if (focus) + popupItem->setFocus(true); } return true; } @@ -451,6 +469,11 @@ bool QQuickPopupPrivate::prepareExitTransition() if (transitionState == ExitTransition && transitionManager.isRunning()) return false; + // We need to cache the original scale and opacity values so we can reset it after + // the exit transition is done so they have the original values again + prevScale = popupItem->scale(); + prevOpacity = popupItem->opacity(); + if (transitionState != ExitTransition) { // The setFocus(false) call below removes any active focus before we're // able to check it in finalizeExitTransition. @@ -469,8 +492,6 @@ bool QQuickPopupPrivate::prepareExitTransition() void QQuickPopupPrivate::finalizeEnterTransition() { Q_Q(QQuickPopup); - if (focus) - popupItem->setFocus(true); transitionState = NoTransition; getPositioner()->reposition(); emit q->openedChanged(); @@ -481,8 +502,10 @@ void QQuickPopupPrivate::finalizeExitTransition() { Q_Q(QQuickPopup); getPositioner()->setParentItem(nullptr); - popupItem->setParentItem(nullptr); - popupItem->setVisible(false); + if (popupItem) { + popupItem->setParentItem(nullptr); + popupItem->setVisible(false); + } destroyOverlay(); if (hadActiveFocusBeforeExitTransition && window) { @@ -491,13 +514,14 @@ void QQuickPopupPrivate::finalizeExitTransition() if (QQuickOverlay *overlay = QQuickOverlay::overlay(window)) { const auto stackingOrderPopups = QQuickOverlayPrivate::get(overlay)->stackingOrderPopups(); for (auto popup : stackingOrderPopups) { - if (QQuickPopupPrivate::get(popup)->transitionState != ExitTransition) { + if (QQuickPopupPrivate::get(popup)->transitionState != ExitTransition + && popup->hasFocus()) { nextFocusPopup = popup; break; } } } - if (nextFocusPopup && nextFocusPopup->hasFocus()) { + if (nextFocusPopup) { nextFocusPopup->forceActiveFocus(); } else { QQuickApplicationWindow *applicationWindow = qobject_cast<QQuickApplicationWindow*>(window); @@ -513,6 +537,10 @@ void QQuickPopupPrivate::finalizeExitTransition() hadActiveFocusBeforeExitTransition = false; emit q->visibleChanged(); emit q->closed(); + if (popupItem) { + popupItem->setScale(prevScale); + popupItem->setOpacity(prevOpacity); + } } QMarginsF QQuickPopupPrivate::getMargins() const @@ -702,6 +730,8 @@ static QQuickItem *createDimmer(QQmlComponent *component, QQuickPopup *popup, QQ if (component) component->completeCreate(); } + qCDebug(lcDimmer) << "finished creating dimmer from component" << component + << "for popup" << popup << "with parent" << parent << "- item is:" << item; return item; } @@ -728,6 +758,7 @@ void QQuickPopupPrivate::createOverlay() void QQuickPopupPrivate::destroyOverlay() { if (dimmer) { + qCDebug(lcDimmer) << "destroying dimmer" << dimmer; dimmer->setParentItem(nullptr); dimmer->deleteLater(); dimmer = nullptr; @@ -826,6 +857,12 @@ QQuickPopup::~QQuickPopup() d->popupItem = nullptr; delete d->positioner; d->positioner = nullptr; + + // If the popup is destroyed before the exit transition finishes, + // the necessary cleanup (removing modal dimmers that block mouse events, + // emitting closed signal, etc.) won't happen. That's why we do it manually here. + if (d->transitionState == QQuickPopupPrivate::ExitTransition && d->transitionManager.isRunning()) + d->finalizeExitTransition(); } /*! diff --git a/src/quicktemplates2/qquickpopup_p_p.h b/src/quicktemplates2/qquickpopup_p_p.h index 8a85f914..ef4b112e 100644 --- a/src/quicktemplates2/qquickpopup_p_p.h +++ b/src/quicktemplates2/qquickpopup_p_p.h @@ -196,6 +196,8 @@ public: QList<QQuickStateAction> exitActions; QQuickPopupTransitionManager transitionManager; QQuickPopupAnchors *anchors = nullptr; + qreal prevOpacity = 0; + qreal prevScale = 0; friend class QQuickPopupTransitionManager; }; diff --git a/src/quicktemplates2/qquickrangeslider.cpp b/src/quicktemplates2/qquickrangeslider.cpp index eb9c1bb1..f1e5c805 100644 --- a/src/quicktemplates2/qquickrangeslider.cpp +++ b/src/quicktemplates2/qquickrangeslider.cpp @@ -665,6 +665,10 @@ void QQuickRangeSlider::setFrom(qreal from) if (isComponentComplete()) { d->first->setValue(d->first->value()); d->second->setValue(d->second->value()); + auto *firstPrivate = QQuickRangeSliderNodePrivate::get(d->first); + auto *secondPrivate = QQuickRangeSliderNodePrivate::get(d->second); + firstPrivate->updatePosition(true); + secondPrivate->updatePosition(); } } @@ -693,6 +697,10 @@ void QQuickRangeSlider::setTo(qreal to) if (isComponentComplete()) { d->first->setValue(d->first->value()); d->second->setValue(d->second->value()); + auto *firstPrivate = QQuickRangeSliderNodePrivate::get(d->first); + auto *secondPrivate = QQuickRangeSliderNodePrivate::get(d->second); + firstPrivate->updatePosition(true); + secondPrivate->updatePosition(); } } diff --git a/src/quicktemplates2/qquickscrollbar.cpp b/src/quicktemplates2/qquickscrollbar.cpp index 4733d665..f0783708 100644 --- a/src/quicktemplates2/qquickscrollbar.cpp +++ b/src/quicktemplates2/qquickscrollbar.cpp @@ -77,7 +77,7 @@ QT_BEGIN_NAMESPACE \list \li \l orientation \li \l position - \li \l size + \li \l {ScrollBar::} {size} \li \l active \endlist @@ -797,6 +797,14 @@ void QQuickScrollBarAttachedPrivate::initHorizontal() if (parent && parent == flickable->parentItem()) horizontal->stackAfter(flickable); + // If a scroll bar was previously hidden (due to e.g. setting a new contentItem + // on a ScrollView), we need to make sure that we un-hide it. + // We don't bother checking if the item is actually the old one, because + // if it's not, all of the things the function does (setting parent, visibility, etc.) + // should be no-ops anyway. + if (auto control = qobject_cast<QQuickControl*>(q_func()->parent())) + QQuickControlPrivate::unhideOldItem(control, horizontal); + layoutHorizontal(); horizontal->setSize(area->property("widthRatio").toReal()); horizontal->setPosition(area->property("xPosition").toReal()); @@ -818,6 +826,9 @@ void QQuickScrollBarAttachedPrivate::initVertical() if (parent && parent == flickable->parentItem()) vertical->stackAfter(flickable); + if (auto control = qobject_cast<QQuickControl*>(q_func()->parent())) + QQuickControlPrivate::unhideOldItem(control, vertical); + layoutVertical(); vertical->setSize(area->property("heightRatio").toReal()); vertical->setPosition(area->property("yPosition").toReal()); @@ -827,6 +838,16 @@ void QQuickScrollBarAttachedPrivate::cleanupHorizontal() { Q_ASSERT(flickable && horizontal); + QQuickControlPrivate::hideOldItem(horizontal); + // ScrollBar.qml has a binding to visible and ScrollView.qml has a binding to parent. + // If we just set visible to false and parent to null, these bindings will overwrite + // them upon component completion as part of the binding evaluation. + // That's why we remove the binding completely. + const QQmlProperty visibleProperty(horizontal, QStringLiteral("visible")); + const QQmlProperty parentProperty(horizontal, QStringLiteral("parent")); + QQmlPropertyPrivate::removeBinding(visibleProperty); + QQmlPropertyPrivate::removeBinding(parentProperty); + disconnect(flickable, &QQuickFlickable::movingHorizontallyChanged, this, &QQuickScrollBarAttachedPrivate::activateHorizontal); // TODO: export QQuickFlickableVisibleArea @@ -839,6 +860,12 @@ void QQuickScrollBarAttachedPrivate::cleanupVertical() { Q_ASSERT(flickable && vertical); + QQuickControlPrivate::hideOldItem(vertical); + const QQmlProperty visibleProperty(vertical, QStringLiteral("visible")); + const QQmlProperty parentProperty(vertical, QStringLiteral("parent")); + QQmlPropertyPrivate::removeBinding(visibleProperty); + QQmlPropertyPrivate::removeBinding(parentProperty); + disconnect(flickable, &QQuickFlickable::movingVerticallyChanged, this, &QQuickScrollBarAttachedPrivate::activateVertical); // TODO: export QQuickFlickableVisibleArea @@ -869,6 +896,9 @@ class QQuickFriendlyFlickable : public QQuickFlickable void QQuickScrollBarAttachedPrivate::scrollHorizontal() { + if (!flickable) + return; + QQuickFriendlyFlickable *f = reinterpret_cast<QQuickFriendlyFlickable *>(flickable); const qreal viewwidth = f->width(); @@ -881,6 +911,9 @@ void QQuickScrollBarAttachedPrivate::scrollHorizontal() void QQuickScrollBarAttachedPrivate::scrollVertical() { + if (!flickable) + return; + QQuickFriendlyFlickable *f = reinterpret_cast<QQuickFriendlyFlickable *>(flickable); const qreal viewheight = f->height(); diff --git a/src/quicktemplates2/qquickscrollbar_p_p.h b/src/quicktemplates2/qquickscrollbar_p_p.h index 5c7628b9..c58c2ed1 100644 --- a/src/quicktemplates2/qquickscrollbar_p_p.h +++ b/src/quicktemplates2/qquickscrollbar_p_p.h @@ -107,6 +107,8 @@ public: class QQuickScrollBarAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener { + Q_DECLARE_PUBLIC(QQuickScrollBar) + public: static QQuickScrollBarAttachedPrivate *get(QQuickScrollBarAttached *attached) { diff --git a/src/quicktemplates2/qquickscrollview.cpp b/src/quicktemplates2/qquickscrollview.cpp index f385778d..01e19b16 100644 --- a/src/quicktemplates2/qquickscrollview.cpp +++ b/src/quicktemplates2/qquickscrollview.cpp @@ -38,6 +38,7 @@ #include "qquickpane_p_p.h" #include "qquickscrollbar_p_p.h" +#include <QtQml/qqmlinfo.h> #include <QtQuick/private/qquickflickable_p.h> QT_BEGIN_NAMESPACE @@ -575,7 +576,10 @@ void QQuickScrollView::contentItemChange(QQuickItem *newItem, QQuickItem *oldIte // assume/require that it has an explicit content size assigned. d->flickableHasExplicitContentWidth = true; d->flickableHasExplicitContentHeight = true; - d->setFlickable(qobject_cast<QQuickFlickable *>(newItem), false); + auto newItemAsFlickable = qobject_cast<QQuickFlickable *>(newItem); + if (newItem && !newItemAsFlickable) + qmlWarning(this) << "ScrollView only supports Flickable types as its contentItem"; + d->setFlickable(newItemAsFlickable, false); } QQuickPane::contentItemChange(newItem, oldItem); } diff --git a/src/quicktemplates2/qquickswipedelegate.cpp b/src/quicktemplates2/qquickswipedelegate.cpp index 018768a2..629bf23d 100644 --- a/src/quicktemplates2/qquickswipedelegate.cpp +++ b/src/quicktemplates2/qquickswipedelegate.cpp @@ -713,6 +713,29 @@ QQuickSwipeDelegatePrivate::QQuickSwipeDelegatePrivate(QQuickSwipeDelegate *cont { } +void QQuickSwipeDelegatePrivate::resizeBackground() +{ + if (!background) + return; + + resizingBackground = true; + + QQuickItemPrivate *p = QQuickItemPrivate::get(background); + const bool extraAllocated = extra.isAllocated(); + // Don't check for or set the x here since it will just be overwritten by reposition(). + if (((!p->widthValid || !extraAllocated || !extra->hasBackgroundWidth)) + || (extraAllocated && (extra->hasLeftInset || extra->hasRightInset))) { + background->setWidth(width - getLeftInset() - getRightInset()); + } + if (((!p->heightValid || !extraAllocated || !extra->hasBackgroundHeight) && qFuzzyIsNull(background->y())) + || (extraAllocated && (extra->hasTopInset || extra->hasBottomInset))) { + background->setY(getTopInset()); + background->setHeight(height - getTopInset() - getBottomInset()); + } + + resizingBackground = false; +} + bool QQuickSwipeDelegatePrivate::handleMousePressEvent(QQuickItem *item, QMouseEvent *event) { Q_Q(QQuickSwipeDelegate); @@ -778,9 +801,10 @@ bool QQuickSwipeDelegatePrivate::handleMouseMoveEvent(QQuickItem *item, QMouseEv const QPointF mappedEventPos = item->mapToItem(q, event->pos()); const qreal distance = (mappedEventPos - pressPoint).x(); if (!q->keepMouseGrab()) { - // Taken from QQuickDrawerPrivate::grabMouse; see comments there. - int threshold = qMax(20, QGuiApplication::styleHints()->startDragDistance() + 5); - const bool overThreshold = QQuickWindowPrivate::dragOverThreshold(distance, Qt::XAxis, event, threshold); + // We used to use the custom threshold that QQuickDrawerPrivate::grabMouse used, + // but since it's larger than what Flickable uses, it results in Flickable + // stealing events from us (QTBUG-50045), so now we use the default. + const bool overThreshold = QQuickWindowPrivate::dragOverThreshold(distance, Qt::XAxis, event); if (window && overThreshold) { QQuickItem *grabber = q->window()->mouseGrabberItem(); if (!grabber || !grabber->keepMouseGrab()) { @@ -935,13 +959,15 @@ void QQuickSwipeDelegatePrivate::resizeContent() // If the background and contentItem are repositioned due to a swipe, // we don't want to call QQuickControlPrivate's implementation of this function, // as it repositions the contentItem to be visible. - // However, we still want to resize the control vertically. + // However, we still want to position the contentItem vertically + // and resize it (in case the control was resized while open). QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&swipe); if (!swipePrivate->complete) { QQuickItemDelegatePrivate::resizeContent(); } else if (contentItem) { Q_Q(QQuickSwipeDelegate); contentItem->setY(q->topPadding()); + contentItem->setWidth(q->availableWidth()); contentItem->setHeight(q->availableHeight()); } } diff --git a/src/quicktemplates2/qquickswipedelegate_p_p.h b/src/quicktemplates2/qquickswipedelegate_p_p.h index 78c72ec8..95a999a0 100644 --- a/src/quicktemplates2/qquickswipedelegate_p_p.h +++ b/src/quicktemplates2/qquickswipedelegate_p_p.h @@ -67,6 +67,7 @@ public: bool handleMouseReleaseEvent(QQuickItem *item, QMouseEvent *event); void resizeContent() override; + void resizeBackground() override; QQuickSwipe swipe; }; diff --git a/src/quicktemplates2/qquickswipeview.cpp b/src/quicktemplates2/qquickswipeview.cpp index dab20b93..98d4d22b 100644 --- a/src/quicktemplates2/qquickswipeview.cpp +++ b/src/quicktemplates2/qquickswipeview.cpp @@ -310,7 +310,6 @@ void QQuickSwipeView::geometryChanged(const QRectF &newGeometry, const QRectF &o void QQuickSwipeView::itemAdded(int index, QQuickItem *item) { Q_D(QQuickSwipeView); - QQuickItemPrivate::get(item)->setCulled(true); // QTBUG-51078, QTBUG-51669 if (isComponentComplete()) item->setSize(QSizeF(d->contentItem->width(), d->contentItem->height())); QQuickSwipeViewAttached *attached = qobject_cast<QQuickSwipeViewAttached *>(qmlAttachedPropertiesObject<QQuickSwipeView>(item)); diff --git a/src/quicktemplates2/qquicktextarea.cpp b/src/quicktemplates2/qquicktextarea.cpp index d0a08c47..64fc631d 100644 --- a/src/quicktemplates2/qquicktextarea.cpp +++ b/src/quicktemplates2/qquicktextarea.cpp @@ -358,6 +358,7 @@ void QQuickTextAreaPrivate::attachFlickable(QQuickFlickable *item) QObject::connect(flickable, &QQuickFlickable::contentYChanged, q, &QQuickItem::update); QQuickItemPrivate::get(flickable)->updateOrAddGeometryChangeListener(this, QQuickGeometryChange::Size); + QQuickItemPrivate::get(flickable)->addItemChangeListener(this, QQuickItemPrivate::Destroyed); QObjectPrivate::connect(flickable, &QQuickFlickable::contentWidthChanged, this, &QQuickTextAreaPrivate::resizeFlickableControl); QObjectPrivate::connect(flickable, &QQuickFlickable::contentHeightChanged, this, &QQuickTextAreaPrivate::resizeFlickableControl); @@ -378,6 +379,7 @@ void QQuickTextAreaPrivate::detachFlickable() QObject::disconnect(flickable, &QQuickFlickable::contentYChanged, q, &QQuickItem::update); QQuickItemPrivate::get(flickable)->updateOrRemoveGeometryChangeListener(this, QQuickGeometryChange::Nothing); + QQuickItemPrivate::get(flickable)->removeItemChangeListener(this, QQuickItemPrivate::Destroyed); QObjectPrivate::disconnect(flickable, &QQuickFlickable::contentWidthChanged, this, &QQuickTextAreaPrivate::resizeFlickableControl); QObjectPrivate::disconnect(flickable, &QQuickFlickable::contentHeightChanged, this, &QQuickTextAreaPrivate::resizeFlickableControl); @@ -562,6 +564,8 @@ void QQuickTextAreaPrivate::itemDestroyed(QQuickItem *item) background = nullptr; emit q->implicitBackgroundWidthChanged(); emit q->implicitBackgroundHeightChanged(); + } else if (item == flickable) { + detachFlickable(); } } @@ -1082,7 +1086,11 @@ QSGNode *QQuickTextArea::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * if (d->flickable) clipper = d->flickable; - const QRectF cr = clipper->clipRect().adjusted(leftPadding(), topPadding(), -rightPadding(), -bottomPadding()); + const QRectF cr = clipper->clipRect().adjusted( + leftPadding(), topPadding(), + (!d->cursorItem && effectiveHAlign() == HAlignment::AlignRight ? 1 : 0) - rightPadding(), + -bottomPadding()); + clipNode->setRect(!d->flickable ? cr : cr.translated(d->flickable->contentX(), d->flickable->contentY())); clipNode->update(); diff --git a/src/quicktemplates2/qquicktumbler.cpp b/src/quicktemplates2/qquicktumbler.cpp index c1d1c00f..35ed9680 100644 --- a/src/quicktemplates2/qquicktumbler.cpp +++ b/src/quicktemplates2/qquicktumbler.cpp @@ -662,8 +662,9 @@ void QQuickTumblerPrivate::syncCurrentIndex() return; } - // PathView likes to use 0 as currentIndex for empty models, but we use -1 for that. - if (q->count() == 0 && actualViewIndex == 0) + // actualViewIndex might be 0 or -1 for PathView and ListView respectively, + // but we always use -1 for that. + if (q->count() == 0 && actualViewIndex <= 0) return; ignoreCurrentIndexChanges = true; diff --git a/src/quicktemplates2/qtquicktemplates2global.cpp b/src/quicktemplates2/qtquicktemplates2global.cpp new file mode 100644 index 00000000..5d7816b4 --- /dev/null +++ b/src/quicktemplates2/qtquicktemplates2global.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qquickpage_p.h" +#include "accessible/qaccessiblequickpage_p.h" + +QT_BEGIN_NAMESPACE + +#if QT_CONFIG(accessibility) +static QAccessibleInterface *qQuickAccessibleFactory(const QString &classname, QObject *object) +{ + if (classname == u"QQuickPage") { + return new QAccessibleQuickPage(qobject_cast<QQuickPage *>(object)); + } + return nullptr; +} +#endif + +void QQuickTemplates_initializeModule() +{ +#if QT_CONFIG(accessibility) + QAccessible::installFactory(&qQuickAccessibleFactory); +#endif +} + +Q_CONSTRUCTOR_FUNCTION(QQuickTemplates_initializeModule) + +QT_END_NAMESPACE diff --git a/src/quicktemplates2/qtquicktemplates2global_p.h b/src/quicktemplates2/qtquicktemplates2global_p.h index e5ee3f2e..9b6610dd 100644 --- a/src/quicktemplates2/qtquicktemplates2global_p.h +++ b/src/quicktemplates2/qtquicktemplates2global_p.h @@ -64,6 +64,8 @@ QT_BEGIN_NAMESPACE # define Q_QUICKTEMPLATES2_PRIVATE_EXPORT #endif +Q_QUICKTEMPLATES2_PRIVATE_EXPORT void QQuickTemplates_initializeModule(); + QT_END_NAMESPACE #endif // QTQUICKTEMPLATES2GLOBAL_P_H diff --git a/src/quicktemplates2/quicktemplates2.pro b/src/quicktemplates2/quicktemplates2.pro index 8ed0151a..a3f778b2 100644 --- a/src/quicktemplates2/quicktemplates2.pro +++ b/src/quicktemplates2/quicktemplates2.pro @@ -10,5 +10,11 @@ DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII HEADERS += \ $$PWD/qtquicktemplates2global_p.h +SOURCES += \ + $$PWD/qtquicktemplates2global.cpp + include(quicktemplates2.pri) +qtConfig(accessibility) { + include(accessible/accessible.pri) +} load(qt_module) |