aboutsummaryrefslogtreecommitdiffstats
path: root/src/quicktemplates2
diff options
context:
space:
mode:
Diffstat (limited to 'src/quicktemplates2')
-rw-r--r--src/quicktemplates2/configure.json20
-rw-r--r--src/quicktemplates2/qquickabstractbutton.cpp250
-rw-r--r--src/quicktemplates2/qquickabstractbutton_p.h18
-rw-r--r--src/quicktemplates2/qquickabstractbutton_p_p.h8
-rw-r--r--src/quicktemplates2/qquickapplicationwindow.cpp23
-rw-r--r--src/quicktemplates2/qquickapplicationwindow_p.h4
-rw-r--r--src/quicktemplates2/qquickbusyindicator.cpp6
-rw-r--r--src/quicktemplates2/qquickbusyindicator_p.h2
-rw-r--r--src/quicktemplates2/qquickbutton.cpp19
-rw-r--r--src/quicktemplates2/qquickbutton_p.h2
-rw-r--r--src/quicktemplates2/qquickbuttongroup.cpp4
-rw-r--r--src/quicktemplates2/qquickcheckbox.cpp16
-rw-r--r--src/quicktemplates2/qquickcheckbox_p.h4
-rw-r--r--src/quicktemplates2/qquickcheckdelegate.cpp16
-rw-r--r--src/quicktemplates2/qquickcheckdelegate_p.h4
-rw-r--r--src/quicktemplates2/qquickcombobox.cpp550
-rw-r--r--src/quicktemplates2/qquickcombobox_p.h50
-rw-r--r--src/quicktemplates2/qquickcontainer.cpp15
-rw-r--r--src/quicktemplates2/qquickcontrol.cpp132
-rw-r--r--src/quicktemplates2/qquickcontrol_p.h10
-rw-r--r--src/quicktemplates2/qquickcontrol_p_p.h18
-rw-r--r--src/quicktemplates2/qquickdelaybutton.cpp271
-rw-r--r--src/quicktemplates2/qquickdelaybutton_p.h98
-rw-r--r--src/quicktemplates2/qquickdial.cpp246
-rw-r--r--src/quicktemplates2/qquickdial_p.h12
-rw-r--r--src/quicktemplates2/qquickdialog.cpp7
-rw-r--r--src/quicktemplates2/qquickdialog_p.h2
-rw-r--r--src/quicktemplates2/qquickdialogbuttonbox.cpp21
-rw-r--r--src/quicktemplates2/qquickdialogbuttonbox_p.h2
-rw-r--r--src/quicktemplates2/qquickdialogbuttonbox_p_p.h9
-rw-r--r--src/quicktemplates2/qquickdrawer.cpp43
-rw-r--r--src/quicktemplates2/qquickdrawer_p.h5
-rw-r--r--src/quicktemplates2/qquickframe.cpp12
-rw-r--r--src/quicktemplates2/qquickframe_p.h2
-rw-r--r--src/quicktemplates2/qquickgroupbox.cpp10
-rw-r--r--src/quicktemplates2/qquickgroupbox_p.h2
-rw-r--r--src/quicktemplates2/qquickitemdelegate.cpp14
-rw-r--r--src/quicktemplates2/qquickitemdelegate_p.h2
-rw-r--r--src/quicktemplates2/qquicklabel.cpp48
-rw-r--r--src/quicktemplates2/qquicklabel_p.h1
-rw-r--r--src/quicktemplates2/qquicklabel_p_p.h21
-rw-r--r--src/quicktemplates2/qquickmenu.cpp14
-rw-r--r--src/quicktemplates2/qquickmenu_p.h4
-rw-r--r--src/quicktemplates2/qquickmenu_p_p.h1
-rw-r--r--src/quicktemplates2/qquickmenuitem.cpp10
-rw-r--r--src/quicktemplates2/qquickmenuitem_p.h2
-rw-r--r--src/quicktemplates2/qquickmenuseparator.cpp6
-rw-r--r--src/quicktemplates2/qquickmenuseparator_p.h2
-rw-r--r--src/quicktemplates2/qquickoverlay.cpp11
-rw-r--r--src/quicktemplates2/qquickoverlay_p.h2
-rw-r--r--src/quicktemplates2/qquickpage.cpp6
-rw-r--r--src/quicktemplates2/qquickpage_p.h2
-rw-r--r--src/quicktemplates2/qquickpageindicator.cpp14
-rw-r--r--src/quicktemplates2/qquickpageindicator_p.h2
-rw-r--r--src/quicktemplates2/qquickpagelayout.cpp4
-rw-r--r--src/quicktemplates2/qquickpane.cpp14
-rw-r--r--src/quicktemplates2/qquickpane_p.h2
-rw-r--r--src/quicktemplates2/qquickpopup.cpp613
-rw-r--r--src/quicktemplates2/qquickpopup_p.h6
-rw-r--r--src/quicktemplates2/qquickpopup_p_p.h78
-rw-r--r--src/quicktemplates2/qquickpopupitem.cpp303
-rw-r--r--src/quicktemplates2/qquickpopupitem_p_p.h108
-rw-r--r--src/quicktemplates2/qquickpopuppositioner.cpp277
-rw-r--r--src/quicktemplates2/qquickpopuppositioner_p_p.h85
-rw-r--r--src/quicktemplates2/qquickpresshandler.cpp15
-rw-r--r--src/quicktemplates2/qquickprogressbar.cpp12
-rw-r--r--src/quicktemplates2/qquickprogressbar_p.h2
-rw-r--r--src/quicktemplates2/qquickradiobutton.cpp6
-rw-r--r--src/quicktemplates2/qquickradiobutton_p.h2
-rw-r--r--src/quicktemplates2/qquickradiodelegate.cpp6
-rw-r--r--src/quicktemplates2/qquickradiodelegate_p.h2
-rw-r--r--src/quicktemplates2/qquickrangeslider.cpp399
-rw-r--r--src/quicktemplates2/qquickrangeslider_p.h9
-rw-r--r--src/quicktemplates2/qquickroundbutton.cpp10
-rw-r--r--src/quicktemplates2/qquickscrollbar.cpp474
-rw-r--r--src/quicktemplates2/qquickscrollbar_p.h38
-rw-r--r--src/quicktemplates2/qquickscrollbar_p_p.h133
-rw-r--r--src/quicktemplates2/qquickscrollindicator.cpp72
-rw-r--r--src/quicktemplates2/qquickscrollindicator_p.h4
-rw-r--r--src/quicktemplates2/qquickscrollview.cpp572
-rw-r--r--src/quicktemplates2/qquickscrollview_p.h105
-rw-r--r--src/quicktemplates2/qquickslider.cpp246
-rw-r--r--src/quicktemplates2/qquickslider_p.h12
-rw-r--r--src/quicktemplates2/qquickspinbox.cpp230
-rw-r--r--src/quicktemplates2/qquickspinbox_p.h17
-rw-r--r--src/quicktemplates2/qquickstackelement.cpp314
-rw-r--r--src/quicktemplates2/qquickstackelement_p_p.h106
-rw-r--r--src/quicktemplates2/qquickstacktransition.cpp158
-rw-r--r--src/quicktemplates2/qquickstacktransition_p_p.h79
-rw-r--r--src/quicktemplates2/qquickstackview.cpp121
-rw-r--r--src/quicktemplates2/qquickstackview_p.cpp394
-rw-r--r--src/quicktemplates2/qquickstackview_p.h26
-rw-r--r--src/quicktemplates2/qquickstackview_p_p.h83
-rw-r--r--src/quicktemplates2/qquickswipe_p.h18
-rw-r--r--src/quicktemplates2/qquickswipedelegate.cpp306
-rw-r--r--src/quicktemplates2/qquickswipedelegate_p.h6
-rw-r--r--src/quicktemplates2/qquickswipeview.cpp62
-rw-r--r--src/quicktemplates2/qquickswipeview_p.h7
-rw-r--r--src/quicktemplates2/qquickswitch.cpp81
-rw-r--r--src/quicktemplates2/qquickswitch_p.h5
-rw-r--r--src/quicktemplates2/qquickswitchdelegate.cpp86
-rw-r--r--src/quicktemplates2/qquickswitchdelegate_p.h5
-rw-r--r--src/quicktemplates2/qquicktabbar.cpp186
-rw-r--r--src/quicktemplates2/qquicktabbar_p.h14
-rw-r--r--src/quicktemplates2/qquicktabbutton.cpp6
-rw-r--r--src/quicktemplates2/qquicktabbutton_p.h2
-rw-r--r--src/quicktemplates2/qquicktextarea.cpp227
-rw-r--r--src/quicktemplates2/qquicktextarea_p.h4
-rw-r--r--src/quicktemplates2/qquicktextarea_p_p.h24
-rw-r--r--src/quicktemplates2/qquicktextfield.cpp163
-rw-r--r--src/quicktemplates2/qquicktextfield_p.h3
-rw-r--r--src/quicktemplates2/qquicktextfield_p_p.h20
-rw-r--r--src/quicktemplates2/qquicktoolbar.cpp6
-rw-r--r--src/quicktemplates2/qquicktoolbar_p.h2
-rw-r--r--src/quicktemplates2/qquicktoolbutton.cpp4
-rw-r--r--src/quicktemplates2/qquicktoolseparator.cpp11
-rw-r--r--src/quicktemplates2/qquicktoolseparator_p.h2
-rw-r--r--src/quicktemplates2/qquicktooltip.cpp28
-rw-r--r--src/quicktemplates2/qquicktooltip_p.h2
-rw-r--r--src/quicktemplates2/qquicktumbler.cpp59
-rw-r--r--src/quicktemplates2/qquicktumbler_p.h4
-rw-r--r--src/quicktemplates2/qquickvelocitycalculator.cpp6
-rw-r--r--src/quicktemplates2/qtquicktemplates2global_p.h1
-rw-r--r--src/quicktemplates2/quicktemplates2.pri24
124 files changed, 6238 insertions, 2348 deletions
diff --git a/src/quicktemplates2/configure.json b/src/quicktemplates2/configure.json
new file mode 100644
index 00000000..9bd5e311
--- /dev/null
+++ b/src/quicktemplates2/configure.json
@@ -0,0 +1,20 @@
+{
+ "module": "quicktemplates2",
+
+ "features": {
+ "quicktemplates2-hover": {
+ "label": "Hover support",
+ "purpose": "Provides support for hover effects in Qt Quick Templates 2",
+ "output": [ "privateFeature" ]
+ }
+ },
+
+ "summary": [
+ {
+ "section": "Qt Quick Templates 2",
+ "entries": [
+ "quicktemplates2-hover"
+ ]
+ }
+ ]
+}
diff --git a/src/quicktemplates2/qquickabstractbutton.cpp b/src/quicktemplates2/qquickabstractbutton.cpp
index 68a0a11b..225ab9ab 100644
--- a/src/quicktemplates2/qquickabstractbutton.cpp
+++ b/src/quicktemplates2/qquickabstractbutton.cpp
@@ -93,6 +93,13 @@ static const int AUTO_REPEAT_INTERVAL = 100;
*/
/*!
+ \since QtQuick.Controls 2.2
+ \qmlsignal QtQuick.Controls::AbstractButton::toggled()
+
+ This signal is emitted when a checkable button is interactively toggled by the user.
+*/
+
+/*!
\qmlsignal QtQuick.Controls::AbstractButton::pressAndHold()
This signal is emitted when the button is interactively pressed and held down by the user.
@@ -104,11 +111,90 @@ static const int AUTO_REPEAT_INTERVAL = 100;
This signal is emitted when the button is interactively double clicked by the user.
*/
-QQuickAbstractButtonPrivate::QQuickAbstractButtonPrivate() :
- down(false), explicitDown(false), pressed(false), keepPressed(false), checked(false), checkable(false),
- autoExclusive(false), autoRepeat(false), wasHeld(false),
- holdTimer(0), delayTimer(0), repeatTimer(0), repeatButton(Qt::NoButton), indicator(nullptr), group(nullptr)
+QQuickAbstractButtonPrivate::QQuickAbstractButtonPrivate()
+ : down(false),
+ explicitDown(false),
+ pressed(false),
+ keepPressed(false),
+ checked(false),
+ checkable(false),
+ autoExclusive(false),
+ autoRepeat(false),
+ wasHeld(false),
+ touchId(-1),
+ holdTimer(0),
+ delayTimer(0),
+ repeatTimer(0),
+ repeatButton(Qt::NoButton),
+ indicator(nullptr),
+ group(nullptr)
+{
+}
+
+void QQuickAbstractButtonPrivate::handlePress(const QPointF &point, Qt::MouseButton button, Qt::MouseButtons buttons)
+{
+ Q_Q(QQuickAbstractButton);
+ pressPoint = point;
+ q->setPressed(true);
+
+ emit q->pressed();
+
+ if (autoRepeat) {
+ startRepeatDelay();
+ repeatButton = button;
+ } else if (Qt::LeftButton == (buttons & Qt::LeftButton)) {
+ startPressAndHold();
+ } else {
+ stopPressAndHold();
+ }
+}
+
+void QQuickAbstractButtonPrivate::handleMove(const QPointF &point)
+{
+ Q_Q(QQuickAbstractButton);
+ q->setPressed(keepPressed || q->contains(point));
+
+ if (!pressed && autoRepeat)
+ stopPressRepeat();
+ else if (holdTimer > 0 && (!pressed || QLineF(pressPoint, point).length() > QGuiApplication::styleHints()->startDragDistance()))
+ stopPressAndHold();
+}
+
+void QQuickAbstractButtonPrivate::handleRelease(const QPointF &point)
{
+ Q_Q(QQuickAbstractButton);
+ bool wasPressed = pressed;
+ q->setPressed(false);
+ touchId = -1;
+
+ if (!wasHeld && (keepPressed || q->contains(point)))
+ q->nextCheckState();
+
+ if (wasPressed) {
+ emit q->released();
+ if (!wasHeld)
+ emit q->clicked();
+ } else {
+ emit q->canceled();
+ }
+
+ if (autoRepeat)
+ stopPressRepeat();
+ else
+ stopPressAndHold();
+}
+
+void QQuickAbstractButtonPrivate::handleCancel()
+{
+ Q_Q(QQuickAbstractButton);
+ if (!pressed)
+ return;
+
+ q->setPressed(false);
+ touchId = -1;
+ stopPressRepeat();
+ stopPressAndHold();
+ emit q->canceled();
}
bool QQuickAbstractButtonPrivate::isPressAndHoldConnected()
@@ -162,6 +248,15 @@ void QQuickAbstractButtonPrivate::stopPressRepeat()
}
}
+void QQuickAbstractButtonPrivate::toggle(bool value)
+{
+ Q_Q(QQuickAbstractButton);
+ const bool wasChecked = checked;
+ q->setChecked(value);
+ if (wasChecked != checked)
+ emit q->toggled();
+}
+
QQuickAbstractButton *QQuickAbstractButtonPrivate::findCheckedButton() const
{
Q_Q(const QQuickAbstractButton);
@@ -207,16 +302,16 @@ QList<QQuickAbstractButton *> QQuickAbstractButtonPrivate::findExclusiveButtons(
return buttons;
}
-QQuickAbstractButton::QQuickAbstractButton(QQuickItem *parent) :
- QQuickControl(*(new QQuickAbstractButtonPrivate), parent)
+QQuickAbstractButton::QQuickAbstractButton(QQuickItem *parent)
+ : QQuickControl(*(new QQuickAbstractButtonPrivate), parent)
{
setActiveFocusOnTab(true);
setFocusPolicy(Qt::StrongFocus);
setAcceptedMouseButtons(Qt::LeftButton);
}
-QQuickAbstractButton::QQuickAbstractButton(QQuickAbstractButtonPrivate &dd, QQuickItem *parent) :
- QQuickControl(dd, parent)
+QQuickAbstractButton::QQuickAbstractButton(QQuickAbstractButtonPrivate &dd, QQuickItem *parent)
+ : QQuickControl(dd, parent)
{
setActiveFocusOnTab(true);
setFocusPolicy(Qt::StrongFocus);
@@ -254,6 +349,7 @@ void QQuickAbstractButton::setText(const QString &text)
d->text = text;
setAccessibleName(text);
+ buttonChange(ButtonTextChange);
emit textChanged();
}
@@ -319,6 +415,7 @@ void QQuickAbstractButton::setPressed(bool isPressed)
d->pressed = isPressed;
setAccessibleProperty("pressed", isPressed);
emit pressedChanged();
+ buttonChange(ButtonPressedChanged);
if (!d->explicitDown) {
setDown(d->pressed);
@@ -350,7 +447,7 @@ void QQuickAbstractButton::setChecked(bool checked)
d->checked = checked;
setAccessibleProperty("checked", checked);
- checkStateSet();
+ buttonChange(ButtonCheckedChange);
emit checkedChanged();
}
@@ -383,7 +480,7 @@ void QQuickAbstractButton::setCheckable(bool checkable)
d->checkable = checkable;
setAccessibleProperty("checkable", checkable);
- checkableChange();
+ buttonChange(ButtonCheckableChange);
emit checkableChanged();
}
@@ -431,7 +528,7 @@ void QQuickAbstractButton::setAutoRepeat(bool repeat)
d->stopPressRepeat();
d->autoRepeat = repeat;
- autoRepeatChange();
+ buttonChange(ButtonAutoRepeatChange);
}
/*!
@@ -451,7 +548,7 @@ void QQuickAbstractButton::setIndicator(QQuickItem *indicator)
if (d->indicator == indicator)
return;
- d->deleteDelegate(d->indicator);
+ QQuickControlPrivate::destroyDelegate(d->indicator, this);
d->indicator = indicator;
if (indicator) {
if (!indicator->parentItem())
@@ -476,10 +573,7 @@ void QQuickAbstractButton::focusOutEvent(QFocusEvent *event)
{
Q_D(QQuickAbstractButton);
QQuickControl::focusOutEvent(event);
- if (d->pressed) {
- setPressed(false);
- emit canceled();
- }
+ d->handleCancel();
}
void QQuickAbstractButton::keyPressEvent(QKeyEvent *event)
@@ -521,55 +615,21 @@ void QQuickAbstractButton::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickAbstractButton);
QQuickControl::mousePressEvent(event);
- d->pressPoint = event->pos();
- setPressed(true);
-
- emit pressed();
-
- if (d->autoRepeat) {
- d->startRepeatDelay();
- d->repeatButton = event->button();
- } else if (Qt::LeftButton == (event->buttons() & Qt::LeftButton)) {
- d->startPressAndHold();
- } else {
- d->stopPressAndHold();
- }
+ d->handlePress(event->localPos(), event->button(), event->buttons());
}
void QQuickAbstractButton::mouseMoveEvent(QMouseEvent *event)
{
Q_D(QQuickAbstractButton);
QQuickControl::mouseMoveEvent(event);
- setPressed(d->keepPressed || contains(event->pos()));
-
- if (!d->pressed && d->autoRepeat)
- d->stopPressRepeat();
- else if (d->holdTimer > 0 && (!d->pressed || QLineF(d->pressPoint, event->localPos()).length() > QGuiApplication::styleHints()->startDragDistance()))
- d->stopPressAndHold();
+ d->handleMove(event->localPos());
}
void QQuickAbstractButton::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QQuickAbstractButton);
QQuickControl::mouseReleaseEvent(event);
- bool wasPressed = d->pressed;
- setPressed(false);
-
- if (!d->wasHeld && (d->keepPressed || contains(event->pos())))
- nextCheckState();
-
- if (wasPressed) {
- emit released();
- if (!d->wasHeld)
- emit clicked();
- } else {
- emit canceled();
- }
-
- if (d->autoRepeat)
- d->stopPressRepeat();
- else
- d->stopPressAndHold();
+ d->handleRelease(event->localPos());
}
void QQuickAbstractButton::mouseDoubleClickEvent(QMouseEvent *event)
@@ -582,12 +642,7 @@ void QQuickAbstractButton::mouseUngrabEvent()
{
Q_D(QQuickAbstractButton);
QQuickControl::mouseUngrabEvent();
- if (d->pressed) {
- setPressed(false);
- d->stopPressRepeat();
- d->stopPressAndHold();
- emit canceled();
- }
+ d->handleCancel();
}
void QQuickAbstractButton::timerEvent(QTimerEvent *event)
@@ -607,32 +662,87 @@ void QQuickAbstractButton::timerEvent(QTimerEvent *event)
}
}
-void QQuickAbstractButton::checkStateSet()
+void QQuickAbstractButton::touchEvent(QTouchEvent *event)
{
Q_D(QQuickAbstractButton);
- if (d->checked) {
- QQuickAbstractButton *button = d->findCheckedButton();
- if (button && button != this)
- button->setChecked(false);
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ if (d->touchId == -1) {
+ const QTouchEvent::TouchPoint point = event->touchPoints().first();
+ d->touchId = point.id();
+ d->handlePress(point.pos());
+ }
+ break;
+
+ case QEvent::TouchUpdate:
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ if (point.id() != d->touchId)
+ continue;
+
+ switch (point.state()) {
+ case Qt::TouchPointPressed:
+ d->handlePress(point.pos());
+ break;
+ case Qt::TouchPointMoved:
+ d->handleMove(point.pos());
+ break;
+ case Qt::TouchPointReleased:
+ d->handleRelease(point.pos());
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+
+ case QEvent::TouchEnd:
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ if (point.id() == d->touchId)
+ d->handleRelease(point.pos());
+ }
+ break;
+
+ case QEvent::TouchCancel:
+ d->handleCancel();
+ break;
+
+ default:
+ QQuickControl::touchEvent(event);
+ break;
}
}
-void QQuickAbstractButton::nextCheckState()
+void QQuickAbstractButton::touchUngrabEvent()
{
Q_D(QQuickAbstractButton);
- if (d->checkable && (!d->checked || d->findCheckedButton() != this))
- setChecked(!d->checked);
+ QQuickControl::touchUngrabEvent();
+ d->handleCancel();
}
-void QQuickAbstractButton::checkableChange()
+void QQuickAbstractButton::buttonChange(ButtonChange change)
{
+ Q_D(QQuickAbstractButton);
+ switch (change) {
+ case ButtonCheckedChange:
+ if (d->checked) {
+ QQuickAbstractButton *button = d->findCheckedButton();
+ if (button && button != this)
+ button->setChecked(false);
+ }
+ break;
+ default:
+ break;
+ }
}
-void QQuickAbstractButton::autoRepeatChange()
+void QQuickAbstractButton::nextCheckState()
{
+ Q_D(QQuickAbstractButton);
+ if (d->checkable && (!d->checked || d->findCheckedButton() != this))
+ d->toggle(!d->checked);
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
void QQuickAbstractButton::accessibilityActiveChanged(bool active)
{
QQuickControl::accessibilityActiveChanged(active);
diff --git a/src/quicktemplates2/qquickabstractbutton_p.h b/src/quicktemplates2/qquickabstractbutton_p.h
index f82c51c5..28a59c00 100644
--- a/src/quicktemplates2/qquickabstractbutton_p.h
+++ b/src/quicktemplates2/qquickabstractbutton_p.h
@@ -102,6 +102,7 @@ Q_SIGNALS:
void released();
void canceled();
void clicked();
+ Q_REVISION(2) void toggled();
void pressAndHold();
void doubleClicked();
void textChanged();
@@ -124,14 +125,21 @@ protected:
void mouseDoubleClickEvent(QMouseEvent *event) override;
void mouseUngrabEvent() override;
void timerEvent(QTimerEvent *event) override;
+ void touchEvent(QTouchEvent *event) override;
+ void touchUngrabEvent() override;
+
+ enum ButtonChange {
+ ButtonAutoRepeatChange,
+ ButtonCheckedChange,
+ ButtonCheckableChange,
+ ButtonPressedChanged,
+ ButtonTextChange
+ };
+ virtual void buttonChange(ButtonChange change);
- virtual void checkStateSet();
virtual void nextCheckState();
- virtual void checkableChange();
- virtual void autoRepeatChange();
-
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
void accessibilityActiveChanged(bool active) override;
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquickabstractbutton_p_p.h b/src/quicktemplates2/qquickabstractbutton_p_p.h
index da40b4c8..e27f5c82 100644
--- a/src/quicktemplates2/qquickabstractbutton_p_p.h
+++ b/src/quicktemplates2/qquickabstractbutton_p_p.h
@@ -67,6 +67,11 @@ public:
return button->d_func();
}
+ virtual void handlePress(const QPointF &point, Qt::MouseButton button = Qt::LeftButton, Qt::MouseButtons buttons = Qt::LeftButton);
+ virtual void handleMove(const QPointF &point);
+ virtual void handleRelease(const QPointF &point);
+ virtual void handleCancel();
+
bool isPressAndHoldConnected();
void startPressAndHold();
void stopPressAndHold();
@@ -78,6 +83,8 @@ public:
QQuickAbstractButton *findCheckedButton() const;
QList<QQuickAbstractButton *> findExclusiveButtons() const;
+ void toggle(bool value);
+
QString text;
bool down;
bool explicitDown;
@@ -88,6 +95,7 @@ public:
bool autoExclusive;
bool autoRepeat;
bool wasHeld;
+ int touchId;
int holdTimer;
int delayTimer;
int repeatTimer;
diff --git a/src/quicktemplates2/qquickapplicationwindow.cpp b/src/quicktemplates2/qquickapplicationwindow.cpp
index 0123786a..dcf1b5f0 100644
--- a/src/quicktemplates2/qquickapplicationwindow.cpp
+++ b/src/quicktemplates2/qquickapplicationwindow.cpp
@@ -138,14 +138,15 @@ class QQuickApplicationWindowPrivate : public QQuickItemChangeListener
public:
QQuickApplicationWindowPrivate()
- : complete(false)
- , background(nullptr)
- , contentItem(nullptr)
- , header(nullptr)
- , footer(nullptr)
- , overlay(nullptr)
- , activeFocusControl(nullptr)
- { }
+ : complete(false),
+ background(nullptr),
+ contentItem(nullptr),
+ header(nullptr),
+ footer(nullptr),
+ overlay(nullptr),
+ activeFocusControl(nullptr)
+ {
+ }
static QQuickApplicationWindowPrivate *get(QQuickApplicationWindow *window)
{
@@ -283,8 +284,8 @@ void QQuickApplicationWindowPrivate::setActiveFocusControl(QQuickItem *control)
}
}
-QQuickApplicationWindow::QQuickApplicationWindow(QWindow *parent) :
- QQuickWindowQmlImpl(parent), d_ptr(new QQuickApplicationWindowPrivate)
+QQuickApplicationWindow::QQuickApplicationWindow(QWindow *parent)
+ : QQuickWindowQmlImpl(parent), d_ptr(new QQuickApplicationWindowPrivate)
{
d_ptr->q_ptr = this;
connect(this, SIGNAL(activeFocusItemChanged()), this, SLOT(_q_updateActiveFocus()));
@@ -334,7 +335,7 @@ void QQuickApplicationWindow::setBackground(QQuickItem *background)
if (d->background == background)
return;
- delete d->background;
+ QQuickControlPrivate::destroyDelegate(d->background, this);
d->background = background;
if (background) {
background->setParentItem(QQuickWindow::contentItem());
diff --git a/src/quicktemplates2/qquickapplicationwindow_p.h b/src/quicktemplates2/qquickapplicationwindow_p.h
index 2c5e604c..07ddc67e 100644
--- a/src/quicktemplates2/qquickapplicationwindow_p.h
+++ b/src/quicktemplates2/qquickapplicationwindow_p.h
@@ -65,14 +65,14 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickApplicationWindow : public QQuickWi
Q_OBJECT
Q_PROPERTY(QQuickItem *background READ background WRITE setBackground NOTIFY backgroundChanged FINAL)
Q_PROPERTY(QQuickItem *contentItem READ contentItem CONSTANT FINAL)
- Q_PROPERTY(QQmlListProperty<QObject> data READ contentData FINAL)
+ Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL)
Q_PROPERTY(QQuickItem *activeFocusControl READ activeFocusControl NOTIFY activeFocusControlChanged FINAL)
Q_PROPERTY(QQuickItem *header READ header WRITE setHeader NOTIFY headerChanged FINAL)
Q_PROPERTY(QQuickItem *footer READ footer WRITE setFooter NOTIFY footerChanged FINAL)
Q_PROPERTY(QQuickOverlay *overlay READ overlay CONSTANT FINAL)
Q_PROPERTY(QFont font READ font WRITE setFont RESET resetFont NOTIFY fontChanged FINAL)
Q_PROPERTY(QLocale locale READ locale WRITE setLocale RESET resetLocale NOTIFY localeChanged FINAL)
- Q_CLASSINFO("DefaultProperty", "data")
+ Q_CLASSINFO("DefaultProperty", "contentData")
public:
explicit QQuickApplicationWindow(QWindow *parent = nullptr);
diff --git a/src/quicktemplates2/qquickbusyindicator.cpp b/src/quicktemplates2/qquickbusyindicator.cpp
index e37992f8..883066d7 100644
--- a/src/quicktemplates2/qquickbusyindicator.cpp
+++ b/src/quicktemplates2/qquickbusyindicator.cpp
@@ -84,8 +84,8 @@ public:
bool running;
};
-QQuickBusyIndicator::QQuickBusyIndicator(QQuickItem *parent) :
- QQuickControl(*(new QQuickBusyIndicatorPrivate), parent)
+QQuickBusyIndicator::QQuickBusyIndicator(QQuickItem *parent)
+ : QQuickControl(*(new QQuickBusyIndicatorPrivate), parent)
{
}
@@ -115,7 +115,7 @@ void QQuickBusyIndicator::setRunning(bool running)
emit runningChanged();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickBusyIndicator::accessibleRole() const
{
return QAccessible::Indicator;
diff --git a/src/quicktemplates2/qquickbusyindicator_p.h b/src/quicktemplates2/qquickbusyindicator_p.h
index 5beb2dbe..3607cc1f 100644
--- a/src/quicktemplates2/qquickbusyindicator_p.h
+++ b/src/quicktemplates2/qquickbusyindicator_p.h
@@ -69,7 +69,7 @@ Q_SIGNALS:
void runningChanged();
protected:
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquickbutton.cpp b/src/quicktemplates2/qquickbutton.cpp
index d1252afd..1a614754 100644
--- a/src/quicktemplates2/qquickbutton.cpp
+++ b/src/quicktemplates2/qquickbutton.cpp
@@ -80,18 +80,19 @@ QT_BEGIN_NAMESPACE
\sa {Customizing Button}, {Button Controls}
*/
-QQuickButtonPrivate::QQuickButtonPrivate() :
- flat(false), highlighted(false)
+QQuickButtonPrivate::QQuickButtonPrivate()
+ : flat(false),
+ highlighted(false)
{
}
-QQuickButton::QQuickButton(QQuickItem *parent) :
- QQuickAbstractButton(*(new QQuickButtonPrivate), parent)
+QQuickButton::QQuickButton(QQuickItem *parent)
+ : QQuickAbstractButton(*(new QQuickButtonPrivate), parent)
{
}
-QQuickButton::QQuickButton(QQuickButtonPrivate &dd, QQuickItem *parent) :
- QQuickAbstractButton(dd, parent)
+QQuickButton::QQuickButton(QQuickButtonPrivate &dd, QQuickItem *parent)
+ : QQuickAbstractButton(dd, parent)
{
}
@@ -106,9 +107,11 @@ QQuickButton::QQuickButton(QQuickButtonPrivate &dd, QQuickItem *parent) :
The default value is \c false.
*/
-void QQuickButton::autoRepeatChange()
+void QQuickButton::buttonChange(ButtonChange change)
{
- emit autoRepeatChanged();
+ QQuickAbstractButton::buttonChange(change);
+ if (change == ButtonAutoRepeatChange)
+ emit autoRepeatChanged();
}
QFont QQuickButton::defaultFont() const
diff --git a/src/quicktemplates2/qquickbutton_p.h b/src/quicktemplates2/qquickbutton_p.h
index be0b7bbd..93fb3c14 100644
--- a/src/quicktemplates2/qquickbutton_p.h
+++ b/src/quicktemplates2/qquickbutton_p.h
@@ -78,7 +78,7 @@ Q_SIGNALS:
protected:
QQuickButton(QQuickButtonPrivate &dd, QQuickItem *parent);
- void autoRepeatChange() override;
+ void buttonChange(ButtonChange change) override;
QFont defaultFont() const override;
diff --git a/src/quicktemplates2/qquickbuttongroup.cpp b/src/quicktemplates2/qquickbuttongroup.cpp
index ad813437..a9c0d435 100644
--- a/src/quicktemplates2/qquickbuttongroup.cpp
+++ b/src/quicktemplates2/qquickbuttongroup.cpp
@@ -371,8 +371,8 @@ public:
QQuickButtonGroup *group;
};
-QQuickButtonGroupAttached::QQuickButtonGroupAttached(QObject *parent) :
- QObject(*(new QQuickButtonGroupAttachedPrivate), parent)
+QQuickButtonGroupAttached::QQuickButtonGroupAttached(QObject *parent)
+ : QObject(*(new QQuickButtonGroupAttachedPrivate), parent)
{
}
diff --git a/src/quicktemplates2/qquickcheckbox.cpp b/src/quicktemplates2/qquickcheckbox.cpp
index 4cdfcd28..e0c7faf1 100644
--- a/src/quicktemplates2/qquickcheckbox.cpp
+++ b/src/quicktemplates2/qquickcheckbox.cpp
@@ -92,7 +92,8 @@ class QQuickCheckBoxPrivate : public QQuickAbstractButtonPrivate
public:
QQuickCheckBoxPrivate()
- : tristate(false), checkState(Qt::Unchecked)
+ : tristate(false),
+ checkState(Qt::Unchecked)
{
}
@@ -100,8 +101,8 @@ public:
Qt::CheckState checkState;
};
-QQuickCheckBox::QQuickCheckBox(QQuickItem *parent) :
- QQuickAbstractButton(*(new QQuickCheckBoxPrivate), parent)
+QQuickCheckBox::QQuickCheckBox(QQuickItem *parent)
+ : QQuickAbstractButton(*(new QQuickCheckBoxPrivate), parent)
{
setCheckable(true);
}
@@ -173,9 +174,12 @@ QFont QQuickCheckBox::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::CheckBoxFont);
}
-void QQuickCheckBox::checkStateSet()
+void QQuickCheckBox::buttonChange(ButtonChange change)
{
- setCheckState(isChecked() ? Qt::Checked : Qt::Unchecked);
+ if (change == ButtonCheckedChange)
+ setCheckState(isChecked() ? Qt::Checked : Qt::Unchecked);
+ else
+ QQuickAbstractButton::buttonChange(change);
}
void QQuickCheckBox::nextCheckState()
@@ -187,7 +191,7 @@ void QQuickCheckBox::nextCheckState()
QQuickAbstractButton::nextCheckState();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickCheckBox::accessibleRole() const
{
return QAccessible::CheckBox;
diff --git a/src/quicktemplates2/qquickcheckbox_p.h b/src/quicktemplates2/qquickcheckbox_p.h
index b736894c..dfd935d3 100644
--- a/src/quicktemplates2/qquickcheckbox_p.h
+++ b/src/quicktemplates2/qquickcheckbox_p.h
@@ -76,10 +76,10 @@ Q_SIGNALS:
protected:
QFont defaultFont() const override;
- void checkStateSet() override;
+ void buttonChange(ButtonChange change) override;
void nextCheckState() override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquickcheckdelegate.cpp b/src/quicktemplates2/qquickcheckdelegate.cpp
index a71cacbd..78d55e1d 100644
--- a/src/quicktemplates2/qquickcheckdelegate.cpp
+++ b/src/quicktemplates2/qquickcheckdelegate.cpp
@@ -89,7 +89,8 @@ class QQuickCheckDelegatePrivate : public QQuickItemDelegatePrivate
public:
QQuickCheckDelegatePrivate()
- : tristate(false), checkState(Qt::Unchecked)
+ : tristate(false),
+ checkState(Qt::Unchecked)
{
}
@@ -97,8 +98,8 @@ public:
Qt::CheckState checkState;
};
-QQuickCheckDelegate::QQuickCheckDelegate(QQuickItem *parent) :
- QQuickItemDelegate(*(new QQuickCheckDelegatePrivate), parent)
+QQuickCheckDelegate::QQuickCheckDelegate(QQuickItem *parent)
+ : QQuickItemDelegate(*(new QQuickCheckDelegatePrivate), parent)
{
setCheckable(true);
}
@@ -170,9 +171,12 @@ QFont QQuickCheckDelegate::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::ListViewFont);
}
-void QQuickCheckDelegate::checkStateSet()
+void QQuickCheckDelegate::buttonChange(ButtonChange change)
{
- setCheckState(isChecked() ? Qt::Checked : Qt::Unchecked);
+ if (change == ButtonCheckedChange)
+ setCheckState(isChecked() ? Qt::Checked : Qt::Unchecked);
+ else
+ QQuickAbstractButton::buttonChange(change);
}
void QQuickCheckDelegate::nextCheckState()
@@ -184,7 +188,7 @@ void QQuickCheckDelegate::nextCheckState()
QQuickItemDelegate::nextCheckState();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickCheckDelegate::accessibleRole() const
{
return QAccessible::CheckBox;
diff --git a/src/quicktemplates2/qquickcheckdelegate_p.h b/src/quicktemplates2/qquickcheckdelegate_p.h
index 3b8e7448..ae2b4f52 100644
--- a/src/quicktemplates2/qquickcheckdelegate_p.h
+++ b/src/quicktemplates2/qquickcheckdelegate_p.h
@@ -76,10 +76,10 @@ Q_SIGNALS:
protected:
QFont defaultFont() const override;
- void checkStateSet() override;
+ void buttonChange(ButtonChange change) override;
void nextCheckState() override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp
index 32a01b7b..95980e6b 100644
--- a/src/quicktemplates2/qquickcombobox.cpp
+++ b/src/quicktemplates2/qquickcombobox.cpp
@@ -41,11 +41,15 @@
#include <QtCore/qregexp.h>
#include <QtCore/qabstractitemmodel.h>
+#include <QtGui/qinputmethod.h>
+#include <QtGui/qguiapplication.h>
#include <QtGui/qpa/qplatformtheme.h>
#include <QtQml/qjsvalue.h>
#include <QtQml/qqmlcontext.h>
+#include <QtQml/private/qlazilyallocated_p.h>
#include <QtQml/private/qqmldelegatemodel_p.h>
#include <QtQuick/private/qquickevents_p_p.h>
+#include <QtQuick/private/qquicktextinput_p.h>
QT_BEGIN_NAMESPACE
@@ -74,6 +78,30 @@ QT_BEGIN_NAMESPACE
}
\endcode
+ \section1 Editable ComboBox
+
+ ComboBox can be made \l editable. An editable combo box auto-completes
+ its text based on what is available in the model.
+
+ The following example demonstrates appending content to an editable
+ combo box by reacting to the \l accepted signal.
+
+ \code
+ ComboBox {
+ editable: true
+ model: ListModel {
+ id: model
+ ListElement { text: "Banana" }
+ ListElement { text: "Apple" }
+ ListElement { text: "Coconut" }
+ }
+ onAccepted: {
+ if (find(editText) === -1)
+ model.append({text: editText})
+ }
+ }
+ \endcode
+
\section1 ComboBox Model Roles
ComboBox is able to visualize standard \l {qml-data-models}{data models}
@@ -130,6 +158,19 @@ QT_BEGIN_NAMESPACE
\sa highlightedIndex
*/
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlsignal void QtQuick.Controls::ComboBox::accepted()
+
+ This signal is emitted when the \uicontrol Return or \uicontrol Enter key is pressed
+ on an \l editable combo box. If the confirmed string is not currently in the model,
+ the \l currentIndex will be set to \c -1 and the \c currentText will be updated
+ accordingly.
+
+ \note If there is a \l validator set on the combo box, the signal will only be
+ emitted if the input is in an acceptable state.
+*/
+
namespace {
enum Activation { NoActivate, Activate };
enum Highlighting { NoHighlight, Highlight };
@@ -145,8 +186,9 @@ private:
QQuickComboBox *combo;
};
-QQuickComboBoxDelegateModel::QQuickComboBoxDelegateModel(QQuickComboBox *combo) :
- QQmlDelegateModel(qmlContext(combo), combo), combo(combo)
+QQuickComboBoxDelegateModel::QQuickComboBoxDelegateModel(QQuickComboBox *combo)
+ : QQmlDelegateModel(qmlContext(combo), combo),
+ combo(combo)
{
}
@@ -170,20 +212,26 @@ class QQuickComboBoxPrivate : public QQuickControlPrivate
Q_DECLARE_PUBLIC(QQuickComboBox)
public:
- QQuickComboBoxPrivate() : flat(false), pressed(false), ownModel(false), hasDisplayText(false), hasCurrentIndex(false),
- highlightedIndex(-1), currentIndex(-1), delegateModel(nullptr),
- delegate(nullptr), indicator(nullptr), popup(nullptr) { }
+ QQuickComboBoxPrivate();
bool isPopupVisible() const;
void showPopup();
void hidePopup(bool accept);
void togglePopup(bool accept);
+ void popupVisibleChanged();
void itemClicked();
void createdItem(int index, QObject *object);
+ void modelUpdated();
void countChanged();
+
+ void updateEditText();
void updateCurrentText();
+
+ void acceptInput();
+ QString tryComplete(const QString &inputText);
+
void incrementCurrentIndex();
void decrementCurrentIndex();
void setCurrentIndex(int index, Activation activate);
@@ -196,6 +244,8 @@ public:
void createDelegateModel();
bool flat;
+ bool down;
+ bool hasDown;
bool pressed;
bool ownModel;
bool hasDisplayText;
@@ -211,8 +261,42 @@ public:
QQmlComponent *delegate;
QQuickItem *indicator;
QQuickPopup *popup;
+
+ struct ExtraData {
+ ExtraData()
+ : editable(false),
+ accepting(false),
+ allowComplete(false),
+ inputMethodHints(Qt::ImhNone),
+ validator(nullptr) { }
+
+ bool editable;
+ bool accepting;
+ bool allowComplete;
+ Qt::InputMethodHints inputMethodHints;
+ QString editText;
+ QValidator *validator;
+ };
+ QLazilyAllocated<ExtraData> extra;
};
+QQuickComboBoxPrivate::QQuickComboBoxPrivate()
+ : flat(false),
+ down(false),
+ hasDown(false),
+ pressed(false),
+ ownModel(false),
+ hasDisplayText(false),
+ hasCurrentIndex(false),
+ highlightedIndex(-1),
+ currentIndex(-1),
+ delegateModel(nullptr),
+ delegate(nullptr),
+ indicator(nullptr),
+ popup(nullptr)
+{
+}
+
bool QQuickComboBoxPrivate::isPopupVisible() const
{
return popup && popup->isVisible();
@@ -246,6 +330,19 @@ void QQuickComboBoxPrivate::togglePopup(bool accept)
showPopup();
}
+void QQuickComboBoxPrivate::popupVisibleChanged()
+{
+ Q_Q(QQuickComboBox);
+ if (isPopupVisible())
+ QGuiApplication::inputMethod()->reset();
+
+ updateHighlightedIndex();
+ if (!hasDown) {
+ q->setDown(pressed || isPopupVisible());
+ hasDown = false;
+ }
+}
+
void QQuickComboBoxPrivate::itemClicked()
{
Q_Q(QQuickComboBox);
@@ -258,13 +355,26 @@ void QQuickComboBoxPrivate::itemClicked()
void QQuickComboBoxPrivate::createdItem(int index, QObject *object)
{
+ Q_Q(QQuickComboBox);
+ QQuickItem *item = qobject_cast<QQuickItem *>(object);
+ if (popup && item && !item->parentItem()) {
+ item->setParentItem(popup->contentItem());
+ QQuickItemPrivate::get(item)->setCulled(true);
+ }
+
QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton *>(object);
if (button) {
button->setFocusPolicy(Qt::NoFocus);
connect(button, &QQuickAbstractButton::clicked, this, &QQuickComboBoxPrivate::itemClicked);
}
- if (index == currentIndex)
+ if (index == currentIndex && !q->isEditable())
+ updateCurrentText();
+}
+
+void QQuickComboBoxPrivate::modelUpdated()
+{
+ if (!extra.isAllocated() || !extra->accepting)
updateCurrentText();
}
@@ -276,6 +386,26 @@ void QQuickComboBoxPrivate::countChanged()
emit q->countChanged();
}
+void QQuickComboBoxPrivate::updateEditText()
+{
+ Q_Q(QQuickComboBox);
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(contentItem);
+ if (!input)
+ return;
+
+ const QString text = input->text();
+
+ if (extra.isAllocated() && extra->allowComplete && !text.isEmpty()) {
+ const QString completed = tryComplete(text);
+ if (completed.length() > text.length()) {
+ input->setText(completed);
+ input->select(completed.length(), text.length());
+ return;
+ }
+ }
+ q->setEditText(text);
+}
+
void QQuickComboBoxPrivate::updateCurrentText()
{
Q_Q(QQuickComboBox);
@@ -290,6 +420,45 @@ void QQuickComboBoxPrivate::updateCurrentText()
displayText = text;
emit q->displayTextChanged();
}
+ if (!extra.isAllocated() || !extra->accepting)
+ q->setEditText(currentText);
+}
+
+void QQuickComboBoxPrivate::acceptInput()
+{
+ Q_Q(QQuickComboBox);
+ int idx = q->find(extra.value().editText, Qt::MatchFixedString);
+ if (idx > -1)
+ q->setCurrentIndex(idx);
+
+ extra.value().accepting = true;
+ emit q->accepted();
+
+ if (idx == -1)
+ q->setCurrentIndex(q->find(extra.value().editText, Qt::MatchFixedString));
+ extra.value().accepting = false;
+}
+
+QString QQuickComboBoxPrivate::tryComplete(const QString &input)
+{
+ Q_Q(QQuickComboBox);
+ QString match;
+
+ const int itemCount = q->count();
+ for (int idx = 0; idx < itemCount; ++idx) {
+ const QString text = q->textAt(idx);
+ if (!text.startsWith(input, Qt::CaseInsensitive))
+ continue;
+
+ // either the first or the shortest match
+ if (match.isEmpty() || text.length() < match.length())
+ match = text;
+ }
+
+ if (match.isEmpty())
+ return input;
+
+ return input + match.mid(input.length());
}
void QQuickComboBoxPrivate::setCurrentIndex(int index, Activation activate)
@@ -311,6 +480,8 @@ void QQuickComboBoxPrivate::setCurrentIndex(int index, Activation activate)
void QQuickComboBoxPrivate::incrementCurrentIndex()
{
Q_Q(QQuickComboBox);
+ if (extra.isAllocated())
+ extra->allowComplete = false;
if (isPopupVisible()) {
if (highlightedIndex < q->count() - 1)
setHighlightedIndex(highlightedIndex + 1, Highlight);
@@ -318,10 +489,14 @@ void QQuickComboBoxPrivate::incrementCurrentIndex()
if (currentIndex < q->count() - 1)
setCurrentIndex(currentIndex + 1, Activate);
}
+ if (extra.isAllocated())
+ extra->allowComplete = true;
}
void QQuickComboBoxPrivate::decrementCurrentIndex()
{
+ if (extra.isAllocated())
+ extra->allowComplete = false;
if (isPopupVisible()) {
if (highlightedIndex > 0)
setHighlightedIndex(highlightedIndex - 1, Highlight);
@@ -329,6 +504,8 @@ void QQuickComboBoxPrivate::decrementCurrentIndex()
if (currentIndex > 0)
setCurrentIndex(currentIndex - 1, Activate);
}
+ if (extra.isAllocated())
+ extra->allowComplete = true;
}
void QQuickComboBoxPrivate::updateHighlightedIndex()
@@ -415,7 +592,7 @@ void QQuickComboBoxPrivate::createDelegateModel()
QQmlInstanceModel* oldModel = delegateModel;
if (oldModel) {
disconnect(delegateModel, &QQmlInstanceModel::countChanged, this, &QQuickComboBoxPrivate::countChanged);
- disconnect(delegateModel, &QQmlInstanceModel::modelUpdated, this, &QQuickComboBoxPrivate::updateCurrentText);
+ disconnect(delegateModel, &QQmlInstanceModel::modelUpdated, this, &QQuickComboBoxPrivate::modelUpdated);
disconnect(delegateModel, &QQmlInstanceModel::createdItem, this, &QQuickComboBoxPrivate::createdItem);
}
@@ -435,7 +612,7 @@ void QQuickComboBoxPrivate::createDelegateModel()
if (delegateModel) {
connect(delegateModel, &QQmlInstanceModel::countChanged, this, &QQuickComboBoxPrivate::countChanged);
- connect(delegateModel, &QQmlInstanceModel::modelUpdated, this, &QQuickComboBoxPrivate::updateCurrentText);
+ connect(delegateModel, &QQmlInstanceModel::modelUpdated, this, &QQuickComboBoxPrivate::modelUpdated);
connect(delegateModel, &QQmlInstanceModel::createdItem, this, &QQuickComboBoxPrivate::createdItem);
}
@@ -445,12 +622,13 @@ void QQuickComboBoxPrivate::createDelegateModel()
delete oldModel;
}
-QQuickComboBox::QQuickComboBox(QQuickItem *parent) :
- QQuickControl(*(new QQuickComboBoxPrivate), parent)
+QQuickComboBox::QQuickComboBox(QQuickItem *parent)
+ : QQuickControl(*(new QQuickComboBoxPrivate), parent)
{
setFocusPolicy(Qt::StrongFocus);
setFlag(QQuickItem::ItemIsFocusScope);
setAcceptedMouseButtons(Qt::LeftButton);
+ setInputMethodHints(Qt::ImhNoPredictiveText);
}
QQuickComboBox::~QQuickComboBox()
@@ -533,6 +711,48 @@ QQmlInstanceModel *QQuickComboBox::delegateModel() const
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::ComboBox::editable
+
+ This property holds whether the combo box is editable.
+
+ The default value is \c false.
+
+ \sa validator
+*/
+bool QQuickComboBox::isEditable() const
+{
+ Q_D(const QQuickComboBox);
+ return d->extra.isAllocated() && d->extra->editable;
+}
+
+void QQuickComboBox::setEditable(bool editable)
+{
+ Q_D(QQuickComboBox);
+ if (editable == isEditable())
+ return;
+
+ if (d->contentItem) {
+ if (editable) {
+ d->contentItem->installEventFilter(this);
+ if (QQuickTextInput *input = qobject_cast<QQuickTextInput *>(d->contentItem)) {
+ QObjectPrivate::connect(input, &QQuickTextInput::textChanged, d, &QQuickComboBoxPrivate::updateEditText);
+ QObjectPrivate::connect(input, &QQuickTextInput::accepted, d, &QQuickComboBoxPrivate::acceptInput);
+ }
+ } else {
+ d->contentItem->removeEventFilter(this);
+ if (QQuickTextInput *input = qobject_cast<QQuickTextInput *>(d->contentItem)) {
+ QObjectPrivate::disconnect(input, &QQuickTextInput::textChanged, d, &QQuickComboBoxPrivate::updateEditText);
+ QObjectPrivate::disconnect(input, &QQuickTextInput::accepted, d, &QQuickComboBoxPrivate::acceptInput);
+ }
+ }
+ }
+
+ d->extra.value().editable = editable;
+ emit editableChanged();
+}
+
+/*!
\since QtQuick.Controls 2.1
\qmlproperty bool QtQuick.Controls::ComboBox::flat
@@ -563,9 +783,52 @@ void QQuickComboBox::setFlat(bool flat)
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::ComboBox::down
+
+ This property holds whether the combo box button is visually down.
+
+ Unless explicitly set, this property is \c true when either \c pressed
+ or \c popup.visible is \c true. To return to the default value, set this
+ property to \c undefined.
+
+ \sa pressed, popup
+*/
+bool QQuickComboBox::isDown() const
+{
+ Q_D(const QQuickComboBox);
+ return d->down;
+}
+
+void QQuickComboBox::setDown(bool down)
+{
+ Q_D(QQuickComboBox);
+ d->hasDown = true;
+
+ if (d->down == down)
+ return;
+
+ d->down = down;
+ emit downChanged();
+}
+
+void QQuickComboBox::resetDown()
+{
+ Q_D(QQuickComboBox);
+ if (!d->hasDown)
+ return;
+
+ setDown(d->pressed || d->isPopupVisible());
+ d->hasDown = false;
+}
+
+/*!
\qmlproperty bool QtQuick.Controls::ComboBox::pressed
- This property holds whether the combo box button is pressed.
+ This property holds whether the combo box button is physically pressed.
+ A button can be pressed by either touch or key events.
+
+ \sa down
*/
bool QQuickComboBox::isPressed() const
{
@@ -581,6 +844,11 @@ void QQuickComboBox::setPressed(bool pressed)
d->pressed = pressed;
emit pressedChanged();
+
+ if (!d->hasDown) {
+ setDown(d->pressed || d->isPopupVisible());
+ d->hasDown = false;
+ }
}
/*!
@@ -683,6 +951,35 @@ void QQuickComboBox::resetDisplayText()
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty string QtQuick.Controls::ComboBox::editText
+
+ This property holds the text in the text field of an editable combo box.
+
+ \sa editable
+*/
+QString QQuickComboBox::editText() const
+{
+ Q_D(const QQuickComboBox);
+ return d->extra.isAllocated() ? d->extra->editText : QString();
+}
+
+void QQuickComboBox::setEditText(const QString &text)
+{
+ Q_D(QQuickComboBox);
+ if (text == editText())
+ return;
+
+ d->extra.value().editText = text;
+ emit editTextChanged();
+}
+
+void QQuickComboBox::resetEditText()
+{
+ setEditText(QString());
+}
+
+/*!
\qmlproperty string QtQuick.Controls::ComboBox::textRole
This property holds the model role used for populating the combo box.
@@ -772,7 +1069,7 @@ void QQuickComboBox::setIndicator(QQuickItem *indicator)
if (d->indicator == indicator)
return;
- d->deleteDelegate(d->indicator);
+ QQuickControlPrivate::destroyDelegate(d->indicator, this);
d->indicator = indicator;
if (indicator) {
if (!indicator->parentItem())
@@ -806,19 +1103,129 @@ void QQuickComboBox::setPopup(QQuickPopup *popup)
if (d->popup == popup)
return;
- if (d->popup)
- QObjectPrivate::disconnect(d->popup, &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::updateHighlightedIndex);
- d->deleteDelegate(d->popup);
+ if (d->popup) {
+ QObjectPrivate::disconnect(d->popup, &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::popupVisibleChanged);
+ QQuickControlPrivate::destroyDelegate(d->popup, this);
+ }
if (popup) {
QQuickPopupPrivate::get(popup)->allowVerticalFlip = true;
popup->setClosePolicy(QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutsideParent);
- QObjectPrivate::connect(popup, &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::updateHighlightedIndex);
+ QObjectPrivate::connect(popup, &QQuickPopup::visibleChanged, d, &QQuickComboBoxPrivate::popupVisibleChanged);
}
d->popup = popup;
emit popupChanged();
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty Validator QtQuick.Controls::ComboBox::validator
+
+ This property holds an input text validator for an editable combo box.
+
+ When a validator is set, the text field will only accept input which
+ leaves the text property in an intermediate state. The \l accepted signal
+ will only be emitted if the text is in an acceptable state when the
+ \uicontrol Return or \uicontrol Enter key is pressed.
+
+ The currently supported validators are \l[QtQuick]{IntValidator},
+ \l[QtQuick]{DoubleValidator}, and \l[QtQuick]{RegExpValidator}. An
+ example of using validators is shown below, which allows input of
+ integers between \c 0 and \c 10 into the text field:
+
+ \code
+ ComboBox {
+ model: 10
+ editable: true
+ validator: IntValidator {
+ top: 9
+ bottom: 0
+ }
+ }
+ \endcode
+
+ \sa acceptableInput, accepted, editable
+*/
+QValidator *QQuickComboBox::validator() const
+{
+ Q_D(const QQuickComboBox);
+ return d->extra.isAllocated() ? d->extra->validator : nullptr;
+}
+
+void QQuickComboBox::setValidator(QValidator *validator)
+{
+ Q_D(QQuickComboBox);
+ if (validator == QQuickComboBox::validator())
+ return;
+
+ d->extra.value().validator = validator;
+ if (validator)
+ validator->setLocale(d->locale);
+ emit validatorChanged();
+}
+
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty flags QtQuick.Controls::ComboBox::inputMethodHints
+
+ Provides hints to the input method about the expected content of the combo box and how it
+ should operate.
+
+ The default value is \c Qt.ImhNoPredictiveText.
+
+ \include inputmethodhints.qdocinc
+*/
+Qt::InputMethodHints QQuickComboBox::inputMethodHints() const
+{
+ Q_D(const QQuickComboBox);
+ return d->extra.isAllocated() ? d->extra->inputMethodHints : Qt::ImhNoPredictiveText;
+}
+
+void QQuickComboBox::setInputMethodHints(Qt::InputMethodHints hints)
+{
+ Q_D(QQuickComboBox);
+ if (hints == inputMethodHints())
+ return;
+
+ d->extra.value().inputMethodHints = hints;
+ emit inputMethodHintsChanged();
+}
+
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::ComboBox::inputMethodComposing
+ \readonly
+
+ This property holds whether an editable combo box has partial text input from an input method.
+
+ While it is composing, an input method may rely on mouse or key events from the combo box to
+ edit or commit the partial text. This property can be used to determine when to disable event
+ handlers that may interfere with the correct operation of an input method.
+*/
+bool QQuickComboBox::isInputMethodComposing() const
+{
+ Q_D(const QQuickComboBox);
+ return d->contentItem && d->contentItem->property("inputMethodComposing").toBool();
+}
+
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::ComboBox::acceptableInput
+ \readonly
+
+ This property holds whether the combo box contains acceptable text in the editable text field.
+
+ If a validator has been set, the value is \c true only if the current text is acceptable
+ to the validator as a final string (not as an intermediate string).
+
+ \sa validator, accepted
+*/
+bool QQuickComboBox::hasAcceptableInput() const
+{
+ Q_D(const QQuickComboBox);
+ return d->contentItem && d->contentItem->property("acceptableInput").toBool();
+}
+
+/*!
\qmlmethod string QtQuick.Controls::ComboBox::textAt(int index)
Returns the text for the specified \a index, or an empty string
@@ -895,6 +1302,61 @@ void QQuickComboBox::decrementCurrentIndex()
d->decrementCurrentIndex();
}
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlmethod void QtQuick.Controls::ComboBox::selectAll()
+
+ Selects all the text in the editable text field of the combo box.
+
+ \sa editText
+*/
+void QQuickComboBox::selectAll()
+{
+ Q_D(QQuickComboBox);
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(d->contentItem);
+ if (!input)
+ return;
+ input->selectAll();
+}
+
+bool QQuickComboBox::eventFilter(QObject *object, QEvent *event)
+{
+ Q_D(QQuickComboBox);
+ switch (event->type()) {
+ case QEvent::MouseButtonRelease:
+ if (d->isPopupVisible())
+ d->hidePopup(false);
+ break;
+ case QEvent::KeyPress: {
+ const int key = static_cast<QKeyEvent *>(event)->key();
+ if (d->extra.isAllocated())
+ d->extra->allowComplete = key != Qt::Key_Backspace && key != Qt::Key_Delete;
+ break;
+ }
+ case QEvent::FocusOut:
+ d->hidePopup(false);
+ setPressed(false);
+ break;
+#if QT_CONFIG(im)
+ case QEvent::InputMethod:
+ if (d->extra.isAllocated())
+ d->extra->allowComplete = !static_cast<QInputMethodEvent*>(event)->commitString().isEmpty();
+ break;
+#endif
+ default:
+ break;
+ }
+ return QQuickControl::eventFilter(object, event);
+}
+
+void QQuickComboBox::focusInEvent(QFocusEvent *event)
+{
+ Q_D(QQuickComboBox);
+ QQuickControl::focusInEvent(event);
+ if (d->contentItem && isEditable())
+ d->contentItem->forceActiveFocus(event->reason());
+}
+
void QQuickComboBox::focusOutEvent(QFocusEvent *event)
{
Q_D(QQuickComboBox);
@@ -903,6 +1365,18 @@ void QQuickComboBox::focusOutEvent(QFocusEvent *event)
setPressed(false);
}
+#if QT_CONFIG(im)
+void QQuickComboBox::inputMethodEvent(QInputMethodEvent *event)
+{
+ Q_D(QQuickComboBox);
+ QQuickControl::inputMethodEvent(event);
+ if (!isEditable() && !event->commitString().isEmpty())
+ d->keySearch(event->commitString());
+ else
+ event->ignore();
+}
+#endif
+
void QQuickComboBox::keyPressEvent(QKeyEvent *event)
{
Q_D(QQuickComboBox);
@@ -948,7 +1422,7 @@ void QQuickComboBox::keyPressEvent(QKeyEvent *event)
event->accept();
break;
default:
- if (!event->text().isEmpty())
+ if (!isEditable() && !event->text().isEmpty())
d->keySearch(event->text());
else
event->ignore();
@@ -965,13 +1439,15 @@ void QQuickComboBox::keyReleaseEvent(QKeyEvent *event)
switch (event->key()) {
case Qt::Key_Space:
- d->togglePopup(true);
+ if (!isEditable())
+ d->togglePopup(true);
setPressed(false);
event->accept();
break;
case Qt::Key_Enter:
case Qt::Key_Return:
- d->hidePopup(d->isPopupVisible());
+ if (!isEditable() || d->isPopupVisible())
+ d->hidePopup(d->isPopupVisible());
setPressed(false);
event->accept();
break;
@@ -1014,6 +1490,7 @@ void QQuickComboBox::mouseUngrabEvent()
setPressed(false);
}
+#if QT_CONFIG(wheelevent)
void QQuickComboBox::wheelEvent(QWheelEvent *event)
{
Q_D(QQuickComboBox);
@@ -1027,6 +1504,7 @@ void QQuickComboBox::wheelEvent(QWheelEvent *event)
event->setAccepted(d->currentIndex != oldIndex);
}
}
+#endif
void QQuickComboBox::componentComplete()
{
@@ -1044,12 +1522,42 @@ void QQuickComboBox::componentComplete()
}
}
+void QQuickComboBox::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
+{
+ Q_D(QQuickComboBox);
+ if (oldItem) {
+ oldItem->removeEventFilter(this);
+ if (QQuickTextInput *oldInput = qobject_cast<QQuickTextInput *>(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);
+ }
+ }
+ if (newItem && isEditable()) {
+ newItem->installEventFilter(this);
+ if (QQuickTextInput *newInput = qobject_cast<QQuickTextInput *>(newItem)) {
+ 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);
+ }
+ }
+}
+
+void QQuickComboBox::localeChange(const QLocale &newLocale, const QLocale &oldLocale)
+{
+ QQuickControl::localeChange(newLocale, oldLocale);
+ if (QValidator *v = validator())
+ v->setLocale(newLocale);
+}
+
QFont QQuickComboBox::defaultFont() const
{
return QQuickControlPrivate::themeFont(QPlatformTheme::ComboMenuItemFont);
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickComboBox::accessibleRole() const
{
return QAccessible::ComboBox;
@@ -1063,6 +1571,6 @@ void QQuickComboBox::accessibilityActiveChanged(bool active)
if (active)
setAccessibleName(d->hasDisplayText ? d->displayText : d->currentText);
}
-#endif // QT_NO_ACCESSIBILITY
+#endif //
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickcombobox_p.h b/src/quicktemplates2/qquickcombobox_p.h
index 4fda8cce..76dce2d5 100644
--- a/src/quicktemplates2/qquickcombobox_p.h
+++ b/src/quicktemplates2/qquickcombobox_p.h
@@ -52,6 +52,7 @@
QT_BEGIN_NAMESPACE
+class QValidator;
class QQuickPopup;
class QQmlInstanceModel;
class QQuickComboBoxPrivate;
@@ -62,16 +63,23 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickComboBox : public QQuickControl
Q_PROPERTY(int count READ count NOTIFY countChanged FINAL)
Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged FINAL)
Q_PROPERTY(QQmlInstanceModel *delegateModel READ delegateModel NOTIFY delegateModelChanged FINAL)
+ Q_PROPERTY(bool editable READ isEditable WRITE setEditable NOTIFY editableChanged FINAL REVISION 2)
Q_PROPERTY(bool flat READ isFlat WRITE setFlat NOTIFY flatChanged FINAL REVISION 1)
- Q_PROPERTY(bool pressed READ isPressed WRITE setPressed NOTIFY pressedChanged FINAL)
+ Q_PROPERTY(bool down READ isDown WRITE setDown RESET resetDown NOTIFY downChanged FINAL REVISION 2)
+ Q_PROPERTY(bool pressed READ isPressed WRITE setPressed NOTIFY pressedChanged FINAL) // ### Qt 6: should not be writable
Q_PROPERTY(int highlightedIndex READ highlightedIndex NOTIFY highlightedIndexChanged FINAL)
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged FINAL)
Q_PROPERTY(QString currentText READ currentText NOTIFY currentTextChanged FINAL)
Q_PROPERTY(QString displayText READ displayText WRITE setDisplayText RESET resetDisplayText NOTIFY displayTextChanged FINAL)
+ Q_PROPERTY(QString editText READ editText WRITE setEditText RESET resetEditText NOTIFY editTextChanged FINAL REVISION 2)
Q_PROPERTY(QString textRole READ textRole WRITE setTextRole NOTIFY textRoleChanged FINAL)
Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged FINAL)
Q_PROPERTY(QQuickItem *indicator READ indicator WRITE setIndicator NOTIFY indicatorChanged FINAL)
Q_PROPERTY(QQuickPopup *popup READ popup WRITE setPopup NOTIFY popupChanged FINAL)
+ Q_PROPERTY(QValidator *validator READ validator WRITE setValidator NOTIFY validatorChanged FINAL REVISION 2)
+ Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints NOTIFY inputMethodHintsChanged FINAL REVISION 2)
+ Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged FINAL REVISION 2)
+ Q_PROPERTY(bool acceptableInput READ hasAcceptableInput NOTIFY acceptableInputChanged FINAL REVISION 2)
public:
explicit QQuickComboBox(QQuickItem *parent = nullptr);
@@ -83,9 +91,16 @@ public:
void setModel(const QVariant &model);
QQmlInstanceModel *delegateModel() const;
+ bool isEditable() const;
+ void setEditable(bool editable);
+
bool isFlat() const;
void setFlat(bool flat);
+ bool isDown() const;
+ void setDown(bool down);
+ void resetDown();
+
bool isPressed() const;
void setPressed(bool pressed);
@@ -100,6 +115,10 @@ public:
void setDisplayText(const QString &text);
void resetDisplayText();
+ QString editText() const;
+ void setEditText(const QString &text);
+ void resetEditText();
+
QString textRole() const;
void setTextRole(const QString &role);
@@ -112,46 +131,73 @@ public:
QQuickPopup *popup() const;
void setPopup(QQuickPopup *popup);
+ QValidator *validator() const;
+ void setValidator(QValidator *validator);
+
+ Qt::InputMethodHints inputMethodHints() const;
+ void setInputMethodHints(Qt::InputMethodHints hints);
+
+ bool isInputMethodComposing() const;
+ bool hasAcceptableInput() const;
+
Q_INVOKABLE QString textAt(int index) const;
Q_INVOKABLE int find(const QString &text, Qt::MatchFlags flags = Qt::MatchExactly) const;
public Q_SLOTS:
void incrementCurrentIndex();
void decrementCurrentIndex();
+ Q_REVISION(2) void selectAll();
Q_SIGNALS:
void countChanged();
void modelChanged();
void delegateModelChanged();
+ Q_REVISION(2) void editableChanged();
Q_REVISION(1) void flatChanged();
+ Q_REVISION(2) void downChanged();
void pressedChanged();
void highlightedIndexChanged();
void currentIndexChanged();
void currentTextChanged();
void displayTextChanged();
+ Q_REVISION(2) void editTextChanged();
void textRoleChanged();
void delegateChanged();
void indicatorChanged();
void popupChanged();
+ Q_REVISION(2) void validatorChanged();
+ Q_REVISION(2) void inputMethodHintsChanged();
+ Q_REVISION(2) void inputMethodComposingChanged();
+ Q_REVISION(2) void acceptableInputChanged();
void activated(int index);
void highlighted(int index);
+ Q_REVISION(2) void accepted();
protected:
+ bool eventFilter(QObject *object, QEvent *event) override;
+ void focusInEvent(QFocusEvent *event) override;
void focusOutEvent(QFocusEvent *event) override;
+#if QT_CONFIG(im)
+ void inputMethodEvent(QInputMethodEvent *event) override;
+#endif
void keyPressEvent(QKeyEvent *event) override;
void keyReleaseEvent(QKeyEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseUngrabEvent() override;
+#if QT_CONFIG(wheelevent)
void wheelEvent(QWheelEvent *event) override;
+#endif
void componentComplete() override;
+ void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override;
+ void localeChange(const QLocale &newLocale, const QLocale &oldLocale) override;
QFont defaultFont() const override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
void accessibilityActiveChanged(bool active) override;
#endif
diff --git a/src/quicktemplates2/qquickcontainer.cpp b/src/quicktemplates2/qquickcontainer.cpp
index 65ec2693..6777fa5d 100644
--- a/src/quicktemplates2/qquickcontainer.cpp
+++ b/src/quicktemplates2/qquickcontainer.cpp
@@ -144,8 +144,11 @@ static QQuickItem *effectiveContentItem(QQuickItem *item)
return item;
}
-QQuickContainerPrivate::QQuickContainerPrivate() : contentModel(nullptr), currentIndex(-1), updatingCurrent(false),
- changeTypes(Destroyed | Parent | SiblingOrder)
+QQuickContainerPrivate::QQuickContainerPrivate()
+ : contentModel(nullptr),
+ currentIndex(-1),
+ updatingCurrent(false),
+ changeTypes(Destroyed | Parent | SiblingOrder)
{
}
@@ -352,15 +355,15 @@ void QQuickContainerPrivate::contentChildren_clear(QQmlListProperty<QQuickItem>
p->contentModel->clear();
}
-QQuickContainer::QQuickContainer(QQuickItem *parent) :
- QQuickControl(*(new QQuickContainerPrivate), parent)
+QQuickContainer::QQuickContainer(QQuickItem *parent)
+ : QQuickControl(*(new QQuickContainerPrivate), parent)
{
Q_D(QQuickContainer);
d->init();
}
-QQuickContainer::QQuickContainer(QQuickContainerPrivate &dd, QQuickItem *parent) :
- QQuickControl(dd, parent)
+QQuickContainer::QQuickContainer(QQuickContainerPrivate &dd, QQuickItem *parent)
+ : QQuickControl(dd, parent)
{
Q_D(QQuickContainer);
d->init();
diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp
index a8f4b952..be050c76 100644
--- a/src/quicktemplates2/qquickcontrol.cpp
+++ b/src/quicktemplates2/qquickcontrol.cpp
@@ -46,13 +46,14 @@
#include "qquicktextfield_p.h"
#include "qquicktextfield_p_p.h"
#include "qquickpopup_p.h"
-#include "qquickpopup_p_p.h"
+#include "qquickpopupitem_p_p.h"
#include "qquickapplicationwindow_p.h"
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/qpa/qplatformtheme.h>
+#include <QtQml/private/qqmlincubator_p.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <QtQuick/private/qquickaccessibleattached_p.h>
#endif
@@ -108,21 +109,37 @@ QQuickControlPrivate::ExtraData::ExtraData()
{
}
-QQuickControlPrivate::QQuickControlPrivate() :
- hasTopPadding(false), hasLeftPadding(false), hasRightPadding(false), hasBottomPadding(false),
- hasLocale(false), hovered(false), wheelEnabled(false), explicitHoverEnabled(false),
- padding(0), topPadding(0), leftPadding(0), rightPadding(0), bottomPadding(0), spacing(0),
- focusPolicy(Qt::NoFocus), focusReason(Qt::OtherFocusReason),
- background(nullptr), contentItem(nullptr), accessibleAttached(nullptr)
-{
-#ifndef QT_NO_ACCESSIBILITY
+QQuickControlPrivate::QQuickControlPrivate()
+ : hasTopPadding(false),
+ hasLeftPadding(false),
+ hasRightPadding(false),
+ hasBottomPadding(false),
+ hasLocale(false),
+ wheelEnabled(false),
+#if QT_CONFIG(quicktemplates2_hover)
+ hovered(false),
+ explicitHoverEnabled(false),
+#endif
+ padding(0),
+ topPadding(0),
+ leftPadding(0),
+ rightPadding(0),
+ bottomPadding(0),
+ spacing(0),
+ focusPolicy(Qt::NoFocus),
+ focusReason(Qt::OtherFocusReason),
+ background(nullptr),
+ contentItem(nullptr),
+ accessibleAttached(nullptr)
+{
+#if QT_CONFIG(accessibility)
QAccessible::installActivationObserver(this);
#endif
}
QQuickControlPrivate::~QQuickControlPrivate()
{
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::removeActivationObserver(this);
#endif
}
@@ -220,7 +237,7 @@ QQuickItem *QQuickControlPrivate::getContentItem()
return contentItem;
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
void QQuickControlPrivate::accessibilityActiveChanged(bool active)
{
Q_Q(QQuickControl);
@@ -362,6 +379,7 @@ void QQuickControlPrivate::updateFontRecur(QQuickItem *item, const QFont &f)
}
}
+#if QT_CONFIG(quicktemplates2_hover)
void QQuickControlPrivate::updateHoverEnabled(bool enabled, bool xplicit)
{
Q_Q(QQuickControl);
@@ -417,10 +435,11 @@ bool QQuickControlPrivate::calcHoverEnabled(const QQuickItem *item)
return QGuiApplication::styleHints()->useHoverEffects();
}
+#endif
QString QQuickControl::accessibleName() const
{
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
Q_D(const QQuickControl);
if (d->accessibleAttached)
return d->accessibleAttached->name();
@@ -430,7 +449,7 @@ QString QQuickControl::accessibleName() const
void QQuickControl::setAccessibleName(const QString &name)
{
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
Q_D(QQuickControl);
if (d->accessibleAttached)
d->accessibleAttached->setName(name);
@@ -441,7 +460,7 @@ void QQuickControl::setAccessibleName(const QString &name)
QVariant QQuickControl::accessibleProperty(const char *propertyName)
{
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
Q_D(QQuickControl);
if (d->accessibleAttached)
return QQuickAccessibleAttached::property(this, propertyName);
@@ -452,7 +471,7 @@ QVariant QQuickControl::accessibleProperty(const char *propertyName)
bool QQuickControl::setAccessibleProperty(const char *propertyName, const QVariant &value)
{
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
Q_D(QQuickControl);
if (d->accessibleAttached)
return QQuickAccessibleAttached::setProperty(this, propertyName, value);
@@ -462,13 +481,13 @@ bool QQuickControl::setAccessibleProperty(const char *propertyName, const QVaria
return false;
}
-QQuickControl::QQuickControl(QQuickItem *parent) :
- QQuickItem(*(new QQuickControlPrivate), parent)
+QQuickControl::QQuickControl(QQuickItem *parent)
+ : QQuickItem(*(new QQuickControlPrivate), parent)
{
}
-QQuickControl::QQuickControl(QQuickControlPrivate &dd, QQuickItem *parent) :
- QQuickItem(dd, parent)
+QQuickControl::QQuickControl(QQuickControlPrivate &dd, QQuickItem *parent)
+ : QQuickItem(dd, parent)
{
}
@@ -478,16 +497,20 @@ void QQuickControl::itemChange(QQuickItem::ItemChange change, const QQuickItem::
QQuickItem::itemChange(change, value);
switch (change) {
case ItemVisibleHasChanged:
+#if QT_CONFIG(quicktemplates2_hover)
if (!value.boolValue)
setHovered(false);
+#endif
break;
case ItemParentHasChanged:
if (value.item) {
d->resolveFont();
if (!d->hasLocale)
d->updateLocale(QQuickControlPrivate::calcLocale(d->parentItem), false); // explicit=false
+#if QT_CONFIG(quicktemplates2_hover)
if (!d->explicitHoverEnabled)
d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
+#endif
}
break;
case ItemActiveFocusHasChanged:
@@ -843,15 +866,13 @@ QLocale QQuickControlPrivate::calcLocale(const QQuickItem *item)
}
/*
- Deletes "delegate" if Component.completed() has been emitted,
- otherwise stores it in pendingDeletions.
+ Cancels incubation to avoid "Object destroyed during incubation" (QTBUG-50992)
*/
-void QQuickControlPrivate::deleteDelegate(QObject *delegate)
+void QQuickControlPrivate::destroyDelegate(QObject *delegate, QObject *parent)
{
- if (componentComplete)
- delete delegate;
- else if (delegate)
- extra.value().pendingDeletions.append(delegate);
+ if (delegate && parent)
+ QQmlIncubatorPrivate::cancel(delegate, qmlContext(parent));
+ delete delegate;
}
void QQuickControlPrivate::updateLocale(const QLocale &l, bool e)
@@ -991,12 +1012,17 @@ bool QQuickControl::hasVisualFocus() const
*/
bool QQuickControl::isHovered() const
{
+#if QT_CONFIG(quicktemplates2_hover)
Q_D(const QQuickControl);
return d->hovered;
+#else
+ return false;
+#endif
}
void QQuickControl::setHovered(bool hovered)
{
+#if QT_CONFIG(quicktemplates2_hover)
Q_D(QQuickControl);
if (hovered == d->hovered)
return;
@@ -1004,6 +1030,9 @@ void QQuickControl::setHovered(bool hovered)
d->hovered = hovered;
emit hoveredChanged();
hoverChange();
+#else
+ Q_UNUSED(hovered);
+#endif
}
/*!
@@ -1023,27 +1052,37 @@ void QQuickControl::setHovered(bool hovered)
*/
bool QQuickControl::isHoverEnabled() const
{
+#if QT_CONFIG(quicktemplates2_hover)
Q_D(const QQuickControl);
return d->hoverEnabled;
+#else
+ return false;
+#endif
}
void QQuickControl::setHoverEnabled(bool enabled)
{
+#if QT_CONFIG(quicktemplates2_hover)
Q_D(QQuickControl);
if (d->explicitHoverEnabled && enabled == d->hoverEnabled)
return;
d->updateHoverEnabled(enabled, true); // explicit=true
+#else
+ Q_UNUSED(enabled)
+#endif
}
void QQuickControl::resetHoverEnabled()
{
+#if QT_CONFIG(quicktemplates2_hover)
Q_D(QQuickControl);
if (!d->explicitHoverEnabled)
return;
d->explicitHoverEnabled = false;
d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
+#endif
}
/*!
@@ -1105,7 +1144,7 @@ void QQuickControl::setBackground(QQuickItem *background)
if (d->background == background)
return;
- d->deleteDelegate(d->background);
+ QQuickControlPrivate::destroyDelegate(d->background, this);
d->background = background;
if (background) {
background->setParentItem(this);
@@ -1122,15 +1161,6 @@ void QQuickControl::setBackground(QQuickItem *background)
This property holds the visual content item.
- \note The content item is automatically resized to fit within the
- \l padding of the control.
-
- \note Most controls use the implicit size of the content item to calculate
- the implicit size of the control itself. If you replace the content item
- with a custom one, you should also consider providing a sensible implicit
- size for it (unless it is an item like \l Text which has its own implicit
- size).
-
\code
Button {
id: control
@@ -1143,6 +1173,15 @@ void QQuickControl::setBackground(QQuickItem *background)
}
\endcode
+ \note The content item is automatically resized to fit within the
+ \l padding of the control.
+
+ \note Most controls use the implicit size of the content item to calculate
+ the implicit size of the control itself. If you replace the content item
+ with a custom one, you should also consider providing a sensible implicit
+ size for it (unless it is an item like \l Text which has its own implicit
+ size).
+
\sa {Control Layout}, padding
*/
QQuickItem *QQuickControl::contentItem() const
@@ -1158,7 +1197,7 @@ void QQuickControl::setContentItem(QQuickItem *item)
return;
contentItemChange(item, d->contentItem);
- d->deleteDelegate(d->contentItem);
+ QQuickControlPrivate::destroyDelegate(d->contentItem, this);
d->contentItem = item;
if (item) {
if (!item->parentItem())
@@ -1183,17 +1222,14 @@ void QQuickControl::componentComplete()
d->resizeContent();
if (!d->hasLocale)
d->locale = QQuickControlPrivate::calcLocale(d->parentItem);
+#if QT_CONFIG(quicktemplates2_hover)
if (!d->explicitHoverEnabled)
setAcceptHoverEvents(QQuickControlPrivate::calcHoverEnabled(d->parentItem));
-#ifndef QT_NO_ACCESSIBILITY
+#endif
+#if QT_CONFIG(accessibility)
if (!d->accessibleAttached && QAccessible::isActive())
accessibilityActiveChanged(true);
#endif
-
- if (d->extra.isAllocated()) {
- qDeleteAll(d->extra.value().pendingDeletions);
- d->extra.value().pendingDeletions.clear();
- }
}
QFont QQuickControl::defaultFont() const
@@ -1213,6 +1249,7 @@ void QQuickControl::focusOutEvent(QFocusEvent *event)
setFocusReason(event->reason());
}
+#if QT_CONFIG(quicktemplates2_hover)
void QQuickControl::hoverEnterEvent(QHoverEvent *event)
{
Q_D(QQuickControl);
@@ -1233,6 +1270,7 @@ void QQuickControl::hoverLeaveEvent(QHoverEvent *event)
setHovered(false);
event->setAccepted(d->hoverEnabled);
}
+#endif
void QQuickControl::mousePressEvent(QMouseEvent *event)
{
@@ -1245,8 +1283,10 @@ void QQuickControl::mousePressEvent(QMouseEvent *event)
void QQuickControl::mouseMoveEvent(QMouseEvent *event)
{
+#if QT_CONFIG(quicktemplates2_hover)
Q_D(QQuickControl);
setHovered(d->hoverEnabled && contains(event->pos()));
+#endif
event->accept();
}
@@ -1259,6 +1299,7 @@ void QQuickControl::mouseReleaseEvent(QMouseEvent *event)
event->accept();
}
+#if QT_CONFIG(wheelevent)
void QQuickControl::wheelEvent(QWheelEvent *event)
{
Q_D(QQuickControl);
@@ -1267,6 +1308,7 @@ void QQuickControl::wheelEvent(QWheelEvent *event)
event->setAccepted(d->wheelEnabled);
}
+#endif
void QQuickControl::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
@@ -1286,9 +1328,11 @@ void QQuickControl::fontChange(const QFont &newFont, const QFont &oldFont)
Q_UNUSED(oldFont);
}
+#if QT_CONFIG(quicktemplates2_hover)
void QQuickControl::hoverChange()
{
}
+#endif
void QQuickControl::mirrorChange()
{
diff --git a/src/quicktemplates2/qquickcontrol_p.h b/src/quicktemplates2/qquickcontrol_p.h
index 0ba90e19..a94ef01d 100644
--- a/src/quicktemplates2/qquickcontrol_p.h
+++ b/src/quicktemplates2/qquickcontrol_p.h
@@ -176,30 +176,36 @@ protected:
void focusInEvent(QFocusEvent *event) override;
void focusOutEvent(QFocusEvent *event) override;
+#if QT_CONFIG(quicktemplates2_hover)
void hoverEnterEvent(QHoverEvent *event) override;
void hoverMoveEvent(QHoverEvent *event) override;
void hoverLeaveEvent(QHoverEvent *event) override;
+#endif
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
+#if QT_CONFIG(wheelevent)
void wheelEvent(QWheelEvent *event) override;
+#endif
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
virtual void fontChange(const QFont &newFont, const QFont &oldFont);
+#if QT_CONFIG(quicktemplates2_hover)
virtual void hoverChange();
+#endif
virtual void mirrorChange();
virtual void spacingChange(qreal newSpacing, qreal oldSpacing);
virtual void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding);
virtual void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem);
virtual void localeChange(const QLocale &newLocale, const QLocale &oldLocale);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
virtual void accessibilityActiveChanged(bool active);
virtual QAccessible::Role accessibleRole() const;
#endif
- // helper functions which avoid to check QT_NO_ACCESSIBILITY
+ // helper functions which avoid to check QT_CONFIG(accessibility)
QString accessibleName() const;
void setAccessibleName(const QString &name);
diff --git a/src/quicktemplates2/qquickcontrol_p_p.h b/src/quicktemplates2/qquickcontrol_p_p.h
index 2cecfc84..14a468f3 100644
--- a/src/quicktemplates2/qquickcontrol_p_p.h
+++ b/src/quicktemplates2/qquickcontrol_p_p.h
@@ -54,7 +54,7 @@
#include <QtQml/private/qlazilyallocated_p.h>
#include <qpa/qplatformtheme.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <QtGui/qaccessible.h>
#endif
@@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE
class QQuickAccessibleAttached;
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickControlPrivate : public QQuickItemPrivate
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
, public QAccessible::ActivationObserver
#endif
{
@@ -90,7 +90,7 @@ public:
virtual QQuickItem *getContentItem();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
void accessibilityActiveChanged(bool active) override;
QAccessible::Role accessibleRole() const override;
#endif
@@ -111,19 +111,17 @@ public:
static void updateLocaleRecur(QQuickItem *item, const QLocale &l);
static QLocale calcLocale(const QQuickItem *item);
+#if QT_CONFIG(quicktemplates2_hover)
void updateHoverEnabled(bool enabled, bool xplicit);
static void updateHoverEnabledRecur(QQuickItem *item, bool enabled);
static bool calcHoverEnabled(const QQuickItem *item);
+#endif
- void deleteDelegate(QObject *object);
+ static void destroyDelegate(QObject *object, QObject *parent);
struct ExtraData {
ExtraData();
QFont font;
- // This list contains the default delegates which were
- // replaced with custom ones via declarative assignments
- // before Component.completed() was emitted. See QTBUG-50992.
- QVector<QObject*> pendingDeletions;
};
QLazilyAllocated<ExtraData> extra;
@@ -133,9 +131,11 @@ public:
bool hasRightPadding;
bool hasBottomPadding;
bool hasLocale;
- bool hovered;
bool wheelEnabled;
+#if QT_CONFIG(quicktemplates2_hover)
+ bool hovered;
bool explicitHoverEnabled;
+#endif
qreal padding;
qreal topPadding;
qreal leftPadding;
diff --git a/src/quicktemplates2/qquickdelaybutton.cpp b/src/quicktemplates2/qquickdelaybutton.cpp
new file mode 100644
index 00000000..f8a495b0
--- /dev/null
+++ b/src/quicktemplates2/qquickdelaybutton.cpp
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** 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 "qquickdelaybutton_p.h"
+#include "qquickabstractbutton_p_p.h"
+
+#include <QtQuick/private/qquickanimation_p.h>
+#include <QtQuick/private/qquicktransition_p.h>
+#include <QtQuick/private/qquicktransitionmanager_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype DelayButton
+ \inherits AbstractButton
+ \instantiates QQuickDelayButton
+ \inqmlmodule QtQuick.Controls
+ \since 5.9
+ \ingroup qtquickcontrols2-buttons
+ \brief Check button that triggers when held down long enough.
+
+ \image qtquickcontrols2-delaybutton.gif
+
+ DelayButton is a checkable button that incorporates a delay before the
+ button becomes \l {AbstractButton::}{checked} and the \l activated()
+ signal is emitted. This delay prevents accidental presses.
+
+ The current progress is expressed as a decimal value between \c 0.0
+ and \c 1.0. The time it takes for \l activated() to be emitted is
+ measured in milliseconds, and can be set with the \l delay property.
+
+ The progress is indicated by a progress indicator on the button.
+
+ \sa {Customizing DelayButton}, {Button Controls}
+*/
+
+/*!
+ \qmlsignal QtQuick.Controls::DelayButton::activated()
+
+ This signal is emitted when \l progress reaches \c 1.0.
+*/
+
+class QQuickDelayTransitionManager;
+
+class QQuickDelayButtonPrivate : public QQuickAbstractButtonPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickDelayButton)
+
+public:
+ QQuickDelayButtonPrivate();
+
+ void beginTransition(qreal to);
+ void finishTransition();
+ void cancelTransition();
+
+ int delay;
+ qreal progress;
+ QQuickTransition *transition;
+ QScopedPointer<QQuickDelayTransitionManager> transitionManager;
+};
+
+class QQuickDelayTransitionManager : public QQuickTransitionManager
+{
+public:
+ QQuickDelayTransitionManager(QQuickDelayButton *button) : m_button(button) { }
+
+ void transition(QQuickTransition *transition, qreal progress);
+
+protected:
+ void finished() override;
+
+private:
+ QQuickDelayButton *m_button;
+};
+
+void QQuickDelayTransitionManager::transition(QQuickTransition *transition, qreal progress)
+{
+ qmlExecuteDeferred(transition);
+
+ QQmlProperty defaultTarget(m_button, QLatin1String("progress"));
+ 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_button, QLatin1String("progress"), progress);
+ QQuickTransitionManager::transition(actions, transition, m_button);
+}
+
+void QQuickDelayTransitionManager::finished()
+{
+ if (qFuzzyCompare(m_button->progress(), 1.0))
+ emit m_button->activated();
+}
+
+QQuickDelayButtonPrivate::QQuickDelayButtonPrivate()
+ : delay(3000),
+ progress(0.0),
+ transition(nullptr)
+{
+}
+
+void QQuickDelayButtonPrivate::beginTransition(qreal to)
+{
+ Q_Q(QQuickDelayButton);
+ if (!transition) {
+ q->setProgress(to);
+ finishTransition();
+ return;
+ }
+
+ if (!transitionManager)
+ transitionManager.reset(new QQuickDelayTransitionManager(q));
+
+ transitionManager->transition(transition, to);
+}
+
+void QQuickDelayButtonPrivate::finishTransition()
+{
+ Q_Q(QQuickDelayButton);
+ if (qFuzzyCompare(progress, 1.0))
+ emit q->activated();
+}
+
+void QQuickDelayButtonPrivate::cancelTransition()
+{
+ if (transitionManager)
+ transitionManager->cancel();
+}
+
+QQuickDelayButton::QQuickDelayButton(QQuickItem *parent)
+ : QQuickAbstractButton(*(new QQuickDelayButtonPrivate), parent)
+{
+ setCheckable(true);
+}
+
+/*!
+ \qmlproperty int QtQuick.Controls::DelayButton::delay
+
+ This property holds the time it takes (in milliseconds) for \l progress
+ to reach \c 1.0 and emit \l activated().
+
+ The default value is \c 3000 ms.
+*/
+int QQuickDelayButton::delay() const
+{
+ Q_D(const QQuickDelayButton);
+ return d->delay;
+}
+
+void QQuickDelayButton::setDelay(int delay)
+{
+ Q_D(QQuickDelayButton);
+ if (d->delay == delay)
+ return;
+
+ d->delay = delay;
+ emit delayChanged();
+}
+
+/*!
+ \qmlproperty real QtQuick.Controls::DelayButton::progress
+ \readonly
+
+ This property holds the current progress as displayed by the progress
+ indicator, in the range \c 0.0 - \c 1.0.
+*/
+qreal QQuickDelayButton::progress() const
+{
+ Q_D(const QQuickDelayButton);
+ return d->progress;
+}
+
+void QQuickDelayButton::setProgress(qreal progress)
+{
+ Q_D(QQuickDelayButton);
+ if (qFuzzyCompare(d->progress, progress))
+ return;
+
+ d->progress = progress;
+ emit progressChanged();
+}
+
+/*!
+ \qmlproperty Transition QtQuick.Controls::DelayButton::transition
+
+ This property holds the transition that is applied on the \l progress
+ property when the button is pressed or released.
+*/
+QQuickTransition *QQuickDelayButton::transition() const
+{
+ Q_D(const QQuickDelayButton);
+ return d->transition;
+}
+
+void QQuickDelayButton::setTransition(QQuickTransition *transition)
+{
+ Q_D(QQuickDelayButton);
+ if (d->transition == transition)
+ return;
+
+ d->transition = transition;
+ emit transitionChanged();
+}
+
+void QQuickDelayButton::buttonChange(ButtonChange change)
+{
+ Q_D(QQuickDelayButton);
+ switch (change) {
+ case ButtonCheckedChange:
+ d->cancelTransition();
+ setProgress(d->checked ? 1.0 : 0.0);
+ break;
+ case ButtonPressedChanged:
+ if (!d->checked)
+ d->beginTransition(d->pressed ? 1.0 : 0.0);
+ break;
+ default:
+ QQuickAbstractButton::buttonChange(change);
+ break;
+ }
+}
+
+void QQuickDelayButton::nextCheckState()
+{
+ Q_D(QQuickDelayButton);
+ setChecked(!d->checked && qFuzzyCompare(d->progress, 1.0));
+}
+
+QFont QQuickDelayButton::defaultFont() const
+{
+ return QQuickControlPrivate::themeFont(QPlatformTheme::PushButtonFont);
+}
+
+QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickdelaybutton_p.h b/src/quicktemplates2/qquickdelaybutton_p.h
new file mode 100644
index 00000000..5ac0885d
--- /dev/null
+++ b/src/quicktemplates2/qquickdelaybutton_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QQUICKDELAYBUTTON_P_H
+#define QQUICKDELAYBUTTON_P_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 <QtQuickTemplates2/private/qquickabstractbutton_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickTransition;
+class QQuickDelayButtonPrivate;
+
+class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickDelayButton : public QQuickAbstractButton
+{
+ Q_OBJECT
+ Q_PROPERTY(int delay READ delay WRITE setDelay NOTIFY delayChanged FINAL)
+ Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged FINAL)
+ Q_PROPERTY(QQuickTransition *transition READ transition WRITE setTransition NOTIFY transitionChanged FINAL)
+
+public:
+ explicit QQuickDelayButton(QQuickItem *parent = nullptr);
+
+ int delay() const;
+ void setDelay(int delay);
+
+ qreal progress() const;
+ void setProgress(qreal progress);
+
+ QQuickTransition *transition() const;
+ void setTransition(QQuickTransition *transition);
+
+Q_SIGNALS:
+ void activated();
+ void delayChanged();
+ void progressChanged();
+ void transitionChanged();
+
+protected:
+ void buttonChange(ButtonChange change) override;
+ void nextCheckState() override;
+
+ QFont defaultFont() const override;
+
+private:
+ Q_DISABLE_COPY(QQuickDelayButton)
+ Q_DECLARE_PRIVATE(QQuickDelayButton)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickDelayButton)
+
+#endif // QQUICKDELAYBUTTON_P_H
diff --git a/src/quicktemplates2/qquickdial.cpp b/src/quicktemplates2/qquickdial.cpp
index fbc73c2a..198bd631 100644
--- a/src/quicktemplates2/qquickdial.cpp
+++ b/src/quicktemplates2/qquickdial.cpp
@@ -77,6 +77,14 @@ QT_BEGIN_NAMESPACE
\sa {Customizing Dial}, {Input Controls}
*/
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlsignal QtQuick.Controls::Dial::moved()
+
+ This signal is emitted when the dial has been interactively moved
+ by the user by either touch, mouse, or keys.
+*/
+
static const qreal startAngleRadians = (M_PI * 2.0) * (4.0 / 6.0);
static const qreal startAngle = -140;
static const qreal endAngleRadians = (M_PI * 2.0) * (5.0 / 6.0);
@@ -87,27 +95,35 @@ class QQuickDialPrivate : public QQuickControlPrivate
Q_DECLARE_PUBLIC(QQuickDial)
public:
- QQuickDialPrivate() :
- from(0),
- to(1),
- value(0),
- position(0),
- angle(startAngle),
- stepSize(0),
- pressed(false),
- snapMode(QQuickDial::NoSnap),
- wrap(false),
- handle(nullptr)
+ QQuickDialPrivate()
+ : touchId(-1),
+ from(0),
+ to(1),
+ value(0),
+ position(0),
+ angle(startAngle),
+ stepSize(0),
+ pressed(false),
+ snapMode(QQuickDial::NoSnap),
+ wrap(false),
+ live(true),
+ handle(nullptr)
{
}
qreal valueAt(qreal position) const;
qreal snapPosition(qreal position) const;
- qreal positionAt(const QPoint &point) const;
+ qreal positionAt(const QPointF &point) const;
void setPosition(qreal position);
void updatePosition();
- bool isLargeChange(const QPoint &eventPos, qreal proposedPosition) const;
+ bool isLargeChange(const QPointF &eventPos, qreal proposedPosition) const;
+
+ void handlePress(const QPointF &point);
+ void handleMove(const QPointF &point);
+ void handleRelease(const QPointF &point);
+ void handleUngrab();
+ int touchId;
qreal from;
qreal to;
qreal value;
@@ -115,9 +131,10 @@ public:
qreal angle;
qreal stepSize;
bool pressed;
- QPoint pressPoint;
+ QPointF pressPoint;
QQuickDial::SnapMode snapMode;
bool wrap;
+ bool live;
QQuickItem *handle;
};
@@ -139,7 +156,7 @@ qreal QQuickDialPrivate::snapPosition(qreal position) const
return qRound(position / effectiveStep) * effectiveStep;
}
-qreal QQuickDialPrivate::positionAt(const QPoint &point) const
+qreal QQuickDialPrivate::positionAt(const QPointF &point) const
{
qreal yy = height / 2.0 - point.y();
qreal xx = point.x() - width / 2.0;
@@ -175,13 +192,71 @@ void QQuickDialPrivate::updatePosition()
setPosition(pos);
}
-bool QQuickDialPrivate::isLargeChange(const QPoint &eventPos, qreal proposedPosition) const
+bool QQuickDialPrivate::isLargeChange(const QPointF &eventPos, qreal proposedPosition) const
{
return qAbs(proposedPosition - position) >= 0.5 && eventPos.y() >= height / 2;
}
-QQuickDial::QQuickDial(QQuickItem *parent) :
- QQuickControl(*(new QQuickDialPrivate), parent)
+void QQuickDialPrivate::handlePress(const QPointF &point)
+{
+ Q_Q(QQuickDial);
+ pressPoint = point;
+ q->setPressed(true);
+}
+
+void QQuickDialPrivate::handleMove(const QPointF &point)
+{
+ Q_Q(QQuickDial);
+ if (!q->keepMouseGrab() && !q->keepTouchGrab())
+ return;
+ const qreal oldPos = position;
+ qreal pos = positionAt(point);
+ if (snapMode == QQuickDial::SnapAlways)
+ pos = snapPosition(pos);
+
+ if (wrap || (!wrap && !isLargeChange(point, pos))) {
+ if (live)
+ q->setValue(valueAt(pos));
+ else
+ setPosition(pos);
+ if (!qFuzzyCompare(pos, oldPos))
+ emit q->moved();
+ }
+}
+
+void QQuickDialPrivate::handleRelease(const QPointF &point)
+{
+ Q_Q(QQuickDial);
+ if (q->keepMouseGrab() || q->keepTouchGrab()) {
+ const qreal oldPos = position;
+ qreal pos = positionAt(point);
+ if (snapMode != QQuickDial::NoSnap)
+ pos = snapPosition(pos);
+
+ if (wrap || (!wrap && !isLargeChange(point, pos)))
+ q->setValue(valueAt(pos));
+ if (!qFuzzyCompare(pos, oldPos))
+ emit q->moved();
+
+ q->setKeepMouseGrab(false);
+ q->setKeepTouchGrab(false);
+ }
+
+ q->setPressed(false);
+ pressPoint = QPointF();
+ touchId = -1;
+}
+
+void QQuickDialPrivate::handleUngrab()
+{
+ Q_Q(QQuickDial);
+ pressPoint = QPointF();
+ touchId = -1;
+ q->setPressed(false);
+}
+
+QQuickDial::QQuickDial(QQuickItem *parent)
+ : QQuickControl(*(new QQuickDialPrivate), parent)
{
setActiveFocusOnTab(true);
setAcceptedMouseButtons(Qt::LeftButton);
@@ -248,11 +323,7 @@ void QQuickDial::setTo(qreal to)
This property holds the value in the range \c from - \c to. The default
value is \c 0.0.
- Unlike the \l position property, the \c value is not updated while the
- handle is dragged. The value is updated after the value has been chosen
- and the dial has been released.
-
- \sa position
+ \sa position, live
*/
qreal QQuickDial::value() const
{
@@ -282,8 +353,6 @@ void QQuickDial::setValue(qreal value)
The position is expressed as a fraction of the control's angle range (the
range within which the handle can be moved) in the range \c {0.0 - 1.0}.
- Unlike the \l value property, the \c position is continuously updated while
- the handle is dragged.
\sa value, angle
*/
@@ -299,9 +368,6 @@ qreal QQuickDial::position() const
This property holds the angle of the handle.
- Like the \l position property, angle is continuously updated while the
- handle is dragged.
-
The range is from \c -140 degrees to \c 140 degrees.
\sa position
@@ -447,6 +513,33 @@ void QQuickDial::setPressed(bool pressed)
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::Dial::live
+
+ This property holds whether the dial provides live updates for the \l value
+ property while the handle is dragged.
+
+ The default value is \c true.
+
+ \sa value, valueAt()
+*/
+bool QQuickDial::live() const
+{
+ Q_D(const QQuickDial);
+ return d->live;
+}
+
+void QQuickDial::setLive(bool live)
+{
+ Q_D(QQuickDial);
+ if (d->live == live)
+ return;
+
+ d->live = live;
+ emit liveChanged();
+}
+
+/*!
\qmlmethod void QtQuick.Controls::Dial::increase()
Increases the value by \l stepSize, or \c 0.1 if stepSize is not defined.
@@ -495,7 +588,7 @@ void QQuickDial::setHandle(QQuickItem *handle)
if (handle == d->handle)
return;
- d->deleteDelegate(d->handle);
+ QQuickControlPrivate::destroyDelegate(d->handle, this);
d->handle = handle;
if (d->handle && !d->handle->parentItem())
d->handle->setParentItem(this);
@@ -505,6 +598,7 @@ void QQuickDial::setHandle(QQuickItem *handle)
void QQuickDial::keyPressEvent(QKeyEvent *event)
{
Q_D(QQuickDial);
+ const qreal oldValue = d->value;
switch (event->key()) {
case Qt::Key_Left:
case Qt::Key_Down:
@@ -539,6 +633,8 @@ void QQuickDial::keyPressEvent(QKeyEvent *event)
QQuickControl::keyPressEvent(event);
break;
}
+ if (!qFuzzyCompare(d->value, oldValue))
+ emit moved();
}
void QQuickDial::keyReleaseEvent(QKeyEvent *event)
@@ -551,8 +647,7 @@ void QQuickDial::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickDial);
QQuickControl::mousePressEvent(event);
- d->pressPoint = event->pos();
- setPressed(true);
+ d->handlePress(event->localPos());
}
void QQuickDial::mouseMoveEvent(QMouseEvent *event)
@@ -560,52 +655,90 @@ void QQuickDial::mouseMoveEvent(QMouseEvent *event)
Q_D(QQuickDial);
QQuickControl::mouseMoveEvent(event);
if (!keepMouseGrab()) {
- bool overXDragThreshold = QQuickWindowPrivate::dragOverThreshold(event->pos().x() - d->pressPoint.x(), Qt::XAxis, event);
+ bool overXDragThreshold = QQuickWindowPrivate::dragOverThreshold(event->localPos().x() - d->pressPoint.x(), Qt::XAxis, event);
setKeepMouseGrab(overXDragThreshold);
if (!overXDragThreshold) {
- bool overYDragThreshold = QQuickWindowPrivate::dragOverThreshold(event->pos().y() - d->pressPoint.y(), Qt::YAxis, event);
+ bool overYDragThreshold = QQuickWindowPrivate::dragOverThreshold(event->localPos().y() - d->pressPoint.y(), Qt::YAxis, event);
setKeepMouseGrab(overYDragThreshold);
}
}
- if (keepMouseGrab()) {
- qreal pos = d->positionAt(event->pos());
- if (d->snapMode == SnapAlways)
- pos = d->snapPosition(pos);
-
- if (d->wrap || (!d->wrap && !d->isLargeChange(event->pos(), pos)))
- d->setPosition(pos);
- }
+ d->handleMove(event->localPos());
}
void QQuickDial::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QQuickDial);
QQuickControl::mouseReleaseEvent(event);
+ d->handleRelease(event->localPos());
+}
+
+void QQuickDial::mouseUngrabEvent()
+{
+ Q_D(QQuickDial);
+ QQuickControl::mouseUngrabEvent();
+ d->handleUngrab();
+}
+
+void QQuickDial::touchEvent(QTouchEvent *event)
+{
+ Q_D(QQuickDial);
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ if (d->touchId == -1) {
+ const QTouchEvent::TouchPoint point = event->touchPoints().first();
+ d->touchId = point.id();
+ d->handlePress(point.pos());
+ } else {
+ event->ignore();
+ }
+ break;
- if (keepMouseGrab()) {
- qreal pos = d->positionAt(event->pos());
- if (d->snapMode != NoSnap)
- pos = d->snapPosition(pos);
+ case QEvent::TouchUpdate:
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ if (point.id() != d->touchId)
+ continue;
+
+ if (!keepTouchGrab()) {
+ bool overXDragThreshold = QQuickWindowPrivate::dragOverThreshold(point.pos().x() - d->pressPoint.x(), Qt::XAxis, &point);
+ setKeepTouchGrab(overXDragThreshold);
+
+ if (!overXDragThreshold) {
+ bool overYDragThreshold = QQuickWindowPrivate::dragOverThreshold(point.pos().y() - d->pressPoint.y(), Qt::YAxis, &point);
+ setKeepTouchGrab(overYDragThreshold);
+ }
+ }
+ d->handleMove(point.pos());
+ }
+ break;
- if (d->wrap || (!d->wrap && !d->isLargeChange(event->pos(), pos)))
- setValue(d->valueAt(pos));
+ case QEvent::TouchEnd:
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ if (point.id() != d->touchId)
+ continue;
- setKeepMouseGrab(false);
- }
+ d->handleRelease(point.pos());
+ }
+ break;
- setPressed(false);
- d->pressPoint = QPoint();
+ case QEvent::TouchCancel:
+ d->handleUngrab();
+ break;
+
+ default:
+ QQuickControl::touchEvent(event);
+ break;
+ }
}
-void QQuickDial::mouseUngrabEvent()
+void QQuickDial::touchUngrabEvent()
{
Q_D(QQuickDial);
- QQuickControl::mouseUngrabEvent();
- d->pressPoint = QPoint();
- setPressed(false);
+ QQuickControl::touchUngrabEvent();
+ d->handleUngrab();
}
+#if QT_CONFIG(wheelevent)
void QQuickDial::wheelEvent(QWheelEvent *event)
{
Q_D(QQuickDial);
@@ -619,6 +752,7 @@ void QQuickDial::wheelEvent(QWheelEvent *event)
event->setAccepted(!qFuzzyCompare(d->value, oldValue));
}
}
+#endif
void QQuickDial::mirrorChange()
{
@@ -634,7 +768,7 @@ void QQuickDial::componentComplete()
d->updatePosition();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
void QQuickDial::accessibilityActiveChanged(bool active)
{
QQuickControl::accessibilityActiveChanged(active);
diff --git a/src/quicktemplates2/qquickdial_p.h b/src/quicktemplates2/qquickdial_p.h
index 03d385fa..e402922d 100644
--- a/src/quicktemplates2/qquickdial_p.h
+++ b/src/quicktemplates2/qquickdial_p.h
@@ -69,6 +69,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickDial : public QQuickControl
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL)
Q_PROPERTY(bool wrap READ wrap WRITE setWrap NOTIFY wrapChanged FINAL)
Q_PROPERTY(bool pressed READ isPressed NOTIFY pressedChanged FINAL)
+ Q_PROPERTY(bool live READ live WRITE setLive NOTIFY liveChanged FINAL REVISION 2)
Q_PROPERTY(QQuickItem *handle READ handle WRITE setHandle NOTIFY handleChanged FINAL)
public:
@@ -106,6 +107,9 @@ public:
bool isPressed() const;
void setPressed(bool pressed);
+ bool live() const;
+ void setLive(bool live);
+
QQuickItem *handle() const;
void setHandle(QQuickItem *handle);
@@ -123,7 +127,9 @@ Q_SIGNALS:
void snapModeChanged();
void wrapChanged();
void pressedChanged();
+ Q_REVISION(2) void liveChanged();
void handleChanged();
+ Q_REVISION(2) void moved();
protected:
void keyPressEvent(QKeyEvent *event) override;
@@ -132,12 +138,16 @@ protected:
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseUngrabEvent() override;
+ void touchEvent(QTouchEvent *event) override;
+ void touchUngrabEvent() override;
+#if QT_CONFIG(wheelevent)
void wheelEvent(QWheelEvent *event) override;
+#endif
void mirrorChange() override;
void componentComplete() override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
void accessibilityActiveChanged(bool active) override;
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquickdialog.cpp b/src/quicktemplates2/qquickdialog.cpp
index 6d26dab8..fbb612b3 100644
--- a/src/quicktemplates2/qquickdialog.cpp
+++ b/src/quicktemplates2/qquickdialog.cpp
@@ -37,6 +37,7 @@
#include "qquickdialog_p.h"
#include "qquickdialog_p_p.h"
#include "qquickdialogbuttonbox_p.h"
+#include "qquickpopupitem_p_p.h"
QT_BEGIN_NAMESPACE
@@ -114,8 +115,8 @@ QT_BEGIN_NAMESPACE
\sa accepted()
*/
-QQuickDialog::QQuickDialog(QObject *parent) :
- QQuickPopup(*(new QQuickDialogPrivate), parent)
+QQuickDialog::QQuickDialog(QObject *parent)
+ : QQuickPopup(*(new QQuickDialogPrivate), parent)
{
Q_D(QQuickDialog);
d->layout.reset(new QQuickPageLayout(d->popupItem));
@@ -344,7 +345,7 @@ void QQuickDialog::spacingChange(qreal newSpacing, qreal oldSpacing)
d->layout->update();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickDialog::accessibleRole() const
{
return QAccessible::Dialog;
diff --git a/src/quicktemplates2/qquickdialog_p.h b/src/quicktemplates2/qquickdialog_p.h
index 9c763b3e..97c90a59 100644
--- a/src/quicktemplates2/qquickdialog_p.h
+++ b/src/quicktemplates2/qquickdialog_p.h
@@ -97,7 +97,7 @@ protected:
void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding) override;
void spacingChange(qreal newSpacing, qreal oldSpacing) override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
void accessibilityActiveChanged(bool active) override;
#endif
diff --git a/src/quicktemplates2/qquickdialogbuttonbox.cpp b/src/quicktemplates2/qquickdialogbuttonbox.cpp
index 40b1e2c7..a912ba6a 100644
--- a/src/quicktemplates2/qquickdialogbuttonbox.cpp
+++ b/src/quicktemplates2/qquickdialogbuttonbox.cpp
@@ -143,11 +143,11 @@ static QPlatformDialogHelper::ButtonRole buttonRole(QQuickAbstractButton *button
return attached ? attached->buttonRole() : QPlatformDialogHelper::InvalidRole;
}
-QQuickDialogButtonBoxPrivate::QQuickDialogButtonBoxPrivate() :
- alignment(0),
- position(QQuickDialogButtonBox::Footer),
- standardButtons(QPlatformDialogHelper::NoButton),
- delegate(nullptr)
+QQuickDialogButtonBoxPrivate::QQuickDialogButtonBoxPrivate()
+ : alignment(0),
+ position(QQuickDialogButtonBox::Footer),
+ standardButtons(QPlatformDialogHelper::NoButton),
+ delegate(nullptr)
{
}
@@ -350,8 +350,8 @@ void QQuickDialogButtonBoxPrivate::removeStandardButtons()
}
}
-QQuickDialogButtonBox::QQuickDialogButtonBox(QQuickItem *parent) :
- QQuickContainer(*(new QQuickDialogButtonBoxPrivate), parent)
+QQuickDialogButtonBox::QQuickDialogButtonBox(QQuickItem *parent)
+ : QQuickContainer(*(new QQuickDialogButtonBoxPrivate), parent)
{
}
@@ -359,7 +359,6 @@ QQuickDialogButtonBox::~QQuickDialogButtonBox()
{
}
-
/*!
\qmlproperty enumeration QtQuick.Controls::DialogButtonBox::position
@@ -603,7 +602,7 @@ void QQuickDialogButtonBox::itemRemoved(int index, QQuickItem *item)
polish();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickDialogButtonBox::accessibleRole() const
{
return QAccessible::PageTabList;
@@ -620,8 +619,8 @@ void QQuickDialogButtonBoxAttachedPrivate::setButtonBox(QQuickDialogButtonBox *b
emit q->buttonBoxChanged();
}
-QQuickDialogButtonBoxAttached::QQuickDialogButtonBoxAttached(QObject *parent) :
- QObject(*(new QQuickDialogButtonBoxAttachedPrivate), parent)
+QQuickDialogButtonBoxAttached::QQuickDialogButtonBoxAttached(QObject *parent)
+ : QObject(*(new QQuickDialogButtonBoxAttachedPrivate), parent)
{
Q_D(QQuickDialogButtonBoxAttached);
QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent);
diff --git a/src/quicktemplates2/qquickdialogbuttonbox_p.h b/src/quicktemplates2/qquickdialogbuttonbox_p.h
index 4aa7f9d2..9bd92c79 100644
--- a/src/quicktemplates2/qquickdialogbuttonbox_p.h
+++ b/src/quicktemplates2/qquickdialogbuttonbox_p.h
@@ -114,7 +114,7 @@ protected:
void itemAdded(int index, QQuickItem *item) override;
void itemRemoved(int index, QQuickItem *item) override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquickdialogbuttonbox_p_p.h b/src/quicktemplates2/qquickdialogbuttonbox_p_p.h
index bfde51d1..7247d591 100644
--- a/src/quicktemplates2/qquickdialogbuttonbox_p_p.h
+++ b/src/quicktemplates2/qquickdialogbuttonbox_p_p.h
@@ -86,9 +86,12 @@ class QQuickDialogButtonBoxAttachedPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QQuickDialogButtonBoxAttached)
public:
- QQuickDialogButtonBoxAttachedPrivate() : buttonBox(nullptr),
- buttonRole(QPlatformDialogHelper::InvalidRole),
- standardButton(QPlatformDialogHelper::NoButton) { }
+ QQuickDialogButtonBoxAttachedPrivate()
+ : buttonBox(nullptr),
+ buttonRole(QPlatformDialogHelper::InvalidRole),
+ standardButton(QPlatformDialogHelper::NoButton)
+ {
+ }
static QQuickDialogButtonBoxAttachedPrivate *get(QQuickDialogButtonBoxAttached *q)
{
diff --git a/src/quicktemplates2/qquickdrawer.cpp b/src/quicktemplates2/qquickdrawer.cpp
index 13d29bf4..b4a7190a 100644
--- a/src/quicktemplates2/qquickdrawer.cpp
+++ b/src/quicktemplates2/qquickdrawer.cpp
@@ -36,6 +36,7 @@
#include "qquickdrawer_p.h"
#include "qquickdrawer_p_p.h"
+#include "qquickpopupitem_p_p.h"
#include <QtGui/qstylehints.h>
#include <QtGui/private/qguiapplication_p.h>
@@ -160,7 +161,9 @@ QT_BEGIN_NAMESPACE
*/
QQuickDrawerPrivate::QQuickDrawerPrivate()
- : edge(Qt::LeftEdge), offset(0), position(0),
+ : edge(Qt::LeftEdge),
+ offset(0),
+ position(0),
dragMargin(QGuiApplication::styleHints()->startDragDistance())
{
setEdge(Qt::LeftEdge);
@@ -238,7 +241,7 @@ static bool dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event, int th
bool QQuickDrawerPrivate::startDrag(QQuickWindow *window, QMouseEvent *event)
{
- if (!window || dragMargin < 0.0 || qFuzzyIsNull(dragMargin))
+ if (!window || !interactive || dragMargin < 0.0 || qFuzzyIsNull(dragMargin))
return false;
bool drag = false;
@@ -271,7 +274,7 @@ bool QQuickDrawerPrivate::startDrag(QQuickWindow *window, QMouseEvent *event)
bool QQuickDrawerPrivate::grabMouse(QMouseEvent *event)
{
Q_Q(QQuickDrawer);
- if (!window || popupItem->keepMouseGrab())
+ if (!window || !interactive || popupItem->keepMouseGrab())
return false;
const QPointF movePoint = event->windowPos();
@@ -467,8 +470,8 @@ void QQuickDrawerPrivate::setEdge(Qt::Edge e)
}
}
-QQuickDrawer::QQuickDrawer(QObject *parent) :
- QQuickPopup(*(new QQuickDrawerPrivate), parent)
+QQuickDrawer::QQuickDrawer(QObject *parent)
+ : QQuickPopup(*(new QQuickDrawerPrivate), parent)
{
setFocus(true);
setModal(true);
@@ -541,6 +544,8 @@ void QQuickDrawer::setPosition(qreal position)
prevents opening the drawer by dragging.
The default value is \c Qt.styleHints.startDragDistance.
+
+ \sa interactive
*/
qreal QQuickDrawer::dragMargin() const
{
@@ -563,6 +568,34 @@ void QQuickDrawer::resetDragMargin()
setDragMargin(QGuiApplication::styleHints()->startDragDistance());
}
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::Drawer::interactive
+
+ This property holds whether the drawer is interactive. A non-interactive
+ drawer does not react to swipes.
+
+ The default value is \c true.
+
+ \sa dragMargin
+*/
+bool QQuickDrawer::isInteractive() const
+{
+ Q_D(const QQuickDrawer);
+ return d->interactive;
+}
+
+void QQuickDrawer::setInteractive(bool interactive)
+{
+ Q_D(QQuickDrawer);
+ if (d->interactive == interactive)
+ return;
+
+ setFiltersChildMouseEvents(interactive);
+ d->interactive = interactive;
+ emit interactiveChanged();
+}
+
bool QQuickDrawer::childMouseEventFilter(QQuickItem *child, QEvent *event)
{
Q_D(QQuickDrawer);
diff --git a/src/quicktemplates2/qquickdrawer_p.h b/src/quicktemplates2/qquickdrawer_p.h
index ad64aed5..68b58362 100644
--- a/src/quicktemplates2/qquickdrawer_p.h
+++ b/src/quicktemplates2/qquickdrawer_p.h
@@ -60,6 +60,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickDrawer : public QQuickPopup
Q_PROPERTY(Qt::Edge edge READ edge WRITE setEdge NOTIFY edgeChanged FINAL)
Q_PROPERTY(qreal position READ position WRITE setPosition NOTIFY positionChanged FINAL)
Q_PROPERTY(qreal dragMargin READ dragMargin WRITE setDragMargin RESET resetDragMargin NOTIFY dragMarginChanged FINAL)
+ Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged FINAL REVISION 2)
public:
explicit QQuickDrawer(QObject *parent = nullptr);
@@ -74,10 +75,14 @@ public:
void setDragMargin(qreal margin);
void resetDragMargin();
+ bool isInteractive() const;
+ void setInteractive(bool interactive);
+
Q_SIGNALS:
void edgeChanged();
void positionChanged();
void dragMarginChanged();
+ Q_REVISION(2) void interactiveChanged();
protected:
bool childMouseEventFilter(QQuickItem *child, QEvent *event) override;
diff --git a/src/quicktemplates2/qquickframe.cpp b/src/quicktemplates2/qquickframe.cpp
index dfb6790a..f880d917 100644
--- a/src/quicktemplates2/qquickframe.cpp
+++ b/src/quicktemplates2/qquickframe.cpp
@@ -68,21 +68,21 @@ QT_BEGIN_NAMESPACE
\sa {Customizing Frame}, {Container Controls}
*/
-QQuickFrame::QQuickFrame(QQuickItem *parent) :
- QQuickPane(*(new QQuickFramePrivate), parent)
+QQuickFrame::QQuickFrame(QQuickItem *parent)
+ : QQuickPane(*(new QQuickFramePrivate), parent)
{
}
-QQuickFrame::QQuickFrame(QQuickFramePrivate &dd, QQuickItem *parent) :
- QQuickPane(dd, parent)
+QQuickFrame::QQuickFrame(QQuickFramePrivate &dd, QQuickItem *parent)
+ : QQuickPane(dd, parent)
{
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickFrame::accessibleRole() const
{
return QAccessible::Border;
}
-#endif // QT_NO_ACCESSIBILITY
+#endif
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickframe_p.h b/src/quicktemplates2/qquickframe_p.h
index 4dc252f4..381088ec 100644
--- a/src/quicktemplates2/qquickframe_p.h
+++ b/src/quicktemplates2/qquickframe_p.h
@@ -64,7 +64,7 @@ public:
protected:
QQuickFrame(QQuickFramePrivate &dd, QQuickItem *parent);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquickgroupbox.cpp b/src/quicktemplates2/qquickgroupbox.cpp
index d003e8f5..09bd49f6 100644
--- a/src/quicktemplates2/qquickgroupbox.cpp
+++ b/src/quicktemplates2/qquickgroupbox.cpp
@@ -92,8 +92,8 @@ public:
QQuickItem *label;
};
-QQuickGroupBox::QQuickGroupBox(QQuickItem *parent) :
- QQuickFrame(*(new QQuickGroupBoxPrivate), parent)
+QQuickGroupBox::QQuickGroupBox(QQuickItem *parent)
+ : QQuickFrame(*(new QQuickGroupBoxPrivate), parent)
{
}
@@ -141,7 +141,7 @@ void QQuickGroupBox::setLabel(QQuickItem *label)
if (d->label == label)
return;
- d->deleteDelegate(d->label);
+ QQuickControlPrivate::destroyDelegate(d->label, this);
d->label = label;
if (label && !label->parentItem())
label->setParentItem(this);
@@ -153,7 +153,7 @@ QFont QQuickGroupBox::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::GroupBoxTitleFont);
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickGroupBox::accessibleRole() const
{
return QAccessible::Grouping;
@@ -167,6 +167,6 @@ void QQuickGroupBox::accessibilityActiveChanged(bool active)
if (active)
setAccessibleName(d->title);
}
-#endif // QT_NO_ACCESSIBILITY
+#endif
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickgroupbox_p.h b/src/quicktemplates2/qquickgroupbox_p.h
index 3b2c41d9..e35db1fc 100644
--- a/src/quicktemplates2/qquickgroupbox_p.h
+++ b/src/quicktemplates2/qquickgroupbox_p.h
@@ -76,7 +76,7 @@ Q_SIGNALS:
protected:
QFont defaultFont() const override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
void accessibilityActiveChanged(bool active) override;
#endif
diff --git a/src/quicktemplates2/qquickitemdelegate.cpp b/src/quicktemplates2/qquickitemdelegate.cpp
index a34227f5..1b93c145 100644
--- a/src/quicktemplates2/qquickitemdelegate.cpp
+++ b/src/quicktemplates2/qquickitemdelegate.cpp
@@ -64,19 +64,19 @@ QT_BEGIN_NAMESPACE
\sa {Customizing ItemDelegate}, {Delegate Controls}
*/
-QQuickItemDelegatePrivate::QQuickItemDelegatePrivate() :
- highlighted(false)
+QQuickItemDelegatePrivate::QQuickItemDelegatePrivate()
+ : highlighted(false)
{
}
-QQuickItemDelegate::QQuickItemDelegate(QQuickItem *parent) :
- QQuickAbstractButton(*(new QQuickItemDelegatePrivate), parent)
+QQuickItemDelegate::QQuickItemDelegate(QQuickItem *parent)
+ : QQuickAbstractButton(*(new QQuickItemDelegatePrivate), parent)
{
setFocusPolicy(Qt::NoFocus);
}
-QQuickItemDelegate::QQuickItemDelegate(QQuickItemDelegatePrivate &dd, QQuickItem *parent) :
- QQuickAbstractButton(dd, parent)
+QQuickItemDelegate::QQuickItemDelegate(QQuickItemDelegatePrivate &dd, QQuickItem *parent)
+ : QQuickAbstractButton(dd, parent)
{
setFocusPolicy(Qt::NoFocus);
}
@@ -125,7 +125,7 @@ QFont QQuickItemDelegate::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::ItemViewFont);
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickItemDelegate::accessibleRole() const
{
return QAccessible::ListItem;
diff --git a/src/quicktemplates2/qquickitemdelegate_p.h b/src/quicktemplates2/qquickitemdelegate_p.h
index c5a9d998..a162ddee 100644
--- a/src/quicktemplates2/qquickitemdelegate_p.h
+++ b/src/quicktemplates2/qquickitemdelegate_p.h
@@ -71,7 +71,7 @@ Q_SIGNALS:
protected:
QFont defaultFont() const override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquicklabel.cpp b/src/quicktemplates2/qquicklabel.cpp
index df710733..45c7e5a4 100644
--- a/src/quicktemplates2/qquicklabel.cpp
+++ b/src/quicktemplates2/qquicklabel.cpp
@@ -41,9 +41,8 @@
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquicktext_p.h>
-#include <QtQuick/private/qquickclipnode_p.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <QtQuick/private/qquickaccessibleattached_p.h>
#endif
@@ -79,29 +78,18 @@ QT_BEGIN_NAMESPACE
\sa {Customizing Label}
*/
-QQuickLabel::QQuickLabel(QQuickItem *parent) :
- QQuickText(*(new QQuickLabelPrivate), parent)
-{
- Q_D(QQuickLabel);
- QObjectPrivate::connect(this, &QQuickText::textChanged,
- d, &QQuickLabelPrivate::_q_textChanged);
-}
-
-QQuickLabel::~QQuickLabel()
-{
-}
-
QQuickLabelPrivate::QQuickLabelPrivate()
- : background(nullptr), accessibleAttached(nullptr)
+ : background(nullptr),
+ accessibleAttached(nullptr)
{
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::installActivationObserver(this);
#endif
}
QQuickLabelPrivate::~QQuickLabelPrivate()
{
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::removeActivationObserver(this);
#endif
}
@@ -135,9 +123,9 @@ void QQuickLabelPrivate::inheritFont(const QFont &f)
emit q->fontChanged();
}
-void QQuickLabelPrivate::_q_textChanged(const QString &text)
+void QQuickLabelPrivate::textChanged(const QString &text)
{
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (accessibleAttached)
accessibleAttached->setName(text);
#else
@@ -145,7 +133,7 @@ void QQuickLabelPrivate::_q_textChanged(const QString &text)
#endif
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
void QQuickLabelPrivate::accessibilityActiveChanged(bool active)
{
if (accessibleAttached || !active)
@@ -167,16 +155,11 @@ QAccessible::Role QQuickLabelPrivate::accessibleRole() const
}
#endif
-/*
- Deletes "delegate" if Component.completed() has been emitted,
- otherwise stores it in pendingDeletions.
-*/
-void QQuickLabelPrivate::deleteDelegate(QObject *delegate)
+QQuickLabel::QQuickLabel(QQuickItem *parent)
+ : QQuickText(*(new QQuickLabelPrivate), parent)
{
- if (componentComplete)
- delete delegate;
- else if (delegate)
- pendingDeletions.append(delegate);
+ Q_D(QQuickLabel);
+ QObjectPrivate::connect(this, &QQuickText::textChanged, d, &QQuickLabelPrivate::textChanged);
}
QFont QQuickLabel::font() const
@@ -217,7 +200,7 @@ void QQuickLabel::setBackground(QQuickItem *background)
if (d->background == background)
return;
- d->deleteDelegate(d->background);
+ QQuickControlPrivate::destroyDelegate(d->background, this);
d->background = background;
if (background) {
background->setParentItem(this);
@@ -238,13 +221,10 @@ void QQuickLabel::componentComplete()
{
Q_D(QQuickLabel);
QQuickText::componentComplete();
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (!d->accessibleAttached && QAccessible::isActive())
d->accessibilityActiveChanged(true);
#endif
-
- qDeleteAll(d->pendingDeletions);
- d->pendingDeletions.clear();
}
void QQuickLabel::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)
diff --git a/src/quicktemplates2/qquicklabel_p.h b/src/quicktemplates2/qquicklabel_p.h
index 29b1e7db..04172900 100644
--- a/src/quicktemplates2/qquicklabel_p.h
+++ b/src/quicktemplates2/qquicklabel_p.h
@@ -63,7 +63,6 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickLabel : public QQuickText
public:
explicit QQuickLabel(QQuickItem *parent = nullptr);
- ~QQuickLabel();
QFont font() const;
void setFont(const QFont &font);
diff --git a/src/quicktemplates2/qquicklabel_p_p.h b/src/quicktemplates2/qquicklabel_p_p.h
index 5b07a85f..c24c855b 100644
--- a/src/quicktemplates2/qquicklabel_p_p.h
+++ b/src/quicktemplates2/qquicklabel_p_p.h
@@ -50,7 +50,7 @@
#include <QtQuick/private/qquicktext_p_p.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <QtGui/qaccessible.h>
#endif
@@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
class QQuickAccessibleAttached;
class QQuickLabelPrivate : public QQuickTextPrivate
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
, public QAccessible::ActivationObserver
#endif
{
@@ -69,29 +69,24 @@ public:
QQuickLabelPrivate();
~QQuickLabelPrivate();
- static QQuickLabelPrivate *get(QQuickLabel *item) {
- return static_cast<QQuickLabelPrivate *>(QObjectPrivate::get(item)); }
+ static QQuickLabelPrivate *get(QQuickLabel *item)
+ {
+ return static_cast<QQuickLabelPrivate *>(QObjectPrivate::get(item));
+ }
- void resizeBackground();
void resolveFont();
void inheritFont(const QFont &f);
- void _q_textChanged(const QString &text);
+ void textChanged(const QString &text);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
void accessibilityActiveChanged(bool active) override;
QAccessible::Role accessibleRole() const override;
#endif
- void deleteDelegate(QObject *object);
-
QFont font;
QQuickItem *background;
QQuickAccessibleAttached *accessibleAttached;
- // This list contains the default delegates which were
- // replaced with custom ones via declarative assignments
- // before Component.completed() was emitted. See QTBUG-50992.
- QVector<QObject *> pendingDeletions;
};
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickmenu.cpp b/src/quicktemplates2/qquickmenu.cpp
index d796f484..04305cea 100644
--- a/src/quicktemplates2/qquickmenu.cpp
+++ b/src/quicktemplates2/qquickmenu.cpp
@@ -101,9 +101,9 @@ QT_BEGIN_NAMESPACE
\sa {Customizing Menu}, {Menu Controls}, {Popup Controls}
*/
-QQuickMenuPrivate::QQuickMenuPrivate() :
- contentItem(nullptr),
- contentModel(nullptr)
+QQuickMenuPrivate::QQuickMenuPrivate()
+ : contentItem(nullptr),
+ contentModel(nullptr)
{
Q_Q(QQuickMenu);
contentModel = new QQmlObjectModel(q);
@@ -284,8 +284,8 @@ void QQuickMenuPrivate::contentData_clear(QQmlListProperty<QObject> *prop)
p->contentData.clear();
}
-QQuickMenu::QQuickMenu(QObject *parent) :
- QQuickPopup(*(new QQuickMenuPrivate), parent)
+QQuickMenu::QQuickMenu(QObject *parent)
+ : QQuickPopup(*(new QQuickMenuPrivate), parent)
{
setFocus(true);
setClosePolicy(CloseOnEscape | CloseOnPressOutside | CloseOnReleaseOutside);
@@ -525,12 +525,12 @@ void QQuickMenu::keyReleaseEvent(QKeyEvent *event)
item->forceActiveFocus();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickMenu::accessibleRole() const
{
return QAccessible::PopupMenu;
}
-#endif // QT_NO_ACCESSIBILITY
+#endif
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickmenu_p.h b/src/quicktemplates2/qquickmenu_p.h
index 146cf9b7..a899fe51 100644
--- a/src/quicktemplates2/qquickmenu_p.h
+++ b/src/quicktemplates2/qquickmenu_p.h
@@ -91,9 +91,9 @@ Q_SIGNALS:
void titleChanged();
protected:
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
-#endif // QT_NO_ACCESSIBILITY
+#endif
private:
Q_DISABLE_COPY(QQuickMenu)
diff --git a/src/quicktemplates2/qquickmenu_p_p.h b/src/quicktemplates2/qquickmenu_p_p.h
index f1aee427..504bc74d 100644
--- a/src/quicktemplates2/qquickmenu_p_p.h
+++ b/src/quicktemplates2/qquickmenu_p_p.h
@@ -98,4 +98,3 @@ public:
QT_END_NAMESPACE
#endif // QQUICKMENU_P_P_H
-
diff --git a/src/quicktemplates2/qquickmenuitem.cpp b/src/quicktemplates2/qquickmenuitem.cpp
index 59822b8e..e15640fb 100644
--- a/src/quicktemplates2/qquickmenuitem.cpp
+++ b/src/quicktemplates2/qquickmenuitem.cpp
@@ -93,8 +93,8 @@ public:
bool highlighted;
};
-QQuickMenuItemPrivate::QQuickMenuItemPrivate() :
- highlighted(false)
+QQuickMenuItemPrivate::QQuickMenuItemPrivate()
+ : highlighted(false)
{
}
@@ -104,8 +104,8 @@ QQuickMenuItemPrivate::QQuickMenuItemPrivate() :
This signal is emitted when the menu item is triggered by the user.
*/
-QQuickMenuItem::QQuickMenuItem(QQuickItem *parent) :
- QQuickAbstractButton(*(new QQuickMenuItemPrivate), parent)
+QQuickMenuItem::QQuickMenuItem(QQuickItem *parent)
+ : QQuickAbstractButton(*(new QQuickMenuItemPrivate), parent)
{
connect(this, &QQuickAbstractButton::clicked, this, &QQuickMenuItem::triggered);
}
@@ -141,7 +141,7 @@ void QQuickMenuItem::setHighlighted(bool highlighted)
emit highlightedChanged();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickMenuItem::accessibleRole() const
{
return QAccessible::MenuItem;
diff --git a/src/quicktemplates2/qquickmenuitem_p.h b/src/quicktemplates2/qquickmenuitem_p.h
index 96aaa28a..76f41f9d 100644
--- a/src/quicktemplates2/qquickmenuitem_p.h
+++ b/src/quicktemplates2/qquickmenuitem_p.h
@@ -72,7 +72,7 @@ Q_SIGNALS:
protected:
QFont defaultFont() const override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquickmenuseparator.cpp b/src/quicktemplates2/qquickmenuseparator.cpp
index 8e4c6384..366f0a27 100644
--- a/src/quicktemplates2/qquickmenuseparator.cpp
+++ b/src/quicktemplates2/qquickmenuseparator.cpp
@@ -65,12 +65,12 @@ QT_BEGIN_NAMESPACE
\sa {Customizing MenuSeparator}, {Separator Controls}
*/
-QQuickMenuSeparator::QQuickMenuSeparator(QQuickItem *parent) :
- QQuickControl(parent)
+QQuickMenuSeparator::QQuickMenuSeparator(QQuickItem *parent)
+ : QQuickControl(parent)
{
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickMenuSeparator::accessibleRole() const
{
return QAccessible::Separator;
diff --git a/src/quicktemplates2/qquickmenuseparator_p.h b/src/quicktemplates2/qquickmenuseparator_p.h
index dde88df3..42147f77 100644
--- a/src/quicktemplates2/qquickmenuseparator_p.h
+++ b/src/quicktemplates2/qquickmenuseparator_p.h
@@ -60,7 +60,7 @@ public:
explicit QQuickMenuSeparator(QQuickItem *parent = nullptr);
protected:
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquickoverlay.cpp b/src/quicktemplates2/qquickoverlay.cpp
index 12ecd284..e3910509 100644
--- a/src/quicktemplates2/qquickoverlay.cpp
+++ b/src/quicktemplates2/qquickoverlay.cpp
@@ -36,6 +36,7 @@
#include "qquickoverlay_p.h"
#include "qquickoverlay_p_p.h"
+#include "qquickpopupitem_p_p.h"
#include "qquickpopup_p_p.h"
#include "qquickdrawer_p_p.h"
#include "qquickapplicationwindow_p.h"
@@ -96,10 +97,12 @@ static QQuickItem *createDimmer(QQmlComponent *component, QQuickPopup *popup, QQ
item->setZ(popup->z());
if (popup->isModal()) {
item->setAcceptedMouseButtons(Qt::AllButtons);
+#if QT_CONFIG(quicktemplates2_hover)
// TODO: switch to QStyleHints::useHoverEffects in Qt 5.8
item->setAcceptHoverEvents(true);
// item->setAcceptHoverEvents(QGuiApplication::styleHints()->useHoverEffects());
// connect(QGuiApplication::styleHints(), &QStyleHints::useHoverEffectsChanged, item, &QQuickItem::setAcceptHoverEvents);
+#endif
}
if (component)
component->completeCreate();
@@ -169,9 +172,9 @@ void QQuickOverlayPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryC
q->setSize(QSizeF(item->width(), item->height()));
}
-QQuickOverlayPrivate::QQuickOverlayPrivate() :
- modal(nullptr),
- modeless(nullptr)
+QQuickOverlayPrivate::QQuickOverlayPrivate()
+ : modal(nullptr),
+ modeless(nullptr)
{
}
@@ -376,6 +379,7 @@ void QQuickOverlay::mouseReleaseEvent(QMouseEvent *event)
}
}
+#if QT_CONFIG(wheelevent)
void QQuickOverlay::wheelEvent(QWheelEvent *event)
{
Q_D(QQuickOverlay);
@@ -391,6 +395,7 @@ void QQuickOverlay::wheelEvent(QWheelEvent *event)
}
event->ignore();
}
+#endif
bool QQuickOverlay::childMouseEventFilter(QQuickItem *item, QEvent *event)
{
diff --git a/src/quicktemplates2/qquickoverlay_p.h b/src/quicktemplates2/qquickoverlay_p.h
index 45b261b7..793edf7e 100644
--- a/src/quicktemplates2/qquickoverlay_p.h
+++ b/src/quicktemplates2/qquickoverlay_p.h
@@ -87,7 +87,9 @@ protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
+#if QT_CONFIG(wheelevent)
void wheelEvent(QWheelEvent *event) override;
+#endif
bool childMouseEventFilter(QQuickItem *item, QEvent *event) override;
private:
diff --git a/src/quicktemplates2/qquickpage.cpp b/src/quicktemplates2/qquickpage.cpp
index 11d55444..701916b6 100644
--- a/src/quicktemplates2/qquickpage.cpp
+++ b/src/quicktemplates2/qquickpage.cpp
@@ -111,8 +111,8 @@ QQuickItem *QQuickPagePrivate::getContentItem()
return contentItem;
}
-QQuickPage::QQuickPage(QQuickItem *parent) :
- QQuickControl(*(new QQuickPagePrivate), parent)
+QQuickPage::QQuickPage(QQuickItem *parent)
+ : QQuickControl(*(new QQuickPagePrivate), parent)
{
Q_D(QQuickPage);
setFlag(ItemIsFocusScope);
@@ -357,7 +357,7 @@ void QQuickPage::spacingChange(qreal newSpacing, qreal oldSpacing)
d->layout->update();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickPage::accessibleRole() const
{
return QAccessible::PageTab;
diff --git a/src/quicktemplates2/qquickpage_p.h b/src/quicktemplates2/qquickpage_p.h
index e2d16adc..90d10e4a 100644
--- a/src/quicktemplates2/qquickpage_p.h
+++ b/src/quicktemplates2/qquickpage_p.h
@@ -102,7 +102,7 @@ protected:
void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding) override;
void spacingChange(qreal newSpacing, qreal oldSpacing) override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
void accessibilityActiveChanged(bool active) override;
#endif
diff --git a/src/quicktemplates2/qquickpageindicator.cpp b/src/quicktemplates2/qquickpageindicator.cpp
index e6e2a01d..92b6c0c0 100644
--- a/src/quicktemplates2/qquickpageindicator.cpp
+++ b/src/quicktemplates2/qquickpageindicator.cpp
@@ -89,8 +89,12 @@ class QQuickPageIndicatorPrivate : public QQuickControlPrivate, public QQuickIte
Q_DECLARE_PUBLIC(QQuickPageIndicator)
public:
- QQuickPageIndicatorPrivate() : count(0), currentIndex(0),
- interactive(false), delegate(nullptr), pressedItem(nullptr)
+ QQuickPageIndicatorPrivate()
+ : count(0),
+ currentIndex(0),
+ interactive(false),
+ delegate(nullptr),
+ pressedItem(nullptr)
{
}
@@ -166,8 +170,8 @@ void QQuickPageIndicatorPrivate::itemChildAdded(QQuickItem *, QQuickItem *child)
setContextProperty(child, QStringLiteral("pressed"), false);
}
-QQuickPageIndicator::QQuickPageIndicator(QQuickItem *parent) :
- QQuickControl(*(new QQuickPageIndicatorPrivate), parent)
+QQuickPageIndicator::QQuickPageIndicator(QQuickItem *parent)
+ : QQuickControl(*(new QQuickPageIndicatorPrivate), parent)
{
}
@@ -320,7 +324,7 @@ void QQuickPageIndicator::mouseUngrabEvent()
d->updatePressed(false);
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickPageIndicator::accessibleRole() const
{
return QAccessible::Indicator;
diff --git a/src/quicktemplates2/qquickpageindicator_p.h b/src/quicktemplates2/qquickpageindicator_p.h
index f1d76d5d..921fe7e8 100644
--- a/src/quicktemplates2/qquickpageindicator_p.h
+++ b/src/quicktemplates2/qquickpageindicator_p.h
@@ -92,7 +92,7 @@ protected:
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseUngrabEvent() override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquickpagelayout.cpp b/src/quicktemplates2/qquickpagelayout.cpp
index 18317af8..99d4fe23 100644
--- a/src/quicktemplates2/qquickpagelayout.cpp
+++ b/src/quicktemplates2/qquickpagelayout.cpp
@@ -74,7 +74,9 @@ static void setPosition(QQuickItem *item, Position position)
}
QQuickPageLayout::QQuickPageLayout(QQuickControl *control)
- : m_header(nullptr), m_footer(nullptr), m_control(control)
+ : m_header(nullptr),
+ m_footer(nullptr),
+ m_control(control)
{
}
diff --git a/src/quicktemplates2/qquickpane.cpp b/src/quicktemplates2/qquickpane.cpp
index 57200121..6cb81316 100644
--- a/src/quicktemplates2/qquickpane.cpp
+++ b/src/quicktemplates2/qquickpane.cpp
@@ -104,7 +104,9 @@ QT_BEGIN_NAMESPACE
\sa {Customizing Pane}, {Container Controls}
*/
-QQuickPanePrivate::QQuickPanePrivate() : contentWidth(0), contentHeight(0)
+QQuickPanePrivate::QQuickPanePrivate()
+ : contentWidth(0),
+ contentHeight(0)
{
}
@@ -116,15 +118,15 @@ QQuickItem *QQuickPanePrivate::getContentItem()
return contentItem;
}
-QQuickPane::QQuickPane(QQuickItem *parent) :
- QQuickControl(*(new QQuickPanePrivate), parent)
+QQuickPane::QQuickPane(QQuickItem *parent)
+ : QQuickControl(*(new QQuickPanePrivate), parent)
{
setFlag(QQuickItem::ItemIsFocusScope);
setAcceptedMouseButtons(Qt::AllButtons);
}
-QQuickPane::QQuickPane(QQuickPanePrivate &dd, QQuickItem *parent) :
- QQuickControl(dd, parent)
+QQuickPane::QQuickPane(QQuickPanePrivate &dd, QQuickItem *parent)
+ : QQuickControl(dd, parent)
{
setFlag(QQuickItem::ItemIsFocusScope);
setAcceptedMouseButtons(Qt::AllButtons);
@@ -239,7 +241,7 @@ void QQuickPane::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
emit contentChildrenChanged();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickPane::accessibleRole() const
{
return QAccessible::Pane;
diff --git a/src/quicktemplates2/qquickpane_p.h b/src/quicktemplates2/qquickpane_p.h
index c0b04edb..759c59d8 100644
--- a/src/quicktemplates2/qquickpane_p.h
+++ b/src/quicktemplates2/qquickpane_p.h
@@ -86,7 +86,7 @@ protected:
void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp
index b07adeb6..9cdb194e 100644
--- a/src/quicktemplates2/qquickpopup.cpp
+++ b/src/quicktemplates2/qquickpopup.cpp
@@ -36,14 +36,13 @@
#include "qquickpopup_p.h"
#include "qquickpopup_p_p.h"
+#include "qquickpopupitem_p_p.h"
+#include "qquickpopuppositioner_p_p.h"
#include "qquickapplicationwindow_p.h"
-#include "qquickshortcutcontext_p_p.h"
#include "qquickoverlay_p_p.h"
#include "qquickcontrol_p_p.h"
#include "qquickdialog_p.h"
-#include <QtGui/private/qshortcutmap_p.h>
-#include <QtGui/private/qguiapplication_p.h>
#include <QtQml/qqmlinfo.h>
#include <QtQuick/qquickitem.h>
#include <QtQuick/private/qquicktransition_p.h>
@@ -188,56 +187,49 @@ QT_BEGIN_NAMESPACE
\sa opened
*/
-static const QQuickItemPrivate::ChangeTypes AncestorChangeTypes = QQuickItemPrivate::Geometry
- | QQuickItemPrivate::Parent
- | QQuickItemPrivate::Children;
-
-static const QQuickItemPrivate::ChangeTypes ItemChangeTypes = QQuickItemPrivate::Geometry
- | QQuickItemPrivate::Parent;
-
QQuickPopupPrivate::QQuickPopupPrivate()
- : QObjectPrivate()
- , focus(false)
- , modal(false)
- , dim(false)
- , hasDim(false)
- , visible(false)
- , complete(false)
- , positioning(false)
- , hasWidth(false)
- , hasHeight(false)
- , hasTopMargin(false)
- , hasLeftMargin(false)
- , hasRightMargin(false)
- , hasBottomMargin(false)
- , allowVerticalFlip(false)
- , allowHorizontalFlip(false)
- , allowVerticalMove(true)
- , allowHorizontalMove(true)
- , allowVerticalResize(true)
- , allowHorizontalResize(true)
- , hadActiveFocusBeforeExitTransition(false)
- , x(0)
- , y(0)
- , effectiveX(0)
- , effectiveY(0)
- , margins(-1)
- , topMargin(0)
- , leftMargin(0)
- , rightMargin(0)
- , bottomMargin(0)
- , contentWidth(0)
- , contentHeight(0)
- , transitionState(QQuickPopupPrivate::NoTransition)
- , closePolicy(QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutside)
- , parentItem(nullptr)
- , dimmer(nullptr)
- , window(nullptr)
- , enter(nullptr)
- , exit(nullptr)
- , popupItem(nullptr)
- , positioner(this)
- , transitionManager(this)
+ : focus(false),
+ modal(false),
+ dim(false),
+ hasDim(false),
+ visible(false),
+ complete(false),
+ positioning(false),
+ hasWidth(false),
+ hasHeight(false),
+ hasTopMargin(false),
+ hasLeftMargin(false),
+ hasRightMargin(false),
+ hasBottomMargin(false),
+ allowVerticalFlip(false),
+ allowHorizontalFlip(false),
+ allowVerticalMove(true),
+ allowHorizontalMove(true),
+ allowVerticalResize(true),
+ allowHorizontalResize(true),
+ hadActiveFocusBeforeExitTransition(false),
+ interactive(true),
+ x(0),
+ y(0),
+ effectiveX(0),
+ effectiveY(0),
+ margins(-1),
+ topMargin(0),
+ leftMargin(0),
+ rightMargin(0),
+ bottomMargin(0),
+ contentWidth(0),
+ contentHeight(0),
+ transitionState(QQuickPopupPrivate::NoTransition),
+ closePolicy(QQuickPopup::CloseOnEscape | QQuickPopup::CloseOnPressOutside),
+ parentItem(nullptr),
+ dimmer(nullptr),
+ window(nullptr),
+ enter(nullptr),
+ exit(nullptr),
+ popupItem(nullptr),
+ positioner(nullptr),
+ transitionManager(this)
{
}
@@ -251,26 +243,30 @@ void QQuickPopupPrivate::init()
popupItem = new QQuickPopupItem(q);
q->setParentItem(qobject_cast<QQuickItem *>(parent));
QObject::connect(popupItem, &QQuickControl::paddingChanged, q, &QQuickPopup::paddingChanged);
+ positioner = new QQuickPopupPositioner(q);
}
-static void closeOrReject(QQuickPopup *popup)
+void QQuickPopupPrivate::closeOrReject()
{
- if (QQuickDialog *dialog = qobject_cast<QQuickDialog*>(popup))
+ Q_Q(QQuickPopup);
+ if (QQuickDialog *dialog = qobject_cast<QQuickDialog*>(q))
dialog->reject();
else
- popup->close();
+ q->close();
}
bool QQuickPopupPrivate::tryClose(QQuickItem *item, QMouseEvent *event)
{
- Q_Q(QQuickPopup);
+ if (!interactive)
+ return false;
+
const bool isPress = event->type() == QEvent::MouseButtonPress;
const bool onOutside = closePolicy.testFlag(isPress ? QQuickPopup::CloseOnPressOutside : QQuickPopup::CloseOnReleaseOutside);
const bool onOutsideParent = closePolicy.testFlag(isPress ? QQuickPopup::CloseOnPressOutsideParent : QQuickPopup::CloseOnReleaseOutsideParent);
if (onOutside || onOutsideParent) {
if (!popupItem->contains(item->mapToItem(popupItem, event->pos()))) {
if (!onOutsideParent || !parentItem || !parentItem->contains(item->mapToItem(parentItem, event->pos()))) {
- closeOrReject(q);
+ closeOrReject();
return true;
}
}
@@ -282,7 +278,7 @@ bool QQuickPopupPrivate::prepareEnterTransition()
{
Q_Q(QQuickPopup);
if (!window) {
- qmlInfo(q) << "cannot find any window to open popup in.";
+ qmlWarning(q) << "cannot find any window to open popup in.";
return false;
}
@@ -295,7 +291,7 @@ bool QQuickPopupPrivate::prepareEnterTransition()
visible = true;
transitionState = EnterTransition;
popupItem->setVisible(true);
- positioner.setParentItem(parentItem);
+ positioner->setParentItem(parentItem);
emit q->visibleChanged();
}
return true;
@@ -332,7 +328,7 @@ void QQuickPopupPrivate::finalizeEnterTransition()
void QQuickPopupPrivate::finalizeExitTransition()
{
Q_Q(QQuickPopup);
- positioner.setParentItem(nullptr);
+ positioner->setParentItem(nullptr);
popupItem->setParentItem(nullptr);
popupItem->setVisible(false);
@@ -436,314 +432,6 @@ void QQuickPopupPrivate::setWindow(QQuickWindow *newWindow)
transitionManager.transitionEnter();
}
-class QQuickPopupItemPrivate : public QQuickControlPrivate
-{
- Q_DECLARE_PUBLIC(QQuickPopupItem)
-
-public:
- QQuickPopupItemPrivate(QQuickPopup *popup);
-
- void implicitWidthChanged() override;
- void implicitHeightChanged() override;
-
- void resolveFont() override;
-
- QQuickItem *getContentItem() override;
-
- int backId;
- int escapeId;
- QQuickPopup *popup;
-};
-
-QQuickPopupItemPrivate::QQuickPopupItemPrivate(QQuickPopup *popup)
- : backId(0),
- escapeId(0),
- popup(popup)
-{
- isTabFence = true;
-}
-
-void QQuickPopupItemPrivate::implicitWidthChanged()
-{
- QQuickControlPrivate::implicitWidthChanged();
- emit popup->implicitWidthChanged();
-}
-
-void QQuickPopupItemPrivate::implicitHeightChanged()
-{
- QQuickControlPrivate::implicitHeightChanged();
- emit popup->implicitHeightChanged();
-}
-
-void QQuickPopupItemPrivate::resolveFont()
-{
- if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(popup->window()))
- inheritFont(window->font());
-}
-
-QQuickItem *QQuickPopupItemPrivate::getContentItem()
-{
- Q_Q(QQuickPopupItem);
- if (!contentItem)
- contentItem = new QQuickItem(q);
- return contentItem;
-}
-
-QQuickPopupItem::QQuickPopupItem(QQuickPopup *popup) :
- QQuickControl(*(new QQuickPopupItemPrivate(popup)), nullptr)
-{
- setParent(popup);
- setVisible(false);
- setFlag(ItemIsFocusScope);
- setAcceptedMouseButtons(Qt::AllButtons);
-
- // TODO: switch to QStyleHints::useHoverEffects in Qt 5.8
- setHoverEnabled(true);
- // setAcceptHoverEvents(QGuiApplication::styleHints()->useHoverEffects());
- // connect(QGuiApplication::styleHints(), &QStyleHints::useHoverEffectsChanged, this, &QQuickItem::setAcceptHoverEvents);
-}
-
-void QQuickPopupItem::updatePolish()
-{
- Q_D(QQuickPopupItem);
- return QQuickPopupPrivate::get(d->popup)->reposition();
-}
-
-void QQuickPopupItem::grabShortcut()
-{
-#ifndef QT_NO_SHORTCUT
- Q_D(QQuickPopupItem);
- QGuiApplicationPrivate *pApp = QGuiApplicationPrivate::instance();
- if (!d->backId)
- d->backId = pApp->shortcutMap.addShortcut(this, Qt::Key_Back, Qt::WindowShortcut, QQuickShortcutContext::matcher);
- if (!d->escapeId)
- d->escapeId = pApp->shortcutMap.addShortcut(this, Qt::Key_Escape, Qt::WindowShortcut, QQuickShortcutContext::matcher);
-#endif // QT_NO_SHORTCUT
-}
-
-void QQuickPopupItem::ungrabShortcut()
-{
-#ifndef QT_NO_SHORTCUT
- Q_D(QQuickPopupItem);
- QGuiApplicationPrivate *pApp = QGuiApplicationPrivate::instance();
- if (d->backId) {
- pApp->shortcutMap.removeShortcut(d->backId, this);
- d->backId = 0;
- }
- if (d->escapeId) {
- pApp->shortcutMap.removeShortcut(d->escapeId, this);
- d->escapeId = 0;
- }
-#endif // QT_NO_SHORTCUT
-}
-
-bool QQuickPopupItem::event(QEvent *event)
-{
- Q_D(QQuickPopupItem);
- if (event->type() == QEvent::Shortcut) {
- QShortcutEvent *se = static_cast<QShortcutEvent *>(event);
- if (se->shortcutId() == d->escapeId || se->shortcutId() == d->backId) {
- closeOrReject(d->popup);
- return true;
- }
- }
- return QQuickItem::event(event);
-}
-
-bool QQuickPopupItem::childMouseEventFilter(QQuickItem *child, QEvent *event)
-{
- Q_D(QQuickPopupItem);
- return d->popup->childMouseEventFilter(child, event);
-}
-
-void QQuickPopupItem::focusInEvent(QFocusEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->focusInEvent(event);
-}
-
-void QQuickPopupItem::focusOutEvent(QFocusEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->focusOutEvent(event);
-}
-
-void QQuickPopupItem::keyPressEvent(QKeyEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->keyPressEvent(event);
-}
-
-void QQuickPopupItem::keyReleaseEvent(QKeyEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->keyReleaseEvent(event);
-}
-
-void QQuickPopupItem::mousePressEvent(QMouseEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->mousePressEvent(event);
-}
-
-void QQuickPopupItem::mouseMoveEvent(QMouseEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->mouseMoveEvent(event);
-}
-
-void QQuickPopupItem::mouseReleaseEvent(QMouseEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->mouseReleaseEvent(event);
-}
-
-void QQuickPopupItem::mouseDoubleClickEvent(QMouseEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->mouseDoubleClickEvent(event);
-}
-
-void QQuickPopupItem::mouseUngrabEvent()
-{
- Q_D(QQuickPopupItem);
- d->popup->mouseUngrabEvent();
-}
-
-void QQuickPopupItem::wheelEvent(QWheelEvent *event)
-{
- Q_D(QQuickPopupItem);
- d->popup->wheelEvent(event);
-}
-
-void QQuickPopupItem::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::contentItemChange(newItem, oldItem);
- d->popup->contentItemChange(newItem, oldItem);
-}
-
-void QQuickPopupItem::fontChange(const QFont &newFont, const QFont &oldFont)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::fontChange(newFont, oldFont);
- d->popup->fontChange(newFont, oldFont);
-}
-
-void QQuickPopupItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::geometryChanged(newGeometry, oldGeometry);
- d->popup->geometryChanged(newGeometry, oldGeometry);
-}
-
-void QQuickPopupItem::localeChange(const QLocale &newLocale, const QLocale &oldLocale)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::localeChange(newLocale, oldLocale);
- d->popup->localeChange(newLocale, oldLocale);
-}
-
-void QQuickPopupItem::itemChange(ItemChange change, const ItemChangeData &data)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::itemChange(change, data);
- d->popup->itemChange(change, data);
-}
-
-void QQuickPopupItem::paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::paddingChange(newPadding, oldPadding);
- d->popup->paddingChange(newPadding, oldPadding);
-}
-
-void QQuickPopupItem::spacingChange(qreal newSpacing, qreal oldSpacing)
-{
- Q_D(QQuickPopupItem);
- QQuickControl::spacingChange(newSpacing, oldSpacing);
- d->popup->spacingChange(newSpacing, oldSpacing);
-}
-
-QFont QQuickPopupItem::defaultFont() const
-{
- Q_D(const QQuickPopupItem);
- return d->popup->defaultFont();
-}
-
-#ifndef QT_NO_ACCESSIBILITY
-QAccessible::Role QQuickPopupItem::accessibleRole() const
-{
- Q_D(const QQuickPopupItem);
- return d->popup->accessibleRole();
-}
-
-void QQuickPopupItem::accessibilityActiveChanged(bool active)
-{
- Q_D(const QQuickPopupItem);
- QQuickControl::accessibilityActiveChanged(active);
- d->popup->accessibilityActiveChanged(active);
-}
-#endif // QT_NO_ACCESSIBILITY
-
-QQuickPopupPositioner::QQuickPopupPositioner(QQuickPopupPrivate *popup) :
- m_parentItem(nullptr),
- m_popup(popup)
-{
-}
-
-QQuickPopupPositioner::~QQuickPopupPositioner()
-{
- if (m_parentItem) {
- QQuickItemPrivate::get(m_parentItem)->removeItemChangeListener(this, ItemChangeTypes);
- removeAncestorListeners(m_parentItem->parentItem());
- }
-}
-
-QQuickItem *QQuickPopupPositioner::parentItem() const
-{
- return m_parentItem;
-}
-
-void QQuickPopupPositioner::setParentItem(QQuickItem *parent)
-{
- if (m_parentItem == parent)
- return;
-
- if (m_parentItem) {
- QQuickItemPrivate::get(m_parentItem)->removeItemChangeListener(this, ItemChangeTypes);
- removeAncestorListeners(m_parentItem->parentItem());
- }
-
- m_parentItem = parent;
-
- if (!parent)
- return;
-
- QQuickItemPrivate::get(parent)->addItemChangeListener(this, ItemChangeTypes);
- addAncestorListeners(parent->parentItem());
-
- if (m_popup->popupItem->isVisible())
- m_popup->reposition();
-}
-
-void QQuickPopupPositioner::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &)
-{
- if (m_parentItem && m_popup->popupItem->isVisible())
- m_popup->reposition();
-}
-
-void QQuickPopupPositioner::itemParentChanged(QQuickItem *, QQuickItem *parent)
-{
- addAncestorListeners(parent);
-}
-
-void QQuickPopupPositioner::itemChildRemoved(QQuickItem *item, QQuickItem *child)
-{
- if (isAncestor(child))
- removeAncestorListeners(item);
-}
-
void QQuickPopupPrivate::itemDestroyed(QQuickItem *item)
{
Q_Q(QQuickPopup);
@@ -753,143 +441,7 @@ void QQuickPopupPrivate::itemDestroyed(QQuickItem *item)
void QQuickPopupPrivate::reposition()
{
- Q_Q(QQuickPopup);
- if (!popupItem->isVisible())
- return;
-
- if (positioning) {
- popupItem->polish();
- return;
- }
-
- const qreal w = popupItem->width();
- const qreal h = popupItem->height();
- const qreal iw = popupItem->implicitWidth();
- const qreal ih = popupItem->implicitHeight();
-
- bool widthAdjusted = false;
- bool heightAdjusted = false;
-
- QRectF rect(allowHorizontalMove ? x : popupItem->x(),
- allowVerticalMove ? y : popupItem->y(),
- !hasWidth && iw > 0 ? iw : w,
- !hasHeight && ih > 0 ? ih : h);
- if (parentItem) {
- rect = parentItem->mapRectToScene(rect);
-
- if (window) {
- const QMarginsF margins = getMargins();
- const QRectF bounds(qMax<qreal>(0.0, margins.left()),
- qMax<qreal>(0.0, margins.top()),
- window->width() - qMax<qreal>(0.0, margins.left()) - qMax<qreal>(0.0, margins.right()),
- window->height() - qMax<qreal>(0.0, margins.top()) - qMax<qreal>(0.0, margins.bottom()));
-
- // if the popup doesn't fit horizontally inside the window, try flipping it around (left <-> right)
- if (allowHorizontalFlip && (rect.left() < bounds.left() || rect.right() > bounds.right())) {
- const QRectF flipped = parentItem->mapRectToScene(QRectF(parentItem->width() - x - rect.width(), y, rect.width(), rect.height()));
- if (flipped.intersected(bounds).width() > rect.intersected(bounds).width())
- rect.moveLeft(flipped.left());
- }
-
- // if the popup doesn't fit vertically inside the window, try flipping it around (above <-> below)
- if (allowVerticalFlip && (rect.top() < bounds.top() || rect.bottom() > bounds.bottom())) {
- const QRectF flipped = parentItem->mapRectToScene(QRectF(x, parentItem->height() - y - rect.height(), rect.width(), rect.height()));
- if (flipped.intersected(bounds).height() > rect.intersected(bounds).height())
- rect.moveTop(flipped.top());
- }
-
- // push inside the margins if specified
- if (allowVerticalMove) {
- if (margins.top() >= 0 && rect.top() < bounds.top())
- rect.moveTop(margins.top());
- if (margins.bottom() >= 0 && rect.bottom() > bounds.bottom())
- rect.moveBottom(bounds.bottom());
- }
- if (allowHorizontalMove) {
- if (margins.left() >= 0 && rect.left() < bounds.left())
- rect.moveLeft(margins.left());
- if (margins.right() >= 0 && rect.right() > bounds.right())
- rect.moveRight(bounds.right());
- }
-
- if (iw > 0 && (rect.left() < bounds.left() || rect.right() > bounds.right())) {
- // neither the flipped or pushed geometry fits inside the window, choose
- // whichever side (left vs. right) fits larger part of the popup
- if (allowHorizontalMove && allowHorizontalFlip) {
- if (rect.left() < bounds.left() && bounds.left() + rect.width() <= bounds.right())
- rect.moveLeft(bounds.left());
- else if (rect.right() > bounds.right() && bounds.right() - rect.width() >= bounds.left())
- rect.moveRight(bounds.right());
- }
-
- // as a last resort, adjust the width to fit the window
- if (allowHorizontalResize) {
- if (rect.left() < bounds.left()) {
- rect.setLeft(bounds.left());
- widthAdjusted = true;
- }
- if (rect.right() > bounds.right()) {
- rect.setRight(bounds.right());
- widthAdjusted = true;
- }
- }
- } else if (iw > 0 && rect.left() >= bounds.left() && rect.right() <= bounds.right()
- && iw != w) {
- // restore original width
- rect.setWidth(iw);
- widthAdjusted = true;
- }
-
- if (ih > 0 && (rect.top() < bounds.top() || rect.bottom() > bounds.bottom())) {
- // neither the flipped or pushed geometry fits inside the window, choose
- // whichever side (above vs. below) fits larger part of the popup
- if (allowVerticalMove && allowVerticalFlip) {
- if (rect.top() < bounds.top() && bounds.top() + rect.height() <= bounds.bottom())
- rect.moveTop(bounds.top());
- else if (rect.bottom() > bounds.bottom() && bounds.bottom() - rect.height() >= bounds.top())
- rect.moveBottom(bounds.bottom());
- }
-
- // as a last resort, adjust the height to fit the window
- if (allowVerticalResize) {
- if (rect.top() < bounds.top()) {
- rect.setTop(bounds.top());
- heightAdjusted = true;
- }
- if (rect.bottom() > bounds.bottom()) {
- rect.setBottom(bounds.bottom());
- heightAdjusted = true;
- }
- }
- } else if (ih > 0 && rect.top() >= bounds.top() && rect.bottom() <= bounds.bottom()
- && ih != h) {
- // restore original height
- rect.setHeight(ih);
- heightAdjusted = true;
- }
- }
- }
-
- positioning = true;
-
- popupItem->setPosition(rect.topLeft());
-
- const QPointF effectivePos = parentItem ? parentItem->mapFromScene(rect.topLeft()) : rect.topLeft();
- if (!qFuzzyCompare(effectiveX, effectivePos.x())) {
- effectiveX = effectivePos.x();
- emit q->xChanged();
- }
- if (!qFuzzyCompare(effectiveY, effectivePos.y())) {
- effectiveY = effectivePos.y();
- emit q->yChanged();
- }
-
- if (!hasWidth && widthAdjusted && rect.width() > 0)
- popupItem->setWidth(rect.width());
- if (!hasHeight && heightAdjusted && rect.height() > 0)
- popupItem->setHeight(rect.height());
-
- positioning = false;
+ positioner->reposition();
}
void QQuickPopupPrivate::resizeOverlay()
@@ -902,45 +454,6 @@ void QQuickPopupPrivate::resizeOverlay()
dimmer->setSize(QSizeF(w, h));
}
-void QQuickPopupPositioner::removeAncestorListeners(QQuickItem *item)
-{
- if (item == m_parentItem)
- return;
-
- QQuickItem *p = item;
- while (p) {
- QQuickItemPrivate::get(p)->removeItemChangeListener(this, AncestorChangeTypes);
- p = p->parentItem();
- }
-}
-
-void QQuickPopupPositioner::addAncestorListeners(QQuickItem *item)
-{
- if (item == m_parentItem)
- return;
-
- QQuickItem *p = item;
- while (p) {
- QQuickItemPrivate::get(p)->addItemChangeListener(this, AncestorChangeTypes);
- p = p->parentItem();
- }
-}
-
-// TODO: use QQuickItem::isAncestorOf() in dev/5.7
-bool QQuickPopupPositioner::isAncestor(QQuickItem *item) const
-{
- if (!m_parentItem)
- return false;
-
- QQuickItem *parent = m_parentItem;
- while (parent) {
- if (parent == item)
- return true;
- parent = parent->parentItem();
- }
- return false;
-}
-
QQuickPopupTransitionManager::QQuickPopupTransitionManager(QQuickPopupPrivate *popup)
: QQuickTransitionManager(), popup(popup)
{
@@ -1722,8 +1235,8 @@ void QQuickPopup::setParentItem(QQuickItem *parent)
QQuickItemPrivate::get(d->parentItem)->removeItemChangeListener(d, QQuickItemPrivate::Destroyed);
}
d->parentItem = parent;
- if (d->positioner.parentItem())
- d->positioner.setParentItem(parent);
+ if (d->positioner->parentItem())
+ d->positioner->setParentItem(parent);
if (parent) {
QObjectPrivate::connect(parent, &QQuickItem::windowChanged, d, &QQuickPopupPrivate::setWindow);
QQuickItemPrivate::get(d->parentItem)->addItemChangeListener(d, QQuickItemPrivate::Destroyed);
@@ -2323,10 +1836,12 @@ bool QQuickPopup::overlayEvent(QQuickItem *item, QEvent *event)
}
}
+#if QT_CONFIG(wheelevent)
void QQuickPopup::wheelEvent(QWheelEvent *event)
{
event->accept();
}
+#endif
void QQuickPopup::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
{
@@ -2428,7 +1943,7 @@ QFont QQuickPopup::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::SystemFont);
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickPopup::accessibleRole() const
{
return QAccessible::Dialog;
@@ -2438,7 +1953,7 @@ void QQuickPopup::accessibilityActiveChanged(bool active)
{
Q_UNUSED(active);
}
-#endif // QT_NO_ACCESSIBILITY
+#endif
QString QQuickPopup::accessibleName() const
{
@@ -2465,5 +1980,3 @@ bool QQuickPopup::setAccessibleProperty(const char *propertyName, const QVariant
}
QT_END_NAMESPACE
-
-#include "moc_qquickpopup_p.cpp"
diff --git a/src/quicktemplates2/qquickpopup_p.h b/src/quicktemplates2/qquickpopup_p.h
index 56dd3086..d1b0dfac 100644
--- a/src/quicktemplates2/qquickpopup_p.h
+++ b/src/quicktemplates2/qquickpopup_p.h
@@ -59,7 +59,7 @@
#include <QtQml/qqmlparserstatus.h>
#include <QtQuick/qquickitem.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <QtGui/qaccessible.h>
#endif
@@ -351,7 +351,9 @@ protected:
virtual void mouseDoubleClickEvent(QMouseEvent *event);
virtual void mouseUngrabEvent();
virtual bool overlayEvent(QQuickItem *item, QEvent *event);
+#if QT_CONFIG(wheelevent)
virtual void wheelEvent(QWheelEvent *event);
+#endif
virtual void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem);
virtual void fontChange(const QFont &newFont, const QFont &oldFont);
@@ -364,7 +366,7 @@ protected:
virtual QFont defaultFont() const;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
virtual QAccessible::Role accessibleRole() const;
virtual void accessibilityActiveChanged(bool active);
#endif
diff --git a/src/quicktemplates2/qquickpopup_p_p.h b/src/quicktemplates2/qquickpopup_p_p.h
index 29c9f42e..084642ec 100644
--- a/src/quicktemplates2/qquickpopup_p_p.h
+++ b/src/quicktemplates2/qquickpopup_p_p.h
@@ -61,8 +61,9 @@ QT_BEGIN_NAMESPACE
class QQuickTransition;
class QQuickTransitionManager;
class QQuickPopup;
+class QQuickPopupItem;
class QQuickPopupPrivate;
-class QQuickPopupItemPrivate;
+class QQuickPopupPositioner;
class QQuickPopupTransitionManager : public QQuickTransitionManager
{
@@ -79,77 +80,6 @@ private:
QQuickPopupPrivate *popup;
};
-class QQuickPopupItem : public QQuickControl
-{
- Q_OBJECT
-
-public:
- explicit QQuickPopupItem(QQuickPopup *popup);
-
- void grabShortcut();
- void ungrabShortcut();
-
-protected:
- void updatePolish() override;
-
- bool event(QEvent *event) override;
- bool childMouseEventFilter(QQuickItem *child, QEvent *event) override;
- void focusInEvent(QFocusEvent *event) override;
- void focusOutEvent(QFocusEvent *event) override;
- void keyPressEvent(QKeyEvent *event) override;
- void keyReleaseEvent(QKeyEvent *event) override;
- void mousePressEvent(QMouseEvent *event) override;
- void mouseMoveEvent(QMouseEvent *event) override;
- void mouseReleaseEvent(QMouseEvent *event) override;
- void mouseDoubleClickEvent(QMouseEvent *event) override;
- void mouseUngrabEvent() override;
- void wheelEvent(QWheelEvent *event) override;
-
- void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override;
- void fontChange(const QFont &newFont, const QFont &oldFont) override;
- void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
- void localeChange(const QLocale &newLocale, const QLocale &oldLocale) override;
- void itemChange(ItemChange change, const ItemChangeData &data) override;
- void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding) override;
- void spacingChange(qreal newSpacing, qreal oldSpacing) override;
-
- QFont defaultFont() const override;
-
-#ifndef QT_NO_ACCESSIBILITY
- QAccessible::Role accessibleRole() const override;
- void accessibilityActiveChanged(bool active) override;
-#endif
-
-private:
- Q_DECLARE_PRIVATE(QQuickPopupItem)
-
- friend class QQuickPopup;
-};
-
-class QQuickPopupPositioner : public QQuickItemChangeListener
-{
-public:
- explicit QQuickPopupPositioner(QQuickPopupPrivate *popup);
- ~QQuickPopupPositioner();
-
- QQuickItem *parentItem() const;
- void setParentItem(QQuickItem *parent);
-
-protected:
- void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) override;
- void itemParentChanged(QQuickItem *, QQuickItem *parent) override;
- void itemChildRemoved(QQuickItem *, QQuickItem *child) override;
-
-private:
- void removeAncestorListeners(QQuickItem *item);
- void addAncestorListeners(QQuickItem *item);
-
- bool isAncestor(QQuickItem *item) const;
-
- QQuickItem *m_parentItem;
- QQuickPopupPrivate *m_popup;
-};
-
class Q_AUTOTEST_EXPORT QQuickPopupPrivate : public QObjectPrivate, public QQuickItemChangeListener
{
Q_DECLARE_PUBLIC(QQuickPopup)
@@ -164,6 +94,7 @@ public:
}
void init();
+ void closeOrReject();
bool tryClose(QQuickItem *item, QMouseEvent *event);
virtual void reposition();
virtual void resizeOverlay();
@@ -207,6 +138,7 @@ public:
bool allowVerticalResize;
bool allowHorizontalResize;
bool hadActiveFocusBeforeExitTransition;
+ bool interactive;
qreal x;
qreal y;
qreal effectiveX;
@@ -226,7 +158,7 @@ public:
QQuickTransition *enter;
QQuickTransition *exit;
QQuickPopupItem *popupItem;
- QQuickPopupPositioner positioner;
+ QQuickPopupPositioner *positioner;
QList<QQuickStateAction> enterActions;
QList<QQuickStateAction> exitActions;
QQuickPopupTransitionManager transitionManager;
diff --git a/src/quicktemplates2/qquickpopupitem.cpp b/src/quicktemplates2/qquickpopupitem.cpp
new file mode 100644
index 00000000..94bd7dec
--- /dev/null
+++ b/src/quicktemplates2/qquickpopupitem.cpp
@@ -0,0 +1,303 @@
+/****************************************************************************
+**
+** 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 "qquickpopupitem_p_p.h"
+#include "qquickapplicationwindow_p.h"
+#include "qquickshortcutcontext_p_p.h"
+#include "qquickcontrol_p_p.h"
+#include "qquickpopup_p_p.h"
+
+#include <QtGui/private/qshortcutmap_p.h>
+#include <QtGui/private/qguiapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickPopupItemPrivate : public QQuickControlPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickPopupItem)
+
+public:
+ QQuickPopupItemPrivate(QQuickPopup *popup);
+
+ void implicitWidthChanged() override;
+ void implicitHeightChanged() override;
+
+ void resolveFont() override;
+
+ QQuickItem *getContentItem() override;
+
+ int backId;
+ int escapeId;
+ QQuickPopup *popup;
+};
+
+QQuickPopupItemPrivate::QQuickPopupItemPrivate(QQuickPopup *popup)
+ : backId(0),
+ escapeId(0),
+ popup(popup)
+{
+ isTabFence = true;
+}
+
+void QQuickPopupItemPrivate::implicitWidthChanged()
+{
+ QQuickControlPrivate::implicitWidthChanged();
+ emit popup->implicitWidthChanged();
+}
+
+void QQuickPopupItemPrivate::implicitHeightChanged()
+{
+ QQuickControlPrivate::implicitHeightChanged();
+ emit popup->implicitHeightChanged();
+}
+
+void QQuickPopupItemPrivate::resolveFont()
+{
+ if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(popup->window()))
+ inheritFont(window->font());
+}
+
+QQuickItem *QQuickPopupItemPrivate::getContentItem()
+{
+ Q_Q(QQuickPopupItem);
+ if (!contentItem)
+ contentItem = new QQuickItem(q);
+ return contentItem;
+}
+
+QQuickPopupItem::QQuickPopupItem(QQuickPopup *popup)
+ : QQuickControl(*(new QQuickPopupItemPrivate(popup)), nullptr)
+{
+ setParent(popup);
+ setVisible(false);
+ setFlag(ItemIsFocusScope);
+ setAcceptedMouseButtons(Qt::AllButtons);
+#if QT_CONFIG(cursor)
+ setCursor(Qt::ArrowCursor);
+#endif
+
+#if QT_CONFIG(quicktemplates2_hover)
+ // TODO: switch to QStyleHints::useHoverEffects in Qt 5.8
+ setHoverEnabled(true);
+ // setAcceptHoverEvents(QGuiApplication::styleHints()->useHoverEffects());
+ // connect(QGuiApplication::styleHints(), &QStyleHints::useHoverEffectsChanged, this, &QQuickItem::setAcceptHoverEvents);
+#endif
+}
+
+void QQuickPopupItem::grabShortcut()
+{
+#if QT_CONFIG(shortcut)
+ Q_D(QQuickPopupItem);
+ QGuiApplicationPrivate *pApp = QGuiApplicationPrivate::instance();
+ if (!d->backId)
+ d->backId = pApp->shortcutMap.addShortcut(this, Qt::Key_Back, Qt::WindowShortcut, QQuickShortcutContext::matcher);
+ if (!d->escapeId)
+ d->escapeId = pApp->shortcutMap.addShortcut(this, Qt::Key_Escape, Qt::WindowShortcut, QQuickShortcutContext::matcher);
+#endif
+}
+
+void QQuickPopupItem::ungrabShortcut()
+{
+#if QT_CONFIG(shortcut)
+ Q_D(QQuickPopupItem);
+ QGuiApplicationPrivate *pApp = QGuiApplicationPrivate::instance();
+ if (d->backId) {
+ pApp->shortcutMap.removeShortcut(d->backId, this);
+ d->backId = 0;
+ }
+ if (d->escapeId) {
+ pApp->shortcutMap.removeShortcut(d->escapeId, this);
+ d->escapeId = 0;
+ }
+#endif
+}
+
+void QQuickPopupItem::updatePolish()
+{
+ Q_D(QQuickPopupItem);
+ return QQuickPopupPrivate::get(d->popup)->reposition();
+}
+
+bool QQuickPopupItem::event(QEvent *event)
+{
+#if QT_CONFIG(shortcut)
+ Q_D(QQuickPopupItem);
+ if (event->type() == QEvent::Shortcut) {
+ QShortcutEvent *se = static_cast<QShortcutEvent *>(event);
+ if (se->shortcutId() == d->escapeId || se->shortcutId() == d->backId) {
+ QQuickPopupPrivate *p = QQuickPopupPrivate::get(d->popup);
+ if (p->interactive) {
+ p->closeOrReject();
+ return true;
+ }
+ }
+ }
+#endif
+ return QQuickItem::event(event);
+}
+
+bool QQuickPopupItem::childMouseEventFilter(QQuickItem *child, QEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ return d->popup->childMouseEventFilter(child, event);
+}
+
+void QQuickPopupItem::focusInEvent(QFocusEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->focusInEvent(event);
+}
+
+void QQuickPopupItem::focusOutEvent(QFocusEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->focusOutEvent(event);
+}
+
+void QQuickPopupItem::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->keyPressEvent(event);
+}
+
+void QQuickPopupItem::keyReleaseEvent(QKeyEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->keyReleaseEvent(event);
+}
+
+void QQuickPopupItem::mousePressEvent(QMouseEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->mousePressEvent(event);
+}
+
+void QQuickPopupItem::mouseMoveEvent(QMouseEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->mouseMoveEvent(event);
+}
+
+void QQuickPopupItem::mouseReleaseEvent(QMouseEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->mouseReleaseEvent(event);
+}
+
+void QQuickPopupItem::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->mouseDoubleClickEvent(event);
+}
+
+void QQuickPopupItem::mouseUngrabEvent()
+{
+ Q_D(QQuickPopupItem);
+ d->popup->mouseUngrabEvent();
+}
+
+#if QT_CONFIG(wheelevent)
+void QQuickPopupItem::wheelEvent(QWheelEvent *event)
+{
+ Q_D(QQuickPopupItem);
+ d->popup->wheelEvent(event);
+}
+#endif
+
+void QQuickPopupItem::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
+{
+ Q_D(QQuickPopupItem);
+ QQuickControl::contentItemChange(newItem, oldItem);
+ d->popup->contentItemChange(newItem, oldItem);
+}
+
+void QQuickPopupItem::fontChange(const QFont &newFont, const QFont &oldFont)
+{
+ Q_D(QQuickPopupItem);
+ QQuickControl::fontChange(newFont, oldFont);
+ d->popup->fontChange(newFont, oldFont);
+}
+
+void QQuickPopupItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_D(QQuickPopupItem);
+ QQuickControl::geometryChanged(newGeometry, oldGeometry);
+ d->popup->geometryChanged(newGeometry, oldGeometry);
+}
+
+void QQuickPopupItem::localeChange(const QLocale &newLocale, const QLocale &oldLocale)
+{
+ Q_D(QQuickPopupItem);
+ QQuickControl::localeChange(newLocale, oldLocale);
+ d->popup->localeChange(newLocale, oldLocale);
+}
+
+void QQuickPopupItem::itemChange(ItemChange change, const ItemChangeData &data)
+{
+ Q_D(QQuickPopupItem);
+ QQuickControl::itemChange(change, data);
+ d->popup->itemChange(change, data);
+}
+
+void QQuickPopupItem::paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding)
+{
+ Q_D(QQuickPopupItem);
+ QQuickControl::paddingChange(newPadding, oldPadding);
+ d->popup->paddingChange(newPadding, oldPadding);
+}
+
+QFont QQuickPopupItem::defaultFont() const
+{
+ Q_D(const QQuickPopupItem);
+ return d->popup->defaultFont();
+}
+
+#if QT_CONFIG(accessibility)
+QAccessible::Role QQuickPopupItem::accessibleRole() const
+{
+ Q_D(const QQuickPopupItem);
+ return d->popup->accessibleRole();
+}
+
+void QQuickPopupItem::accessibilityActiveChanged(bool active)
+{
+ Q_D(const QQuickPopupItem);
+ QQuickControl::accessibilityActiveChanged(active);
+ d->popup->accessibilityActiveChanged(active);
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickpopupitem_p_p.h b/src/quicktemplates2/qquickpopupitem_p_p.h
new file mode 100644
index 00000000..ef97b038
--- /dev/null
+++ b/src/quicktemplates2/qquickpopupitem_p_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QQUICKPOPUPITEM_P_P_H
+#define QQUICKPOPUPITEM_P_P_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 "qquickcontrol_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QQuickPopup;
+class QQuickPopupItemPrivate;
+
+class QQuickPopupItem : public QQuickControl
+{
+ Q_OBJECT
+
+public:
+ explicit QQuickPopupItem(QQuickPopup *popup);
+
+ void grabShortcut();
+ void ungrabShortcut();
+
+protected:
+ void updatePolish() override;
+
+ bool event(QEvent *event) override;
+ bool childMouseEventFilter(QQuickItem *child, QEvent *event) override;
+ void focusInEvent(QFocusEvent *event) override;
+ void focusOutEvent(QFocusEvent *event) override;
+ void keyPressEvent(QKeyEvent *event) override;
+ void keyReleaseEvent(QKeyEvent *event) override;
+ void mousePressEvent(QMouseEvent *event) override;
+ void mouseMoveEvent(QMouseEvent *event) override;
+ void mouseReleaseEvent(QMouseEvent *event) override;
+ void mouseDoubleClickEvent(QMouseEvent *event) override;
+ void mouseUngrabEvent() override;
+#if QT_CONFIG(wheelevent)
+ void wheelEvent(QWheelEvent *event) override;
+#endif
+
+ void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override;
+ void fontChange(const QFont &newFont, const QFont &oldFont) override;
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
+ void localeChange(const QLocale &newLocale, const QLocale &oldLocale) override;
+ void itemChange(ItemChange change, const ItemChangeData &data) override;
+ void paddingChange(const QMarginsF &newPadding, const QMarginsF &oldPadding) override;
+
+ QFont defaultFont() const override;
+
+#if QT_CONFIG(accessibility)
+ QAccessible::Role accessibleRole() const override;
+ void accessibilityActiveChanged(bool active) override;
+#endif
+
+private:
+ Q_DISABLE_COPY(QQuickPopupItem)
+ Q_DECLARE_PRIVATE(QQuickPopupItem)
+ friend class QQuickPopup;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKPOPUPITEM_P_P_H
diff --git a/src/quicktemplates2/qquickpopuppositioner.cpp b/src/quicktemplates2/qquickpopuppositioner.cpp
new file mode 100644
index 00000000..2f320eb3
--- /dev/null
+++ b/src/quicktemplates2/qquickpopuppositioner.cpp
@@ -0,0 +1,277 @@
+/****************************************************************************
+**
+** 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 "qquickpopuppositioner_p_p.h"
+#include "qquickpopupitem_p_p.h"
+#include "qquickpopup_p_p.h"
+
+#include <QtQuick/private/qquickitem_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static const QQuickItemPrivate::ChangeTypes AncestorChangeTypes = QQuickItemPrivate::Geometry
+ | QQuickItemPrivate::Parent
+ | QQuickItemPrivate::Children;
+
+static const QQuickItemPrivate::ChangeTypes ItemChangeTypes = QQuickItemPrivate::Geometry
+ | QQuickItemPrivate::Parent;
+
+QQuickPopupPositioner::QQuickPopupPositioner(QQuickPopup *popup)
+ : m_positioning(false),
+ m_parentItem(nullptr),
+ m_popup(popup)
+{
+}
+
+QQuickPopupPositioner::~QQuickPopupPositioner()
+{
+ if (m_parentItem) {
+ QQuickItemPrivate::get(m_parentItem)->removeItemChangeListener(this, ItemChangeTypes);
+ removeAncestorListeners(m_parentItem->parentItem());
+ }
+}
+
+QQuickItem *QQuickPopupPositioner::parentItem() const
+{
+ return m_parentItem;
+}
+
+void QQuickPopupPositioner::setParentItem(QQuickItem *parent)
+{
+ if (m_parentItem == parent)
+ return;
+
+ if (m_parentItem) {
+ QQuickItemPrivate::get(m_parentItem)->removeItemChangeListener(this, ItemChangeTypes);
+ removeAncestorListeners(m_parentItem->parentItem());
+ }
+
+ m_parentItem = parent;
+
+ if (!parent)
+ return;
+
+ QQuickItemPrivate::get(parent)->addItemChangeListener(this, ItemChangeTypes);
+ addAncestorListeners(parent->parentItem());
+
+ if (m_popup->popupItem()->isVisible())
+ reposition();
+}
+
+void QQuickPopupPositioner::reposition()
+{
+ QQuickItem *popupItem = m_popup->popupItem();
+ if (!popupItem->isVisible())
+ return;
+
+ if (m_positioning) {
+ popupItem->polish();
+ return;
+ }
+
+ const qreal w = popupItem->width();
+ const qreal h = popupItem->height();
+ const qreal iw = popupItem->implicitWidth();
+ const qreal ih = popupItem->implicitHeight();
+
+ bool widthAdjusted = false;
+ bool heightAdjusted = false;
+ QQuickPopupPrivate *p = QQuickPopupPrivate::get(m_popup);
+
+ QRectF rect(p->allowHorizontalMove ? p->x : popupItem->x(),
+ p->allowVerticalMove ? p->y : popupItem->y(),
+ !p->hasWidth && iw > 0 ? iw : w,
+ !p->hasHeight && ih > 0 ? ih : h);
+ if (m_parentItem) {
+ rect = m_parentItem->mapRectToScene(rect);
+
+ if (p->window) {
+ const QMarginsF margins = p->getMargins();
+ const QRectF bounds(qMax<qreal>(0.0, margins.left()),
+ qMax<qreal>(0.0, margins.top()),
+ p->window->width() - qMax<qreal>(0.0, margins.left()) - qMax<qreal>(0.0, margins.right()),
+ p->window->height() - qMax<qreal>(0.0, margins.top()) - qMax<qreal>(0.0, margins.bottom()));
+
+ // if the popup doesn't fit horizontally inside the window, try flipping it around (left <-> right)
+ if (p->allowHorizontalFlip && (rect.left() < bounds.left() || rect.right() > bounds.right())) {
+ const QRectF flipped = m_parentItem->mapRectToScene(QRectF(m_parentItem->width() - p->x - rect.width(), p->y, rect.width(), rect.height()));
+ if (flipped.intersected(bounds).width() > rect.intersected(bounds).width())
+ rect.moveLeft(flipped.left());
+ }
+
+ // if the popup doesn't fit vertically inside the window, try flipping it around (above <-> below)
+ if (p->allowVerticalFlip && (rect.top() < bounds.top() || rect.bottom() > bounds.bottom())) {
+ const QRectF flipped = m_parentItem->mapRectToScene(QRectF(p->x, m_parentItem->height() - p->y - rect.height(), rect.width(), rect.height()));
+ if (flipped.intersected(bounds).height() > rect.intersected(bounds).height())
+ rect.moveTop(flipped.top());
+ }
+
+ // push inside the margins if specified
+ if (p->allowVerticalMove) {
+ if (margins.top() >= 0 && rect.top() < bounds.top())
+ rect.moveTop(margins.top());
+ if (margins.bottom() >= 0 && rect.bottom() > bounds.bottom())
+ rect.moveBottom(bounds.bottom());
+ }
+ if (p->allowHorizontalMove) {
+ if (margins.left() >= 0 && rect.left() < bounds.left())
+ rect.moveLeft(margins.left());
+ if (margins.right() >= 0 && rect.right() > bounds.right())
+ rect.moveRight(bounds.right());
+ }
+
+ if (iw > 0 && (rect.left() < bounds.left() || rect.right() > bounds.right())) {
+ // neither the flipped or pushed geometry fits inside the window, choose
+ // whichever side (left vs. right) fits larger part of the popup
+ if (p->allowHorizontalMove && p->allowHorizontalFlip) {
+ if (rect.left() < bounds.left() && bounds.left() + rect.width() <= bounds.right())
+ rect.moveLeft(bounds.left());
+ else if (rect.right() > bounds.right() && bounds.right() - rect.width() >= bounds.left())
+ rect.moveRight(bounds.right());
+ }
+
+ // as a last resort, adjust the width to fit the window
+ if (p->allowHorizontalResize) {
+ if (rect.left() < bounds.left()) {
+ rect.setLeft(bounds.left());
+ widthAdjusted = true;
+ }
+ if (rect.right() > bounds.right()) {
+ rect.setRight(bounds.right());
+ widthAdjusted = true;
+ }
+ }
+ } else if (iw > 0 && rect.left() >= bounds.left() && rect.right() <= bounds.right()
+ && iw != w) {
+ // restore original width
+ rect.setWidth(iw);
+ widthAdjusted = true;
+ }
+
+ if (ih > 0 && (rect.top() < bounds.top() || rect.bottom() > bounds.bottom())) {
+ // neither the flipped or pushed geometry fits inside the window, choose
+ // whichever side (above vs. below) fits larger part of the popup
+ if (p->allowVerticalMove && p->allowVerticalFlip) {
+ if (rect.top() < bounds.top() && bounds.top() + rect.height() <= bounds.bottom())
+ rect.moveTop(bounds.top());
+ else if (rect.bottom() > bounds.bottom() && bounds.bottom() - rect.height() >= bounds.top())
+ rect.moveBottom(bounds.bottom());
+ }
+
+ // as a last resort, adjust the height to fit the window
+ if (p->allowVerticalResize) {
+ if (rect.top() < bounds.top()) {
+ rect.setTop(bounds.top());
+ heightAdjusted = true;
+ }
+ if (rect.bottom() > bounds.bottom()) {
+ rect.setBottom(bounds.bottom());
+ heightAdjusted = true;
+ }
+ }
+ } else if (ih > 0 && rect.top() >= bounds.top() && rect.bottom() <= bounds.bottom()
+ && ih != h) {
+ // restore original height
+ rect.setHeight(ih);
+ heightAdjusted = true;
+ }
+ }
+ }
+
+ m_positioning = true;
+
+ popupItem->setPosition(rect.topLeft());
+
+ const QPointF effectivePos = m_parentItem ? m_parentItem->mapFromScene(rect.topLeft()) : rect.topLeft();
+ if (!qFuzzyCompare(p->effectiveX, effectivePos.x())) {
+ p->effectiveX = effectivePos.x();
+ emit m_popup->xChanged();
+ }
+ if (!qFuzzyCompare(p->effectiveY, effectivePos.y())) {
+ p->effectiveY = effectivePos.y();
+ emit m_popup->yChanged();
+ }
+
+ if (!p->hasWidth && widthAdjusted && rect.width() > 0)
+ popupItem->setWidth(rect.width());
+ if (!p->hasHeight && heightAdjusted && rect.height() > 0)
+ popupItem->setHeight(rect.height());
+
+ m_positioning = false;
+}
+
+void QQuickPopupPositioner::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &)
+{
+ if (m_parentItem && m_popup->popupItem()->isVisible())
+ reposition();
+}
+
+void QQuickPopupPositioner::itemParentChanged(QQuickItem *, QQuickItem *parent)
+{
+ addAncestorListeners(parent);
+}
+
+void QQuickPopupPositioner::itemChildRemoved(QQuickItem *item, QQuickItem *child)
+{
+ if (child->isAncestorOf(m_parentItem))
+ removeAncestorListeners(item);
+}
+
+void QQuickPopupPositioner::removeAncestorListeners(QQuickItem *item)
+{
+ if (item == m_parentItem)
+ return;
+
+ QQuickItem *p = item;
+ while (p) {
+ QQuickItemPrivate::get(p)->removeItemChangeListener(this, AncestorChangeTypes);
+ p = p->parentItem();
+ }
+}
+
+void QQuickPopupPositioner::addAncestorListeners(QQuickItem *item)
+{
+ if (item == m_parentItem)
+ return;
+
+ QQuickItem *p = item;
+ while (p) {
+ QQuickItemPrivate::get(p)->addItemChangeListener(this, AncestorChangeTypes);
+ p = p->parentItem();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickpopuppositioner_p_p.h b/src/quicktemplates2/qquickpopuppositioner_p_p.h
new file mode 100644
index 00000000..45b33538
--- /dev/null
+++ b/src/quicktemplates2/qquickpopuppositioner_p_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QQUICKPOPUPPOSITIONER_P_P_H
+#define QQUICKPOPUPPOSITIONER_P_P_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/qquickitemchangelistener_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickItem;
+class QQuickPopup;
+
+class QQuickPopupPositioner : public QQuickItemChangeListener
+{
+public:
+ explicit QQuickPopupPositioner(QQuickPopup *popup);
+ ~QQuickPopupPositioner();
+
+ QQuickItem *parentItem() const;
+ void setParentItem(QQuickItem *parent);
+
+ virtual void reposition();
+
+protected:
+ void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) override;
+ void itemParentChanged(QQuickItem *, QQuickItem *parent) override;
+ void itemChildRemoved(QQuickItem *, QQuickItem *child) override;
+
+private:
+ void removeAncestorListeners(QQuickItem *item);
+ void addAncestorListeners(QQuickItem *item);
+
+ bool m_positioning;
+ QQuickItem *m_parentItem;
+ QQuickPopup *m_popup;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKPOPUPPOSITIONER_P_P_H
diff --git a/src/quicktemplates2/qquickpresshandler.cpp b/src/quicktemplates2/qquickpresshandler.cpp
index 0c2db981..8f8167cd 100644
--- a/src/quicktemplates2/qquickpresshandler.cpp
+++ b/src/quicktemplates2/qquickpresshandler.cpp
@@ -45,13 +45,14 @@
QT_BEGIN_NAMESPACE
QQuickPressHandler::QQuickPressHandler()
- : control(nullptr)
- , longPress(false)
- , pressAndHoldSignalIndex(-1)
- , pressedSignalIndex(-1)
- , releasedSignalIndex(-1)
- , delayedMousePressEvent(nullptr)
-{ }
+ : control(nullptr),
+ longPress(false),
+ pressAndHoldSignalIndex(-1),
+ pressedSignalIndex(-1),
+ releasedSignalIndex(-1),
+ delayedMousePressEvent(nullptr)
+{
+}
void QQuickPressHandler::mousePressEvent(QMouseEvent *event)
{
diff --git a/src/quicktemplates2/qquickprogressbar.cpp b/src/quicktemplates2/qquickprogressbar.cpp
index ec0ebf66..c5a24f6c 100644
--- a/src/quicktemplates2/qquickprogressbar.cpp
+++ b/src/quicktemplates2/qquickprogressbar.cpp
@@ -89,7 +89,11 @@ QT_BEGIN_NAMESPACE
class QQuickProgressBarPrivate : public QQuickControlPrivate
{
public:
- QQuickProgressBarPrivate() : from(0), to(1.0), value(0), indeterminate(false)
+ QQuickProgressBarPrivate()
+ : from(0),
+ to(1.0),
+ value(0),
+ indeterminate(false)
{
}
@@ -99,8 +103,8 @@ public:
bool indeterminate;
};
-QQuickProgressBar::QQuickProgressBar(QQuickItem *parent) :
- QQuickControl(*(new QQuickProgressBarPrivate), parent)
+QQuickProgressBar::QQuickProgressBar(QQuickItem *parent)
+ : QQuickControl(*(new QQuickProgressBarPrivate), parent)
{
}
@@ -265,7 +269,7 @@ void QQuickProgressBar::componentComplete()
setValue(d->value);
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickProgressBar::accessibleRole() const
{
return QAccessible::ProgressBar;
diff --git a/src/quicktemplates2/qquickprogressbar_p.h b/src/quicktemplates2/qquickprogressbar_p.h
index fc2d6c43..f2284c65 100644
--- a/src/quicktemplates2/qquickprogressbar_p.h
+++ b/src/quicktemplates2/qquickprogressbar_p.h
@@ -94,7 +94,7 @@ protected:
void mirrorChange() override;
void componentComplete() override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquickradiobutton.cpp b/src/quicktemplates2/qquickradiobutton.cpp
index 9aa57b0a..c923fbbf 100644
--- a/src/quicktemplates2/qquickradiobutton.cpp
+++ b/src/quicktemplates2/qquickradiobutton.cpp
@@ -90,8 +90,8 @@ QT_BEGIN_NAMESPACE
\sa ButtonGroup, {Customizing RadioButton}, {Button Controls}, RadioDelegate
*/
-QQuickRadioButton::QQuickRadioButton(QQuickItem *parent) :
- QQuickAbstractButton(parent)
+QQuickRadioButton::QQuickRadioButton(QQuickItem *parent)
+ : QQuickAbstractButton(parent)
{
setCheckable(true);
setAutoExclusive(true);
@@ -102,7 +102,7 @@ QFont QQuickRadioButton::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::RadioButtonFont);
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickRadioButton::accessibleRole() const
{
return QAccessible::RadioButton;
diff --git a/src/quicktemplates2/qquickradiobutton_p.h b/src/quicktemplates2/qquickradiobutton_p.h
index 0e16a36c..0fe4eb70 100644
--- a/src/quicktemplates2/qquickradiobutton_p.h
+++ b/src/quicktemplates2/qquickradiobutton_p.h
@@ -62,7 +62,7 @@ public:
protected:
QFont defaultFont() const override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
};
diff --git a/src/quicktemplates2/qquickradiodelegate.cpp b/src/quicktemplates2/qquickradiodelegate.cpp
index e2747d93..fe603d36 100644
--- a/src/quicktemplates2/qquickradiodelegate.cpp
+++ b/src/quicktemplates2/qquickradiodelegate.cpp
@@ -91,8 +91,8 @@ QT_BEGIN_NAMESPACE
\sa {Customizing RadioDelegate}, {Delegate Controls}, RadioButton
*/
-QQuickRadioDelegate::QQuickRadioDelegate(QQuickItem *parent) :
- QQuickItemDelegate(parent)
+QQuickRadioDelegate::QQuickRadioDelegate(QQuickItem *parent)
+ : QQuickItemDelegate(parent)
{
setCheckable(true);
setAutoExclusive(true);
@@ -103,7 +103,7 @@ QFont QQuickRadioDelegate::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::ListViewFont);
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickRadioDelegate::accessibleRole() const
{
return QAccessible::RadioButton;
diff --git a/src/quicktemplates2/qquickradiodelegate_p.h b/src/quicktemplates2/qquickradiodelegate_p.h
index 9e3cde6b..4db9959d 100644
--- a/src/quicktemplates2/qquickradiodelegate_p.h
+++ b/src/quicktemplates2/qquickradiodelegate_p.h
@@ -64,7 +64,7 @@ public:
protected:
QFont defaultFont() const override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
};
diff --git a/src/quicktemplates2/qquickrangeslider.cpp b/src/quicktemplates2/qquickrangeslider.cpp
index 4e350ef2..1c74f9ee 100644
--- a/src/quicktemplates2/qquickrangeslider.cpp
+++ b/src/quicktemplates2/qquickrangeslider.cpp
@@ -84,15 +84,16 @@ class QQuickRangeSliderNodePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QQuickRangeSliderNode)
public:
- QQuickRangeSliderNodePrivate(qreal value, QQuickRangeSlider *slider) :
- value(value),
- isPendingValue(false),
- pendingValue(0),
- position(0),
- handle(nullptr),
- slider(slider),
- pressed(false),
- hovered(false)
+ QQuickRangeSliderNodePrivate(qreal value, QQuickRangeSlider *slider)
+ : value(value),
+ isPendingValue(false),
+ pendingValue(0),
+ position(0),
+ handle(nullptr),
+ slider(slider),
+ pressed(false),
+ hovered(false),
+ touchId(-1)
{
}
@@ -103,9 +104,6 @@ public:
static QQuickRangeSliderNodePrivate *get(QQuickRangeSliderNode *node);
-private:
- friend class QQuickRangeSlider;
-
qreal value;
bool isPendingValue;
qreal pendingValue;
@@ -114,6 +112,7 @@ private:
QQuickRangeSlider *slider;
bool pressed;
bool hovered;
+ int touchId;
};
bool QQuickRangeSliderNodePrivate::isFirst() const
@@ -148,8 +147,8 @@ QQuickRangeSliderNodePrivate *QQuickRangeSliderNodePrivate::get(QQuickRangeSlide
return node->d_func();
}
-QQuickRangeSliderNode::QQuickRangeSliderNode(qreal value, QQuickRangeSlider *slider) :
- QObject(*(new QQuickRangeSliderNodePrivate(value, slider)), slider)
+QQuickRangeSliderNode::QQuickRangeSliderNode(qreal value, QQuickRangeSlider *slider)
+ : QObject(*(new QQuickRangeSliderNodePrivate(value, slider)), slider)
{
}
@@ -231,7 +230,7 @@ void QQuickRangeSliderNode::setHandle(QQuickItem *handle)
if (d->handle == handle)
return;
- QQuickControlPrivate::get(d->slider)->deleteDelegate(d->handle);
+ QQuickControlPrivate::destroyDelegate(d->handle, d->slider);
d->handle = handle;
if (handle) {
if (!handle->parentItem())
@@ -315,38 +314,37 @@ class QQuickRangeSliderPrivate : public QQuickControlPrivate
Q_DECLARE_PUBLIC(QQuickRangeSlider)
public:
- QQuickRangeSliderPrivate() :
- from(defaultFrom),
- to(defaultTo),
- stepSize(0),
- first(nullptr),
- second(nullptr),
- orientation(Qt::Horizontal),
- snapMode(QQuickRangeSlider::NoSnap)
+ QQuickRangeSliderPrivate()
+ : live(true),
+ from(defaultFrom),
+ to(defaultTo),
+ stepSize(0),
+ first(nullptr),
+ second(nullptr),
+ orientation(Qt::Horizontal),
+ snapMode(QQuickRangeSlider::NoSnap)
{
}
+ QQuickRangeSliderNode *pressedNode(int touchId = -1) const;
+ void handlePress(const QPointF &point, int touchId = -1);
+ void handleMove(const QPointF &point, int touchId = -1);
+ void handleRelease(const QPointF &point, int touchId = -1);
+ void handleUngrab();
+
void updateHover(const QPointF &pos);
+ bool live;
qreal from;
qreal to;
qreal stepSize;
QQuickRangeSliderNode *first;
QQuickRangeSliderNode *second;
- QPoint pressPoint;
+ QPointF pressPoint;
Qt::Orientation orientation;
QQuickRangeSlider::SnapMode snapMode;
};
-void QQuickRangeSliderPrivate::updateHover(const QPointF &pos)
-{
- Q_Q(QQuickRangeSlider);
- QQuickItem *firstHandle = first->handle();
- QQuickItem *secondHandle = second->handle();
- first->setHovered(firstHandle && firstHandle->isEnabled() && firstHandle->contains(q->mapToItem(firstHandle, pos)));
- second->setHovered(secondHandle && secondHandle->isEnabled() && secondHandle->contains(q->mapToItem(secondHandle, pos)));
-}
-
static qreal valueAt(const QQuickRangeSlider *slider, qreal position)
{
return slider->from() + (slider->to() - slider->from()) * position;
@@ -365,7 +363,7 @@ static qreal snapPosition(const QQuickRangeSlider *slider, qreal position)
return qRound(position / effectiveStep) * effectiveStep;
}
-static qreal positionAt(const QQuickRangeSlider *slider, QQuickItem *handle, const QPoint &point)
+static qreal positionAt(const QQuickRangeSlider *slider, QQuickItem *handle, const QPointF &point)
{
if (slider->orientation() == Qt::Horizontal) {
const qreal hw = handle ? handle->width() : 0;
@@ -386,8 +384,138 @@ static qreal positionAt(const QQuickRangeSlider *slider, QQuickItem *handle, con
return 0;
}
-QQuickRangeSlider::QQuickRangeSlider(QQuickItem *parent) :
- QQuickControl(*(new QQuickRangeSliderPrivate), parent)
+QQuickRangeSliderNode *QQuickRangeSliderPrivate::pressedNode(int touchId) const
+{
+ if (touchId == -1)
+ return first->isPressed() ? first : (second->isPressed() ? second : nullptr);
+ if (QQuickRangeSliderNodePrivate::get(first)->touchId == touchId)
+ return first;
+ if (QQuickRangeSliderNodePrivate::get(second)->touchId == touchId)
+ return second;
+ return nullptr;
+}
+
+void QQuickRangeSliderPrivate::handlePress(const QPointF &point, int touchId)
+{
+ Q_Q(QQuickRangeSlider);
+ pressPoint = point;
+
+ QQuickItem *firstHandle = first->handle();
+ QQuickItem *secondHandle = second->handle();
+ const bool firstHit = firstHandle && !first->isPressed() && firstHandle->contains(q->mapToItem(firstHandle, point));
+ const bool secondHit = secondHandle && !second->isPressed() && secondHandle->contains(q->mapToItem(secondHandle, point));
+ QQuickRangeSliderNode *hitNode = nullptr;
+ QQuickRangeSliderNode *otherNode = nullptr;
+
+ if (firstHit && secondHit) {
+ // choose highest
+ hitNode = firstHandle->z() > secondHandle->z() ? first : second;
+ otherNode = firstHandle->z() > secondHandle->z() ? second : first;
+ } else if (firstHit) {
+ hitNode = first;
+ otherNode = second;
+ } else if (secondHit) {
+ hitNode = second;
+ otherNode = first;
+ } else {
+ // find the nearest
+ const qreal firstDistance = QLineF(firstHandle->boundingRect().center(),
+ q->mapToItem(firstHandle, point)).length();
+ const qreal secondDistance = QLineF(secondHandle->boundingRect().center(),
+ q->mapToItem(secondHandle, point)).length();
+
+ if (qFuzzyCompare(firstDistance, secondDistance)) {
+ // same distance => choose the one that can be moved towards the press position
+ const bool inverted = from > to;
+ const qreal pos = positionAt(q, firstHandle, point);
+ if ((!inverted && pos < first->position()) || (inverted && pos > first->position())) {
+ hitNode = first;
+ otherNode = second;
+ } else {
+ hitNode = second;
+ otherNode = first;
+ }
+ } else if (firstDistance < secondDistance) {
+ hitNode = first;
+ otherNode = second;
+ } else {
+ hitNode = second;
+ otherNode = first;
+ }
+ }
+
+ if (hitNode) {
+ hitNode->setPressed(true);
+ hitNode->handle()->setZ(1);
+ QQuickRangeSliderNodePrivate::get(hitNode)->touchId = touchId;
+ }
+ if (otherNode)
+ otherNode->handle()->setZ(0);
+}
+
+void QQuickRangeSliderPrivate::handleMove(const QPointF &point, int touchId)
+{
+ Q_Q(QQuickRangeSlider);
+ if (!q->keepMouseGrab() && !q->keepTouchGrab())
+ return;
+ QQuickRangeSliderNode *pressedNode = QQuickRangeSliderPrivate::pressedNode(touchId);
+ if (pressedNode) {
+ qreal pos = positionAt(q, pressedNode->handle(), point);
+ if (snapMode == QQuickRangeSlider::SnapAlways)
+ pos = snapPosition(q, pos);
+ if (live)
+ pressedNode->setValue(valueAt(q, pos));
+ else
+ QQuickRangeSliderNodePrivate::get(pressedNode)->setPosition(pos);
+ }
+}
+
+void QQuickRangeSliderPrivate::handleRelease(const QPointF &point, int touchId)
+{
+ Q_Q(QQuickRangeSlider);
+ pressPoint = QPointF();
+
+ QQuickRangeSliderNode *pressedNode = QQuickRangeSliderPrivate::pressedNode(touchId);
+ if (!pressedNode)
+ return;
+ QQuickRangeSliderNodePrivate *pressedNodePrivate = QQuickRangeSliderNodePrivate::get(pressedNode);
+
+ if (q->keepMouseGrab() || q->keepTouchGrab()) {
+ qreal pos = positionAt(q, pressedNode->handle(), point);
+ if (snapMode != QQuickRangeSlider::NoSnap)
+ pos = snapPosition(q, pos);
+ qreal val = valueAt(q, pos);
+ if (!qFuzzyCompare(val, pressedNode->value()))
+ pressedNode->setValue(val);
+ else if (snapMode != QQuickRangeSlider::NoSnap)
+ pressedNodePrivate->setPosition(pos);
+ q->setKeepMouseGrab(false);
+ q->setKeepTouchGrab(false);
+ }
+ pressedNode->setPressed(false);
+ pressedNodePrivate->touchId = -1;
+}
+
+void QQuickRangeSliderPrivate::handleUngrab()
+{
+ pressPoint = QPointF();
+ first->setPressed(false);
+ second->setPressed(false);
+ QQuickRangeSliderNodePrivate::get(first)->touchId = -1;
+ QQuickRangeSliderNodePrivate::get(second)->touchId = -1;
+}
+
+void QQuickRangeSliderPrivate::updateHover(const QPointF &pos)
+{
+ Q_Q(QQuickRangeSlider);
+ QQuickItem *firstHandle = first->handle();
+ QQuickItem *secondHandle = second->handle();
+ first->setHovered(firstHandle && firstHandle->isEnabled() && firstHandle->contains(q->mapToItem(firstHandle, pos)));
+ second->setHovered(secondHandle && secondHandle->isEnabled() && secondHandle->contains(q->mapToItem(secondHandle, pos)));
+}
+
+QQuickRangeSlider::QQuickRangeSlider(QQuickItem *parent)
+ : QQuickControl(*(new QQuickRangeSliderPrivate), parent)
{
Q_D(QQuickRangeSlider);
d->first = new QQuickRangeSliderNode(0.0, this);
@@ -474,9 +602,6 @@ void QQuickRangeSlider::setTo(qreal to)
If \l to is greater than \l from, the value of the first handle
must be greater than the second, and vice versa.
- Unlike \l {first.position}{position}, value is not updated while the
- handle is dragged, but rather when it has been released.
-
The default value is \c 0.0.
\row
\li handle
@@ -494,9 +619,7 @@ void QQuickRangeSlider::setTo(qreal to)
\li This property holds the logical position of the first handle.
The position is expressed as a fraction of the control's size, in the range
- \c {0.0 - 1.0}. Unlike \l {first.value}{value}, position is
- continuously updated while the handle is dragged. For visualizing a
- slider, the right-to-left aware
+ \c {0.0 - 1.0}. For visualizing a slider, the right-to-left aware
\l {first.visualPosition}{visualPosition} should be used instead.
\row
\li pressed
@@ -536,9 +659,6 @@ QQuickRangeSliderNode *QQuickRangeSlider::first() const
If \l to is greater than \l from, the value of the first handle
must be greater than the second, and vice versa.
- Unlike \l {second.position}{position}, value is not updated while the
- handle is dragged, but rather when it has been released.
-
The default value is \c 0.0.
\row
\li handle
@@ -556,9 +676,7 @@ QQuickRangeSliderNode *QQuickRangeSlider::first() const
\li This property holds the logical position of the second handle.
The position is expressed as a fraction of the control's size, in the range
- \c {0.0 - 1.0}. Unlike \l {second.value}{value}, position is
- continuously updated while the handle is dragged. For visualizing a
- slider, the right-to-left aware
+ \c {0.0 - 1.0}. For visualizing a slider, the right-to-left aware
\l {second.visualPosition}{visualPosition} should be used instead.
\row
\li pressed
@@ -657,6 +775,33 @@ void QQuickRangeSlider::setOrientation(Qt::Orientation orientation)
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::RangeSlider::live
+
+ This property holds whether the slider provides live updates for the \l first.value
+ and \l second.value properties while the respective handles are dragged.
+
+ The default value is \c true.
+
+ \sa first.value, second.value
+*/
+bool QQuickRangeSlider::live() const
+{
+ Q_D(const QQuickRangeSlider);
+ return d->live;
+}
+
+void QQuickRangeSlider::setLive(bool live)
+{
+ Q_D(QQuickRangeSlider);
+ if (d->live == live)
+ return;
+
+ d->live = live;
+ emit liveChanged();
+}
+
+/*!
\qmlmethod void QtQuick.Controls::RangeSlider::setValues(real firstValue, real secondValue)
Sets \l first.value and \l second.value with the given arguments.
@@ -804,58 +949,7 @@ void QQuickRangeSlider::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickRangeSlider);
QQuickControl::mousePressEvent(event);
- d->pressPoint = event->pos();
-
- QQuickItem *firstHandle = d->first->handle();
- QQuickItem *secondHandle = d->second->handle();
- const bool firstHit = firstHandle && firstHandle->contains(mapToItem(firstHandle, d->pressPoint));
- const bool secondHit = secondHandle && secondHandle->contains(mapToItem(secondHandle, d->pressPoint));
- QQuickRangeSliderNode *hitNode = nullptr;
- QQuickRangeSliderNode *otherNode = nullptr;
-
- if (firstHit && secondHit) {
- // choose highest
- hitNode = firstHandle->z() > secondHandle->z() ? d->first : d->second;
- otherNode = firstHandle->z() > secondHandle->z() ? d->second : d->first;
- } else if (firstHit) {
- hitNode = d->first;
- otherNode = d->second;
- } else if (secondHit) {
- hitNode = d->second;
- otherNode = d->first;
- } else {
- // find the nearest
- const qreal firstDistance = QLineF(firstHandle->boundingRect().center(),
- mapToItem(firstHandle, event->pos())).length();
- const qreal secondDistance = QLineF(secondHandle->boundingRect().center(),
- mapToItem(secondHandle, event->pos())).length();
-
- if (qFuzzyCompare(firstDistance, secondDistance)) {
- // same distance => choose the one that can be moved towards the press position
- const bool inverted = d->from > d->to;
- const qreal pos = positionAt(this, firstHandle, event->pos());
- if ((!inverted && pos < d->first->position()) || (inverted && pos > d->first->position())) {
- hitNode = d->first;
- otherNode = d->second;
- } else {
- hitNode = d->second;
- otherNode = d->first;
- }
- } else if (firstDistance < secondDistance) {
- hitNode = d->first;
- otherNode = d->second;
- } else {
- hitNode = d->second;
- otherNode = d->first;
- }
- }
-
- if (hitNode) {
- hitNode->setPressed(true);
- hitNode->handle()->setZ(1);
- }
- if (otherNode)
- otherNode->handle()->setZ(0);
+ d->handlePress(event->localPos());
}
void QQuickRangeSlider::mouseMoveEvent(QMouseEvent *event)
@@ -864,53 +958,92 @@ void QQuickRangeSlider::mouseMoveEvent(QMouseEvent *event)
QQuickControl::mouseMoveEvent(event);
if (!keepMouseGrab()) {
if (d->orientation == Qt::Horizontal)
- setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->pos().x() - d->pressPoint.x(), Qt::XAxis, event));
+ setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->localPos().x() - d->pressPoint.x(), Qt::XAxis, event));
else
- setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->pos().y() - d->pressPoint.y(), Qt::YAxis, event));
- }
- if (keepMouseGrab()) {
- QQuickRangeSliderNode *pressedNode = d->first->isPressed() ? d->first : (d->second->isPressed() ? d->second : nullptr);
- if (pressedNode) {
- qreal pos = positionAt(this, pressedNode->handle(), event->pos());
- if (d->snapMode == SnapAlways)
- pos = snapPosition(this, pos);
- QQuickRangeSliderNodePrivate::get(pressedNode)->setPosition(pos);
- }
+ setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->localPos().y() - d->pressPoint.y(), Qt::YAxis, event));
}
+ d->handleMove(event->localPos());
}
void QQuickRangeSlider::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QQuickRangeSlider);
QQuickControl::mouseReleaseEvent(event);
+ d->handleRelease(event->localPos());
+}
- d->pressPoint = QPoint();
- if (!keepMouseGrab())
- return;
+void QQuickRangeSlider::mouseUngrabEvent()
+{
+ Q_D(QQuickRangeSlider);
+ QQuickControl::mouseUngrabEvent();
+ d->handleUngrab();
+}
- QQuickRangeSliderNode *pressedNode = d->first->isPressed() ? d->first : (d->second->isPressed() ? d->second : nullptr);
- if (!pressedNode)
- return;
+void QQuickRangeSlider::touchEvent(QTouchEvent *event)
+{
+ Q_D(QQuickRangeSlider);
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ if (!d->first->isPressed() || !d->second->isPressed()) {
+ const QTouchEvent::TouchPoint point = event->touchPoints().first();
+ d->handlePress(point.pos(), point.id());
+ } else {
+ event->ignore();
+ }
+ break;
+
+ case QEvent::TouchUpdate:
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ switch (point.state()) {
+ case Qt::TouchPointPressed:
+ if (!d->first->isPressed() || !d->second->isPressed())
+ d->handlePress(point.pos(), point.id());
+ break;
+ case Qt::TouchPointMoved:
+ if (!keepTouchGrab()) {
+ if (d->orientation == Qt::Horizontal)
+ setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().x() - point.startPos().x(), Qt::XAxis, &point));
+ else
+ setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().y() - point.startPos().y(), Qt::YAxis, &point));
+ }
+ if (point.id() == QQuickRangeSliderNodePrivate::get(d->first)->touchId
+ || point.id() == QQuickRangeSliderNodePrivate::get(d->second)->touchId)
+ d->handleMove(point.pos(), point.id());
+ break;
+ case Qt::TouchPointReleased:
+ if (point.id() == QQuickRangeSliderNodePrivate::get(d->first)->touchId
+ || point.id() == QQuickRangeSliderNodePrivate::get(d->second)->touchId)
+ d->handleRelease(point.pos(), point.id());
+ break;
+ default:
+ break;
+ }
+ }
+ break;
- qreal pos = positionAt(this, pressedNode->handle(), event->pos());
- if (d->snapMode != NoSnap)
- pos = snapPosition(this, pos);
- qreal val = valueAt(this, pos);
- if (!qFuzzyCompare(val, pressedNode->value()))
- pressedNode->setValue(val);
- else if (d->snapMode != NoSnap)
- QQuickRangeSliderNodePrivate::get(pressedNode)->setPosition(pos);
- setKeepMouseGrab(false);
- pressedNode->setPressed(false);
+ case QEvent::TouchEnd:
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ if (point.id() == QQuickRangeSliderNodePrivate::get(d->first)->touchId
+ || point.id() == QQuickRangeSliderNodePrivate::get(d->second)->touchId)
+ d->handleRelease(point.pos(), point.id());
+ }
+ break;
+
+ case QEvent::TouchCancel:
+ d->handleUngrab();
+ break;
+
+ default:
+ QQuickControl::touchEvent(event);
+ break;
+ }
}
-void QQuickRangeSlider::mouseUngrabEvent()
+void QQuickRangeSlider::touchUngrabEvent()
{
Q_D(QQuickRangeSlider);
- QQuickControl::mouseUngrabEvent();
- d->pressPoint = QPoint();
- d->first->setPressed(false);
- d->second->setPressed(false);
+ QQuickControl::touchUngrabEvent();
+ d->handleUngrab();
}
void QQuickRangeSlider::mirrorChange()
@@ -983,7 +1116,7 @@ void QQuickRangeSlider::componentComplete()
\sa second
*/
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickRangeSlider::accessibleRole() const
{
return QAccessible::Slider;
diff --git a/src/quicktemplates2/qquickrangeslider_p.h b/src/quicktemplates2/qquickrangeslider_p.h
index b7bf63fb..d07cb6f0 100644
--- a/src/quicktemplates2/qquickrangeslider_p.h
+++ b/src/quicktemplates2/qquickrangeslider_p.h
@@ -65,6 +65,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickRangeSlider : public QQuickControl
Q_PROPERTY(qreal stepSize READ stepSize WRITE setStepSize NOTIFY stepSizeChanged FINAL)
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL)
Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged FINAL)
+ Q_PROPERTY(bool live READ live WRITE setLive NOTIFY liveChanged FINAL REVISION 2)
public:
explicit QQuickRangeSlider(QQuickItem *parent = nullptr);
@@ -94,6 +95,9 @@ public:
Qt::Orientation orientation() const;
void setOrientation(Qt::Orientation orientation);
+ bool live() const;
+ void setLive(bool live);
+
Q_INVOKABLE void setValues(qreal firstValue, qreal secondValue);
Q_SIGNALS:
@@ -102,6 +106,7 @@ Q_SIGNALS:
void stepSizeChanged();
void snapModeChanged();
void orientationChanged();
+ Q_REVISION(2) void liveChanged();
protected:
void focusInEvent(QFocusEvent *event) override;
@@ -114,10 +119,12 @@ protected:
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseUngrabEvent() override;
+ void touchEvent(QTouchEvent *event) override;
+ void touchUngrabEvent() override;
void mirrorChange() override;
void componentComplete() override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquickroundbutton.cpp b/src/quicktemplates2/qquickroundbutton.cpp
index 7164eab0..0784de81 100644
--- a/src/quicktemplates2/qquickroundbutton.cpp
+++ b/src/quicktemplates2/qquickroundbutton.cpp
@@ -73,9 +73,9 @@ public:
void setRadius(qreal newRadius = -1.0);
};
-QQuickRoundButtonPrivate::QQuickRoundButtonPrivate() :
- radius(0),
- explicitRadius(false)
+QQuickRoundButtonPrivate::QQuickRoundButtonPrivate()
+ : radius(0),
+ explicitRadius(false)
{
}
@@ -92,8 +92,8 @@ void QQuickRoundButtonPrivate::setRadius(qreal newRadius)
emit q->radiusChanged();
}
-QQuickRoundButton::QQuickRoundButton(QQuickItem *parent) :
- QQuickButton(*(new QQuickRoundButtonPrivate), parent)
+QQuickRoundButton::QQuickRoundButton(QQuickItem *parent)
+ : QQuickButton(*(new QQuickRoundButtonPrivate), parent)
{
}
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();
}
diff --git a/src/quicktemplates2/qquickscrollbar_p.h b/src/quicktemplates2/qquickscrollbar_p.h
index 2d89ab72..1b18c4ad 100644
--- a/src/quicktemplates2/qquickscrollbar_p.h
+++ b/src/quicktemplates2/qquickscrollbar_p.h
@@ -52,7 +52,6 @@
QT_BEGIN_NAMESPACE
-class QQuickFlickable;
class QQuickScrollBarAttached;
class QQuickScrollBarPrivate;
@@ -65,6 +64,9 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickScrollBar : public QQuickControl
Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged FINAL)
Q_PROPERTY(bool pressed READ isPressed WRITE setPressed NOTIFY pressedChanged FINAL)
Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged FINAL)
+ Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL REVISION 2)
+ Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive RESET resetInteractive NOTIFY interactiveChanged FINAL REVISION 2)
+ Q_PROPERTY(Policy policy READ policy WRITE setPolicy NOTIFY policyChanged FINAL REVISION 2)
public:
explicit QQuickScrollBar(QQuickItem *parent = nullptr);
@@ -86,6 +88,30 @@ public:
Qt::Orientation orientation() const;
void setOrientation(Qt::Orientation orientation);
+ enum SnapMode {
+ NoSnap,
+ SnapAlways,
+ SnapOnRelease
+ };
+ Q_ENUM(SnapMode)
+
+ SnapMode snapMode() const;
+ void setSnapMode(SnapMode mode);
+
+ bool isInteractive() const;
+ void setInteractive(bool interactive);
+ void resetInteractive();
+
+ enum Policy {
+ AsNeeded = Qt::ScrollBarAsNeeded,
+ AlwaysOff = Qt::ScrollBarAlwaysOff,
+ AlwaysOn = Qt::ScrollBarAlwaysOn
+ };
+ Q_ENUM(Policy)
+
+ Policy policy() const;
+ void setPolicy(Policy policy);
+
public Q_SLOTS:
void increase();
void decrease();
@@ -99,15 +125,21 @@ Q_SIGNALS:
void activeChanged();
void pressedChanged();
void orientationChanged();
+ Q_REVISION(2) void snapModeChanged();
+ Q_REVISION(2) void interactiveChanged();
+ Q_REVISION(2) void policyChanged();
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
+ void mouseUngrabEvent() override;
+#if QT_CONFIG(quicktemplates2_hover)
void hoverChange() override;
+#endif
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
void accessibilityActiveChanged(bool active) override;
QAccessible::Role accessibleRole() const override;
#endif
@@ -126,7 +158,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickScrollBarAttached : public QObject
Q_PROPERTY(QQuickScrollBar *vertical READ vertical WRITE setVertical NOTIFY verticalChanged FINAL)
public:
- explicit QQuickScrollBarAttached(QQuickFlickable *flickable);
+ explicit QQuickScrollBarAttached(QObject *parent = nullptr);
~QQuickScrollBarAttached();
QQuickScrollBar *horizontal() const;
diff --git a/src/quicktemplates2/qquickscrollbar_p_p.h b/src/quicktemplates2/qquickscrollbar_p_p.h
new file mode 100644
index 00000000..cbbef2c8
--- /dev/null
+++ b/src/quicktemplates2/qquickscrollbar_p_p.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QQUICKSCROLLBAR_P_P_H
+#define QQUICKSCROLLBAR_P_P_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 <QtQuickTemplates2/private/qquickscrollbar_p.h>
+#include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
+#include <QtQuick/private/qquickitemchangelistener_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickFlickable;
+
+class QQuickScrollBarPrivate : public QQuickControlPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickScrollBar)
+
+public:
+ QQuickScrollBarPrivate();
+
+ static QQuickScrollBarPrivate *get(QQuickScrollBar *bar)
+ {
+ return bar->d_func();
+ }
+
+ qreal snapPosition(qreal position) const;
+ qreal positionAt(const QPointF &point) const;
+ void setInteractive(bool interactive);
+ void updateActive();
+ void resizeContent() override;
+
+ void handlePress(const QPointF &point);
+ void handleMove(const QPointF &point);
+ void handleRelease(const QPointF &point);
+ void handleUngrab();
+
+ qreal size;
+ qreal position;
+ qreal stepSize;
+ qreal offset;
+ bool active;
+ bool pressed;
+ bool moving;
+ bool interactive;
+ bool explicitInteractive;
+ Qt::Orientation orientation;
+ QQuickScrollBar::SnapMode snapMode;
+ QQuickScrollBar::Policy policy;
+};
+
+class QQuickScrollBarAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener
+{
+public:
+ QQuickScrollBarAttachedPrivate();
+
+ static QQuickScrollBarAttachedPrivate *get(QQuickScrollBarAttached *attached)
+ {
+ return attached->d_func();
+ }
+
+ void setFlickable(QQuickFlickable *flickable);
+
+ void initHorizontal();
+ void initVertical();
+ void cleanupHorizontal();
+ void cleanupVertical();
+ void activateHorizontal();
+ void activateVertical();
+ void scrollHorizontal();
+ void scrollVertical();
+ void mirrorVertical();
+
+ void layoutHorizontal(bool move = true);
+ void layoutVertical(bool move = true);
+
+ void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override;
+ void itemImplicitWidthChanged(QQuickItem *item) override;
+ void itemImplicitHeightChanged(QQuickItem *item) override;
+ void itemDestroyed(QQuickItem *item) override;
+
+ QQuickFlickable *flickable;
+ QQuickScrollBar *horizontal;
+ QQuickScrollBar *vertical;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKSCROLLBAR_P_P_H
diff --git a/src/quicktemplates2/qquickscrollindicator.cpp b/src/quicktemplates2/qquickscrollindicator.cpp
index e858e7c1..347c2a68 100644
--- a/src/quicktemplates2/qquickscrollindicator.cpp
+++ b/src/quicktemplates2/qquickscrollindicator.cpp
@@ -126,13 +126,20 @@ QT_BEGIN_NAMESPACE
\sa ScrollBar, {Customizing ScrollIndicator}, {Indicator Controls}
*/
+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;
+
class QQuickScrollIndicatorPrivate : public QQuickControlPrivate
{
Q_DECLARE_PUBLIC(QQuickScrollIndicator)
public:
- QQuickScrollIndicatorPrivate() : size(0), position(0),
- active(false), orientation(Qt::Vertical)
+ QQuickScrollIndicatorPrivate()
+ : size(0),
+ position(0),
+ active(false),
+ orientation(Qt::Vertical)
{
}
@@ -164,18 +171,14 @@ void QQuickScrollIndicatorPrivate::resizeContent()
}
}
-QQuickScrollIndicator::QQuickScrollIndicator(QQuickItem *parent) :
- QQuickControl(*(new QQuickScrollIndicatorPrivate), parent)
+QQuickScrollIndicator::QQuickScrollIndicator(QQuickItem *parent)
+ : QQuickControl(*(new QQuickScrollIndicatorPrivate), parent)
{
}
QQuickScrollIndicatorAttached *QQuickScrollIndicator::qmlAttachedProperties(QObject *object)
{
- QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(object);
- if (!flickable)
- qmlInfo(object) << "ScrollIndicator must be attached to a Flickable";
-
- return new QQuickScrollIndicatorAttached(flickable);
+ return new QQuickScrollIndicatorAttached(object);
}
/*!
@@ -295,7 +298,12 @@ void QQuickScrollIndicator::setOrientation(Qt::Orientation orientation)
class QQuickScrollIndicatorAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener
{
public:
- QQuickScrollIndicatorAttachedPrivate(QQuickFlickable *flickable) : flickable(flickable), horizontal(nullptr), vertical(nullptr) { }
+ QQuickScrollIndicatorAttachedPrivate()
+ : flickable(nullptr),
+ horizontal(nullptr),
+ vertical(nullptr)
+ {
+ }
void activateHorizontal();
void activateVertical();
@@ -304,6 +312,8 @@ public:
void layoutVertical(bool move = true);
void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override;
+ void itemImplicitWidthChanged(QQuickItem *item) override;
+ void itemImplicitHeightChanged(QQuickItem *item) override;
void itemDestroyed(QQuickItem *item) override;
QQuickFlickable *flickable;
@@ -363,6 +373,18 @@ void QQuickScrollIndicatorAttachedPrivate::itemGeometryChanged(QQuickItem *item,
}
}
+void QQuickScrollIndicatorAttachedPrivate::itemImplicitWidthChanged(QQuickItem *item)
+{
+ if (item == vertical)
+ layoutVertical(true);
+}
+
+void QQuickScrollIndicatorAttachedPrivate::itemImplicitHeightChanged(QQuickItem *item)
+{
+ if (item == horizontal)
+ layoutHorizontal(true);
+}
+
void QQuickScrollIndicatorAttachedPrivate::itemDestroyed(QQuickItem *item)
{
if (item == horizontal)
@@ -371,14 +393,15 @@ void QQuickScrollIndicatorAttachedPrivate::itemDestroyed(QQuickItem *item)
vertical = nullptr;
}
-QQuickScrollIndicatorAttached::QQuickScrollIndicatorAttached(QQuickFlickable *flickable) :
- QObject(*(new QQuickScrollIndicatorAttachedPrivate(flickable)), flickable)
+QQuickScrollIndicatorAttached::QQuickScrollIndicatorAttached(QObject *parent)
+ : QObject(*(new QQuickScrollIndicatorAttachedPrivate), parent)
{
Q_D(QQuickScrollIndicatorAttached);
- if (flickable) {
- QQuickItemPrivate *p = QQuickItemPrivate::get(flickable);
- p->updateOrAddGeometryChangeListener(d, QQuickGeometryChange::Size);
- }
+ d->flickable = qobject_cast<QQuickFlickable *>(parent);
+ if (d->flickable)
+ QQuickItemPrivate::get(d->flickable)->updateOrAddGeometryChangeListener(d, QQuickGeometryChange::Size);
+ else if (parent)
+ qmlWarning(parent) << "ScrollIndicator must be attached to a Flickable";
}
QQuickScrollIndicatorAttached::~QQuickScrollIndicatorAttached()
@@ -386,9 +409,12 @@ QQuickScrollIndicatorAttached::~QQuickScrollIndicatorAttached()
Q_D(QQuickScrollIndicatorAttached);
if (d->flickable) {
if (d->horizontal)
- QQuickItemPrivate::get(d->horizontal)->removeItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
+ QQuickItemPrivate::get(d->horizontal)->removeItemChangeListener(d, horizontalChangeTypes);
if (d->vertical)
- QQuickItemPrivate::get(d->vertical)->removeItemChangeListener(d,QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
+ QQuickItemPrivate::get(d->vertical)->removeItemChangeListener(d,verticalChangeTypes);
+ // 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(d->flickable)->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
}
}
@@ -420,7 +446,7 @@ void QQuickScrollIndicatorAttached::setHorizontal(QQuickScrollIndicator *horizon
return;
if (d->horizontal && d->flickable) {
- QQuickItemPrivate::get(d->horizontal)->removeItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
+ QQuickItemPrivate::get(d->horizontal)->removeItemChangeListener(d, horizontalChangeTypes);
QObjectPrivate::disconnect(d->flickable, &QQuickFlickable::movingHorizontallyChanged, d, &QQuickScrollIndicatorAttachedPrivate::activateHorizontal);
// TODO: export QQuickFlickableVisibleArea
@@ -436,7 +462,7 @@ void QQuickScrollIndicatorAttached::setHorizontal(QQuickScrollIndicator *horizon
horizontal->setParentItem(d->flickable);
horizontal->setOrientation(Qt::Horizontal);
- QQuickItemPrivate::get(horizontal)->addItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
+ QQuickItemPrivate::get(horizontal)->addItemChangeListener(d, horizontalChangeTypes);
QObjectPrivate::connect(d->flickable, &QQuickFlickable::movingHorizontallyChanged, d, &QQuickScrollIndicatorAttachedPrivate::activateHorizontal);
// TODO: export QQuickFlickableVisibleArea
@@ -478,7 +504,7 @@ void QQuickScrollIndicatorAttached::setVertical(QQuickScrollIndicator *vertical)
return;
if (d->vertical && d->flickable) {
- QQuickItemPrivate::get(d->vertical)->removeItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
+ QQuickItemPrivate::get(d->vertical)->removeItemChangeListener(d, verticalChangeTypes);
QObjectPrivate::disconnect(d->flickable, &QQuickFlickable::movingVerticallyChanged, d, &QQuickScrollIndicatorAttachedPrivate::activateVertical);
// TODO: export QQuickFlickableVisibleArea
@@ -494,7 +520,7 @@ void QQuickScrollIndicatorAttached::setVertical(QQuickScrollIndicator *vertical)
vertical->setParentItem(d->flickable);
vertical->setOrientation(Qt::Vertical);
- QQuickItemPrivate::get(vertical)->addItemChangeListener(d, QQuickItemPrivate::Geometry | QQuickItemPrivate::Destroyed);
+ QQuickItemPrivate::get(vertical)->addItemChangeListener(d, verticalChangeTypes);
QObjectPrivate::connect(d->flickable, &QQuickFlickable::movingVerticallyChanged, d, &QQuickScrollIndicatorAttachedPrivate::activateVertical);
// TODO: export QQuickFlickableVisibleArea
@@ -509,7 +535,7 @@ void QQuickScrollIndicatorAttached::setVertical(QQuickScrollIndicator *vertical)
emit verticalChanged();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickScrollIndicator::accessibleRole() const
{
return QAccessible::Indicator;
diff --git a/src/quicktemplates2/qquickscrollindicator_p.h b/src/quicktemplates2/qquickscrollindicator_p.h
index 13be7394..bc6c5418 100644
--- a/src/quicktemplates2/qquickscrollindicator_p.h
+++ b/src/quicktemplates2/qquickscrollindicator_p.h
@@ -89,7 +89,7 @@ Q_SIGNALS:
void orientationChanged();
protected:
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
@@ -107,7 +107,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickScrollIndicatorAttached : public QO
Q_PROPERTY(QQuickScrollIndicator *vertical READ vertical WRITE setVertical NOTIFY verticalChanged FINAL)
public:
- explicit QQuickScrollIndicatorAttached(QQuickFlickable *flickable);
+ explicit QQuickScrollIndicatorAttached(QObject *parent = nullptr);
~QQuickScrollIndicatorAttached();
QQuickScrollIndicator *horizontal() const;
diff --git a/src/quicktemplates2/qquickscrollview.cpp b/src/quicktemplates2/qquickscrollview.cpp
new file mode 100644
index 00000000..fc763511
--- /dev/null
+++ b/src/quicktemplates2/qquickscrollview.cpp
@@ -0,0 +1,572 @@
+/****************************************************************************
+**
+** 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 "qquickscrollview_p.h"
+#include "qquickcontrol_p_p.h"
+#include "qquickscrollbar_p_p.h"
+
+#include <QtQuick/private/qquickflickable_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype ScrollView
+ \inherits Control
+ \instantiates QQuickScrollView
+ \inqmlmodule QtQuick.Controls
+ \since 5.9
+ \ingroup qtquickcontrols2-containers
+ \brief Scrollable view.
+
+ ScrollView provides scrolling for user-defined content. It can be used to
+ either replace a \l Flickable, or to decorate an existing one.
+
+ \image qtquickcontrols2-scrollview.png
+
+ The first example demonstrates the simplest usage of ScrollView.
+
+ \snippet qtquickcontrols2-scrollview.qml file
+
+ \note ScrollView does not automatically clip its contents. If it is not used as
+ a full-screen item, you should consider setting the \l {Item::}{clip} property
+ to \c true, as shown above.
+
+ The second example illustrates using an existing \l Flickable, that is,
+ a \l ListView.
+
+ \snippet qtquickcontrols2-scrollview-listview.qml file
+
+ \section2 Scroll Bars
+
+ The horizontal and vertical scroll bars can be accessed and customized using
+ the \l {ScrollBar::horizontal}{ScrollBar.horizontal} and \l {ScrollBar::vertical}
+ {ScrollBar.vertical} attached properties. The following example adjusts the scroll
+ bar policies so that the horizontal scroll bar is always off, and the vertical
+ scroll bar is always on.
+
+ \snippet qtquickcontrols2-scrollview-policy.qml file
+
+ \section2 Touch vs. Mouse Interaction
+
+ On touch, ScrollView enables flicking and makes the scroll bars non-interactive.
+
+ \image qtquickcontrols2-scrollindicator.gif
+
+ When interacted with a mouse device, flicking is disabled and the scroll bars
+ are interactive.
+
+ \image qtquickcontrols2-scrollbar.gif
+
+ Scroll bars can be made interactive on touch, or non-interactive when interacted
+ with a mouse device, by setting the \l {ScrollBar::}{interactive} property explicitly
+ to \c true or \c false, respectively.
+
+ \snippet qtquickcontrols2-scrollview-interactive.qml file
+
+ \sa ScrollBar, ScrollIndicator, {Customizing ScrollView}, {Container Controls},
+*/
+
+class QQuickScrollViewPrivate : public QQuickControlPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickScrollView)
+
+public:
+ QQuickScrollViewPrivate();
+
+ QQuickItem *getContentItem() override;
+
+ QQuickFlickable *ensureFlickable();
+ bool setFlickable(QQuickFlickable *flickable, bool content);
+
+ void updateContentWidth();
+ void updateContentHeight();
+
+ QQuickScrollBar *verticalScrollBar() const;
+ QQuickScrollBar *horizontalScrollBar() const;
+
+ void setScrollBarsInteractive(bool interactive);
+
+ static void contentData_append(QQmlListProperty<QObject> *prop, QObject *obj);
+ static int contentData_count(QQmlListProperty<QObject> *prop);
+ static QObject *contentData_at(QQmlListProperty<QObject> *prop, int index);
+ static void contentData_clear(QQmlListProperty<QObject> *prop);
+
+ static void contentChildren_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *obj);
+ static int contentChildren_count(QQmlListProperty<QQuickItem> *prop);
+ static QQuickItem *contentChildren_at(QQmlListProperty<QQuickItem> *prop, int index);
+ static void contentChildren_clear(QQmlListProperty<QQuickItem> *prop);
+
+ bool wasTouched;
+ qreal contentWidth;
+ qreal contentHeight;
+ QQuickFlickable *flickable;
+};
+
+QQuickScrollViewPrivate::QQuickScrollViewPrivate()
+ : wasTouched(false),
+ contentWidth(-1),
+ contentHeight(-1),
+ flickable(nullptr)
+{
+ wheelEnabled = true;
+}
+
+QQuickItem *QQuickScrollViewPrivate::getContentItem()
+{
+ return ensureFlickable();
+}
+
+QQuickFlickable *QQuickScrollViewPrivate::ensureFlickable()
+{
+ Q_Q(QQuickScrollView);
+ if (!flickable)
+ setFlickable(new QQuickFlickable(q), true);
+ return flickable;
+}
+
+bool QQuickScrollViewPrivate::setFlickable(QQuickFlickable *item, bool content)
+{
+ Q_Q(QQuickScrollView);
+ if (item == flickable)
+ return false;
+
+ QQuickScrollBarAttached *attached = qobject_cast<QQuickScrollBarAttached *>(qmlAttachedPropertiesObject<QQuickScrollBar>(q, false));
+
+ if (flickable) {
+ flickable->removeEventFilter(q);
+
+ if (attached)
+ QQuickScrollBarAttachedPrivate::get(attached)->setFlickable(nullptr);
+
+ QObject::disconnect(flickable->contentItem(), &QQuickItem::childrenChanged, q, &QQuickScrollView::contentChildrenChanged);
+ QObjectPrivate::disconnect(flickable, &QQuickFlickable::contentWidthChanged, this, &QQuickScrollViewPrivate::updateContentWidth);
+ QObjectPrivate::disconnect(flickable, &QQuickFlickable::contentHeightChanged, this, &QQuickScrollViewPrivate::updateContentHeight);
+ }
+
+ flickable = item;
+ if (content)
+ q->setContentItem(flickable);
+
+ if (flickable) {
+ flickable->installEventFilter(q);
+ if (contentWidth > 0)
+ item->setContentWidth(contentWidth);
+ else
+ updateContentWidth();
+ if (contentHeight > 0)
+ item->setContentHeight(contentHeight);
+ else
+ updateContentHeight();
+
+ if (attached)
+ QQuickScrollBarAttachedPrivate::get(attached)->setFlickable(flickable);
+
+ QObject::connect(flickable->contentItem(), &QQuickItem::childrenChanged, q, &QQuickScrollView::contentChildrenChanged);
+ QObjectPrivate::connect(flickable, &QQuickFlickable::contentWidthChanged, this, &QQuickScrollViewPrivate::updateContentWidth);
+ QObjectPrivate::connect(flickable, &QQuickFlickable::contentHeightChanged, this, &QQuickScrollViewPrivate::updateContentHeight);
+ }
+
+ return true;
+}
+
+void QQuickScrollViewPrivate::updateContentWidth()
+{
+ Q_Q(QQuickScrollView);
+ if (!flickable)
+ return;
+
+ const qreal cw = flickable->contentWidth();
+ if (qFuzzyCompare(cw, contentWidth))
+ return;
+
+ contentWidth = cw;
+ emit q->contentWidthChanged();
+}
+
+void QQuickScrollViewPrivate::updateContentHeight()
+{
+ Q_Q(QQuickScrollView);
+ if (!flickable)
+ return;
+
+ const qreal ch = flickable->contentHeight();
+ if (qFuzzyCompare(ch, contentHeight))
+ return;
+
+ contentHeight = ch;
+ emit q->contentHeightChanged();
+}
+
+QQuickScrollBar *QQuickScrollViewPrivate::verticalScrollBar() const
+{
+ Q_Q(const QQuickScrollView);
+ QQuickScrollBarAttached *attached = qobject_cast<QQuickScrollBarAttached *>(qmlAttachedPropertiesObject<QQuickScrollBar>(q, false));
+ if (!attached)
+ return nullptr;
+ return attached->vertical();
+}
+
+QQuickScrollBar *QQuickScrollViewPrivate::horizontalScrollBar() const
+{
+ Q_Q(const QQuickScrollView);
+ QQuickScrollBarAttached *attached = qobject_cast<QQuickScrollBarAttached *>(qmlAttachedPropertiesObject<QQuickScrollBar>(q, false));
+ if (!attached)
+ return nullptr;
+ return attached->horizontal();
+}
+
+void QQuickScrollViewPrivate::setScrollBarsInteractive(bool interactive)
+{
+ QQuickScrollBar *hbar = horizontalScrollBar();
+ if (hbar) {
+ QQuickScrollBarPrivate *p = QQuickScrollBarPrivate::get(hbar);
+ if (!p->explicitInteractive)
+ p->setInteractive(interactive);
+ }
+
+ QQuickScrollBar *vbar = verticalScrollBar();
+ if (vbar) {
+ QQuickScrollBarPrivate *p = QQuickScrollBarPrivate::get(vbar);
+ if (!p->explicitInteractive)
+ p->setInteractive(interactive);
+ }
+}
+
+void QQuickScrollViewPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObject *obj)
+{
+ QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
+ if (!p->flickable && p->setFlickable(qobject_cast<QQuickFlickable *>(obj), true))
+ return;
+
+ QQuickFlickable *flickable = p->ensureFlickable();
+ Q_ASSERT(flickable);
+ QQmlListProperty<QObject> data = flickable->flickableData();
+ data.append(&data, obj);
+}
+
+int QQuickScrollViewPrivate::contentData_count(QQmlListProperty<QObject> *prop)
+{
+ QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
+ if (!p->flickable)
+ return 0;
+
+ QQmlListProperty<QObject> data = p->flickable->flickableData();
+ return data.count(&data);
+}
+
+QObject *QQuickScrollViewPrivate::contentData_at(QQmlListProperty<QObject> *prop, int index)
+{
+ QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
+ if (!p->flickable)
+ return nullptr;
+
+ QQmlListProperty<QObject> data = p->flickable->flickableData();
+ return data.at(&data, index);
+}
+
+void QQuickScrollViewPrivate::contentData_clear(QQmlListProperty<QObject> *prop)
+{
+ QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
+ if (!p->flickable)
+ return;
+
+ QQmlListProperty<QObject> data = p->flickable->flickableData();
+ return data.clear(&data);
+}
+
+void QQuickScrollViewPrivate::contentChildren_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *item)
+{
+ QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
+ if (!p->flickable)
+ p->setFlickable(qobject_cast<QQuickFlickable *>(item), true);
+
+ QQuickFlickable *flickable = p->ensureFlickable();
+ Q_ASSERT(flickable);
+ QQmlListProperty<QQuickItem> children = flickable->flickableChildren();
+ children.append(&children, item);
+}
+
+int QQuickScrollViewPrivate::contentChildren_count(QQmlListProperty<QQuickItem> *prop)
+{
+ QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
+ if (!p->flickable)
+ return 0;
+
+ QQmlListProperty<QQuickItem> children = p->flickable->flickableChildren();
+ return children.count(&children);
+}
+
+QQuickItem *QQuickScrollViewPrivate::contentChildren_at(QQmlListProperty<QQuickItem> *prop, int index)
+{
+ QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
+ if (!p->flickable)
+ return nullptr;
+
+ QQmlListProperty<QQuickItem> children = p->flickable->flickableChildren();
+ return children.at(&children, index);
+}
+
+void QQuickScrollViewPrivate::contentChildren_clear(QQmlListProperty<QQuickItem> *prop)
+{
+ QQuickScrollViewPrivate *p = static_cast<QQuickScrollViewPrivate *>(prop->data);
+ if (!p->flickable)
+ return;
+
+ QQmlListProperty<QQuickItem> children = p->flickable->flickableChildren();
+ children.clear(&children);
+}
+
+QQuickScrollView::QQuickScrollView(QQuickItem *parent)
+ : QQuickControl(*(new QQuickScrollViewPrivate), parent)
+{
+ setFlag(ItemIsFocusScope);
+ setActiveFocusOnTab(true);
+ setFiltersChildMouseEvents(true);
+}
+
+/*!
+ \qmlproperty real QtQuick.Controls::ScrollView::contentWidth
+
+ This property holds the width of the scrollable content.
+
+ If only a single item is used within a ScrollView, the content size is
+ automatically calculated based on the implicit size of its contained item.
+
+ \sa contentHeight
+*/
+qreal QQuickScrollView::contentWidth() const
+{
+ Q_D(const QQuickScrollView);
+ return d->contentWidth;
+}
+
+void QQuickScrollView::setContentWidth(qreal width)
+{
+ Q_D(QQuickScrollView);
+ if (qFuzzyCompare(d->contentWidth, width))
+ return;
+
+ if (d->flickable) {
+ d->flickable->setContentWidth(width);
+ } else {
+ d->contentWidth = width;
+ emit contentWidthChanged();
+ }
+}
+
+/*!
+ \qmlproperty real QtQuick.Controls::ScrollView::contentHeight
+
+ This property holds the height of the scrollable content.
+
+ If only a single item is used within a ScrollView, the content size is
+ automatically calculated based on the implicit size of its contained item.
+
+ \sa contentWidth
+*/
+qreal QQuickScrollView::contentHeight() const
+{
+ Q_D(const QQuickScrollView);
+ return d->contentHeight;
+}
+
+void QQuickScrollView::setContentHeight(qreal height)
+{
+ Q_D(QQuickScrollView);
+ if (qFuzzyCompare(d->contentHeight, height))
+ return;
+
+ if (d->flickable) {
+ d->flickable->setContentHeight(height);
+ } else {
+ d->contentHeight = height;
+ emit contentHeightChanged();
+ }
+}
+
+/*!
+ \qmlproperty list<Object> QtQuick.Controls::ScrollView::contentData
+ \default
+
+ This property holds the list of content data.
+
+ The list contains all objects that have been declared in QML as children of the view.
+
+ \note Unlike \c contentChildren, \c contentData does include non-visual QML objects.
+
+ \sa Item::data, contentChildren
+*/
+QQmlListProperty<QObject> QQuickScrollView::contentData()
+{
+ Q_D(QQuickScrollView);
+ return QQmlListProperty<QObject>(this, d,
+ QQuickScrollViewPrivate::contentData_append,
+ QQuickScrollViewPrivate::contentData_count,
+ QQuickScrollViewPrivate::contentData_at,
+ QQuickScrollViewPrivate::contentData_clear);
+}
+
+/*!
+ \qmlproperty list<Item> QtQuick.Controls::ScrollView::contentChildren
+
+ This property holds the list of content children.
+
+ The list contains all items that have been declared in QML as children of the view.
+
+ \note Unlike \c contentData, \c contentChildren does not include non-visual QML objects.
+
+ \sa Item::children, contentData
+*/
+QQmlListProperty<QQuickItem> QQuickScrollView::contentChildren()
+{
+ Q_D(QQuickScrollView);
+ return QQmlListProperty<QQuickItem>(this, d,
+ QQuickScrollViewPrivate::contentChildren_append,
+ QQuickScrollViewPrivate::contentChildren_count,
+ QQuickScrollViewPrivate::contentChildren_at,
+ QQuickScrollViewPrivate::contentChildren_clear);
+}
+
+bool QQuickScrollView::childMouseEventFilter(QQuickItem *item, QEvent *event)
+{
+ Q_D(QQuickScrollView);
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ d->wasTouched = true;
+ d->setScrollBarsInteractive(false);
+ return false;
+
+ case QEvent::TouchEnd:
+ d->wasTouched = false;
+ return false;
+
+ case QEvent::MouseButtonPress:
+ // NOTE: Flickable does not handle touch events, only synthesized mouse events
+ if (static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventNotSynthesized) {
+ d->wasTouched = false;
+ d->setScrollBarsInteractive(true);
+ return false;
+ }
+ return !d->wasTouched && item == d->flickable;
+
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ if (static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventNotSynthesized)
+ return item == d->flickable;
+ break;
+
+ case QEvent::HoverEnter:
+ case QEvent::HoverMove:
+ if (d->wasTouched && (item == d->verticalScrollBar() || item == d->horizontalScrollBar()))
+ d->setScrollBarsInteractive(true);
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool QQuickScrollView::eventFilter(QObject *object, QEvent *event)
+{
+ Q_D(QQuickScrollView);
+ if (event->type() == QEvent::Wheel) {
+ d->setScrollBarsInteractive(true);
+ if (!d->wheelEnabled)
+ return true;
+ }
+ return QQuickControl::eventFilter(object, event);
+}
+
+void QQuickScrollView::keyPressEvent(QKeyEvent *event)
+{
+ Q_D(QQuickScrollView);
+ QQuickControl::keyPressEvent(event);
+ switch (event->key()) {
+ case Qt::Key_Up:
+ if (QQuickScrollBar *vbar = d->verticalScrollBar()) {
+ vbar->decrease();
+ event->accept();
+ }
+ break;
+ case Qt::Key_Down:
+ if (QQuickScrollBar *vbar = d->verticalScrollBar()) {
+ vbar->increase();
+ event->accept();
+ }
+ break;
+ case Qt::Key_Left:
+ if (QQuickScrollBar *hbar = d->horizontalScrollBar()) {
+ hbar->decrease();
+ event->accept();
+ }
+ break;
+ case Qt::Key_Right:
+ if (QQuickScrollBar *hbar = d->horizontalScrollBar()) {
+ hbar->increase();
+ event->accept();
+ }
+ break;
+ default:
+ event->ignore();
+ break;
+ }
+}
+
+void QQuickScrollView::componentComplete()
+{
+ Q_D(QQuickScrollView);
+ QQuickControl::componentComplete();
+ if (!d->contentItem)
+ d->ensureFlickable();
+}
+
+void QQuickScrollView::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
+{
+ Q_D(QQuickScrollView);
+ QQuickControl::contentItemChange(newItem, oldItem);
+ d->setFlickable(qobject_cast<QQuickFlickable *>(newItem), false);
+}
+
+#if QT_CONFIG(accessibility)
+QAccessible::Role QQuickScrollView::accessibleRole() const
+{
+ return QAccessible::Pane;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickscrollview_p.h b/src/quicktemplates2/qquickscrollview_p.h
new file mode 100644
index 00000000..136260c2
--- /dev/null
+++ b/src/quicktemplates2/qquickscrollview_p.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QQUICKSCROLLVIEW_P_H
+#define QQUICKSCROLLVIEW_P_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 <QtQuickTemplates2/private/qquickcontrol_p.h>
+#include <QtQml/qqmllist.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickScrollViewPrivate;
+
+class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickScrollView : public QQuickControl
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth NOTIFY contentWidthChanged FINAL)
+ Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight NOTIFY contentHeightChanged FINAL)
+ Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL)
+ Q_PROPERTY(QQmlListProperty<QQuickItem> contentChildren READ contentChildren NOTIFY contentChildrenChanged FINAL)
+ Q_CLASSINFO("DefaultProperty", "contentData")
+
+public:
+ explicit QQuickScrollView(QQuickItem *parent = nullptr);
+
+ qreal contentWidth() const;
+ void setContentWidth(qreal width);
+
+ qreal contentHeight() const;
+ void setContentHeight(qreal height);
+
+ QQmlListProperty<QObject> contentData();
+ QQmlListProperty<QQuickItem> contentChildren();
+
+Q_SIGNALS:
+ void contentWidthChanged();
+ void contentHeightChanged();
+ void contentChildrenChanged();
+
+protected:
+ bool childMouseEventFilter(QQuickItem *item, QEvent *event) override;
+ bool eventFilter(QObject *object, QEvent *event) override;
+ void keyPressEvent(QKeyEvent *event) override;
+
+ void componentComplete() override;
+ void contentItemChange(QQuickItem *newItem, QQuickItem *oldItem) override;
+
+#if QT_CONFIG(accessibility)
+ QAccessible::Role accessibleRole() const override;
+#endif
+
+private:
+ Q_DISABLE_COPY(QQuickScrollView)
+ Q_DECLARE_PRIVATE(QQuickScrollView)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickScrollView)
+
+#endif // QQUICKSCROLLVIEW_P_H
diff --git a/src/quicktemplates2/qquickslider.cpp b/src/quicktemplates2/qquickslider.cpp
index da352f36..266f883f 100644
--- a/src/quicktemplates2/qquickslider.cpp
+++ b/src/quicktemplates2/qquickslider.cpp
@@ -75,29 +75,53 @@ QT_BEGIN_NAMESPACE
\sa {Customizing Slider}, {Input Controls}
*/
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlsignal QtQuick.Controls::Slider::moved()
+
+ This signal is emitted when the slider has been interactively moved
+ by the user by either touch, mouse, wheel, or keys.
+*/
+
class QQuickSliderPrivate : public QQuickControlPrivate
{
Q_DECLARE_PUBLIC(QQuickSlider)
public:
- QQuickSliderPrivate() : from(0), to(1), value(0), position(0), stepSize(0), pressed(false),
- orientation(Qt::Horizontal), snapMode(QQuickSlider::NoSnap),
- handle(nullptr)
+ QQuickSliderPrivate()
+ : from(0),
+ to(1),
+ value(0),
+ position(0),
+ stepSize(0),
+ live(true),
+ pressed(false),
+ touchId(-1),
+ orientation(Qt::Horizontal),
+ snapMode(QQuickSlider::NoSnap),
+ handle(nullptr)
{
}
qreal snapPosition(qreal position) const;
- qreal positionAt(const QPoint &point) const;
+ qreal positionAt(const QPointF &point) const;
void setPosition(qreal position);
void updatePosition();
+ void handlePress(const QPointF &point);
+ void handleMove(const QPointF &point);
+ void handleRelease(const QPointF &point);
+ void handleUngrab();
+
qreal from;
qreal to;
qreal value;
qreal position;
qreal stepSize;
+ bool live;
bool pressed;
- QPoint pressPoint;
+ int touchId;
+ QPointF pressPoint;
Qt::Orientation orientation;
QQuickSlider::SnapMode snapMode;
QQuickItem *handle;
@@ -116,26 +140,28 @@ qreal QQuickSliderPrivate::snapPosition(qreal position) const
return qRound(position / effectiveStep) * effectiveStep;
}
-qreal QQuickSliderPrivate::positionAt(const QPoint &point) const
+qreal QQuickSliderPrivate::positionAt(const QPointF &point) const
{
Q_Q(const QQuickSlider);
+ qreal pos = 0.0;
if (orientation == Qt::Horizontal) {
const qreal hw = handle ? handle->width() : 0;
const qreal offset = hw / 2;
const qreal extent = q->availableWidth() - hw;
if (!qFuzzyIsNull(extent)) {
if (q->isMirrored())
- return (q->width() - point.x() - q->rightPadding() - offset) / extent;
- return (point.x() - q->leftPadding() - offset) / extent;
+ pos = (q->width() - point.x() - q->rightPadding() - offset) / extent;
+ else
+ pos = (point.x() - q->leftPadding() - offset) / extent;
}
} else {
const qreal hh = handle ? handle->height() : 0;
const qreal offset = hh / 2;
const qreal extent = q->availableHeight() - hh;
if (!qFuzzyIsNull(extent))
- return (q->height() - point.y() - q->bottomPadding() - offset) / extent;
+ pos = (q->height() - point.y() - q->bottomPadding() - offset) / extent;
}
- return 0;
+ return qBound<qreal>(0.0, pos, 1.0);
}
void QQuickSliderPrivate::setPosition(qreal pos)
@@ -158,8 +184,61 @@ void QQuickSliderPrivate::updatePosition()
setPosition(pos);
}
-QQuickSlider::QQuickSlider(QQuickItem *parent) :
- QQuickControl(*(new QQuickSliderPrivate), parent)
+void QQuickSliderPrivate::handlePress(const QPointF &point)
+{
+ Q_Q(QQuickSlider);
+ pressPoint = point;
+ q->setPressed(true);
+}
+
+void QQuickSliderPrivate::handleMove(const QPointF &point)
+{
+ Q_Q(QQuickSlider);
+ if (!q->keepMouseGrab() && !q->keepTouchGrab())
+ return;
+ const qreal oldPos = position;
+ qreal pos = positionAt(point);
+ if (snapMode == QQuickSlider::SnapAlways)
+ pos = snapPosition(pos);
+ if (live)
+ q->setValue(q->valueAt(pos));
+ else
+ setPosition(pos);
+ if (!qFuzzyCompare(pos, oldPos))
+ emit q->moved();
+}
+
+void QQuickSliderPrivate::handleRelease(const QPointF &point)
+{
+ Q_Q(QQuickSlider);
+ touchId = -1;
+ pressPoint = QPointF();
+ const qreal oldPos = position;
+ qreal pos = positionAt(point);
+ if (snapMode != QQuickSlider::NoSnap)
+ pos = snapPosition(pos);
+ qreal val = q->valueAt(pos);
+ if (!qFuzzyCompare(val, value))
+ q->setValue(val);
+ else if (snapMode != QQuickSlider::NoSnap)
+ setPosition(pos);
+ if (!qFuzzyCompare(pos, oldPos))
+ emit q->moved();
+ q->setKeepMouseGrab(false);
+ q->setKeepTouchGrab(false);
+ q->setPressed(false);
+}
+
+void QQuickSliderPrivate::handleUngrab()
+{
+ Q_Q(QQuickSlider);
+ touchId = -1;
+ pressPoint = QPointF();
+ q->setPressed(false);
+}
+
+QQuickSlider::QQuickSlider(QQuickItem *parent)
+ : QQuickControl(*(new QQuickSliderPrivate), parent)
{
setActiveFocusOnTab(true);
setFocusPolicy(Qt::StrongFocus);
@@ -225,12 +304,7 @@ void QQuickSlider::setTo(qreal to)
This property holds the value in the range \c from - \c to. The default value is \c 0.0.
- Unlike the \l position property, the \c value is not updated while the
- handle is dragged, but only after the value has been chosen and the slider
- has been released. The \l valueAt() method can be used to get continuous
- updates.
-
- \sa position, valueAt()
+ \sa position
*/
qreal QQuickSlider::value() const
{
@@ -259,9 +333,8 @@ void QQuickSlider::setValue(qreal value)
This property holds the logical position of the handle.
The position is expressed as a fraction of the control's size, in the range
- \c {0.0 - 1.0}. Unlike the \l value property, the \c position is
- continuously updated while the handle is dragged. For visualizing a
- slider, the right-to-left aware \l visualPosition should be used instead.
+ \c {0.0 - 1.0}. For visualizing a slider, the right-to-left aware
+ \l visualPosition should be used instead.
\sa value, visualPosition, valueAt()
*/
@@ -356,6 +429,33 @@ void QQuickSlider::setSnapMode(SnapMode mode)
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::Slider::live
+
+ This property holds whether the slider provides live updates for the \l value
+ property while the handle is dragged.
+
+ The default value is \c true.
+
+ \sa value, valueAt()
+*/
+bool QQuickSlider::live() const
+{
+ Q_D(const QQuickSlider);
+ return d->live;
+}
+
+void QQuickSlider::setLive(bool live)
+{
+ Q_D(QQuickSlider);
+ if (d->live == live)
+ return;
+
+ d->live = live;
+ emit liveChanged();
+}
+
+/*!
\qmlproperty bool QtQuick.Controls::Slider::pressed
This property holds whether the slider is pressed.
@@ -421,7 +521,7 @@ void QQuickSlider::setHandle(QQuickItem *handle)
if (d->handle == handle)
return;
- d->deleteDelegate(d->handle);
+ QQuickControlPrivate::destroyDelegate(d->handle, this);
d->handle = handle;
if (handle && !handle->parentItem())
handle->setParentItem(this);
@@ -434,11 +534,6 @@ void QQuickSlider::setHandle(QQuickItem *handle)
Returns the value for the given \a position.
- The \l value property is not updated while the handle is dragged, but this
- method can be used to get continuous value updates:
-
- \snippet qtquickcontrols2-tooltip-slider.qml 1
-
\sa value, position
*/
qreal QQuickSlider::valueAt(qreal position) const
@@ -479,6 +574,8 @@ void QQuickSlider::keyPressEvent(QKeyEvent *event)
{
Q_D(QQuickSlider);
QQuickControl::keyPressEvent(event);
+
+ const qreal oldValue = d->value;
if (d->orientation == Qt::Horizontal) {
if (event->key() == Qt::Key_Left) {
setPressed(true);
@@ -506,6 +603,8 @@ void QQuickSlider::keyPressEvent(QKeyEvent *event)
event->accept();
}
}
+ if (!qFuzzyCompare(d->value, oldValue))
+ emit moved();
}
void QQuickSlider::keyReleaseEvent(QKeyEvent *event)
@@ -518,8 +617,7 @@ void QQuickSlider::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickSlider);
QQuickControl::mousePressEvent(event);
- d->pressPoint = event->pos();
- setPressed(true);
+ d->handlePress(event->localPos());
}
void QQuickSlider::mouseMoveEvent(QMouseEvent *event)
@@ -528,43 +626,83 @@ void QQuickSlider::mouseMoveEvent(QMouseEvent *event)
QQuickControl::mouseMoveEvent(event);
if (!keepMouseGrab()) {
if (d->orientation == Qt::Horizontal)
- setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->pos().x() - d->pressPoint.x(), Qt::XAxis, event));
+ setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->localPos().x() - d->pressPoint.x(), Qt::XAxis, event));
else
- setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->pos().y() - d->pressPoint.y(), Qt::YAxis, event));
- }
- if (keepMouseGrab()) {
- qreal pos = d->positionAt(event->pos());
- if (d->snapMode == SnapAlways)
- pos = d->snapPosition(pos);
- d->setPosition(pos);
+ setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->localPos().y() - d->pressPoint.y(), Qt::YAxis, event));
}
+ d->handleMove(event->localPos());
}
void QQuickSlider::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QQuickSlider);
QQuickControl::mouseReleaseEvent(event);
- d->pressPoint = QPoint();
- qreal pos = d->positionAt(event->pos());
- if (d->snapMode != NoSnap)
- pos = d->snapPosition(pos);
- qreal val = valueAt(pos);
- if (!qFuzzyCompare(val, d->value))
- setValue(val);
- else if (d->snapMode != NoSnap)
- d->setPosition(pos);
- setKeepMouseGrab(false);
- setPressed(false);
+ d->handleRelease(event->localPos());
}
void QQuickSlider::mouseUngrabEvent()
{
Q_D(QQuickSlider);
QQuickControl::mouseUngrabEvent();
- d->pressPoint = QPoint();
- setPressed(false);
+ d->handleUngrab();
+}
+
+void QQuickSlider::touchEvent(QTouchEvent *event)
+{
+ Q_D(QQuickSlider);
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ if (d->touchId == -1) {
+ const QTouchEvent::TouchPoint point = event->touchPoints().first();
+ d->touchId = point.id();
+ d->handlePress(point.pos());
+ } else {
+ event->ignore();
+ }
+ break;
+
+ case QEvent::TouchUpdate:
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ if (point.id() != d->touchId)
+ continue;
+
+ if (!keepTouchGrab()) {
+ if (d->orientation == Qt::Horizontal)
+ setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().x() - d->pressPoint.x(), Qt::XAxis, &point));
+ else
+ setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().y() - d->pressPoint.y(), Qt::YAxis, &point));
+ }
+ d->handleMove(point.pos());
+ }
+ break;
+
+ case QEvent::TouchEnd:
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ if (point.id() != d->touchId)
+ continue;
+
+ d->handleRelease(point.pos());
+ }
+ break;
+
+ case QEvent::TouchCancel:
+ d->handleUngrab();
+ break;
+
+ default:
+ QQuickControl::touchEvent(event);
+ break;
+ }
}
+void QQuickSlider::touchUngrabEvent()
+{
+ Q_D(QQuickSlider);
+ QQuickControl::touchUngrabEvent();
+ d->handleUngrab();
+}
+
+#if QT_CONFIG(wheelevent)
void QQuickSlider::wheelEvent(QWheelEvent *event)
{
Q_D(QQuickSlider);
@@ -575,9 +713,13 @@ void QQuickSlider::wheelEvent(QWheelEvent *event)
const qreal delta = (qFuzzyIsNull(angle.y()) ? angle.x() : (event->inverted() ? -angle.y() : angle.y())) / QWheelEvent::DefaultDeltasPerStep;
const qreal step = qFuzzyIsNull(d->stepSize) ? 0.1 : d->stepSize;
setValue(oldValue + step * delta);
- event->setAccepted(!qFuzzyCompare(d->value, oldValue));
+ const bool wasMoved = !qFuzzyCompare(d->value, oldValue);
+ if (wasMoved)
+ emit moved();
+ event->setAccepted(wasMoved);
}
}
+#endif
void QQuickSlider::mirrorChange()
{
@@ -593,7 +735,7 @@ void QQuickSlider::componentComplete()
d->updatePosition();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
void QQuickSlider::accessibilityActiveChanged(bool active)
{
QQuickControl::accessibilityActiveChanged(active);
diff --git a/src/quicktemplates2/qquickslider_p.h b/src/quicktemplates2/qquickslider_p.h
index d18a3c24..a6cf02fb 100644
--- a/src/quicktemplates2/qquickslider_p.h
+++ b/src/quicktemplates2/qquickslider_p.h
@@ -64,6 +64,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSlider : public QQuickControl
Q_PROPERTY(qreal visualPosition READ visualPosition NOTIFY visualPositionChanged FINAL)
Q_PROPERTY(qreal stepSize READ stepSize WRITE setStepSize NOTIFY stepSizeChanged FINAL)
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL)
+ Q_PROPERTY(bool live READ live WRITE setLive NOTIFY liveChanged FINAL REVISION 2)
Q_PROPERTY(bool pressed READ isPressed WRITE setPressed NOTIFY pressedChanged FINAL)
Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged FINAL)
Q_PROPERTY(QQuickItem *handle READ handle WRITE setHandle NOTIFY handleChanged FINAL)
@@ -96,6 +97,9 @@ public:
SnapMode snapMode() const;
void setSnapMode(SnapMode mode);
+ bool live() const;
+ void setLive(bool live);
+
bool isPressed() const;
void setPressed(bool pressed);
@@ -119,9 +123,11 @@ Q_SIGNALS:
void visualPositionChanged();
void stepSizeChanged();
void snapModeChanged();
+ Q_REVISION(2) void liveChanged();
void pressedChanged();
void orientationChanged();
void handleChanged();
+ Q_REVISION(2) void moved();
protected:
void keyPressEvent(QKeyEvent *event) override;
@@ -130,12 +136,16 @@ protected:
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseUngrabEvent() override;
+ void touchEvent(QTouchEvent *event) override;
+ void touchUngrabEvent() override;
+#if QT_CONFIG(wheelevent)
void wheelEvent(QWheelEvent *event) override;
+#endif
void mirrorChange() override;
void componentComplete() override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
void accessibilityActiveChanged(bool active) override;
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquickspinbox.cpp b/src/quicktemplates2/qquickspinbox.cpp
index c44b9e81..657102c3 100644
--- a/src/quicktemplates2/qquickspinbox.cpp
+++ b/src/quicktemplates2/qquickspinbox.cpp
@@ -43,6 +43,7 @@
#include <QtQml/qqmlinfo.h>
#include <QtQml/private/qqmllocale_p.h>
#include <QtQml/private/qqmlengine_p.h>
+#include <QtQuick/private/qquicktextinput_p.h>
QT_BEGIN_NAMESPACE
@@ -92,13 +93,34 @@ static const int AUTO_REPEAT_INTERVAL = 100;
\sa Tumbler, {Customizing SpinBox}
*/
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlsignal QtQuick.Controls::SpinBox::valueModified()
+
+ This signal is emitted when the spin box value has been interactively
+ modified by the user by either touch, mouse, wheel, or keys.
+*/
+
class QQuickSpinBoxPrivate : public QQuickControlPrivate
{
Q_DECLARE_PUBLIC(QQuickSpinBox)
public:
- QQuickSpinBoxPrivate() : editable(false), from(0), to(99), value(0), stepSize(1),
- delayTimer(0), repeatTimer(0), up(nullptr), down(nullptr), validator(nullptr) { }
+ QQuickSpinBoxPrivate()
+ : editable(false),
+ from(0),
+ to(99),
+ value(0),
+ stepSize(1),
+ delayTimer(0),
+ repeatTimer(0),
+ touchId(-1),
+ up(nullptr),
+ down(nullptr),
+ validator(nullptr),
+ inputMethodHints(Qt::ImhDigitsOnly)
+ {
+ }
int boundValue(int value) const;
void updateValue();
@@ -116,10 +138,10 @@ public:
void startPressRepeat();
void stopPressRepeat();
- bool handleMousePressEvent(QQuickItem *child, QMouseEvent *event);
- bool handleMouseMoveEvent(QQuickItem *child, QMouseEvent *event);
- bool handleMouseReleaseEvent(QQuickItem *child, QMouseEvent *event);
- bool handleMouseUngrabEvent(QQuickItem *child);
+ bool handlePress(const QPointF &point);
+ bool handleMove(const QPointF &point);
+ bool handleRelease(const QPointF &point);
+ bool handleUngrab();
bool editable;
int from;
@@ -128,11 +150,13 @@ public:
int stepSize;
int delayTimer;
int repeatTimer;
+ int touchId;
QQuickSpinButton *up;
QQuickSpinButton *down;
QValidator *validator;
mutable QJSValue textFromValue;
mutable QJSValue valueFromText;
+ Qt::InputMethodHints inputMethodHints;
};
int QQuickSpinBoxPrivate::boundValue(int value) const
@@ -151,7 +175,10 @@ void QQuickSpinBoxPrivate::updateValue()
QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine);
QJSValue loc(v4, QQmlLocale::wrap(v4, locale));
QJSValue val = q->valueFromText().call(QJSValueList() << text.toString() << loc);
+ const int oldValue = value;
q->setValue(val.toInt());
+ if (oldValue != value)
+ emit q->valueModified();
}
}
}
@@ -246,13 +273,13 @@ void QQuickSpinBoxPrivate::stopPressRepeat()
}
}
-bool QQuickSpinBoxPrivate::handleMousePressEvent(QQuickItem *child, QMouseEvent *event)
+bool QQuickSpinBoxPrivate::handlePress(const QPointF &point)
{
Q_Q(QQuickSpinBox);
QQuickItem *ui = up->indicator();
QQuickItem *di = down->indicator();
- up->setPressed(ui && ui->isEnabled() && ui->contains(ui->mapFromItem(child, event->pos())));
- down->setPressed(di && di->isEnabled() && di->contains(di->mapFromItem(child, event->pos())));
+ up->setPressed(ui && ui->isEnabled() && ui->contains(ui->mapFromItem(q, point)));
+ down->setPressed(di && di->isEnabled() && di->contains(di->mapFromItem(q, point)));
bool pressed = up->isPressed() || down->isPressed();
q->setAccessibleProperty("pressed", pressed);
@@ -261,13 +288,13 @@ bool QQuickSpinBoxPrivate::handleMousePressEvent(QQuickItem *child, QMouseEvent
return pressed;
}
-bool QQuickSpinBoxPrivate::handleMouseMoveEvent(QQuickItem *child, QMouseEvent *event)
+bool QQuickSpinBoxPrivate::handleMove(const QPointF &point)
{
Q_Q(QQuickSpinBox);
QQuickItem *ui = up->indicator();
QQuickItem *di = down->indicator();
- up->setPressed(ui && ui->isEnabled() && ui->contains(ui->mapFromItem(child, event->pos())));
- down->setPressed(di && di->isEnabled() && di->contains(di->mapFromItem(child, event->pos())));
+ up->setPressed(ui && ui->isEnabled() && ui->contains(ui->mapFromItem(q, point)));
+ down->setPressed(di && di->isEnabled() && di->contains(di->mapFromItem(q, point)));
bool pressed = up->isPressed() || down->isPressed();
q->setAccessibleProperty("pressed", pressed);
@@ -276,40 +303,46 @@ bool QQuickSpinBoxPrivate::handleMouseMoveEvent(QQuickItem *child, QMouseEvent *
return pressed;
}
-bool QQuickSpinBoxPrivate::handleMouseReleaseEvent(QQuickItem *child, QMouseEvent *event)
+bool QQuickSpinBoxPrivate::handleRelease(const QPointF &point)
{
Q_Q(QQuickSpinBox);
QQuickItem *ui = up->indicator();
QQuickItem *di = down->indicator();
+
+ int oldValue = value;
bool wasPressed = up->isPressed() || down->isPressed();
if (up->isPressed()) {
up->setPressed(false);
- if (repeatTimer <= 0 && ui && ui->contains(ui->mapFromItem(child, event->pos())))
+ if (repeatTimer <= 0 && ui && ui->contains(ui->mapFromItem(q, point)))
q->increase();
} else if (down->isPressed()) {
down->setPressed(false);
- if (repeatTimer <= 0 && di && di->contains(di->mapFromItem(child, event->pos())))
+ if (repeatTimer <= 0 && di && di->contains(di->mapFromItem(q, point)))
q->decrease();
}
+ if (value != oldValue)
+ emit q->valueModified();
+ touchId = -1;
q->setAccessibleProperty("pressed", false);
stopPressRepeat();
return wasPressed;
}
-bool QQuickSpinBoxPrivate::handleMouseUngrabEvent(QQuickItem *)
+bool QQuickSpinBoxPrivate::handleUngrab()
{
Q_Q(QQuickSpinBox);
up->setPressed(false);
down->setPressed(false);
+ touchId = -1;
q->setAccessibleProperty("pressed", false);
stopPressRepeat();
return false;
}
-QQuickSpinBox::QQuickSpinBox(QQuickItem *parent) :
- QQuickControl(*(new QQuickSpinBoxPrivate), parent)
+QQuickSpinBox::QQuickSpinBox(QQuickItem *parent)
+ : QQuickControl(*(new QQuickSpinBoxPrivate), parent)
{
Q_D(QQuickSpinBox);
d->up = new QQuickSpinButton(this);
@@ -520,7 +553,7 @@ void QQuickSpinBox::setTextFromValue(const QJSValue &callback)
{
Q_D(QQuickSpinBox);
if (!callback.isCallable()) {
- qmlInfo(this) << "textFromValue must be a callable function";
+ qmlWarning(this) << "textFromValue must be a callable function";
return;
}
d->textFromValue = callback;
@@ -568,7 +601,7 @@ void QQuickSpinBox::setValueFromText(const QJSValue &callback)
{
Q_D(QQuickSpinBox);
if (!callback.isCallable()) {
- qmlInfo(this) << "valueFromText must be a callable function";
+ qmlWarning(this) << "valueFromText must be a callable function";
return;
}
d->valueFromText = callback;
@@ -610,6 +643,50 @@ QQuickSpinButton *QQuickSpinBox::down() const
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty flags QtQuick.Controls::SpinBox::inputMethodHints
+
+ This property provides hints to the input method about the expected content
+ of the spin box and how it should operate.
+
+ The default value is \c Qt.ImhDigitsOnly.
+
+ \include inputmethodhints.qdocinc
+*/
+Qt::InputMethodHints QQuickSpinBox::inputMethodHints() const
+{
+ Q_D(const QQuickSpinBox);
+ return d->inputMethodHints;
+}
+
+void QQuickSpinBox::setInputMethodHints(Qt::InputMethodHints hints)
+{
+ Q_D(QQuickSpinBox);
+ if (d->inputMethodHints == hints)
+ return;
+
+ d->inputMethodHints = hints;
+ emit inputMethodHintsChanged();
+}
+
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty bool QtQuick.Controls::SpinBox::inputMethodComposing
+ \readonly
+
+ This property holds whether an editable spin box has partial text input from an input method.
+
+ While it is composing, an input method may rely on mouse or key events from the spin box to
+ edit or commit the partial text. This property can be used to determine when to disable event
+ handlers that may interfere with the correct operation of an input method.
+*/
+bool QQuickSpinBox::isInputMethodComposing() const
+{
+ Q_D(const QQuickSpinBox);
+ return d->contentItem && d->contentItem->property("inputMethodComposing").toBool();
+}
+
+/*!
\qmlmethod void QtQuick.Controls::SpinBox::increase()
Increases the value by \l stepSize, or \c 1 if stepSize is not defined.
@@ -662,6 +739,7 @@ void QQuickSpinBox::keyPressEvent(QKeyEvent *event)
Q_D(QQuickSpinBox);
QQuickControl::keyPressEvent(event);
+ const int oldValue = d->value;
switch (event->key()) {
case Qt::Key_Up:
if (d->upEnabled()) {
@@ -682,6 +760,8 @@ void QQuickSpinBox::keyPressEvent(QKeyEvent *event)
default:
break;
}
+ if (d->value != oldValue)
+ emit valueModified();
setAccessibleProperty("pressed", d->up->isPressed() || d->down->isPressed());
}
@@ -699,49 +779,32 @@ void QQuickSpinBox::keyReleaseEvent(QKeyEvent *event)
setAccessibleProperty("pressed", false);
}
-bool QQuickSpinBox::childMouseEventFilter(QQuickItem *child, QEvent *event)
-{
- Q_D(QQuickSpinBox);
- 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:
- return d->handleMouseReleaseEvent(child, static_cast<QMouseEvent *>(event));
- case QEvent::UngrabMouse:
- return d->handleMouseUngrabEvent(child);
- default:
- return false;
- }
-}
-
void QQuickSpinBox::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickSpinBox);
QQuickControl::mousePressEvent(event);
- d->handleMousePressEvent(this, event);
+ d->handlePress(event->localPos());
}
void QQuickSpinBox::mouseMoveEvent(QMouseEvent *event)
{
Q_D(QQuickSpinBox);
QQuickControl::mouseMoveEvent(event);
- d->handleMouseMoveEvent(this, event);
+ d->handleMove(event->localPos());
}
void QQuickSpinBox::mouseReleaseEvent(QMouseEvent *event)
{
Q_D(QQuickSpinBox);
QQuickControl::mouseReleaseEvent(event);
- d->handleMouseReleaseEvent(this, event);
+ d->handleRelease(event->localPos());
}
void QQuickSpinBox::mouseUngrabEvent()
{
Q_D(QQuickSpinBox);
QQuickControl::mouseUngrabEvent();
- d->handleMouseUngrabEvent(this);
+ d->handleUngrab();
}
void QQuickSpinBox::timerEvent(QTimerEvent *event)
@@ -758,6 +821,56 @@ void QQuickSpinBox::timerEvent(QTimerEvent *event)
}
}
+void QQuickSpinBox::touchEvent(QTouchEvent *event)
+{
+ Q_D(QQuickSpinBox);
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ if (d->touchId == -1) {
+ const QTouchEvent::TouchPoint point = event->touchPoints().first();
+ d->touchId = point.id();
+ d->handlePress(point.pos());
+ } else {
+ event->ignore();
+ }
+ break;
+
+ case QEvent::TouchUpdate:
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ if (point.id() != d->touchId)
+ continue;
+
+ d->handleMove(point.pos());
+ }
+ break;
+
+ case QEvent::TouchEnd:
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ if (point.id() != d->touchId)
+ continue;
+
+ d->handleRelease(point.pos());
+ }
+ break;
+
+ case QEvent::TouchCancel:
+ d->handleUngrab();
+ break;
+
+ default:
+ QQuickControl::touchEvent(event);
+ break;
+ }
+}
+
+void QQuickSpinBox::touchUngrabEvent()
+{
+ Q_D(QQuickSpinBox);
+ QQuickControl::touchUngrabEvent();
+ d->handleUngrab();
+}
+
+#if QT_CONFIG(wheelevent)
void QQuickSpinBox::wheelEvent(QWheelEvent *event)
{
Q_D(QQuickSpinBox);
@@ -767,9 +880,12 @@ void QQuickSpinBox::wheelEvent(QWheelEvent *event)
const QPointF angle = event->angleDelta();
const qreal delta = (qFuzzyIsNull(angle.y()) ? angle.x() : angle.y()) / QWheelEvent::DefaultDeltasPerStep;
setValue(oldValue + qRound(d->effectiveStepSize() * delta));
+ if (d->value != oldValue)
+ emit valueModified();
event->setAccepted(d->value != oldValue);
}
}
+#endif
void QQuickSpinBox::componentComplete()
{
@@ -789,9 +905,15 @@ void QQuickSpinBox::itemChange(ItemChange change, const ItemChangeData &value)
void QQuickSpinBox::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
{
- Q_UNUSED(oldItem);
- if (newItem)
+ if (QQuickTextInput *oldInput = qobject_cast<QQuickTextInput *>(oldItem))
+ disconnect(oldInput, &QQuickTextInput::inputMethodComposingChanged, this, &QQuickSpinBox::inputMethodComposingChanged);
+
+ if (newItem) {
newItem->setActiveFocusOnTab(true);
+
+ if (QQuickTextInput *newInput = qobject_cast<QQuickTextInput *>(newItem))
+ connect(newInput, &QQuickTextInput::inputMethodComposingChanged, this, &QQuickSpinBox::inputMethodComposingChanged);
+ }
}
QFont QQuickSpinBox::defaultFont() const
@@ -799,7 +921,7 @@ QFont QQuickSpinBox::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::EditorFont);
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickSpinBox::accessibleRole() const
{
return QAccessible::SpinBox;
@@ -809,14 +931,20 @@ QAccessible::Role QQuickSpinBox::accessibleRole() const
class QQuickSpinButtonPrivate : public QObjectPrivate
{
public:
- QQuickSpinButtonPrivate() : pressed(false), hovered(false), indicator(nullptr) { }
+ QQuickSpinButtonPrivate()
+ : pressed(false),
+ hovered(false),
+ indicator(nullptr)
+ {
+ }
+
bool pressed;
bool hovered;
QQuickItem *indicator;
};
-QQuickSpinButton::QQuickSpinButton(QQuickSpinBox *parent) :
- QObject(*(new QQuickSpinButtonPrivate), parent)
+QQuickSpinButton::QQuickSpinButton(QQuickSpinBox *parent)
+ : QObject(*(new QQuickSpinButtonPrivate), parent)
{
}
@@ -864,18 +992,12 @@ void QQuickSpinButton::setIndicator(QQuickItem *indicator)
if (d->indicator == indicator)
return;
- QQuickControl *control = qobject_cast<QQuickControl*>(d->parent);
- if (control)
- QQuickControlPrivate::get(control)->deleteDelegate(d->indicator);
- else
- delete d->indicator;
-
+ QQuickControlPrivate::destroyDelegate(d->indicator, d->parent);
d->indicator = indicator;
if (indicator) {
if (!indicator->parentItem())
indicator->setParentItem(static_cast<QQuickItem *>(parent()));
- indicator->setAcceptedMouseButtons(Qt::LeftButton);
}
emit indicatorChanged();
}
diff --git a/src/quicktemplates2/qquickspinbox_p.h b/src/quicktemplates2/qquickspinbox_p.h
index a2ea90f9..3d554870 100644
--- a/src/quicktemplates2/qquickspinbox_p.h
+++ b/src/quicktemplates2/qquickspinbox_p.h
@@ -71,6 +71,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSpinBox : public QQuickControl
Q_PROPERTY(QJSValue valueFromText READ valueFromText WRITE setValueFromText NOTIFY valueFromTextChanged FINAL)
Q_PROPERTY(QQuickSpinButton *up READ up CONSTANT FINAL)
Q_PROPERTY(QQuickSpinButton *down READ down CONSTANT FINAL)
+ Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints NOTIFY inputMethodHintsChanged FINAL REVISION 2)
+ Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged FINAL REVISION 2)
public:
explicit QQuickSpinBox(QQuickItem *parent = nullptr);
@@ -102,6 +104,11 @@ public:
QQuickSpinButton *up() const;
QQuickSpinButton *down() const;
+ Qt::InputMethodHints inputMethodHints() const;
+ void setInputMethodHints(Qt::InputMethodHints hints);
+
+ bool isInputMethodComposing() const;
+
public Q_SLOTS:
void increase();
void decrease();
@@ -115,9 +122,11 @@ Q_SIGNALS:
void validatorChanged();
void textFromValueChanged();
void valueFromTextChanged();
+ Q_REVISION(2) void valueModified();
+ Q_REVISION(2) void inputMethodHintsChanged();
+ Q_REVISION(2) void inputMethodComposingChanged();
protected:
- bool childMouseEventFilter(QQuickItem *child, QEvent *event) override;
void hoverEnterEvent(QHoverEvent *event) override;
void hoverMoveEvent(QHoverEvent *event) override;
void hoverLeaveEvent(QHoverEvent *event) override;
@@ -128,7 +137,11 @@ protected:
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseUngrabEvent() override;
void timerEvent(QTimerEvent *event) override;
+ void touchEvent(QTouchEvent *event) override;
+ void touchUngrabEvent() override;
+#if QT_CONFIG(wheelevent)
void wheelEvent(QWheelEvent *event) override;
+#endif
void componentComplete() override;
void itemChange(ItemChange change, const ItemChangeData &value) override;
@@ -136,7 +149,7 @@ protected:
QFont defaultFont() const override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquickstackelement.cpp b/src/quicktemplates2/qquickstackelement.cpp
new file mode 100644
index 00000000..2744c3e9
--- /dev/null
+++ b/src/quicktemplates2/qquickstackelement.cpp
@@ -0,0 +1,314 @@
+/****************************************************************************
+**
+** 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 "qquickstackelement_p_p.h"
+#include "qquickstackview_p_p.h"
+
+#include <QtQml/qqmlinfo.h>
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlincubator.h>
+#include <QtQml/private/qv4qobjectwrapper_p.h>
+#include <QtQml/private/qqmlcomponent_p.h>
+#include <QtQml/private/qqmlengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static QQuickStackViewAttached *attachedStackObject(QQuickStackElement *element)
+{
+ QQuickStackViewAttached *attached = qobject_cast<QQuickStackViewAttached *>(qmlAttachedPropertiesObject<QQuickStackView>(element->item, false));
+ if (attached)
+ QQuickStackViewAttachedPrivate::get(attached)->element = element;
+ return attached;
+}
+
+class QQuickStackIncubator : public QQmlIncubator
+{
+public:
+ QQuickStackIncubator(QQuickStackElement *element)
+ : QQmlIncubator(Synchronous),
+ element(element)
+ {
+ }
+
+protected:
+ void setInitialState(QObject *object) override { element->incubate(object); }
+
+private:
+ QQuickStackElement *element;
+};
+
+QQuickStackElement::QQuickStackElement()
+ : QQuickItemViewTransitionableItem(nullptr),
+ index(-1),
+ init(false),
+ removal(false),
+ ownItem(false),
+ ownComponent(false),
+ widthValid(false),
+ heightValid(false),
+ context(nullptr),
+ component(nullptr),
+ view(nullptr),
+ status(QQuickStackView::Inactive)
+{
+}
+
+QQuickStackElement::~QQuickStackElement()
+{
+ if (item)
+ QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Destroyed);
+
+ if (ownComponent)
+ delete component;
+
+ QQuickStackViewAttached *attached = attachedStackObject(this);
+ if (item) {
+ if (ownItem) {
+ item->setParentItem(nullptr);
+ item->deleteLater();
+ item = nullptr;
+ } else {
+ setVisible(false);
+ if (!widthValid)
+ item->resetWidth();
+ if (!heightValid)
+ item->resetHeight();
+ if (item->parentItem() != originalParent) {
+ item->setParentItem(originalParent);
+ } else {
+ if (attached)
+ QQuickStackViewAttachedPrivate::get(attached)->itemParentChanged(item, nullptr);
+ }
+ }
+ }
+
+ if (attached)
+ emit attached->removed();
+
+ delete context;
+}
+
+QQuickStackElement *QQuickStackElement::fromString(const QString &str, QQuickStackView *view)
+{
+ QQuickStackElement *element = new QQuickStackElement;
+ element->component = new QQmlComponent(qmlEngine(view), QUrl(str), view);
+ element->ownComponent = true;
+ return element;
+}
+
+QQuickStackElement *QQuickStackElement::fromObject(QObject *object, QQuickStackView *view)
+{
+ Q_UNUSED(view);
+ QQuickStackElement *element = new QQuickStackElement;
+ element->component = qobject_cast<QQmlComponent *>(object);
+ element->item = qobject_cast<QQuickItem *>(object);
+ if (element->item)
+ element->originalParent = element->item->parentItem();
+ return element;
+}
+
+bool QQuickStackElement::load(QQuickStackView *parent)
+{
+ setView(parent);
+ if (!item) {
+ ownItem = true;
+
+ if (component->isLoading()) {
+ QObject::connect(component, &QQmlComponent::statusChanged, [this](QQmlComponent::Status status) {
+ if (status == QQmlComponent::Ready)
+ load(view);
+ else if (status == QQmlComponent::Error)
+ qWarning() << qPrintable(component->errorString().trimmed());
+ });
+ return true;
+ }
+
+ QQmlContext *creationContext = component->creationContext();
+ if (!creationContext)
+ creationContext = qmlContext(parent);
+ context = new QQmlContext(creationContext);
+ context->setContextObject(parent);
+
+ QQuickStackIncubator incubator(this);
+ component->create(incubator, context);
+ if (component->isError())
+ qWarning() << qPrintable(component->errorString().trimmed());
+ } else {
+ initialize();
+ }
+ return item;
+}
+
+void QQuickStackElement::incubate(QObject *object)
+{
+ item = qmlobject_cast<QQuickItem *>(object);
+ if (item) {
+ QQmlEngine::setObjectOwnership(item, QQmlEngine::CppOwnership);
+ item->setParent(view);
+ initialize();
+ }
+}
+
+void QQuickStackElement::initialize()
+{
+ if (!item || init)
+ return;
+
+ QQuickItemPrivate *p = QQuickItemPrivate::get(item);
+ if (!(widthValid = p->widthValid))
+ item->setWidth(view->width());
+ if (!(heightValid = p->heightValid))
+ item->setHeight(view->height());
+ item->setParentItem(view);
+ p->addItemChangeListener(this, QQuickItemPrivate::Destroyed);
+
+ if (!properties.isUndefined()) {
+ QQmlEngine *engine = qmlEngine(view);
+ Q_ASSERT(engine);
+ QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine);
+ Q_ASSERT(v4);
+ QV4::Scope scope(v4);
+ QV4::ScopedValue ipv(scope, properties.value());
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, qmlCallingContext.value());
+ QV4::ScopedValue qmlObject(scope, QV4::QObjectWrapper::wrap(v4, item));
+ QQmlComponentPrivate::setInitialProperties(v4, qmlContext, qmlObject, ipv);
+ properties.clear();
+ }
+
+ init = true;
+}
+
+void QQuickStackElement::setIndex(int value)
+{
+ if (index == value)
+ return;
+
+ index = value;
+ QQuickStackViewAttached *attached = attachedStackObject(this);
+ if (attached)
+ emit attached->indexChanged();
+}
+
+void QQuickStackElement::setView(QQuickStackView *value)
+{
+ if (view == value)
+ return;
+
+ view = value;
+ QQuickStackViewAttached *attached = attachedStackObject(this);
+ if (attached)
+ emit attached->viewChanged();
+}
+
+void QQuickStackElement::setStatus(QQuickStackView::Status value)
+{
+ if (status == value)
+ return;
+
+ status = value;
+ QQuickStackViewAttached *attached = attachedStackObject(this);
+ if (!attached)
+ return;
+
+ switch (value) {
+ case QQuickStackView::Inactive:
+ emit attached->deactivated();
+ break;
+ case QQuickStackView::Deactivating:
+ emit attached->deactivating();
+ break;
+ case QQuickStackView::Activating:
+ emit attached->activating();
+ break;
+ case QQuickStackView::Active:
+ emit attached->activated();
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+
+ emit attached->statusChanged();
+}
+
+void QQuickStackElement::setVisible(bool visible)
+{
+ QQuickStackViewAttached *attached = attachedStackObject(this);
+ if (!item || (attached && QQuickStackViewAttachedPrivate::get(attached)->explicitVisible))
+ return;
+
+ item->setVisible(visible);
+}
+
+void QQuickStackElement::transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget)
+{
+ if (transitioner)
+ transitioner->transitionNextReposition(this, type, asTarget);
+}
+
+bool QQuickStackElement::prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds)
+{
+ if (transitioner) {
+ if (item) {
+ QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors;
+ // TODO: expose QQuickAnchorLine so we can test for other conflicting anchors
+ if (anchors && (anchors->fill() || anchors->centerIn()))
+ qmlWarning(item) << "StackView has detected conflicting anchors. Transitions may not execute properly.";
+ }
+
+ // TODO: add force argument to QQuickItemViewTransitionableItem::prepareTransition()?
+ nextTransitionToSet = true;
+ nextTransitionFromSet = true;
+ nextTransitionFrom += QPointF(1, 1);
+ return QQuickItemViewTransitionableItem::prepareTransition(transitioner, index, viewBounds);
+ }
+ return false;
+}
+
+void QQuickStackElement::startTransition(QQuickItemViewTransitioner *transitioner, QQuickStackView::Status status)
+{
+ setStatus(status);
+ if (transitioner)
+ QQuickItemViewTransitionableItem::startTransition(transitioner, index);
+}
+
+void QQuickStackElement::itemDestroyed(QQuickItem *)
+{
+ item = nullptr;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickstackelement_p_p.h b/src/quicktemplates2/qquickstackelement_p_p.h
new file mode 100644
index 00000000..9cb11855
--- /dev/null
+++ b/src/quicktemplates2/qquickstackelement_p_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QQUICKSTACKELEMENT_P_P_H
+#define QQUICKSTACKELEMENT_P_P_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 <QtQuickTemplates2/private/qquickstackview_p.h>
+#include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
+#include <QtQuick/private/qquickitemviewtransition_p.h>
+#include <QtQuick/private/qquickitemchangelistener_p.h>
+#include <QtQml/private/qv4persistent_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlContext;
+class QQmlComponent;
+struct QQuickStackTransition;
+
+class QQuickStackElement : public QQuickItemViewTransitionableItem, public QQuickItemChangeListener
+{
+ QQuickStackElement();
+
+public:
+ ~QQuickStackElement();
+
+ static QQuickStackElement *fromString(const QString &str, QQuickStackView *view);
+ static QQuickStackElement *fromObject(QObject *object, QQuickStackView *view);
+
+ bool load(QQuickStackView *parent);
+ void incubate(QObject *object);
+ void initialize();
+
+ void setIndex(int index);
+ void setView(QQuickStackView *view);
+ void setStatus(QQuickStackView::Status status);
+ void setVisible(bool visible);
+
+ void transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget);
+ bool prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds);
+ void startTransition(QQuickItemViewTransitioner *transitioner, QQuickStackView::Status status);
+
+ void itemDestroyed(QQuickItem *item) override;
+
+ int index;
+ bool init;
+ bool removal;
+ bool ownItem;
+ bool ownComponent;
+ bool widthValid;
+ bool heightValid;
+ QQmlContext *context;
+ QQmlComponent *component;
+ QQuickStackView *view;
+ QPointer<QQuickItem> originalParent;
+ QQuickStackView::Status status;
+ QV4::PersistentValue properties;
+ QV4::PersistentValue qmlCallingContext;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKSTACKELEMENT_P_P_H
diff --git a/src/quicktemplates2/qquickstacktransition.cpp b/src/quicktemplates2/qquickstacktransition.cpp
new file mode 100644
index 00000000..058359c3
--- /dev/null
+++ b/src/quicktemplates2/qquickstacktransition.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** 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 "qquickstacktransition_p_p.h"
+#include "qquickstackelement_p_p.h"
+#include "qquickstackview_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+static QQuickStackTransition exitTransition(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
+{
+ QQuickStackTransition st;
+ st.status = QQuickStackView::Deactivating;
+ st.transition = nullptr;
+ st.element = element;
+
+ const QQuickItemViewTransitioner *transitioner = QQuickStackViewPrivate::get(view)->transitioner;
+
+ switch (operation) {
+ case QQuickStackView::PushTransition:
+ st.target = false;
+ st.type = QQuickItemViewTransitioner::AddTransition;
+ st.viewBounds = QRectF();
+ if (transitioner)
+ st.transition = transitioner->addDisplacedTransition;
+ break;
+ case QQuickStackView::ReplaceTransition:
+ st.target = false;
+ st.type = QQuickItemViewTransitioner::MoveTransition;
+ st.viewBounds = QRectF();
+ if (transitioner)
+ st.transition = transitioner->moveDisplacedTransition;
+ break;
+ case QQuickStackView::PopTransition:
+ st.target = true;
+ st.type = QQuickItemViewTransitioner::RemoveTransition;
+ st.viewBounds = view->boundingRect();
+ if (transitioner)
+ st.transition = transitioner->removeTransition;
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+
+ return st;
+}
+
+static QQuickStackTransition enterTransition(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
+{
+ QQuickStackTransition st;
+ st.status = QQuickStackView::Activating;
+ st.transition = nullptr;
+ st.element = element;
+
+ const QQuickItemViewTransitioner *transitioner = QQuickStackViewPrivate::get(view)->transitioner;
+
+ switch (operation) {
+ case QQuickStackView::PushTransition:
+ st.target = true;
+ st.type = QQuickItemViewTransitioner::AddTransition;
+ st.viewBounds = view->boundingRect();
+ if (transitioner)
+ st.transition = transitioner->addTransition;
+ break;
+ case QQuickStackView::ReplaceTransition:
+ st.target = true;
+ st.type = QQuickItemViewTransitioner::MoveTransition;
+ st.viewBounds = view->boundingRect();
+ if (transitioner)
+ st.transition = transitioner->moveTransition;
+ break;
+ case QQuickStackView::PopTransition:
+ st.target = false;
+ st.type = QQuickItemViewTransitioner::RemoveTransition;
+ st.viewBounds = QRectF();
+ if (transitioner)
+ st.transition = transitioner->removeDisplacedTransition;
+ break;
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+
+ return st;
+}
+
+static QQuickStackView::Operation operationTransition(QQuickStackView::Operation operation, QQuickStackView::Operation transition)
+{
+ if (operation == QQuickStackView::Immediate || operation == QQuickStackView::Transition)
+ return transition;
+ return operation;
+}
+
+QQuickStackTransition QQuickStackTransition::popExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
+{
+ return exitTransition(operationTransition(operation, QQuickStackView::PopTransition), element, view);
+}
+
+QQuickStackTransition QQuickStackTransition::popEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
+{
+ return enterTransition(operationTransition(operation, QQuickStackView::PopTransition), element, view);
+}
+
+QQuickStackTransition QQuickStackTransition::pushExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
+{
+ return exitTransition(operationTransition(operation, QQuickStackView::PushTransition), element, view);
+}
+
+QQuickStackTransition QQuickStackTransition::pushEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
+{
+ return enterTransition(operationTransition(operation, QQuickStackView::PushTransition), element, view);
+}
+
+QQuickStackTransition QQuickStackTransition::replaceExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
+{
+ return exitTransition(operationTransition(operation, QQuickStackView::ReplaceTransition), element, view);
+}
+
+QQuickStackTransition QQuickStackTransition::replaceEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
+{
+ return enterTransition(operationTransition(operation, QQuickStackView::ReplaceTransition), element, view);
+}
+
+QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickstacktransition_p_p.h b/src/quicktemplates2/qquickstacktransition_p_p.h
new file mode 100644
index 00000000..7101420c
--- /dev/null
+++ b/src/quicktemplates2/qquickstacktransition_p_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QQUICKSTACKTRANSITION_P_P_H
+#define QQUICKSTACKTRANSITION_P_P_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 <QtQuickTemplates2/private/qquickstackview_p.h>
+#include <QtQuick/private/qquickitemviewtransition_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickStackElement;
+
+struct QQuickStackTransition
+{
+ static QQuickStackTransition popExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
+ static QQuickStackTransition popEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
+
+ static QQuickStackTransition pushExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
+ static QQuickStackTransition pushEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
+
+ static QQuickStackTransition replaceExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
+ static QQuickStackTransition replaceEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
+
+ bool target;
+ QQuickStackView::Status status;
+ QQuickItemViewTransitioner::TransitionType type;
+ QRectF viewBounds;
+ QQuickStackElement *element;
+ QQuickTransition *transition;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKSTACKTRANSITION_P_P_H
diff --git a/src/quicktemplates2/qquickstackview.cpp b/src/quicktemplates2/qquickstackview.cpp
index a7853df7..a9922704 100644
--- a/src/quicktemplates2/qquickstackview.cpp
+++ b/src/quicktemplates2/qquickstackview.cpp
@@ -36,6 +36,8 @@
#include "qquickstackview_p.h"
#include "qquickstackview_p_p.h"
+#include "qquickstackelement_p_p.h"
+#include "qquickstacktransition_p_p.h"
#include <QtQml/qjsvalue.h>
#include <QtQml/qqmlengine.h>
@@ -109,7 +111,7 @@ QT_BEGIN_NAMESPACE
Using StackView in an application is as simple as adding it as a child to
a Window. The stack is usually anchored to the edges of the window, except
at the top or bottom where it might be anchored to a status bar, or some
- other similar UI component. The stack can then be used by invoking its
+ other similar UI component. The stack can then be used by invoking its
navigation methods. The first item to show in the StackView is the one
that was assigned to \l initialItem, or the topmost item if \l initialItem
is not set.
@@ -295,8 +297,8 @@ QT_BEGIN_NAMESPACE
\sa {Customizing StackView}, {Navigation Controls}, {Container Controls}
*/
-QQuickStackView::QQuickStackView(QQuickItem *parent) :
- QQuickControl(*(new QQuickStackViewPrivate), parent)
+QQuickStackView::QQuickStackView(QQuickItem *parent)
+ : QQuickControl(*(new QQuickStackViewPrivate), parent)
{
setFlag(ItemIsFocusScope);
}
@@ -308,13 +310,14 @@ QQuickStackView::~QQuickStackView()
d->transitioner->setChangeListener(nullptr);
delete d->transitioner;
}
- qDeleteAll(d->removals);
+ qDeleteAll(d->removing);
+ qDeleteAll(d->removed);
qDeleteAll(d->elements);
}
-QQuickStackAttached *QQuickStackView::qmlAttachedProperties(QObject *object)
+QQuickStackViewAttached *QQuickStackView::qmlAttachedProperties(QObject *object)
{
- return new QQuickStackAttached(object);
+ return new QQuickStackViewAttached(object);
}
/*!
@@ -472,7 +475,7 @@ void QQuickStackView::push(QQmlV4Function *args)
{
Q_D(QQuickStackView);
if (args->length() <= 0) {
- qmlInfo(this) << "push: missing arguments";
+ qmlWarning(this) << "push: missing arguments";
args->setReturnValue(QV4::Encode::null());
return;
}
@@ -496,7 +499,7 @@ void QQuickStackView::push(QQmlV4Function *args)
}
if (elements.isEmpty()) {
- qmlInfo(this) << "push: nothing to push";
+ qmlWarning(this) << "push: nothing to push";
args->setReturnValue(QV4::Encode::null());
return;
}
@@ -511,7 +514,7 @@ void QQuickStackView::push(QQmlV4Function *args)
d->startTransition(QQuickStackTransition::pushEnter(operation, enter, this),
QQuickStackTransition::pushExit(operation, exit, this),
operation == Immediate);
- d->setCurrentItem(enter->item);
+ d->setCurrentItem(enter);
}
if (d->currentItem) {
@@ -557,7 +560,7 @@ void QQuickStackView::pop(QQmlV4Function *args)
int argc = args->length();
if (d->elements.count() <= 1 || argc > 2) {
if (argc > 2)
- qmlInfo(this) << "pop: too many arguments";
+ qmlWarning(this) << "pop: too many arguments";
args->setReturnValue(QV4::Encode::null());
return;
}
@@ -577,7 +580,7 @@ void QQuickStackView::pop(QQmlV4Function *args)
enter = d->findElement(item);
if (!enter) {
if (item != d->currentItem)
- qmlInfo(this) << "pop: unknown argument: " << value->toQString(); // TODO: safe?
+ qmlWarning(this) << "pop: unknown argument: " << value->toQString(); // TODO: safe?
args->setReturnValue(QV4::Encode::null());
d->elements.push(exit); // restore
return;
@@ -597,13 +600,14 @@ void QQuickStackView::pop(QQmlV4Function *args)
if (d->popElements(enter)) {
if (exit) {
exit->removal = true;
+ d->removing.insert(exit);
previousItem = exit->item;
}
emit depthChanged();
d->startTransition(QQuickStackTransition::popExit(operation, exit, this),
QQuickStackTransition::popEnter(operation, enter, this),
operation == Immediate);
- d->setCurrentItem(enter->item);
+ d->setCurrentItem(enter);
}
if (previousItem) {
@@ -705,7 +709,7 @@ void QQuickStackView::replace(QQmlV4Function *args)
{
Q_D(QQuickStackView);
if (args->length() <= 0) {
- qmlInfo(this) << "replace: missing arguments";
+ qmlWarning(this) << "replace: missing arguments";
args->setReturnValue(QV4::Encode::null());
return;
}
@@ -727,7 +731,7 @@ void QQuickStackView::replace(QQmlV4Function *args)
QList<QQuickStackElement *> elements = d->parseElements(args, target ? 1 : 0);
if (elements.isEmpty()) {
- qmlInfo(this) << "replace: nothing to push";
+ qmlWarning(this) << "replace: nothing to push";
args->setReturnValue(QV4::Encode::null());
return;
}
@@ -740,13 +744,15 @@ void QQuickStackView::replace(QQmlV4Function *args)
if (exit != target ? d->replaceElements(target, elements) : d->pushElements(elements)) {
if (depth != d->elements.count())
emit depthChanged();
- if (exit)
+ if (exit) {
exit->removal = true;
+ d->removing.insert(exit);
+ }
QQuickStackElement *enter = d->elements.top();
d->startTransition(QQuickStackTransition::replaceExit(operation, exit, this),
QQuickStackTransition::replaceEnter(operation, enter, this),
operation == Immediate);
- d->setCurrentItem(enter->item);
+ d->setCurrentItem(enter);
}
if (d->currentItem) {
@@ -969,7 +975,7 @@ void QQuickStackView::componentComplete()
element = QQuickStackElement::fromString(d->initialItem.toString(), this);
if (d->pushElement(element)) {
emit depthChanged();
- d->setCurrentItem(element->item);
+ d->setCurrentItem(element);
element->setStatus(QQuickStackView::Active);
}
}
@@ -999,20 +1005,22 @@ bool QQuickStackView::childMouseEventFilter(QQuickItem *item, QEvent *event)
// breaking its state (QTBUG-50305).
if (event->type() == QEvent::MouseButtonPress)
return true;
+ if (event->type() == QEvent::UngrabMouse)
+ return false;
QQuickWindow *window = item->window();
return window && !window->mouseGrabberItem();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickStackView::accessibleRole() const
{
return QAccessible::LayeredPane;
}
#endif
-void QQuickStackAttachedPrivate::itemParentChanged(QQuickItem *item, QQuickItem *parent)
+void QQuickStackViewAttachedPrivate::itemParentChanged(QQuickItem *item, QQuickItem *parent)
{
- Q_Q(QQuickStackAttached);
+ Q_Q(QQuickStackViewAttached);
int oldIndex = element ? element->index : -1;
QQuickStackView *oldView = element ? element->view : nullptr;
QQuickStackView::Status oldStatus = element ? element->status : QQuickStackView::Inactive;
@@ -1031,22 +1039,23 @@ void QQuickStackAttachedPrivate::itemParentChanged(QQuickItem *item, QQuickItem
emit q->statusChanged();
}
-QQuickStackAttached::QQuickStackAttached(QObject *parent) :
- QObject(*(new QQuickStackAttachedPrivate), parent)
+QQuickStackViewAttached::QQuickStackViewAttached(QObject *parent)
+ : QObject(*(new QQuickStackViewAttachedPrivate), parent)
{
- Q_D(QQuickStackAttached);
+ Q_D(QQuickStackViewAttached);
QQuickItem *item = qobject_cast<QQuickItem *>(parent);
if (item) {
+ connect(item, &QQuickItem::visibleChanged, this, &QQuickStackViewAttached::visibleChanged);
QQuickItemPrivate::get(item)->addItemChangeListener(d, QQuickItemPrivate::Parent);
d->itemParentChanged(item, item->parentItem());
} else if (parent) {
- qmlInfo(parent) << "StackView must be attached to an Item";
+ qmlWarning(parent) << "StackView must be attached to an Item";
}
}
-QQuickStackAttached::~QQuickStackAttached()
+QQuickStackViewAttached::~QQuickStackViewAttached()
{
- Q_D(QQuickStackAttached);
+ Q_D(QQuickStackViewAttached);
QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
if (parentItem)
QQuickItemPrivate::get(parentItem)->removeItemChangeListener(d, QQuickItemPrivate::Parent);
@@ -1059,9 +1068,9 @@ QQuickStackAttached::~QQuickStackAttached()
This attached property holds the stack index of the item it's
attached to, or \c -1 if the item is not in a stack.
*/
-int QQuickStackAttached::index() const
+int QQuickStackViewAttached::index() const
{
- Q_D(const QQuickStackAttached);
+ Q_D(const QQuickStackViewAttached);
return d->element ? d->element->index : -1;
}
@@ -1072,9 +1081,9 @@ int QQuickStackAttached::index() const
This attached property holds the stack view of the item it's
attached to, or \c null if the item is not in a stack.
*/
-QQuickStackView *QQuickStackAttached::view() const
+QQuickStackView *QQuickStackViewAttached::view() const
{
- Q_D(const QQuickStackAttached);
+ Q_D(const QQuickStackViewAttached);
return d->element ? d->element->view : nullptr;
}
@@ -1091,13 +1100,61 @@ QQuickStackView *QQuickStackAttached::view() const
\value StackView.Activating The item is being activated (becoming the current item).
\value StackView.Active The item is active, that is, the current item.
*/
-QQuickStackView::Status QQuickStackAttached::status() const
+QQuickStackView::Status QQuickStackViewAttached::status() const
{
- Q_D(const QQuickStackAttached);
+ Q_D(const QQuickStackViewAttached);
return d->element ? d->element->status : QQuickStackView::Inactive;
}
/*!
+ \since QtQuick.Controls 2.2
+ \qmlattachedproperty bool QtQuick.Controls::StackView::visible
+
+ This attached property holds the visibility of the item it's attached to.
+ The value follows the value of \l Item::visible.
+
+ By default, StackView shows incoming items when the enter transition begins,
+ and hides outgoing items when the exit transition ends. Setting this property
+ explicitly allows the default behavior to be overridden, making it possible
+ to keep items that are below the top-most item visible.
+
+ \note The default transitions of most styles slide outgoing items outside the
+ view, and may also animate their opacity. In order to keep a full stack
+ of items visible, consider customizing the \l transitions so that the
+ items underneath can be seen.
+
+ \image qtquickcontrols2-stackview-visible.png
+
+ \snippet qtquickcontrols2-stackview-visible.qml 1
+*/
+bool QQuickStackViewAttached::isVisible() const
+{
+ const QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
+ return parentItem && parentItem->isVisible();
+}
+
+void QQuickStackViewAttached::setVisible(bool visible)
+{
+ Q_D(QQuickStackViewAttached);
+ d->explicitVisible = true;
+ QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
+ if (parentItem)
+ parentItem->setVisible(visible);
+}
+
+void QQuickStackViewAttached::resetVisible()
+{
+ Q_D(QQuickStackViewAttached);
+ d->explicitVisible = false;
+ if (!d->element || !d->element->view)
+ return;
+
+ QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent());
+ if (parentItem)
+ parentItem->setVisible(parentItem == d->element->view->currentItem());
+}
+
+/*!
\qmlattachedsignal QtQuick.Controls::StackView::activated()
\since QtQuick.Controls 2.1
diff --git a/src/quicktemplates2/qquickstackview_p.cpp b/src/quicktemplates2/qquickstackview_p.cpp
index 1eaaa9a4..89b3c6e3 100644
--- a/src/quicktemplates2/qquickstackview_p.cpp
+++ b/src/quicktemplates2/qquickstackview_p.cpp
@@ -35,276 +35,34 @@
****************************************************************************/
#include "qquickstackview_p_p.h"
+#include "qquickstackelement_p_p.h"
+#include "qquickstacktransition_p_p.h"
-#include <QtQml/qqmlinfo.h>
#include <QtQml/qqmllist.h>
-#include <QtQml/qqmlengine.h>
-#include <QtQml/qqmlcomponent.h>
-#include <QtQml/qqmlincubator.h>
+#include <QtQml/private/qv4qmlcontext_p.h>
#include <QtQml/private/qv4qobjectwrapper_p.h>
-#include <QtQml/private/qqmlcomponent_p.h>
-#include <QtQml/private/qqmlengine_p.h>
#include <QtQuick/private/qquickanimation_p.h>
#include <QtQuick/private/qquicktransition_p.h>
-#include <QtQuick/private/qquickitemviewtransition_p.h>
QT_BEGIN_NAMESPACE
-static QQuickStackAttached *attachedStackObject(QQuickStackElement *element)
+QQuickStackViewPrivate::QQuickStackViewPrivate()
+ : busy(false),
+ currentItem(nullptr),
+ transitioner(nullptr)
{
- QQuickStackAttached *attached = qobject_cast<QQuickStackAttached *>(qmlAttachedPropertiesObject<QQuickStackView>(element->item, false));
- if (attached)
- QQuickStackAttachedPrivate::get(attached)->element = element;
- return attached;
}
-class QQuickStackIncubator : public QQmlIncubator
-{
-public:
- QQuickStackIncubator(QQuickStackElement *element) : QQmlIncubator(Synchronous), element(element) { }
-
-protected:
- void setInitialState(QObject *object) override { element->incubate(object); }
-
-private:
- QQuickStackElement *element;
-};
-
-QQuickStackElement::QQuickStackElement() : QQuickItemViewTransitionableItem(nullptr),
- index(-1), init(false), removal(false), ownItem(false), ownComponent(false), widthValid(false), heightValid(false),
- context(nullptr), component(nullptr), view(nullptr),
- status(QQuickStackView::Inactive)
-{
-}
-
-QQuickStackElement::~QQuickStackElement()
-{
- if (item)
- QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Destroyed);
-
- if (ownComponent)
- delete component;
-
- QQuickStackAttached *attached = attachedStackObject(this);
- if (item) {
- if (ownItem) {
- item->setParentItem(nullptr);
- item->deleteLater();
- item = nullptr;
- } else {
- item->setVisible(false);
- if (!widthValid)
- item->resetWidth();
- if (!heightValid)
- item->resetHeight();
- if (item->parentItem() != originalParent) {
- item->setParentItem(originalParent);
- } else {
- if (attached)
- QQuickStackAttachedPrivate::get(attached)->itemParentChanged(item, nullptr);
- }
- }
- }
-
- if (attached)
- emit attached->removed();
-
- delete context;
-}
-
-QQuickStackElement *QQuickStackElement::fromString(const QString &str, QQuickStackView *view)
-{
- QQuickStackElement *element = new QQuickStackElement;
- element->component = new QQmlComponent(qmlEngine(view), QUrl(str), view);
- element->ownComponent = true;
- return element;
-}
-
-QQuickStackElement *QQuickStackElement::fromObject(QObject *object, QQuickStackView *view)
-{
- Q_UNUSED(view);
- QQuickStackElement *element = new QQuickStackElement;
- element->component = qobject_cast<QQmlComponent *>(object);
- element->item = qobject_cast<QQuickItem *>(object);
- if (element->item)
- element->originalParent = element->item->parentItem();
- return element;
-}
-
-bool QQuickStackElement::load(QQuickStackView *parent)
-{
- setView(parent);
- if (!item) {
- ownItem = true;
-
- if (component->isLoading()) {
- QObject::connect(component, &QQmlComponent::statusChanged, [this](QQmlComponent::Status status) {
- if (status == QQmlComponent::Ready)
- load(view);
- else if (status == QQmlComponent::Error)
- qWarning() << qPrintable(component->errorString().trimmed());
- });
- return true;
- }
-
- QQmlContext *creationContext = component->creationContext();
- if (!creationContext)
- creationContext = qmlContext(parent);
- context = new QQmlContext(creationContext);
- context->setContextObject(parent);
-
- QQuickStackIncubator incubator(this);
- component->create(incubator, context);
- if (component->isError())
- qWarning() << qPrintable(component->errorString().trimmed());
- } else {
- initialize();
- }
- return item;
-}
-
-void QQuickStackElement::incubate(QObject *object)
-{
- item = qmlobject_cast<QQuickItem *>(object);
- if (item) {
- QQmlEngine::setObjectOwnership(item, QQmlEngine::CppOwnership);
- item->setParent(view);
- initialize();
- }
-}
-
-void QQuickStackElement::initialize()
-{
- if (!item || init)
- return;
-
- QQuickItemPrivate *p = QQuickItemPrivate::get(item);
- if (!(widthValid = p->widthValid))
- item->setWidth(view->width());
- if (!(heightValid = p->heightValid))
- item->setHeight(view->height());
- item->setParentItem(view);
- p->addItemChangeListener(this, QQuickItemPrivate::Destroyed);
-
- if (!properties.isUndefined()) {
- QQmlEngine *engine = qmlEngine(view);
- Q_ASSERT(engine);
- QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine);
- Q_ASSERT(v4);
- QV4::Scope scope(v4);
- QV4::ScopedValue ipv(scope, properties.value());
- QV4::Scoped<QV4::QmlContext> qmlContext(scope, qmlCallingContext.value());
- QV4::ScopedValue qmlObject(scope, QV4::QObjectWrapper::wrap(v4, item));
- QQmlComponentPrivate::setInitialProperties(v4, qmlContext, qmlObject, ipv);
- properties.clear();
- }
-
- init = true;
-}
-
-void QQuickStackElement::setIndex(int value)
-{
- if (index == value)
- return;
-
- index = value;
- QQuickStackAttached *attached = attachedStackObject(this);
- if (attached)
- emit attached->indexChanged();
-}
-
-void QQuickStackElement::setView(QQuickStackView *value)
-{
- if (view == value)
- return;
-
- view = value;
- QQuickStackAttached *attached = attachedStackObject(this);
- if (attached)
- emit attached->viewChanged();
-}
-
-void QQuickStackElement::setStatus(QQuickStackView::Status value)
-{
- if (status == value)
- return;
-
- status = value;
- QQuickStackAttached *attached = attachedStackObject(this);
- if (!attached)
- return;
-
- switch (value) {
- case QQuickStackView::Inactive:
- emit attached->deactivated();
- break;
- case QQuickStackView::Deactivating:
- emit attached->deactivating();
- break;
- case QQuickStackView::Activating:
- emit attached->activating();
- break;
- case QQuickStackView::Active:
- emit attached->activated();
- break;
- default:
- Q_UNREACHABLE();
- break;
- }
-
- emit attached->statusChanged();
-}
-
-void QQuickStackElement::transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget)
-{
- if (transitioner)
- transitioner->transitionNextReposition(this, type, asTarget);
-}
-
-bool QQuickStackElement::prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds)
-{
- if (transitioner) {
- if (item) {
- QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors;
- // TODO: expose QQuickAnchorLine so we can test for other conflicting anchors
- if (anchors && (anchors->fill() || anchors->centerIn()))
- qmlInfo(item) << "StackView has detected conflicting anchors. Transitions may not execute properly.";
- }
-
- // TODO: add force argument to QQuickItemViewTransitionableItem::prepareTransition()?
- nextTransitionToSet = true;
- nextTransitionFromSet = true;
- nextTransitionFrom += QPointF(1, 1);
- return QQuickItemViewTransitionableItem::prepareTransition(transitioner, index, viewBounds);
- }
- return false;
-}
-
-void QQuickStackElement::startTransition(QQuickItemViewTransitioner *transitioner, QQuickStackView::Status status)
-{
- setStatus(status);
- if (transitioner)
- QQuickItemViewTransitionableItem::startTransition(transitioner, index);
-}
-
-void QQuickStackElement::itemDestroyed(QQuickItem *)
-{
- item = nullptr;
-}
-
-QQuickStackViewPrivate::QQuickStackViewPrivate() : busy(false), currentItem(nullptr), transitioner(nullptr)
-{
-}
-
-void QQuickStackViewPrivate::setCurrentItem(QQuickItem *item)
+void QQuickStackViewPrivate::setCurrentItem(QQuickStackElement *element)
{
Q_Q(QQuickStackView);
+ QQuickItem *item = element ? element->item : nullptr;
if (currentItem == item)
return;
currentItem = item;
- if (item)
- item->setVisible(true);
+ if (element)
+ element->setVisible(true);
emit q->currentItemChanged();
}
@@ -450,13 +208,13 @@ void QQuickStackViewPrivate::startTransition(const QQuickStackTransition &first,
if (first.element) {
if (immediate || !first.element->item || !first.element->prepareTransition(transitioner, first.viewBounds))
- completeTransition(first.element, transitioner->removeTransition, first.status);
+ completeTransition(first.element, first.transition, first.status);
else
first.element->startTransition(transitioner, first.status);
}
if (second.element) {
if (immediate || !second.element->item || !second.element->prepareTransition(transitioner, second.viewBounds))
- completeTransition(second.element, transitioner->removeDisplacedTransition, second.status);
+ completeTransition(second.element, second.transition, second.status);
else
second.element->startTransition(transitioner, second.status);
}
@@ -489,17 +247,18 @@ void QQuickStackViewPrivate::viewItemTransitionFinished(QQuickItemViewTransition
element->setStatus(QQuickStackView::Active);
} else if (element->status == QQuickStackView::Deactivating) {
element->setStatus(QQuickStackView::Inactive);
- if (element->item)
- element->item->setVisible(false);
+ element->setVisible(false);
if (element->removal || element->isPendingRemoval())
- removals += element;
+ removed += element;
}
if (transitioner->runningJobs.isEmpty()) {
- qDeleteAll(removals);
- removals.clear();
+ qDeleteAll(removed);
+ removed.clear();
setBusy(false);
}
+
+ removing.remove(element);
}
void QQuickStackViewPrivate::setBusy(bool b)
@@ -513,119 +272,4 @@ void QQuickStackViewPrivate::setBusy(bool b)
emit q->busyChanged();
}
-static QQuickStackTransition exitTransition(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
-{
- QQuickStackTransition st;
- st.status = QQuickStackView::Deactivating;
- st.transition = nullptr;
- st.element = element;
-
- const QQuickItemViewTransitioner *transitioner = QQuickStackViewPrivate::get(view)->transitioner;
-
- switch (operation) {
- case QQuickStackView::PushTransition:
- st.target = false;
- st.type = QQuickItemViewTransitioner::AddTransition;
- st.viewBounds = QRectF();
- if (transitioner)
- st.transition = transitioner->addDisplacedTransition;
- break;
- case QQuickStackView::ReplaceTransition:
- st.target = false;
- st.type = QQuickItemViewTransitioner::MoveTransition;
- st.viewBounds = QRectF();
- if (transitioner)
- st.transition = transitioner->moveDisplacedTransition;
- break;
- case QQuickStackView::PopTransition:
- st.target = true;
- st.type = QQuickItemViewTransitioner::RemoveTransition;
- st.viewBounds = view->boundingRect();
- if (transitioner)
- st.transition = transitioner->removeTransition;
- break;
- default:
- Q_UNREACHABLE();
- break;
- }
-
- return st;
-}
-
-static QQuickStackTransition enterTransition(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
-{
- QQuickStackTransition st;
- st.status = QQuickStackView::Activating;
- st.transition = nullptr;
- st.element = element;
-
- const QQuickItemViewTransitioner *transitioner = QQuickStackViewPrivate::get(view)->transitioner;
-
- switch (operation) {
- case QQuickStackView::PushTransition:
- st.target = true;
- st.type = QQuickItemViewTransitioner::AddTransition;
- st.viewBounds = view->boundingRect();
- if (transitioner)
- st.transition = transitioner->addTransition;
- break;
- case QQuickStackView::ReplaceTransition:
- st.target = true;
- st.type = QQuickItemViewTransitioner::MoveTransition;
- st.viewBounds = view->boundingRect();
- if (transitioner)
- st.transition = transitioner->moveTransition;
- break;
- case QQuickStackView::PopTransition:
- st.target = false;
- st.type = QQuickItemViewTransitioner::RemoveTransition;
- st.viewBounds = QRectF();
- if (transitioner)
- st.transition = transitioner->removeDisplacedTransition;
- break;
- default:
- Q_UNREACHABLE();
- break;
- }
-
- return st;
-}
-
-static QQuickStackView::Operation operationTransition(QQuickStackView::Operation operation, QQuickStackView::Operation transition)
-{
- if (operation == QQuickStackView::Immediate || operation == QQuickStackView::Transition)
- return transition;
- return operation;
-}
-
-QQuickStackTransition QQuickStackTransition::popExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
-{
- return exitTransition(operationTransition(operation, QQuickStackView::PopTransition), element, view);
-}
-
-QQuickStackTransition QQuickStackTransition::popEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
-{
- return enterTransition(operationTransition(operation, QQuickStackView::PopTransition), element, view);
-}
-
-QQuickStackTransition QQuickStackTransition::pushExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
-{
- return exitTransition(operationTransition(operation, QQuickStackView::PushTransition), element, view);
-}
-
-QQuickStackTransition QQuickStackTransition::pushEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
-{
- return enterTransition(operationTransition(operation, QQuickStackView::PushTransition), element, view);
-}
-
-QQuickStackTransition QQuickStackTransition::replaceExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
-{
- return exitTransition(operationTransition(operation, QQuickStackView::ReplaceTransition), element, view);
-}
-
-QQuickStackTransition QQuickStackTransition::replaceEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view)
-{
- return enterTransition(operationTransition(operation, QQuickStackView::ReplaceTransition), element, view);
-}
-
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickstackview_p.h b/src/quicktemplates2/qquickstackview_p.h
index d305453c..b74a162d 100644
--- a/src/quicktemplates2/qquickstackview_p.h
+++ b/src/quicktemplates2/qquickstackview_p.h
@@ -55,8 +55,9 @@ QT_BEGIN_NAMESPACE
class QQmlV4Function;
class QQuickTransition;
class QQuickStackElement;
-class QQuickStackAttached;
class QQuickStackViewPrivate;
+class QQuickStackViewAttached;
+class QQuickStackViewAttachedPrivate;
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickStackView : public QQuickControl
{
@@ -76,7 +77,7 @@ public:
explicit QQuickStackView(QQuickItem *parent = nullptr);
~QQuickStackView();
- static QQuickStackAttached *qmlAttachedProperties(QObject *object);
+ static QQuickStackViewAttached *qmlAttachedProperties(QObject *object);
bool isBusy() const;
int depth() const;
@@ -152,7 +153,7 @@ protected:
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
bool childMouseEventFilter(QQuickItem *, QEvent *) override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
@@ -161,27 +162,32 @@ private:
Q_DECLARE_PRIVATE(QQuickStackView)
};
-class QQuickStackAttachedPrivate;
-
-class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickStackAttached : public QObject
+class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickStackViewAttached : public QObject
{
Q_OBJECT
Q_PROPERTY(int index READ index NOTIFY indexChanged FINAL)
Q_PROPERTY(QQuickStackView *view READ view NOTIFY viewChanged FINAL)
Q_PROPERTY(QQuickStackView::Status status READ status NOTIFY statusChanged FINAL)
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible RESET resetVisible NOTIFY visibleChanged FINAL) // REVISION 2
public:
- explicit QQuickStackAttached(QObject *parent = nullptr);
- ~QQuickStackAttached();
+ explicit QQuickStackViewAttached(QObject *parent = nullptr);
+ ~QQuickStackViewAttached();
int index() const;
QQuickStackView *view() const;
QQuickStackView::Status status() const;
+ bool isVisible() const;
+ void setVisible(bool visible);
+ void resetVisible();
+
Q_SIGNALS:
void indexChanged();
void viewChanged();
void statusChanged();
+ /*Q_REVISION(2)*/ void visibleChanged();
+
/*Q_REVISION(1)*/ void activated();
/*Q_REVISION(1)*/ void activating();
/*Q_REVISION(1)*/ void deactivated();
@@ -189,8 +195,8 @@ Q_SIGNALS:
/*Q_REVISION(1)*/ void removed();
private:
- Q_DISABLE_COPY(QQuickStackAttached)
- Q_DECLARE_PRIVATE(QQuickStackAttached)
+ Q_DISABLE_COPY(QQuickStackViewAttached)
+ Q_DECLARE_PRIVATE(QQuickStackViewAttached)
};
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickstackview_p_p.h b/src/quicktemplates2/qquickstackview_p_p.h
index 8a6b594d..ca610153 100644
--- a/src/quicktemplates2/qquickstackview_p_p.h
+++ b/src/quicktemplates2/qquickstackview_p_p.h
@@ -52,54 +52,14 @@
#include <QtQuickTemplates2/private/qquickcontrol_p_p.h>
#include <QtQuick/private/qquickitemviewtransition_p.h>
#include <QtQuick/private/qquickitemchangelistener_p.h>
-#include <QtQml/private/qv4persistent_p.h>
+#include <QtQml/private/qv4value_p.h>
+#include <QtCore/qset.h>
QT_BEGIN_NAMESPACE
-class QQmlContext;
-class QQmlComponent;
+class QQuickStackElement;
struct QQuickStackTransition;
-class QQuickStackElement : public QQuickItemViewTransitionableItem, public QQuickItemChangeListener
-{
- QQuickStackElement();
-
-public:
- ~QQuickStackElement();
-
- static QQuickStackElement *fromString(const QString &str, QQuickStackView *view);
- static QQuickStackElement *fromObject(QObject *object, QQuickStackView *view);
-
- bool load(QQuickStackView *parent);
- void incubate(QObject *object);
- void initialize();
-
- void setIndex(int index);
- void setView(QQuickStackView *view);
- void setStatus(QQuickStackView::Status status);
-
- void transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget);
- bool prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds);
- void startTransition(QQuickItemViewTransitioner *transitioner, QQuickStackView::Status status);
-
- void itemDestroyed(QQuickItem *item) override;
-
- int index;
- bool init;
- bool removal;
- bool ownItem;
- bool ownComponent;
- bool widthValid;
- bool heightValid;
- QQmlContext *context;
- QQmlComponent *component;
- QQuickStackView *view;
- QPointer<QQuickItem> originalParent;
- QQuickStackView::Status status;
- QV4::PersistentValue properties;
- QV4::PersistentValue qmlCallingContext;
-};
-
class QQuickStackViewPrivate : public QQuickControlPrivate, public QQuickItemViewTransitionChangeListener
{
Q_DECLARE_PUBLIC(QQuickStackView)
@@ -112,7 +72,7 @@ public:
return view->d_func();
}
- void setCurrentItem(QQuickItem *item);
+ void setCurrentItem(QQuickStackElement *element);
QList<QQuickStackElement *> parseElements(QQmlV4Function *args, int from = 0);
QQuickStackElement *findElement(QQuickItem *item) const;
@@ -133,44 +93,31 @@ public:
bool busy;
QVariant initialItem;
QQuickItem *currentItem;
- QList<QQuickStackElement*> removals;
+ QSet<QQuickStackElement*> removing;
+ QList<QQuickStackElement*> removed;
QStack<QQuickStackElement *> elements;
QQuickItemViewTransitioner *transitioner;
};
-struct QQuickStackTransition
-{
- static QQuickStackTransition popExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
- static QQuickStackTransition popEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
-
- static QQuickStackTransition pushExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
- static QQuickStackTransition pushEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
-
- static QQuickStackTransition replaceExit(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
- static QQuickStackTransition replaceEnter(QQuickStackView::Operation operation, QQuickStackElement *element, QQuickStackView *view);
-
- bool target;
- QQuickStackView::Status status;
- QQuickItemViewTransitioner::TransitionType type;
- QRectF viewBounds;
- QQuickStackElement *element;
- QQuickTransition *transition;
-};
-
-class QQuickStackAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener
+class QQuickStackViewAttachedPrivate : public QObjectPrivate, public QQuickItemChangeListener
{
- Q_DECLARE_PUBLIC(QQuickStackAttached)
+ Q_DECLARE_PUBLIC(QQuickStackViewAttached)
public:
- QQuickStackAttachedPrivate() : element(nullptr) { }
+ QQuickStackViewAttachedPrivate()
+ : explicitVisible(false),
+ element(nullptr)
+ {
+ }
- static QQuickStackAttachedPrivate *get(QQuickStackAttached *attached)
+ static QQuickStackViewAttachedPrivate *get(QQuickStackViewAttached *attached)
{
return attached->d_func();
}
void itemParentChanged(QQuickItem *item, QQuickItem *parent);
+ bool explicitVisible;
QQuickStackElement *element;
};
diff --git a/src/quicktemplates2/qquickswipe_p.h b/src/quicktemplates2/qquickswipe_p.h
index ea2ec3c5..62b0e903 100644
--- a/src/quicktemplates2/qquickswipe_p.h
+++ b/src/quicktemplates2/qquickswipe_p.h
@@ -50,25 +50,28 @@
#include <QtCore/qobject.h>
#include <QtQuickTemplates2/private/qtquicktemplates2global_p.h>
+#include <QtQuickTemplates2/private/qquickswipedelegate_p.h>
QT_BEGIN_NAMESPACE
class QQmlComponent;
class QQuickItem;
-class QQuickSwipeDelegate;
+class QQuickTransition;
class QQuickSwipePrivate;
class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSwipe : public QObject
{
Q_OBJECT
- Q_PROPERTY(qreal position READ position NOTIFY positionChanged FINAL)
+ Q_PROPERTY(qreal position READ position WRITE setPosition NOTIFY positionChanged FINAL)
Q_PROPERTY(bool complete READ isComplete NOTIFY completeChanged FINAL)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged FINAL) // REVISION 2
Q_PROPERTY(QQmlComponent *left READ left WRITE setLeft NOTIFY leftChanged FINAL)
Q_PROPERTY(QQmlComponent *behind READ behind WRITE setBehind NOTIFY behindChanged FINAL)
Q_PROPERTY(QQmlComponent *right READ right WRITE setRight NOTIFY rightChanged FINAL)
Q_PROPERTY(QQuickItem *leftItem READ leftItem NOTIFY leftItemChanged FINAL)
Q_PROPERTY(QQuickItem *behindItem READ behindItem NOTIFY behindItemChanged FINAL)
Q_PROPERTY(QQuickItem *rightItem READ rightItem NOTIFY rightItemChanged FINAL)
+ Q_PROPERTY(QQuickTransition *transition READ transition WRITE setTransition NOTIFY transitionChanged FINAL) // REVISION 2
public:
explicit QQuickSwipe(QQuickSwipeDelegate *control);
@@ -79,6 +82,9 @@ public:
bool isComplete() const;
void setComplete(bool complete);
+ bool isEnabled() const;
+ void setEnabled(bool enabled);
+
QQmlComponent *left() const;
void setLeft(QQmlComponent *left);
@@ -97,18 +103,26 @@ public:
QQuickItem *rightItem() const;
void setRightItem(QQuickItem *item);
+ QQuickTransition *transition() const;
+ void setTransition(QQuickTransition *transition);
+
+ Q_REVISION(2) Q_INVOKABLE void open(QQuickSwipeDelegate::Side side);
Q_REVISION(1) Q_INVOKABLE void close();
Q_SIGNALS:
void positionChanged();
void completeChanged();
+ /*Q_REVISION(2)*/ void enabledChanged();
/*Q_REVISION(1)*/ void completed();
+ /*Q_REVISION(2)*/ void opened();
+ /*Q_REVISION(2)*/ void closed();
void leftChanged();
void behindChanged();
void rightChanged();
void leftItemChanged();
void behindItemChanged();
void rightItemChanged();
+ /*Q_REVISION(2)*/ void transitionChanged();
private:
Q_DISABLE_COPY(QQuickSwipe)
diff --git a/src/quicktemplates2/qquickswipedelegate.cpp b/src/quicktemplates2/qquickswipedelegate.cpp
index ae69937c..7824708a 100644
--- a/src/quicktemplates2/qquickswipedelegate.cpp
+++ b/src/quicktemplates2/qquickswipedelegate.cpp
@@ -44,6 +44,9 @@
#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
@@ -97,7 +100,7 @@ QT_BEGIN_NAMESPACE
\image qtquickcontrols2-swipedelegate-behind.gif
- \sa {Customizing SwipeDelegate}, {Delegate Controls}
+ \sa {Customizing SwipeDelegate}, {Delegate Controls}, {Qt Quick Controls 2 - Swipe to Remove}{Swipe to Remove Example}
*/
namespace {
@@ -113,23 +116,40 @@ namespace {
};
}
+class QQuickSwipeTransitionManager : public QQuickTransitionManager
+{
+public:
+ QQuickSwipeTransitionManager(QQuickSwipe *swipe);
+
+ void transition(QQuickTransition *transition, qreal position);
+
+protected:
+ void finished() override;
+
+private:
+ QQuickSwipe *m_swipe;
+};
+
class QQuickSwipePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QQuickSwipe)
public:
- QQuickSwipePrivate(QQuickSwipeDelegate *control) :
- control(control),
- positionBeforePress(0),
- position(0),
- wasComplete(false),
- complete(false),
- left(nullptr),
- behind(nullptr),
- right(nullptr),
- leftItem(nullptr),
- behindItem(nullptr),
- rightItem(nullptr)
+ QQuickSwipePrivate(QQuickSwipeDelegate *control)
+ : control(control),
+ positionBeforePress(0),
+ position(0),
+ wasComplete(false),
+ complete(false),
+ enabled(true),
+ left(nullptr),
+ behind(nullptr),
+ right(nullptr),
+ leftItem(nullptr),
+ behindItem(nullptr),
+ rightItem(nullptr),
+ transition(nullptr),
+ transitionManager(nullptr)
{
}
@@ -151,6 +171,10 @@ public:
bool hasDelegates() const;
+ bool isTransitioning() const;
+ void beginTransition(qreal position);
+ void finishTransition();
+
QQuickSwipeDelegate *control;
// 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.
@@ -160,6 +184,7 @@ public:
// before the last press event.
bool wasComplete;
bool complete;
+ bool enabled;
QQuickVelocityCalculator velocityCalculator;
QQmlComponent *left;
QQmlComponent *behind;
@@ -167,8 +192,37 @@ public:
QQuickItem *leftItem;
QQuickItem *behindItem;
QQuickItem *rightItem;
+ QQuickTransition *transition;
+ 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();
@@ -285,7 +339,7 @@ void QQuickSwipePrivate::createLeftItem()
Q_Q(QQuickSwipe);
q->setLeftItem(createDelegateItem(left));
if (!leftItem)
- qmlInfo(control) << "Failed to create left item:" << left->errors();
+ qmlWarning(control) << "Failed to create left item:" << left->errors();
}
}
@@ -295,7 +349,7 @@ void QQuickSwipePrivate::createBehindItem()
Q_Q(QQuickSwipe);
q->setBehindItem(createDelegateItem(behind));
if (!behindItem)
- qmlInfo(control) << "Failed to create behind item:" << behind->errors();
+ qmlWarning(control) << "Failed to create behind item:" << behind->errors();
}
}
@@ -305,7 +359,7 @@ void QQuickSwipePrivate::createRightItem()
Q_Q(QQuickSwipe);
q->setRightItem(createDelegateItem(right));
if (!rightItem)
- qmlInfo(control) << "Failed to create right item:" << right->errors();
+ qmlWarning(control) << "Failed to create right item:" << right->errors();
}
}
@@ -343,12 +397,12 @@ void QQuickSwipePrivate::createAndShowRightItem()
void QQuickSwipePrivate::warnAboutMixingDelegates()
{
- qmlInfo(control) << "cannot set both behind and left/right properties";
+ qmlWarning(control) << "cannot set both behind and left/right properties";
}
void QQuickSwipePrivate::warnAboutSettingDelegatesWhileVisible()
{
- qmlInfo(control) << "left/right/behind properties may only be set when swipe.position is 0";
+ qmlWarning(control) << "left/right/behind properties may only be set when swipe.position is 0";
}
bool QQuickSwipePrivate::hasDelegates() const
@@ -356,8 +410,38 @@ bool QQuickSwipePrivate::hasDelegates() const
return left || right || behind;
}
-QQuickSwipe::QQuickSwipe(QQuickSwipeDelegate *control) :
- QObject(*(new QQuickSwipePrivate(control)))
+bool QQuickSwipePrivate::isTransitioning() const
+{
+ return transitionManager && transitionManager->isRunning();
+}
+
+void QQuickSwipePrivate::beginTransition(qreal newPosition)
+{
+ 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);
+ q->setComplete(qFuzzyCompare(qAbs(position), 1.0));
+ if (complete)
+ emit q->opened();
+ else
+ emit q->closed();
+}
+
+QQuickSwipe::QQuickSwipe(QQuickSwipeDelegate *control)
+ : QObject(*(new QQuickSwipePrivate(control)))
{
}
@@ -574,18 +658,69 @@ void QQuickSwipe::setComplete(bool 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), 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);
- setPosition(0);
- setComplete(false);
+ if (qFuzzyIsNull(d->position))
+ return;
+
+ d->beginTransition(0.0);
d->wasComplete = false;
d->positionBeforePress = 0.0;
d->velocityCalculator.reset();
}
-QQuickSwipeDelegatePrivate::QQuickSwipeDelegatePrivate(QQuickSwipeDelegate *control) :
- swipe(control)
+QQuickSwipeDelegatePrivate::QQuickSwipeDelegatePrivate(QQuickSwipeDelegate *control)
+ : swipe(control)
{
}
@@ -633,12 +768,17 @@ bool QQuickSwipeDelegatePrivate::handleMouseMoveEvent(QQuickItem *item, QMouseEv
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.
- QQuickSwipePrivate *swipePrivate = QQuickSwipePrivate::get(&swipe);
if (!swipePrivate->left && !swipePrivate->right && !swipePrivate->behind)
return false;
@@ -710,6 +850,8 @@ bool QQuickSwipeDelegatePrivate::handleMouseMoveEvent(QQuickItem *item, QMouseEv
position = distance > 0 ? normalizedDistance - 1.0 : normalizedDistance + 1.0;
}
+ if (swipePrivate->isTransitioning())
+ swipePrivate->transitionManager->cancel();
swipe.setPosition(position);
}
} else {
@@ -756,17 +898,14 @@ bool QQuickSwipeDelegatePrivate::handleMouseReleaseEvent(QQuickItem *item, QMous
const qreal swipeVelocity = swipePrivate->velocityCalculator.velocity().x();
if (swipePrivate->position > 0.5 ||
(swipePrivate->position > 0.0 && swipeVelocity > exposeVelocityThreshold)) {
- swipe.setPosition(1.0);
- swipe.setComplete(true);
+ swipePrivate->beginTransition(1.0);
swipePrivate->wasComplete = true;
} else if (swipePrivate->position < -0.5 ||
(swipePrivate->position < 0.0 && swipeVelocity < -exposeVelocityThreshold)) {
- swipe.setPosition(-1.0);
- swipe.setComplete(true);
+ swipePrivate->beginTransition(-1.0);
swipePrivate->wasComplete = true;
- } else {
- swipe.setPosition(0.0);
- swipe.setComplete(false);
+ } else if (!swipePrivate->isTransitioning()) {
+ swipePrivate->beginTransition(0.0);
swipePrivate->wasComplete = false;
}
@@ -790,7 +929,7 @@ static void warnIfHorizontallyAnchored(QQuickItem *item, const QString &itemName
QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors;
if (anchors && (anchors->fill() || anchors->centerIn() || anchors->left().item || anchors->right().item)
&& !item->property("_q_QQuickSwipeDelegate_warned").toBool()) {
- qmlInfo(item) << QString::fromLatin1("SwipeDelegate: cannot use horizontal anchors with %1; unable to layout the item.").arg(itemName);
+ qmlWarning(item) << QString::fromLatin1("SwipeDelegate: cannot use horizontal anchors with %1; unable to layout the item.").arg(itemName);
item->setProperty("_q_QQuickSwipeDelegate_warned", true);
}
}
@@ -814,12 +953,33 @@ void QQuickSwipeDelegatePrivate::resizeContent()
}
}
-QQuickSwipeDelegate::QQuickSwipeDelegate(QQuickItem *parent) :
- QQuickItemDelegate(*(new QQuickSwipeDelegatePrivate(this)), parent)
+QQuickSwipeDelegate::QQuickSwipeDelegate(QQuickItem *parent)
+ : QQuickItemDelegate(*(new QQuickSwipeDelegatePrivate(this)), parent)
{
}
/*!
+ \since QtQuick.Controls 2.2
+ \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
\qmlmethod void QtQuick.Controls::SwipeDelegate::swipe.close()
@@ -827,6 +987,47 @@ QQuickSwipeDelegate::QQuickSwipeDelegate(QQuickItem *parent) :
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
+ \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
+ \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
+ \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
*/
@@ -834,12 +1035,14 @@ QQuickSwipeDelegate::QQuickSwipeDelegate(QQuickItem *parent) :
\qmlpropertygroup QtQuick.Controls::SwipeDelegate::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
@@ -859,6 +1062,11 @@ QQuickSwipeDelegate::QQuickSwipeDelegate(QQuickItem *parent) :
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.
@@ -906,17 +1114,16 @@ QQuickSwipeDelegate::QQuickSwipeDelegate(QQuickItem *parent) :
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 completed()
- \li This signal is emitted when \c complete becomes \c true.
+ \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.
- 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.
+ \snippet qtquickcontrols2-swipedelegate-transition.qml 1
- This signal was added in QtQuick.Controls 2.1.
+ This property was added in Qt Quick Controls 2.2.
\endtable
- \sa {Control::}{contentItem}, {Control::}{background}, swipe.close()
+ \sa {Control::}{contentItem}, {Control::}{background}, swipe.open(), swipe.close()
*/
QQuickSwipe *QQuickSwipeDelegate::swipe() const
{
@@ -978,7 +1185,11 @@ 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->pos(), event->timestamp());
}
@@ -1015,7 +1226,7 @@ QFont QQuickSwipeDelegate::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::ListViewFont);
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickSwipeDelegate::accessibleRole() const
{
return QAccessible::ListItem;
@@ -1027,10 +1238,7 @@ class QQuickSwipeDelegateAttachedPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QQuickSwipeDelegateAttached)
public:
- QQuickSwipeDelegateAttachedPrivate() :
- pressed(false)
- {
- }
+ QQuickSwipeDelegateAttachedPrivate() : pressed(false) { }
// True when left/right/behind is non-interactive and is pressed.
bool pressed;
@@ -1056,8 +1264,8 @@ public:
\sa pressed
*/
-QQuickSwipeDelegateAttached::QQuickSwipeDelegateAttached(QObject *object) :
- QObject(*(new QQuickSwipeDelegateAttachedPrivate), object)
+QQuickSwipeDelegateAttached::QQuickSwipeDelegateAttached(QObject *object)
+ : QObject(*(new QQuickSwipeDelegateAttachedPrivate), object)
{
QQuickItem *item = qobject_cast<QQuickItem *>(object);
if (item) {
diff --git a/src/quicktemplates2/qquickswipedelegate_p.h b/src/quicktemplates2/qquickswipedelegate_p.h
index cb3978ad..34d11c0f 100644
--- a/src/quicktemplates2/qquickswipedelegate_p.h
+++ b/src/quicktemplates2/qquickswipedelegate_p.h
@@ -67,6 +67,9 @@ public:
QQuickSwipe *swipe() const;
+ enum Side { Left = 1, Right = -1 };
+ Q_ENUM(Side)
+
static QQuickSwipeDelegateAttached *qmlAttachedProperties(QObject *object);
protected:
@@ -79,7 +82,7 @@ protected:
QFont defaultFont() const override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
@@ -112,5 +115,6 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QQuickSwipeDelegate)
QML_DECLARE_TYPEINFO(QQuickSwipeDelegate, QML_HAS_ATTACHED_PROPERTIES)
+Q_DECLARE_METATYPE(QQuickSwipeDelegate::Side)
#endif // QQUICKSWIPEDELEGATE_P_H
diff --git a/src/quicktemplates2/qquickswipeview.cpp b/src/quicktemplates2/qquickswipeview.cpp
index 79fc221a..cc015bd3 100644
--- a/src/quicktemplates2/qquickswipeview.cpp
+++ b/src/quicktemplates2/qquickswipeview.cpp
@@ -106,7 +106,11 @@ class QQuickSwipeViewPrivate : public QQuickContainerPrivate
Q_DECLARE_PUBLIC(QQuickSwipeView)
public:
- QQuickSwipeViewPrivate() : interactive(true) { }
+ QQuickSwipeViewPrivate()
+ : interactive(true),
+ orientation(Qt::Horizontal)
+ {
+ }
void resizeItem(QQuickItem *item);
void resizeItems();
@@ -114,6 +118,7 @@ public:
static QQuickSwipeViewPrivate *get(QQuickSwipeView *view);
bool interactive;
+ Qt::Orientation orientation;
};
void QQuickSwipeViewPrivate::resizeItems()
@@ -126,10 +131,14 @@ void QQuickSwipeViewPrivate::resizeItems()
QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors;
// TODO: expose QQuickAnchorLine so we can test for other conflicting anchors
if (anchors && (anchors->fill() || anchors->centerIn()) && !item->property("_q_QQuickSwipeView_warned").toBool()) {
- qmlInfo(item) << "SwipeView has detected conflicting anchors. Unable to layout the item.";
+ qmlWarning(item) << "SwipeView has detected conflicting anchors. Unable to layout the item.";
item->setProperty("_q_QQuickSwipeView_warned", true);
}
+ if (orientation == Qt::Horizontal)
+ item->setY(0);
+ else
+ item->setX(0);
item->setSize(QSizeF(contentItem->width(), contentItem->height()));
}
}
@@ -140,8 +149,8 @@ QQuickSwipeViewPrivate *QQuickSwipeViewPrivate::get(QQuickSwipeView *view)
return view->d_func();
}
-QQuickSwipeView::QQuickSwipeView(QQuickItem *parent) :
- QQuickContainer(*(new QQuickSwipeViewPrivate), parent)
+QQuickSwipeView::QQuickSwipeView(QQuickItem *parent)
+ : QQuickContainer(*(new QQuickSwipeViewPrivate), parent)
{
setFlag(ItemIsFocusScope);
setActiveFocusOnTab(true);
@@ -172,6 +181,33 @@ void QQuickSwipeView::setInteractive(bool interactive)
emit interactiveChanged();
}
+/*!
+ \qmlproperty enumeration QtQuick.Controls::SwipeView::orientation
+
+ This property holds the orientation.
+
+ Possible values:
+ \value Qt.Horizontal Horizontal (default)
+ \value Qt.Vertical Vertical
+*/
+Qt::Orientation QQuickSwipeView::orientation() const
+{
+ Q_D(const QQuickSwipeView);
+ return d->orientation;
+}
+
+void QQuickSwipeView::setOrientation(Qt::Orientation orientation)
+{
+ Q_D(QQuickSwipeView);
+ if (d->orientation == orientation)
+ return;
+
+ d->orientation = orientation;
+ if (isComponentComplete())
+ d->resizeItems();
+ emit orientationChanged();
+}
+
QQuickSwipeViewAttached *QQuickSwipeView::qmlAttachedProperties(QObject *object)
{
return new QQuickSwipeViewAttached(object);
@@ -192,7 +228,7 @@ void QQuickSwipeView::itemAdded(int, QQuickItem *item)
item->setSize(QSizeF(d->contentItem->width(), d->contentItem->height()));
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickSwipeView::accessibleRole() const
{
return QAccessible::PageTabList;
@@ -250,11 +286,11 @@ class QQuickSwipeViewAttachedPrivate : public QObjectPrivate, public QQuickItemC
{
Q_DECLARE_PUBLIC(QQuickSwipeViewAttached)
public:
- QQuickSwipeViewAttachedPrivate() :
- item(nullptr),
- swipeView(nullptr),
- index(-1),
- currentIndex(-1)
+ QQuickSwipeViewAttachedPrivate()
+ : item(nullptr),
+ swipeView(nullptr),
+ index(-1),
+ currentIndex(-1)
{
}
@@ -395,8 +431,8 @@ void QQuickSwipeViewAttachedPrivate::itemDestroyed(QQuickItem *item)
QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Parent | QQuickItemPrivate::Destroyed);
}
-QQuickSwipeViewAttached::QQuickSwipeViewAttached(QObject *parent) :
- QObject(*(new QQuickSwipeViewAttachedPrivate), parent)
+QQuickSwipeViewAttached::QQuickSwipeViewAttached(QObject *parent)
+ : QObject(*(new QQuickSwipeViewAttachedPrivate), parent)
{
Q_D(QQuickSwipeViewAttached);
d->item = qobject_cast<QQuickItem *>(parent);
@@ -407,7 +443,7 @@ QQuickSwipeViewAttached::QQuickSwipeViewAttached(QObject *parent) :
QQuickItemPrivate *p = QQuickItemPrivate::get(d->item);
p->addItemChangeListener(d, QQuickItemPrivate::Parent | QQuickItemPrivate::Destroyed);
} else if (parent) {
- qmlInfo(parent) << "SwipeView: attached properties must be accessed from within a child item";
+ qmlWarning(parent) << "SwipeView: attached properties must be accessed from within a child item";
}
}
diff --git a/src/quicktemplates2/qquickswipeview_p.h b/src/quicktemplates2/qquickswipeview_p.h
index 832cde37..e07ed7f0 100644
--- a/src/quicktemplates2/qquickswipeview_p.h
+++ b/src/quicktemplates2/qquickswipeview_p.h
@@ -59,6 +59,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickSwipeView : public QQuickContainer
{
Q_OBJECT
Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged FINAL REVISION 1)
+ Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged FINAL REVISION 2)
public:
explicit QQuickSwipeView(QQuickItem *parent = nullptr);
@@ -66,16 +67,20 @@ public:
bool isInteractive() const;
void setInteractive(bool interactive);
+ Qt::Orientation orientation() const;
+ void setOrientation(Qt::Orientation orientation);
+
static QQuickSwipeViewAttached *qmlAttachedProperties(QObject *object);
Q_SIGNALS:
Q_REVISION(1) void interactiveChanged();
+ Q_REVISION(2) void orientationChanged();
protected:
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
void itemAdded(int index, QQuickItem *item) override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquickswitch.cpp b/src/quicktemplates2/qquickswitch.cpp
index c1a7d34a..ece9802d 100644
--- a/src/quicktemplates2/qquickswitch.cpp
+++ b/src/quicktemplates2/qquickswitch.cpp
@@ -86,6 +86,10 @@ public:
qreal positionAt(const QPointF &point) const;
+ bool canDrag(const QPointF &movePoint) const;
+ void handleMove(const QPointF &point) override;
+ void handleRelease(const QPointF &point) override;
+
qreal position;
};
@@ -100,8 +104,34 @@ qreal QQuickSwitchPrivate::positionAt(const QPointF &point) const
return pos;
}
-QQuickSwitch::QQuickSwitch(QQuickItem *parent) :
- QQuickAbstractButton(*(new QQuickSwitchPrivate), parent)
+bool QQuickSwitchPrivate::canDrag(const QPointF &movePoint) const
+{
+ // don't start dragging the handle unless the initial press was at the indicator,
+ // or the drag has reached the indicator area. this prevents unnatural jumps when
+ // dragging far outside the indicator.
+ const qreal pressPos = positionAt(pressPoint);
+ const qreal movePos = positionAt(movePoint);
+ return (pressPos >= 0.0 && pressPos <= 1.0) || (movePos >= 0.0 && movePos <= 1.0);
+}
+
+void QQuickSwitchPrivate::handleMove(const QPointF &point)
+{
+ Q_Q(QQuickSwitch);
+ QQuickAbstractButtonPrivate::handleMove(point);
+ if (q->keepMouseGrab() || q->keepTouchGrab())
+ q->setPosition(positionAt(point));
+}
+
+void QQuickSwitchPrivate::handleRelease(const QPointF &point)
+{
+ Q_Q(QQuickSwitch);
+ QQuickAbstractButtonPrivate::handleRelease(point);
+ q->setKeepMouseGrab(false);
+ q->setKeepTouchGrab(false);
+}
+
+QQuickSwitch::QQuickSwitch(QQuickItem *parent)
+ : QQuickAbstractButton(*(new QQuickSwitchPrivate), parent)
{
Q_D(QQuickSwitch);
d->keepPressed = true;
@@ -146,35 +176,29 @@ qreal QQuickSwitch::visualPosition() const
return d->position;
}
-void QQuickSwitch::mousePressEvent(QMouseEvent *event)
-{
- QQuickAbstractButton::mousePressEvent(event);
-}
-
void QQuickSwitch::mouseMoveEvent(QMouseEvent *event)
{
Q_D(QQuickSwitch);
- QQuickAbstractButton::mouseMoveEvent(event);
-
- const QPointF movePoint = event->localPos();
if (!keepMouseGrab()) {
- // don't start dragging the handle unless the initial press was at the indicator,
- // or the drag has reached the indicator area. this prevents unnatural jumps when
- // dragging far outside the indicator.
- const qreal pressPos = d->positionAt(d->pressPoint);
- const qreal movePos = d->positionAt(movePoint);
- if ((pressPos >= 0.0 && pressPos <= 1.0) || (movePos >= 0.0 && movePos <= 1.0))
+ const QPointF movePoint = event->localPos();
+ if (d->canDrag(movePoint))
setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(movePoint.x() - d->pressPoint.x(), Qt::XAxis, event));
}
-
- if (keepMouseGrab())
- setPosition(d->positionAt(movePoint));
+ QQuickAbstractButton::mouseMoveEvent(event);
}
-void QQuickSwitch::mouseReleaseEvent(QMouseEvent *event)
+void QQuickSwitch::touchEvent(QTouchEvent *event)
{
- QQuickAbstractButton::mouseReleaseEvent(event);
- setKeepMouseGrab(false);
+ Q_D(QQuickSwitch);
+ if (!keepTouchGrab() && event->type() == QEvent::TouchUpdate) {
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ if (point.id() != d->touchId || point.state() != Qt::TouchPointMoved)
+ continue;
+ if (d->canDrag(point.pos()))
+ setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().x() - d->pressPoint.x(), Qt::XAxis, &point));
+ }
+ }
+ QQuickAbstractButton::touchEvent(event);
}
void QQuickSwitch::mirrorChange()
@@ -186,20 +210,23 @@ void QQuickSwitch::mirrorChange()
void QQuickSwitch::nextCheckState()
{
Q_D(QQuickSwitch);
- if (keepMouseGrab()) {
- setChecked(d->position > 0.5);
+ if (keepMouseGrab() || keepTouchGrab()) {
+ d->toggle(d->position > 0.5);
// the checked state might not change => force a position update to
// avoid that the handle is left somewhere in the middle (QTBUG-57944)
- checkStateSet();
+ setPosition(d->checked ? 1.0 : 0.0);
} else {
QQuickAbstractButton::nextCheckState();
}
}
-void QQuickSwitch::checkStateSet()
+void QQuickSwitch::buttonChange(ButtonChange change)
{
Q_D(QQuickSwitch);
- setPosition(d->checked ? 1.0 : 0.0);
+ if (change == ButtonCheckedChange)
+ setPosition(d->checked ? 1.0 : 0.0);
+ else
+ QQuickAbstractButton::buttonChange(change);
}
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickswitch_p.h b/src/quicktemplates2/qquickswitch_p.h
index 405e15f4..5b93cd32 100644
--- a/src/quicktemplates2/qquickswitch_p.h
+++ b/src/quicktemplates2/qquickswitch_p.h
@@ -73,14 +73,13 @@ Q_SIGNALS:
void visualPositionChanged();
protected:
- void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
- void mouseReleaseEvent(QMouseEvent *event) override;
+ void touchEvent(QTouchEvent *event) override;
void mirrorChange() override;
void nextCheckState() override;
- void checkStateSet() override;
+ void buttonChange(ButtonChange change) override;
private:
Q_DISABLE_COPY(QQuickSwitch)
diff --git a/src/quicktemplates2/qquickswitchdelegate.cpp b/src/quicktemplates2/qquickswitchdelegate.cpp
index d0d14ae5..9bce76db 100644
--- a/src/quicktemplates2/qquickswitchdelegate.cpp
+++ b/src/quicktemplates2/qquickswitchdelegate.cpp
@@ -79,13 +79,14 @@ class QQuickSwitchDelegatePrivate : public QQuickItemDelegatePrivate
Q_DECLARE_PUBLIC(QQuickSwitchDelegate)
public:
- QQuickSwitchDelegatePrivate() :
- position(0)
- {
- }
+ QQuickSwitchDelegatePrivate() : position(0) { }
qreal positionAt(const QPointF &point) const;
+ bool canDrag(const QPointF &movePoint) const;
+ void handleMove(const QPointF &point) override;
+ void handleRelease(const QPointF &point) override;
+
qreal position;
};
@@ -100,8 +101,34 @@ qreal QQuickSwitchDelegatePrivate::positionAt(const QPointF &point) const
return pos;
}
-QQuickSwitchDelegate::QQuickSwitchDelegate(QQuickItem *parent) :
- QQuickItemDelegate(*(new QQuickSwitchDelegatePrivate), parent)
+bool QQuickSwitchDelegatePrivate::canDrag(const QPointF &movePoint) const
+{
+ // don't start dragging the handle unless the initial press was at the indicator,
+ // or the drag has reached the indicator area. this prevents unnatural jumps when
+ // dragging far outside the indicator.
+ const qreal pressPos = positionAt(pressPoint);
+ const qreal movePos = positionAt(movePoint);
+ return (pressPos >= 0.0 && pressPos <= 1.0) || (movePos >= 0.0 && movePos <= 1.0);
+}
+
+void QQuickSwitchDelegatePrivate::handleMove(const QPointF &point)
+{
+ Q_Q(QQuickSwitchDelegate);
+ QQuickItemDelegatePrivate::handleMove(point);
+ if (q->keepMouseGrab() || q->keepTouchGrab())
+ q->setPosition(positionAt(point));
+}
+
+void QQuickSwitchDelegatePrivate::handleRelease(const QPointF &point)
+{
+ Q_Q(QQuickSwitchDelegate);
+ QQuickItemDelegatePrivate::handleRelease(point);
+ q->setKeepMouseGrab(false);
+ q->setKeepTouchGrab(false);
+}
+
+QQuickSwitchDelegate::QQuickSwitchDelegate(QQuickItem *parent)
+ : QQuickItemDelegate(*(new QQuickSwitchDelegatePrivate), parent)
{
Q_D(QQuickSwitchDelegate);
d->keepPressed = true;
@@ -146,35 +173,29 @@ qreal QQuickSwitchDelegate::visualPosition() const
return d->position;
}
-void QQuickSwitchDelegate::mousePressEvent(QMouseEvent *event)
-{
- QQuickItemDelegate::mousePressEvent(event);
-}
-
void QQuickSwitchDelegate::mouseMoveEvent(QMouseEvent *event)
{
Q_D(QQuickSwitchDelegate);
- QQuickItemDelegate::mouseMoveEvent(event);
-
- const QPointF movePoint = event->localPos();
if (!keepMouseGrab()) {
- // don't start dragging the handle unless the initial press was at the indicator,
- // or the drag has reached the indicator area. this prevents unnatural jumps when
- // dragging far outside the indicator.
- const qreal pressPos = d->positionAt(d->pressPoint);
- const qreal movePos = d->positionAt(movePoint);
- if ((pressPos >= 0.0 && pressPos <= 1.0) || (movePos >= 0.0 && movePos <= 1.0))
+ const QPointF movePoint = event->localPos();
+ if (d->canDrag(movePoint))
setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(movePoint.x() - d->pressPoint.x(), Qt::XAxis, event));
}
-
- if (keepMouseGrab())
- setPosition(d->positionAt(movePoint));
+ QQuickItemDelegate::mouseMoveEvent(event);
}
-void QQuickSwitchDelegate::mouseReleaseEvent(QMouseEvent *event)
+void QQuickSwitchDelegate::touchEvent(QTouchEvent *event)
{
- QQuickItemDelegate::mouseReleaseEvent(event);
- setKeepMouseGrab(false);
+ Q_D(QQuickSwitchDelegate);
+ if (!keepTouchGrab() && event->type() == QEvent::TouchUpdate) {
+ for (const QTouchEvent::TouchPoint &point : event->touchPoints()) {
+ if (point.id() != d->touchId || point.state() != Qt::TouchPointMoved)
+ continue;
+ if (d->canDrag(point.pos()))
+ setKeepTouchGrab(QQuickWindowPrivate::dragOverThreshold(point.pos().x() - d->pressPoint.x(), Qt::XAxis, &point));
+ }
+ }
+ QQuickItemDelegate::touchEvent(event);
}
QFont QQuickSwitchDelegate::defaultFont() const
@@ -191,20 +212,23 @@ void QQuickSwitchDelegate::mirrorChange()
void QQuickSwitchDelegate::nextCheckState()
{
Q_D(QQuickSwitchDelegate);
- if (keepMouseGrab()) {
- setChecked(d->position > 0.5);
+ if (keepMouseGrab() || keepTouchGrab()) {
+ d->toggle(d->position > 0.5);
// the checked state might not change => force a position update to
// avoid that the handle is left somewhere in the middle (QTBUG-57944)
- checkStateSet();
+ setPosition(d->checked ? 1.0 : 0.0);
} else {
QQuickItemDelegate::nextCheckState();
}
}
-void QQuickSwitchDelegate::checkStateSet()
+void QQuickSwitchDelegate::buttonChange(ButtonChange change)
{
Q_D(QQuickSwitchDelegate);
- setPosition(d->checked ? 1.0 : 0.0);
+ if (change == ButtonCheckedChange)
+ setPosition(d->checked ? 1.0 : 0.0);
+ else
+ QQuickAbstractButton::buttonChange(change);
}
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquickswitchdelegate_p.h b/src/quicktemplates2/qquickswitchdelegate_p.h
index f32bc695..e3e0804a 100644
--- a/src/quicktemplates2/qquickswitchdelegate_p.h
+++ b/src/quicktemplates2/qquickswitchdelegate_p.h
@@ -73,15 +73,14 @@ Q_SIGNALS:
void visualPositionChanged();
protected:
- void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
- void mouseReleaseEvent(QMouseEvent *event) override;
+ void touchEvent(QTouchEvent *event) override;
QFont defaultFont() const override;
void mirrorChange() override;
void nextCheckState() override;
- void checkStateSet() override;
+ void buttonChange(ButtonChange change) override;
private:
Q_DISABLE_COPY(QQuickSwitchDelegate)
diff --git a/src/quicktemplates2/qquicktabbar.cpp b/src/quicktemplates2/qquicktabbar.cpp
index b32e55d3..7ce8a21e 100644
--- a/src/quicktemplates2/qquicktabbar.cpp
+++ b/src/quicktemplates2/qquicktabbar.cpp
@@ -105,14 +105,26 @@ public:
void updateLayout();
void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override;
+ void itemImplicitWidthChanged(QQuickItem *item) override;
+ void itemImplicitHeightChanged(QQuickItem *item) override;
bool updatingLayout;
+ bool hasContentWidth;
+ bool hasContentHeight;
+ qreal contentWidth;
+ qreal contentHeight;
QQuickTabBar::Position position;
};
-QQuickTabBarPrivate::QQuickTabBarPrivate() : updatingLayout(false), position(QQuickTabBar::Header)
+QQuickTabBarPrivate::QQuickTabBarPrivate()
+ : updatingLayout(false),
+ hasContentWidth(false),
+ hasContentHeight(false),
+ contentWidth(0),
+ contentHeight(0),
+ position(QQuickTabBar::Header)
{
- changeTypes |= Geometry;
+ changeTypes |= Geometry | ImplicitWidth | ImplicitHeight;
}
void QQuickTabBarPrivate::updateCurrentItem()
@@ -134,34 +146,61 @@ void QQuickTabBarPrivate::updateLayout()
{
Q_Q(QQuickTabBar);
const int count = contentModel->count();
- if (count > 0 && contentItem) {
- qreal reservedWidth = 0;
- QVector<QQuickItem *> resizableItems;
- resizableItems.reserve(count);
-
- for (int i = 0; i < count; ++i) {
- QQuickItem *item = q->itemAt(i);
- if (item) {
- QQuickItemPrivate *p = QQuickItemPrivate::get(item);
- if (!p->widthValid)
- resizableItems += item;
- else
- reservedWidth += item->width();
+ if (count <= 0 || !contentItem)
+ return;
+
+ qreal maxHeight = 0;
+ qreal totalWidth = 0;
+ qreal reservedWidth = 0;
+
+ QVector<QQuickItem *> resizableItems;
+ resizableItems.reserve(count);
+
+ for (int i = 0; i < count; ++i) {
+ QQuickItem *item = q->itemAt(i);
+ if (item) {
+ QQuickItemPrivate *p = QQuickItemPrivate::get(item);
+ if (!p->widthValid) {
+ resizableItems += item;
+ totalWidth += item->implicitWidth();
+ } else {
+ reservedWidth += item->width();
+ totalWidth += item->width();
}
+ maxHeight = qMax(maxHeight, item->implicitHeight());
}
+ }
- if (!resizableItems.isEmpty()) {
- const qreal totalSpacing = qMax(0, count - 1) * spacing;
- const qreal itemWidth = (contentItem->width() - reservedWidth - totalSpacing) / resizableItems.count();
+ const qreal totalSpacing = qMax(0, count - 1) * spacing;
+ totalWidth += totalSpacing;
- updatingLayout = true;
- for (QQuickItem *item : qAsConst(resizableItems)) {
- item->setWidth(itemWidth);
- QQuickItemPrivate::get(item)->widthValid = false;
- }
- updatingLayout = false;
+ if (!resizableItems.isEmpty()) {
+ const qreal itemWidth = (contentItem->width() - reservedWidth - totalSpacing) / resizableItems.count();
+
+ updatingLayout = true;
+ for (QQuickItem *item : qAsConst(resizableItems)) {
+ item->setWidth(itemWidth);
+ QQuickItemPrivate::get(item)->widthValid = false;
}
+ updatingLayout = false;
+ }
+
+ bool contentWidthChange = false;
+ if (!hasContentWidth && !qFuzzyCompare(contentWidth, totalWidth)) {
+ contentWidth = totalWidth;
+ contentWidthChange = true;
+ }
+
+ bool contentHeightChange = false;
+ if (!hasContentHeight && !qFuzzyCompare(contentHeight, maxHeight)) {
+ contentHeight = maxHeight;
+ contentHeightChange = true;
}
+
+ if (contentWidthChange)
+ emit q->contentWidthChanged();
+ if (contentHeightChange)
+ emit q->contentHeightChanged();
}
void QQuickTabBarPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &)
@@ -170,8 +209,20 @@ void QQuickTabBarPrivate::itemGeometryChanged(QQuickItem *, QQuickGeometryChange
updateLayout();
}
-QQuickTabBar::QQuickTabBar(QQuickItem *parent) :
- QQuickContainer(*(new QQuickTabBarPrivate), parent)
+void QQuickTabBarPrivate::itemImplicitWidthChanged(QQuickItem *)
+{
+ if (!updatingLayout && !hasContentWidth)
+ updateLayout();
+}
+
+void QQuickTabBarPrivate::itemImplicitHeightChanged(QQuickItem *)
+{
+ if (!updatingLayout && !hasContentHeight)
+ updateLayout();
+}
+
+QQuickTabBar::QQuickTabBar(QQuickItem *parent)
+ : QQuickContainer(*(new QQuickTabBarPrivate), parent)
{
Q_D(QQuickTabBar);
setFlag(ItemIsFocusScope);
@@ -210,6 +261,87 @@ void QQuickTabBar::setPosition(Position position)
emit positionChanged();
}
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty real QtQuick.Controls::TabBar::contentWidth
+
+ This property holds the content width. It is used for calculating the total
+ implicit width of the tab bar.
+
+ Unless explicitly overridden, the content width is automatically calculated
+ based on the total implicit width of the tabs and the \l {Control::}{spacing}
+ of the tab bar.
+
+ \sa contentHeight
+*/
+qreal QQuickTabBar::contentWidth() const
+{
+ Q_D(const QQuickTabBar);
+ return d->contentWidth;
+}
+
+void QQuickTabBar::setContentWidth(qreal width)
+{
+ Q_D(QQuickTabBar);
+ d->hasContentWidth = true;
+ if (qFuzzyCompare(d->contentWidth, width))
+ return;
+
+ d->contentWidth = width;
+ emit contentWidthChanged();
+}
+
+void QQuickTabBar::resetContentWidth()
+{
+ Q_D(QQuickTabBar);
+ if (!d->hasContentWidth)
+ return;
+
+ d->hasContentWidth = false;
+ if (isComponentComplete())
+ d->updateLayout();
+}
+
+/*!
+ \since QtQuick.Controls 2.2
+ \qmlproperty real QtQuick.Controls::TabBar::contentHeight
+
+ This property holds the content height. It is used for calculating the total
+ implicit height of the tab bar.
+
+ Unless explicitly overridden, the content height is automatically calculated
+ based on the maximum implicit height of the tabs.
+
+ \sa contentWidth
+*/
+qreal QQuickTabBar::contentHeight() const
+{
+ Q_D(const QQuickTabBar);
+ return d->contentHeight;
+}
+
+void QQuickTabBar::setContentHeight(qreal height)
+{
+ Q_D(QQuickTabBar);
+ d->hasContentHeight = true;
+ if (qFuzzyCompare(d->contentHeight, height))
+ return;
+
+ d->contentHeight = height;
+ emit contentHeightChanged();
+}
+
+void QQuickTabBar::resetContentHeight()
+{
+ Q_D(QQuickTabBar);
+ if (!d->hasContentHeight)
+ return;
+
+ d->hasContentHeight = false;
+ if (isComponentComplete())
+ d->updateLayout();
+}
+
void QQuickTabBar::updatePolish()
{
Q_D(QQuickTabBar);
@@ -258,7 +390,7 @@ void QQuickTabBar::itemRemoved(int index, QQuickItem *item)
polish();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickTabBar::accessibleRole() const
{
return QAccessible::PageTabList;
diff --git a/src/quicktemplates2/qquicktabbar_p.h b/src/quicktemplates2/qquicktabbar_p.h
index 31491b54..bc228346 100644
--- a/src/quicktemplates2/qquicktabbar_p.h
+++ b/src/quicktemplates2/qquicktabbar_p.h
@@ -58,6 +58,8 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTabBar : public QQuickContainer
{
Q_OBJECT
Q_PROPERTY(Position position READ position WRITE setPosition NOTIFY positionChanged FINAL)
+ Q_PROPERTY(qreal contentWidth READ contentWidth WRITE setContentWidth RESET resetContentWidth NOTIFY contentWidthChanged FINAL REVISION 2)
+ Q_PROPERTY(qreal contentHeight READ contentHeight WRITE setContentHeight RESET resetContentHeight NOTIFY contentHeightChanged FINAL REVISION 2)
public:
explicit QQuickTabBar(QQuickItem *parent = nullptr);
@@ -71,8 +73,18 @@ public:
Position position() const;
void setPosition(Position position);
+ qreal contentWidth() const;
+ void setContentWidth(qreal width);
+ void resetContentWidth();
+
+ qreal contentHeight() const;
+ void setContentHeight(qreal height);
+ void resetContentHeight();
+
Q_SIGNALS:
void positionChanged();
+ void contentWidthChanged();
+ void contentHeightChanged();
protected:
void updatePolish() override;
@@ -82,7 +94,7 @@ protected:
void itemAdded(int index, QQuickItem *item) override;
void itemRemoved(int index, QQuickItem *item) override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquicktabbutton.cpp b/src/quicktemplates2/qquicktabbutton.cpp
index 375897d1..9afe5363 100644
--- a/src/quicktemplates2/qquicktabbutton.cpp
+++ b/src/quicktemplates2/qquicktabbutton.cpp
@@ -63,8 +63,8 @@ QT_BEGIN_NAMESPACE
\sa TabBar, {Customizing TabButton}, {Button Controls}, {Navigation Controls}
*/
-QQuickTabButton::QQuickTabButton(QQuickItem *parent) :
- QQuickAbstractButton(parent)
+QQuickTabButton::QQuickTabButton(QQuickItem *parent)
+ : QQuickAbstractButton(parent)
{
setCheckable(true);
setAutoExclusive(true);
@@ -75,7 +75,7 @@ QFont QQuickTabButton::defaultFont() const
return QQuickControlPrivate::themeFont(QPlatformTheme::TabButtonFont);
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickTabButton::accessibleRole() const
{
return QAccessible::PageTab;
diff --git a/src/quicktemplates2/qquicktabbutton_p.h b/src/quicktemplates2/qquicktabbutton_p.h
index b9f93bb6..49ecee50 100644
--- a/src/quicktemplates2/qquicktabbutton_p.h
+++ b/src/quicktemplates2/qquicktabbutton_p.h
@@ -62,7 +62,7 @@ public:
protected:
QFont defaultFont() const override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
};
diff --git a/src/quicktemplates2/qquicktextarea.cpp b/src/quicktemplates2/qquicktextarea.cpp
index 5d710d4e..21d74dd8 100644
--- a/src/quicktemplates2/qquicktextarea.cpp
+++ b/src/quicktemplates2/qquicktextarea.cpp
@@ -38,15 +38,14 @@
#include "qquicktextarea_p_p.h"
#include "qquickcontrol_p.h"
#include "qquickcontrol_p_p.h"
+#include "qquickscrollview_p.h"
-#include <QtGui/qguiapplication.h>
#include <QtQml/qqmlinfo.h>
#include <QtQuick/private/qquickitem_p.h>
-#include <QtQuick/private/qquicktext_p.h>
#include <QtQuick/private/qquickclipnode_p.h>
#include <QtQuick/private/qquickflickable_p.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <QtQuick/private/qquickaccessibleattached_p.h>
#endif
@@ -82,14 +81,13 @@ QT_BEGIN_NAMESPACE
\section2 Scrollable TextArea
If you want to make a TextArea scrollable, for example, when it covers
- an entire application page, attach it to a \l Flickable and combine with a
- \l ScrollBar or \l ScrollIndicator.
+ an entire application page, it can be placed inside a \l ScrollView.
- \image qtquickcontrols2-textarea-flickable.png
+ \image qtquickcontrols2-textarea-scrollable.png
- \snippet qtquickcontrols2-textarea-flickable.qml 1
+ \snippet qtquickcontrols2-textarea-scrollable.qml 1
- A TextArea that is attached to a \l Flickable does the following:
+ A TextArea that is placed inside a \l ScrollView does the following:
\list
\li Sets the content size automatically
@@ -133,17 +131,24 @@ QT_BEGIN_NAMESPACE
*/
QQuickTextAreaPrivate::QQuickTextAreaPrivate()
- : hovered(false), explicitHoverEnabled(false), background(nullptr),
- focusReason(Qt::OtherFocusReason), accessibleAttached(nullptr), flickable(nullptr)
+ : QQuickTextEditPrivate(),
+#if QT_CONFIG(quicktemplates2_hover)
+ hovered(false),
+ explicitHoverEnabled(false),
+#endif
+ background(nullptr),
+ focusReason(Qt::OtherFocusReason),
+ accessibleAttached(nullptr),
+ flickable(nullptr)
{
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::installActivationObserver(this);
#endif
}
QQuickTextAreaPrivate::~QQuickTextAreaPrivate()
{
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::removeActivationObserver(this);
#endif
}
@@ -170,6 +175,52 @@ void QQuickTextAreaPrivate::resizeBackground()
}
}
+/*!
+ \internal
+
+ Determine which font is implicitly imposed on this control by its ancestors
+ and QGuiApplication::font, resolve this against its own font (attributes from
+ the implicit font are copied over). Then propagate this font to this
+ control's children.
+*/
+void QQuickTextAreaPrivate::resolveFont()
+{
+ Q_Q(QQuickTextArea);
+ inheritFont(QQuickControlPrivate::parentFont(q));
+}
+
+void QQuickTextAreaPrivate::inheritFont(const QFont &f)
+{
+ Q_Q(QQuickTextArea);
+ QFont parentFont = font.resolve(f);
+ parentFont.resolve(font.resolve() | f.resolve());
+
+ const QFont defaultFont = QQuickControlPrivate::themeFont(QPlatformTheme::EditorFont);
+ const QFont resolvedFont = parentFont.resolve(defaultFont);
+
+ const bool changed = resolvedFont != sourceFont;
+ q->QQuickTextEdit::setFont(resolvedFont);
+ if (changed)
+ emit q->fontChanged();
+}
+
+#if QT_CONFIG(quicktemplates2_hover)
+void QQuickTextAreaPrivate::updateHoverEnabled(bool enabled, bool xplicit)
+{
+ Q_Q(QQuickTextArea);
+ if (!xplicit && explicitHoverEnabled)
+ return;
+
+ bool wasEnabled = q->isHoverEnabled();
+ explicitHoverEnabled = xplicit;
+ if (wasEnabled != enabled) {
+ q->setAcceptHoverEvents(enabled);
+ QQuickControlPrivate::updateHoverEnabledRecur(q, enabled);
+ emit q->hoverEnabledChanged();
+ }
+}
+#endif
+
void QQuickTextAreaPrivate::attachFlickable(QQuickFlickable *item)
{
Q_Q(QQuickTextArea);
@@ -305,87 +356,19 @@ void QQuickTextAreaPrivate::implicitHeightChanged()
emit q->implicitHeightChanged3();
}
-QQuickTextArea::QQuickTextArea(QQuickItem *parent) :
- QQuickTextEdit(*(new QQuickTextAreaPrivate), parent)
-{
- Q_D(QQuickTextArea);
- setActiveFocusOnTab(true);
- setAcceptedMouseButtons(Qt::AllButtons);
- d->setImplicitResizeEnabled(false);
- d->pressHandler.control = this;
-#ifndef QT_NO_CURSOR
- setCursor(Qt::IBeamCursor);
-#endif
- QObjectPrivate::connect(this, &QQuickTextEdit::readOnlyChanged,
- d, &QQuickTextAreaPrivate::_q_readOnlyChanged);
-}
-
-QQuickTextArea::~QQuickTextArea()
-{
-}
-
-QQuickTextAreaAttached *QQuickTextArea::qmlAttachedProperties(QObject *object)
-{
- return new QQuickTextAreaAttached(object);
-}
-
-/*!
- \internal
-
- Determine which font is implicitly imposed on this control by its ancestors
- and QGuiApplication::font, resolve this against its own font (attributes from
- the implicit font are copied over). Then propagate this font to this
- control's children.
-*/
-void QQuickTextAreaPrivate::resolveFont()
-{
- Q_Q(QQuickTextArea);
- inheritFont(QQuickControlPrivate::parentFont(q));
-}
-
-void QQuickTextAreaPrivate::inheritFont(const QFont &f)
-{
- Q_Q(QQuickTextArea);
- QFont parentFont = font.resolve(f);
- parentFont.resolve(font.resolve() | f.resolve());
-
- const QFont defaultFont = QQuickControlPrivate::themeFont(QPlatformTheme::EditorFont);
- const QFont resolvedFont = parentFont.resolve(defaultFont);
-
- const bool changed = resolvedFont != sourceFont;
- q->QQuickTextEdit::setFont(resolvedFont);
- if (changed)
- emit q->fontChanged();
-}
-
-void QQuickTextAreaPrivate::updateHoverEnabled(bool enabled, bool xplicit)
-{
- Q_Q(QQuickTextArea);
- if (!xplicit && explicitHoverEnabled)
- return;
-
- bool wasEnabled = q->isHoverEnabled();
- explicitHoverEnabled = xplicit;
- if (wasEnabled != enabled) {
- q->setAcceptHoverEvents(enabled);
- QQuickControlPrivate::updateHoverEnabledRecur(q, enabled);
- emit q->hoverEnabledChanged();
- }
-}
-
-void QQuickTextAreaPrivate::_q_readOnlyChanged(bool isReadOnly)
+void QQuickTextAreaPrivate::readOnlyChanged(bool isReadOnly)
{
Q_UNUSED(isReadOnly);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (accessibleAttached)
accessibleAttached->set_readOnly(isReadOnly);
#endif
-#ifndef QT_NO_CURSOR
+#if QT_CONFIG(cursor)
q_func()->setCursor(isReadOnly ? Qt::ArrowCursor : Qt::IBeamCursor);
#endif
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
void QQuickTextAreaPrivate::accessibilityActiveChanged(bool active)
{
if (accessibleAttached || !active)
@@ -408,12 +391,24 @@ QAccessible::Role QQuickTextAreaPrivate::accessibleRole() const
}
#endif
-void QQuickTextAreaPrivate::deleteDelegate(QObject *delegate)
+QQuickTextArea::QQuickTextArea(QQuickItem *parent)
+ : QQuickTextEdit(*(new QQuickTextAreaPrivate), parent)
+{
+ Q_D(QQuickTextArea);
+ setActiveFocusOnTab(true);
+ setAcceptedMouseButtons(Qt::AllButtons);
+ d->setImplicitResizeEnabled(false);
+ d->pressHandler.control = this;
+#if QT_CONFIG(cursor)
+ setCursor(Qt::IBeamCursor);
+#endif
+ QObjectPrivate::connect(this, &QQuickTextEdit::readOnlyChanged,
+ d, &QQuickTextAreaPrivate::readOnlyChanged);
+}
+
+QQuickTextAreaAttached *QQuickTextArea::qmlAttachedProperties(QObject *object)
{
- if (componentComplete)
- delete delegate;
- else if (delegate)
- pendingDeletions.append(delegate);
+ return new QQuickTextAreaAttached(object);
}
QFont QQuickTextArea::font() const
@@ -452,7 +447,7 @@ void QQuickTextArea::setBackground(QQuickItem *background)
if (d->background == background)
return;
- d->deleteDelegate(d->background);
+ QQuickControlPrivate::destroyDelegate(d->background, this);
d->background = background;
if (background) {
background->setParentItem(this);
@@ -483,7 +478,7 @@ void QQuickTextArea::setPlaceholderText(const QString &text)
return;
d->placeholder = text;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (d->accessibleAttached)
d->accessibleAttached->setDescription(text);
#endif
@@ -522,18 +517,26 @@ void QQuickTextArea::setFocusReason(Qt::FocusReason reason)
*/
bool QQuickTextArea::isHovered() const
{
+#if QT_CONFIG(quicktemplates2_hover)
Q_D(const QQuickTextArea);
return d->hovered;
+#else
+ return false;
+#endif
}
void QQuickTextArea::setHovered(bool hovered)
{
+#if QT_CONFIG(quicktemplates2_hover)
Q_D(QQuickTextArea);
if (hovered == d->hovered)
return;
d->hovered = hovered;
emit hoveredChanged();
+#else
+ Q_UNUSED(hovered);
+#endif
}
/*!
@@ -546,27 +549,37 @@ void QQuickTextArea::setHovered(bool hovered)
*/
bool QQuickTextArea::isHoverEnabled() const
{
+#if QT_CONFIG(quicktemplates2_hover)
Q_D(const QQuickTextArea);
return d->hoverEnabled;
+#else
+ return false;
+#endif
}
void QQuickTextArea::setHoverEnabled(bool enabled)
{
+#if QT_CONFIG(quicktemplates2_hover)
Q_D(QQuickTextArea);
if (d->explicitHoverEnabled && enabled == d->hoverEnabled)
return;
d->updateHoverEnabled(enabled, true); // explicit=true
+#else
+ Q_UNUSED(enabled);
+#endif
}
void QQuickTextArea::resetHoverEnabled()
{
+#if QT_CONFIG(quicktemplates2_hover)
Q_D(QQuickTextArea);
if (!d->explicitHoverEnabled)
return;
d->explicitHoverEnabled = false;
d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
+#endif
}
bool QQuickTextArea::contains(const QPointF &point) const
@@ -588,15 +601,14 @@ void QQuickTextArea::componentComplete()
{
Q_D(QQuickTextArea);
QQuickTextEdit::componentComplete();
+#if QT_CONFIG(quicktemplates2_hover)
if (!d->explicitHoverEnabled)
setAcceptHoverEvents(QQuickControlPrivate::calcHoverEnabled(d->parentItem));
-#ifndef QT_NO_ACCESSIBILITY
+#endif
+#if QT_CONFIG(accessibility)
if (!d->accessibleAttached && QAccessible::isActive())
d->accessibilityActiveChanged(true);
#endif
-
- qDeleteAll(d->pendingDeletions);
- d->pendingDeletions.clear();
}
void QQuickTextArea::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)
@@ -605,8 +617,16 @@ void QQuickTextArea::itemChange(QQuickItem::ItemChange change, const QQuickItem:
QQuickTextEdit::itemChange(change, value);
if (change == ItemParentHasChanged && value.item) {
d->resolveFont();
+#if QT_CONFIG(quicktemplates2_hover)
if (!d->explicitHoverEnabled)
d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
+#endif
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(value.item->parentItem());
+ if (flickable) {
+ QQuickScrollView *scrollView = qobject_cast<QQuickScrollView *>(flickable->parentItem());
+ if (scrollView)
+ d->attachFlickable(flickable);
+ }
}
}
@@ -657,6 +677,7 @@ void QQuickTextArea::focusOutEvent(QFocusEvent *event)
setFocusReason(event->reason());
}
+#if QT_CONFIG(quicktemplates2_hover)
void QQuickTextArea::hoverEnterEvent(QHoverEvent *event)
{
Q_D(QQuickTextArea);
@@ -672,6 +693,7 @@ void QQuickTextArea::hoverLeaveEvent(QHoverEvent *event)
setHovered(false);
event->setAccepted(d->hoverEnabled);
}
+#endif
void QQuickTextArea::mousePressEvent(QMouseEvent *event)
{
@@ -730,11 +752,10 @@ void QQuickTextArea::mouseDoubleClickEvent(QMouseEvent *event)
void QQuickTextArea::timerEvent(QTimerEvent *event)
{
Q_D(QQuickTextArea);
- if (event->timerId() == d->pressHandler.timer.timerId()) {
+ if (event->timerId() == d->pressHandler.timer.timerId())
d->pressHandler.timerEvent(event);
- } else {
+ else
QQuickTextEdit::timerEvent(event);
- }
}
class QQuickTextAreaAttachedPrivate : public QObjectPrivate
@@ -745,12 +766,8 @@ public:
QQuickTextArea *control;
};
-QQuickTextAreaAttached::QQuickTextAreaAttached(QObject *parent) :
- QObject(*(new QQuickTextAreaAttachedPrivate), parent)
-{
-}
-
-QQuickTextAreaAttached::~QQuickTextAreaAttached()
+QQuickTextAreaAttached::QQuickTextAreaAttached(QObject *parent)
+ : QObject(*(new QQuickTextAreaAttachedPrivate), parent)
{
}
@@ -772,7 +789,7 @@ void QQuickTextAreaAttached::setFlickable(QQuickTextArea *control)
Q_D(QQuickTextAreaAttached);
QQuickFlickable *flickable = qobject_cast<QQuickFlickable *>(parent());
if (!flickable) {
- qmlInfo(parent()) << "TextArea must be attached to a Flickable";
+ qmlWarning(parent()) << "TextArea must be attached to a Flickable";
return;
}
diff --git a/src/quicktemplates2/qquicktextarea_p.h b/src/quicktemplates2/qquicktextarea_p.h
index 87c75f03..af7c1d13 100644
--- a/src/quicktemplates2/qquicktextarea_p.h
+++ b/src/quicktemplates2/qquicktextarea_p.h
@@ -72,7 +72,6 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTextArea : public QQuickTextEdit
public:
explicit QQuickTextArea(QQuickItem *parent = nullptr);
- ~QQuickTextArea();
static QQuickTextAreaAttached *qmlAttachedProperties(QObject *object);
@@ -120,8 +119,10 @@ protected:
void focusInEvent(QFocusEvent *event) override;
void focusOutEvent(QFocusEvent *event) override;
+#if QT_CONFIG(quicktemplates2_hover)
void hoverEnterEvent(QHoverEvent *event) override;
void hoverLeaveEvent(QHoverEvent *event) override;
+#endif
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
@@ -142,7 +143,6 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTextAreaAttached : public QObject
public:
explicit QQuickTextAreaAttached(QObject *parent);
- ~QQuickTextAreaAttached();
QQuickTextArea *flickable() const;
void setFlickable(QQuickTextArea *control);
diff --git a/src/quicktemplates2/qquicktextarea_p_p.h b/src/quicktemplates2/qquicktextarea_p_p.h
index 85afd226..ef2c7237 100644
--- a/src/quicktemplates2/qquicktextarea_p_p.h
+++ b/src/quicktemplates2/qquicktextarea_p_p.h
@@ -54,7 +54,7 @@
#include "qquicktextarea_p.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <QtGui/qaccessible.h>
#endif
@@ -64,7 +64,7 @@ class QQuickFlickable;
class QQuickAccessibleAttached;
class QQuickTextAreaPrivate : public QQuickTextEditPrivate, public QQuickItemChangeListener
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
, public QAccessible::ActivationObserver
#endif
{
@@ -74,14 +74,18 @@ public:
QQuickTextAreaPrivate();
~QQuickTextAreaPrivate();
- static QQuickTextAreaPrivate *get(QQuickTextArea *item) {
- return static_cast<QQuickTextAreaPrivate *>(QObjectPrivate::get(item)); }
+ static QQuickTextAreaPrivate *get(QQuickTextArea *item)
+ {
+ return static_cast<QQuickTextAreaPrivate *>(QObjectPrivate::get(item));
+ }
void resizeBackground();
void resolveFont();
void inheritFont(const QFont &f);
+#if QT_CONFIG(quicktemplates2_hover)
void updateHoverEnabled(bool h, bool e);
+#endif
void attachFlickable(QQuickFlickable *flickable);
void detachFlickable();
@@ -97,17 +101,17 @@ public:
void implicitWidthChanged() override;
void implicitHeightChanged() override;
- void _q_readOnlyChanged(bool isReadOnly);
+ void readOnlyChanged(bool isReadOnly);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
void accessibilityActiveChanged(bool active) override;
QAccessible::Role accessibleRole() const override;
#endif
- void deleteDelegate(QObject *object);
-
+#if QT_CONFIG(quicktemplates2_hover)
bool hovered;
bool explicitHoverEnabled;
+#endif
QFont font;
QQuickItem *background;
QString placeholder;
@@ -115,10 +119,6 @@ public:
QQuickPressHandler pressHandler;
QQuickAccessibleAttached *accessibleAttached;
QQuickFlickable *flickable;
- // This list contains the default delegates which were
- // replaced with custom ones via declarative assignments
- // before Component.completed() was emitted. See QTBUG-50992.
- QVector<QObject *> pendingDeletions;
};
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquicktextfield.cpp b/src/quicktemplates2/qquicktextfield.cpp
index 2718b13e..e6ca2496 100644
--- a/src/quicktemplates2/qquicktextfield.cpp
+++ b/src/quicktemplates2/qquicktextfield.cpp
@@ -39,13 +39,11 @@
#include "qquickcontrol_p.h"
#include "qquickcontrol_p_p.h"
-#include <QtCore/qbasictimer.h>
#include <QtQuick/private/qquickitem_p.h>
-#include <QtQuick/private/qquicktext_p.h>
#include <QtQuick/private/qquicktextinput_p.h>
#include <QtQuick/private/qquickclipnode_p.h>
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <QtQuick/private/qquickaccessibleattached_p.h>
#endif
@@ -114,20 +112,23 @@ QT_BEGIN_NAMESPACE
*/
QQuickTextFieldPrivate::QQuickTextFieldPrivate()
- : hovered(false)
- , explicitHoverEnabled(false)
- , background(nullptr)
- , focusReason(Qt::OtherFocusReason)
- , accessibleAttached(nullptr)
+ : QQuickTextInputPrivate(),
+#if QT_CONFIG(quicktemplates2_hover)
+ hovered(false),
+ explicitHoverEnabled(false),
+#endif
+ background(nullptr),
+ focusReason(Qt::OtherFocusReason),
+ accessibleAttached(nullptr)
{
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::installActivationObserver(this);
#endif
}
QQuickTextFieldPrivate::~QQuickTextFieldPrivate()
{
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::removeActivationObserver(this);
#endif
}
@@ -148,51 +149,6 @@ void QQuickTextFieldPrivate::resizeBackground()
}
}
-qreal QQuickTextFieldPrivate::getImplicitWidth() const
-{
- return QQuickItemPrivate::getImplicitWidth();
-}
-
-qreal QQuickTextFieldPrivate::getImplicitHeight() const
-{
- return QQuickItemPrivate::getImplicitHeight();
-}
-
-void QQuickTextFieldPrivate::implicitWidthChanged()
-{
- Q_Q(QQuickTextField);
- QQuickItemPrivate::implicitWidthChanged();
- emit q->implicitWidthChanged3();
-}
-
-void QQuickTextFieldPrivate::implicitHeightChanged()
-{
- Q_Q(QQuickTextField);
- QQuickItemPrivate::implicitHeightChanged();
- emit q->implicitHeightChanged3();
-}
-
-QQuickTextField::QQuickTextField(QQuickItem *parent) :
- QQuickTextInput(*(new QQuickTextFieldPrivate), parent)
-{
- Q_D(QQuickTextField);
- d->pressHandler.control = this;
- d->setImplicitResizeEnabled(false);
- setAcceptedMouseButtons(Qt::AllButtons);
- setActiveFocusOnTab(true);
-#ifndef QT_NO_CURSOR
- setCursor(Qt::IBeamCursor);
-#endif
- QObjectPrivate::connect(this, &QQuickTextInput::readOnlyChanged,
- d, &QQuickTextFieldPrivate::_q_readOnlyChanged);
- QObjectPrivate::connect(this, &QQuickTextInput::echoModeChanged,
- d, &QQuickTextFieldPrivate::_q_echoModeChanged);
-}
-
-QQuickTextField::~QQuickTextField()
-{
-}
-
/*!
\internal
@@ -222,6 +178,7 @@ void QQuickTextFieldPrivate::inheritFont(const QFont &f)
emit q->fontChanged();
}
+#if QT_CONFIG(quicktemplates2_hover)
void QQuickTextFieldPrivate::updateHoverEnabled(bool enabled, bool xplicit)
{
Q_Q(QQuickTextField);
@@ -236,22 +193,47 @@ void QQuickTextFieldPrivate::updateHoverEnabled(bool enabled, bool xplicit)
emit q->hoverEnabledChanged();
}
}
+#endif
+
+qreal QQuickTextFieldPrivate::getImplicitWidth() const
+{
+ return QQuickItemPrivate::getImplicitWidth();
+}
+
+qreal QQuickTextFieldPrivate::getImplicitHeight() const
+{
+ return QQuickItemPrivate::getImplicitHeight();
+}
+
+void QQuickTextFieldPrivate::implicitWidthChanged()
+{
+ Q_Q(QQuickTextField);
+ QQuickItemPrivate::implicitWidthChanged();
+ emit q->implicitWidthChanged3();
+}
-void QQuickTextFieldPrivate::_q_readOnlyChanged(bool isReadOnly)
+void QQuickTextFieldPrivate::implicitHeightChanged()
+{
+ Q_Q(QQuickTextField);
+ QQuickItemPrivate::implicitHeightChanged();
+ emit q->implicitHeightChanged3();
+}
+
+void QQuickTextFieldPrivate::readOnlyChanged(bool isReadOnly)
{
Q_UNUSED(isReadOnly);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (accessibleAttached)
accessibleAttached->set_readOnly(isReadOnly);
#endif
-#ifndef QT_NO_CURSOR
+#if QT_CONFIG(cursor)
q_func()->setCursor(isReadOnly ? Qt::ArrowCursor : Qt::IBeamCursor);
#endif
}
-void QQuickTextFieldPrivate::_q_echoModeChanged(QQuickTextField::EchoMode echoMode)
+void QQuickTextFieldPrivate::echoModeChanged(QQuickTextField::EchoMode echoMode)
{
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (accessibleAttached)
accessibleAttached->set_passwordEdit((echoMode == QQuickTextField::Password || echoMode == QQuickTextField::PasswordEchoOnEdit) ? true : false);
#else
@@ -259,7 +241,7 @@ void QQuickTextFieldPrivate::_q_echoModeChanged(QQuickTextField::EchoMode echoMo
#endif
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
void QQuickTextFieldPrivate::accessibilityActiveChanged(bool active)
{
if (accessibleAttached || !active)
@@ -283,16 +265,19 @@ QAccessible::Role QQuickTextFieldPrivate::accessibleRole() const
}
#endif
-/*
- Deletes "delegate" if Component.completed() has been emitted,
- otherwise stores it in pendingDeletions.
-*/
-void QQuickTextFieldPrivate::deleteDelegate(QObject *delegate)
+QQuickTextField::QQuickTextField(QQuickItem *parent)
+ : QQuickTextInput(*(new QQuickTextFieldPrivate), parent)
{
- if (componentComplete)
- delete delegate;
- else if (delegate)
- pendingDeletions.append(delegate);
+ Q_D(QQuickTextField);
+ d->pressHandler.control = this;
+ d->setImplicitResizeEnabled(false);
+ setAcceptedMouseButtons(Qt::AllButtons);
+ setActiveFocusOnTab(true);
+#if QT_CONFIG(cursor)
+ setCursor(Qt::IBeamCursor);
+#endif
+ QObjectPrivate::connect(this, &QQuickTextInput::readOnlyChanged, d, &QQuickTextFieldPrivate::readOnlyChanged);
+ QObjectPrivate::connect(this, &QQuickTextInput::echoModeChanged, d, &QQuickTextFieldPrivate::echoModeChanged);
}
QFont QQuickTextField::font() const
@@ -331,7 +316,7 @@ void QQuickTextField::setBackground(QQuickItem *background)
if (d->background == background)
return;
- d->deleteDelegate(d->background);
+ QQuickControlPrivate::destroyDelegate(d->background, this);
d->background = background;
if (background) {
background->setParentItem(this);
@@ -362,7 +347,7 @@ void QQuickTextField::setPlaceholderText(const QString &text)
return;
d->placeholder = text;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (d->accessibleAttached)
d->accessibleAttached->setDescription(text);
#endif
@@ -401,18 +386,26 @@ void QQuickTextField::setFocusReason(Qt::FocusReason reason)
*/
bool QQuickTextField::isHovered() const
{
+#if QT_CONFIG(quicktemplates2_hover)
Q_D(const QQuickTextField);
return d->hovered;
+#else
+ return false;
+#endif
}
void QQuickTextField::setHovered(bool hovered)
{
+#if QT_CONFIG(quicktemplates2_hover)
Q_D(QQuickTextField);
if (hovered == d->hovered)
return;
d->hovered = hovered;
emit hoveredChanged();
+#else
+ Q_UNUSED(hovered);
+#endif
}
/*!
@@ -425,27 +418,37 @@ void QQuickTextField::setHovered(bool hovered)
*/
bool QQuickTextField::isHoverEnabled() const
{
+#if QT_CONFIG(quicktemplates2_hover)
Q_D(const QQuickTextField);
return d->hoverEnabled;
+#else
+ return false;
+#endif
}
void QQuickTextField::setHoverEnabled(bool enabled)
{
+#if QT_CONFIG(quicktemplates2_hover)
Q_D(QQuickTextField);
if (d->explicitHoverEnabled && enabled == d->hoverEnabled)
return;
d->updateHoverEnabled(enabled, true); // explicit=true
+#else
+ Q_UNUSED(enabled);
+#endif
}
void QQuickTextField::resetHoverEnabled()
{
+#if QT_CONFIG(quicktemplates2_hover)
Q_D(QQuickTextField);
if (!d->explicitHoverEnabled)
return;
d->explicitHoverEnabled = false;
d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
+#endif
}
void QQuickTextField::classBegin()
@@ -459,15 +462,14 @@ void QQuickTextField::componentComplete()
{
Q_D(QQuickTextField);
QQuickTextInput::componentComplete();
+#if QT_CONFIG(quicktemplates2_hover)
if (!d->explicitHoverEnabled)
setAcceptHoverEvents(QQuickControlPrivate::calcHoverEnabled(d->parentItem));
-#ifndef QT_NO_ACCESSIBILITY
+#endif
+#if QT_CONFIG(accessibility)
if (!d->accessibleAttached && QAccessible::isActive())
d->accessibilityActiveChanged(true);
#endif
-
- qDeleteAll(d->pendingDeletions);
- d->pendingDeletions.clear();
}
void QQuickTextField::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)
@@ -476,8 +478,10 @@ void QQuickTextField::itemChange(QQuickItem::ItemChange change, const QQuickItem
QQuickTextInput::itemChange(change, value);
if (change == ItemParentHasChanged && value.item) {
d->resolveFont();
+#if QT_CONFIG(quicktemplates2_hover)
if (!d->explicitHoverEnabled)
d->updateHoverEnabled(QQuickControlPrivate::calcHoverEnabled(d->parentItem), false); // explicit=false
+#endif
}
}
@@ -516,6 +520,7 @@ void QQuickTextField::focusOutEvent(QFocusEvent *event)
setFocusReason(event->reason());
}
+#if QT_CONFIG(quicktemplates2_hover)
void QQuickTextField::hoverEnterEvent(QHoverEvent *event)
{
Q_D(QQuickTextField);
@@ -531,6 +536,7 @@ void QQuickTextField::hoverLeaveEvent(QHoverEvent *event)
setHovered(false);
event->setAccepted(d->hoverEnabled);
}
+#endif
void QQuickTextField::mousePressEvent(QMouseEvent *event)
{
@@ -584,11 +590,10 @@ void QQuickTextField::mouseDoubleClickEvent(QMouseEvent *event)
void QQuickTextField::timerEvent(QTimerEvent *event)
{
Q_D(QQuickTextField);
- if (event->timerId() == d->pressHandler.timer.timerId()) {
+ if (event->timerId() == d->pressHandler.timer.timerId())
d->pressHandler.timerEvent(event);
- } else {
+ else
QQuickTextInput::timerEvent(event);
- }
}
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquicktextfield_p.h b/src/quicktemplates2/qquicktextfield_p.h
index 3a520527..24e6ce53 100644
--- a/src/quicktemplates2/qquicktextfield_p.h
+++ b/src/quicktemplates2/qquicktextfield_p.h
@@ -71,7 +71,6 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTextField : public QQuickTextInput
public:
explicit QQuickTextField(QQuickItem *parent = nullptr);
- ~QQuickTextField();
QFont font() const;
void setFont(const QFont &font);
@@ -115,8 +114,10 @@ protected:
void focusInEvent(QFocusEvent *event) override;
void focusOutEvent(QFocusEvent *event) override;
+#if QT_CONFIG(quicktemplates2_hover)
void hoverEnterEvent(QHoverEvent *event) override;
void hoverLeaveEvent(QHoverEvent *event) override;
+#endif
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
diff --git a/src/quicktemplates2/qquicktextfield_p_p.h b/src/quicktemplates2/qquicktextfield_p_p.h
index d46ef6dc..31ccb361 100644
--- a/src/quicktemplates2/qquicktextfield_p_p.h
+++ b/src/quicktemplates2/qquicktextfield_p_p.h
@@ -53,7 +53,7 @@
#include "qquicktextfield_p.h"
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
#include <QtGui/qaccessible.h>
#endif
@@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE
class QQuickAccessibleAttached;
class QQuickTextFieldPrivate : public QQuickTextInputPrivate
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
, public QAccessible::ActivationObserver
#endif
{
@@ -79,7 +79,9 @@ public:
void resolveFont();
void inheritFont(const QFont &f);
+#if QT_CONFIG(quicktemplates2_hover)
void updateHoverEnabled(bool h, bool e);
+#endif
qreal getImplicitWidth() const override;
qreal getImplicitHeight() const override;
@@ -87,28 +89,24 @@ public:
void implicitWidthChanged() override;
void implicitHeightChanged() override;
- void _q_readOnlyChanged(bool isReadOnly);
- void _q_echoModeChanged(QQuickTextField::EchoMode echoMode);
+ void readOnlyChanged(bool isReadOnly);
+ void echoModeChanged(QQuickTextField::EchoMode echoMode);
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
void accessibilityActiveChanged(bool active) override;
QAccessible::Role accessibleRole() const override;
#endif
- void deleteDelegate(QObject *object);
-
+#if QT_CONFIG(quicktemplates2_hover)
bool hovered;
bool explicitHoverEnabled;
+#endif
QFont font;
QQuickItem *background;
QString placeholder;
Qt::FocusReason focusReason;
QQuickPressHandler pressHandler;
QQuickAccessibleAttached *accessibleAttached;
- // This list contains the default delegates which were
- // replaced with custom ones via declarative assignments
- // before Component.completed() was emitted. See QTBUG-50992.
- QVector<QObject *> pendingDeletions;
};
QT_END_NAMESPACE
diff --git a/src/quicktemplates2/qquicktoolbar.cpp b/src/quicktemplates2/qquicktoolbar.cpp
index 7b9d1444..9f5f210e 100644
--- a/src/quicktemplates2/qquicktoolbar.cpp
+++ b/src/quicktemplates2/qquicktoolbar.cpp
@@ -104,8 +104,8 @@ public:
QQuickToolBar::Position position;
};
-QQuickToolBar::QQuickToolBar(QQuickItem *parent) :
- QQuickPane(*(new QQuickToolBarPrivate), parent)
+QQuickToolBar::QQuickToolBar(QQuickItem *parent)
+ : QQuickPane(*(new QQuickToolBarPrivate), parent)
{
}
@@ -141,7 +141,7 @@ void QQuickToolBar::setPosition(Position position)
emit positionChanged();
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickToolBar::accessibleRole() const
{
return QAccessible::ToolBar;
diff --git a/src/quicktemplates2/qquicktoolbar_p.h b/src/quicktemplates2/qquicktoolbar_p.h
index 27dd37bb..58192ff9 100644
--- a/src/quicktemplates2/qquicktoolbar_p.h
+++ b/src/quicktemplates2/qquicktoolbar_p.h
@@ -75,7 +75,7 @@ Q_SIGNALS:
void positionChanged();
protected:
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquicktoolbutton.cpp b/src/quicktemplates2/qquicktoolbutton.cpp
index 5589162b..5ef25e3e 100644
--- a/src/quicktemplates2/qquicktoolbutton.cpp
+++ b/src/quicktemplates2/qquicktoolbutton.cpp
@@ -64,8 +64,8 @@ QT_BEGIN_NAMESPACE
\sa ToolBar, {Customizing ToolButton}, {Button Controls}
*/
-QQuickToolButton::QQuickToolButton(QQuickItem *parent) :
- QQuickButton(parent)
+QQuickToolButton::QQuickToolButton(QQuickItem *parent)
+ : QQuickButton(parent)
{
}
diff --git a/src/quicktemplates2/qquicktoolseparator.cpp b/src/quicktemplates2/qquicktoolseparator.cpp
index 676bf201..4da63907 100644
--- a/src/quicktemplates2/qquicktoolseparator.cpp
+++ b/src/quicktemplates2/qquicktoolseparator.cpp
@@ -66,16 +66,13 @@ class QQuickToolSeparatorPrivate : public QQuickControlPrivate
Q_DECLARE_PUBLIC(QQuickToolSeparator)
public:
- QQuickToolSeparatorPrivate() :
- orientation(Qt::Vertical)
- {
- }
+ QQuickToolSeparatorPrivate() : orientation(Qt::Vertical) { }
Qt::Orientation orientation;
};
-QQuickToolSeparator::QQuickToolSeparator(QQuickItem *parent) :
- QQuickControl(*(new QQuickToolSeparatorPrivate), parent)
+QQuickToolSeparator::QQuickToolSeparator(QQuickItem *parent)
+ : QQuickControl(*(new QQuickToolSeparatorPrivate), parent)
{
}
@@ -136,7 +133,7 @@ bool QQuickToolSeparator::isVertical() const
return d->orientation == Qt::Vertical;
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickToolSeparator::accessibleRole() const
{
return QAccessible::Separator;
diff --git a/src/quicktemplates2/qquicktoolseparator_p.h b/src/quicktemplates2/qquicktoolseparator_p.h
index 552c6fa8..055f475c 100644
--- a/src/quicktemplates2/qquicktoolseparator_p.h
+++ b/src/quicktemplates2/qquicktoolseparator_p.h
@@ -74,7 +74,7 @@ Q_SIGNALS:
void orientationChanged();
protected:
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
#endif
diff --git a/src/quicktemplates2/qquicktooltip.cpp b/src/quicktemplates2/qquicktooltip.cpp
index 3ce4c762..bf83a725 100644
--- a/src/quicktemplates2/qquicktooltip.cpp
+++ b/src/quicktemplates2/qquicktooltip.cpp
@@ -107,7 +107,7 @@ QT_BEGIN_NAMESPACE
Should one need more fine-grained control over the tool tip position, or
multiple simultaneous tool tip instances are needed, it is also possible
to create local tool tip instances. This way, it is possible to
- \l {Customizing ToolTip}{customize} the tool tip, and the whole \l Popup
+ \l {Customizing ToolTip}{customize} the tool tip, and the whole \l Popup
API is available. The following example presents a tool tip that presents
the value of a slider when the handle is dragged.
@@ -123,7 +123,11 @@ class QQuickToolTipPrivate : public QQuickPopupPrivate
Q_DECLARE_PUBLIC(QQuickToolTip)
public:
- QQuickToolTipPrivate() : delay(0), timeout(-1) { }
+ QQuickToolTipPrivate()
+ : delay(0),
+ timeout(-1)
+ {
+ }
void startDelay();
void stopDelay();
@@ -162,8 +166,8 @@ void QQuickToolTipPrivate::stopTimeout()
timeoutTimer.stop();
}
-QQuickToolTip::QQuickToolTip(QQuickItem *parent) :
- QQuickPopup(*(new QQuickToolTipPrivate), parent)
+QQuickToolTip::QQuickToolTip(QQuickItem *parent)
+ : QQuickPopup(*(new QQuickToolTipPrivate), parent)
{
Q_D(QQuickToolTip);
d->allowVerticalFlip = true;
@@ -265,7 +269,7 @@ QQuickToolTipAttached *QQuickToolTip::qmlAttachedProperties(QObject *object)
{
QQuickItem *item = qobject_cast<QQuickItem *>(object);
if (!item)
- qmlInfo(object) << "ToolTip must be attached to an Item";
+ qmlWarning(object) << "ToolTip must be attached to an Item";
return new QQuickToolTipAttached(object);
}
@@ -303,7 +307,7 @@ void QQuickToolTip::timerEvent(QTimerEvent *event)
}
}
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role QQuickToolTip::accessibleRole() const
{
return QAccessible::ToolTip;
@@ -324,7 +328,11 @@ class QQuickToolTipAttachedPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QQuickToolTipAttached)
public:
- QQuickToolTipAttachedPrivate() : delay(0), timeout(-1) { }
+ QQuickToolTipAttachedPrivate()
+ : delay(0),
+ timeout(-1)
+ {
+ }
QQuickToolTip *instance(bool create) const;
@@ -345,7 +353,7 @@ QQuickToolTip *QQuickToolTipAttachedPrivate::instance(bool create) const
if (!tip && create) {
// TODO: a cleaner way to create the instance? QQml(Meta)Type?
QQmlComponent component(engine);
- component.setData("import QtQuick.Controls 2.1; ToolTip { }", QUrl());
+ component.setData("import QtQuick.Controls 2.2; ToolTip { }", QUrl());
QObject *object = component.create();
if (object)
@@ -360,8 +368,8 @@ QQuickToolTip *QQuickToolTipAttachedPrivate::instance(bool create) const
return tip;
}
-QQuickToolTipAttached::QQuickToolTipAttached(QObject *parent) :
- QObject(*(new QQuickToolTipAttachedPrivate), parent)
+QQuickToolTipAttached::QQuickToolTipAttached(QObject *parent)
+ : QObject(*(new QQuickToolTipAttachedPrivate), parent)
{
}
diff --git a/src/quicktemplates2/qquicktooltip_p.h b/src/quicktemplates2/qquicktooltip_p.h
index 6fffa94e..bdfbe362 100644
--- a/src/quicktemplates2/qquicktooltip_p.h
+++ b/src/quicktemplates2/qquicktooltip_p.h
@@ -90,7 +90,7 @@ protected:
void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data) override;
void timerEvent(QTimerEvent *event) override;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
QAccessible::Role accessibleRole() const override;
void accessibilityActiveChanged(bool active) override;
#endif
diff --git a/src/quicktemplates2/qquicktumbler.cpp b/src/quicktemplates2/qquicktumbler.cpp
index 9091743c..05e4612d 100644
--- a/src/quicktemplates2/qquicktumbler.cpp
+++ b/src/quicktemplates2/qquicktumbler.cpp
@@ -85,19 +85,19 @@ QT_BEGIN_NAMESPACE
\sa {Customizing Tumbler}, {Input Controls}
*/
-QQuickTumblerPrivate::QQuickTumblerPrivate() :
- delegate(nullptr),
- visibleItemCount(5),
- wrap(true),
- explicitWrap(false),
- ignoreWrapChanges(false),
- view(nullptr),
- viewContentItem(nullptr),
- viewContentItemType(UnsupportedContentItemType),
- currentIndex(-1),
- pendingCurrentIndex(-1),
- ignoreCurrentIndexChanges(false),
- count(0)
+QQuickTumblerPrivate::QQuickTumblerPrivate()
+ : delegate(nullptr),
+ visibleItemCount(5),
+ wrap(true),
+ explicitWrap(false),
+ ignoreWrapChanges(false),
+ view(nullptr),
+ viewContentItem(nullptr),
+ viewContentItemType(UnsupportedContentItemType),
+ currentIndex(-1),
+ pendingCurrentIndex(-1),
+ ignoreCurrentIndexChanges(false),
+ count(0)
{
}
@@ -231,8 +231,8 @@ void QQuickTumblerPrivate::itemChildRemoved(QQuickItem *, QQuickItem *)
_q_updateItemHeights();
}
-QQuickTumbler::QQuickTumbler(QQuickItem *parent) :
- QQuickControl(*(new QQuickTumblerPrivate), parent)
+QQuickTumbler::QQuickTumbler(QQuickItem *parent)
+ : QQuickControl(*(new QQuickTumblerPrivate), parent)
{
setActiveFocusOnTab(true);
@@ -439,6 +439,19 @@ void QQuickTumbler::resetWrap()
d->setWrapBasedOnCount();
}
+/*!
+ \qmlproperty bool QtQuick.Controls::Tumbler::moving
+ \since QtQuick.Controls 2.2
+
+ This property describes whether the tumbler is currently moving, due to
+ the user either dragging or flicking it.
+*/
+bool QQuickTumbler::isMoving() const
+{
+ Q_D(const QQuickTumbler);
+ return d->view && d->view->property("moving").toBool();
+}
+
QQuickTumblerAttached *QQuickTumbler::qmlAttachedProperties(QObject *object)
{
return new QQuickTumblerAttached(object);
@@ -505,6 +518,7 @@ void QQuickTumblerPrivate::disconnectFromView()
QObject::disconnect(view, SIGNAL(currentIndexChanged()), q, SLOT(_q_onViewCurrentIndexChanged()));
QObject::disconnect(view, SIGNAL(currentItemChanged()), q, SIGNAL(currentItemChanged()));
QObject::disconnect(view, SIGNAL(countChanged()), q, SLOT(_q_onViewCountChanged()));
+ QObject::disconnect(view, SIGNAL(movingChanged()), q, SIGNAL(movingChanged()));
QQuickItemPrivate *oldViewContentItemPrivate = QQuickItemPrivate::get(viewContentItem);
oldViewContentItemPrivate->removeItemChangeListener(this, QQuickItemPrivate::Children);
@@ -529,6 +543,7 @@ void QQuickTumblerPrivate::setupViewData(QQuickItem *newControlContentItem)
QObject::connect(view, SIGNAL(currentIndexChanged()), q, SLOT(_q_onViewCurrentIndexChanged()));
QObject::connect(view, SIGNAL(currentItemChanged()), q, SIGNAL(currentItemChanged()));
QObject::connect(view, SIGNAL(countChanged()), q, SLOT(_q_onViewCountChanged()));
+ QObject::connect(view, SIGNAL(movingChanged()), q, SIGNAL(movingChanged()));
QQuickItemPrivate *viewContentItemPrivate = QQuickItemPrivate::get(viewContentItem);
viewContentItemPrivate->addItemChangeListener(this, QQuickItemPrivate::Children);
@@ -667,10 +682,10 @@ class QQuickTumblerAttachedPrivate : public QObjectPrivate, public QQuickItemCha
{
Q_DECLARE_PUBLIC(QQuickTumblerAttached)
public:
- QQuickTumblerAttachedPrivate() :
- tumbler(nullptr),
- index(-1),
- displacement(0)
+ QQuickTumblerAttachedPrivate()
+ : tumbler(nullptr),
+ index(-1),
+ displacement(0)
{
}
@@ -794,15 +809,15 @@ void QQuickTumblerAttachedPrivate::emitIfDisplacementChanged(qreal oldDisplaceme
emit q->displacementChanged();
}
-QQuickTumblerAttached::QQuickTumblerAttached(QObject *parent) :
- QObject(*(new QQuickTumblerAttachedPrivate), parent)
+QQuickTumblerAttached::QQuickTumblerAttached(QObject *parent)
+ : QObject(*(new QQuickTumblerAttachedPrivate), parent)
{
Q_D(QQuickTumblerAttached);
QQuickItem *delegateItem = qobject_cast<QQuickItem *>(parent);
if (delegateItem)
d->init(delegateItem);
else if (parent)
- qmlInfo(parent) << "Tumbler: attached properties of Tumbler must be accessed through a delegate item";
+ qmlWarning(parent) << "Tumbler: attached properties of Tumbler must be accessed through a delegate item";
if (d->tumbler) {
// When the Tumbler is completed, wrapChanged() is emitted to let QQuickTumblerView
diff --git a/src/quicktemplates2/qquicktumbler_p.h b/src/quicktemplates2/qquicktumbler_p.h
index 68644a5a..b71a7636 100644
--- a/src/quicktemplates2/qquicktumbler_p.h
+++ b/src/quicktemplates2/qquicktumbler_p.h
@@ -67,6 +67,7 @@ class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickTumbler : public QQuickControl
Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged FINAL)
Q_PROPERTY(int visibleItemCount READ visibleItemCount WRITE setVisibleItemCount NOTIFY visibleItemCountChanged FINAL)
Q_PROPERTY(bool wrap READ wrap WRITE setWrap RESET resetWrap NOTIFY wrapChanged FINAL REVISION 1)
+ Q_PROPERTY(bool moving READ isMoving NOTIFY movingChanged FINAL REVISION 2)
public:
explicit QQuickTumbler(QQuickItem *parent = nullptr);
@@ -91,6 +92,8 @@ public:
void setWrap(bool wrap);
void resetWrap();
+ bool isMoving() const;
+
static QQuickTumblerAttached *qmlAttachedProperties(QObject *object);
Q_SIGNALS:
@@ -101,6 +104,7 @@ Q_SIGNALS:
void delegateChanged();
void visibleItemCountChanged();
Q_REVISION(1) void wrapChanged();
+ Q_REVISION(2) void movingChanged();
protected:
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
diff --git a/src/quicktemplates2/qquickvelocitycalculator.cpp b/src/quicktemplates2/qquickvelocitycalculator.cpp
index 21b8b27d..b98eeff9 100644
--- a/src/quicktemplates2/qquickvelocitycalculator.cpp
+++ b/src/quicktemplates2/qquickvelocitycalculator.cpp
@@ -58,9 +58,9 @@ QT_BEGIN_NAMESPACE
doSomethingElse();
*/
-QQuickVelocityCalculator::QQuickVelocityCalculator() :
- m_point1Timestamp(0),
- m_point2Timestamp(0)
+QQuickVelocityCalculator::QQuickVelocityCalculator()
+ : m_point1Timestamp(0),
+ m_point2Timestamp(0)
{
}
diff --git a/src/quicktemplates2/qtquicktemplates2global_p.h b/src/quicktemplates2/qtquicktemplates2global_p.h
index 322a334f..b7f54bb6 100644
--- a/src/quicktemplates2/qtquicktemplates2global_p.h
+++ b/src/quicktemplates2/qtquicktemplates2global_p.h
@@ -49,6 +49,7 @@
//
#include <QtCore/qglobal.h>
+#include <QtQuickTemplates2/private/qtquicktemplates2-config_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quicktemplates2/quicktemplates2.pri b/src/quicktemplates2/quicktemplates2.pri
index 4a128501..a7570ec5 100644
--- a/src/quicktemplates2/quicktemplates2.pri
+++ b/src/quicktemplates2/quicktemplates2.pri
@@ -15,6 +15,7 @@ HEADERS += \
$$PWD/qquickcontainer_p_p.h \
$$PWD/qquickcontrol_p.h \
$$PWD/qquickcontrol_p_p.h \
+ $$PWD/qquickdelaybutton_p.h \
$$PWD/qquickdial_p.h \
$$PWD/qquickdialog_p.h \
$$PWD/qquickdialog_p_p.h \
@@ -42,6 +43,8 @@ HEADERS += \
$$PWD/qquickpane_p_p.h \
$$PWD/qquickpopup_p.h \
$$PWD/qquickpopup_p_p.h \
+ $$PWD/qquickpopupitem_p_p.h \
+ $$PWD/qquickpopuppositioner_p_p.h \
$$PWD/qquickpresshandler_p_p.h \
$$PWD/qquickprogressbar_p.h \
$$PWD/qquickradiobutton_p.h \
@@ -49,10 +52,14 @@ HEADERS += \
$$PWD/qquickrangeslider_p.h \
$$PWD/qquickroundbutton_p.h \
$$PWD/qquickscrollbar_p.h \
+ $$PWD/qquickscrollbar_p_p.h \
$$PWD/qquickscrollindicator_p.h \
+ $$PWD/qquickscrollview_p.h \
$$PWD/qquickshortcutcontext_p_p.h \
$$PWD/qquickslider_p.h \
$$PWD/qquickspinbox_p.h \
+ $$PWD/qquickstackelement_p_p.h \
+ $$PWD/qquickstacktransition_p_p.h \
$$PWD/qquickstackview_p.h \
$$PWD/qquickstackview_p_p.h \
$$PWD/qquickswipe_p.h \
@@ -71,8 +78,6 @@ HEADERS += \
$$PWD/qquicktoolbutton_p.h \
$$PWD/qquicktoolseparator_p.h \
$$PWD/qquicktooltip_p.h \
- $$PWD/qquicktumbler_p.h \
- $$PWD/qquicktumbler_p_p.h \
$$PWD/qquickvelocitycalculator_p_p.h
SOURCES += \
@@ -86,6 +91,7 @@ SOURCES += \
$$PWD/qquickcombobox.cpp \
$$PWD/qquickcontainer.cpp \
$$PWD/qquickcontrol.cpp \
+ $$PWD/qquickdelaybutton.cpp \
$$PWD/qquickdial.cpp \
$$PWD/qquickdialog.cpp \
$$PWD/qquickdialogbuttonbox.cpp \
@@ -103,6 +109,8 @@ SOURCES += \
$$PWD/qquickpagelayout.cpp \
$$PWD/qquickpane.cpp \
$$PWD/qquickpopup.cpp \
+ $$PWD/qquickpopupitem.cpp \
+ $$PWD/qquickpopuppositioner.cpp \
$$PWD/qquickpresshandler.cpp \
$$PWD/qquickprogressbar.cpp \
$$PWD/qquickradiobutton.cpp \
@@ -111,9 +119,12 @@ SOURCES += \
$$PWD/qquickroundbutton.cpp \
$$PWD/qquickscrollbar.cpp \
$$PWD/qquickscrollindicator.cpp \
+ $$PWD/qquickscrollview.cpp \
$$PWD/qquickshortcutcontext.cpp \
$$PWD/qquickslider.cpp \
$$PWD/qquickspinbox.cpp \
+ $$PWD/qquickstackelement.cpp \
+ $$PWD/qquickstacktransition.cpp \
$$PWD/qquickstackview.cpp \
$$PWD/qquickstackview_p.cpp \
$$PWD/qquickswipedelegate.cpp \
@@ -128,5 +139,12 @@ SOURCES += \
$$PWD/qquicktoolbutton.cpp \
$$PWD/qquicktoolseparator.cpp \
$$PWD/qquicktooltip.cpp \
- $$PWD/qquicktumbler.cpp \
$$PWD/qquickvelocitycalculator.cpp
+
+qtConfig(quick-listview):qtConfig(quick-pathview) {
+ HEADERS += \
+ $$PWD/qquicktumbler_p.h \
+ $$PWD/qquicktumbler_p_p.h
+ SOURCES += \
+ $$PWD/qquicktumbler.cpp
+}