Merge lp:~zsombi/ubuntu-ui-toolkit/cppAbstractButton into lp:ubuntu-ui-toolkit/staging

Proposed by Zsombor Egri
Status: Merged
Approved by: Zsombor Egri
Approved revision: 1638
Merged at revision: 1618
Proposed branch: lp:~zsombi/ubuntu-ui-toolkit/cppAbstractButton
Merge into: lp:ubuntu-ui-toolkit/staging
Prerequisite: lp:~zsombi/ubuntu-ui-toolkit/cppHaptics
Diff against target: 807 lines (+449/-125)
21 files modified
components.api (+2/-2)
src/Ubuntu/Components/1.3/AbstractButton.qml (+0/-109)
src/Ubuntu/Components/1.3/Button.qml (+1/-1)
src/Ubuntu/Components/1.3/ComboButton.qml (+1/-0)
src/Ubuntu/Components/1.3/TextField.qml (+1/-1)
src/Ubuntu/Components/ComponentModule.pro (+1/-2)
src/Ubuntu/Components/ListItems/1.3/SingleControl.qml (+2/-1)
src/Ubuntu/Components/plugin/plugin.cpp (+2/-0)
src/Ubuntu/Components/plugin/plugin.pri (+4/-2)
src/Ubuntu/Components/plugin/ucabstractbutton.cpp (+156/-0)
src/Ubuntu/Components/plugin/ucabstractbutton.h (+64/-0)
src/Ubuntu/Components/plugin/ucaction.cpp (+2/-1)
src/Ubuntu/Components/plugin/ucactionitem.cpp (+15/-4)
src/Ubuntu/Components/plugin/ucactionitem.h (+2/-0)
src/Ubuntu/Components/qmldir (+0/-1)
tests/unit/tst_components/tst_action.qml (+16/-0)
tests/unit/tst_performance/AbstractButton13Grid.qml (+30/-0)
tests/unit/tst_performance/AbstractButtonGrid.qml (+30/-0)
tests/unit/tst_performance/tst_performance.cpp (+2/-0)
tests/unit/tst_performance/tst_performance.pro (+3/-1)
tests/unit_x11/tst_components/tst_abstractbutton13.qml (+115/-0)
To merge this branch: bzr merge lp:~zsombi/ubuntu-ui-toolkit/cppAbstractButton
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Cris Dywan Approve
Tim Peeters Approve
Review via email: mp+268442@code.launchpad.net

Commit message

AbstractButton to C++.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote :

Why are you not importing the latest versions (not only of Ubuntu.Components, but also QtQuick and Ambience) in the performance tests?

686 === added file 'tests/unit/tst_performance/AbstractButtonGrid.qml'
706 +import QtQuick 2.0
707 +import Ubuntu.Components 1.1
708 +import Ubuntu.Components.Themes.Ambiance 0.1

722 === modified file 'tests/unit/tst_performance/ButtonGrid.qml'
728 import QtQuick 2.0
729 -import Ubuntu.Components 1.1
730 +import Ubuntu.Components 1.3
731 import Ubuntu.Components.Themes.Ambiance 0.1

Revision history for this message
Tim Peeters (tpeeters) wrote :

