diff options
Diffstat (limited to 'src/quicktemplates2/qquickscrollbar.cpp')
-rw-r--r-- | src/quicktemplates2/qquickscrollbar.cpp | 474 |
1 files changed, 351 insertions, 123 deletions
diff --git a/src/quicktemplates2/qquickscrollbar.cpp b/src/quicktemplates2/qquickscrollbar.cpp index c17b3be6..3dcb720a 100644 --- a/src/quicktemplates2/qquickscrollbar.cpp +++ b/src/quicktemplates2/qquickscrollbar.cpp @@ -35,11 +35,11 @@ ****************************************************************************/ #include "qquickscrollbar_p.h" -#include "qquickcontrol_p_p.h" +#include "qquickscrollbar_p_p.h" +#include "qquickscrollview_p.h" #include <QtQml/qqmlinfo.h> #include <QtQuick/private/qquickflickable_p.h> -#include <QtQuick/private/qquickitemchangelistener_p.h> QT_BEGIN_NAMESPACE @@ -151,37 +151,36 @@ QT_BEGIN_NAMESPACE \sa ScrollIndicator, {Customizing ScrollBar}, {Indicator Controls} */ -class QQuickScrollBarPrivate : public QQuickControlPrivate -{ - Q_DECLARE_PUBLIC(QQuickScrollBar) +static const QQuickItemPrivate::ChangeTypes changeTypes = QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed; +static const QQuickItemPrivate::ChangeTypes horizontalChangeTypes = changeTypes | QQuickItemPrivate::ImplicitHeight; +static const QQuickItemPrivate::ChangeTypes verticalChangeTypes = changeTypes | QQuickItemPrivate::ImplicitWidth; -public: - QQuickScrollBarPrivate() : size(0), position(0), stepSize(0), offset(0), - active(false), pressed(false), moving(false), - orientation(Qt::Vertical) - { - } +QQuickScrollBarPrivate::QQuickScrollBarPrivate() + : size(0), + position(0), + stepSize(0), + offset(0), + active(false), + pressed(false), + moving(false), + interactive(true), + explicitInteractive(false), + orientation(Qt::Vertical), + snapMode(QQuickScrollBar::NoSnap), + policy(QQuickScrollBar::AsNeeded) +{ +} - static QQuickScrollBarPrivate *get(QQuickScrollBar *bar) - { - return bar->d_func(); - } +qreal QQuickScrollBarPrivate::snapPosition(qreal position) const +{ + const qreal effectiveStep = stepSize * (1.0 - size); + if (qFuzzyIsNull(effectiveStep)) + return position; - qreal positionAt(const QPoint &point) const; - void updateActive(); - void resizeContent() override; - - qreal size; - qreal position; - qreal stepSize; - qreal offset; - bool active; - bool pressed; - bool moving; - Qt::Orientation orientation; -}; + return qRound(position / effectiveStep) * effectiveStep; +} -qreal QQuickScrollBarPrivate::positionAt(const QPoint &point) const +qreal QQuickScrollBarPrivate::positionAt(const QPointF &point) const { Q_Q(const QQuickScrollBar); if (orientation == Qt::Horizontal) @@ -190,10 +189,28 @@ qreal QQuickScrollBarPrivate::positionAt(const QPoint &point) const return (point.y() - q->topPadding()) / q->availableHeight(); } +void QQuickScrollBarPrivate::setInteractive(bool enabled) +{ + Q_Q(QQuickScrollBar); + if (interactive == enabled) + return; + + interactive = enabled; + q->setAcceptedMouseButtons(interactive ? Qt::LeftButton : Qt::NoButton); + if (!interactive) + q->ungrabMouse(); + emit q->interactiveChanged(); +} + void QQuickScrollBarPrivate::updateActive() { Q_Q(QQuickScrollBar); - q->setActive(moving || pressed || hovered); +#if QT_CONFIG(quicktemplates2_hover) + bool hover = hovered; +#else + bool hover = false; +#endif + q->setActive(moving || (interactive && (pressed || hover))); } void QQuickScrollBarPrivate::resizeContent() @@ -202,17 +219,58 @@ void QQuickScrollBarPrivate::resizeContent() if (!contentItem) return; + // - negative overshoot (pos < 0): clamp the pos to 0, and deduct the overshoot from the size + // - positive overshoot (pos + size > 1): clamp the size to 1-pos + const qreal clampedSize = qBound<qreal>(0, size + qMin<qreal>(0, position), 1.0 - position); + const qreal clampedPos = qBound<qreal>(0, position, 1.0 - clampedSize); + if (orientation == Qt::Horizontal) { - contentItem->setPosition(QPointF(q->leftPadding() + position * q->availableWidth(), q->topPadding())); - contentItem->setSize(QSizeF(q->availableWidth() * size, q->availableHeight())); + contentItem->setPosition(QPointF(q->leftPadding() + clampedPos * q->availableWidth(), q->topPadding())); + contentItem->setSize(QSizeF(q->availableWidth() * clampedSize, q->availableHeight())); } else { - contentItem->setPosition(QPointF(q->leftPadding(), q->topPadding() + position * q->availableHeight())); - contentItem->setSize(QSizeF(q->availableWidth(), q->availableHeight() * size)); + contentItem->setPosition(QPointF(q->leftPadding(), q->topPadding() + clampedPos * q->availableHeight())); + contentItem->setSize(QSizeF(q->availableWidth(), q->availableHeight() * clampedSize)); } } -QQuickScrollBar::QQuickScrollBar(QQuickItem *parent) : - QQuickControl(*(new QQuickScrollBarPrivate), parent) +void QQuickScrollBarPrivate::handlePress(const QPointF &point) +{ + Q_Q(QQuickScrollBar); + offset = positionAt(point) - position; + if (offset < 0 || offset > size) + offset = size / 2; + q->setPressed(true); +} + +void QQuickScrollBarPrivate::handleMove(const QPointF &point) +{ + Q_Q(QQuickScrollBar); + qreal pos = qBound<qreal>(0.0, positionAt(point) - offset, 1.0 - size); + if (snapMode == QQuickScrollBar::SnapAlways) + pos = snapPosition(pos); + q->setPosition(pos); +} + +void QQuickScrollBarPrivate::handleRelease(const QPointF &point) +{ + Q_Q(QQuickScrollBar); + qreal pos = qBound<qreal>(0.0, positionAt(point) - offset, 1.0 - size); + if (snapMode != QQuickScrollBar::NoSnap) + pos = snapPosition(pos); + q->setPosition(pos); + offset = 0.0; + q->setPressed(false); +} + +void QQuickScrollBarPrivate::handleUngrab() +{ + Q_Q(QQuickScrollBar); + offset = 0.0; + q->setPressed(false); +} + +QQuickScrollBar::QQuickScrollBar(QQuickItem *parent) + : QQuickControl(*(new QQuickScrollBarPrivate), parent) { setKeepMouseGrab(true); setAcceptedMouseButtons(Qt::LeftButton); @@ -220,11 +278,7 @@ QQuickScrollBar::QQuickScrollBar(QQuickItem *parent) : QQuickScrollBarAttached *QQuickScrollBar::qmlAttachedProperties(QObject *object) { - QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(object); - if (!flickable) - qmlInfo(object) << "ScrollBar must be attached to a Flickable"; - - return new QQuickScrollBarAttached(flickable); + return new QQuickScrollBarAttached(object); } /*! @@ -246,7 +300,6 @@ qreal QQuickScrollBar::size() const void QQuickScrollBar::setSize(qreal size) { Q_D(QQuickScrollBar); - size = qBound<qreal>(0.0, size, 1.0 - d->position); if (qFuzzyCompare(d->size, size)) return; @@ -275,7 +328,6 @@ qreal QQuickScrollBar::position() const void QQuickScrollBar::setPosition(qreal position) { Q_D(QQuickScrollBar); - position = qBound<qreal>(0.0, position, 1.0 - d->size); if (qFuzzyCompare(d->position, position)) return; @@ -290,7 +342,7 @@ void QQuickScrollBar::setPosition(qreal position) This property holds the step size. The default value is \c 0.0. - \sa increase(), decrease() + \sa snapMode, increase(), decrease() */ qreal QQuickScrollBar::stepSize() const { @@ -390,6 +442,107 @@ void QQuickScrollBar::setOrientation(Qt::Orientation orientation) } /*! + \since QtQuick.Controls 2.2 + \qmlproperty enumeration QtQuick.Controls::ScrollBar::snapMode + + This property holds the snap mode. + + Possible values: + \value ScrollBar.NoSnap The scrollbar does not snap (default). + \value ScrollBar.SnapAlways The scrollbar snaps while dragged. + \value ScrollBar.SnapOnRelease The scrollbar does not snap while being dragged, but only after released. + + In the following table, the various modes are illustrated with animations. + The movement and the \l stepSize (\c 0.25) are identical in each animation. + + \table + \header + \row \li \b Value \li \b Example + \row \li \c ScrollBar.NoSnap \li \image qtquickcontrols2-scrollbar-nosnap.gif + \row \li \c ScrollBar.SnapAlways \li \image qtquickcontrols2-scrollbar-snapalways.gif + \row \li \c ScrollBar.SnapOnRelease \li \image qtquickcontrols2-scrollbar-snaponrelease.gif + \endtable + + \sa stepSize +*/ +QQuickScrollBar::SnapMode QQuickScrollBar::snapMode() const +{ + Q_D(const QQuickScrollBar); + return d->snapMode; +} + +void QQuickScrollBar::setSnapMode(SnapMode mode) +{ + Q_D(QQuickScrollBar); + if (d->snapMode == mode) + return; + + d->snapMode = mode; + emit snapModeChanged(); +} + +/*! + \since QtQuick.Controls 2.2 + \qmlproperty bool QtQuick.Controls::ScrollBar::interactive + + This property holds whether the scroll bar is interactive. The default value is \c true. + + A non-interactive scroll bar is visually and behaviorally similar to \l ScrollIndicator. + This property is useful for switching between typical mouse- and touch-orientated UIs + with interactive and non-interactive scroll bars, respectively. +*/ +bool QQuickScrollBar::isInteractive() const +{ + Q_D(const QQuickScrollBar); + return d->interactive; +} + +void QQuickScrollBar::setInteractive(bool interactive) +{ + Q_D(QQuickScrollBar); + d->explicitInteractive = true; + d->setInteractive(interactive); +} + +void QQuickScrollBar::resetInteractive() +{ + Q_D(QQuickScrollBar); + d->explicitInteractive = false; + d->setInteractive(true); +} + +/*! + \since QtQuick.Controls 2.2 + \qmlproperty enumeration QtQuick.Controls::ScrollBar::policy + + This property holds the policy of the scroll bar. The default policy is \c ScrollBar.AsNeeded. + + Possible values: + \value ScrollBar.AsNeeded The scroll bar is only shown when the content is too large to fit. + \value ScrollBar.AlwaysOff The scroll bar is never shown. + \value ScrollBar.AlwaysOn The scroll bar is always shown. + + The following example keeps the vertical scroll bar always visible: + + \snippet qtquickcontrols2-scrollbar-policy.qml 1 +*/ +QQuickScrollBar::Policy QQuickScrollBar::policy() const +{ + Q_D(const QQuickScrollBar); + return d->policy; +} + +void QQuickScrollBar::setPolicy(Policy policy) +{ + Q_D(QQuickScrollBar); + if (d->policy == policy) + return; + + d->policy = policy; + emit policyChanged(); +} + +/*! \qmlmethod void QtQuick.Controls::ScrollBar::increase() Increases the position by \l stepSize or \c 0.1 if stepSize is \c 0.0. @@ -402,7 +555,7 @@ void QQuickScrollBar::increase() qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize; bool wasActive = d->active; setActive(true); - setPosition(d->position + step); + setPosition(qMin<qreal>(1.0 - d->size, d->position + step)); setActive(wasActive); } @@ -419,7 +572,7 @@ void QQuickScrollBar::decrease() qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize; bool wasActive = d->active; setActive(true); - setPosition(d->position - step); + setPosition(qMax<qreal>(0.0, d->position - step)); setActive(wasActive); } @@ -427,35 +580,39 @@ void QQuickScrollBar::mousePressEvent(QMouseEvent *event) { Q_D(QQuickScrollBar); QQuickControl::mousePressEvent(event); - d->offset = d->positionAt(event->pos()) - d->position; - if (d->offset < 0 || d->offset > d->size) - d->offset = d->size / 2; - setPressed(true); + d->handlePress(event->localPos()); } void QQuickScrollBar::mouseMoveEvent(QMouseEvent *event) { Q_D(QQuickScrollBar); QQuickControl::mouseMoveEvent(event); - setPosition(qBound<qreal>(0.0, d->positionAt(event->pos()) - d->offset, 1.0 - d->size)); + d->handleMove(event->localPos()); } void QQuickScrollBar::mouseReleaseEvent(QMouseEvent *event) { Q_D(QQuickScrollBar); QQuickControl::mouseReleaseEvent(event); - setPosition(qBound<qreal>(0.0, d->positionAt(event->pos()) - d->offset, 1.0 - d->size)); - d->offset = 0.0; - setPressed(false); + d->handleRelease(event->localPos()); +} + +void QQuickScrollBar::mouseUngrabEvent() +{ + Q_D(QQuickScrollBar); + QQuickControl::mouseUngrabEvent(); + d->handleUngrab(); } +#if QT_CONFIG(quicktemplates2_hover) void QQuickScrollBar::hoverChange() { Q_D(QQuickScrollBar); d->updateActive(); } +#endif -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) void QQuickScrollBar::accessibilityActiveChanged(bool active) { QQuickControl::accessibilityActiveChanged(active); @@ -471,27 +628,102 @@ QAccessible::Role QQuickScrollBar::accessibleRole() const } #endif -class QQuickScrollBarAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener +QQuickScrollBarAttachedPrivate::QQuickScrollBarAttachedPrivate() + : flickable(nullptr), + horizontal(nullptr), + vertical(nullptr) +{ +} + +void QQuickScrollBarAttachedPrivate::setFlickable(QQuickFlickable *item) { -public: - QQuickScrollBarAttachedPrivate(QQuickFlickable *flickable) : flickable(flickable), horizontal(nullptr), vertical(nullptr) { } + if (flickable) { + // NOTE: Use removeItemChangeListener(Geometry) instead of updateOrRemoveGeometryChangeListener(Size). + // The latter doesn't remove the listener but only resets its types. Thus, it leaves behind a dangling + // pointer on destruction. + QQuickItemPrivate::get(flickable)->removeItemChangeListener(this, QQuickItemPrivate::Geometry); + if (horizontal) + cleanupHorizontal(); + if (vertical) + cleanupVertical(); + } - void activateHorizontal(); - void activateVertical(); - void scrollHorizontal(); - void scrollVertical(); - void mirrorVertical(); + flickable = item; - void layoutHorizontal(bool move = true); - void layoutVertical(bool move = true); + if (item) { + QQuickItemPrivate::get(item)->updateOrAddGeometryChangeListener(this, QQuickGeometryChange::Size); + if (horizontal) + initHorizontal(); + if (vertical) + initVertical(); + } +} - void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override; - void itemDestroyed(QQuickItem *item) override; +void QQuickScrollBarAttachedPrivate::initHorizontal() +{ + Q_ASSERT(flickable && horizontal); - QQuickFlickable *flickable; - QQuickScrollBar *horizontal; - QQuickScrollBar *vertical; -}; + connect(flickable, &QQuickFlickable::movingHorizontallyChanged, this, &QQuickScrollBarAttachedPrivate::activateHorizontal); + + // TODO: export QQuickFlickableVisibleArea + QObject *area = flickable->property("visibleArea").value<QObject *>(); + QObject::connect(area, SIGNAL(widthRatioChanged(qreal)), horizontal, SLOT(setSize(qreal))); + QObject::connect(area, SIGNAL(xPositionChanged(qreal)), horizontal, SLOT(setPosition(qreal))); + + // ensure that the ScrollBar is stacked above the Flickable in a ScrollView + QQuickItem *parent = horizontal->parentItem(); + if (parent && parent == flickable->parentItem()) + horizontal->stackAfter(flickable); + + layoutHorizontal(); + horizontal->setSize(area->property("widthRatio").toReal()); + horizontal->setPosition(area->property("xPosition").toReal()); +} + +void QQuickScrollBarAttachedPrivate::initVertical() +{ + Q_ASSERT(flickable && vertical); + + connect(flickable, &QQuickFlickable::movingVerticallyChanged, this, &QQuickScrollBarAttachedPrivate::activateVertical); + + // TODO: export QQuickFlickableVisibleArea + QObject *area = flickable->property("visibleArea").value<QObject *>(); + QObject::connect(area, SIGNAL(heightRatioChanged(qreal)), vertical, SLOT(setSize(qreal))); + QObject::connect(area, SIGNAL(yPositionChanged(qreal)), vertical, SLOT(setPosition(qreal))); + + // ensure that the ScrollBar is stacked above the Flickable in a ScrollView + QQuickItem *parent = vertical->parentItem(); + if (parent && parent == flickable->parentItem()) + vertical->stackAfter(flickable); + + layoutVertical(); + vertical->setSize(area->property("heightRatio").toReal()); + vertical->setPosition(area->property("yPosition").toReal()); +} + +void QQuickScrollBarAttachedPrivate::cleanupHorizontal() +{ + Q_ASSERT(flickable && horizontal); + + disconnect(flickable, &QQuickFlickable::movingHorizontallyChanged, this, &QQuickScrollBarAttachedPrivate::activateHorizontal); + + // TODO: export QQuickFlickableVisibleArea + QObject *area = flickable->property("visibleArea").value<QObject *>(); + QObject::disconnect(area, SIGNAL(widthRatioChanged(qreal)), horizontal, SLOT(setSize(qreal))); + QObject::disconnect(area, SIGNAL(xPositionChanged(qreal)), horizontal, SLOT(setPosition(qreal))); +} + +void QQuickScrollBarAttachedPrivate::cleanupVertical() +{ + Q_ASSERT(flickable && vertical); + + disconnect(flickable, &QQuickFlickable::movingVerticallyChanged, this, &QQuickScrollBarAttachedPrivate::activateVertical); + + // TODO: export QQuickFlickableVisibleArea + QObject *area = flickable->property("visibleArea").value<QObject *>(); + QObject::disconnect(area, SIGNAL(heightRatioChanged(qreal)), vertical, SLOT(setSize(qreal))); + QObject::disconnect(area, SIGNAL(yPositionChanged(qreal)), vertical, SLOT(setPosition(qreal))); +} void QQuickScrollBarAttachedPrivate::activateHorizontal() { @@ -570,7 +802,8 @@ void QQuickScrollBarAttachedPrivate::itemGeometryChanged(QQuickItem *item, const #else bool move = qFuzzyIsNull(horizontal->y()) || qFuzzyCompare(horizontal->y(), item->height() - diff.height() - horizontal->height()); #endif - layoutHorizontal(move); + if (flickable) + layoutHorizontal(move); } if (vertical && vertical->width() > 0) { #ifdef QT_QUICK_NEW_GEOMETRY_CHANGED_HANDLING // TODO: correct/rename diff to oldGeometry @@ -578,10 +811,23 @@ void QQuickScrollBarAttachedPrivate::itemGeometryChanged(QQuickItem *item, const #else bool move = qFuzzyIsNull(vertical->x()) || qFuzzyCompare(vertical->x(), item->width() - diff.width() - vertical->width()); #endif - layoutVertical(move); + if (flickable) + layoutVertical(move); } } +void QQuickScrollBarAttachedPrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + if (item == vertical && flickable) + layoutVertical(true); +} + +void QQuickScrollBarAttachedPrivate::itemImplicitHeightChanged(QQuickItem *item) +{ + if (item == horizontal && flickable) + layoutHorizontal(true); +} + void QQuickScrollBarAttachedPrivate::itemDestroyed(QQuickItem *item) { if (item == horizontal) @@ -590,26 +836,28 @@ void QQuickScrollBarAttachedPrivate::itemDestroyed(QQuickItem *item) vertical = nullptr; } -QQuickScrollBarAttached::QQuickScrollBarAttached(QQuickFlickable *flickable) : - QObject(*(new QQuickScrollBarAttachedPrivate(flickable)), flickable) +QQuickScrollBarAttached::QQuickScrollBarAttached(QObject *parent) + : QObject(*(new QQuickScrollBarAttachedPrivate), parent) { Q_D(QQuickScrollBarAttached); - if (flickable) { - QQuickItemPrivate *p = QQuickItemPrivate::get(flickable); - p->updateOrAddGeometryChangeListener(d, QQuickGeometryChange::Size); - } + d->setFlickable(qobject_cast<QQuickFlickable *>(parent)); + + if (parent && !d->flickable && !qobject_cast<QQuickScrollView *>(parent)) + qmlWarning(parent) << "ScrollBar must be attached to a Flickable or ScrollView"; } QQuickScrollBarAttached::~QQuickScrollBarAttached() { Q_D(QQuickScrollBarAttached); - if (d->flickable) { - if (d->horizontal) - QQuickItemPrivate::get(d->horizontal)->removeItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed); - if (d->vertical) - QQuickItemPrivate::get(d->vertical)->removeItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed); - QQuickItemPrivate::get(d->flickable)->removeItemChangeListener(d, QQuickItemPrivate::Geometry); + if (d->horizontal) { + QQuickItemPrivate::get(d->horizontal)->removeItemChangeListener(d, horizontalChangeTypes); + d->horizontal = nullptr; + } + if (d->vertical) { + QQuickItemPrivate::get(d->vertical)->removeItemChangeListener(d, verticalChangeTypes); + d->vertical = nullptr; } + d->setFlickable(nullptr); } /*! @@ -638,36 +886,26 @@ void QQuickScrollBarAttached::setHorizontal(QQuickScrollBar *horizontal) if (d->horizontal == horizontal) return; - if (d->horizontal && d->flickable) { - QQuickItemPrivate::get(d->horizontal)->removeItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed); + if (d->horizontal) { + QQuickItemPrivate::get(d->horizontal)->removeItemChangeListener(d, horizontalChangeTypes); QObjectPrivate::disconnect(d->horizontal, &QQuickScrollBar::positionChanged, d, &QQuickScrollBarAttachedPrivate::scrollHorizontal); - QObjectPrivate::disconnect(d->flickable, &QQuickFlickable::movingHorizontallyChanged, d, &QQuickScrollBarAttachedPrivate::activateHorizontal); - // TODO: export QQuickFlickableVisibleArea - QObject *area = d->flickable->property("visibleArea").value<QObject *>(); - disconnect(area, SIGNAL(widthRatioChanged(qreal)), d->horizontal, SLOT(setSize(qreal))); - disconnect(area, SIGNAL(xPositionChanged(qreal)), d->horizontal, SLOT(setPosition(qreal))); + if (d->flickable) + d->cleanupHorizontal(); } d->horizontal = horizontal; - if (horizontal && d->flickable) { + if (horizontal) { if (!horizontal->parentItem()) - horizontal->setParentItem(d->flickable); + horizontal->setParentItem(qobject_cast<QQuickItem *>(parent())); horizontal->setOrientation(Qt::Horizontal); - QQuickItemPrivate::get(horizontal)->addItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed); + QQuickItemPrivate::get(horizontal)->addItemChangeListener(d, horizontalChangeTypes); QObjectPrivate::connect(horizontal, &QQuickScrollBar::positionChanged, d, &QQuickScrollBarAttachedPrivate::scrollHorizontal); - QObjectPrivate::connect(d->flickable, &QQuickFlickable::movingHorizontallyChanged, d, &QQuickScrollBarAttachedPrivate::activateHorizontal); - // TODO: export QQuickFlickableVisibleArea - QObject *area = d->flickable->property("visibleArea").value<QObject *>(); - connect(area, SIGNAL(widthRatioChanged(qreal)), horizontal, SLOT(setSize(qreal))); - connect(area, SIGNAL(xPositionChanged(qreal)), horizontal, SLOT(setPosition(qreal))); - - d->layoutHorizontal(); - horizontal->setSize(area->property("widthRatio").toReal()); - horizontal->setPosition(area->property("xPosition").toReal()); + if (d->flickable) + d->initHorizontal(); } emit horizontalChanged(); } @@ -698,38 +936,28 @@ void QQuickScrollBarAttached::setVertical(QQuickScrollBar *vertical) if (d->vertical == vertical) return; - if (d->vertical && d->flickable) { - QQuickItemPrivate::get(d->vertical)->removeItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed); + if (d->vertical) { + QQuickItemPrivate::get(d->vertical)->removeItemChangeListener(d, verticalChangeTypes); QObjectPrivate::disconnect(d->vertical, &QQuickScrollBar::mirroredChanged, d, &QQuickScrollBarAttachedPrivate::mirrorVertical); QObjectPrivate::disconnect(d->vertical, &QQuickScrollBar::positionChanged, d, &QQuickScrollBarAttachedPrivate::scrollVertical); - QObjectPrivate::disconnect(d->flickable, &QQuickFlickable::movingVerticallyChanged, d, &QQuickScrollBarAttachedPrivate::activateVertical); - // TODO: export QQuickFlickableVisibleArea - QObject *area = d->flickable->property("visibleArea").value<QObject *>(); - disconnect(area, SIGNAL(heightRatioChanged(qreal)), d->vertical, SLOT(setSize(qreal))); - disconnect(area, SIGNAL(yPositionChanged(qreal)), d->vertical, SLOT(setPosition(qreal))); + if (d->flickable) + d->cleanupVertical(); } d->vertical = vertical; - if (vertical && d->flickable) { + if (vertical) { if (!vertical->parentItem()) - vertical->setParentItem(d->flickable); + vertical->setParentItem(qobject_cast<QQuickItem *>(parent())); vertical->setOrientation(Qt::Vertical); - QQuickItemPrivate::get(vertical)->addItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed); + QQuickItemPrivate::get(vertical)->addItemChangeListener(d, verticalChangeTypes); QObjectPrivate::connect(vertical, &QQuickScrollBar::mirroredChanged, d, &QQuickScrollBarAttachedPrivate::mirrorVertical); QObjectPrivate::connect(vertical, &QQuickScrollBar::positionChanged, d, &QQuickScrollBarAttachedPrivate::scrollVertical); - QObjectPrivate::connect(d->flickable, &QQuickFlickable::movingVerticallyChanged, d, &QQuickScrollBarAttachedPrivate::activateVertical); - - // TODO: export QQuickFlickableVisibleArea - QObject *area = d->flickable->property("visibleArea").value<QObject *>(); - connect(area, SIGNAL(heightRatioChanged(qreal)), vertical, SLOT(setSize(qreal))); - connect(area, SIGNAL(yPositionChanged(qreal)), vertical, SLOT(setPosition(qreal))); - d->layoutVertical(); - vertical->setSize(area->property("heightRatio").toReal()); - vertical->setPosition(area->property("yPosition").toReal()); + if (d->flickable) + d->initVertical(); } emit verticalChanged(); } |