on xenial help sign in
Merge lp:unity8
f469362Albert Astals
Bottombar/Bottombar.qml+3−3
@@ -16,10 +16,10 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import "../Components"
18import "../Components"
19−import "../Components/Math.js" as MathLocal
20import Unity 0.1
19import Unity 0.1
21import Unity.Application 0.1
20import Unity.Application 0.1
22import Ubuntu.Gestures 0.1
21import Ubuntu.Gestures 0.1
22+import Ubuntu.Components 0.1
23
23
24Item {
24Item {
25 id: bottombar
25 id: bottombar
@@ -82,7 +82,7 @@ Item {
82
82
83 readonly property bool centeredHud: parent.width < units.gu(68) // Nexus 7 has 67 gu width
83 readonly property bool centeredHud: parent.width < units.gu(68) // Nexus 7 has 67 gu width
84
84
85− x: centeredHud ? parent.width / 2 - width / 2 : MathLocal.clamp(dragArea.touchStartX - (width / 2), 0, bottombar.width - width)
85+ x: centeredHud ? parent.width / 2 - width / 2 : MathUtils.clamp(dragArea.touchStartX - (width / 2), 0, bottombar.width - width)
86 y: bottombar.height - bottomEdgeButtonCenterDistance - (height / 2) - bottomMargin
86 y: bottombar.height - bottomEdgeButtonCenterDistance - (height / 2) - bottomMargin
87 z: 1
87 z: 1
88 visible: opacity != 0
88 visible: opacity != 0
@@ -136,7 +136,7 @@ Item {
136 readonly property real distanceFromThreshold: (-distance) - distanceThreshold // distance is negative
136 readonly property real distanceFromThreshold: (-distance) - distanceThreshold // distance is negative
137 readonly property real revealDistance: units.gu(2)
137 readonly property real revealDistance: units.gu(2)
138 readonly property real commitDistance: units.gu(6)
138 readonly property real commitDistance: units.gu(6)
139− readonly property real commitProgress: MathLocal.clamp(distanceFromThreshold / commitDistance, 0, 1)
139+ readonly property real commitProgress: MathUtils.clamp(distanceFromThreshold / commitDistance, 0, 1)
140
140
141 onStatusChanged: {
141 onStatusChanged: {
142 if (status === DirectionalDragArea.WaitingForTouch) {
142 if (status === DirectionalDragArea.WaitingForTouch) {
Components/DragHandle.qml+1−2
@@ -17,7 +17,6 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19import Ubuntu.Gestures 0.1
19import Ubuntu.Gestures 0.1
20−import "Math.js" as MathLocal
21
20
22/*
21/*
23 Put a DragHandle inside a Showable to enable the user to drag it from that handle.
22 Put a DragHandle inside a Showable to enable the user to drag it from that handle.
@@ -117,7 +116,7 @@ EdgeDragArea {
117 }
116 }
118
117
119 function limitMovement(inputStep) {
118 function limitMovement(inputStep) {
120− var targetValue = MathLocal.clamp(dragParent[targetProp] + inputStep, minValue, maxValue);
119+ var targetValue = MathUtils.clamp(dragParent[targetProp] + inputStep, minValue, maxValue);
121 var step = targetValue - dragParent[targetProp];
120 var step = targetValue - dragParent[targetProp];
122
121
123 if (hintDisplacement == 0) {
122 if (hintDisplacement == 0) {
Components/DraggingArea.qml+1−2
@@ -16,7 +16,6 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19−import "Math.js" as MathLocal
20
19
21MouseArea {
20MouseArea {
22 id: draggingArea
21 id: draggingArea
@@ -26,7 +25,7 @@ MouseArea {
26 property real dragVelocity: 0
25 property real dragVelocity: 0
27 property real dragValue: (orientation == Qt.Vertical ? (mouseY - __pressedPosition.y)
26 property real dragValue: (orientation == Qt.Vertical ? (mouseY - __pressedPosition.y)
28 : (mouseX - __pressedPosition.x))
27 : (mouseX - __pressedPosition.x))
29− property real lateralPosition: orientation == Qt.Horizontal ? MathLocal.clamp(mouseY, 0, height) : MathLocal.clamp(mouseX, 0, width)
28+ property real lateralPosition: orientation == Qt.Horizontal ? MathUtils.clamp(mouseY, 0, height) : MathUtils.clamp(mouseX, 0, width)
30 property point __pressedPosition: Qt.point(0, 0)
29 property point __pressedPosition: Qt.point(0, 0)
31 property var __dragEvents: []
30 property var __dragEvents: []
32 property bool clickValidated: true
31 property bool clickValidated: true
Components/EdgeDemoOverlay.qml+2
@@ -105,6 +105,8 @@ Showable {
105 visible: overlay.active
105 visible: overlay.active
106
106
107 MouseArea {
107 MouseArea {
108+ objectName: "backgroundShadeMouseArea"
109+
108 anchors.fill: parent
110 anchors.fill: parent
109 enabled: overlay.edge == "none" && overlay.opacity == 1.0
111 enabled: overlay.edge == "none" && overlay.opacity == 1.0
110 onClicked: overlay.doSkip()
112 onClicked: overlay.doSkip()
Components/Revealer.qml+1−2
@@ -16,7 +16,6 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19−import "Math.js" as MathLocal
20
19
21Item {
20Item {
22 id: revealer
21 id: revealer
@@ -95,7 +94,7 @@ Item {
95 onClosedValueChanged: if (!__opened && !dragging) target[boundProperty] = closedValue
94 onClosedValueChanged: if (!__opened && !dragging) target[boundProperty] = closedValue
96
95
97 function __computeValue(dragPosition) {
96 function __computeValue(dragPosition) {
98− return MathLocal.clamp(dragToValue(dragPosition), __hintValue, openedValue)
97+ return MathUtils.clamp(dragToValue(dragPosition), __hintValue, openedValue)
99 }
98 }
100
99
101 function __open() {
100 function __open() {
Greeter/Greeter.qml+1−2
@@ -19,7 +19,6 @@ import Ubuntu.Components 0.1
19import Ubuntu.Gestures 0.1
19import Ubuntu.Gestures 0.1
20import LightDM 0.1 as LightDM
20import LightDM 0.1 as LightDM
21import "../Components"
21import "../Components"
22−import "../Components/Math.js" as MathLocal
23
22
24Showable {
23Showable {
25 id: greeter
24 id: greeter
@@ -29,7 +28,7 @@ Showable {
29 property url defaultBackground
28 property url defaultBackground
30
29
31 // 1 when fully shown and 0 when fully hidden
30 // 1 when fully shown and 0 when fully hidden
32− property real showProgress: MathLocal.clamp((width + x) / width, 0, 1)
31+ property real showProgress: MathUtils.clamp((width + x) / width, 0, 1)
33
32
34 showAnimation: StandardAnimation { property: "x"; to: 0 }
33 showAnimation: StandardAnimation { property: "x"; to: 0 }
35 hideAnimation: StandardAnimation { property: "x"; to: -width }
34 hideAnimation: StandardAnimation { property: "x"; to: -width }
Greeter/GreeterContent.qml+11−11
@@ -74,17 +74,6 @@ MouseArea {
74 opacity: 0.4
74 opacity: 0.4
75 }
75 }
76
76
77− Clock {
78− id: clock
79− visible: narrowMode
80−
81− anchors {
82− top: parent.top
83− topMargin: units.gu(2)
84− horizontalCenter: parent.horizontalCenter
85− }
86− }
87−
88 MouseArea {
77 MouseArea {
89 id: teasingMouseArea
78 id: teasingMouseArea
90 anchors.fill: parent
79 anchors.fill: parent
@@ -163,4 +152,15 @@ MouseArea {
163 right: root.right
152 right: root.right
164 }
153 }
165 }
154 }
155+
156+ Clock {
157+ id: clock
158+ visible: narrowMode
159+
160+ anchors {
161+ top: parent.top
162+ topMargin: units.gu(2)
163+ horizontalCenter: parent.horizontalCenter
164+ }
165+ }
166}
166}
Panel/Indicators.qml+1−2
@@ -21,7 +21,6 @@ import Unity.Indicators 0.1 as Indicators
21
21
22import "../Components"
22import "../Components"
23import "../Components/ListItems"
23import "../Components/ListItems"
24−import "../Components/Math.js" as MathLocal
25
24
26Showable {
25Showable {
27 id: indicators
26 id: indicators
@@ -100,7 +99,7 @@ Showable {
100 Otherwise it contains the bar's location as a fraction of the distance between hintValue (is 0) and lockThreshold (is 1).
99 Otherwise it contains the bar's location as a fraction of the distance between hintValue (is 0) and lockThreshold (is 1).
101 */
100 */
102 var verticalProgress =
101 var verticalProgress =
103− MathLocal.clamp((indicators.height - handle.height - hintValue) /
102+ MathUtils.clamp((indicators.height - handle.height - hintValue) /
104 (lockThreshold - hintValue), 0, 1);
103 (lockThreshold - hintValue), 0, 1);
105
104
106 /*
105 /*
Panel/Indicators/DefaultIndicatorWidget.qml+32−10
@@ -24,7 +24,7 @@ import Unity.Indicators 0.1 as Indicators
24Indicators.IndicatorWidget {
24Indicators.IndicatorWidget {
25 id: indicatorWidget
25 id: indicatorWidget
26
26
27− width: itemRow.width + units.gu(0.5)
27+ width: itemRow.width
28
28
29 property alias leftLabel: itemLeftLabel.text
29 property alias leftLabel: itemLeftLabel.text
30 property alias rightLabel: itemRightLabel.text
30 property alias rightLabel: itemRightLabel.text
@@ -32,16 +32,17 @@ Indicators.IndicatorWidget {
32
32
33 Row {
33 Row {
34 id: itemRow
34 id: itemRow
35+ width: childrenRect.width
35 objectName: "itemRow"
36 objectName: "itemRow"
36 anchors {
37 anchors {
37 top: parent.top
38 top: parent.top
38 bottom: parent.bottom
39 bottom: parent.bottom
39 horizontalCenter: parent.horizontalCenter
40 horizontalCenter: parent.horizontalCenter
40 }
41 }
41− spacing: units.gu(0.5)
42
42
43 Label {
43 Label {
44 id: itemLeftLabel
44 id: itemLeftLabel
45+ width: guRoundUp(implicitWidth)
45 objectName: "leftLabel"
46 objectName: "leftLabel"
46 color: Theme.palette.selected.backgroundText
47 color: Theme.palette.selected.backgroundText
47 opacity: 0.8
48 opacity: 0.8
@@ -57,25 +58,35 @@ Indicators.IndicatorWidget {
57 top: parent.top
58 top: parent.top
58 bottom: parent.bottom
59 bottom: parent.bottom
59 }
60 }
60− spacing: units.gu(0.5)
61
61
62 Repeater {
62 Repeater {
63 model: indicatorWidget.icons
63 model: indicatorWidget.icons
64
64
65− Image {
65+ Item {
66− id: itemImage
66+ width: guRoundUp(itemImage.width)
67− objectName: "itemImage"
68− visible: source != ""
69− source: modelData
70 height: indicatorWidget.iconSize
67 height: indicatorWidget.iconSize
68+
69+ Image {
70+ id: itemImage
71+ objectName: "itemImage"
72+ visible: source != ""
73+ source: modelData
74+ height: parent.height
75+ anchors.horizontalCenter: parent.horizontalCenter
76+ fillMode: Image.PreserveAspectFit
77+
78+ sourceSize {
71− width: indicatorWidget.iconSize
79+ width: indicatorWidget.iconSize
72− anchors.verticalCenter: parent.verticalCenter
80+ height: indicatorWidget.iconSize
81+ }
82+ }
73 }
83 }
74 }
84 }
75 }
85 }
76
86
77 Label {
87 Label {
78 id: itemRightLabel
88 id: itemRightLabel
89+ width: guRoundUp(implicitWidth)
79 objectName: "rightLabel"
90 objectName: "rightLabel"
80 color: Theme.palette.selected.backgroundText
91 color: Theme.palette.selected.backgroundText
81 opacity: 0.8
92 opacity: 0.8
@@ -86,6 +97,17 @@ Indicators.IndicatorWidget {
86 }
97 }
87 }
98 }
88
99
100+ // TODO: Use toolkit function https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1242575
101+ function guRoundUp(width) {
102+ if (width == 0) {
103+ return 0;
104+ }
105+ var gu1 = units.gu(1.0);
106+ var mod = (width % gu1);
107+
108+ return mod == 0 ? width : width + (gu1 - mod);
109+ }
110+
89 onRootActionStateChanged: {
111 onRootActionStateChanged: {
90 if (rootActionState == undefined) {
112 if (rootActionState == undefined) {
91 leftLabel = "";
113 leftLabel = "";
Shell.qml+1−2
@@ -30,7 +30,6 @@ import "Launcher"
30import "Panel"
30import "Panel"
31import "Hud"
31import "Hud"
32import "Components"
32import "Components"
33−import "Components/Math.js" as MathLocal
34import "Bottombar"
33import "Bottombar"
35import "SideStage"
34import "SideStage"
36import "Notifications"
35import "Notifications"
@@ -237,7 +236,7 @@ FocusScope {
237 Behavior on x {SmoothedAnimation{velocity: 600}}
236 Behavior on x {SmoothedAnimation{velocity: 600}}
238
237
239 property real showProgress:
238 property real showProgress:
240− MathLocal.clamp(1 - (x + stages.x) / shell.width, 0, 1)
239+ MathUtils.clamp(1 - (x + stages.x) / shell.width, 0, 1)
241
240
242 Showable {
241 Showable {
243 id: stages
242 id: stages
plugins/Unity/Indicators/qml/IndicatorWidget.qml+1−1
@@ -24,5 +24,5 @@ IndicatorBase {
24 id: indicatorWidget
24 id: indicatorWidget
25
25
26 enabled: false
26 enabled: false
27− property int iconSize: height - units.gu(0.5)
27+ property int iconSize: height
28}
28}
plugins/Unity/Indicators/unitymenumodelstack.cpp+98−7
@@ -19,6 +19,64 @@
19
19
20#include "unitymenumodelstack.h"
20#include "unitymenumodelstack.h"
21
21
22+#include <QDebug>
23+#include <unitymenumodel.h>
24+
25+class UnityMenuModelEntry : public QObject {
26+ Q_OBJECT
27+public:
28+ UnityMenuModelEntry(UnityMenuModel* model, UnityMenuModel* parentModel, int index)
29+ : m_model(model),
30+ m_parentModel(parentModel),
31+ m_index(index)
32+ {
33+ if (m_parentModel) {
34+ QObject::connect(m_parentModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(onRowsInserted(QModelIndex, int, int)));
35+ QObject::connect(m_parentModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(onRowsRemoved(QModelIndex, int, int)));
36+ QObject::connect(m_parentModel, SIGNAL(modelReset()), this, SLOT(onModelReset()));
37+ }
38+ }
39+
40+ UnityMenuModel* model() const { return m_model; }
41+
42+private Q_SLOTS:
43+ void onRowsInserted(const QModelIndex&, int start, int end)
44+ {
45+ int delta = end-start + 1;
46+ if (start <= m_index) {
47+ m_index += delta;
48+ }
49+ }
50+
51+ void onRowsRemoved(const QModelIndex&, int start, int end)
52+ {
53+ int delta = end-start + 1;
54+ if (start <= m_index) {
55+ if (start + delta > m_index) {
56+ // in the range removed
57+ Q_EMIT remove();
58+ disconnect(m_parentModel, 0, this, 0);
59+ } else {
60+ m_index -= delta;
61+ }
62+ }
63+ }
64+
65+ void onModelReset()
66+ {
67+ Q_EMIT remove();
68+ disconnect(m_parentModel, 0, this, 0);
69+ }
70+
71+Q_SIGNALS:
72+ void remove();
73+
74+private:
75+ UnityMenuModel* m_model;
76+ UnityMenuModel* m_parentModel;
77+ int m_index;
78+};
79+
22UnityMenuModelStack::UnityMenuModelStack(QObject* parent)
80UnityMenuModelStack::UnityMenuModelStack(QObject* parent)
23 : QObject(parent)
81 : QObject(parent)
24{
82{
@@ -26,31 +84,44 @@ UnityMenuModelStack::UnityMenuModelStack(QObject* parent)
26
84
27UnityMenuModelStack::~UnityMenuModelStack()
85UnityMenuModelStack::~UnityMenuModelStack()
28{
86{
87+ qDeleteAll(m_menuModels);
88+ m_menuModels.clear();
29}
89}
30
90
31UnityMenuModel* UnityMenuModelStack::head() const
91UnityMenuModel* UnityMenuModelStack::head() const
32{
92{
33− return !m_menuModels.isEmpty() ? m_menuModels.first() : NULL;
93+ return !m_menuModels.isEmpty() ? m_menuModels.first()->model() : NULL;
34}
94}
35
95
36void UnityMenuModelStack::setHead(UnityMenuModel* model)
96void UnityMenuModelStack::setHead(UnityMenuModel* model)
37{
97{
38 if (head() != model) {
98 if (head() != model) {
99+ qDeleteAll(m_menuModels);
39 m_menuModels.clear();
100 m_menuModels.clear();
101+
40− push(model);
102+ push(model, 0);
41 Q_EMIT headChanged(model);
103 Q_EMIT headChanged(model);
42 }
104 }
43}
105}
44
106
45UnityMenuModel* UnityMenuModelStack::tail() const
107UnityMenuModel* UnityMenuModelStack::tail() const
46{
108{
47− return !m_menuModels.isEmpty() ? m_menuModels.last() : NULL;
109+ return !m_menuModels.isEmpty() ? m_menuModels.last()->model() : NULL;
110+}
111+
112+int UnityMenuModelStack::count() const
113+{
114+ return m_menuModels.count();
48}
115}
49
116
50−void UnityMenuModelStack::push(UnityMenuModel* model)
117+void UnityMenuModelStack::push(UnityMenuModel* model, int index)
51{
118{
119+ UnityMenuModelEntry* entry = new UnityMenuModelEntry(model, tail(), index);
120+ QObject::connect(entry, SIGNAL(remove()), SLOT(onRemove()));
121+
52− m_menuModels << model;
122+ m_menuModels << entry;
53 Q_EMIT tailChanged(model);
123 Q_EMIT tailChanged(model);
124+ Q_EMIT countChanged(m_menuModels.count());
54}
125}
55
126
56UnityMenuModel* UnityMenuModelStack::pop()
127UnityMenuModel* UnityMenuModelStack::pop()
@@ -58,12 +129,32 @@ UnityMenuModel* UnityMenuModelStack::pop()
58 if (m_menuModels.isEmpty()) {
129 if (m_menuModels.isEmpty()) {
59 return NULL;
130 return NULL;
60 }
131 }
61− UnityMenuModel* model = m_menuModels.takeLast();
132+ UnityMenuModelEntry* entry = m_menuModels.takeLast();
133+ UnityMenuModel* model = entry->model();
134+ entry->deleteLater();
62
135
63 Q_EMIT tailChanged(tail());
136 Q_EMIT tailChanged(tail());
64 if (m_menuModels.isEmpty()) {
137 if (m_menuModels.isEmpty()) {
65 Q_EMIT headChanged(NULL);
138 Q_EMIT headChanged(NULL);
66 }
139 }
140+ Q_EMIT countChanged(m_menuModels.count());
67
141
68 return model;
142 return model;
69−}
143+}
144+
145+void UnityMenuModelStack::onRemove()
146+{
147+ UnityMenuModelEntry* removed = qobject_cast<UnityMenuModelEntry*>(sender());
148+ if (!m_menuModels.contains(removed))
149+ return;
150+
151+ for (int i = m_menuModels.count() -1; i >= 0; i--) {
152+ UnityMenuModelEntry* entry = m_menuModels[i];
153+ pop();
154+ if (entry == removed) {
155+ break;
156+ }
157+ }
158+}
159+
160+#include "unitymenumodelstack.moc"
plugins/Unity/Indicators/unitymenumodelstack.h+10−2
@@ -25,6 +25,7 @@
25#include <QObject>
25#include <QObject>
26#include <QList>
26#include <QList>
27
27
28+class UnityMenuModelEntry;
28class UnityMenuModel;
29class UnityMenuModel;
29
30
30// A LIFO queue for storing the current submenu of a UnityMenuModel.
31// A LIFO queue for storing the current submenu of a UnityMenuModel.
@@ -37,6 +38,7 @@ class UNITYINDICATORS_EXPORT UnityMenuModelStack : public QObject
37 Q_OBJECT
38 Q_OBJECT
38 Q_PROPERTY(UnityMenuModel* head READ head WRITE setHead NOTIFY headChanged)
39 Q_PROPERTY(UnityMenuModel* head READ head WRITE setHead NOTIFY headChanged)
39 Q_PROPERTY(UnityMenuModel* tail READ tail NOTIFY tailChanged)
40 Q_PROPERTY(UnityMenuModel* tail READ tail NOTIFY tailChanged)
41+ Q_PROPERTY(int count READ count NOTIFY countChanged)
40public:
42public:
41 UnityMenuModelStack(QObject*parent=NULL);
43 UnityMenuModelStack(QObject*parent=NULL);
42 ~UnityMenuModelStack();
44 ~UnityMenuModelStack();
@@ -46,15 +48,21 @@ public:
46
48
47 UnityMenuModel* tail() const;
49 UnityMenuModel* tail() const;
48
50
51+ int count() const;
52+
49− Q_INVOKABLE void push(UnityMenuModel* model);
53+ Q_INVOKABLE void push(UnityMenuModel* model, int menuIndex);
50 Q_INVOKABLE UnityMenuModel* pop();
54 Q_INVOKABLE UnityMenuModel* pop();
51
55
52Q_SIGNALS:
56Q_SIGNALS:
53 void headChanged(UnityMenuModel* head);
57 void headChanged(UnityMenuModel* head);
54 void tailChanged(UnityMenuModel* tail);
58 void tailChanged(UnityMenuModel* tail);
59+ void countChanged(int count);
60+
61+private Q_SLOTS:
62+ void onRemove();
55
63
56private:
64private:
57− QList<UnityMenuModel*> m_menuModels;
65+ QList<UnityMenuModelEntry*> m_menuModels;
58};
66};
59
67
60#endif // UNITYMENUMODELSTACK_H
68#endif // UNITYMENUMODELSTACK_H
tests/mocks/QMenuModel/CMakeLists.txt+23
@@ -9,3 +9,26 @@ add_custom_target(QMenuModelQmlFiles ALL
9 COMMAND cp ${QMLFILES} ${CMAKE_CURRENT_BINARY_DIR}
9 COMMAND cp ${QMLFILES} ${CMAKE_CURRENT_BINARY_DIR}
10 DEPENDS ${QMLFILES}
10 DEPENDS ${QMLFILES}
11)
11)
12+
13+include_directories(
14+ ${Qt5Core_INCLUDE_DIRS}
15+ ${Qt5Quick_INCLUDE_DIRS}
16+)
17+
18+set(QMenuModelQml_SOURCES
19+ actionstateparser.cpp
20+ plugin.cpp
21+ unitymenumodel.cpp
22+)
23+
24+add_library(QMenuModelQml SHARED ${QMenuModelQml_SOURCES})
25+target_link_libraries(QMenuModelQml
26+ ${Qt5Core_LIBRARIES}
27+ ${Qt5Quick_LIBRARIES}
28+)
29+
30+qt5_use_modules(QMenuModelQml Core Quick)
31+
32+set_target_properties(QMenuModelQml PROPERTIES
33+ OUTPUT_NAME qmenumodel
34+ VERSION 0)
Components/Math.js → tests/mocks/QMenuModel/UnityMenuAction.qmlrenamed+12−8
@@ -12,15 +12,19 @@
12 *
12 *
13 * You should have received a copy of the GNU General Public License
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Nick Dedekind <nick.dedekind@canonical.com>
15 */
18 */
16
19
17−.pragma library
20+import QtQuick 2.0
21+import QMenuModel 0.1
22+
23+QtObject {
24+ property string name
25+ property UnityMenuModel model
26+ property int index
18
27
19−function clamp(value, min, max) {
28+ readonly property var state: undefined
20− if (min <= max) {
29+ readonly property bool valid: false
21− return Math.max(min, Math.min(max, value))
22− } else {
23− // swap min/max if min > max
24− return clamp(value, max, min)
25− }
26}
30}
tests/mocks/QMenuModel/UnityMenuModel.qml → tests/mocks/QMenuModel/actionstateparser.cpprenamed+3−10
@@ -1,9 +1,6 @@
1/*
1/*
2 * Copyright (C) 2013 Canonical, Ltd.
2 * Copyright (C) 2013 Canonical, Ltd.
3 *
3 *
4− * Authors:
5− * Mirco Müller <mirco.mueller@canonical.com>
6− *
7 * This program is free software; you can redistribute it and/or modify
4 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
5 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 3.
6 * the Free Software Foundation; version 3.
@@ -15,12 +12,8 @@
15 *
12 *
16 * You should have received a copy of the GNU General Public License
13 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
18 */
17 */
19
18
20−import QtQuick 2.0
19+#include "actionstateparser.h"
21−
22−QtObject {
23− property variant busName
24− property variant actions
25− property variant menuObjectPath
26−}
tests/mocks/QMenuModel/actionstateparser.hnew file+35
@@ -0,0 +1,35 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+#ifndef MOCK_ACTIONSTATEPARSER_H
20+#define MOCK_ACTIONSTATEPARSER_H
21+
22+#include <QObject>
23+#include <QVariant>
24+
25+typedef struct _GVariant GVariant;
26+
27+class Q_DECL_EXPORT ActionStateParser : public QObject
28+{
29+ Q_OBJECT
30+public:
31+ ActionStateParser(QObject* parent = 0):QObject(parent) {}
32+ virtual QVariant toQVariant(GVariant*) const { return QVariant(); }
33+};
34+
35+#endif // MOCK_ACTIONSTATEPARSER_H
tests/mocks/QMenuModel/plugin.cppnew file+30
@@ -0,0 +1,30 @@
1+/*
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+#include "plugin.h"
20+#include "unitymenumodel.h"
21+#include "actionstateparser.h"
22+
23+#include <QtQml>
24+
25+void QMenuModelPlugin::registerTypes(const char *uri)
26+{
27+ Q_ASSERT(uri == QLatin1String("QMenuModel"));
28+ qmlRegisterType<UnityMenuModel>(uri, 0, 1, "UnityMenuModel");
29+ qmlRegisterType<ActionStateParser>(uri, 0, 1, "ActionStateParser");
30+}
tests/mocks/QMenuModel/plugin.hnew file+34
@@ -0,0 +1,34 @@
1+/*
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+#ifndef MOCK_QMENUMODEL_PLUGIN_H
20+#define MOCK_QMENUMODEL_PLUGIN_H
21+
22+#include <QQmlEngine>
23+#include <QQmlExtensionPlugin>
24+
25+class QMenuModelPlugin : public QQmlExtensionPlugin
26+{
27+ Q_OBJECT
28+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
29+
30+public:
31+ void registerTypes(const char *uri);
32+};
33+
34+#endif
tests/mocks/QMenuModel/qmldir+3−1
@@ -1,3 +1,5 @@
1module QMenuModel
1module QMenuModel
2+plugin qmenumodel
3+
2QDBusActionGroup 0.1 QDBusActionGroup.qml
4QDBusActionGroup 0.1 QDBusActionGroup.qml
3−UnityMenuModel 0.1 UnityMenuModel.qml
5+UnityMenuAction 0.1 UnityMenuAction.qml
tests/mocks/QMenuModel/unitymenumodel.cppnew file+239
@@ -0,0 +1,239 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+#include "unitymenumodel.h"
20+#include <QDebug>
21+
22+enum MenuRoles {
23+ LabelRole = Qt::DisplayRole + 1,
24+ SensitiveRole,
25+ IsSeparatorRole,
26+ IconRole,
27+ TypeRole,
28+ ExtendedAttributesRole,
29+ ActionRole,
30+ ActionStateRole,
31+ IsCheckRole,
32+ IsRadioRole,
33+ IsToggledRole
34+};
35+
36+UnityMenuModel::UnityMenuModel(QObject *parent)
37+: QAbstractListModel(parent)
38+{
39+}
40+
41+QVariant UnityMenuModel::modelData() const
42+{
43+ return m_modelData;
44+}
45+
46+void UnityMenuModel::setModelData(const QVariant& data)
47+{
48+ beginResetModel();
49+
50+ m_modelData.clear();
51+ m_modelData = data.toList();
52+
53+ endResetModel();
54+}
55+
56+
57+void UnityMenuModel::insertRow(int row, const QVariant& data)
58+{
59+ row = qMin(row, rowCount());
60+
61+ beginInsertRows(QModelIndex(), row, row);
62+
63+ m_modelData.insert(row, data);
64+
65+ endInsertRows();
66+}
67+
68+void UnityMenuModel::appendRow(const QVariant& data)
69+{
70+ insertRow(rowCount(), data);
71+}
72+
73+void UnityMenuModel::removeRow(int row)
74+{
75+ if (row < 0 || rowCount() <= row) {
76+ return;
77+ }
78+
79+ beginRemoveRows(QModelIndex(), row, row);
80+
81+ m_modelData.removeAt(row);
82+
83+ endRemoveRows();
84+}
85+
86+UnityMenuModel::~UnityMenuModel()
87+{
88+}
89+
90+QByteArray UnityMenuModel::busName() const
91+{
92+ return m_busName;
93+}
94+
95+void UnityMenuModel::setBusName(const QByteArray &busName)
96+{
97+ this->m_busName = busName;
98+}
99+
100+QVariantMap UnityMenuModel::actions() const
101+{
102+ return m_actions;
103+}
104+
105+void UnityMenuModel::setActions(const QVariantMap &actions)
106+{
107+ this->m_actions = actions;
108+}
109+
110+QByteArray UnityMenuModel::menuObjectPath() const
111+{
112+ return m_menuObjectPath;
113+}
114+
115+void UnityMenuModel::setMenuObjectPath(const QByteArray &path)
116+{
117+ this->m_menuObjectPath = path;
118+}
119+
120+ActionStateParser* UnityMenuModel::actionStateParser() const
121+{
122+ return NULL;
123+}
124+
125+void UnityMenuModel::setActionStateParser(ActionStateParser*)
126+{
127+}
128+
129+int UnityMenuModel::rowCount(const QModelIndex&) const
130+{
131+ return m_modelData.count();
132+}
133+
134+int UnityMenuModel::columnCount(const QModelIndex&) const
135+{
136+ return 1;
137+}
138+
139+QVariant UnityMenuModel::data(const QModelIndex &index, int role) const
140+{
141+ return rowData(index.row())[roleNames()[role]];
142+}
143+
144+QVariantMap UnityMenuModel::rowData(int row) const
145+{
146+ return m_modelData[row].toMap()["rowData"].toMap();
147+}
148+
149+QVariant UnityMenuModel::subMenuData(int row) const
150+{
151+ return m_modelData[row].toMap()["submenu"];
152+}
153+
154+QModelIndex UnityMenuModel::index(int row, int column, const QModelIndex&) const
155+{
156+ return createIndex(row, column);
157+}
158+
159+QModelIndex UnityMenuModel::parent(const QModelIndex &) const
160+{
161+ return QModelIndex();
162+}
163+
164+QHash<int, QByteArray> UnityMenuModel::roleNames() const
165+{
166+ QHash<int, QByteArray> names;
167+
168+ names[LabelRole] = "label";
169+ names[SensitiveRole] = "sensitive";
170+ names[IsSeparatorRole] = "isSeparator";
171+ names[IconRole] = "icon";
172+ names[TypeRole] = "type";
173+ names[ExtendedAttributesRole] = "ext";
174+ names[ActionRole] = "action";
175+ names[ActionStateRole] = "actionState";
176+ names[IsCheckRole] = "isCheck";
177+ names[IsRadioRole] = "isRadio";
178+ names[IsToggledRole] = "isToggled";
179+
180+ return names;
181+}
182+
183+QObject * UnityMenuModel::submenu(int position, QQmlComponent*)
184+{
185+ if (position < 0 || m_modelData.count() < position) {
186+ return NULL;
187+ }
188+
189+ while (submenus.count() <= position) {
190+ submenus.append(NULL);
191+ }
192+
193+ QVariant submenuData = subMenuData(position);
194+ if (submenuData.type() == (int)QMetaType::QVariantList) {
195+ UnityMenuModel*& model = submenus[position];
196+ if (!model) {
197+ model = new UnityMenuModel(this);
198+ }
199+ if (model->modelData() != submenuData) {
200+ model->setModelData(submenuData);
201+ }
202+ return model;
203+ }
204+
205+ return NULL;
206+}
207+
208+bool UnityMenuModel::loadExtendedAttributes(int, const QVariantMap &)
209+{
210+ return false;
211+}
212+
213+QVariant UnityMenuModel::get(int row, const QByteArray &role)
214+{
215+ static QHash<QByteArray, int> roles;
216+ if (roles.isEmpty()) {
217+ QHash<int, QByteArray> names = roleNames();
218+ Q_FOREACH (int role, names.keys())
219+ roles.insert(names[role], role);
220+ }
221+
222+ return this->data(this->index(row, 0), roles[role]);
223+}
224+
225+void UnityMenuModel::activate(int, const QVariant&)
226+{
227+}
228+
229+void UnityMenuModel::changeState(int, const QVariant&)
230+{
231+}
232+
233+void UnityMenuModel::registerAction(UnityMenuAction*)
234+{
235+}
236+
237+void UnityMenuModel::unregisterAction(UnityMenuAction*)
238+{
239+}
tests/mocks/QMenuModel/unitymenumodel.hnew file+96
@@ -0,0 +1,96 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Nick Dedekind <nick.dedekind@canonical.com>
17+ */
18+
19+#ifndef MOCK_UNITYMENUMODEL_H
20+#define MOCK_UNITYMENUMODEL_H
21+
22+#include <QAbstractListModel>
23+class QQmlComponent;
24+class UnityMenuAction;
25+class ActionStateParser;
26+
27+class Q_DECL_EXPORT UnityMenuModel : public QAbstractListModel
28+{
29+ Q_OBJECT
30+ Q_PROPERTY(QVariant modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
31+ Q_PROPERTY(QByteArray busName READ busName WRITE setBusName NOTIFY busNameChanged)
32+ Q_PROPERTY(QVariantMap actions READ actions WRITE setActions NOTIFY actionsChanged)
33+ Q_PROPERTY(QByteArray menuObjectPath READ menuObjectPath WRITE setMenuObjectPath NOTIFY menuObjectPathChanged)
34+ Q_PROPERTY(ActionStateParser* actionStateParser READ actionStateParser WRITE setActionStateParser NOTIFY actionStateParserChanged)
35+
36+public:
37+ UnityMenuModel(QObject *parent = NULL);
38+ virtual ~UnityMenuModel();
39+
40+ Q_INVOKABLE void insertRow(int row, const QVariant& data);
41+ Q_INVOKABLE void appendRow(const QVariant& data);
42+ Q_INVOKABLE void removeRow(int row);
43+
44+ QVariant modelData() const;
45+ void setModelData(const QVariant& data);
46+
47+ QByteArray busName() const;
48+ void setBusName(const QByteArray &busName);
49+
50+ QVariantMap actions() const;
51+ void setActions(const QVariantMap &actions);
52+
53+ QByteArray menuObjectPath() const;
54+ void setMenuObjectPath(const QByteArray &path);
55+
56+ ActionStateParser* actionStateParser() const;
57+ void setActionStateParser(ActionStateParser* actionStateParser);
58+
59+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
60+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
61+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
62+ QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const;
63+ QModelIndex parent(const QModelIndex &index) const;
64+ QHash<int, QByteArray> roleNames() const;
65+
66+ Q_INVOKABLE QObject * submenu(int position, QQmlComponent* actionStateParser = NULL);
67+ Q_INVOKABLE bool loadExtendedAttributes(int position, const QVariantMap &schema);
68+ Q_INVOKABLE QVariant get(int row, const QByteArray &role);
69+
70+ Q_INVOKABLE void activate(int index, const QVariant& parameter = QVariant());
71+ Q_INVOKABLE void changeState(int index, const QVariant& parameter);
72+
73+ void registerAction(UnityMenuAction* action);
74+ void unregisterAction(UnityMenuAction* action);
75+
76+Q_SIGNALS:
77+ void busNameChanged();
78+ void actionsChanged();
79+ void menuObjectPathChanged();
80+ void actionStateParserChanged();
81+ void modelDataChanged();
82+
83+private:
84+ QVariantMap rowData(int row) const;
85+ QVariant subMenuData(int row) const;
86+
87+ class Row;
88+ QVariantList m_modelData;
89+ QList<UnityMenuModel*> submenus;
90+
91+ QByteArray m_busName;
92+ QVariantMap m_actions;
93+ QByteArray m_menuObjectPath;
94+};
95+
96+#endif // MOCK_UNITYMENUMODEL_H
tests/mocks/Unity/Indicators/IndicatorBase.qmlnew file+37
@@ -0,0 +1,37 @@
1+/*
2+ * Copyright 2013 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+ * Authors:
17+ * Nick Dedekind <nick.dedekind@canonical.com>
18+ */
19+
20+import QtQuick 2.0
21+import QMenuModel 0.1
22+
23+Item {
24+ id: indicatorBase
25+
26+ //const
27+ property string busName
28+ property string actionsObjectPath
29+ property string rootMenuType: "com.canonical.indicator.root"
30+ property string deviceMenuObjectPath
31+
32+ property var menuModel: UnityMenuModel {}
33+
34+ property RootActionState rootActionState: RootActionState {
35+ onUpdated: indicatorBase.rootActionStateChanged()
36+ }
37+}
tests/mocks/Unity/Indicators/IndicatorWidget.qmlnew file+28
@@ -0,0 +1,28 @@
1+/*
2+ * Copyright 2013 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+ * Authors:
17+ * Nick Dedekind <nick.dedekind@canonical.com>
18+ */
19+
20+import QtQuick 2.0
21+import Unity.Indicators 0.1 as Indicators
22+
23+IndicatorBase {
24+ id: indicatorWidget
25+
26+ enabled: false
27+ property int iconSize: height
28+}
tests/mocks/Unity/Indicators/RootActionState.qml+17−9
@@ -20,14 +20,22 @@
20import QtQuick 2.0
20import QtQuick 2.0
21
21
22QtObject {
22QtObject {
23− property var menu
23+ property var menu
24− property bool valid: false
24+ property bool valid: false
25− property string title
25+ property string title
26− property string leftLabel
26+ property string leftLabel
27− property string rightLabel
27+ property string rightLabel
28− property var icons
28+ property var icons
29− property string accessibleName
29+ property string accessibleName
30− property bool visible: true
30+ property bool visible: true
31
31
32− signal updated
32+ signal updated
33+
34+ onValidChanged: updated()
35+ onTitleChanged: updated()
36+ onLeftLabelChanged: updated()
37+ onRightLabelChanged: updated()
38+ onIconsChanged: updated()
39+ onAccessibleNameChanged: updated()
40+ onVisibleChanged: updated()
33}
41}
tests/mocks/Unity/Indicators/qmldir+2
@@ -2,6 +2,8 @@ module Unity.Indicators
2plugin IndicatorsFakeQml
2plugin IndicatorsFakeQml
3
3
4CachedUnityMenuModel 0.1 CachedUnityMenuModel.qml
4CachedUnityMenuModel 0.1 CachedUnityMenuModel.qml
5+IndicatorBase 0.1 IndicatorBase.qml
6+IndicatorWidget 0.1 IndicatorWidget.qml
5IndicatorsModel 0.1 IndicatorsModel.qml
7IndicatorsModel 0.1 IndicatorsModel.qml
6FakeMenuPage 0.1 FakeMenuPage.qml
8FakeMenuPage 0.1 FakeMenuPage.qml
7RootActionState 0.1 RootActionState.qml
9RootActionState 0.1 RootActionState.qml
tests/mocks/Unity/fake_scope.cpp+3−20
@@ -25,25 +25,8 @@ static DeeModel* create_results_model(unsigned category_count, unsigned result_c
25
25
26// TODO: Implement remaining pieces
26// TODO: Implement remaining pieces
27
27
28−Scope::Scope(QObject* parent)
28+Scope::Scope(QObject* parent) : Scope(QString(), QString(), false, parent)
29− : QObject(parent)
30− , m_visible(false)
31− , m_searching(false)
32− , m_isActive(false)
33− , m_categories(new Categories(this))
34− , m_results(new DeeListModel(this))
35{
29{
36− DeeModel* results_model = create_results_model(4, 30);
37− m_categories->setResultModel(results_model);
38− m_categories->setModel(create_categories_model(4));
39− m_results->setModel(results_model);
40−
41− m_timer.setInterval(1000);
42− m_timer.setSingleShot(true);
43− connect(&m_timer, &QTimer::timeout, [this]() {
44− Preview *p = new Preview(this);
45− Q_EMIT previewReady(p);
46− });
47}
30}
48
31
49Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent)
32Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent)
@@ -56,9 +39,9 @@ Scope::Scope(QString const& id, QString const& name, bool visible, QObject* pare
56 , m_categories(new Categories(this))
39 , m_categories(new Categories(this))
57 , m_results(new DeeListModel(this))
40 , m_results(new DeeListModel(this))
58{
41{
59− DeeModel* results_model = create_results_model(4, 30);
42+ DeeModel* results_model = create_results_model(20, 300);
60 m_categories->setResultModel(results_model);
43 m_categories->setResultModel(results_model);
61− m_categories->setModel(create_categories_model(4));
44+ m_categories->setModel(create_categories_model(20));
62 m_results->setModel(results_model);
45 m_results->setModel(results_model);
63
46
64 m_timer.setInterval(1000);
47 m_timer.setInterval(1000);
tests/plugins/ListViewWithPageHeader/listviewwithpageheadertest.cpp+3
@@ -1724,6 +1724,9 @@ private Q_SLOTS:
1724
1724
1725 void testMaximizeVisibleAreaMoveUpAndShowHeader()
1725 void testMaximizeVisibleAreaMoveUpAndShowHeader()
1726 {
1726 {
1727+#if (QT_VERSION < QT_VERSION_CHECK(5, 1, 0))
1728+ QSKIP("This test is extremely unstable in 5.0.x");
1729+#endif
1727 model->setProperty(0, "size", 800);
1730 model->setProperty(0, "size", 800);
1728 verifyItem(0, 50., 800., false);
1731 verifyItem(0, 50., 800., false);
1729
1732
tests/plugins/Unity/Indicators/CMakeLists.txt+36−27
@@ -1,34 +1,43 @@
1+pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)
2+pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)
1pkg_check_modules(QMENUMODEL REQUIRED qmenumodel)
3pkg_check_modules(QMENUMODEL REQUIRED qmenumodel)
2
4
5+set(INDICATORS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../plugins/Unity/Indicators)
6+set(TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
7+
3include_directories(
8include_directories(
4 ${CMAKE_CURRENT_BINARY_DIR}
9 ${CMAKE_CURRENT_BINARY_DIR}
5− ${CMAKE_CURRENT_SOURCE_DIR}/../../../../plugins/Unity/Indicators
10+ ${INDICATORS_DIR}
6− ${QMENUMODEL_INCLUDE_DIRS}
11+ ${TEST_DIR}/mocks/QMenuModel
12+ ${GLIB_INCLUDE_DIRS}
13+ ${GIO_INCLUDE_DIRS}
7 )
14 )
8
15
9−macro(run_tests)
16+macro(indicator_test TEST)
10− set(_test_list "")
17+ set(multi_value_keywords ADDITIONAL_CPPS ADDITIONAL_LIBS)
11− foreach(_test ${ARGN})
18+ cmake_parse_arguments(test "" "" "${multi_value_keywords}" ${ARGN})
12− set(testCommand ${CMAKE_CURRENT_BINARY_DIR}/${_test}Exec
13− -o ${CMAKE_BINARY_DIR}/${_test}.xml,xunitxml
14− -o -,txt)
15− add_test(NAME ${_test} COMMAND ${testCommand})
16− add_custom_target(${_test} ${testCommand})
17− add_executable(${_test}Exec ${_test}.cpp
18− )
19− qt5_use_modules(${_test}Exec Test Core Qml)
20− target_link_libraries(${_test}Exec
21− IndicatorsQml
22− ${QMENUMODEL_LDFLAGS}
23− )
24− set(_test_list "${_test_list};${_test}")
25− endforeach()
26−endmacro(run_tests)
27
19
28−run_tests(
20+ set(testCommand ${CMAKE_CURRENT_BINARY_DIR}/${TEST}Exec
21+ -o ${CMAKE_BINARY_DIR}/${TEST}.xml,xunitxml
22+ -o -,txt)
23+ add_test(NAME ${TEST} COMMAND ${testCommand})
24+ add_custom_target(${TEST} ${testCommand})
25+ add_executable(${TEST}Exec
26+ ${TEST}.cpp
27+ ${test_ADDITIONAL_CPPS}
28+ )
29+ qt5_use_modules(${TEST}Exec Test Core Qml)
30+ target_link_libraries(${TEST}Exec
31+ ${test_ADDITIONAL_LIBS}
32+ ${GLIB_LIBRARIES}
33+ ${GIO_LIBRARIES}
34+ ${QMENUMODEL_LDFLAGS}
35+ )
36+endmacro(indicator_test)
37+
29− indicatorsmanagertest
38+indicator_test(indicatorsmanagertest ADDITIONAL_LIBS IndicatorsQml)
30− indicatorsmodeltest
39+indicator_test(indicatorsmodeltest ADDITIONAL_LIBS IndicatorsQml)
31− menucontentactivatortest
40+indicator_test(menucontentactivatortest ADDITIONAL_CPPS ${INDICATORS_DIR}/menucontentactivator.cpp)
41+indicator_test(unitymenumodelstacktest ADDITIONAL_CPPS ${TEST_DIR}/mocks/QMenuModel/unitymenumodel.cpp ${INDICATORS_DIR}/unitymenumodelstack.cpp)
32− rootactionstatetest
42+indicator_test(rootactionstatetest ADDITIONAL_LIBS IndicatorsQml)
33− timeformattertest
43+indicator_test(timeformattertest ADDITIONAL_LIBS IndicatorsQml)
34− )
tests/plugins/Unity/Indicators/unitymenumodelstacktest.cppnew file+206
@@ -0,0 +1,206 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Nick Dedekind <nick.dedekind@canonical.com>
18+ */
19+
20+#include "indicatorsmanager.h"
21+#include "paths.h"
22+#include "unitymenumodelstack.h"
23+
24+#include <QtTest>
25+#include <QDebug>
26+#include <unitymenumodel.h>
27+
28+class UnityMenuModelStackTest : public QObject
29+{
30+ Q_OBJECT
31+private Q_SLOTS:
32+
33+ void init()
34+ {
35+ m_model = new UnityMenuModel();
36+ m_headChanged = false;
37+ m_tailChanged = false;
38+ }
39+
40+ void cleanup()
41+ {
42+ delete m_model;
43+ m_model = NULL;
44+ }
45+
46+ void testHeadOnSetHead()
47+ {
48+ UnityMenuModelStack stack;
49+ connect(&stack, SIGNAL(headChanged(UnityMenuModel*)), this, SLOT(onHeadChanged()));
50+ stack.setHead(m_model);
51+
52+ QCOMPARE(stack.head(), m_model);
53+ QCOMPARE(m_headChanged, true);
54+ }
55+
56+ void testTailOnSetHead()
57+ {
58+ UnityMenuModelStack stack;
59+ connect(&stack, SIGNAL(tailChanged(UnityMenuModel*)), this, SLOT(onTailChanged()));
60+ stack.setHead(m_model);
61+
62+ QCOMPARE(stack.tail(), m_model);
63+ QCOMPARE(m_tailChanged, true);
64+ }
65+
66+ void testPushPop_data() {
67+ QTest::addColumn<int>("menuDepth");
68+ QTest::addColumn<int>("subMenuCount");
69+ QTest::addColumn<int>("subMenuIndex");
70+
71+ QTest::newRow("depth=0") << 0 << 1 << 0;
72+ QTest::newRow("depth=1") << 1 << 1 << 0;
73+ QTest::newRow("depth=8") << 8 << 2 << 1;
74+ }
75+
76+ void testPushPop()
77+ {
78+ QFETCH(int, menuDepth);
79+ QFETCH(int, subMenuCount);
80+ QFETCH(int, subMenuIndex);
81+
82+ m_model->setModelData(recuseAddMenu(subMenuCount, menuDepth));
83+
84+ UnityMenuModelStack stack;
85+ connect(&stack, SIGNAL(tailChanged(UnityMenuModel*)), this, SLOT(onTailChanged()));
86+
87+ QList<UnityMenuModel*> models;
88+
89+ int count = 0;
90+ auto foreachChild = [&](UnityMenuModel* child, int childIndex) {
91+ stack.push(child, childIndex);
92+ QCOMPARE(stack.count(), count+1);
93+
94+ count++;
95+ models << child;
96+ };
97+ recuseSubmenus(m_model, subMenuIndex, foreachChild);
98+
99+ QCOMPARE(stack.count(), models.count());
100+ QCOMPARE(stack.count(), menuDepth+1);
101+ while(stack.count() > 0) {
102+ m_tailChanged = false;
103+
104+ QCOMPARE(stack.pop(), models.takeLast());
105+
106+ QCOMPARE(m_tailChanged, true);
107+ if (stack.count()) {
108+ QCOMPARE(stack.tail(), models.last());
109+ }
110+ }
111+ QCOMPARE(m_tailChanged, true);
112+ }
113+
114+ void testPopOnRemove_data() {
115+ QTest::addColumn<int>("menuDepth");
116+ QTest::addColumn<int>("subMenuCount");
117+ QTest::addColumn<int>("subMenuIndex");
118+ QTest::addColumn<int>("removeIndex");
119+ QTest::addColumn<int>("resultCount");
120+
121+ QTest::newRow("removeIndexBefore") << 4 << 2 << 1 << 0 << 5;
122+ QTest::newRow("removeCurrentIndex") << 4 << 2 << 0 << 0 << 1;
123+ QTest::newRow("removeIndexAfter") << 4 << 2 << 0 << 1 << 5;
124+ }
125+
126+ void testPopOnRemove()
127+ {
128+ QFETCH(int, menuDepth);
129+ QFETCH(int, subMenuCount);
130+ QFETCH(int, subMenuIndex);
131+ QFETCH(int, removeIndex);
132+ QFETCH(int, resultCount);
133+
134+ m_model->setModelData(recuseAddMenu(subMenuCount, menuDepth));
135+
136+ UnityMenuModelStack stack;
137+
138+ auto foreachChild = [&](UnityMenuModel* child, int childIndex) {
139+ stack.push(child, childIndex);
140+ };
141+ recuseSubmenus(m_model, subMenuIndex, foreachChild);
142+
143+ QCOMPARE(stack.count(), menuDepth+1);
144+
145+ m_model->removeRow(removeIndex);
146+
147+ waitFor([&stack, resultCount]() { return stack.count() == resultCount; }, 1000);
148+ QCOMPARE(stack.count(), resultCount);
149+ }
150+
151+private:
152+ bool waitFor(std::function<bool()> functor, int ms) {
153+
154+ QElapsedTimer timer;
155+ timer.start();
156+ while(!functor() && timer.elapsed() < ms) { QTest::qWait(10); }
157+ return functor();
158+ }
159+
160+ QVariant recuseAddMenu(int subMenuCount, int depth_remaining)
161+ {
162+ QVariantList rows;
163+
164+ for (int i = 0; i < subMenuCount; i ++) {
165+ QVariantMap row;
166+ QVariantMap rowData;
167+
168+ if (depth_remaining > 0) {
169+ row["submenu"] = recuseAddMenu(subMenuCount, depth_remaining-1);
170+ }
171+
172+ row["rowData"] = rowData;
173+
174+ rows << row;
175+ }
176+
177+ return rows;
178+ }
179+
180+ void recuseSubmenus(UnityMenuModel* model, int childIndex, std::function<void(UnityMenuModel*, int)> func) {
181+ UnityMenuModel* parent = model;
182+ UnityMenuModel* child = model;
183+
184+ while(child) {
185+ if (func) {
186+ func(child, childIndex);
187+ }
188+
189+ parent = child;
190+ child = qobject_cast<UnityMenuModel*>(parent->submenu(childIndex));
191+ }
192+
193+ }
194+
195+private Q_SLOTS:
196+ void onHeadChanged() { m_headChanged = true; }
197+ void onTailChanged() { m_tailChanged = true; }
198+
199+public:
200+ UnityMenuModel* m_model;
201+ bool m_headChanged;
202+ bool m_tailChanged;
203+};
204+
205+QTEST_GUILESS_MAIN(UnityMenuModelStackTest)
206+#include "unitymenumodelstacktest.moc"
tests/qmltests/CMakeLists.txt+5−3
@@ -13,11 +13,9 @@ set(qmltest_DEFAULT_NO_ADD_TEST FALSE)
13set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=minimal")
13set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=minimal")
14add_qml_test(Components AnimationControllerWithSignals)
14add_qml_test(Components AnimationControllerWithSignals)
15add_qml_test(Components Carousel)
15add_qml_test(Components Carousel)
16−add_qml_test(Components MathLocal)
17add_qml_test(Components OpenEffect)
16add_qml_test(Components OpenEffect)
18add_qml_test(Components RatingStars)
17add_qml_test(Components RatingStars)
19add_qml_test(Components TimeLocal)
18add_qml_test(Components TimeLocal)
20−add_qml_test(Greeter Clock IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
21add_qml_test(Panel IndicatorItem)
19add_qml_test(Panel IndicatorItem)
22add_qml_test(utils/Unity/Test UnityTest)
20add_qml_test(utils/Unity/Test UnityTest)
23
21
@@ -60,15 +58,19 @@ add_qml_test(Greeter Phone IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DE
60 ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
58 ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
61add_qml_test(Greeter Infographics IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
59add_qml_test(Greeter Infographics IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
62 ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
60 ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
61+add_qml_test(Greeter Clock IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
62+ ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel")
63add_qml_test(Hud Hud)
63add_qml_test(Hud Hud)
64add_qml_test(Hud Result)
64add_qml_test(Hud Result)
65add_qml_test(Launcher Launcher IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
65add_qml_test(Launcher Launcher IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
66−add_qml_test(Notifications Notifications IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_SOURCE_DIR}/tests/mocks)
66+add_qml_test(Notifications Notifications IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
67add_qml_test(Panel IndicatorRow)
67add_qml_test(Panel IndicatorRow)
68add_qml_test(Panel Indicators IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
68add_qml_test(Panel Indicators IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
69add_qml_test(Panel MenuContent IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
69add_qml_test(Panel MenuContent IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
70add_qml_test(Panel Panel IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
70add_qml_test(Panel Panel IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
71add_qml_test(Panel SearchIndicator)
71add_qml_test(Panel SearchIndicator)
72+add_qml_test(Panel/Indicators DefaultIndicatorWidget IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
73+ ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel")
72add_qml_test(SideStage SideStage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS}
74add_qml_test(SideStage SideStage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS}
73 ${CMAKE_BINARY_DIR}/tests/mocks
75 ${CMAKE_BINARY_DIR}/tests/mocks
74 ${CMAKE_BINARY_DIR}/plugins)
76 ${CMAKE_BINARY_DIR}/plugins)
tests/qmltests/Components/tst_EdgeDemoOverlay.qml+2−2
@@ -112,8 +112,8 @@ Item {
112 // Test that the 'none' edge skips anywhere
112 // Test that the 'none' edge skips anywhere
113 signalSpy.target = none
113 signalSpy.target = none
114 signalSpy.clear()
114 signalSpy.clear()
115− var backgroundShade = findChild(none, "backgroundShade")
115+ var backgroundShade = findChild(none, "backgroundShadeMouseArea")
116− tryCompare(none, "opacity", 1)
116+ tryCompare(backgroundShade, "enabled", true)
117 mousePress(backgroundShade, 1, 1)
117 mousePress(backgroundShade, 1, 1)
118 mouseRelease(backgroundShade, 1, 1)
118 mouseRelease(backgroundShade, 1, 1)
119 signalSpy.wait()
119 signalSpy.wait()
tests/qmltests/Components/tst_MathLocal.qmldeleted−91
@@ -1,91 +0,0 @@
1−/*
2− * Copyright 2013 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU 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 General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import QtTest 1.0
19−import "../../../Components/Math.js" as MathLocal
20−
21−TestCase {
22− name: "MathLocal"
23−
24− property int minValue
25− property int maxValue
26− property int clampValue
27− property int clamped
28−
29− function test_clamp_positive_lower() {
30− minValue = 9
31− maxValue = 42
32− clampValue = -7
33−
34− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
35− compare(clamped, minValue, "clamped value not within range")
36− }
37−
38− function test_clamp_positive_greater() {
39− minValue = 9
40− maxValue = 42
41− clampValue = 111
42−
43− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
44− compare(clamped, maxValue, "clamped value not within range")
45− }
46−
47− function test_clamp_positive_within() {
48− minValue = 9
49− maxValue = 53
50− clampValue = 42
51−
52− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
53− compare(clamped, clampValue, "clamped value changed even though it shouldn't have")
54− }
55−
56− function test_clamp_positive_on_border() {
57− minValue = 9
58− maxValue = 42
59− clampValue = 9
60−
61− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
62− compare(clamped, clampValue, "clamped value changed even though it shouldn't have")
63− }
64−
65− function test_clamp_negative_lower() {
66− minValue = -42
67− maxValue = -9
68− clampValue = -50
69−
70− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
71− compare(clamped, minValue, "clamped value not within range")
72− }
73−
74− function test_clamp_negative_greater() {
75− minValue = -42
76− maxValue = -9
77− clampValue = 50
78−
79− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
80− compare(clamped, maxValue, "clamped value not within range")
81− }
82−
83− function test_clamp_postive_and_negative_greater() {
84− minValue = -42
85− maxValue = 9
86− clampValue = 50
87−
88− clamped = MathLocal.clamp(clampValue, minValue, maxValue)
89− compare(clamped, maxValue, "clamped value not within range")
90− }
91−}
tests/qmltests/Dash/qml/FakeScopeView.qml+1
@@ -23,6 +23,7 @@ GenericScopeView {
23 id: fakeScopeView
23 id: fakeScopeView
24
24
25 property alias backColor : back.color
25 property alias backColor : back.color
26+ moving: listView.moving
26
27
27 onEndReached: {
28 onEndReached: {
28 if (scope != undefined && shell != undefined && shell.scopeStatus != undefined) {
29 if (scope != undefined && shell != undefined && shell.scopeStatus != undefined) {
tests/qmltests/Dash/tst_Dash.qml+2
@@ -103,6 +103,8 @@ Item {
103 return;
103 return;
104 }
104 }
105 dash.showScopeOnLoaded = data.tag
105 dash.showScopeOnLoaded = data.tag
106+ scopes.clear();
107+ scopes.load();
106
108
107 var dashContentList = findChild(dash, "dashContentList");
109 var dashContentList = findChild(dash, "dashContentList");
108 verify(dashContentList != undefined);
110 verify(dashContentList != undefined);
tests/qmltests/Dash/tst_DashContent.qml+14
@@ -241,5 +241,19 @@ Item {
241 tryCompare(scopesModel.get(1), "isActive", data.active1);
241 tryCompare(scopesModel.get(1), "isActive", data.active1);
242 tryCompare(scopesModel.get(2), "isActive", data.active2);
242 tryCompare(scopesModel.get(2), "isActive", data.active2);
243 }
243 }
244+
245+ function test_hswipe_disabled_vswipe() {
246+ var dashContentList = findChild(dashContent, "dashContentList");
247+
248+ tryCompare(dashContentList, "interactive", true);
249+
250+ var startX = dashContentList.width/2;
251+ var startY = dashContentList.height/2;
252+ touchFlick(dashContentList, startX, startY, startX, startY - units.gu(800));
253+
254+ tryCompare(dashContentList.currentItem, "moving", true);
255+
256+ compare(dashContentList.interactive, false);
257+ }
244 }
258 }
245}
259}
tests/qmltests/Dash/tst_GenericScopeView.qml+3
@@ -74,6 +74,9 @@ Item {
74 }
74 }
75
75
76 function openPreview() {
76 function openPreview() {
77+ var categoryListView = findChild(genericScopeView, "categoryListView");
78+ categoryListView.positionAtBeginning();
79+
77 var tile = findChild(genericScopeView, "delegate0");
80 var tile = findChild(genericScopeView, "delegate0");
78 mouseClick(tile, tile.width / 2, tile.height / 2);
81 mouseClick(tile, tile.width / 2, tile.height / 2);
79 var openEffect = findChild(genericScopeView, "openEffect");
82 var openEffect = findChild(genericScopeView, "openEffect");
tests/qmltests/Greeter/tst_Clock.qml+16
@@ -19,6 +19,7 @@ import QtTest 1.0
19import ".."
19import ".."
20import "../../../Greeter"
20import "../../../Greeter"
21import Ubuntu.Components 0.1
21import Ubuntu.Components 0.1
22+import QMenuModel 0.1
22import Unity.Test 0.1 as UT
23import Unity.Test 0.1 as UT
23
24
24Rectangle {
25Rectangle {
@@ -35,9 +36,24 @@ Rectangle {
35 }
36 }
36 }
37 }
37
38
39+ UnityMenuModel {
40+ id: menuModel
41+ modelData: [{
42+ "rowData": {
43+ "actionState": { "label": Qt.formatTime(new Date("October 13, 1975 11:13:00")) }
44+ }
45+ }]
46+ }
47+
38 UT.UnityTestCase {
48 UT.UnityTestCase {
39 name: "Clock"
49 name: "Clock"
40
50
51+ function init() {
52+ var cachedModel = findChild(clock, "timeModel");
53+ verify(cachedModel !== undefined);
54+ cachedModel.model = menuModel;
55+ }
56+
41 function test_customDate() {
57 function test_customDate() {
42 var dateObj = new Date("October 13, 1975 11:13:00")
58 var dateObj = new Date("October 13, 1975 11:13:00")
43 var dateString = Qt.formatDate(dateObj, Qt.DefaultLocaleLongDate)
59 var dateString = Qt.formatDate(dateObj, Qt.DefaultLocaleLongDate)
tests/qmltests/Panel/Indicators/tst_DefaultIndicatorWidget.qmlnew file+97
@@ -0,0 +1,97 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU 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 General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import QtTest 1.0
19+import Unity.Test 0.1 as UT
20+import QMenuModel 0.1
21+import "../../../../Panel/Indicators"
22+
23+Item {
24+ id: testView
25+ width: units.gu(40)
26+ height: units.gu(70)
27+
28+ DefaultIndicatorWidget {
29+ id: widget
30+
31+ anchors {
32+ left: parent.left
33+ top: parent.top
34+ }
35+
36+ busName: "test"
37+ actionsObjectPath: "test"
38+ deviceMenuObjectPath: "test"
39+
40+ rootMenuType: ""
41+
42+ iconSize: units.gu(3.2)
43+ height: units.gu(3)
44+
45+ rootActionState {
46+ icons: [ "image://theme/audio-volume-high", "image://theme/audio-volume-low" ]
47+ leftLabel: "left"
48+ rightLabel: "right"
49+ }
50+ }
51+
52+ UT.UnityTestCase {
53+ name: "DefaultIndicatorWidget"
54+ when: windowShown
55+
56+ function init() {
57+ widget.rootActionState.icons = [];
58+ widget.rootActionState.leftLabel = "";
59+ widget.rootActionState.rightLabel = "";
60+ wait(50);
61+ }
62+
63+ function test_guRoundedWidth_data() {
64+ return [
65+ { tag: "empty", icons: [], leftLabel: "", rightLabel: "" },
66+ { tag: "1-icon-no-label", icons: [ "image://theme/audio-volume-high" ], leftLabel: "", rightLabel: "" },
67+ { tag: "2-icon-no-label", icons: [ "image://theme/audio-volume-high", "image://theme/audio-volume-low" ], leftLabel: "", rightLabel: "" },
68+ { tag: "no-icon-l-label", icons: [], leftLabel: "left", rightLabel: "" },
69+ { tag: "no-icon-lr-label", icons: [], leftLabel: "left", rightLabel: "right" },
70+ { tag: "1-icon-l-label", icons: [ "image://theme/audio-volume-high" ], leftLabel: "left", rightLabel: "" },
71+ { tag: "1-icon-lr-label", icons: [ "image://theme/audio-volume-high" ], leftLabel: "left", rightLabel: "right" },
72+ { tag: "2-icon-l-label", icons: [ "image://theme/audio-volume-high", "image://theme/audio-volume-low" ], leftLabel: "left", rightLabel: "" },
73+ { tag: "2-icon-lr-label", icons: [ "image://theme/audio-volume-high", "image://theme/audio-volume-low" ], leftLabel: "left", rightLabel: "right" }
74+ ];
75+ }
76+
77+ function test_guRoundedWidth(data) {
78+ widget.rootActionState.icons = data.icons
79+ widget.rootActionState.leftLabel = data.leftLabel;
80+ widget.rootActionState.rightLabel = data.rightLabel;
81+ wait(50);
82+
83+ compare(widget.width, guRoundUp(widget.width));
84+ }
85+ }
86+
87+ // TODO: Use toolkit function https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1242575
88+ function guRoundUp(width) {
89+ if (width == 0) {
90+ return 0;
91+ }
92+ var gu1 = units.gu(1.0);
93+ var mod = (width % gu1);
94+
95+ return mod == 0 ? width : width + (gu1 - mod);
96+ }
97+}