diff options
author | Mitch Curtis <[email protected]> | 2021-08-12 14:39:51 +0200 |
---|---|---|
committer | Mitch Curtis <[email protected]> | 2021-08-16 12:52:59 +0200 |
commit | 809339d1484cf556512534367b8170bc26baf072 (patch) | |
tree | 12871313b658f36d058b5ef25af1e247e9c46ce9 /src/quicktemplates2/qquickswipedelegate.cpp | |
parent | b01b4f00eae8022c6a97d90f54dac395144ae095 (diff) |
Now that qtquickcontrols2 has been merged into qtdeclarative,
we should make it obvious that this repo should no longer be
used, by preventing it from being built.
Task-number: QTBUG-95173
Pick-to: 6.2
Change-Id: I95bd6a214f3d75a865ab163ee0a1f9ffbeb7a051
Reviewed-by: Alexandru Croitor <[email protected]>
Reviewed-by: Volker Hilsheimer <[email protected]>
Diffstat (limited to 'src/quicktemplates2/qquickswipedelegate.cpp')
-rw-r--r-- | src/quicktemplates2/qquickswipedelegate.cpp | 1527 |
1 files changed, 0 insertions, 1527 deletions
diff --git a/src/quicktemplates2/qquickswipedelegate.cpp b/src/quicktemplates2/qquickswipedelegate.cpp deleted file mode 100644 index 817704ba..00000000 --- a/src/quicktemplates2/qquickswipedelegate.cpp +++ /dev/null @@ -1,1527 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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 "qquickswipedelegate_p.h" -#include "qquickswipedelegate_p_p.h" -#include "qquickcontrol_p_p.h" -#include "qquickitemdelegate_p_p.h" -#include "qquickvelocitycalculator_p_p.h" - -#include <QtGui/qstylehints.h> -#include <QtGui/private/qguiapplication_p.h> -#include <QtGui/qpa/qplatformtheme.h> -#include <QtQml/qqmlinfo.h> -#include <QtQuick/private/qquickanimation_p.h> -#include <QtQuick/private/qquicktransition_p.h> -#include <QtQuick/private/qquicktransitionmanager_p_p.h> - -QT_BEGIN_NAMESPACE - -/*! - \qmltype SwipeDelegate - \inherits ItemDelegate -//! \instantiates QQuickSwipeDelegate - \inqmlmodule QtQuick.Controls - \since 5.7 - \ingroup qtquickcontrols2-delegates - \brief Swipable item delegate. - - SwipeDelegate presents a view item that can be swiped left or right to - expose more options or information. It is used as a delegate in views such - as \l ListView. - - In the following example, SwipeDelegate is used in a \l ListView to allow - items to be removed from it by swiping to the left: - - \snippet qtquickcontrols2-swipedelegate.qml 1 - - SwipeDelegate inherits its API from \l ItemDelegate, which is inherited - from AbstractButton. For instance, you can set \l {AbstractButton::text}{text}, - and react to \l {AbstractButton::clicked}{clicks} using the AbstractButton - API. - - Information regarding the progress of a swipe, as well as the components - that should be shown upon swiping, are both available through the - \l {SwipeDelegate::}{swipe} grouped property object. For example, - \c swipe.position holds the position of the - swipe within the range \c -1.0 to \c 1.0. The \c swipe.left - property determines which item will be displayed when the control is swiped - to the right, and vice versa for \c swipe.right. The positioning of these - components is left to applications to decide. For example, without specifying - any position for \c swipe.left or \c swipe.right, the following will - occur: - - \image qtquickcontrols2-swipedelegate.gif - - If \c swipe.left and \c swipe.right are anchored to the left and - right of the \l {Control::}{background} item (respectively), they'll behave like this: - - \image qtquickcontrols2-swipedelegate-leading-trailing.gif - - When using \c swipe.left and \c swipe.right, the control cannot be - swiped past the left and right edges. To achieve this type of "wrapping" - behavior, set \c swipe.behind instead. This will result in the same - item being shown regardless of which direction the control is swiped. For - example, in the image below, we set \c swipe.behind and then swipe the - control repeatedly in both directions: - - \image qtquickcontrols2-swipedelegate-behind.gif - - \sa {Customizing SwipeDelegate}, {Delegate Controls}, {Qt Quick Controls 2 - Swipe to Remove}{Swipe to Remove Example} -*/ - -namespace { - typedef QQuickSwipeDelegateAttached Attached; - - Attached *attachedObject(QQuickItem *item) { - return qobject_cast<Attached*>(qmlAttachedPropertiesObject<QQuickSwipeDelegate>(item, false)); - } - - enum PositionAnimation { - DontAnimatePosition, - AnimatePosition - }; -} - -class QQuickSwipeTransitionManager : public QQuickTransitionManager -{ -public: - QQuickSwipeTransitionManager(QQuickSwipe *swipe); - - void transition(QQuickTransition *transition, qreal position); - -protected: - void finished() override; - -private: - QQuickSwipe *m_swipe = nullptr; -}; - -class QQuickSwipePrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QQuickSwipe) - -public: - QQuickSwipePrivate(QQuickSwipeDelegate *control) : control(control) { } - - static QQuickSwipePrivate *get(QQuickSwipe *swipe); - - QQuickItem *createDelegateItem(QQmlComponent *component); - QQuickItem *showRelevantItemForPosition(qreal position); - QQuickItem *createRelevantItemForDistance(qreal distance); - void reposition(PositionAnimation animationPolicy); - void createLeftItem(); - void createBehindItem(); - void createRightItem(); - void createAndShowLeftItem(); - void createAndShowBehindItem(); - void createAndShowRightItem(); - - void warnAboutMixingDelegates(); - void warnAboutSettingDelegatesWhileVisible(); - - bool hasDelegates() const; - - bool isTransitioning() const; - void beginTransition(qreal position); - void finishTransition(); - - QQuickSwipeDelegate *control = nullptr; - // Same range as position, but is set before press events so that we can - // keep track of which direction the user must swipe when using left and right delegates. - qreal positionBeforePress = 0; - qreal position = 0; - // A "less strict" version of complete that is true if complete was true - // before the last press event. - bool wasComplete = false; - bool complete = false; - bool enabled = true; - bool waitForTransition = false; - QQuickVelocityCalculator velocityCalculator; - QQmlComponent *left = nullptr; - QQmlComponent *behind = nullptr; - QQmlComponent *right = nullptr; - QQuickItem *leftItem = nullptr; - QQuickItem *behindItem = nullptr; - QQuickItem *rightItem = nullptr; - QQuickTransition *transition = nullptr; - QScopedPointer<QQuickSwipeTransitionManager> transitionManager; -}; - -QQuickSwipeTransitionManager::QQuickSwipeTransitionManager(QQuickSwipe *swipe) - : m_swipe(swipe) -{ -} - -void QQuickSwipeTransitionManager::transition(QQuickTransition *transition, qreal position) -{ - qmlExecuteDeferred(transition); - - QQmlProperty defaultTarget(m_swipe, QLatin1String("position")); - QQmlListProperty<QQuickAbstractAnimation> animations = transition->animations(); - const int count = animations.count(&animations); - for (int i = 0; i < count; ++i) { - QQuickAbstractAnimation *anim = animations.at(&animations, i); - anim->setDefaultTarget(defaultTarget); - } - - QList<QQuickStateAction> actions; - actions << QQuickStateAction(m_swipe, QLatin1String("position"), position); - QQuickTransitionManager::transition(actions, transition, m_swipe); -} - -void QQuickSwipeTransitionManager::finished() -{ - QQuickSwipePrivate::get(m_swipe)->finishTransition(); -} - -QQuickSwipePrivate *QQuickSwipePrivate::get(QQuickSwipe *swipe) -{ - return swipe->d_func(); -} - -QQuickItem *QQuickSwipePrivate::createDelegateItem(QQmlComponent *component) -{ - // If we don't use the correct context, it won't be possible to refer to - // the control's id from within the delegates. - QQmlContext *creationContext = component->creationContext(); - // The component might not have been created in QML, in which case - // the creation context will be null and we have to create it ourselves. - if (!creationContext) - creationContext = qmlContext(control); - QQmlContext *context = new QQmlContext(creationContext, control); - context->setContextObject(control); - QQuickItem *item = qobject_cast<QQuickItem*>(component->beginCreate(context)); - if (item) { - item->setParentItem(control); - component->completeCreate(); - } - return item; -} - -QQuickItem *QQuickSwipePrivate::showRelevantItemForPosition(qreal position) -{ - if (qFuzzyIsNull(position)) - return nullptr; - - if (behind) { - createAndShowBehindItem(); - return behindItem; - } - - if (right && position < 0.0) { - createAndShowRightItem(); - return rightItem; - } - - if (left && position > 0.0) { - createAndShowLeftItem(); - return leftItem; - } - - return nullptr; -} - -QQuickItem *QQuickSwipePrivate::createRelevantItemForDistance(qreal distance) -{ - if (qFuzzyIsNull(distance)) - return nullptr; - - if (behind) { - createBehindItem(); - return behindItem; - } - - // a) If the position before the press was 0.0, we know that *any* movement - // whose distance is negative will result in the right item being shown and - // vice versa. - // b) Once the control has been exposed (that is, swiped to the left or right, - // and hence the position is either -1.0 or 1.0), we must use the width of the - // relevant item to determine if the distance is larger than that item, - // in order to know whether or not to display it. - // c) If the control has been exposed, and the swipe is larger than the width - // of the relevant item from which the swipe started from, we must show the - // item on the other side (if any). - - if (right) { - if ((distance < 0.0 && positionBeforePress == 0.0) /* a) */ - || (rightItem && positionBeforePress == -1.0 && distance < rightItem->width()) /* b) */ - || (leftItem && positionBeforePress == 1.0 && qAbs(distance) > leftItem->width())) /* c) */ { - createRightItem(); - return rightItem; - } - } - - if (left) { - if ((distance > 0.0 && positionBeforePress == 0.0) /* a) */ - || (leftItem && positionBeforePress == 1.0 && qAbs(distance) < leftItem->width()) /* b) */ - || (rightItem && positionBeforePress == -1.0 && qAbs(distance) > rightItem->width())) /* c) */ { - createLeftItem(); - return leftItem; - } - } - - return nullptr; -} - -void QQuickSwipePrivate::reposition(PositionAnimation animationPolicy) -{ - QQuickItem *relevantItem = showRelevantItemForPosition(position); - const qreal relevantWidth = relevantItem ? relevantItem->width() : 0.0; - const qreal contentItemX = position * relevantWidth + control->leftPadding(); - - // "Behavior on x" relies on the property system to know when it should update, - // so we can prevent it from animating by setting the x position directly. - if (animationPolicy == AnimatePosition) { - if (QQuickItem *contentItem = control->contentItem()) - contentItem->setProperty("x", contentItemX); - if (QQuickItem *background = control->background()) - background->setProperty("x", position * relevantWidth); - } else { - if (QQuickItem *contentItem = control->contentItem()) - contentItem->setX(contentItemX); - if (QQuickItem *background = control->background()) - background->setX(position * relevantWidth); - } -} - -void QQuickSwipePrivate::createLeftItem() -{ - if (!leftItem) { - Q_Q(QQuickSwipe); - q->setLeftItem(createDelegateItem(left)); - if (!leftItem) - qmlWarning(control) << "Failed to create left item:" << left->errors(); - } -} - -void QQuickSwipePrivate::createBehindItem() -{ - if (!behindItem) { - Q_Q(QQuickSwipe); - q->setBehindItem(createDelegateItem(behind)); - if (!behindItem) - qmlWarning(control) << "Failed to create behind item:" << behind->errors(); - } -} - -void QQuickSwipePrivate::createRightItem() -{ - if (!rightItem) { - Q_Q(QQuickSwipe); - q->setRightItem(createDelegateItem(right)); - if (!rightItem) - qmlWarning(control) << "Failed to create right item:" << right->errors(); - } -} - -void QQuickSwipePrivate::createAndShowLeftItem() -{ - createLeftItem(); - - if (leftItem) - leftItem->setVisible(true); - - if (rightItem) - rightItem->setVisible(false); -} - -void QQuickSwipePrivate::createAndShowBehindItem() -{ - createBehindItem(); - - if (behindItem) - behindItem->setVisible(true); -} - -void QQuickSwipePrivate::createAndShowRightItem() -{ - createRightItem(); - - // This item may have already existed but was hidden. - if (rightItem) - rightItem->setVisible(true); - - // The left item isn't visible when the right item is visible, so save rendering effort by hiding it. - if (leftItem) - leftItem->setVisible(false); -} - -void QQuickSwipePrivate::warnAboutMixingDelegates() -{ - qmlWarning(control) << "cannot set both behind and left/right properties"; -} - -void QQuickSwipePrivate::warnAboutSettingDelegatesWhileVisible() -{ - qmlWarning(control) << "left/right/behind properties may only be set when swipe.position is 0"; -} - -bool QQuickSwipePrivate::hasDelegates() const -{ - return left || right || behind; -} - -bool QQuickSwipePrivate::isTransitioning() const -{ - return transitionManager && transitionManager->isRunning(); -} - -void QQuickSwipePrivate::beginTransition(qreal newPosition) -{ - if (waitForTransition) - return; - Q_Q(QQuickSwipe); - if (!transition) { - q->setPosition(newPosition); - finishTransition(); - return; - } - - if (!transitionManager) - transitionManager.reset(new QQuickSwipeTransitionManager(q)); - - transitionManager->transition(transition, newPosition); -} - -void QQuickSwipePrivate::finishTransition() -{ - Q_Q(QQuickSwipe); - waitForTransition = false; - q->setComplete(qFuzzyCompare(qAbs(position), qreal(1.0))); - if (complete) { - emit q->opened(); - } else { - if (qFuzzyIsNull(position)) - wasComplete = false; - emit q->closed(); - } -} - -QQuickSwipe::QQuickSwipe(QQuickSwipeDelegate *control) - : QObject(*(new QQuickSwipePrivate(control))) -{ -} - -QQmlComponent *QQuickSwipe::left() const -{ - Q_D(const QQuickSwipe); - return d->left; -} - -void QQuickSwipe::setLeft(QQmlComponent *left) -{ - Q_D(QQuickSwipe); - if (left == d->left) - return; - - if (d->behind) { - d->warnAboutMixingDelegates(); - return; - } - - if (!qFuzzyIsNull(d->position)) { - d->warnAboutSettingDelegatesWhileVisible(); - return; - } - - d->left = left; - - if (!d->left) { - delete d->leftItem; - d->leftItem = nullptr; - } - - d->control->setFiltersChildMouseEvents(d->hasDelegates()); - - emit leftChanged(); -} - -QQmlComponent *QQuickSwipe::behind() const -{ - Q_D(const QQuickSwipe); - return d->behind; -} - -void QQuickSwipe::setBehind(QQmlComponent *behind) -{ - Q_D(QQuickSwipe); - if (behind == d->behind) - return; - - if (d->left || d->right) { - d->warnAboutMixingDelegates(); - return; - } - - if (!qFuzzyIsNull(d->position)) { - d->warnAboutSettingDelegatesWhileVisible(); - return; - } - - d->behind = behind; - - if (!d->behind) { - delete d->behindItem; - d->behindItem = nullptr; - } - - d->control->setFiltersChildMouseEvents(d->hasDelegates()); - - emit behindChanged(); -} - -QQmlComponent *QQuickSwipe::right() const -{ - Q_D(const QQuickSwipe); - return d->right; -} - -void QQuickSwipe::setRight(QQmlComponent *right) -{ - Q_D(QQuickSwipe); - if (right == d->right) - return; - - if (d->behind) { - d->warnAboutMixingDelegates(); - return; - } - - if (!qFuzzyIsNull(d->position)) { - d->warnAboutSettingDelegatesWhileVisible(); - return; - } - - d->right = right; - - if (!d->right) { - delete d->rightItem; - d->rightItem = nullptr; - } - - d->control->setFiltersChildMouseEvents(d->hasDelegates()); - - emit rightChanged(); -} - -QQuickItem *QQuickSwipe::leftItem() const -{ - Q_D(const QQuickSwipe); - return d->leftItem; -} - -void QQuickSwipe::setLeftItem(QQuickItem *item) -{ - Q_D(QQuickSwipe); - if (item == d->leftItem) - return; - - delete d->leftItem; - d->leftItem = item; - - if (d->leftItem) { - d->leftItem->setParentItem(d->control); - - if (qFuzzyIsNull(d->leftItem->z())) - d->leftItem->setZ(-2); - } - - emit leftItemChanged(); -} - -QQuickItem *QQuickSwipe::behindItem() const -{ - Q_D(const QQuickSwipe); - return d->behindItem; -} - -void QQuickSwipe::setBehindItem(QQuickItem *item) -{ - Q_D(QQuickSwipe); - if (item == d->behindItem) - return; - - delete d->behindItem; - d->behindItem = item; - - if (d->behindItem) { - d->behindItem->setParentItem(d->control); - - if (qFuzzyIsNull(d->behindItem->z())) - d->behindItem->setZ(-2); - } - - emit behindItemChanged(); -} - -QQuickItem *QQuickSwipe::rightItem() const -{ - Q_D(const QQuickSwipe); - return d->rightItem; -} - -void QQuickSwipe::setRightItem(QQuickItem *item) -{ - Q_D(QQuickSwipe); - if (item == d->rightItem) - return; - - delete d->rightItem; - d->rightItem = item; - - if (d->rightItem) { - d->rightItem->setParentItem(d->control); - - if (qFuzzyIsNull(d->rightItem->z())) - d->rightItem->setZ(-2); - } - - emit rightItemChanged(); -} - -qreal QQuickSwipe::position() const -{ - Q_D(const QQuickSwipe); - return d->position; -} - -void QQuickSwipe::setPosition(qreal position) -{ - Q_D(QQuickSwipe); - const qreal adjustedPosition = qBound<qreal>(-1.0, position, 1.0); - if (adjustedPosition == d->position) - return; - - d->position = adjustedPosition; - d->reposition(AnimatePosition); - emit positionChanged(); -} - -bool QQuickSwipe::isComplete() const -{ - Q_D(const QQuickSwipe); - return d->complete; -} - -void QQuickSwipe::setComplete(bool complete) -{ - Q_D(QQuickSwipe); - if (complete == d->complete) - return; - - d->complete = complete; - emit completeChanged(); - if (d->complete) - emit completed(); -} - -bool QQuickSwipe::isEnabled() const -{ - Q_D(const QQuickSwipe); - return d->enabled; -} - -void QQuickSwipe::setEnabled(bool enabled) -{ - Q_D(QQuickSwipe); - if (enabled == d->enabled) - return; - - d->enabled = enabled; - emit enabledChanged(); -} - -QQuickTransition *QQuickSwipe::transition() const -{ - Q_D(const QQuickSwipe); - return d->transition; -} - -void QQuickSwipe::setTransition(QQuickTransition *transition) -{ - Q_D(QQuickSwipe); - if (transition == d->transition) - return; - - d->transition = transition; - emit transitionChanged(); -} - -void QQuickSwipe::open(QQuickSwipeDelegate::Side side) -{ - Q_D(QQuickSwipe); - if (qFuzzyCompare(qAbs(d->position), qreal(1.0))) - return; - - if ((side != QQuickSwipeDelegate::Left && side != QQuickSwipeDelegate::Right) - || (!d->left && !d->behind && side == QQuickSwipeDelegate::Left) - || (!d->right && !d->behind && side == QQuickSwipeDelegate::Right)) - return; - - d->beginTransition(side); - d->wasComplete = true; - d->velocityCalculator.reset(); - d->positionBeforePress = d->position; -} - -void QQuickSwipe::close() -{ - Q_D(QQuickSwipe); - if (qFuzzyIsNull(d->position)) - return; - - if (d->control->isPressed()) { - // We don't support closing when we're pressed; release() or clicked() should be used instead. - return; - } - - d->beginTransition(0.0); - d->waitForTransition = true; - d->wasComplete = false; - d->positionBeforePress = 0.0; - d->velocityCalculator.reset(); -} - -QQuickSwipeDelegatePrivate::QQuickSwipeDelegatePrivate(QQuickSwipeDelegate *control) - : swipe(control) -{ -} - -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); - const auto posInItem = item->mapToItem(q, event->position().toPoint()); - QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&swipe); - // If the position is 0, we want to handle events ourselves - we don't want child items to steal them. - // This code will only get called when a child item has been created; - // events will go through the regular channels (mousePressEvent()) until then. - if (qFuzzyIsNull(swipePrivate->position)) { - q->mousePressEvent(event); - // The press point could be incorrect if the press happened over a child item, - // so we correct it after calling the base class' mousePressEvent(), rather - // than having to duplicate its code just so we can set the pressPoint. - setPressPoint(posInItem); - return true; - } - - // If the delegate is swiped open, send the event to the exposed item, - // in case it's an interactive child (like a Button). - if (swipePrivate->complete) - forwardMouseEvent(event, item, posInItem); - - // The position is non-zero, this press could be either for a delegate or the control itself - // (the control can be clicked to e.g. close the swipe). Either way, we must begin measuring - // mouse movement in case it turns into a swipe, in which case we grab the mouse. - swipePrivate->positionBeforePress = swipePrivate->position; - swipePrivate->velocityCalculator.startMeasuring(event->position().toPoint(), event->timestamp()); - setPressPoint(item->mapToItem(q, event->position().toPoint())); - - // When a delegate or any of its children uses the attached properties and signals, - // it declares that it wants mouse events. - const bool delivered = attachedObjectsSetPressed(item, event->scenePosition(), true); - if (delivered) - event->accept(); - return delivered; -} - -bool QQuickSwipeDelegatePrivate::handleMouseMoveEvent(QQuickItem *item, QMouseEvent *event) -{ - Q_Q(QQuickSwipeDelegate); - - if (holdTimer > 0) { - if (QLineF(pressPoint, event->position()).length() > QGuiApplication::styleHints()->startDragDistance()) - stopPressAndHold(); - } - - // The delegate can still be pressed when swipe.enabled is false, - // but the mouse moving shouldn't have any effect on swipe.position. - QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&swipe); - if (!swipePrivate->enabled) - return false; - - // Protect against division by zero. - if (width == 0) - return false; - - // Don't bother reacting to events if we don't have any delegates. - if (!swipePrivate->left && !swipePrivate->right && !swipePrivate->behind) - return false; - - // Don't handle move events for the control if it wasn't pressed. - if (item == q && !pressed) - return false; - - const QPointF mappedEventPos = item->mapToItem(q, event->position().toPoint()); - const qreal distance = (mappedEventPos - pressPoint).x(); - if (!q->keepMouseGrab()) { - // 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()) { - q->grabMouse(); - q->setKeepMouseGrab(true); - q->setPressed(true); - swipe.setComplete(false); - - attachedObjectsSetPressed(item, event->scenePosition(), false, true); - } - } - } - - if (q->keepMouseGrab()) { - // Ensure we don't try to calculate a position when the user tried to drag - // to the left when the left item is already exposed, and vice versa. - // The code below assumes that the drag is valid, so if we don't have this check, - // the wrong items are visible and the swiping wraps. - if (swipePrivate->behind - || ((swipePrivate->left || swipePrivate->right) - && (qFuzzyIsNull(swipePrivate->positionBeforePress) - || (swipePrivate->positionBeforePress == -1.0 && distance >= 0.0) - || (swipePrivate->positionBeforePress == 1.0 && distance <= 0.0)))) { - - // We must instantiate the items here so that we can calculate the - // position against the width of the relevant item. - QQuickItem *relevantItem = swipePrivate->createRelevantItemForDistance(distance); - // If there isn't any relevant item, the user may have swiped back to the 0 position, - // or they swiped back to a position that is equal to positionBeforePress. - const qreal normalizedDistance = relevantItem ? distance / relevantItem->width() : 0.0; - qreal position = 0; - - // If the control was exposed before the drag begun, the distance should be inverted. - // For example, if the control had been swiped to the right, the position would be 1.0. - // If the control was then swiped to the left by a distance of -20 pixels, the normalized - // distance might be -0.2, for example, which cannot be used as the position; the swipe - // started from the right, so we account for that by adding the position. - if (qFuzzyIsNull(normalizedDistance)) { - // There are two cases when the normalizedDistance can be 0, - // and we must distinguish between them: - // - // a) The swipe returns to the position that it was at before the press event. - // In this case, the distance will be 0. - // There would have been many position changes in the meantime, so we can't just - // ignore the move event; we have to set position to what it was before the press. - // - // b) If the position was at, 1.0, for example, and the control was then swiped - // to the left by the exact width of the left item, there won't be any relevant item - // (because the swipe's position would be at 0.0). In turn, the normalizedDistance - // would be 0 (because of the lack of a relevant item), but the distance will be non-zero. - position = qFuzzyIsNull(distance) ? swipePrivate->positionBeforePress : 0; - } else if (!swipePrivate->wasComplete) { - position = normalizedDistance; - } else { - position = distance > 0 ? normalizedDistance - 1.0 : normalizedDistance + 1.0; - } - - if (swipePrivate->isTransitioning()) - swipePrivate->transitionManager->cancel(); - swipe.setPosition(position); - } - } else { - // The swipe wasn't initiated. - if (event->position().toPoint().y() < 0 || event->position().toPoint().y() > height) { - // The mouse went outside the vertical bounds of the control, so - // we should no longer consider it pressed. - q->setPressed(false); - } - } - - event->accept(); - - return q->keepMouseGrab(); -} - -static const qreal exposeVelocityThreshold = 300.0; - -bool QQuickSwipeDelegatePrivate::handleMouseReleaseEvent(QQuickItem *item, QMouseEvent *event) -{ - Q_Q(QQuickSwipeDelegate); - QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&swipe); - swipePrivate->velocityCalculator.stopMeasuring(event->position().toPoint(), event->timestamp()); - - const bool hadGrabbedMouse = q->keepMouseGrab(); - q->setKeepMouseGrab(false); - - // QQuickSwipe::close() doesn't allow closing while pressed, but now we're releasing. - // So set the pressed state false if this release _could_ result in closing, so that check can be bypassed. - if (!qIsNull(swipePrivate->position)) - q->setPressed(false); - - // Animations for the background and contentItem delegates are typically - // only enabled when !control.down, so that the animations aren't running - // when the user is swiping. To ensure that the animations are enabled - // *before* the positions of these delegates change (via the swipe.setPosition() calls below), - // we must cancel the press. QQuickAbstractButton::mouseUngrabEvent() does this - // for us, but by then it's too late. - if (hadGrabbedMouse) { - // TODO: this is copied from QQuickAbstractButton::mouseUngrabEvent(). - // Eventually it should be moved into a private helper so that we don't have to duplicate it. - q->setPressed(false); - stopPressRepeat(); - stopPressAndHold(); - emit q->canceled(); - } - - // Inform the given item that the mouse is released, in case it's an interactive child. - if (item != q && (swipePrivate->complete || swipePrivate->wasComplete)) - forwardMouseEvent(event, item, item->mapFromScene(event->scenePosition())); - - // The control can be exposed by either swiping past the halfway mark, or swiping fast enough. - const qreal swipeVelocity = swipePrivate->velocityCalculator.velocity().x(); - if (swipePrivate->position > 0.5 || - (swipePrivate->position > 0.0 && swipeVelocity > exposeVelocityThreshold)) { - swipePrivate->beginTransition(1.0); - swipePrivate->wasComplete = true; - } else if (swipePrivate->position < -0.5 || - (swipePrivate->position < 0.0 && swipeVelocity < -exposeVelocityThreshold)) { - swipePrivate->beginTransition(-1.0); - swipePrivate->wasComplete = true; - } else if (!swipePrivate->isTransitioning()) { - // The position is either <= 0.5 or >= -0.5, so the position should go to 0. - // However, if the position was already 0 or close to it, we were just clicked, - // and we don't need to start a transition. - if (!qFuzzyIsNull(swipePrivate->position)) - swipePrivate->beginTransition(0.0); - swipePrivate->wasComplete = false; - } - - // Inform any QQuickSwipeDelegateAttached objects that the mouse is released. - attachedObjectsSetPressed(item, event->scenePosition(), false); - - // Only consume child events if we had grabbed the mouse. - return hadGrabbedMouse; -} - -/*! \internal - Send a localized copy of \a event with \a localPos to the \a destination item. -*/ -void QQuickSwipeDelegatePrivate::forwardMouseEvent(QMouseEvent *event, QQuickItem *destination, QPointF localPos) -{ - Q_Q(QQuickSwipeDelegate); - QMutableSinglePointEvent localizedEvent(*event); - localizedEvent.mutablePoint().setPosition(localPos); - QGuiApplication::sendEvent(destination, &localizedEvent); - q->setPressed(!localizedEvent.isAccepted()); -} - -/*! \internal - For each QQuickSwipeDelegateAttached object on children of \a item: - if \a scenePos is in the attachee (the item to which it's attached), then - set its \a pressed state. Unless \a cancel is \c true, when the state - transitions from pressed to released, also emit \l QQuickSwipeDelegateAttached::clicked(). - Returns \c true if at least one relevant attached object was found. -*/ -bool QQuickSwipeDelegatePrivate::attachedObjectsSetPressed(QQuickItem *item, QPointF scenePos, bool pressed, bool cancel) -{ - bool found = false; - QVarLengthArray<QQuickItem *, 16> itemAndChildren; - itemAndChildren.append(item); - for (int i = 0; i < itemAndChildren.count(); ++i) { - auto item = itemAndChildren.at(i); - auto posInItem = item->mapFromScene(scenePos); - if (item->contains(posInItem)) { - if (Attached *attached = attachedObject(item)) { - const bool wasPressed = attached->isPressed(); - attached->setPressed(pressed); - if (wasPressed && !pressed && !cancel) - emit attached->clicked(); - found = true; - } - } - for (auto child : item->childItems()) - itemAndChildren.append(child); - } - return found; -} - -static void warnIfHorizontallyAnchored(QQuickItem *item, const QString &itemName) -{ - if (!item) - return; - - QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors; - if (anchors && (anchors->fill() || anchors->centerIn() || anchors->left().item || anchors->right().item) - && !item->property("_q_QQuickSwipeDelegate_warned").toBool()) { - qmlWarning(item) << QString::fromLatin1("SwipeDelegate: cannot use horizontal anchors with %1; unable to layout the item.").arg(itemName); - item->setProperty("_q_QQuickSwipeDelegate_warned", true); - } -} - -void QQuickSwipeDelegatePrivate::resizeContent() -{ - warnIfHorizontallyAnchored(background, QStringLiteral("background")); - warnIfHorizontallyAnchored(contentItem, QStringLiteral("contentItem")); - - // 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 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()); - } -} - -QPalette QQuickSwipeDelegatePrivate::defaultPalette() const -{ - return QQuickTheme::palette(QQuickTheme::ListView); -} - -QQuickSwipeDelegate::QQuickSwipeDelegate(QQuickItem *parent) - : QQuickItemDelegate(*(new QQuickSwipeDelegatePrivate(this)), parent) -{ - // QQuickSwipeDelegate still depends on synthesized mouse events - setAcceptTouchEvents(false); -} - -/*! - \since QtQuick.Controls 2.2 (Qt 5.9) - \qmlmethod void QtQuick.Controls::SwipeDelegate::swipe.open(enumeration side) - - This method sets the \c position of the swipe so that it opens - from the specified \a side. - - Available values: - \value SwipeDelegate.Left The \c position is set to \c 1, which makes the swipe open - from the left. Either \c swipe.left or \c swipe.behind must - have been specified; otherwise the call is ignored. - \value SwipeDelegate.Right The \c position is set to \c -1, which makes the swipe open - from the right. Either \c swipe.right or \c swipe.behind must - have been specified; otherwise the call is ignored. - - Any animations defined for the \l {Item::}{x} position of \l {Control::}{contentItem} - and \l {Control::}{background} will be triggered. - - \sa swipe, swipe.close() -*/ - -/*! - \since QtQuick.Controls 2.1 (Qt 5.8) - \qmlmethod void QtQuick.Controls::SwipeDelegate::swipe.close() - - This method sets the \c position of the swipe to \c 0. Any animations - defined for the \l {Item::}{x} position of \l {Control::}{contentItem} - and \l {Control::}{background} will be triggered. - - \sa swipe, swipe.open() -*/ - -/*! - \since QtQuick.Controls 2.2 (Qt 5.9) - \qmlsignal void QtQuick.Controls::SwipeDelegate::swipe.opened() - - This signal is emitted when the delegate has been swiped open - and the transition has finished. - - It is useful for performing some action upon completion of a swipe. - For example, it can be used to remove the delegate from the list - that it is in. - - \sa swipe, swipe.closed() -*/ - -/*! - \since QtQuick.Controls 2.2 (Qt 5.9) - \qmlsignal void QtQuick.Controls::SwipeDelegate::swipe.closed() - - This signal is emitted when the delegate has been swiped to closed - and the transition has finished. - - It is useful for performing some action upon cancellation of a swipe. - For example, it can be used to cancel the removal of the delegate from - the list that it is in. - - \sa swipe, swipe.opened() -*/ - -/*! - \since QtQuick.Controls 2.1 (Qt 5.8) - \qmlsignal void QtQuick.Controls::SwipeDelegate::swipe.completed() - - This signal is emitted when \c swipe.complete becomes \c true. - - It is useful for performing some action upon completion of a swipe. - For example, it can be used to remove the delegate from the list - that it is in. - - \sa swipe -*/ - -/*! - \qmlproperty real QtQuick.Controls::SwipeDelegate::swipe.position - \qmlproperty bool QtQuick.Controls::SwipeDelegate::swipe.complete - \qmlproperty bool QtQuick.Controls::SwipeDelegate::swipe.enabled - \qmlproperty Component QtQuick.Controls::SwipeDelegate::swipe.left - \qmlproperty Component QtQuick.Controls::SwipeDelegate::swipe.behind - \qmlproperty Component QtQuick.Controls::SwipeDelegate::swipe.right - \qmlproperty Item QtQuick.Controls::SwipeDelegate::swipe.leftItem - \qmlproperty Item QtQuick.Controls::SwipeDelegate::swipe.behindItem - \qmlproperty Item QtQuick.Controls::SwipeDelegate::swipe.rightItem - \qmlproperty Transition QtQuick.Controls::SwipeDelegate::swipe.transition - - \table - \header - \li Name - \li Description - \row - \li position - \li This read-only property holds the position of the swipe relative to either - side of the control. When this value reaches either - \c -1.0 (left side) or \c 1.0 (right side) and the mouse button is - released, \c complete will be \c true. - \row - \li complete - \li This read-only property holds whether the control is fully exposed after - having been swiped to the left or right. - - When complete is \c true, any interactive items declared in \c left, - \c right, or \c behind will receive mouse events. - \row - \li enabled - \li This property determines whether or not the control can be swiped. - - This property was added in QtQuick.Controls 2.2. - \row - \li left - \li This property holds the left delegate. - - The left delegate sits behind both \l {Control::}{contentItem} and - \l {Control::}{background}. When the SwipeDelegate is swiped to the right, - this item will be gradually revealed. - - \include qquickswipedelegate-interaction.qdocinc - \row - \li behind - \li This property holds the delegate that is shown when the - SwipeDelegate is swiped to both the left and right. - - As with the \c left and \c right delegates, it sits behind both - \l {Control::}{contentItem} and \l {Control::}{background}. However, a - SwipeDelegate whose \c behind has been set can be continuously swiped - from either side, and will always show the same item. - - \include qquickswipedelegate-interaction.qdocinc - \row - \li right - \li This property holds the right delegate. - - The right delegate sits behind both \l {Control::}{contentItem} and - \l {Control::}{background}. When the SwipeDelegate is swiped to the left, - this item will be gradually revealed. - - \include qquickswipedelegate-interaction.qdocinc - \row - \li leftItem - \li This read-only property holds the item instantiated from the \c left component. - - If \c left has not been set, or the position hasn't changed since - creation of the SwipeDelegate, this property will be \c null. - \row - \li behindItem - \li This read-only property holds the item instantiated from the \c behind component. - - If \c behind has not been set, or the position hasn't changed since - creation of the SwipeDelegate, this property will be \c null. - \row - \li rightItem - \li This read-only property holds the item instantiated from the \c right component. - - If \c right has not been set, or the position hasn't changed since - creation of the SwipeDelegate, this property will be \c null. - \row - \li transition - \li This property holds the transition that is applied when a swipe is released, - or \l swipe.open() or \l swipe.close() is called. - - \snippet qtquickcontrols2-swipedelegate-transition.qml 1 - - This property was added in Qt Quick Controls 2.2. - \endtable - - \sa {Control::}{contentItem}, {Control::}{background}, swipe.open(), swipe.close() -*/ -QQuickSwipe *QQuickSwipeDelegate::swipe() const -{ - Q_D(const QQuickSwipeDelegate); - return const_cast<QQuickSwipe*>(&d->swipe); -} - -QQuickSwipeDelegateAttached *QQuickSwipeDelegate::qmlAttachedProperties(QObject *object) -{ - return new QQuickSwipeDelegateAttached(object); -} - -static bool isChildOrGrandchildOf(QQuickItem *child, QQuickItem *item) -{ - return item && (child == item || item->isAncestorOf(child)); -} - -bool QQuickSwipeDelegate::childMouseEventFilter(QQuickItem *child, QEvent *event) -{ - Q_D(QQuickSwipeDelegate); - // The contentItem is, by default, usually a non-interactive item like Text, and - // the same applies to the background. This means that simply stacking the left/right/behind - // items before these items won't allow us to get mouse events when the control is not currently exposed - // but has been previously. Therefore, we instead call setFiltersChildMouseEvents(true) in the constructor - // and filter out child events only when the child is the left/right/behind item. - const QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&d->swipe); - if (!isChildOrGrandchildOf(child, swipePrivate->leftItem) && !isChildOrGrandchildOf(child, swipePrivate->behindItem) - && !isChildOrGrandchildOf(child, swipePrivate->rightItem)) { - return false; - } - - switch (event->type()) { - case QEvent::MouseButtonPress: { - return d->handleMousePressEvent(child, static_cast<QMouseEvent *>(event)); - } case QEvent::MouseMove: { - return d->handleMouseMoveEvent(child, static_cast<QMouseEvent *>(event)); - } case QEvent::MouseButtonRelease: { - // Make sure that the control gets release events if it has created child - // items that are stealing events from it. - QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); - QQuickItemDelegate::mouseReleaseEvent(mouseEvent); - return d->handleMouseReleaseEvent(child, mouseEvent); - } case QEvent::UngrabMouse: { - // If the mouse was pressed over e.g. rightItem and then dragged down, - // the ListView would eventually grab the mouse, at which point we must - // clear the pressed flag so that it doesn't stay pressed after the release. - Attached *attached = attachedObject(child); - if (attached) - attached->setPressed(false); - return false; - } default: - return false; - } -} - -// We only override this to set positionBeforePress; -// otherwise, it's the same as the base class implementation. -void QQuickSwipeDelegate::mousePressEvent(QMouseEvent *event) -{ - Q_D(QQuickSwipeDelegate); - QQuickItemDelegate::mousePressEvent(event); - - QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&d->swipe); - if (!swipePrivate->enabled) - return; - - swipePrivate->positionBeforePress = swipePrivate->position; - swipePrivate->velocityCalculator.startMeasuring(event->position().toPoint(), event->timestamp()); - - if (swipePrivate->complete) { - auto item = d->swipe.rightItem(); - if (item && item->contains(item->mapFromScene(event->scenePosition()))) { - d->pressedItem = item; - d->handleMousePressEvent(item, event); - } else { - item = d->swipe.leftItem(); - if (item && item->contains(item->mapFromScene(event->scenePosition()))) { - d->pressedItem = item; - d->handleMousePressEvent(item, event); - } - } - } -} - -void QQuickSwipeDelegate::mouseMoveEvent(QMouseEvent *event) -{ - Q_D(QQuickSwipeDelegate); - if (filtersChildMouseEvents()) - d->handleMouseMoveEvent(this, event); - else - QQuickItemDelegate::mouseMoveEvent(event); - if (d->pressedItem) - d->handleMouseMoveEvent(d->pressedItem, event); -} - -void QQuickSwipeDelegate::mouseReleaseEvent(QMouseEvent *event) -{ - Q_D(QQuickSwipeDelegate); - if (!filtersChildMouseEvents() || !d->handleMouseReleaseEvent(this, event)) - QQuickItemDelegate::mouseReleaseEvent(event); - - if (d->pressedItem) { - if (d->pressedItem->acceptedMouseButtons()) - d->handleMouseReleaseEvent(d->pressedItem, event); - d->pressedItem = nullptr; - } -} - -void QQuickSwipeDelegate::mouseUngrabEvent() -{ - Q_D(QQuickSwipeDelegate); - setPressed(false); - - auto item = d->swipe.rightItem(); - if (item) { - if (auto control = qmlobject_cast<QQuickControl *>(item)) - QQuickControlPrivate::get(control)->handleUngrab(); - Attached *attached = attachedObject(item); - if (attached) - attached->setPressed(false); - } else { - item = d->swipe.leftItem(); - if (item) { - if (auto control = qmlobject_cast<QQuickControl *>(item)) - QQuickControlPrivate::get(control)->handleUngrab(); - Attached *attached = attachedObject(item); - if (attached) - attached->setPressed(false); - } - } - - d->pressedItem = nullptr; -} - -void QQuickSwipeDelegate::touchEvent(QTouchEvent *event) -{ - // Don't allow QQuickControl accept the touch event, because QQuickSwipeDelegate - // is still based on synthesized mouse events - event->ignore(); -} - -void QQuickSwipeDelegate::componentComplete() -{ - Q_D(QQuickSwipeDelegate); - QQuickItemDelegate::componentComplete(); - QQuickSwipePrivate::get(&d->swipe)->reposition(DontAnimatePosition); -} - -void QQuickSwipeDelegate::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) -{ - Q_D(QQuickSwipeDelegate); - QQuickControl::geometryChange(newGeometry, oldGeometry); - - if (isComponentComplete() && !qFuzzyCompare(newGeometry.width(), oldGeometry.width())) { - QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&d->swipe); - swipePrivate->reposition(DontAnimatePosition); - } -} - -QFont QQuickSwipeDelegate::defaultFont() const -{ - return QQuickTheme::font(QQuickTheme::ListView); -} - -#if QT_CONFIG(accessibility) -QAccessible::Role QQuickSwipeDelegate::accessibleRole() const -{ - return QAccessible::ListItem; -} -#endif - -class QQuickSwipeDelegateAttachedPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QQuickSwipeDelegateAttached) - -public: - // True when left/right/behind is non-interactive and is pressed. - bool pressed = false; -}; - -/*! - \since QtQuick.Controls 2.1 (Qt 5.8) - \qmlattachedsignal QtQuick.Controls::SwipeDelegate::clicked() - - This signal can be attached to a non-interactive item declared in - \c swipe.left, \c swipe.right, or \c swipe.behind, in order to react to - clicks. Items can only be clicked when \c swipe.complete is \c true. - - For interactive controls (such as \l Button) declared in these - items, use their respective \c clicked() signal instead. - - To respond to clicks on the SwipeDelegate itself, use its - \l {AbstractButton::}{clicked()} signal. - - \note See the documentation for \l pressed for information on - how to use the event-related properties correctly. - - \sa pressed -*/ - -QQuickSwipeDelegateAttached::QQuickSwipeDelegateAttached(QObject *object) - : QObject(*(new QQuickSwipeDelegateAttachedPrivate), object) -{ - QQuickItem *item = qobject_cast<QQuickItem *>(object); - if (item) { - // This allows us to be notified when an otherwise non-interactive item - // is pressed and clicked. The alternative is much more more complex: - // iterating through children that contain the event pos and finding - // the first one with an attached object. - item->setAcceptedMouseButtons(Qt::AllButtons); - } else { - qWarning() << "Attached properties of SwipeDelegate must be accessed through an Item"; - } -} - -/*! - \since QtQuick.Controls 2.1 (Qt 5.8) - \qmlattachedproperty bool QtQuick.Controls::SwipeDelegate::pressed - \readonly - - This property can be attached to a non-interactive item declared in - \c swipe.left, \c swipe.right, or \c swipe.behind, in order to detect if it - is pressed. Items can only be pressed when \c swipe.complete is \c true. - - For example: - - \code - swipe.right: Label { - anchors.right: parent.right - height: parent.height - text: "Action" - color: "white" - padding: 12 - background: Rectangle { - color: SwipeDelegate.pressed ? Qt.darker("tomato", 1.1) : "tomato" - } - } - \endcode - - It is possible to have multiple items which individually receive mouse and - touch events. For example, to have two actions in the \c swipe.right item, - use the following code: - - \code - swipe.right: Row { - anchors.right: parent.right - height: parent.height - - Label { - id: moveLabel - text: qsTr("Move") - color: "white" - verticalAlignment: Label.AlignVCenter - padding: 12 - height: parent.height - - SwipeDelegate.onClicked: console.log("Moving...") - - background: Rectangle { - color: moveLabel.SwipeDelegate.pressed ? Qt.darker("#ffbf47", 1.1) : "#ffbf47" - } - } - Label { - id: deleteLabel - text: qsTr("Delete") - color: "white" - verticalAlignment: Label.AlignVCenter - padding: 12 - height: parent.height - - SwipeDelegate.onClicked: console.log("Deleting...") - - background: Rectangle { - color: deleteLabel.SwipeDelegate.pressed ? Qt.darker("tomato", 1.1) : "tomato" - } - } - } - \endcode - - Note how the \c color assignment in each \l {Control::}{background} item - qualifies the attached property with the \c id of the label. This - is important; using the attached properties on an item causes that item - to accept events. Suppose we had left out the \c id in the previous example: - - \code - color: SwipeDelegate.pressed ? Qt.darker("tomato", 1.1) : "tomato" - \endcode - - The \l Rectangle background item is a child of the label, so it naturally - receives events before it. In practice, this means that the background - color will change, but the \c onClicked handler in the label will never - get called. - - For interactive controls (such as \l Button) declared in these - items, use their respective \c pressed property instead. - - For presses on the SwipeDelegate itself, use its - \l {AbstractButton::}{pressed} property. - - \sa clicked() -*/ -bool QQuickSwipeDelegateAttached::isPressed() const -{ - Q_D(const QQuickSwipeDelegateAttached); - return d->pressed; -} - -void QQuickSwipeDelegateAttached::setPressed(bool pressed) -{ - Q_D(QQuickSwipeDelegateAttached); - if (pressed == d->pressed) - return; - - d->pressed = pressed; - emit pressedChanged(); -} - -QT_END_NAMESPACE - -#include "moc_qquickswipe_p.cpp" -#include "moc_qquickswipedelegate_p.cpp" |