on xenial help sign in
Added active call hint

A hint is displayed in the indicator panel when an call is active on the Telephony Serivce Approved by: Olga Kemmet, Daniel d'Andrada, PS Jenkins bot, Michał Sawicz

commit620f9640ffa23fbf5eb77c3c29c62f8fbf8621db authorNick Dedekind <nicholas.dedekind@gmail.com> dateWed 9 Jul 2014, 19:44 (12 years ago) parent4c3de71d199e5d
36 files changed+1353−196
build.sh+1 debian/control+1 plugins/Ubuntu/Gestures/DirectionalDragArea.cpp+1 plugins/Ubuntu/Gestures/DirectionalDragArea.h+1 qml/Dash/graphics/phone/screenshots/phone@12.png → qml/Dash/graphics/phone/screenshots/dialer@12.png qml/Panel/ActiveCallHint.qml+206 qml/Panel/IndicatorRow.qml+1−1 qml/Panel/Indicators.qml+22−36 qml/Panel/Panel.qml+141−70 qml/Shell.qml+7−8 qml/graphics/applicationIcons/phone-app@18.png → qml/graphics/applicationIcons/dialer-app@18.png tests/autopilot/unity8/shell/tests/test_notifications.py+4−4 tests/mocks/Ubuntu/CMakeLists.txt+1 tests/mocks/Ubuntu/Telephony/CMakeLists.txt+22 tests/mocks/Ubuntu/Telephony/ContactWatcherData.cpp+43 tests/mocks/Ubuntu/Telephony/ContactWatcherData.h+46 tests/mocks/Ubuntu/Telephony/MockCallEntry.cpp+66 tests/mocks/Ubuntu/Telephony/MockCallEntry.h+57 tests/mocks/Ubuntu/Telephony/MockCallManager.cpp+80 tests/mocks/Ubuntu/Telephony/MockCallManager.h+60 tests/mocks/Ubuntu/Telephony/MockContactWatcher.cpp+50 tests/mocks/Ubuntu/Telephony/MockContactWatcher.h+49 tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.cpp+35 tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.h+36 tests/mocks/Ubuntu/Telephony/plugin.cpp+52 tests/mocks/Ubuntu/Telephony/plugin.h+37 tests/mocks/Ubuntu/Telephony/qmldir+2 tests/mocks/Unity/Application/ApplicationManager.cpp+3−3 tests/mocks/Unity/Launcher/MockLauncherModel.cpp+1−1 tests/qmltests/CMakeLists.txt+1 tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml+2−2 tests/qmltests/Launcher/tst_Launcher.qml+2−2 tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml+1−1 tests/qmltests/Panel/tst_ActiveCallHint.qml+165 tests/qmltests/Panel/tst_Indicators.qml+10−21 tests/qmltests/Panel/tst_Panel.qml+147−47
build.sh+1
@@ -48,6 +48,7 @@ install_dependencies() {
4848 qtdeclarative5-gsettings1.0 \
4949 qtdeclarative5-ubuntu-ui-toolkit-plugin \
5050 qtdeclarative5-ubuntu-settings-components \
51+ qtdeclarative5-ubuntu-telephony0.1 \
5152 qtdeclarative5-ubuntu-thumbnailer0.1 \
5253 unity-notifications-impl \
5354 ubuntu-mobile-icons \
debian/control+1
@@ -81,6 +81,7 @@ Depends: gsettings-desktop-schemas,
8181 qml-module-qtquick-xmllistmodel,
8282 qtdeclarative5-gsettings1.0,
8383 qtdeclarative5-ubuntu-settings-components (>= 0.3),
84+ qtdeclarative5-ubuntu-telephony0.1,
8485 unity-launcher-impl-3,
8586 unity8-common (= ${source:Version}),
8687 unity8-private (= ${binary:Version}),
plugins/Ubuntu/Gestures/DirectionalDragArea.cpp+1
@@ -378,6 +378,7 @@ void DirectionalDragArea::touchEvent_undecided(QTouchEvent *event)
378378 // touch has ended before recognition concluded
379379 DDA_DEBUG("Touch has ended before recognition concluded");
380380 setStatus(WaitingForTouch);
381+ Q_EMIT tapped();
381382 return;
382383 }
383384
plugins/Ubuntu/Gestures/DirectionalDragArea.h+1
@@ -212,6 +212,7 @@ Q_SIGNALS:
212212 void touchYChanged(qreal value);
213213 void touchSceneXChanged(qreal value);
214214 void touchSceneYChanged(qreal value);
215+ void tapped();
215216
216217protected:
217218 virtual void touchEvent(QTouchEvent *event);
qml/Dash/graphics/phone/screenshots/phone@12.png → qml/Dash/graphics/phone/screenshots/dialer@12.pngrenamed

Binary file not shown.