883 + // fixing bugs 1365471 and 1458028
884 + function test_no_pressAndHold_connected_clicks() {

890 + // fixing bugs 1365471 and 1458028
891 + function test_pressAndHold_connected_suppresses_clicks() {

We have the policy to add _bugXXX to the function names. Let's do that here too because when a test starts to fail like that we can look up the bug immediately without going into the test code first.

review: Needs Fixing
Revision history for this message
Tim Peeters (tpeeters) wrote :

351 === modified file 'src/Ubuntu/Components/ListItems/1.2/SingleControl.qml'
360 + /*! \internal - overriding readonly pressed property due to the buggy pressed property exposure in former AbstractButton */
361 + property bool pressed: __mouseArea.pressed || (control && control.hasOwnProperty("pressed") && control.pressed)

I think we should override the property in Empty.qml instead to avoid problems in apps that have their own components deriving from Empty.

Revision history for this message
Tim Peeters (tpeeters) wrote :

^maybe for 'hovered' too, to be sure.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> Why are you not importing the latest versions (not only of Ubuntu.Components,
> but also QtQuick and Ambience) in the performance tests?
>
> 686 === added file 'tests/unit/tst_performance/AbstractButtonGrid.qml'
> 706 +import QtQuick 2.0
> 707 +import Ubuntu.Components 1.1
> 708 +import Ubuntu.Components.Themes.Ambiance 0.1

Copy-paste bug :)
>
> 722 === modified file 'tests/unit/tst_performance/ButtonGrid.qml'
> 728 import QtQuick 2.0
> 729 -import Ubuntu.Components 1.1
> 730 +import Ubuntu.Components 1.3
> 731 import Ubuntu.Components.Themes.Ambiance 0.1

This is the same reason we must get rid of the deprecation warnings... I'll roll this back

Revision history for this message
Zsombor Egri (zsombi) wrote :

> 351 === modified file
> 'src/Ubuntu/Components/ListItems/1.2/SingleControl.qml'
> 360 + /*! \internal - overriding readonly pressed property due to the
> buggy pressed property exposure in former AbstractButton */
> 361 + property bool pressed: __mouseArea.pressed || (control &&
> control.hasOwnProperty("pressed") && control.pressed)
>
>
> I think we should override the property in Empty.qml instead to avoid problems
> in apps that have their own components deriving from Empty.

Well, the property was there in SingleControl, so why would I move that to Empty?Beside, this should not happen according to the new design, so when you tap on a widget, that should not highlight the component.

Revision history for this message
Tim Peeters (tpeeters) wrote :

> > 351 === modified file
> > 'src/Ubuntu/Components/ListItems/1.2/SingleControl.qml'
> > 360 + /*! \internal - overriding readonly pressed property due to the
> > buggy pressed property exposure in former AbstractButton */
> > 361 + property bool pressed: __mouseArea.pressed || (control &&
> > control.hasOwnProperty("pressed") && control.pressed)
> >
> >
> > I think we should override the property in Empty.qml instead to avoid
> problems
> > in apps that have their own components deriving from Empty.
>
> Well, the property was there in SingleControl, so why would I move that to
> Empty?Beside, this should not happen according to the new design, so when you
> tap on a widget, that should not highlight the component.

Like SingleControl, custom list items may set the value of pressed. Making it read-only will break those custom list items. Of course we cannot be sure that this is (still) happening without checking the code of the apps.

Revision history for this message
Tim Peeters (tpeeters) wrote :

Because it is cpp, the change will affect also 0.1-1.2... so it is dangerous.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote :

Okay, looks good now.

Note that in all import versions we change the RW properties hovered and pressed to read-only. That makes sense (overriding the values of the properties would break the button's functionality), but before it lands we make sure that no apps are setting the properties.

Happroving.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1633. By Zsombor Egri

roll back AbstractButton for versions earlier than 1.3 to avoid API break

Revision history for this message
Cris Dywan (kalikiana) wrote :

Leaving the 1.2 at QML is a good idea that I didn't consider an option. That way we're safe in terms of compatibility. Nice!
Let's see that the tests agree, too.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1634. By Zsombor Egri

documentation fix

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote :

there are some failures:

Test Result (2 failures / ±0)
components.AbstractButtonAPI::test_no_pressAndHold_connected_clicks_bug1365471_bug1458028
components.ListItemsEmptyAPI::test_hovered

1635. By Zsombor Egri

reverting unit test move for API 1.2

1636. By Zsombor Egri

separate 1.3 tests from earlier versions; add 1.3 performance tests

1637. By Zsombor Egri

overridden trigger() function support

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote :

222 === modified file 'src/Ubuntu/Components/ListItems/1.2/Empty.qml'
223 --- src/Ubuntu/Components/ListItems/1.2/Empty.qml 2015-04-30 08:32:44 +0000
224 +++ src/Ubuntu/Components/ListItems/1.2/Empty.qml 2015-08-25 11:31:46 +0000
225 @@ -158,6 +158,10 @@
226 */
227 property real __contentsMargins: units.gu(2)
228
229 + // override pressed and hovered as those were declared writable
230 + property bool pressed: __mouseArea.pressed
231 + property bool hovered: __acceptEvents && __mouseArea.containsMouse
232 +

do we still need this? 1.2 now has the old AbstractButton where those properties are already writable.

1638. By Zsombor Egri

revert unneeded 1.2 changes

Revision history for this message
Cris Dywan (kalikiana) wrote :

Nice!

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'components.api'
--- components.api 2015-08-20 08:10:44 +0000
+++ components.api 2015-08-25 13:10:33 +0000
@@ -4,10 +4,10 @@
4 signal pressAndHold()4 signal pressAndHold()
5 property bool pressed5 property bool pressed
6Ubuntu.Components.AbstractButton 1.3: ActionItem6Ubuntu.Components.AbstractButton 1.3: ActionItem
7 property bool hovered7 readonly property bool hovered
8 signal clicked()8 signal clicked()
9 signal pressAndHold()9 signal pressAndHold()
10 property bool pressed10 readonly property bool pressed
11Ubuntu.Components.Action 1.3 1.0 0.1: QtObject11Ubuntu.Components.Action 1.3 1.0 0.1: QtObject
12 property string description12 property string description
13 property bool enabled13 property bool enabled
1414
=== removed file 'src/Ubuntu/Components/1.3/AbstractButton.qml'
--- src/Ubuntu/Components/1.3/AbstractButton.qml 2015-04-25 08:54:58 +0000
+++ src/Ubuntu/Components/1.3/AbstractButton.qml 1970-01-01 00:00:00 +0000
@@ -1,109 +0,0 @@
1/*
2 * Copyright 2012 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.4
18import Ubuntu.Components 1.3
19
20/*!
21 \qmlabstract AbstractButton
22 \inqmlmodule Ubuntu.Components 1.1
23 \ingroup ubuntu
24 \brief The AbstractButton class defines the behavior of the button.
25
26 This class defines the behavior of the button: it defines the MouseArea
27 and the states.
28 All components deriving from this class support haptic feedback out of the box.
29*/
30ActionItem {
31 id: button
32
33 /*!
34 If an action is specified, the button's clicked signal will trigger the action.
35 Subclasses of AbstractButton can use other properties of action (for example
36 the text and iconName).
37 \qmlproperty Action action
38 */
39
40 /*!
41 This handler is called when there is a mouse click on the button
42 and the button is not disabled. If \b action is defined,
43 the action will be triggered.
44 */
45 signal clicked()
46
47 /*!
48 If a button is clicked, its triggered() signal will automatically be called.
49 */
50 onClicked: button.trigger()
51
52 Keys.onEnterPressed: clicked()
53 Keys.onReturnPressed: clicked()
54
55 /*!
56 This handler is called when there is a long press.
57 */
58 signal pressAndHold()
59
60 /*!
61 True if the user presses a mouse button in the button's mouse area.
62 */
63 property bool pressed: mouseArea.pressed
64
65 /*!
66 True if the mouse cursor hovers over the button's mouse area.
67 */
68 property bool hovered: __acceptEvents && mouseArea.containsMouse
69
70 /*!
71 \internal
72 Disable or enable signal emition by default.
73 Some classes want to emit the signal by themselves (ListItem.Standard)
74 */
75 property bool __acceptEvents: true
76
77 /*!
78 \internal
79 To get the properties of the mouse area in subclasses.
80 */
81 property alias __mouseArea: mouseArea
82
83 activeFocusOnPress: true
84
85 MouseArea {
86 id: mouseArea
87 anchors.fill: parent
88 // if mouseArea is given a new value, disable defaultMouseArea
89 // as it might occlude the newly assigned mouse area.
90 hoverEnabled: true
91
92 // invoke Haptics singleton earlier than we press the button,
93 // so we give some time for the singleton to sync settings with the service
94 property bool hapticsEnabled: Haptics.enabled
95
96 onClicked: {
97 if (button.__acceptEvents) {
98 // FIXME (Vivid) call this in the style rather than from AbstractButton
99 Haptics.play();
100 button.clicked()
101 }
102 }
103 onPressAndHold: {
104 if (button.__acceptEvents) {
105 button.pressAndHold()
106 }
107 }
108 }
109}
1100
=== modified file 'src/Ubuntu/Components/1.3/Button.qml'
--- src/Ubuntu/Components/1.3/Button.qml 2015-05-26 15:05:46 +0000
+++ src/Ubuntu/Components/1.3/Button.qml 2015-08-25 13:10:33 +0000
@@ -105,7 +105,7 @@
105 /*!105 /*!
106 The font used for the button's text.106 The font used for the button's text.
107 */107 */
108 property font font: __styleInstance ? __styleInstance.defaultFont : Qt.font({family: "Ubuntu", pixelSize: FontUtils.sizeToPixels("medium")})108 property font font: __styleInstance.defaultFont
109109
110 /*!110 /*!
111 The position of the icon relative to the text. Options111 The position of the icon relative to the text. Options
112112
=== modified file 'src/Ubuntu/Components/1.3/ComboButton.qml'
--- src/Ubuntu/Components/1.3/ComboButton.qml 2015-05-21 10:50:35 +0000
+++ src/Ubuntu/Components/1.3/ComboButton.qml 2015-08-25 13:10:33 +0000
@@ -15,6 +15,7 @@
15 */15 */
1616
17import QtQuick 2.417import QtQuick 2.4
18import Ubuntu.Components 1.3
18import Ubuntu.Components.Popups 1.319import Ubuntu.Components.Popups 1.3
1920
20/*!21/*!
2122
=== modified file 'src/Ubuntu/Components/1.3/TextField.qml'
--- src/Ubuntu/Components/1.3/TextField.qml 2015-08-18 15:51:43 +0000
+++ src/Ubuntu/Components/1.3/TextField.qml 2015-08-25 13:10:33 +0000
@@ -896,7 +896,7 @@
896 }896 }
897 }897 }
898898
899 AbstractButton {899 Ubuntu.AbstractButton {
900 id: clearButton900 id: clearButton
901 objectName: "clear_button"901 objectName: "clear_button"
902 activeFocusOnPress: false902 activeFocusOnPress: false
903903
=== modified file 'src/Ubuntu/Components/ComponentModule.pro'
--- src/Ubuntu/Components/ComponentModule.pro 2015-08-19 08:57:18 +0000
+++ src/Ubuntu/Components/ComponentModule.pro 2015-08-25 13:10:33 +0000
@@ -80,8 +80,7 @@
80 1.2/UbuntuNumberAnimation.qml80 1.2/UbuntuNumberAnimation.qml
8181
82#1.382#1.3
83QML_FILES += 1.3/AbstractButton.qml \83QML_FILES += 1.3/ActionBar.qml \
84 1.3/ActionBar.qml \
85 1.3/ActionList.qml \84 1.3/ActionList.qml \
86 1.3/ActivityIndicator.qml \85 1.3/ActivityIndicator.qml \
87 1.3/AdaptivePageLayout.qml \86 1.3/AdaptivePageLayout.qml \
8887
=== modified file 'src/Ubuntu/Components/ListItems/1.3/SingleControl.qml'
--- src/Ubuntu/Components/ListItems/1.3/SingleControl.qml 2015-04-29 07:21:29 +0000
+++ src/Ubuntu/Components/ListItems/1.3/SingleControl.qml 2015-08-25 13:10:33 +0000
@@ -54,7 +54,8 @@
5454
55 /*! \internal */55 /*! \internal */
56 onClicked: if (control && control.enabled && control.hasOwnProperty("clicked")) control.clicked()56 onClicked: if (control && control.enabled && control.hasOwnProperty("clicked")) control.clicked()
57 pressed: __mouseArea.pressed || (control && control.hasOwnProperty("pressed") && control.pressed)57 /*! \internal */
58 property bool pressed: __mouseArea.pressed || (control && control.hasOwnProperty("pressed") && control.pressed)
58 /*! \internal */59 /*! \internal */
59 onPressedChanged: if (control && control.enabled && control.hasOwnProperty("pressed")) control.pressed = singleControlListItem.pressed60 onPressedChanged: if (control && control.enabled && control.hasOwnProperty("pressed")) control.pressed = singleControlListItem.pressed
6061
6162
=== modified file 'src/Ubuntu/Components/plugin/plugin.cpp'
--- src/Ubuntu/Components/plugin/plugin.cpp 2015-08-19 08:44:45 +0000
+++ src/Ubuntu/Components/plugin/plugin.cpp 2015-08-25 13:10:33 +0000
@@ -64,6 +64,7 @@
64#include "ucnamespace.h"64#include "ucnamespace.h"
65#include "ucactionitem.h"65#include "ucactionitem.h"
66#include "uchaptics.h"66#include "uchaptics.h"
67#include "ucabstractbutton.h"
6768
68#include <sys/types.h>69#include <sys/types.h>
69#include <unistd.h>70#include <unistd.h>
@@ -232,6 +233,7 @@
232 qmlRegisterType<UCUbuntuShape, 2>(uri, 1, 3, "UbuntuShape");233 qmlRegisterType<UCUbuntuShape, 2>(uri, 1, 3, "UbuntuShape");
233 qmlRegisterType<UCProportionalShape>(uri, 1, 3, "ProportionalShape");234 qmlRegisterType<UCProportionalShape>(uri, 1, 3, "ProportionalShape");
234 qmlRegisterType<LiveTimer>(uri, 1, 3, "LiveTimer");235 qmlRegisterType<LiveTimer>(uri, 1, 3, "LiveTimer");
236 qmlRegisterType<UCAbstractButton>(uri, 1, 3, "AbstractButton");
235}237}
236238
237void UbuntuComponentsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)239void UbuntuComponentsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
238240
=== modified file 'src/Ubuntu/Components/plugin/plugin.pri'
--- src/Ubuntu/Components/plugin/plugin.pri 2015-08-20 11:35:51 +0000
+++ src/Ubuntu/Components/plugin/plugin.pri 2015-08-25 13:10:33 +0000
@@ -82,7 +82,8 @@
82 $$PWD/livetimer_p.h \82 $$PWD/livetimer_p.h \
83 $$PWD/timeutils_p.h \83 $$PWD/timeutils_p.h \
84 $$PWD/ucactionitem.h \84 $$PWD/ucactionitem.h \
85 $$PWD/uchaptics.h85 $$PWD/uchaptics.h \
86 $$PWD/ucabstractbutton.h
8687
87SOURCES += $$PWD/plugin.cpp \88SOURCES += $$PWD/plugin.cpp \
88 $$PWD/uctheme.cpp \89 $$PWD/uctheme.cpp \
@@ -136,7 +137,8 @@
136 $$PWD/livetimer.cpp \137 $$PWD/livetimer.cpp \
137 $$PWD/livetimer_p.cpp \138 $$PWD/livetimer_p.cpp \
138 $$PWD/ucactionitem.cpp \139 $$PWD/ucactionitem.cpp \
139 $$PWD/uchaptics.cpp140 $$PWD/uchaptics.cpp \
141 $$PWD/ucabstractbutton.cpp
140142
141# adapters143# adapters
142SOURCES += $$PWD/adapters/alarmsadapter_organizer.cpp144SOURCES += $$PWD/adapters/alarmsadapter_organizer.cpp
143145
=== added file 'src/Ubuntu/Components/plugin/ucabstractbutton.cpp'
--- src/Ubuntu/Components/plugin/ucabstractbutton.cpp 1970-01-01 00:00:00 +0000
+++ src/Ubuntu/Components/plugin/ucabstractbutton.cpp 2015-08-25 13:10:33 +0000
@@ -0,0 +1,156 @@
1/*
2 * Copyright 2015 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "ucabstractbutton.h"
18#include "uchaptics.h"
19#include <QtQuick/private/qquickitem_p.h>
20#include <QtQuick/private/qquickmousearea_p.h>
21#include <QtQml/private/qqmlglobal_p.h>
22
23/*!
24 \qmltype AbstractButton
25 \instantiates UCAbstractButton
26 \inqmlmodule Ubuntu.Components 1.1
27 \ingroup ubuntu
28 \brief The AbstractButton class defines the behavior of the button.
29
30 This class defines the behavior of the button. All components deriving from
31 this class support haptic feedback out of the box.
32
33 If an action is specified, the button's clicked signal will trigger the action.
34 Subclasses of AbstractButton can use other properties of action (for example
35 the text and iconName).
36*/
37
38/*!
39 *
40 * \qmlsignal AbstractButton::clicked()
41 * This handler is called when there is a mouse click on the button and the button
42 * is not disabled. If \l {ActionItem::action}{action} is defined, the action will be triggered.
43 */
44
45/*!
46 *
47 * \qmlsignal AbstractButton::pressAndHold()
48 * This handler is called when there is a long press.
49 */
50
51UCAbstractButton::UCAbstractButton(QQuickItem *parent)
52 : UCActionItem(parent)
53 , m_mouseArea(new QQuickMouseArea)
54 , m_acceptEvents(true)
55{
56 setActiveFocusOnPress(true);
57}
58
59bool UCAbstractButton::isPressAndHoldConnected()
60{
61 static QMetaMethod method = QMetaMethod::fromSignal(&UCAbstractButton::pressAndHold);
62 static int signalIdx = QMetaObjectPrivate::signalIndex(method);
63 return QObjectPrivate::get(this)->isSignalConnected(signalIdx);
64}
65
66void UCAbstractButton::classBegin()
67{
68 UCActionItem::classBegin();
69
70 // make sure we have the haptics set up!
71 HapticsProxy::instance().initialize();
72
73 // set up mouse area
74 QQml_setParent_noEvent(m_mouseArea, this);
75 m_mouseArea->setParentItem(this);
76 QQuickAnchors *anchors = QQuickItemPrivate::get(m_mouseArea)->anchors();
77 anchors->setFill(this);
78 m_mouseArea->setHoverEnabled(true);
79}
80
81void UCAbstractButton::componentComplete()
82{
83 UCActionItem::componentComplete();
84 // connect to the right slot, using macros so we get the proper slot
85 connect(this, SIGNAL(clicked()), this, SLOT(trigger()));
86
87 // bind mouse area
88 connect(m_mouseArea, &QQuickMouseArea::pressedChanged, this, &UCAbstractButton::pressedChanged);
89 connect(m_mouseArea, &QQuickMouseArea::hoveredChanged, this, &UCAbstractButton::hoveredChanged);
90 connect(m_mouseArea, SIGNAL(clicked(QQuickMouseEvent*)), this, SLOT(_q_mouseAreaClicked()));
91 if (isPressAndHoldConnected()) {
92 connect(m_mouseArea, SIGNAL(pressAndHold(QQuickMouseEvent*)), this, SLOT(_q_mouseAreaPressAndHold()));
93 }
94}
95
96// handle mouseClicked with Haptics
97void UCAbstractButton::_q_mouseAreaClicked()
98{
99 // required by the deprecated ListItem module
100 if (!m_acceptEvents) {
101 return;
102 }
103 // play haptics
104 HapticsProxy::instance().play(QVariant());
105 Q_EMIT clicked();
106}
107
108// handle pressAndHold
109void UCAbstractButton::_q_mouseAreaPressAndHold()
110{
111 // required by the deprecated ListItem module
112 if (!m_acceptEvents) {
113 return;
114 }
115 Q_EMIT pressAndHold();
116}
117
118// emit clicked when Enter/Return is pressed
119void UCAbstractButton::keyPressEvent(QKeyEvent *event)
120{
121 UCActionItem::keyPressEvent(event);
122
123 switch (event->key()) {
124 case Qt::Key_Enter:
125 case Qt::Key_Return:
126 // FIXME: space may also come here, however that depends on the button type
127 // (i.e default Dialog btn) so we may need to add that to Button
128 {
129 Q_EMIT clicked();
130 break;
131 }
132 }
133}
134
135/*!
136 * \qmlproperty bool AbstractButton::pressed
137 * True if the user presses a mouse button in the button's mouse area.
138 */
139bool UCAbstractButton::pressed() const
140{
141 return m_mouseArea ? m_mouseArea->pressed() : false;
142}
143
144/*!
145 * \qmlproperty bool AbstractButton::hovered
146 * True if the mouse cursor hovers over the button's mouse area.
147 */
148bool UCAbstractButton::hovered() const
149{
150 return m_mouseArea ? m_mouseArea->hovered() : false;
151}
152
153QQuickMouseArea *UCAbstractButton::privateMouseArea() const
154{
155 return m_mouseArea;
156}
0157
=== added file 'src/Ubuntu/Components/plugin/ucabstractbutton.h'
--- src/Ubuntu/Components/plugin/ucabstractbutton.h 1970-01-01 00:00:00 +0000
+++ src/Ubuntu/Components/plugin/ucabstractbutton.h 2015-08-25 13:10:33 +0000
@@ -0,0 +1,64 @@
1/*
2 * Copyright 2015 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef UCABSTRACTBUTTON_H
18#define UCABSTRACTBUTTON_H
19
20#include "ucactionitem.h"
21
22class QQuickMouseArea;
23class UCAbstractButton : public UCActionItem
24{
25 Q_OBJECT
26 Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged)
27 Q_PROPERTY(bool hovered READ hovered NOTIFY hoveredChanged)
28
29 // internal, declared to support the deprecated ListItem module
30 Q_PROPERTY(bool __acceptEvents MEMBER m_acceptEvents)
31 Q_PROPERTY(QQuickMouseArea *__mouseArea READ privateMouseArea CONSTANT)
32public:
33 explicit UCAbstractButton(QQuickItem *parent = 0);
34
35 bool pressed() const;
36 bool hovered() const;
37
38 bool privateAcceptEvents() const;
39 void setPrivateAcceptEvents(bool accept);
40 QQuickMouseArea *privateMouseArea() const;
41
42protected:
43 void classBegin();
44 void componentComplete();
45 void keyPressEvent(QKeyEvent *key);
46
47Q_SIGNALS:
48 void pressedChanged();
49 void hoveredChanged();
50 void clicked();
51 void pressAndHold();
52
53protected Q_SLOTS:
54 void _q_mouseAreaClicked();
55 void _q_mouseAreaPressAndHold();
56
57protected:
58 QQuickMouseArea *m_mouseArea;
59 bool m_acceptEvents:1;
60
61 bool isPressAndHoldConnected();
62};
63
64#endif // UCABSTRACTBUTTON_H
065
=== modified file 'src/Ubuntu/Components/plugin/ucaction.cpp'
--- src/Ubuntu/Components/plugin/ucaction.cpp 2015-08-18 15:51:43 +0000
+++ src/Ubuntu/Components/plugin/ucaction.cpp 2015-08-25 13:10:33 +0000
@@ -301,7 +301,8 @@
301 return false;301 return false;
302 }302 }
303303
304 trigger();304 // do not call trigger() directly but invoke, as it may get overridden in QML
305 metaObject()->invokeMethod(this, "trigger");
305 return true;306 return true;
306}307}
307308
308309
=== modified file 'src/Ubuntu/Components/plugin/ucactionitem.cpp'
--- src/Ubuntu/Components/plugin/ucactionitem.cpp 2015-08-19 06:56:56 +0000
+++ src/Ubuntu/Components/plugin/ucactionitem.cpp 2015-08-25 13:10:33 +0000
@@ -44,6 +44,17 @@
44 connect(this, &UCActionItem::enabledChanged, this, &UCActionItem::_q_enabledChanged);44 connect(this, &UCActionItem::enabledChanged, this, &UCActionItem::_q_enabledChanged);
45}45}
4646
47void UCActionItem::componentComplete()
48{
49 UCStyledItemBase::componentComplete();
50 // make sure we connect to the right signals, so we detach and re-attach actions
51 // to make sure the SLOT macro picks up the custom trigger() slot
52 if (m_action) {
53 attachAction(false);
54 attachAction(true);
55 }
56}
57
47void UCActionItem::_q_visibleChanged()58void UCActionItem::_q_visibleChanged()
48{59{
49 m_flags |= CustomVisible;60 m_flags |= CustomVisible;
@@ -96,8 +107,8 @@
96void UCActionItem::attachAction(bool attach)107void UCActionItem::attachAction(bool attach)
97{108{
98 if (attach) {109 if (attach) {
99 connect(this, &UCActionItem::triggered,110 connect(this, SIGNAL(triggered(QVariant)),
100 m_action, &UCAction::triggered, Qt::DirectConnection);111 m_action, SLOT(trigger(QVariant)), Qt::DirectConnection);
101 connect(m_action, &UCAction::visibleChanged,112 connect(m_action, &UCAction::visibleChanged,
102 this, &UCActionItem::_q_updateVisible, Qt::DirectConnection);113 this, &UCActionItem::_q_updateVisible, Qt::DirectConnection);
103 connect(m_action, &UCAction::enabledChanged,114 connect(m_action, &UCAction::enabledChanged,
@@ -115,8 +126,8 @@
115 this, &UCActionItem::iconNameChanged, Qt::DirectConnection);126 this, &UCActionItem::iconNameChanged, Qt::DirectConnection);
116 }127 }
117 } else {128 } else {
118 disconnect(this, &UCActionItem::triggered,129 disconnect(this, SIGNAL(triggered(QVariant)),
119 m_action, &UCAction::triggered);130 m_action, SLOT(trigger(QVariant)));
120 disconnect(m_action, &UCAction::visibleChanged,131 disconnect(m_action, &UCAction::visibleChanged,
121 this, &UCActionItem::_q_updateVisible);132 this, &UCActionItem::_q_updateVisible);
122 disconnect(m_action, &UCAction::enabledChanged,133 disconnect(m_action, &UCAction::enabledChanged,
123134
=== modified file 'src/Ubuntu/Components/plugin/ucactionitem.h'
--- src/Ubuntu/Components/plugin/ucactionitem.h 2015-08-19 06:55:11 +0000
+++ src/Ubuntu/Components/plugin/ucactionitem.h 2015-08-25 13:10:33 +0000
@@ -70,6 +70,8 @@
70 UCAction *m_action;70 UCAction *m_action;
71 quint8 m_flags;71 quint8 m_flags;
7272
73 void componentComplete();
74
73 void updateProperties();75 void updateProperties();
74 void attachAction(bool attach);76 void attachAction(bool attach);
75};77};
7678
=== modified file 'src/Ubuntu/Components/qmldir'
--- src/Ubuntu/Components/qmldir 2015-08-19 08:44:45 +0000
+++ src/Ubuntu/Components/qmldir 2015-08-25 13:10:33 +0000
@@ -115,7 +115,6 @@
115TabBar 1.3 1.3/TabBar.qml115TabBar 1.3 1.3/TabBar.qml
116Tabs 1.3 1.3/Tabs.qml116Tabs 1.3 1.3/Tabs.qml
117Label 1.3 1.3/Label.qml117Label 1.3 1.3/Label.qml
118AbstractButton 1.3 1.3/AbstractButton.qml
119ActivityIndicator 1.3 1.3/ActivityIndicator.qml118ActivityIndicator 1.3 1.3/ActivityIndicator.qml
120ProgressBar 1.3 1.3/ProgressBar.qml119ProgressBar 1.3 1.3/ProgressBar.qml
121TextField 1.3 1.3/TextField.qml120TextField 1.3 1.3/TextField.qml
122121
=== modified file 'tests/unit/tst_components/tst_action.qml'
--- tests/unit/tst_components/tst_action.qml 2015-07-09 17:55:03 +0000
+++ tests/unit/tst_components/tst_action.qml 2015-08-25 13:10:33 +0000
@@ -34,6 +34,11 @@
34 return false;34 return false;
35 }35 }
3636
37 function cleanup() {
38 triggeredSignalSpy.target = action;
39 triggeredSignalSpy.clear();
40 }
41
37 function initTestCase() {42 function initTestCase() {
38 compare(action.text, "", "text is empty string set by default")43 compare(action.text, "", "text is empty string set by default")
39 compare(action.iconSource, "", "iconSource is empty string by default")44 compare(action.iconSource, "", "iconSource is empty string by default")
@@ -132,6 +137,12 @@
132 verify(!data.inactive.active, "Context deactivation error");137 verify(!data.inactive.active, "Context deactivation error");
133 }138 }
134139
140 function test_overloaded_action_trigger() {
141 triggeredSignalSpy.target = suppressTrigger;
142 suppressTrigger.trigger();
143 compare(triggeredSignalSpy.count, 0, "Overloaded trigger should not trigger action");
144 }
145
135 Action {146 Action {
136 id: action147 id: action
137 }148 }
@@ -185,4 +196,9 @@
185 id: context2196 id: context2
186 }197 }
187198
199 Action {
200 id: suppressTrigger
201 function trigger() {}
202 }
203
188}204}
189205
=== added file 'tests/unit/tst_performance/AbstractButton13Grid.qml'
--- tests/unit/tst_performance/AbstractButton13Grid.qml 1970-01-01 00:00:00 +0000
+++ tests/unit/tst_performance/AbstractButton13Grid.qml 2015-08-25 13:10:33 +0000
@@ -0,0 +1,30 @@
1/*
2 * Copyright 2015 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.0
18import Ubuntu.Components 1.3
19
20Grid {
21 width: 800
22 height: 600
23 rows: 16
24 columns: 16
25 Repeater {
26 model: 16*16
27 AbstractButton {
28 }
29 }
30}
031
=== added file 'tests/unit/tst_performance/AbstractButtonGrid.qml'
--- tests/unit/tst_performance/AbstractButtonGrid.qml 1970-01-01 00:00:00 +0000
+++ tests/unit/tst_performance/AbstractButtonGrid.qml 2015-08-25 13:10:33 +0000
@@ -0,0 +1,30 @@
1/*
2 * Copyright 2015 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.0
18import Ubuntu.Components 1.1
19
20Grid {
21 width: 800
22 height: 600
23 rows: 16
24 columns: 16
25 Repeater {
26 model: 16*16
27 AbstractButton {
28 }
29 }
30}
031
=== modified file 'tests/unit/tst_performance/tst_performance.cpp'
--- tests/unit/tst_performance/tst_performance.cpp 2015-04-14 07:41:52 +0000
+++ tests/unit/tst_performance/tst_performance.cpp 2015-08-25 13:10:33 +0000
@@ -102,6 +102,8 @@
102 QTest::addColumn<QString>("document");102 QTest::addColumn<QString>("document");
103 QTest::addColumn<QUrl>("theme");103 QTest::addColumn<QUrl>("theme");
104104
105 QTest::newRow("AbstractButton 1.2") << "AbstractButtonGrid.qml" << QUrl();
106 QTest::newRow("AbstractButton 1.3") << "AbstractButton13Grid.qml" << QUrl();
105 QTest::newRow("grid with Rectangle") << "RectangleGrid.qml" << QUrl();107 QTest::newRow("grid with Rectangle") << "RectangleGrid.qml" << QUrl();
106 QTest::newRow("grid with Text") << "TextGrid.qml" << QUrl();108 QTest::newRow("grid with Text") << "TextGrid.qml" << QUrl();
107 QTest::newRow("grid with Label") << "LabelGrid.qml" << QUrl();109 QTest::newRow("grid with Label") << "LabelGrid.qml" << QUrl();
108110
=== modified file 'tests/unit/tst_performance/tst_performance.pro'
--- tests/unit/tst_performance/tst_performance.pro 2015-04-01 08:33:53 +0000
+++ tests/unit/tst_performance/tst_performance.pro 2015-08-25 13:10:33 +0000
@@ -30,4 +30,6 @@
30 Styling.qml \30 Styling.qml \
31 PaletteConfigurationOneColor.qml \31 PaletteConfigurationOneColor.qml \
32 PaletteConfigurationAllColors.qml \32 PaletteConfigurationAllColors.qml \
33 StyledItemNewTheming.qml33 StyledItemNewTheming.qml \
34 AbstractButtonGrid.qml \
35 AbstractButton13Grid.qml
3436
=== added file 'tests/unit_x11/tst_components/tst_abstractbutton13.qml'
--- tests/unit_x11/tst_components/tst_abstractbutton13.qml 1970-01-01 00:00:00 +0000
+++ tests/unit_x11/tst_components/tst_abstractbutton13.qml 2015-08-25 13:10:33 +0000
@@ -0,0 +1,115 @@
1/*
2 * Copyright 2012 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.0
18import QtTest 1.0
19import Ubuntu.Test 1.0
20import Ubuntu.Components 1.3
21
22Item {
23 width: units.gu(40)
24 height: units.gu(71)
25
26 Column {
27 AbstractButton {
28 id: absButton
29 width: units.gu(10)
30 height: units.gu(10)
31 }
32 AbstractButton {
33 id: absLongTap
34 width: units.gu(10)
35 height: width
36 onPressAndHold: {}
37 }
38 AbstractButton {
39 id: suppressTrigger
40 width: units.gu(10)
41 height: width
42 function trigger() {}
43 }
44 }
45
46 Action {
47 id: action1
48 property int triggerCount: 0
49 onTriggered: triggerCount++
50 }
51
52 SignalSpy {
53 id: signalSpy
54 target: absButton
55 signalName: "clicked"
56 }
57
58 SignalSpy {
59 id: pressAndHoldSpy
60 target: absLongTap
61 signalName: "pressAndHold"
62 }
63
64 SignalSpy {
65 id: triggeredSpy
66 signalName: "triggered"
67 }
68
69 UbuntuTestCase {
70 name: "AbstractButtonAPI"
71 when: windowShown
72
73 function cleanup() {
74 signalSpy.clear();
75 triggeredSpy.clear();
76 }
77
78 function test_action() {
79 compare(absButton.action, null,"Action is null by default")
80 absButton.action = action1
81 compare(absButton.action, action1, "Action can be set")
82 var numTriggers = action1.triggerCount
83 absButton.clicked()
84 compare(action1.triggerCount, numTriggers+1, "Button clicked triggers action")
85 absButton.action = null
86 }
87
88 function test_custom_trigger_function() {
89 suppressTrigger.action = action1;
90 triggeredSpy.target = action1;
91 mouseClick(suppressTrigger, centerOf(suppressTrigger).x, centerOf(suppressTrigger).y);
92 compare(triggeredSpy.count, 0, "Trigger should be overridden");
93 }
94
95 // fixing bugs 1365471 and 1458028
96 function test_no_pressAndHold_connected_clicks_bug1365471_bug1458028() {
97 signalSpy.target = absButton;
98 mouseLongPress(absButton, centerOf(absButton).x, centerOf(absButton).y);
99 mouseRelease(absButton, centerOf(absButton).x, centerOf(absButton).y);
100 signalSpy.wait();
101 }
102
103 // fixing bugs 1365471 and 1458028
104 function test_pressAndHold_connected_suppresses_clicks_bug1365471_bug1458028() {
105 function testFunc() {}
106 signalSpy.target = absButton;
107 absLongTap.pressAndHold.connect(testFunc);
108 mouseLongPress(absLongTap, centerOf(absLongTap).x, centerOf(absLongTap).y);
109 absLongTap.pressAndHold.disconnect(testFunc);
110 pressAndHoldSpy.wait();
111 mouseRelease(absLongTap, centerOf(absLongTap).x, centerOf(absLongTap).y);
112 compare(signalSpy.count, 0, "click() must be suppressed when pressAndHold handler is implemented");
113 }
114 }
115}

Subscribers

People subscribed via source and target branches