qml/Panel/ActiveCallHint.qmlnew file+206
@@ -0,0 +1,206 @@
1+/*
2+ * Copyright (C) 2014 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 Ubuntu.Telephony 0.1 as Telephony
19+import Ubuntu.Components 0.1
20+import Unity.Application 0.1
21+import "../Components"
22+
23+Item {
24+ id: callHint
25+
26+ readonly property bool active: {
27+ var application = ApplicationManager.findApplication("dialer-app");
28+
29+ if (callManager.callIndicatorVisible) {
30+ // at the moment, callIndicatorVisible is only "valid" if dialer is in focus.
31+ if (application && ApplicationManager.focusedApplicationId === "dialer-app") {
32+ // Don't show if application is still starting; might get a fleeting true/false.
33+ return application.state !== ApplicationInfoInterface.Starting;
34+ }
35+ }
36+ if (ApplicationManager.focusedApplicationId !== "dialer-app") {
37+ if (application) {
38+ // Don't show if application is still starting; might get a fleeting true/false.
39+ return application.state !== ApplicationInfoInterface.Starting && callManager.hasCalls;
40+ }
41+ return callManager.hasCalls;
42+ }
43+ return false;
44+ }
45+ readonly property QtObject contactWatcher: _contactWatcher
46+ property int labelSwitchInterval: 6000
47+ implicitWidth: row.x + row.width
48+
49+ Component.onCompleted: {
50+ telepathyHelper.registerChannelObserver("unity8");
51+ }
52+
53+ function showLiveCall() {
54+ Qt.openUrlExternally("dialer:///?view=liveCall");
55+ }
56+
57+ Component {
58+ id: contactColumn
59+
60+ Column {
61+ id: column
62+ objectName: "contactColumn"
63+
64+ anchors.left: parent.left
65+
66+ Component.onCompleted: {
67+ if (index === 0) {
68+ labelPathView.column1 = column;
69+ } else {
70+ labelPathView.column2 = column;
71+ }
72+ }
73+
74+ Label {
75+ height: callHint.height
76+ verticalAlignment: Text.AlignVCenter
77+ text: i18n.tr("Tap to return to call...");
78+ }
79+
80+ Label {
81+ objectName: "contactLabel"
82+ height: callHint.height
83+ verticalAlignment: Text.AlignVCenter
84+ width: Math.max(contentWidth, 1)
85+
86+ text: {
87+ if (!d.activeCall) {
88+ return "";
89+ } else if (d.activeCall.isConference) {
90+ return i18n.tr("Conference");
91+ } else {
92+ return contactWatcher.alias !== "" ? contactWatcher.alias : contactWatcher.phoneNumber;
93+ }
94+ }
95+ }
96+ }
97+ }
98+
99+ Row {
100+ id: row
101+ anchors {
102+ top: parent.top
103+ bottom: parent.bottom
104+ left: parent.left
105+ leftMargin: units.gu(1)
106+ }
107+ spacing: units.gu(1)
108+
109+ Label {
110+ id: time
111+ objectName: "timeLabel"
112+
113+ anchors {
114+ top: parent.top
115+ bottom: parent.bottom
116+ }
117+ verticalAlignment: Text.AlignVCenter
118+ horizontalAlignment: Text.AlignRight
119+ text: {
120+ var m = Math.round(d.callTime/60);
121+ var ss = d.callTime % 60;
122+ if (ss >= 10) {
123+ return m + ":" + ss;
124+ } else {
125+ return m + ":0" + ss;
126+ }
127+ }
128+ }
129+
130+ PathView {
131+ id: labelPathView
132+ objectName: "labelPathView"
133+
134+ anchors {
135+ top: parent.top
136+ bottom: parent.bottom
137+ }
138+ width: column1 && column2 ? Math.max(column1.width, column1.width) : 0
139+ clip: true
140+
141+ property Column column1
142+ property Column column2
143+ property int columnHeight: column1 ? column1.height : 0
144+
145+ delegate: contactColumn
146+ model: 2
147+ offset: 0
148+ interactive: false
149+
150+ path: Path {
151+ startY: -labelPathView.columnHeight / 2
152+ PathLine {
153+ y: labelPathView.columnHeight * 1.5
154+ }
155+ }
156+
157+ Behavior on offset {
158+ id: offsetBehaviour
159+ SmoothedAnimation {
160+ id: offsetAnimation
161+ // ensure we go faster than the label switch
162+ duration: labelSwitchInterval/8
163+ velocity: 0.75
164+ easing.type: Easing.InOutQuad
165+ }
166+ }
167+ }
168+ }
169+
170+ Timer {
171+ id: alternateLabelTimer
172+ running: callHint.active
173+ interval: labelPathView.offset % 1.0 !== 0 ? labelSwitchInterval : labelSwitchInterval/4
174+ repeat: true
175+
176+ onRunningChanged: {
177+ if (running) {
178+ offsetBehaviour.enabled = false;
179+ labelPathView.offset = 0;
180+ offsetBehaviour.enabled = true;
181+ }
182+ }
183+
184+ onTriggered: {
185+ labelPathView.offset = labelPathView.offset + 0.5;
186+ }
187+ }
188+
189+ Telephony.ContactWatcher {
190+ id: _contactWatcher
191+ objectName: "contactWatcher"
192+ phoneNumber: d.activeCall ? d.activeCall.phoneNumber : ""
193+ }
194+
195+ QtObject {
196+ id: d
197+
198+ property QtObject activeCall: {
199+ if (callManager.foregroundCall) {
200+ return callManager.foregroundCall;
201+ }
202+ return callManager.backgroundCall;
203+ }
204+ property int callTime: activeCall ? activeCall.elapsedTime : 0
205+ }
206+}
qml/Panel/IndicatorRow.qml+1−1
@@ -36,7 +36,7 @@ Item {
3636
3737 function setDefaultItem() {
3838 // The leftmost indicator
39− setCurrentItem(0);
39+ setCurrentItemIndex(0);
4040 }
4141
4242 function setCurrentItemIndex(index) {
qml/Panel/Indicators.qml+22−36
@@ -28,7 +28,6 @@ Showable {
2828
2929 property real openedHeight: units.gu(71)
3030 property int panelHeight: units.gu(3)
31− property bool pinnedMode: true //should be set true if indicators menu can cover whole screen
3231 property alias overFlowWidth: indicatorRow.overFlowWidth
3332 property alias showAll: indicatorRow.showAll
3433 // TODO: This should be sourced by device type (eg "desktop", "tablet", "phone"...)
@@ -38,26 +37,20 @@ Showable {
3837 readonly property int lockThreshold: openedHeight / 2
3938 property bool fullyOpened: height == openedHeight
4039 property bool partiallyOpened: height > panelHeight && !fullyOpened
41− property real visualBottom: Math.max(y+height, y+indicatorRow.y+indicatorRow.height)
4240 property bool contentEnabled: true
4341 property bool initalizeItem: true
4442 readonly property alias content: menuContent
4543 property real unitProgress: (height - panelHeight) / (openedHeight - panelHeight)
44+ property bool enableHint: true
45+ property real showHintBottomMargin: 0
46+
47+ signal showTapped(point position)
4648
4749 // TODO: Perhaps we need a animation standard for showing/hiding? Each showable seems to
4850 // use its own values. Need to ask design about this.
4951 showAnimation: StandardAnimation {
5052 property: "height"
51− duration: 350
5253 to: openedHeight
53− easing.type: Easing.OutCubic
54−
55− // Re-size if we've changed the openHeight while shown.
56− onToChanged: {
57− if (indicators.shown) {
58− indicators.show();
59− }
60− }
6154 }
6255
6356 hideAnimation: StandardAnimation {
@@ -67,16 +60,24 @@ Showable {
6760 easing.type: Easing.OutCubic
6861 }
6962
63+ onOpenedHeightChanged: {
64+ if (showAnimation.running) {
65+ showAnimation.restart();
66+ } else if (indicators.shown) {
67+ height = openedHeight;
68+ }
69+ }
70+
7071 height: panelHeight
71− onHeightChanged: updateRevealProgressState(indicators.height - panelHeight, true)
72+ onHeightChanged: updateRevealProgressState(indicators.height - panelHeight - showHintBottomMargin, true)
7273
7374 function updateRevealProgressState(revealProgress, enableRelease) {
7475 if (!showAnimation.running && !hideAnimation.running) {
7576 if (revealProgress === 0) {
7677 indicators.state = "initial";
77− } else if (revealProgress > 0 && revealProgress <= hintValue) {
78+ } else if (enableHint && revealProgress > 0 && revealProgress <= hintValue) {
7879 indicators.state = "hint";
79− } else if (revealProgress > hintValue && revealProgress < lockThreshold) {
80+ } else if ((!enableHint || revealProgress > hintValue) && revealProgress < lockThreshold) {
8081 indicators.state = "reveal";
8182 } else if (revealProgress >= lockThreshold && lockThreshold > 0) {
8283 indicators.state = "locked";
@@ -171,17 +172,6 @@ Showable {
171172 }
172173 }
173174
174− VerticalThinDivider {
175− anchors {
176− top: indicators.top
177− topMargin: panelHeight
178− bottom: handle.bottom
179− right: indicators.left
180− }
181− width: units.dp(2)
182− source: "graphics/VerticalDivider.png"
183− }
184−
185175 VisibleIndicators {
186176 id: visibleIndicators
187177 }
@@ -245,10 +235,6 @@ Showable {
245235 }
246236 }
247237
248− PanelBackground {
249− anchors.fill: indicatorRow
250− }
251−
252238 IndicatorRow {
253239 id: indicatorRow
254240 objectName: "indicatorRow"
@@ -356,24 +342,27 @@ Showable {
356342 id: showDragHandle
357343 anchors.bottom: parent.bottom
358344 // go beyond parent so that it stays reachable, at the top of the screen.
359− anchors.bottomMargin: pinnedMode ? 0 : -panelHeight
345+ anchors.bottomMargin: showHintBottomMargin
360346 anchors.left: parent.left
361347 anchors.right: parent.right
362348 height: panelHeight
363349 direction: Direction.Downwards
364350 enabled: !indicators.shown && indicators.available
365− hintDisplacement: pinnedMode ? indicators.hintValue : 0
351+ hintDisplacement: enableHint ? indicators.hintValue : 0
366352 autoCompleteDragThreshold: maxTotalDragDistance / 2
367353 stretch: true
368354 maxTotalDragDistance: openedHeight - panelHeight
369− distanceThreshold: pinnedMode ? 0 : units.gu(3)
355+ distanceThreshold: panelHeight
370356
371357 onStatusChanged: {
372358 if (status === DirectionalDragArea.Recognized) {
373359 menuContent.activateContent();
374360 }
375361 }
362+
363+ onTapped: showTapped(Qt.point(touchSceneX, touchSceneY));
376364 }
365+
377366 DragHandle {
378367 id: hideDragHandle
379368 anchors.fill: handle
@@ -396,10 +385,6 @@ Showable {
396385 },
397386 State {
398387 name: "hint"
399− PropertyChanges {
400− target: indicatorRow;
401− y: pinnedMode ? 0 : panelHeight
402− }
403388 StateChangeScript {
404389 script: {
405390 if (d.activeDragHandle) {
@@ -432,5 +417,6 @@ Showable {
432417 Component.onCompleted: initialise();
433418 function initialise() {
434419 visibleIndicators.load(profile);
420+ indicatorRow.setDefaultItem();
435421 }
436422}
qml/Panel/Panel.qml+141−70
@@ -16,24 +16,23 @@
1616
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
19+import Unity.Application 0.1
1920import "../Components"
21+import "../Components/ListItems"
2022
2123Item {
2224 id: root
23− readonly property real panelHeight: units.gu(3) + units.dp(2)
24− property real indicatorsMenuWidth: width
25− property alias indicators: indicatorsMenu
25+ readonly property real panelHeight: indicatorArea.y + d.indicatorHeight
26+ property alias indicators: __indicators
27+ property alias callHint: __callHint
2628 property bool fullscreenMode: false
2729
28− readonly property real separatorLineHeight: leftSeparatorLine.height
29− readonly property real __panelMinusSeparatorLineHeight: panelHeight - separatorLineHeight
30−
3130 function hideIndicatorMenu(delay) {
3231 if (delay !== undefined) {
3332 hideTimer.interval = delay;
3433 hideTimer.start();
3534 } else {
36− indicatorsMenu.hide();
35+ indicators.hide();
3736 }
3837 }
3938
@@ -41,102 +40,174 @@ Item {
4140 id: hideTimer
4241 running: false
4342 onTriggered: {
44− indicatorsMenu.hide();
43+ indicators.hide();
4544 }
4645 }
4746
4847 Connections {
49− target: indicatorsMenu
48+ target: indicators
5049 onShownChanged: hideTimer.stop()
5150 }
5251
53− PanelBackground {
54− id: panelBackground
55− anchors {
56− left: parent.left
57− right: parent.right
58− }
59− height: __panelMinusSeparatorLineHeight
60− y: 0
61−
62− Behavior on y { StandardAnimation { duration: 500 } }
63− }
64−
65− PanelSeparatorLine {
66− id: leftSeparatorLine
67− anchors {
68− top: panelBackground.bottom
69− left: parent.left
70− right: indicatorsMenu.left
71− }
72− saturation: 1 - indicatorsMenu.unitProgress
73− }
74−
7552 Rectangle {
7653 id: darkenedArea
7754 property real darkenedOpacity: 0.6
7855 anchors {
56+ top: parent.top
57+ topMargin: panelHeight
7958 left: parent.left
8059 right: parent.right
81− top: panelBackground.bottom
8260 bottom: parent.bottom
8361 }
8462 color: "black"
85− opacity: indicatorsMenu.unitProgress * darkenedOpacity
63+ opacity: indicators.unitProgress * darkenedOpacity
64+
8665 MouseArea {
8766 anchors.fill: parent
88− enabled: indicatorsMenu.shown
89− onClicked: if (indicatorsMenu.fullyOpened) indicatorsMenu.hide();
67+ enabled: indicators.shown
68+ onClicked: if (indicators.fullyOpened) indicators.hide();
9069 }
9170 }
9271
93− Indicators {
94− id: indicatorsMenu
95− objectName: "indicators"
96−
97− anchors.right: parent.right
98− y: panelBackground.y
99− width: root.indicatorsMenuWidth
100− shown: false
101− panelHeight: __panelMinusSeparatorLineHeight
102− openedHeight: parent.height + (pinnedMode ? 0 : root.panelHeight)
103− pinnedMode: !fullscreenMode
104− overFlowWidth: parent.width
105− }
72+ Item {
73+ id: indicatorArea
74+ objectName: "indicatorArea"
10675
107− PanelSeparatorLine {
108− id: indicatorsSeparatorLine
109− visible: true
110− anchors {
111− left: indicatorsMenu.left
112− right: indicatorsMenu.right
76+ anchors.fill: parent
77+
78+ Behavior on anchors.topMargin { StandardAnimation {} }
79+
80+ BorderImage {
81+ id: dropShadow
82+ anchors {
83+ fill: indicators
84+ leftMargin: -units.gu(1)
85+ bottomMargin: -units.gu(1)
86+ }
87+ visible: indicators.height > indicators.panelHeight
88+ source: "graphics/rectangular_dropshadow.sci"
11389 }
114− y: indicatorsMenu.visualBottom
115− }
11690
117− BorderImage {
118− id: dropShadow
119− anchors {
120− top: indicators.top
121− bottom: indicatorsSeparatorLine.bottom
122− left: indicators.left
123− right: indicators.right
124− margins: -units.gu(1)
91+ VerticalThinDivider {
92+ id: indicatorDividor
93+ anchors {
94+ top: indicators.top
95+ bottom: indicators.bottom
96+ right: indicators.left
97+
98+ topMargin: indicatorArea.anchors.topMargin + indicators.panelHeight
99+ }
100+
101+ width: units.dp(2)
102+ source: "graphics/VerticalDivider.png"
103+ }
104+
105+ Rectangle {
106+ id: indicatorAreaBackground
107+ color: callHint.visible ? "green" : "black"
108+ anchors {
109+ top: parent.top
110+ left: parent.left
111+ right: parent.right
112+ }
113+ height: indicators.panelHeight
114+
115+ Behavior on color { ColorAnimation { duration: UbuntuAnimation.FastDuration } }
116+ }
117+
118+ PanelSeparatorLine {
119+ id: nonIndicatorAreaSeparatorLine
120+ anchors {
121+ top: indicatorAreaBackground.bottom
122+ left: parent.left
123+ right: indicators.left
124+ }
125+ saturation: 1 - indicators.unitProgress
125126 }
126− visible: indicatorsMenu.height > indicatorsMenu.panelHeight
127− source: "graphics/rectangular_dropshadow.sci"
127+
128+ MouseArea {
129+ anchors {
130+ top: parent.top
131+ left: parent.left
132+ right: indicators.left
133+ }
134+ height: indicators.panelHeight
135+ enabled: callHint.visible
136+ onClicked: callHint.showLiveCall()
137+ }
138+
139+ Indicators {
140+ id: __indicators
141+ objectName: "indicators"
142+
143+ anchors {
144+ top: parent.top
145+ right: parent.right
146+ }
147+
148+ width: root.width
149+ shown: false
150+ panelHeight: units.gu(3)
151+ openedHeight: root.height
152+ overFlowWidth: {
153+ if (callHint.visible) {
154+ return Math.max(root.width - (callHint.width + units.gu(2)), 0)
155+ }
156+ return root.width
157+ }
158+
159+ enableHint: !callHint.active && !fullscreenMode
160+ showHintBottomMargin: fullscreenMode ? -panelHeight : 0
161+
162+ onShowTapped: {
163+ if (callHint.active) {
164+ callHint.showLiveCall();
165+ }
166+ }
167+ }
168+
169+ ActiveCallHint {
170+ id: __callHint
171+ anchors {
172+ top: parent.top
173+ left: parent.left
174+ }
175+ height: indicators.panelHeight
176+ visible: active && indicators.state == "initial"
177+ }
178+
179+ PanelSeparatorLine {
180+ id: indicatorsSeparatorLine
181+ visible: true
182+ anchors {
183+ top: indicators.bottom
184+ left: indicatorDividor.left
185+ right: indicators.right
186+ }
187+ }
188+ }
189+
190+ QtObject {
191+ id: d
192+ readonly property real indicatorHeight: indicators.panelHeight + indicatorsSeparatorLine.height
128193 }
129194
130195 states: [
131196 State {
132− name: "in" //fully opaque and visible at top edge of screen
197+ name: "onscreen" //fully opaque and visible at top edge of screen
133198 when: !fullscreenMode
134− PropertyChanges { target: panelBackground; y: 0 }
199+ PropertyChanges {
200+ target: indicatorArea;
201+ anchors.topMargin: 0
202+ }
135203 },
136204 State {
137− name: "out" //pushed off screen
205+ name: "offscreen" //pushed off screen
138206 when: fullscreenMode
139− PropertyChanges { target: panelBackground; y: -panelHeight }
207+ PropertyChanges {
208+ target: indicatorArea;
209+ anchors.topMargin: indicators.state === "initial" ? -d.indicatorHeight : 0
210+ }
140211 }
141212 ]
142213}
qml/Shell.qml+7−8
@@ -109,7 +109,7 @@ FocusScope {
109109 anchors.rightMargin: -parent.anchors.rightMargin
110110
111111 // Whether the underlay is fully covered by opaque UI elements.
112− property bool fullyCovered: panel.indicators.fullyOpened && shell.width <= panel.indicatorsMenuWidth
112+ property bool fullyCovered: panel.indicators.fullyOpened && shell.width <= panel.indicators.width
113113
114114 // Whether the user should see the topmost application surface (if there's one at all).
115115 readonly property bool applicationSurfaceShouldBeSeen: stages.shown && !stages.painting && !stages.overlayMode
@@ -484,11 +484,12 @@ FocusScope {
484484 Panel {
485485 id: panel
486486 anchors.fill: parent //because this draws indicator menus
487− indicatorsMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
488487 indicators {
489488 hides: [launcher]
490489 available: edgeDemo.panelEnabled
491490 contentEnabled: edgeDemo.panelContentEnabled
491+ width: parent.width > units.gu(60) ? units.gu(40) : parent.width
492+ panelHeight: units.gu(3)
492493 }
493494 property string focusedAppId: ApplicationManager.focusedApplicationId
494495 property var focusedApplication: ApplicationManager.findApplication(focusedAppId)
@@ -581,12 +582,10 @@ FocusScope {
581582 model: NotificationBackend.Model
582583 margin: units.gu(1)
583584
584− anchors {
585− top: parent.top
586− right: parent.right
587− bottom: parent.bottom
588− topMargin: panel.panelHeight
589− }
585+ y: panel.panelHeight
586+ width: parent.width
587+ height: parent.height - panel.panelHeight
588+
590589 states: [
591590 State {
592591 name: "narrow"
qml/graphics/applicationIcons/phone-app@18.png → qml/graphics/applicationIcons/dialer-app@18.pngrenamed

Binary file not shown.

tests/autopilot/unity8/shell/tests/test_notifications.py+4−4
@@ -137,7 +137,7 @@ class InteractiveNotificationBase(NotificationsBase):
137137 ("x-canonical-switch-to-application", "true"),
138138 (
139139 "x-canonical-secondary-icon",
140− self._get_icon_path('applicationIcons/phone-app.png')
140+ self._get_icon_path('applicationIcons/dialer-app.png')
141141 )
142142 ]
143143
@@ -172,7 +172,7 @@ class InteractiveNotificationBase(NotificationsBase):
172172 hints = [
173173 (
174174 "x-canonical-secondary-icon",
175− self._get_icon_path('applicationIcons/phone-app.png')
175+ self._get_icon_path('applicationIcons/dialer-app.png')
176176 ),
177177 ("x-canonical-snap-decisions", "true"),
178178 ]
@@ -438,7 +438,7 @@ class EphemeralNotificationsTests(NotificationsBase):
438438 hints = [
439439 (
440440 "x-canonical-secondary-icon",
441− self._get_icon_path('applicationIcons/phone-app.png')
441+ self._get_icon_path('applicationIcons/dialer-app.png')
442442 )
443443 ]
444444
@@ -681,7 +681,7 @@ class EphemeralNotificationsTests(NotificationsBase):
681681 body = 'This bubble uses the icon-title-body layout with a ' \
682682 'secondary icon.'
683683 icon_path = self._get_icon_path('avatars/anna_olsson.png')
684− hint_icon = self._get_icon_path('applicationIcons/phone-app.png')
684+ hint_icon = self._get_icon_path('applicationIcons/dialer-app.png')
685685
686686 notification = shell.create_ephemeral_notification(
687687 summary,
tests/mocks/Ubuntu/CMakeLists.txt+1
@@ -1,3 +1,4 @@
11add_subdirectory(DownloadDaemonListener)
22add_subdirectory(Payments)
3+add_subdirectory(Telephony)
34add_subdirectory(Thumbnailer)
tests/mocks/Ubuntu/Telephony/CMakeLists.txtnew file+22
@@ -0,0 +1,22 @@
1+set(FakeUbuntuTelephonyQml_SOURCES
2+ plugin.cpp
3+ ContactWatcherData.cpp
4+ MockCallEntry.cpp
5+ MockCallManager.cpp
6+ MockContactWatcher.cpp
7+ MockTelepathyHelper.cpp
8+)
9+
10+add_library(FakeUbuntuTelephonyQml MODULE ${FakeUbuntuTelephonyQml_SOURCES})
11+
12+qt5_use_modules(FakeUbuntuTelephonyQml Core Quick)
13+
14+# copy files into build directory for shadow builds
15+add_custom_target(UbuntuTelephonyQmlDirFile ALL
16+ COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/qmldir" ${CMAKE_CURRENT_BINARY_DIR}
17+ DEPENDS qmldir
18+)
19+
20+install(TARGETS FakeUbuntuTelephonyQml
21+ DESTINATION ${SHELL_INSTALL_QML}/mocks/Ubuntu/Telephony
22+ )
tests/mocks/Ubuntu/Telephony/ContactWatcherData.cppnew file+43
@@ -0,0 +1,43 @@
1+/*
2+ * Copyright (C) 2014 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+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
17+ */
18+
19+#include "ContactWatcherData.h"
20+
21+ContactWatcherData::ContactWatcherData(QObject *parent)
22+ : QObject(parent)
23+{
24+}
25+
26+ContactWatcherData *ContactWatcherData::instance()
27+{
28+ static ContactWatcherData* contactData = new ContactWatcherData();
29+ return contactData;
30+}
31+
32+QVariant ContactWatcherData::contactData() const
33+{
34+ return m_data;
35+}
36+
37+void ContactWatcherData::setContactData(const QVariant& contactData)
38+{
39+ if(m_data != contactData){
40+ m_data = contactData;
41+ Q_EMIT contactDataChanged();
42+ }
43+}
tests/mocks/Ubuntu/Telephony/ContactWatcherData.hnew file+46
@@ -0,0 +1,46 @@
1+/*
2+ * Copyright (C) 2014 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+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
17+ */
18+
19+#ifndef CONTACTWATCHERDATA_H
20+#define CONTACTWATCHERDATA_H
21+
22+#include <QObject>
23+#include <QVariant>
24+
25+class ContactWatcherData : public QObject
26+{
27+ Q_OBJECT
28+ Q_DISABLE_COPY(ContactWatcherData)
29+ Q_PROPERTY(QVariant contactData READ contactData WRITE setContactData NOTIFY contactDataChanged)
30+
31+public:
32+ ContactWatcherData(QObject *parent = 0);
33+
34+ static ContactWatcherData *instance();
35+
36+ QVariant contactData() const;
37+ void setContactData(const QVariant& contactData);
38+
39+Q_SIGNALS:
40+ void contactDataChanged();
41+
42+private:
43+ QVariant m_data;
44+};
45+
46+#endif // CONTACTWATCHERDATA_H
tests/mocks/Ubuntu/Telephony/MockCallEntry.cppnew file+66
@@ -0,0 +1,66 @@
1+/*
2+ * Copyright (C) 2014 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+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
17+ */
18+
19+#include "MockCallEntry.h"
20+
21+MockCallEntry::MockCallEntry(QObject *parent)
22+ : QObject(parent)
23+ , m_conference(false)
24+ , m_elapsed(0)
25+{
26+ startTimer(1000);
27+}
28+
29+QString MockCallEntry::phoneNumber() const
30+{
31+ return m_phoneNumber;
32+}
33+
34+void MockCallEntry::setPhoneNumber(const QString& phoneNumber)
35+{
36+ if(m_phoneNumber != phoneNumber){
37+ m_phoneNumber = phoneNumber;
38+ Q_EMIT phoneNumberChanged();
39+ }
40+}
41+
42+bool MockCallEntry::isConference() const
43+{
44+ return m_conference;
45+}
46+
47+void MockCallEntry::setIsConference(bool isConference)
48+{
49+ if(m_conference != isConference){
50+ m_conference = isConference;
51+ Q_EMIT isConferenceChanged();
52+ }
53+}
54+
55+int MockCallEntry::elapsedTime() const
56+{
57+ return m_elapsed;
58+}
59+
60+void MockCallEntry::timerEvent(QTimerEvent * event)
61+{
62+ Q_UNUSED(event);
63+
64+ m_elapsed++;
65+ Q_EMIT elapsedTimeChanged();
66+}
tests/mocks/Ubuntu/Telephony/MockCallEntry.hnew file+57
@@ -0,0 +1,57 @@
1+/*
2+ * Copyright (C) 2014 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+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
17+ */
18+
19+#ifndef MOCKCALLENTRY_H
20+#define MOCKCALLENTRY_H
21+
22+#include <QObject>
23+
24+class MockCallEntry : public QObject
25+{
26+ Q_OBJECT
27+ Q_DISABLE_COPY(MockCallEntry)
28+
29+ Q_PROPERTY(QString phoneNumber READ phoneNumber WRITE setPhoneNumber NOTIFY phoneNumberChanged)
30+ Q_PROPERTY(bool isConference READ isConference WRITE setIsConference NOTIFY isConferenceChanged)
31+ Q_PROPERTY(int elapsedTime READ elapsedTime NOTIFY elapsedTimeChanged)
32+
33+public:
34+ MockCallEntry(QObject *parent = 0);
35+
36+ QString phoneNumber() const;
37+ bool isConference() const;
38+ int elapsedTime() const;
39+
40+ void setPhoneNumber(const QString& phoneNumber);
41+ void setIsConference(bool isConference);
42+
43+Q_SIGNALS:
44+ void phoneNumberChanged();
45+ void isConferenceChanged();
46+ void elapsedTimeChanged();
47+
48+protected:
49+ void timerEvent(QTimerEvent * event);
50+
51+private:
52+ QString m_phoneNumber;
53+ bool m_conference;
54+ int m_elapsed;
55+};
56+
57+#endif // MOCKCALLENTRY_H
tests/mocks/Ubuntu/Telephony/MockCallManager.cppnew file+80
@@ -0,0 +1,80 @@
1+/*
2+ * Copyright (C) 2014 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+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
17+ */
18+
19+#include "MockCallManager.h"
20+
21+MockCallManager::MockCallManager(QObject *parent)
22+ : QObject(parent)
23+ , m_foregroundCall(nullptr)
24+ , m_backgroundCall(nullptr)
25+ , m_callIndicatorVisible(false)
26+{
27+}
28+
29+MockCallManager *MockCallManager::instance()
30+{
31+ static MockCallManager* manager = new MockCallManager();
32+ return manager;
33+}
34+
35+QObject* MockCallManager::foregroundCall() const
36+{
37+ return m_foregroundCall;
38+}
39+
40+void MockCallManager::setForegroundCall(QObject* foregroundCall)
41+{
42+ if(m_foregroundCall != foregroundCall){
43+ m_foregroundCall = foregroundCall;
44+ Q_EMIT foregroundCallChanged();
45+ Q_EMIT hasCallsChanged();
46+ }
47+}
48+
49+QObject* MockCallManager::backgroundCall() const
50+{
51+ return m_backgroundCall;
52+}
53+
54+void MockCallManager::setBackgroundCall(QObject* backgroundCall)
55+{
56+ if(m_backgroundCall != backgroundCall){
57+ m_backgroundCall = backgroundCall;
58+ Q_EMIT backgroundCallChanged();
59+ Q_EMIT hasCallsChanged();
60+ }
61+}
62+
63+bool MockCallManager::hasCalls() const
64+{
65+ return m_foregroundCall || m_backgroundCall;
66+}
67+
68+
69+bool MockCallManager::callIndicatorVisible() const
70+{
71+ return m_callIndicatorVisible;
72+}
73+
74+void MockCallManager::setCallIndicatorVisible(bool callIndicatorVisible)
75+{
76+ if(m_callIndicatorVisible != callIndicatorVisible){
77+ m_callIndicatorVisible = callIndicatorVisible;
78+ Q_EMIT callIndicatorVisibleChanged();
79+ }
80+}
tests/mocks/Ubuntu/Telephony/MockCallManager.hnew file+60
@@ -0,0 +1,60 @@
1+/*
2+ * Copyright (C) 2014 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+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
17+ */
18+
19+#ifndef MOCKCALLMANAGER_H
20+#define MOCKCALLMANAGER_H
21+
22+#include <QObject>
23+
24+class MockCallManager : public QObject
25+{
26+ Q_OBJECT
27+ Q_DISABLE_COPY(MockCallManager)
28+
29+ Q_PROPERTY(QObject *foregroundCall READ foregroundCall WRITE setForegroundCall NOTIFY foregroundCallChanged)
30+ Q_PROPERTY(QObject *backgroundCall READ backgroundCall WRITE setBackgroundCall NOTIFY backgroundCallChanged)
31+ Q_PROPERTY(bool hasCalls READ hasCalls NOTIFY hasCallsChanged)
32+ Q_PROPERTY(bool callIndicatorVisible READ callIndicatorVisible WRITE setCallIndicatorVisible NOTIFY callIndicatorVisibleChanged)
33+
34+public:
35+ explicit MockCallManager(QObject *parent = 0);
36+
37+ static MockCallManager *instance();
38+
39+ QObject* foregroundCall() const;
40+ QObject* backgroundCall() const;
41+ bool hasCalls() const;
42+ bool callIndicatorVisible() const;
43+
44+ void setForegroundCall(QObject* foregroundCall);
45+ void setBackgroundCall(QObject* backgroundCall);
46+ void setCallIndicatorVisible(bool callIndicatorVisible);
47+
48+Q_SIGNALS:
49+ void foregroundCallChanged();
50+ void backgroundCallChanged();
51+ void hasCallsChanged();
52+ void callIndicatorVisibleChanged();
53+
54+private:
55+ QObject* m_foregroundCall;
56+ QObject* m_backgroundCall;
57+ bool m_callIndicatorVisible;
58+};
59+
60+#endif // MOCKCALLMANAGER_H
tests/mocks/Ubuntu/Telephony/MockContactWatcher.cppnew file+50
@@ -0,0 +1,50 @@
1+/*
2+ * Copyright (C) 2014 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+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
17+ */
18+
19+#include "MockContactWatcher.h"
20+#include "ContactWatcherData.h"
21+
22+MockContactWatcher::MockContactWatcher(QObject *parent)
23+ : QObject(parent)
24+{
25+ connect(ContactWatcherData::instance(), &ContactWatcherData::contactDataChanged,
26+ this, &MockContactWatcher::aliasChanged);
27+}
28+
29+QString MockContactWatcher::phoneNumber() const
30+{
31+ return m_phoneNumber;
32+}
33+
34+void MockContactWatcher::setPhoneNumber(const QString& phoneNumber)
35+{
36+ if(m_phoneNumber != phoneNumber){
37+ m_phoneNumber = phoneNumber;
38+ Q_EMIT phoneNumberChanged();
39+ Q_EMIT aliasChanged();
40+ }
41+}
42+
43+QString MockContactWatcher::alias() const
44+{
45+ QVariantMap data = ContactWatcherData::instance()->contactData().toMap();
46+ if (data.contains(m_phoneNumber)) {
47+ return data[m_phoneNumber].toMap()["alias"].toString();
48+ }
49+ return "";
50+}
tests/mocks/Ubuntu/Telephony/MockContactWatcher.hnew file+49
@@ -0,0 +1,49 @@
1+/*
2+ * Copyright (C) 2014 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+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
17+ */
18+
19+#ifndef MOCKCONTACTWATCHER_H
20+#define MOCKCONTACTWATCHER_H
21+
22+#include <QObject>
23+#include <QVariant>
24+
25+class MockContactWatcher : public QObject
26+{
27+ Q_OBJECT
28+ Q_DISABLE_COPY(MockContactWatcher)
29+
30+ Q_PROPERTY(QString phoneNumber READ phoneNumber WRITE setPhoneNumber NOTIFY phoneNumberChanged)
31+ Q_PROPERTY(QString alias READ alias NOTIFY aliasChanged)
32+
33+public:
34+ MockContactWatcher(QObject *parent = 0);
35+
36+ QString phoneNumber() const;
37+ QString alias() const;
38+
39+ void setPhoneNumber(const QString& phoneNumber);
40+
41+Q_SIGNALS:
42+ void phoneNumberChanged();
43+ void aliasChanged();
44+
45+private:
46+ QString m_phoneNumber;
47+};
48+
49+#endif // MOCKCONTACTWATCHER_H
tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.cppnew file+35
@@ -0,0 +1,35 @@
1+/*
2+ * Copyright (C) 2014 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+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
17+ */
18+
19+#include "MockTelepathyHelper.h"
20+
21+MockTelepathyHelper::MockTelepathyHelper(QObject *parent)
22+ : QObject(parent)
23+{
24+}
25+
26+MockTelepathyHelper *MockTelepathyHelper::instance()
27+{
28+ static MockTelepathyHelper* helper = new MockTelepathyHelper();
29+ return helper;
30+}
31+
32+void MockTelepathyHelper::registerChannelObserver(const QString& name)
33+{
34+ Q_UNUSED(name);
35+}
tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.hnew file+36
@@ -0,0 +1,36 @@
1+/*
2+ * Copyright (C) 2014 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+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
17+ */
18+
19+#ifndef MOCKTELEPATHYHELPER_H
20+#define MOCKTELEPATHYHELPER_H
21+
22+#include <QObject>
23+
24+class MockTelepathyHelper : public QObject
25+{
26+ Q_OBJECT
27+ Q_DISABLE_COPY(MockTelepathyHelper)
28+public:
29+ MockTelepathyHelper(QObject *parent = 0);
30+
31+ static MockTelepathyHelper *instance();
32+
33+ Q_INVOKABLE void registerChannelObserver(const QString& name);
34+};
35+
36+#endif // MOCKCONTACTWATCHER_H
tests/mocks/Ubuntu/Telephony/plugin.cppnew file+52
@@ -0,0 +1,52 @@
1+/*
2+ * Copyright (C) 2014 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+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
17+ */
18+
19+#include "plugin.h"
20+#include "MockCallEntry.h"
21+#include "MockCallManager.h"
22+#include "MockContactWatcher.h"
23+#include "MockTelepathyHelper.h"
24+#include "ContactWatcherData.h"
25+
26+#include <QtQml/QQmlContext>
27+#include <QtQml/QQmlEngine>
28+#include <qqml.h>
29+
30+void FakeUbuntuTelephonyQmlPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
31+{
32+ Q_ASSERT(engine);
33+
34+ Q_UNUSED(uri);
35+
36+ mRootContext = engine->rootContext();
37+ Q_ASSERT(mRootContext);
38+
39+ mRootContext->setContextProperty("telepathyHelper", MockTelepathyHelper::instance());
40+ mRootContext->setContextProperty("callManager", MockCallManager::instance());
41+ mRootContext->setContextProperty("contactWactherData", ContactWatcherData::instance());
42+}
43+
44+void FakeUbuntuTelephonyQmlPlugin::registerTypes(const char *uri)
45+{
46+ // @uri Telephony
47+ qmlRegisterUncreatableType<MockTelepathyHelper>(uri, 0, 1, "TelepathyHelper", "This is a singleton helper class");
48+ qmlRegisterUncreatableType<MockCallManager>(uri, 0, 1, "CallManager", "This is a singleton manager class");
49+ qmlRegisterUncreatableType<ContactWatcherData>(uri, 0, 1, "ContactWatcherData", "This is a singleton data class");
50+ qmlRegisterType<MockCallEntry>(uri, 0, 1, "CallEntry");
51+ qmlRegisterType<MockContactWatcher>(uri, 0, 1, "ContactWatcher");
52+}
tests/mocks/Ubuntu/Telephony/plugin.hnew file+37
@@ -0,0 +1,37 @@
1+/*
2+ * Copyright (C) 2014 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+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
17+ */
18+
19+#ifndef PLUGIN_H
20+#define PLUGIN_H
21+
22+#include <QQmlContext>
23+#include <QQmlExtensionPlugin>
24+
25+class FakeUbuntuTelephonyQmlPlugin : public QQmlExtensionPlugin
26+{
27+ Q_OBJECT
28+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
29+public:
30+ void initializeEngine(QQmlEngine *engine, const char *uri);
31+ void registerTypes(const char *uri);
32+
33+private:
34+ QQmlContext *mRootContext;
35+};
36+
37+#endif
tests/mocks/Ubuntu/Telephony/qmldirnew file+2
@@ -0,0 +1,2 @@
1+module Ubuntu.Telephony
2+plugin FakeUbuntuTelephonyQml
tests/mocks/Unity/Application/ApplicationManager.cpp+3−3
@@ -361,9 +361,9 @@ void ApplicationManager::buildListOfAvailableApplications()
361361 ApplicationInfo *application;
362362
363363 application = new ApplicationInfo(this);
364− application->setAppId("phone-app");
365− application->setName("Phone");
366− application->setIcon(QUrl("phone"));
364+ application->setAppId("dialer-app");
365+ application->setName("Dialer");
366+ application->setIcon(QUrl("dialer"));
367367 application->setStage(ApplicationInfo::SideStage);
368368 application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
369369 generateQmlStrings(application);
tests/mocks/Unity/Launcher/MockLauncherModel.cpp+1−1
@@ -22,7 +22,7 @@
2222
2323MockLauncherModel::MockLauncherModel(QObject* parent): LauncherModelInterface(parent)
2424{
25− MockLauncherItem *item = new MockLauncherItem("phone-app", "/usr/share/applications/phone-app.desktop", "Phone", "phone-app", this);
25+ MockLauncherItem *item = new MockLauncherItem("dialer-app", "/usr/share/applications/dialer-app.desktop", "Dialer", "dialer-app", this);
2626 item->setProgress(0);
2727 m_list.append(item);
2828 item->setFocused(true);
tests/qmltests/CMakeLists.txt+1
@@ -64,6 +64,7 @@ add_qml_test(Hud Result)
6464add_qml_test(Launcher Launcher)
6565add_qml_test(Notifications Notifications)
6666add_qml_test(Notifications VisualSnapDecisionsQueue)
67+add_qml_test(Panel ActiveCallHint)
6768add_qml_test(Panel IndicatorRow)
6869add_qml_test(Panel Indicators)
6970add_qml_test(Panel MenuContent)
tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml+2−2
@@ -30,7 +30,7 @@ Rectangle {
3030 ApplicationManager.stopApplication(ApplicationManager.get(0).appId)
3131 }
3232
33− ApplicationManager.startApplication("phone-app");
33+ ApplicationManager.startApplication("dialer-app");
3434 ApplicationManager.startApplication("webbrowser-app");
3535 }
3636
@@ -70,7 +70,7 @@ Rectangle {
7070 verify(browserTile != undefined)
7171 browserTile.onPressAndHold.connect(onBrowserLongPressed)
7272
73− phoneTile = findChild(runningApplicationsGrid, "runningAppTile Phone")
73+ phoneTile = findChild(runningApplicationsGrid, "runningAppTile Dialer")
7474 verify(phoneTile != undefined)
7575 phoneTile.onPressAndHold.connect(onPhoneLongPressed)
7676
tests/qmltests/Launcher/tst_Launcher.qml+2−2
@@ -115,7 +115,7 @@ Item {
115115 /* If I click on the icon of an application on the launcher
116116 Launcher::launcherApplicationSelected signal should be emitted with the
117117 corresponding desktop file. E.g. clicking on phone icon should yield
118− launcherApplicationSelected("[...]phone-app.desktop") */
118+ launcherApplicationSelected("[...]dialer-app.desktop") */
119119 function test_clickingOnAppIconCausesSignalEmission() {
120120 launcher.lastSelectedApplication = ""
121121
@@ -131,7 +131,7 @@ Item {
131131 mouseClick(appIcon, appIcon.width/2, appIcon.height/2)
132132
133133 tryCompare(launcher, "lastSelectedApplication",
134− "phone-app")
134+ "dialer-app")
135135
136136 // Tapping on an application icon also dismisses the launcher
137137 revealer.waitUntilLauncherDisappears()
tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml+1−1
@@ -67,7 +67,7 @@ Row {
6767 summary: "Incoming call",
6868 body: "Frank Zappa\n+44 (0)7736 027340",
6969 icon: "../graphics/avatars/funky.png",
70− secondaryIcon: "../graphics/applicationIcons/phone-app.png",
70+ secondaryIcon: "../graphics/applicationIcons/dialer-app.png",
7171 actions: [{ id: "pickup_id", label: "Pick up"},
7272 { id: "decline_1_id", label: "Decline"},
7373 { id: "decline_2_id", label: "Can't talk now, what's up?"},
tests/qmltests/Panel/tst_ActiveCallHint.qmlnew file+165
@@ -0,0 +1,165 @@
1+/*
2+ * Copyright 2014 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 Ubuntu.Telephony 0.1 as Telephony
21+import Unity.Application 0.1
22+import ".."
23+import "../../../qml/Panel"
24+
25+Item {
26+ width: units.gu(40)
27+ height: units.gu(20)
28+
29+ Telephony.CallEntry {
30+ id: call1
31+ phoneNumber: "+447812221111"
32+ }
33+
34+ Telephony.CallEntry {
35+ id: call2
36+ phoneNumber: "+447812221112"
37+ }
38+
39+ Telephony.CallEntry {
40+ id: call3
41+ phoneNumber: "+447812221113"
42+ }
43+
44+ ActiveCallHint {
45+ id: callHint
46+ anchors {
47+ top: parent.top
48+ left:parent.left
49+ right:parent.right
50+ }
51+ height: units.gu(3)
52+ labelSwitchInterval: 2000
53+ }
54+
55+ Component.onCompleted: {
56+ contactWactherData.contactData = {
57+ "+447812221113": {
58+ "alias": "Bob's Uncle"
59+ }
60+ };
61+ callManager.foregroundCall = call3;
62+ }
63+
64+ UT.UnityTestCase {
65+ name: "ActiveCallHint"
66+ when: windowShown
67+
68+ function init() {
69+ callManager.foregroundCall = null;
70+ callManager.backgroundCall = null;
71+ callHint.labelSwitchInterval = 300;
72+
73+ ApplicationManager.stopApplication("dialer-app");
74+ }
75+
76+ function test_activeHint_data() {
77+ return [
78+ { tag: "noCall-callNotVisible", dialer: false, call: null, visible: false, expected: false },
79+ { tag: "noCall-callVisible", dialer: false, call: null, visible: true, expected: false },
80+ { tag: "hasCall-callNotVisible", dialer: false, call: call1, visible: false, expected: true },
81+ { tag: "hasCall-callVisible", dialer: false, call: call1, visible: true, expected: true },
82+
83+ { tag: "dialerNotFocused-noCall-callNotVisible", dialer: true, focused: false, call: null, visible: false, expected: false },
84+ { tag: "dialerNotFocused-noCall-callVisible", dialer: true, focused: false, call: null, visible: true, expected: false },
85+ { tag: "dialerNotFocused-hasCall-callNotVisible", dialer: true, focused: false, call: call1, visible: false, expected: true },
86+ { tag: "dialerNotFocused-hasCall-callVisible", dialer: true, focused: false, call: call1, visible: true, expected: true },
87+
88+ { tag: "dialerFocused-noCall-callNotVisible", dialer: true, focused: true, call: null, visible: false, expected: false },
89+ { tag: "dialerFocused-noCall-callVisible", dialer: true, focused: true, call: null, visible: true, expected: true },
90+ { tag: "dialerFocused-hasCall-callNotVisible", dialer: true, focused: true, call: call1, visible: false, expected: false },
91+ { tag: "dialerFocused-hasCall-callVisible", dialer: true, focused: true, call: call1, visible: true, expected: true },
92+ ];
93+ }
94+
95+ function test_activeHint(data) {
96+ if (data.dialer) {
97+ var application = ApplicationManager.startApplication("dialer-app");
98+ tryCompare(ApplicationManager, "focusedApplicationId", "dialer-app");
99+ tryCompare(application, "state", ApplicationInfo.Running);
100+
101+ if (!data.focused) { ApplicationManager.unfocusCurrentApplication(); }
102+ }
103+ callManager.foregroundCall = data.call;
104+ callManager.callIndicatorVisible = data.visible;
105+
106+ compare(callHint.active, data.expected, "Call hint should be active when callIndicatorVisible=true");
107+ }
108+
109+ function test_currentCall_data() {
110+ return [
111+ { tag: "empty", foreground: null, background: null, active: false, label: "" },
112+ { tag: "foreground", foreground: call1, background: null, active: true, label: "+447812221111" },
113+ { tag: "background", foreground: null, background: call2, active: true, label: "+447812221112" },
114+ { tag: "multiple", foreground: call1, background: call2, active: true, label: "+447812221111" },
115+ ];
116+ }
117+
118+ function test_currentCall(data) {
119+ callManager.foregroundCall = data.foreground;
120+ callManager.backgroundCall = data.background;
121+
122+ var contactLabel = findChild(callHint, "contactLabel");
123+ verify(contactLabel !== null);
124+
125+ compare(contactLabel.text, data.label, "Contact label does not match call");
126+ }
127+
128+ function test_changeContactData() {
129+ callManager.backgroundCall = call3;
130+
131+ var contactLabel = findChild(callHint, "contactLabel");
132+ verify(contactLabel !== null);
133+
134+ contactWactherData.contactData = { "+447812221113": { "alias": "Bob's Uncle" } };
135+ compare(contactLabel.text, "Bob's Uncle", "Contact label does not match call");
136+
137+ contactWactherData.contactData = { "+447812221113": { "alias": "Freddy" } };
138+ compare(contactLabel.text, "Freddy", "Contact label does not match call");
139+ }
140+
141+ function test_timeLapse() {
142+ callManager.backgroundCall = call3;
143+
144+ var timeLabel = findChild(callHint, "timeLabel");
145+ verify(timeLabel !== null);
146+
147+ var currentLabel = timeLabel.text;
148+ tryCompareFunction(function() { return timeLabel.text !== currentLabel }, true);
149+ currentLabel = timeLabel.text;
150+ tryCompareFunction(function() { return timeLabel.text !== currentLabel }, true);
151+ }
152+
153+ function test_displayedLabelChangesOverTime() {
154+ callManager.backgroundCall = call3;
155+
156+ var labelPathView = findChild(callHint, "labelPathView");
157+ verify(labelPathView !== null);
158+
159+ var currentOffset = labelPathView.offset
160+ tryCompareFunction(function() { return labelPathView.offset !== currentOffset }, true);
161+ currentOffset = labelPathView.offset
162+ tryCompareFunction(function() { return labelPathView.offset !== currentOffset }, true);
163+ }
164+ }
165+}
tests/qmltests/Panel/tst_Indicators.qml+10−21
@@ -17,6 +17,7 @@
1717import QtQuick 2.0
1818import QtTest 1.0
1919import Unity.Test 0.1 as UT
20+import Ubuntu.Components 0.1 as UC
2021import ".."
2122import "../../../qml/Panel"
2223import "../../../qml/Components"
@@ -45,13 +46,12 @@ Item {
4546 shown: false
4647 profile: "test1"
4748
48− openedHeight: parent.height - click_me.height
49+ openedHeight: parent.height - button.height
4950 }
5051
51− // Just a rect for clicking to open the indicators.
52− Rectangle {
53− id: click_me
54− color: "red"
52+ UC.Button {
53+ id: button
54+ text: indicators.shown ? "Hide" : "Show"
5555 anchors {
5656 bottom: shell.bottom
5757 left: parent.left
@@ -59,22 +59,11 @@ Item {
5959 }
6060 height: 50
6161
62− Text {
63− text: "Click Me"
64− horizontalAlignment: Text.AlignHCenter
65− verticalAlignment: Text.AlignVCenter
66− anchors.fill: parent
67−
68− MouseArea {
69− anchors.fill: parent
70−
71− onClicked: {
72− if (!indicators.shown) {
73− indicators.show();
74− } else {
75− indicators.hide();
76− }
77− }
62+ onClicked: {
63+ if (!indicators.shown) {
64+ indicators.show();
65+ } else {
66+ indicators.hide();
7867 }
7968 }
8069 }
tests/qmltests/Panel/tst_Panel.qml+147−47
@@ -17,6 +17,8 @@
1717import QtQuick 2.0
1818import QtTest 1.0
1919import Unity.Test 0.1 as UT
20+import Ubuntu.Components 0.1 as UC
21+import Ubuntu.Telephony 0.1 as Telephony
2022import ".."
2123import "../../../qml/Panel"
2224
@@ -32,32 +34,102 @@ Item {
3234
3335 Panel {
3436 id: panel
35− anchors.fill: parent
37+ anchors {
38+ left: parent.left
39+ right: parent.right
40+ }
41+ height: parent.height - row.height
42+ fullscreenMode: false
3643
3744 indicators {
3845 profile: "test1"
46+ panelHeight: units.gu(5)
47+ }
48+ callHint {
49+ height: units.gu(4)
3950 }
51+
52+ property real panelAndSeparatorHeight: panel.indicators.panelHeight + units.dp(2)
53+ }
54+
55+
56+ Row {
57+ id: row
58+ anchors {
59+ bottom: shell.bottom
60+ left: parent.left
61+ right: parent.right
62+ }
63+ height: 50
64+
65+ UC.Button {
66+ text: panel.indicators.shown ? "Hide" : "Show"
67+ anchors {
68+ top: parent.top
69+ bottom: parent.bottom
70+ }
71+ width: parent.width/3
72+
73+ onClicked: {
74+ if (panel.indicators.shown) {
75+ panel.indicators.hide();
76+ } else {
77+ panel.indicators.show();
78+ }
79+ }
80+ }
81+
82+ UC.Button {
83+ text: panel.fullscreenMode ? "Maximize" : "FullScreen"
84+ anchors {
85+ top: parent.top
86+ bottom: parent.bottom
87+ }
88+ width: parent.width/3
89+
90+ onClicked: panel.fullscreenMode = !panel.fullscreenMode
91+ }
92+
93+ UC.Button {
94+ text: callManager.hasCalls ? "Called" : "No Calls"
95+ anchors {
96+ top: parent.top
97+ bottom: parent.bottom
98+ }
99+ width: parent.width/3
100+
101+ onClicked: {
102+ if (callManager.foregroundCall) {
103+ callManager.foregroundCall = null;
104+ } else {
105+ callManager.foregroundCall = phoneCall;
106+ }
107+ }
108+ }
109+ }
110+
111+ Telephony.CallEntry {
112+ id: phoneCall
113+ phoneNumber: "+447812221111"
40114 }
41115
42116 UT.UnityTestCase {
43117 name: "Panel"
44118 when: windowShown
45119
46− function get_window_data() {
47− return [
48− {tag: "pinned", fullscreenFlag: false, alreadyOpen: false },
49− {tag: "fullscreen", fullscreenFlag: true, alreadyOpen: false },
50− {tag: "pinned-alreadyOpen", fullscreenFlag: false, alreadyOpen: true },
51− {tag: "fullscreen-alreadyOpen", fullscreenFlag: true, alreadyOpen: true }
52− ];
53− }
54−
55120 function init() {
56121 panel.indicators.initialise();
122+ panel.fullscreenMode = false;
57123
58124 panel.indicators.hide();
125+ // Wait for animation to complete
59126 tryCompare(panel.indicators.hideAnimation, "running", false);
60− tryCompare(panel.indicators, "state", "initial");
127+ callManager.foregroundCall = null;
128+
129+ // Wait for the indicators to get into position.
130+ // (switches between normal and fullscreen modes are animated)
131+ var indicatorArea = findChild(panel, "indicatorArea");
132+ tryCompare(indicatorArea, "y", 0);
61133 }
62134
63135 function get_indicator_item(index) {
@@ -80,46 +152,37 @@ Item {
80152 // Pressing on the indicator panel should activate the indicator hints
81153 // and expose a portion of the conent.
82154 function test_hint() {
83− panel.fullscreenMode = false;
84− // Wait for the indicators to get into position.
85− // (switches between normal and fullscreen modes are animated)
86− tryCompare(panel.indicators, "y", 0);
87−
88155 var indicatorItemCoord = get_indicator_item_position(0);
89156
90− touchPress(panel, indicatorItemCoord.x, panel.panelHeight / 2);
157+ touchPress(panel, indicatorItemCoord.x, panel.indicators.panelHeight / 2);
91158
92159 // hint animation should be run, meaning that indicators will move downwards
93160 // by hintValue pixels without any drag taking place
94− tryCompare(panel.indicators, "height",
95− panel.indicators.panelHeight + panel.indicators.hintValue);
161+ tryCompareFunction(function() { return panel.indicators.height },
162+ panel.indicators.panelHeight + panel.indicators.hintValue);
96163 tryCompare(panel.indicators, "partiallyOpened", true);
97164 tryCompare(panel.indicators, "fullyOpened", false);
98165
99− touchRelease(panel, indicatorItemCoord.x, panel.panelHeight/2);
166+ touchRelease(panel, indicatorItemCoord.x, panel.indicators.panelHeight/2);
100167 }
101168
102169 // Pressing on the top edge of the screen should have no effect if the panel
103− // is hidden (!pinned), which is the case when a fullscreen app is being shown
170+ // is hidden (fullscreen), which is the case when a fullscreen app is being shown
104171 function test_noHintOnFullscreenMode() {
105172 panel.fullscreenMode = true;
106173 // Wait for the indicators to get into position.
107174 // (switches between normal and fullscreen modes are animated)
108− tryCompare(panel.indicators, "y", -panel.panelHeight);
175+ var indicatorArea = findChild(panel, "indicatorArea");
176+ tryCompare(indicatorArea, "y", -panel.panelHeight);
109177
110178 var indicatorItemCoord = get_indicator_item_position(0);
111179
112− touchPress(panel, indicatorItemCoord.x, panel.panelHeight / 2);
180+ touchPress(panel, indicatorItemCoord.x, panel.indicators.panelHeight / 2);
113181
114182 // Give some time for a hint animation to change things, if any
115183 wait(500);
116184
117185 // no hint animation when fullscreen
118− compare(panel.indicators.y, -panel.panelHeight);
119− var indicatorRow = findChild(panel.indicators, "indicatorRow");
120− verify(indicatorRow !== null);
121− compare(indicatorRow.y, 0);
122− compare(panel.indicators.height, panel.indicators.panelHeight);
123186 compare(panel.indicators.partiallyOpened, false,
124187 "Indicator should not be partially opened when panel is pressed in" +
125188 " fullscreenmode");
@@ -129,34 +192,69 @@ Item {
129192 touchRelease(panel, indicatorItemCoord.x, panel.panelHeight/2);
130193 }
131194
132− function test_drag_show_data() { return get_window_data(); }
195+ // Pressing on the top edge of the indicator should have no effect if the panel
196+ // has an active call
197+ function test_noHintOnActiveCall() {
198+ callManager.foregroundCall = phoneCall;
199+
200+ var indicatorItemCoord = get_indicator_item_position(0);
201+
202+ touchPress(panel, indicatorItemCoord.x, panel.callHint.height + panel.indicators.panelHeight / 2);
203+
204+ // Give some time for a hint animation to change things, if any
205+ wait(500);
206+
207+ // no hint animation when fullscreen
208+ compare(panel.indicators.partiallyOpened, false,
209+ "Indicator should not be partially opened when panel is pressed in" +
210+ " fullscreenmode");
211+ compare(panel.indicators.fullyOpened, false, "Indicator should not be partially" +
212+ " opened when panel is pressed in fullscreenmode");
213+
214+ touchRelease(panel, indicatorItemCoord.x, panel.panelHeight/2);
215+ }
216+
217+ function test_drag_show_data() {
218+ return [
219+ { tag: "pinned", fullscreenFlag: false, alreadyOpen: false, call: null,
220+ indicatorY: 0 },
221+ { tag: "fullscreen", fullscreenFlag: true, alreadyOpen: false, call: null,
222+ indicatorY: -panel.panelAndSeparatorHeight },
223+ { tag: "pinned-alreadyOpen", fullscreenFlag: false, alreadyOpen: true, call: null,
224+ indicatorY: 0 },
225+ { tag: "fullscreen-alreadyOpen", fullscreenFlag: true, alreadyOpen: true, call: null,
226+ indicatorY: 0 },
227+ { tag: "pinned-callActive", fullscreenFlag: false, alreadyOpen: false, call: phoneCall,
228+ indicatorY: 0},
229+ { tag: "fullscreen-callActive", fullscreenFlag: true, alreadyOpen: false, call: phoneCall,
230+ indicatorY: -panel.panelAndSeparatorHeight }
231+ ];
232+ }
133233
134234 // Dragging from a indicator item in the panel will gradually expose the
135235 // indicators, first by running the hint animation, then after dragging down will
136236 // expose more of the panel, binding it to the selected indicator and opening it's menu.
137237 function test_drag_show(data) {
138238 panel.fullscreenMode = data.fullscreenFlag;
239+ callManager.foregroundCall = data.call;
240+
139241 if (data.alreadyOpen) {
140242 panel.indicators.show();
141243 tryCompare(panel.indicators, "fullyOpened", true);
142244 }
143245
144− var indicatorRow = findChild(panel.indicators, "indicatorRow");
246+ var indicatorRow = findChild(panel.indicators, "indicatorRow");
145247 verify(indicatorRow !== null);
146248
147249 var menuContent = findChild(panel.indicators, "menuContent");
148− verify(indicatorRow !== null);
250+ verify(menuContent !== null);
149251
150− var menuContent = findChild(panel.indicators, "menuContent");
151− verify(indicatorRow !== null);
252+ var indicatorArea = findChild(panel, "indicatorArea");
253+ verify(indicatorArea !== null);
152254
153255 // Wait for the indicators to get into position.
154256 // (switches between normal and fullscreen modes are animated)
155− if (data.fullscreenFlag) {
156− tryCompare(panel.indicators, "y", -panel.panelHeight);
157− } else {
158− tryCompare(panel.indicators, "y", 0);
159− }
257+ tryCompareFunction(function() { return indicatorArea.y }, data.indicatorY);
160258
161259 // do this for each indicator item
162260 for (var i = 0; i < indicatorRow.row.count; i++) {
@@ -170,12 +268,12 @@ Item {
170268 var indicatorItemCoord = get_indicator_item_position(i);
171269
172270 touchPress(panel,
173− indicatorItemCoord.x, panel.panelHeight / 2);
271+ indicatorItemCoord.x, panel.indicators.panelHeight / 2);
174272
175273 // 1) Drag the mouse down
176274 touchFlick(panel,
177− indicatorItemCoord.x, panel.panelHeight / 2,
178− indicatorItemCoord.x, panel.height * 0.8,
275+ indicatorItemCoord.x, panel.indicators.panelHeight / 2,
276+ indicatorItemCoord.x, panel.height,
179277 false /* beginTouch */, false /* endTouch */);
180278
181279 // Indicators height should follow the drag, and therefore increase accordingly.
@@ -184,7 +282,7 @@ Item {
184282 function() {return panel.indicators.height >= panel.height * 0.5},
185283 true);
186284
187− touchRelease(panel, indicatorItemCoord.x, panel.height * 0.8);
285+ touchRelease(panel, indicatorItemCoord.x, panel.height);
188286
189287 compare(indicatorRow.currentItem, indicatorItem,
190288 "Incorrect item activated at position " + i);
@@ -192,7 +290,9 @@ Item {
192290
193291 // init for next indicatorItem
194292 if (!data.alreadyOpen) {
195− init();
293+ panel.indicators.hide();
294+ tryCompare(panel.indicators.hideAnimation, "running", false);
295+ tryCompare(panel.indicators, "state", "initial");
196296 }
197297 }
198298 }
@@ -214,19 +314,19 @@ Item {
214314 var indicatorItemCoordNext = get_indicator_item_position(indicatorRow.row.count - 1);
215315
216316 touchPress(panel,
217− indicatorItemCoordFirst.x, panel.panelHeight / 2);
317+ indicatorItemCoordFirst.x, panel.indicators.panelHeight / 2);
218318
219319 // 1) Drag the mouse down to hint a bit
220320 touchFlick(panel,
221− indicatorItemCoordFirst.x, panel.panelHeight / 2,
222− indicatorItemCoordFirst.x, panel.panelHeight * 2,
321+ indicatorItemCoordFirst.x, panel.indicators.panelHeight / 2,
322+ indicatorItemCoordFirst.x, panel.indicators.panelHeight * 2,
223323 false /* beginTouch */, false /* endTouch */);
224324
225325 tryCompare(indicatorRow, "currentItem", indicatorItemFirst)
226326
227327 // 1) Flick mouse down to bottom
228328 touchFlick(panel,
229− indicatorItemCoordFirst.x, panel.panelHeight * 2,
329+ indicatorItemCoordFirst.x, panel.indicators.panelHeight * 2,
230330 indicatorItemCoordNext.x, panel.height,
231331 false /* beginTouch */, true /* endTouch */,
232332 units.gu(10) /* speed */, 30 /* iterations */); // more samples needed for accurate velocity