Merge lp:~nick-dedekind/unity8/indicator.call-hint into lp:unity8

Proposed by Nick Dedekind
Status: Merged
Approved by: Michał Sawicz
Approved revision: 890
Merged at revision: 1026
Proposed branch: lp:~nick-dedekind/unity8/indicator.call-hint
Merge into: lp:unity8
Diff against target: 4017 lines (+1866/-1110)
52 files modified
build.sh (+1/-0)
debian/control (+4/-3)
plugins/Ubuntu/Gestures/DirectionalDragArea.cpp (+1/-0)
plugins/Ubuntu/Gestures/DirectionalDragArea.h (+1/-0)
qml/Components/PageHeader.qml (+250/-351)
qml/Components/PageHeaderLabel.qml (+0/-41)
qml/Components/SearchHistoryModel.qml (+0/-41)
qml/Components/SearchHistoryModel/SearchHistoryModel.qml (+42/-0)
qml/Components/SearchHistoryModel/qmldir (+1/-0)
qml/Dash/Dash.qml (+0/-3)
qml/Dash/DashContent.qml (+1/-63)
qml/Dash/GenericScopeView.qml (+22/-29)
qml/Dash/PreviewListView.qml (+3/-20)
qml/Dash/ScopeItem.qml (+4/-39)
qml/Hud/HudParametrizedActionsPage.qml (+2/-2)
qml/Panel/ActiveCallHint.qml (+206/-0)
qml/Panel/IndicatorRow.qml (+1/-1)
qml/Panel/Indicators.qml (+22/-36)
qml/Panel/Panel.qml (+148/-107)
qml/ScopeTool.qml (+0/-1)
qml/Shell.qml (+7/-9)
tests/autopilot/unity8/shell/tests/test_notifications.py (+4/-4)
tests/mocks/Ubuntu/CMakeLists.txt (+1/-0)
tests/mocks/Ubuntu/Telephony/CMakeLists.txt (+22/-0)
tests/mocks/Ubuntu/Telephony/ContactWatcherData.cpp (+43/-0)
tests/mocks/Ubuntu/Telephony/ContactWatcherData.h (+46/-0)
tests/mocks/Ubuntu/Telephony/MockCallEntry.cpp (+66/-0)
tests/mocks/Ubuntu/Telephony/MockCallEntry.h (+57/-0)
tests/mocks/Ubuntu/Telephony/MockCallManager.cpp (+80/-0)
tests/mocks/Ubuntu/Telephony/MockCallManager.h (+60/-0)
tests/mocks/Ubuntu/Telephony/MockContactWatcher.cpp (+50/-0)
tests/mocks/Ubuntu/Telephony/MockContactWatcher.h (+49/-0)
tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.cpp (+35/-0)
tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.h (+36/-0)
tests/mocks/Ubuntu/Telephony/plugin.cpp (+52/-0)
tests/mocks/Ubuntu/Telephony/plugin.h (+37/-0)
tests/mocks/Ubuntu/Telephony/qmldir (+2/-0)
tests/mocks/Unity/Application/ApplicationManager.cpp (+3/-3)
tests/mocks/Unity/Launcher/MockLauncherModel.cpp (+1/-1)
tests/qmltests/CMakeLists.txt (+2/-1)
tests/qmltests/Components/tst_PageHeader.qml (+91/-58)
tests/qmltests/Components/tst_PageHeader/logo-ubuntu-orange.svg (+60/-0)
tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml (+2/-2)
tests/qmltests/Dash/tst_Dash.qml (+0/-39)
tests/qmltests/Dash/tst_DashContent.qml (+4/-66)
tests/qmltests/Dash/tst_GenericScopeView.qml (+0/-26)
tests/qmltests/Launcher/tst_Launcher.qml (+2/-2)
tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml (+1/-1)
tests/qmltests/Panel/tst_ActiveCallHint.qml (+165/-0)
tests/qmltests/Panel/tst_Indicators.qml (+10/-21)
tests/qmltests/Panel/tst_Panel.qml (+169/-104)
tests/qmltests/tst_Shell.qml (+0/-36)
To merge this branch: bzr merge lp:~nick-dedekind/unity8/indicator.call-hint
Reviewer Review Type Date Requested Status
Michał Sawicz Approve
PS Jenkins bot (community) continuous-integration Approve
Daniel d'Andrada (community) Approve
Olga Kemmet (community) on device Approve
Albert Astals Cid (community) Needs Fixing
Review via email: mp+218627@code.launchpad.net

Commit message

Added active call hint

A hint is displayed in the indicator panel when an call is active on the Telephony Serivce

Description of the change

Spec:
https://docs.google.com/a/canonical.com/document/d/18Gk__rGcg7UVxrmw4HIBnhAL6ek3exQJNbXbkT8J87o/edit

 * Are there any related MPs required for this MP to build/function as expected? Please list.
functionality: lp:~boiko/dialer-app/active_call_indicator

 * Did you perform an exploratory manual test run of your code change and any related functionality?
Yes

 * Did you make sure that your branch does not contain spurious tags?
Yes

 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A

 * If you changed the UI, has there been a design review?
Yes. Olga has approved the design.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

In tests/qmltests/Panel/tst_ActiveCallHint.qml

+ * Copyright 2013 Canonical Ltd.

s/2013/2014

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

Text conflict in debian/control
Text conflict in qml/Panel/Panel.qml
Text conflict in qml/Shell.qml
Text conflict in tests/qmltests/CMakeLists.txt
4 conflicts encountered.

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Olga Kemmet (olga-kemmet) :
review: Approve (on device)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
884. By Nick Dedekind

added comment to active property

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

Getting merge conflicts with latest trunk now:

Text conflict in debian/control
Text conflict in qml/Panel/Panel.qml

review: Needs Fixing
885. By Nick Dedekind

merged with trunk

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> Getting merge conflicts with latest trunk now:
>
> Text conflict in debian/control
> Text conflict in qml/Panel/Panel.qml

Thanks. Done.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
886. By Nick Dedekind

search disabled when not visible

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

I'm seeing a floating "emergency call" icon/button sticking out from the lower right corner of the screen.

If it's caused by some external module you're using then I don't think this MP should be blocked by this bug.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> I'm seeing a floating "emergency call" icon/button sticking out from the lower
> right corner of the screen.
>
> If it's caused by some external module you're using then I don't think this MP
> should be blocked by this bug.

Other than that, it's working fine.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

"""
    states: [
        State {
            name: "onscreen" //fully opaque and visible at top edge of screen
            when: !fullscreenMode
        },
        State {
            name: "offscreen" //pushed off screen
            when: fullscreenMode
            PropertyChanges { target: indicatorArea; anchors.topMargin: indicators.state === "initial" ? -d.indicatorHeight : 0 }
        }
    ]
""""

For correctness I think you should specify the value indicatorArea.anchors.topMargin when in the "onscreen" state.

review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> """
> states: [
> State {
> name: "onscreen" //fully opaque and visible at top edge of screen
> when: !fullscreenMode
> },
> State {
> name: "offscreen" //pushed off screen
> when: fullscreenMode
> PropertyChanges { target: indicatorArea; anchors.topMargin:
> indicators.state === "initial" ? -d.indicatorHeight : 0 }
> }
> ]
> """"
>
> For correctness I think you should specify the value
> indicatorArea.anchors.topMargin when in the "onscreen" state.

Also that PropertyChanges line is too long (according to our style guide no line should be longer than 120 chars).

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

"""
            onShowTapped: {
                if (callHint.active) {
                    callHint.activate();
                }
            }

"""
A sign of bad naming: How can you activate something that is already active?

Suggestions:
I would rather call it something more descriptive like "activateDialer()" or "showLiveCall()".

review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

in tests/qmltests/CMakeLists.txt

"""
-add_qml_test(. Shell IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks
- ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
+#add_qml_test(. Shell IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks
+# ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/LightDM/single")
"""

Unrelated change.

review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

"""
        function test_tapToReturn() {
"""

I would rather name it according to what it is actually testing (even if it's a bit of a mouthful). E.g: "test_displayedLabelChangesOvertime"

-----

You got bonus points for having "make tryActiveCallHint" actually showing something meaningful!

The tests/qmltests/Panel/tst_Indicators.qml improvement is unrelated but welcome.

"make tryPanel" is looking good!

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

As I'm going on holidays, fell free to merge once those minor things I pointed out have been addressed.
Also make sure you find the culprit of that floating "Emergency Call" button before merging.

review: Approve
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

 * Did you perform an exploratory manual test run of the code change and any related functionality?
Yes.

 * Did CI run pass? If not, please explain why.
Not yet as there were merge conflics that have been resolved already.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
887. By Nick Dedekind

merged witrh trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
888. By Nick Dedekind

removed qtdeclarative5-ubuntu-telephony0.1 build-dep

889. By Nick Dedekind

review comments

890. By Nick Dedekind

reverted change to shell causing lockscreen overlay

Revision history for this message
Nick Dedekind (nick-dedekind) wrote :

> I'm seeing a floating "emergency call" icon/button sticking out from the lower
> right corner of the screen.
>
> If it's caused by some external module you're using then I don't think this MP
> should be blocked by this bug.

It was caused by a change to the lockscreen placement.
Fixed.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

 * Did you perform an exploratory manual test run of the code change and any related functionality?
Yes. Nice!

 * Did CI run pass? If not, please explain why.
Yes.

review: Approve
891. By Nick Dedekind

merged lp:~mzanetti/unity8/new-header

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'build.sh'
2--- build.sh 2014-07-03 14:46:32 +0000
3+++ build.sh 2014-07-08 15:02:30 +0000
4@@ -48,6 +48,7 @@
5 qtdeclarative5-gsettings1.0 \
6 qtdeclarative5-ubuntu-ui-toolkit-plugin \
7 qtdeclarative5-ubuntu-settings-components \
8+ qtdeclarative5-ubuntu-telephony0.1 \
9 qtdeclarative5-ubuntu-thumbnailer0.1 \
10 unity-notifications-impl \
11 ubuntu-mobile-icons \
12
13=== modified file 'debian/control'
14--- debian/control 2014-07-07 11:33:52 +0000
15+++ debian/control 2014-07-08 15:02:30 +0000
16@@ -40,7 +40,7 @@
17 qtdeclarative5-private-dev (>= 5.2.1),
18 qtdeclarative5-qtmultimedia-plugin,
19 qtdeclarative5-ubuntu-settings-components (>= 0.3),
20- qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 0.1.48) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 0.1.48),
21+ qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 0.1.49) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 0.1.49),
22 ttf-ubuntu-font-family,
23 Standards-Version: 3.9.4
24 Homepage: http://launchpad.net/unity
25@@ -53,7 +53,7 @@
26 Package: indicators-client
27 Architecture: amd64 armhf i386
28 Depends: qmenumodel-qml (>= 0.2.7),
29- qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 0.1.48) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 0.1.48),
30+ qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 0.1.49) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 0.1.49),
31 unity8 (= ${binary:Version}),
32 ${misc:Depends},
33 ${shlibs:Depends},
34@@ -81,6 +81,7 @@
35 qml-module-qtquick-xmllistmodel,
36 qtdeclarative5-gsettings1.0,
37 qtdeclarative5-ubuntu-settings-components (>= 0.3),
38+ qtdeclarative5-ubuntu-telephony0.1,
39 unity-launcher-impl-3,
40 unity8-common (= ${source:Version}),
41 unity8-private (= ${binary:Version}),
42@@ -101,7 +102,7 @@
43 Package: unity8-common
44 Architecture: all
45 Depends: qtdeclarative5-ubuntu-thumbnailer0.1 | ubuntu-thumbnailer-impl,
46- qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 0.1.48) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 0.1.48),
47+ qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 0.1.49) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 0.1.49),
48 qtdeclarative5-unity-notifications-plugin | unity-notifications-impl,
49 ubuntu-thumbnailer-impl-0,
50 unity-application-impl-2,
51
52=== modified file 'plugins/Ubuntu/Gestures/DirectionalDragArea.cpp'
53--- plugins/Ubuntu/Gestures/DirectionalDragArea.cpp 2014-03-04 11:42:29 +0000
54+++ plugins/Ubuntu/Gestures/DirectionalDragArea.cpp 2014-07-08 15:02:30 +0000
55@@ -378,6 +378,7 @@
56 // touch has ended before recognition concluded
57 DDA_DEBUG("Touch has ended before recognition concluded");
58 setStatus(WaitingForTouch);
59+ Q_EMIT tapped();
60 return;
61 }
62
63
64=== modified file 'plugins/Ubuntu/Gestures/DirectionalDragArea.h'
65--- plugins/Ubuntu/Gestures/DirectionalDragArea.h 2014-02-24 16:25:25 +0000
66+++ plugins/Ubuntu/Gestures/DirectionalDragArea.h 2014-07-08 15:02:30 +0000
67@@ -212,6 +212,7 @@
68 void touchYChanged(qreal value);
69 void touchSceneXChanged(qreal value);
70 void touchSceneYChanged(qreal value);
71+ void tapped();
72
73 protected:
74 virtual void touchEvent(QTouchEvent *event);
75
76=== modified file 'qml/Components/PageHeader.qml'
77--- qml/Components/PageHeader.qml 2014-06-19 11:17:28 +0000
78+++ qml/Components/PageHeader.qml 2014-07-08 15:02:30 +0000
79@@ -14,386 +14,285 @@
80 * along with this program. If not, see <http://www.gnu.org/licenses/>.
81 */
82
83-import QtQuick 2.0
84-import Ubuntu.Components 0.1
85-import Ubuntu.Components.Popups 0.1
86-import Ubuntu.Components.ListItems 0.1 as ListItem
87-import Unity 0.2
88+import QtQuick 2.2
89+import Ubuntu.Components 1.1
90+import Ubuntu.Components.Themes.Ambiance 1.1
91+import Ubuntu.Components.Popups 1.0
92+import Ubuntu.Components.ListItems 1.0
93+import "SearchHistoryModel"
94
95 Item {
96 id: root
97+ implicitHeight: headerContainer.height + units.gu(2) + bottomContainer.height
98+
99+ property bool showBackButton: false
100+ property string title
101+ property string imageSource
102+
103 property bool searchEntryEnabled: false
104- property alias searchQuery: searchField.text
105- property ListModel searchHistory
106- property var scope: null
107- property alias childItem: itemContainer.children
108+ property ListModel searchHistory: SearchHistoryModel
109+ property alias searchQuery: searchTextField.text
110+ property bool searchInProgress: false
111+
112 property alias bottomItem: bottomContainer.children
113- property alias showBackButton: backButton.visible
114-
115- signal backClicked
116-
117- height: header.height + units.gu(2) + bottomContainer.height
118- implicitHeight: header.height + units.gu(2) + bottomContainer.height
119+
120+ signal backClicked()
121
122 function triggerSearch() {
123- if (searchEntryEnabled) searchField.forceActiveFocus()
124+ if (searchEntryEnabled) {
125+ headerContainer.showSearch = true;
126+ searchTextField.forceActiveFocus();
127+ }
128 }
129
130- function resetSearch() {
131- if (!searchHistory) return;
132-
133- searchHistory.addQuery(searchField.text);
134- unfocus();
135- searchField.text = "";
136+ function resetSearch(keepFocus) {
137+ if (searchHistory) {
138+ searchHistory.addQuery(searchTextField.text);
139+ }
140+ if (!keepFocus) {
141+ unfocus();
142+ }
143+ searchTextField.text = "";
144+ if (headerContainer.popover != null) {
145+ PopupUtils.close(headerContainer.popover);
146+ }
147 }
148
149 function unfocus() {
150- searchField.focus = false;
151- }
152-
153- Connections {
154- target: greeter
155- onShownChanged: if (shown) resetSearch()
156+ searchTextField.focus = false;
157+ if (!searchTextField.text) {
158+ headerContainer.showSearch = false;
159+ }
160+ }
161+
162+ function openSearchHistory() {
163+ if (openSearchAnimation.running) {
164+ openSearchAnimation.openSearchHistory = true;
165+ } else if (root.searchHistory.count > 0 && headerContainer.popover == null) {
166+ headerContainer.popover = PopupUtils.open(popoverComponent, searchTextField,
167+ {
168+ "contentWidth": searchTextField.width,
169+ "edgeMargins": units.gu(1)
170+ }
171+ );
172+ }
173+ }
174+
175+ onImageSourceChanged: {
176+ if (imageSource) {
177+ header.contents = imageComponent.createObject();
178+ } else {
179+ header.contents.destroy();
180+ header.contents = null;
181+ }
182+ }
183+
184+ InverseMouseArea {
185+ anchors { fill: parent; margins: units.gu(1); bottomMargin: units.gu(3) + bottomContainer.height }
186+ visible: headerContainer.showSearch
187+ onPressed: {
188+ if (headerContainer.popover) {
189+ PopupUtils.close(headerContainer.popover);
190+ }
191+ if (!searchTextField.text) {
192+ headerContainer.showSearch = false;
193+ }
194+ searchTextField.focus = false;
195+ mouse.accepted = false;
196+ }
197 }
198
199 Flickable {
200- id: header
201- anchors {
202- left: parent.left
203- right: parent.right
204- top: parent.top
205- }
206+ id: headerContainer
207+ objectName: "headerContainer"
208+ clip: true
209+ anchors { left: parent.left; top: parent.top; right: parent.right }
210 height: units.gu(6.5)
211-
212+ contentHeight: headersColumn.height
213 interactive: false
214- contentHeight: headerContainer.height
215- clip: true
216-
217- contentY: searchField.activeFocus || searchField.text != "" ? searchContainer.y : headerContainer.y
218-
219- Behavior on contentY { NumberAnimation { duration: 200; easing.type: Easing.OutQuad } }
220-
221- AbstractButton {
222- id: backButton
223- objectName: root.objectName + "_backButton"
224- visible: false
225- height: header.height
226- y: header.contentY
227- anchors {
228- left: parent.left
229- leftMargin: visible ? units.gu(2) : 0
230- }
231- width: visible ? image.width + units.gu(2) : 0
232- onClicked: root.backClicked();
233- Image {
234- id: image
235- anchors.centerIn: parent
236- source: "graphics/headerback.png"
237+ contentY: showSearch ? 0 : height
238+
239+ property bool showSearch: false
240+ property var popover: null
241+
242+ Behavior on contentY {
243+ UbuntuNumberAnimation {
244+ id: openSearchAnimation
245+ property bool openSearchHistory: false
246+
247+ onRunningChanged: {
248+ if (!running && openSearchAnimation.openSearchHistory) {
249+ openSearchAnimation.openSearchHistory = false;
250+ root.openSearchHistory();
251+ }
252+ }
253 }
254 }
255
256- // FIXME this could potentially be simplified to avoid all the containers
257- Item {
258- id: headerContainer
259-
260- anchors {
261- left: backButton.right
262- right: parent.right
263- }
264- height: childrenRect.height
265-
266- Item {
267- id: itemContainer
268-
269- width: searchContainer.narrowMode ? header.width : header.width - searchContainer.width
270- height: header.height
271- }
272-
273- Item {
274- id: searchContainer
275- objectName: "searchContainer"
276-
277- visible: searchEntryEnabled
278- property bool popoverShouldOpen: false
279- property bool popoverShouldClose: false
280-
281- property bool narrowMode: parent.width < units.gu(80)
282-
283- property bool active: searchField.text != "" || searchField.activeFocus
284- property var popover: null
285-
286- anchors.right: headerContainer.right
287- height: header.height
288-
289- state:
290- if (active && narrowMode) "narrowActive"
291- else if (!active && narrowMode) "narrowInactive"
292- else if (active && !narrowMode) "active"
293- else if (!active && !narrowMode) "inactive"
294-
295- onStateChanged: {
296- if (state == "active" || state == "narrowActive") {
297- popoverShouldOpen = true;
298- popoverShouldClose = false;
299- } else {
300- popoverShouldOpen = false;
301- popoverShouldClose = true;
302- }
303- }
304-
305- function openPopover() {
306- if (searchHistory.count > 0) {
307- searchContainer.popover = PopupUtils.open(popoverComponent, pointerPositioner,
308- {
309- "contentWidth": searchField.width,
310- "edgeMargins": units.gu(1)
311- }
312- )
313- }
314- popoverShouldOpen = false;
315- popoverShouldClose = false;
316- }
317-
318- function closePopover() {
319- if (searchContainer.popover) {
320- PopupUtils.close(searchContainer.popover);
321- searchContainer.popover = null;
322- }
323- popoverShouldOpen = false;
324- popoverShouldClose = false;
325- }
326-
327- onActiveFocusChanged: if (!activeFocus) { searchHistory.addQuery(searchField.text) }
328-
329- TextField {
330- id: searchField
331-
332- anchors.fill: parent
333- anchors.margins: units.gu(1)
334-
335- inputMethodHints: Qt.ImhNoPredictiveText
336+ Column {
337+ id: headersColumn
338+ anchors { left: parent.left; right: parent.right }
339+
340+ PageHeadStyle {
341+ id: searchHeader
342+ anchors { left: parent.left; right: parent.right }
343+ height: headerContainer.height
344+ contentHeight: height
345+ separatorSource: ""
346+ // Required to keep PageHeadStyle noise down as it expects the Page's properties around.
347+ property var styledItem: searchHeader
348+ property string title
349+ property var config: PageHeadConfiguration {
350+ backAction: Action {
351+ iconName: "back"
352+ onTriggered: {
353+ root.resetSearch();
354+ headerContainer.showSearch = false;
355+ }
356+ }
357+ }
358+ property var contents: TextField {
359+ id: searchTextField
360 hasClearButton: false
361+ anchors {
362+ fill: parent
363+ leftMargin: units.gu(1)
364+ topMargin: units.gu(1)
365+ bottomMargin: units.gu(1)
366+ rightMargin: root.width > units.gu(60) ? root.width - units.gu(40) : units.gu(1)
367+ }
368
369- primaryItem: AbstractButton {
370- enabled: searchField.text != "" && !searchIndicator.running
371- onClicked: {
372- if (searchField.text != "") {
373- searchHistory.addQuery(searchField.text)
374- searchField.text = ""
375- }
376- }
377- height: parent.height
378+ secondaryItem: AbstractButton {
379+ height: searchTextField.height
380 width: height
381+ enabled: searchTextField.text.length > 0
382+
383+ Image {
384+ objectName: "clearIcon"
385+ anchors.fill: parent
386+ anchors.margins: units.gu(.75)
387+ source: "image://theme/clear"
388+ opacity: searchTextField.text.length > 0 && !searchActivityIndicator.running
389+ visible: opacity > 0
390+ Behavior on opacity {
391+ UbuntuNumberAnimation { duration: UbuntuAnimation.FastDuration }
392+ }
393+ }
394
395 ActivityIndicator {
396- id: searchIndicator
397+ id: searchActivityIndicator
398 objectName: "searchIndicator"
399-
400- anchors {
401- verticalCenter: parent.verticalCenter
402- left: parent.left
403- leftMargin: units.gu(0.5)
404- }
405-
406- running: opacity > 0
407- }
408-
409- Image {
410- id: primaryImage
411- objectName: "primaryImage"
412- anchors {
413- verticalCenter: parent.verticalCenter
414- left: parent.left
415- leftMargin: units.gu(0.5)
416- }
417- width: units.gu(3)
418- height: units.gu(3)
419- visible: opacity > 0
420- }
421-
422- Item {
423- id: pointerPositioner
424- anchors.left: parent.right
425- anchors.leftMargin: units.gu(0.5)
426- anchors.top: parent.bottom
427- }
428- }
429-
430- onTextChanged: {
431- if (text != "") searchContainer.closePopover()
432- else if (text == "" && activeFocus) searchContainer.openPopover()
433+ anchors.fill: parent
434+ anchors.margins: units.gu(.75)
435+ running: root.searchInProgress
436+ opacity: running ? 1 : 0
437+ Behavior on opacity {
438+ UbuntuNumberAnimation { duration: UbuntuAnimation.FastDuration }
439+ }
440+ }
441+
442+ onClicked: {
443+ root.resetSearch(true);
444+ root.openSearchHistory();
445+ }
446 }
447
448 onActiveFocusChanged: {
449- if (!activeFocus) searchContainer.closePopover()
450- }
451-
452- states: [
453- State {
454- name: "searching"
455- when: scope && scope.searchInProgress
456- PropertyChanges { target: searchIndicator; running: true; opacity: 1 }
457- PropertyChanges { target: primaryImage; opacity: 0 }
458- },
459- State {
460- name: "idle"
461- when: !scope || !scope.searchInProgress
462- PropertyChanges { target: searchIndicator; opacity: 0 }
463- PropertyChanges { target: primaryImage; opacity: 1 }
464- }
465- ]
466-
467- transitions: [
468- Transition {
469- to: "searching"
470- reversible: true
471- SequentialAnimation {
472- NumberAnimation { target: primaryImage; property: "opacity"; duration: UbuntuAnimation.FastDuration; easing.type: Easing.Linear }
473- NumberAnimation { target: searchIndicator; property: "opacity"; duration: UbuntuAnimation.FastDuration; easing.type: Easing.Linear }
474- }
475- }
476- ]
477- }
478-
479- states: [
480- State {
481- name: "wide"
482- AnchorChanges { target: itemContainer; anchors.top: headerContainer.top }
483- AnchorChanges { target: searchContainer; anchors.left: undefined; anchors.top: itemContainer.top }
484- },
485- State {
486- name: "narrow"
487- PropertyChanges { target: searchField; highlighted: true }
488- AnchorChanges { target: itemContainer; anchors.top: searchContainer.bottom }
489- AnchorChanges { target: searchContainer; anchors.left: headerContainer.left; anchors.top: headerContainer.top }
490- },
491- State {
492- name: "active"
493- extend: "wide"
494- PropertyChanges { target: searchContainer; width: units.gu(40) }
495- PropertyChanges { target: primaryImage; source: searchField.text ? "../Dash/graphics/icon_clear.png" : "../Dash/graphics/icon_search_active.png" }
496- PropertyChanges { target: searchField; highlighted: true }
497- },
498- State {
499- name: "inactive"
500- extend: "wide"
501- PropertyChanges { target: searchContainer; width: units.gu(25) }
502- PropertyChanges { target: primaryImage; source: "../Dash/graphics/icon_search_inactive.png" }
503- PropertyChanges { target: searchField; highlighted: false }
504- },
505- State {
506- name: "narrowActive"
507- extend: "narrow"
508- PropertyChanges { target: header; contentY: 0 }
509- PropertyChanges { target: primaryImage; source: searchField.text ? "../Dash/graphics/icon_clear.png" : "../Dash/graphics/icon_search_active.png" }
510- },
511- State {
512- name: "narrowInactive"
513- extend: "narrow"
514- PropertyChanges { target: header; contentY: header.height }
515- PropertyChanges { target: primaryImage; source: searchField.text ? "../Dash/graphics/icon_clear.png" : "../Dash/graphics/icon_search_active.png" }
516- }
517- ]
518-
519- transitions: [
520- Transition {
521- to: "active"
522- SequentialAnimation {
523- ParallelAnimation {
524- NumberAnimation { targets: [searchContainer, searchField]; property: "width"; duration: 200; easing.type: Easing.InOutQuad }
525- PropertyAction { target: primaryImage; property: "source" }
526- AnchorAnimation { targets: [searchContainer, itemContainer]; duration: 200; easing.type: Easing.InOutQuad }
527- }
528- ScriptAction { script: if (searchContainer.popoverShouldOpen) { searchContainer.openPopover(); } }
529- }
530- },
531- Transition {
532- to: "inactive"
533- ScriptAction { script: if (searchContainer.popoverShouldClose) { searchContainer.closePopover(); } }
534- NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.InOutQuad }
535- AnchorAnimation { targets: [searchContainer, itemContainer]; duration: 200; easing.type: Easing.InOutQuad }
536- },
537- Transition {
538- to: "narrowActive"
539- SequentialAnimation {
540- ParallelAnimation {
541- NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
542- AnchorAnimation { targets: [searchContainer, itemContainer]; duration: 200; easing.type: Easing.InOutQuad }
543- }
544- ScriptAction { script: if (searchContainer.popoverShouldOpen) { searchContainer.openPopover(); } }
545- }
546- },
547- Transition {
548- to: "narrowInactive"
549- ScriptAction { script: if (searchContainer.popoverShouldClose) { searchContainer.closePopover(); } }
550- NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
551- AnchorAnimation { targets: [searchContainer, itemContainer]; duration: 200; easing.type: Easing.InOutQuad }
552- }
553- ]
554-
555+ if (activeFocus) {
556+ root.openSearchHistory();
557+ }
558+ }
559+ }
560+ }
561+
562+ PageHeadStyle {
563+ id: header
564+ objectName: "pageHeader"
565+ anchors { left: parent.left; right: parent.right }
566+ height: headerContainer.height
567+ contentHeight: height
568+ separatorSource: ""
569+ // FIXME: Use the theme's color once we're split from the shell
570+ textColor: "grey"
571+ property var styledItem: header
572+ property string title: root.title
573+ property var config: PageHeadConfiguration {
574+ backAction: Action {
575+ iconName: "back"
576+ visible: root.showBackButton
577+ onTriggered: {
578+ root.backClicked();
579+ }
580+ }
581+
582+ actions: [
583+ Action {
584+ iconName: "search"
585+ visible: root.searchEntryEnabled
586+ onTriggered: {
587+ headerContainer.showSearch = true;
588+ searchTextField.forceActiveFocus();
589+ }
590+ }
591+ ]
592+ }
593+
594+ property var contents: null
595+ Component.onCompleted: {
596+ if (root.imageSource) {
597+ header.contents = imageComponent.createObject();
598+ }
599+ }
600 Component {
601- id: popoverComponent
602- Popover {
603- id: popover
604-
605- // FIXME: this should go into the first item below, but enable: false
606- // prevents mouse events propagation
607- AbstractButton {
608- anchors {
609- top: parent.top
610- right: parent.right
611- }
612- height: units.gu(6)
613- width: height
614-
615- onClicked: searchContainer.closePopover()
616-
617- Image {
618- anchors.centerIn: parent
619- width: units.gu(2)
620- height: units.gu(2)
621- source: "../Dash/graphics/icon_listview_clear.png"
622- }
623- }
624-
625- Column {
626- anchors {
627- top: parent.top
628- left: parent.left
629- right: parent.right
630- }
631-
632- ListItem.Standard { enabled: false; text: i18n.tr("Recent searches") }
633-
634- Repeater {
635- id: recentSearches
636- model: searchHistory
637-
638- delegate: ListItem.Standard {
639- showDivider: index < recentSearches.count - 1
640- text: query
641- onClicked: {
642- searchHistory.addQuery(text)
643- searchField.text = text
644- }
645- }
646- }
647- }
648- }
649- }
650-
651- InverseMouseArea {
652- enabled: searchField.activeFocus
653-
654- anchors {
655- top: parent.top
656- left: parent.left
657- right: parent.right
658- }
659-
660- height: searchContainer.popover ? parent.height + searchContainer.popover.contentHeight + units.gu(2) : parent.height
661-
662- onPressed: searchField.focus = false
663+ id: imageComponent
664+
665+ Item {
666+ anchors { fill: parent; topMargin: units.gu(1); bottomMargin: units.gu(1) }
667+ clip: true
668+ Image {
669+ objectName: "titleImage"
670+ anchors.fill: parent
671+ source: root.imageSource
672+ fillMode: Image.PreserveAspectFit
673+ horizontalAlignment: Image.AlignLeft
674+ sourceSize.height: height
675+ }
676+ }
677+ }
678+ }
679+ }
680+ }
681+
682+ Component {
683+ id: popoverComponent
684+ Popover {
685+ id: popover
686+ autoClose: false
687+
688+ Component.onDestruction: {
689+ headerContainer.popover = null;
690+ }
691+
692+ Column {
693+ anchors {
694+ top: parent.top
695+ left: parent.left
696+ right: parent.right
697+ }
698+
699+ Repeater {
700+ id: recentSearches
701+ model: searchHistory
702+
703+ delegate: Standard {
704+ showDivider: index < recentSearches.count - 1
705+ text: query
706+ onClicked: {
707+ searchHistory.addQuery(text);
708+ searchTextField.text = text;
709+ PopupUtils.close(popover);
710+ }
711+ }
712 }
713 }
714 }
715@@ -402,7 +301,7 @@
716 BorderImage {
717 id: bottomBorder
718 anchors {
719- top: header.bottom
720+ top: headerContainer.bottom
721 left: parent.left
722 right: parent.right
723 bottom: bottomContainer.top
724
725=== removed file 'qml/Components/PageHeaderLabel.qml'
726--- qml/Components/PageHeaderLabel.qml 2013-11-05 16:06:09 +0000
727+++ qml/Components/PageHeaderLabel.qml 1970-01-01 00:00:00 +0000
728@@ -1,41 +0,0 @@
729-/*
730- * Copyright (C) 2013 Canonical, Ltd.
731- *
732- * This program is free software; you can redistribute it and/or modify
733- * it under the terms of the GNU General Public License as published by
734- * the Free Software Foundation; version 3.
735- *
736- * This program is distributed in the hope that it will be useful,
737- * but WITHOUT ANY WARRANTY; without even the implied warranty of
738- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
739- * GNU General Public License for more details.
740- *
741- * You should have received a copy of the GNU General Public License
742- * along with this program. If not, see <http://www.gnu.org/licenses/>.
743- */
744-
745-import QtQuick 2.0
746-import Ubuntu.Components 0.1
747-
748-PageHeader {
749- property alias text: label.text
750-
751- childItem: Label {
752- id: label
753- anchors {
754- left: parent.left
755- leftMargin: units.gu(2)
756- right: parent.right
757- verticalCenter: parent.verticalCenter
758- }
759-
760- color: Theme.palette.selected.backgroundText
761- opacity: 0.8
762- font.family: "Ubuntu"
763- font.weight: Font.Light
764- fontSize: "x-large"
765- elide: Text.ElideRight
766- style: Text.Raised
767- styleColor: "black"
768- }
769-}
770
771=== added directory 'qml/Components/SearchHistoryModel'
772=== removed file 'qml/Components/SearchHistoryModel.qml'
773--- qml/Components/SearchHistoryModel.qml 2013-06-05 22:03:08 +0000
774+++ qml/Components/SearchHistoryModel.qml 1970-01-01 00:00:00 +0000
775@@ -1,41 +0,0 @@
776-/*
777- * Copyright (C) 2013 Canonical, Ltd.
778- *
779- * This program is free software; you can redistribute it and/or modify
780- * it under the terms of the GNU General Public License as published by
781- * the Free Software Foundation; version 3.
782- *
783- * This program is distributed in the hope that it will be useful,
784- * but WITHOUT ANY WARRANTY; without even the implied warranty of
785- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
786- * GNU General Public License for more details.
787- *
788- * You should have received a copy of the GNU General Public License
789- * along with this program. If not, see <http://www.gnu.org/licenses/>.
790- */
791-
792-import QtQuick 2.0
793-
794-// TODO sanitize input, move to persistent storage
795-
796-ListModel {
797- function addQuery(newQuery) {
798- // strip whitespaces
799- newQuery = newQuery.replace(/^\s+|\s+$/g, '');
800- // ignore empty queries
801- if (newQuery == "") return
802- for (var i = 0; i < count; i++) {
803- if (get(i).query == newQuery) {
804- // promote existing entry
805- move(i, 0, 1)
806- return
807- }
808- }
809- // add a new entry
810- insert(0, { "query": newQuery })
811- if (count > 3) {
812- // remove entries if there's more than three
813- remove(3)
814- }
815- }
816-}
817
818=== added file 'qml/Components/SearchHistoryModel/SearchHistoryModel.qml'
819--- qml/Components/SearchHistoryModel/SearchHistoryModel.qml 1970-01-01 00:00:00 +0000
820+++ qml/Components/SearchHistoryModel/SearchHistoryModel.qml 2014-07-08 15:02:30 +0000
821@@ -0,0 +1,42 @@
822+/*
823+ * Copyright (C) 2013 Canonical, Ltd.
824+ *
825+ * This program is free software; you can redistribute it and/or modify
826+ * it under the terms of the GNU General Public License as published by
827+ * the Free Software Foundation; version 3.
828+ *
829+ * This program is distributed in the hope that it will be useful,
830+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
831+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
832+ * GNU General Public License for more details.
833+ *
834+ * You should have received a copy of the GNU General Public License
835+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
836+ */
837+
838+pragma Singleton
839+import QtQuick 2.0
840+
841+// TODO sanitize input, move to persistent storage
842+
843+ListModel {
844+ function addQuery(newQuery) {
845+ // strip whitespaces
846+ newQuery = newQuery.replace(/^\s+|\s+$/g, '');
847+ // ignore empty queries
848+ if (newQuery == "") return
849+ for (var i = 0; i < count; i++) {
850+ if (get(i).query == newQuery) {
851+ // promote existing entry
852+ move(i, 0, 1)
853+ return
854+ }
855+ }
856+ // add a new entry
857+ insert(0, { "query": newQuery })
858+ if (count > 3) {
859+ // remove entries if there's more than three
860+ remove(3)
861+ }
862+ }
863+}
864
865=== added file 'qml/Components/SearchHistoryModel/qmldir'
866--- qml/Components/SearchHistoryModel/qmldir 1970-01-01 00:00:00 +0000
867+++ qml/Components/SearchHistoryModel/qmldir 2014-07-08 15:02:30 +0000
868@@ -0,0 +1,1 @@
869+singleton SearchHistoryModel 1.0 SearchHistoryModel.qml
870
871=== removed file 'qml/Components/graphics/headerback@27.png'
872Binary files qml/Components/graphics/headerback@27.png 2014-02-19 13:30:38 +0000 and qml/Components/graphics/headerback@27.png 1970-01-01 00:00:00 +0000 differ
873=== modified file 'qml/Dash/Dash.qml'
874--- qml/Dash/Dash.qml 2014-03-24 12:36:29 +0000
875+++ qml/Dash/Dash.qml 2014-07-08 15:02:30 +0000
876@@ -26,7 +26,6 @@
877
878 visible: shown
879
880- property ListModel searchHistory: SearchHistoryModel {}
881 property bool searchable: !dashContent.previewOpen && !scopeItem.previewOpen
882
883 property string showScopeOnLoaded: "clickscope"
884@@ -76,7 +75,6 @@
885 height: parent.height
886 model: filteredScopes
887 scopes: scopes
888- searchHistory: dash.searchHistory
889 visible: x != -width
890 onGotoScope: {
891 dash.setCurrentScope(scopeId, true, false);
892@@ -110,7 +108,6 @@
893 anchors.left: dashContent.right
894 width: parent.width
895 height: parent.height
896- searchHistory: dash.searchHistory
897 scale: dash.contentScale
898 clip: scale != 1.0
899 visible: scope != null
900
901=== modified file 'qml/Dash/DashContent.qml'
902--- qml/Dash/DashContent.qml 2014-06-17 14:08:21 +0000
903+++ qml/Dash/DashContent.qml 2014-07-08 15:02:30 +0000
904@@ -28,8 +28,6 @@
905 readonly property alias currentIndex: dashContentList.currentIndex
906 property alias previewOpen: previewListView.open
907
908- property ListModel searchHistory
909-
910 signal scopeLoaded(string scopeId)
911 signal gotoScope(string scopeId)
912 signal openScope(var scope)
913@@ -147,11 +145,10 @@
914
915 onLoaded: {
916 item.objectName = scope.id
917- item.pageHeader = dashPageHeader;
918 item.previewListView = previewListView;
919 item.scope = Qt.binding(function() { return scope })
920 item.isCurrent = Qt.binding(function() { return visible && ListView.isCurrentItem })
921- item.tabBarHeight = Qt.binding(function() { return dashPageHeader.implicitHeight; })
922+ item.title = Qt.binding(function() { return dashContentList.model.get(index).title; })
923 dashContent.scopeLoaded(item.scope.id)
924 }
925 Connections {
926@@ -168,64 +165,6 @@
927 Component.onDestruction: active = false
928 }
929 }
930-
931- PageHeader {
932- id: dashPageHeader
933- objectName: "pageHeader"
934- width: parent.width
935- searchEntryEnabled: true
936- searchHistory: dashContent.searchHistory
937- scope: dashContentList.currentItem && dashContentList.currentItem.theScope
938-
939- childItem: TabBar {
940- id: tabBar
941- objectName: "tabbar"
942- height: units.gu(6.5)
943- width: parent.width
944- style: DashContentTabBarStyle {}
945-
946- SortFilterProxyModel {
947- id: tabBarModel
948-
949- model: dashContentList.model
950-
951- property int selectedIndex: -1
952- onSelectedIndexChanged: {
953- if (dashContentList.currentIndex == -1 && tabBar.selectedIndex != -1) {
954- // TODO This together with the Timer below
955- // are a workaround for the first tab sometimes not showing the text.
956- // But Tabs are going away in the future so not sure if makes
957- // sense invetigating what's the problem at this stage
958- selectionModeTimer.restart();
959- }
960- dashContentList.currentIndex = selectedIndex;
961- }
962- }
963-
964- model: tabBarModel.count > 0 ? tabBarModel : null
965-
966- Connections {
967- target: dashContentList
968- onCurrentIndexChanged: {
969- tabBarModel.selectedIndex = dashContentList.currentIndex
970- }
971- }
972-
973- Timer {
974- id: selectionModeTimer
975- interval: 1
976- onTriggered: tabBar.selectionMode = false
977- }
978- }
979-
980- bottomItem: DashDepartments {
981- scope: dashContentList.currentItem ? dashContentList.currentItem.theScope : null
982- width: parent.width <= units.gu(60) ? parent.width : units.gu(40)
983- anchors.right: parent.right
984- windowHeight: dashContent.height
985- windowWidth: dashContent.width
986- }
987- }
988 }
989
990 PreviewListView {
991@@ -233,7 +172,6 @@
992 objectName: "dashContentPreviewList"
993 visible: x != width
994 scope: dashContentList.currentItem ? dashContentList.currentItem.theScope : null
995- pageHeader: dashPageHeader
996 width: parent.width
997 height: parent.height
998 anchors.left: dashContentListHolder.right
999
1000=== modified file 'qml/Dash/GenericScopeView.qml'
1001--- qml/Dash/GenericScopeView.qml 2014-06-20 10:31:49 +0000
1002+++ qml/Dash/GenericScopeView.qml 2014-07-08 15:02:30 +0000
1003@@ -29,13 +29,14 @@
1004 property SortFilterProxyModel categories: categoryFilter
1005 property bool isCurrent: false
1006 property alias moving: categoryView.moving
1007- property int tabBarHeight: 0
1008- property PageHeader pageHeader: null
1009 property Item previewListView: null
1010-
1011+ property string title
1012+ property bool hasBackAction: false
1013 property bool enableHeightBehaviorOnNextCreation: false
1014 property var categoryView: categoryView
1015
1016+ signal backClicked()
1017+
1018 onScopeChanged: {
1019 if (scope) {
1020 scope.activateApplication.connect(activateApp);
1021@@ -89,14 +90,6 @@
1022 }
1023
1024 Connections {
1025- target: panel
1026- onSearchClicked: if (isCurrent) {
1027- pageHeader.triggerSearch()
1028- categoryView.showHeader()
1029- }
1030- }
1031-
1032- Connections {
1033 target: scopeView.scope
1034 onShowDash: previewListView.open = false;
1035 onHideDash: previewListView.open = false;
1036@@ -111,10 +104,6 @@
1037
1038 property string expandedCategoryId: ""
1039
1040- onContentYChanged: pageHeader.positionRealHeader();
1041- onOriginYChanged: pageHeader.positionRealHeader();
1042- onContentHeightChanged: pageHeader.positionRealHeader();
1043-
1044 delegate: ListItems.Base {
1045 id: baseItem
1046 objectName: "dashCategory" + category
1047@@ -319,20 +308,24 @@
1048 categoryView.expandedCategoryId = "";
1049 }
1050 }
1051- pageHeader: Item {
1052- implicitHeight: scopeView.tabBarHeight
1053- onHeightChanged: {
1054- if (scopeView.pageHeader && scopeView.isCurrent) {
1055- scopeView.pageHeader.height = height;
1056- }
1057- }
1058- onYChanged: positionRealHeader();
1059-
1060- function positionRealHeader() {
1061- if (scopeView.pageHeader && scopeView.isCurrent) {
1062- scopeView.pageHeader.y = y + parent.y;
1063- }
1064- }
1065+
1066+ pageHeader: PageHeader {
1067+ id: pageHeader
1068+ width: parent.width
1069+ title: scopeView.title
1070+ showBackButton: scopeView.hasBackAction
1071+ searchEntryEnabled: true
1072+ searchInProgress: scopeView.scope.searchInProgress
1073+
1074+ bottomItem: DashDepartments {
1075+ scope: scopeView.scope
1076+ width: parent.width <= units.gu(60) ? parent.width : units.gu(40)
1077+ anchors.right: parent.right
1078+ windowHeight: scopeView.height
1079+ windowWidth: scopeView.width
1080+ }
1081+
1082+ onBackClicked: scopeView.backClicked()
1083 }
1084 }
1085 }
1086
1087=== modified file 'qml/Dash/PreviewListView.qml'
1088--- qml/Dash/PreviewListView.qml 2014-06-13 07:44:18 +0000
1089+++ qml/Dash/PreviewListView.qml 2014-07-08 15:02:30 +0000
1090@@ -24,7 +24,6 @@
1091 id: root
1092
1093 property var scope: null
1094- property var pageHeader: null
1095
1096 property alias open: previewListView.open
1097 property alias model: previewListView.model
1098@@ -36,27 +35,11 @@
1099 id: header
1100 objectName: root.objectName + "_pageHeader"
1101 width: parent.width
1102+ title: scope.name
1103+ showBackButton: true
1104 searchEntryEnabled: false
1105- scope: root.scope
1106- height: units.gu(8.5)
1107- showBackButton: true
1108+
1109 onBackClicked: root.open = false
1110-
1111- childItem: Label {
1112- id: label
1113- anchors {
1114- left: parent.left
1115- right: parent.right
1116- verticalCenter: parent.verticalCenter
1117- }
1118- text: scope ? scope.name : ""
1119- // TODO Saviq: These should come from updated Ubuntu Palette.
1120- color: "#888888"
1121- font.family: "Ubuntu"
1122- font.weight: Font.Light
1123- fontSize: "x-large"
1124- elide: Text.ElideRight
1125- }
1126 }
1127
1128 ListView {
1129
1130=== modified file 'qml/Dash/ScopeItem.qml'
1131--- qml/Dash/ScopeItem.qml 2014-06-17 14:08:21 +0000
1132+++ qml/Dash/ScopeItem.qml 2014-07-08 15:02:30 +0000
1133@@ -25,8 +25,6 @@
1134 property alias scope: scopeView.scope
1135 property alias previewOpen: previewListView.open
1136
1137- property ListModel searchHistory
1138-
1139 signal back
1140 signal gotoScope(string scopeId)
1141 signal openScope(var scope)
1142@@ -48,56 +46,23 @@
1143 width: parent.width
1144 height: parent.height
1145 isCurrent: scope != null
1146- tabBarHeight: scopeItemPageHeader.implicitHeight
1147- pageHeader: scopeItemPageHeader
1148+ title: scope ? scope.name : ""
1149+ hasBackAction: true
1150 previewListView: previewListView
1151
1152+ onBackClicked: root.back();
1153+
1154 Connections {
1155 target: scopeView.isCurrent ? scope : null
1156 onGotoScope: root.gotoScope(scopeId);
1157 onOpenScope: root.openScope(scope);
1158 }
1159 }
1160-
1161- PageHeader {
1162- id: scopeItemPageHeader
1163- width: parent.width
1164- searchEntryEnabled: true
1165- searchHistory: root.searchHistory
1166- scope: root.scope
1167- height: units.gu(8.5)
1168- showBackButton: true
1169- onBackClicked: root.back();
1170-
1171- childItem: Label {
1172- id: label
1173- anchors {
1174- left: parent.left
1175- right: parent.right
1176- verticalCenter: parent.verticalCenter
1177- }
1178- text: scope ? scope.name : ""
1179- color: "#888888"
1180- font.family: "Ubuntu"
1181- font.weight: Font.Light
1182- fontSize: "x-large"
1183- elide: Text.ElideRight
1184- }
1185-
1186- bottomItem: DashDepartments {
1187- scope: root.scope
1188- width: parent.width <= units.gu(60) ? parent.width : units.gu(40)
1189- anchors.right: parent.right
1190- windowHeight: root.height
1191- windowWidth: root.width
1192- }
1193- }
1194 }
1195
1196 PreviewListView {
1197 id: previewListView
1198 visible: x != width
1199- pageHeader: scopeItemPageHeader
1200 scope: root.scope
1201 width: parent.width
1202 height: parent.height
1203
1204=== removed file 'qml/Dash/graphics/icon_listview_clear@20.png'
1205Binary files qml/Dash/graphics/icon_listview_clear@20.png 2013-06-20 13:42:39 +0000 and qml/Dash/graphics/icon_listview_clear@20.png 1970-01-01 00:00:00 +0000 differ
1206=== renamed file 'qml/Dash/graphics/phone/screenshots/phone@12.png' => 'qml/Dash/graphics/phone/screenshots/dialer@12.png'
1207=== modified file 'qml/Hud/HudParametrizedActionsPage.qml'
1208--- qml/Hud/HudParametrizedActionsPage.qml 2013-11-05 16:06:09 +0000
1209+++ qml/Hud/HudParametrizedActionsPage.qml 2014-07-08 15:02:30 +0000
1210@@ -19,7 +19,7 @@
1211 import "../Components"
1212
1213 Item {
1214- property alias header: header.text
1215+ property alias header: header.title
1216 signal backPressed
1217 signal confirmPressed
1218 signal valuesUpdated
1219@@ -89,7 +89,7 @@
1220 anchors.left: parent.left
1221 anchors.right: parent.right
1222
1223- PageHeaderLabel {
1224+ PageHeader {
1225 id: header
1226 anchors.top: parent.top
1227 anchors.left: parent.left
1228
1229=== added file 'qml/Panel/ActiveCallHint.qml'
1230--- qml/Panel/ActiveCallHint.qml 1970-01-01 00:00:00 +0000
1231+++ qml/Panel/ActiveCallHint.qml 2014-07-08 15:02:30 +0000
1232@@ -0,0 +1,206 @@
1233+/*
1234+ * Copyright (C) 2014 Canonical, Ltd.
1235+ *
1236+ * This program is free software; you can redistribute it and/or modify
1237+ * it under the terms of the GNU General Public License as published by
1238+ * the Free Software Foundation; version 3.
1239+ *
1240+ * This program is distributed in the hope that it will be useful,
1241+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1242+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1243+ * GNU General Public License for more details.
1244+ *
1245+ * You should have received a copy of the GNU General Public License
1246+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1247+ */
1248+
1249+import QtQuick 2.0
1250+import Ubuntu.Telephony 0.1 as Telephony
1251+import Ubuntu.Components 0.1
1252+import Unity.Application 0.1
1253+import "../Components"
1254+
1255+Item {
1256+ id: callHint
1257+
1258+ readonly property bool active: {
1259+ var application = ApplicationManager.findApplication("dialer-app");
1260+
1261+ if (callManager.callIndicatorVisible) {
1262+ // at the moment, callIndicatorVisible is only "valid" if dialer is in focus.
1263+ if (application && ApplicationManager.focusedApplicationId === "dialer-app") {
1264+ // Don't show if application is still starting; might get a fleeting true/false.
1265+ return application.state !== ApplicationInfoInterface.Starting;
1266+ }
1267+ }
1268+ if (ApplicationManager.focusedApplicationId !== "dialer-app") {
1269+ if (application) {
1270+ // Don't show if application is still starting; might get a fleeting true/false.
1271+ return application.state !== ApplicationInfoInterface.Starting && callManager.hasCalls;
1272+ }
1273+ return callManager.hasCalls;
1274+ }
1275+ return false;
1276+ }
1277+ readonly property QtObject contactWatcher: _contactWatcher
1278+ property int labelSwitchInterval: 6000
1279+ implicitWidth: row.x + row.width
1280+
1281+ Component.onCompleted: {
1282+ telepathyHelper.registerChannelObserver("unity8");
1283+ }
1284+
1285+ function showLiveCall() {
1286+ Qt.openUrlExternally("dialer:///?view=liveCall");
1287+ }
1288+
1289+ Component {
1290+ id: contactColumn
1291+
1292+ Column {
1293+ id: column
1294+ objectName: "contactColumn"
1295+
1296+ anchors.left: parent.left
1297+
1298+ Component.onCompleted: {
1299+ if (index === 0) {
1300+ labelPathView.column1 = column;
1301+ } else {
1302+ labelPathView.column2 = column;
1303+ }
1304+ }
1305+
1306+ Label {
1307+ height: callHint.height
1308+ verticalAlignment: Text.AlignVCenter
1309+ text: i18n.tr("Tap to return to call...");
1310+ }
1311+
1312+ Label {
1313+ objectName: "contactLabel"
1314+ height: callHint.height
1315+ verticalAlignment: Text.AlignVCenter
1316+ width: Math.max(contentWidth, 1)
1317+
1318+ text: {
1319+ if (!d.activeCall) {
1320+ return "";
1321+ } else if (d.activeCall.isConference) {
1322+ return i18n.tr("Conference");
1323+ } else {
1324+ return contactWatcher.alias !== "" ? contactWatcher.alias : contactWatcher.phoneNumber;
1325+ }
1326+ }
1327+ }
1328+ }
1329+ }
1330+
1331+ Row {
1332+ id: row
1333+ anchors {
1334+ top: parent.top
1335+ bottom: parent.bottom
1336+ left: parent.left
1337+ leftMargin: units.gu(1)
1338+ }
1339+ spacing: units.gu(1)
1340+
1341+ Label {
1342+ id: time
1343+ objectName: "timeLabel"
1344+
1345+ anchors {
1346+ top: parent.top
1347+ bottom: parent.bottom
1348+ }
1349+ verticalAlignment: Text.AlignVCenter
1350+ horizontalAlignment: Text.AlignRight
1351+ text: {
1352+ var m = Math.round(d.callTime/60);
1353+ var ss = d.callTime % 60;
1354+ if (ss >= 10) {
1355+ return m + ":" + ss;
1356+ } else {
1357+ return m + ":0" + ss;
1358+ }
1359+ }
1360+ }
1361+
1362+ PathView {
1363+ id: labelPathView
1364+ objectName: "labelPathView"
1365+
1366+ anchors {
1367+ top: parent.top
1368+ bottom: parent.bottom
1369+ }
1370+ width: column1 && column2 ? Math.max(column1.width, column1.width) : 0
1371+ clip: true
1372+
1373+ property Column column1
1374+ property Column column2
1375+ property int columnHeight: column1 ? column1.height : 0
1376+
1377+ delegate: contactColumn
1378+ model: 2
1379+ offset: 0
1380+ interactive: false
1381+
1382+ path: Path {
1383+ startY: -labelPathView.columnHeight / 2
1384+ PathLine {
1385+ y: labelPathView.columnHeight * 1.5
1386+ }
1387+ }
1388+
1389+ Behavior on offset {
1390+ id: offsetBehaviour
1391+ SmoothedAnimation {
1392+ id: offsetAnimation
1393+ // ensure we go faster than the label switch
1394+ duration: labelSwitchInterval/8
1395+ velocity: 0.75
1396+ easing.type: Easing.InOutQuad
1397+ }
1398+ }
1399+ }
1400+ }
1401+
1402+ Timer {
1403+ id: alternateLabelTimer
1404+ running: callHint.active
1405+ interval: labelPathView.offset % 1.0 !== 0 ? labelSwitchInterval : labelSwitchInterval/4
1406+ repeat: true
1407+
1408+ onRunningChanged: {
1409+ if (running) {
1410+ offsetBehaviour.enabled = false;
1411+ labelPathView.offset = 0;
1412+ offsetBehaviour.enabled = true;
1413+ }
1414+ }
1415+
1416+ onTriggered: {
1417+ labelPathView.offset = labelPathView.offset + 0.5;
1418+ }
1419+ }
1420+
1421+ Telephony.ContactWatcher {
1422+ id: _contactWatcher
1423+ objectName: "contactWatcher"
1424+ phoneNumber: d.activeCall ? d.activeCall.phoneNumber : ""
1425+ }
1426+
1427+ QtObject {
1428+ id: d
1429+
1430+ property QtObject activeCall: {
1431+ if (callManager.foregroundCall) {
1432+ return callManager.foregroundCall;
1433+ }
1434+ return callManager.backgroundCall;
1435+ }
1436+ property int callTime: activeCall ? activeCall.elapsedTime : 0
1437+ }
1438+}
1439
1440=== modified file 'qml/Panel/IndicatorRow.qml'
1441--- qml/Panel/IndicatorRow.qml 2014-03-05 08:44:52 +0000
1442+++ qml/Panel/IndicatorRow.qml 2014-07-08 15:02:30 +0000
1443@@ -36,7 +36,7 @@
1444
1445 function setDefaultItem() {
1446 // The leftmost indicator
1447- setCurrentItem(0);
1448+ setCurrentItemIndex(0);
1449 }
1450
1451 function setCurrentItemIndex(index) {
1452
1453=== modified file 'qml/Panel/Indicators.qml'
1454--- qml/Panel/Indicators.qml 2014-06-30 14:37:22 +0000
1455+++ qml/Panel/Indicators.qml 2014-07-08 15:02:30 +0000
1456@@ -28,7 +28,6 @@
1457
1458 property real openedHeight: units.gu(71)
1459 property int panelHeight: units.gu(3)
1460- property bool pinnedMode: true //should be set true if indicators menu can cover whole screen
1461 property alias overFlowWidth: indicatorRow.overFlowWidth
1462 property alias showAll: indicatorRow.showAll
1463 // TODO: This should be sourced by device type (eg "desktop", "tablet", "phone"...)
1464@@ -38,26 +37,20 @@
1465 readonly property int lockThreshold: openedHeight / 2
1466 property bool fullyOpened: height == openedHeight
1467 property bool partiallyOpened: height > panelHeight && !fullyOpened
1468- property real visualBottom: Math.max(y+height, y+indicatorRow.y+indicatorRow.height)
1469 property bool contentEnabled: true
1470 property bool initalizeItem: true
1471 readonly property alias content: menuContent
1472 property real unitProgress: (height - panelHeight) / (openedHeight - panelHeight)
1473+ property bool enableHint: true
1474+ property real showHintBottomMargin: 0
1475+
1476+ signal showTapped(point position)
1477
1478 // TODO: Perhaps we need a animation standard for showing/hiding? Each showable seems to
1479 // use its own values. Need to ask design about this.
1480 showAnimation: StandardAnimation {
1481 property: "height"
1482- duration: 350
1483 to: openedHeight
1484- easing.type: Easing.OutCubic
1485-
1486- // Re-size if we've changed the openHeight while shown.
1487- onToChanged: {
1488- if (indicators.shown) {
1489- indicators.show();
1490- }
1491- }
1492 }
1493
1494 hideAnimation: StandardAnimation {
1495@@ -67,16 +60,24 @@
1496 easing.type: Easing.OutCubic
1497 }
1498
1499+ onOpenedHeightChanged: {
1500+ if (showAnimation.running) {
1501+ showAnimation.restart();
1502+ } else if (indicators.shown) {
1503+ height = openedHeight;
1504+ }
1505+ }
1506+
1507 height: panelHeight
1508- onHeightChanged: updateRevealProgressState(indicators.height - panelHeight, true)
1509+ onHeightChanged: updateRevealProgressState(indicators.height - panelHeight - showHintBottomMargin, true)
1510
1511 function updateRevealProgressState(revealProgress, enableRelease) {
1512 if (!showAnimation.running && !hideAnimation.running) {
1513 if (revealProgress === 0) {
1514 indicators.state = "initial";
1515- } else if (revealProgress > 0 && revealProgress <= hintValue) {
1516+ } else if (enableHint && revealProgress > 0 && revealProgress <= hintValue) {
1517 indicators.state = "hint";
1518- } else if (revealProgress > hintValue && revealProgress < lockThreshold) {
1519+ } else if ((!enableHint || revealProgress > hintValue) && revealProgress < lockThreshold) {
1520 indicators.state = "reveal";
1521 } else if (revealProgress >= lockThreshold && lockThreshold > 0) {
1522 indicators.state = "locked";
1523@@ -171,17 +172,6 @@
1524 }
1525 }
1526
1527- VerticalThinDivider {
1528- anchors {
1529- top: indicators.top
1530- topMargin: panelHeight
1531- bottom: handle.bottom
1532- right: indicators.left
1533- }
1534- width: units.dp(2)
1535- source: "graphics/VerticalDivider.png"
1536- }
1537-
1538 VisibleIndicators {
1539 id: visibleIndicators
1540 }
1541@@ -245,10 +235,6 @@
1542 }
1543 }
1544
1545- PanelBackground {
1546- anchors.fill: indicatorRow
1547- }
1548-
1549 IndicatorRow {
1550 id: indicatorRow
1551 objectName: "indicatorRow"
1552@@ -356,24 +342,27 @@
1553 id: showDragHandle
1554 anchors.bottom: parent.bottom
1555 // go beyond parent so that it stays reachable, at the top of the screen.
1556- anchors.bottomMargin: pinnedMode ? 0 : -panelHeight
1557+ anchors.bottomMargin: showHintBottomMargin
1558 anchors.left: parent.left
1559 anchors.right: parent.right
1560 height: panelHeight
1561 direction: Direction.Downwards
1562 enabled: !indicators.shown && indicators.available
1563- hintDisplacement: pinnedMode ? indicators.hintValue : 0
1564+ hintDisplacement: enableHint ? indicators.hintValue : 0
1565 autoCompleteDragThreshold: maxTotalDragDistance / 2
1566 stretch: true
1567 maxTotalDragDistance: openedHeight - panelHeight
1568- distanceThreshold: pinnedMode ? 0 : units.gu(3)
1569+ distanceThreshold: panelHeight
1570
1571 onStatusChanged: {
1572 if (status === DirectionalDragArea.Recognized) {
1573 menuContent.activateContent();
1574 }
1575 }
1576+
1577+ onTapped: showTapped(Qt.point(touchSceneX, touchSceneY));
1578 }
1579+
1580 DragHandle {
1581 id: hideDragHandle
1582 anchors.fill: handle
1583@@ -396,10 +385,6 @@
1584 },
1585 State {
1586 name: "hint"
1587- PropertyChanges {
1588- target: indicatorRow;
1589- y: pinnedMode ? 0 : panelHeight
1590- }
1591 StateChangeScript {
1592 script: {
1593 if (d.activeDragHandle) {
1594@@ -432,5 +417,6 @@
1595 Component.onCompleted: initialise();
1596 function initialise() {
1597 visibleIndicators.load(profile);
1598+ indicatorRow.setDefaultItem();
1599 }
1600 }
1601
1602=== modified file 'qml/Panel/Panel.qml'
1603--- qml/Panel/Panel.qml 2014-06-24 17:04:11 +0000
1604+++ qml/Panel/Panel.qml 2014-07-08 15:02:30 +0000
1605@@ -16,27 +16,23 @@
1606
1607 import QtQuick 2.0
1608 import Ubuntu.Components 0.1
1609+import Unity.Application 0.1
1610 import "../Components"
1611+import "../Components/ListItems"
1612
1613 Item {
1614 id: root
1615- readonly property real panelHeight: units.gu(3) + units.dp(2)
1616- property real indicatorsMenuWidth: width
1617- property alias indicators: indicatorsMenu
1618+ readonly property real panelHeight: indicatorArea.y + d.indicatorHeight
1619+ property alias indicators: __indicators
1620+ property alias callHint: __callHint
1621 property bool fullscreenMode: false
1622- property bool searchVisible: true
1623-
1624- readonly property real separatorLineHeight: leftSeparatorLine.height
1625- readonly property real __panelMinusSeparatorLineHeight: panelHeight - separatorLineHeight
1626-
1627- signal searchClicked
1628
1629 function hideIndicatorMenu(delay) {
1630 if (delay !== undefined) {
1631 hideTimer.interval = delay;
1632 hideTimer.start();
1633 } else {
1634- indicatorsMenu.hide();
1635+ indicators.hide();
1636 }
1637 }
1638
1639@@ -44,129 +40,174 @@
1640 id: hideTimer
1641 running: false
1642 onTriggered: {
1643- indicatorsMenu.hide();
1644+ indicators.hide();
1645 }
1646 }
1647
1648 Connections {
1649- target: indicatorsMenu
1650+ target: indicators
1651 onShownChanged: hideTimer.stop()
1652 }
1653
1654- PanelBackground {
1655- id: panelBackground
1656- anchors {
1657- left: parent.left
1658- right: parent.right
1659- }
1660- height: __panelMinusSeparatorLineHeight
1661- y: 0
1662-
1663- Behavior on y { StandardAnimation { duration: 500 } }
1664- }
1665-
1666- PanelSeparatorLine {
1667- id: leftSeparatorLine
1668- anchors {
1669- top: panelBackground.bottom
1670- left: parent.left
1671- right: indicatorsMenu.left
1672- }
1673- saturation: 1 - indicatorsMenu.unitProgress
1674- }
1675-
1676 Rectangle {
1677 id: darkenedArea
1678 property real darkenedOpacity: 0.6
1679 anchors {
1680+ top: parent.top
1681+ topMargin: panelHeight
1682 left: parent.left
1683 right: parent.right
1684- top: panelBackground.bottom
1685 bottom: parent.bottom
1686 }
1687 color: "black"
1688- opacity: indicatorsMenu.unitProgress * darkenedOpacity
1689+ opacity: indicators.unitProgress * darkenedOpacity
1690+
1691 MouseArea {
1692 anchors.fill: parent
1693- enabled: indicatorsMenu.shown
1694- onClicked: if (indicatorsMenu.fullyOpened) indicatorsMenu.hide();
1695- }
1696- }
1697-
1698- Indicators {
1699- id: indicatorsMenu
1700- objectName: "indicators"
1701-
1702- anchors.right: parent.right
1703- y: panelBackground.y
1704- width: root.indicatorsMenuWidth
1705- shown: false
1706- panelHeight: __panelMinusSeparatorLineHeight
1707- openedHeight: parent.height + (pinnedMode ? 0 : root.panelHeight)
1708- pinnedMode: !fullscreenMode
1709- overFlowWidth: search.state=="hidden" ? parent.width : parent.width - search.width
1710- }
1711-
1712- PanelSeparatorLine {
1713- id: indicatorsSeparatorLine
1714- visible: true
1715- anchors {
1716- left: indicatorsMenu.left
1717- right: indicatorsMenu.right
1718- }
1719- y: indicatorsMenu.visualBottom
1720- }
1721-
1722- BorderImage {
1723- id: dropShadow
1724- anchors {
1725- top: indicators.top
1726- bottom: indicatorsSeparatorLine.bottom
1727- left: indicators.left
1728- right: indicators.right
1729- margins: -units.gu(1)
1730- }
1731- visible: indicatorsMenu.height > indicatorsMenu.panelHeight
1732- source: "graphics/rectangular_dropshadow.sci"
1733- }
1734-
1735- SearchIndicator {
1736- id: search
1737- objectName: "search"
1738- enabled: root.searchVisible
1739-
1740- state: {
1741- if (parent.width < indicatorsMenu.width + width) {
1742- if (indicatorsMenu.state != "initial") {
1743- return "hidden";
1744- }
1745- }
1746- if (root.searchVisible && !indicatorsMenu.showAll) {
1747- return "visible";
1748- }
1749-
1750- return "hidden";
1751- }
1752-
1753- height: __panelMinusSeparatorLineHeight
1754- anchors {
1755- top: panelBackground.top
1756- left: panelBackground.left
1757- }
1758-
1759- onClicked: root.searchClicked()
1760+ enabled: indicators.shown
1761+ onClicked: if (indicators.fullyOpened) indicators.hide();
1762+ }
1763+ }
1764+
1765+ Item {
1766+ id: indicatorArea
1767+ objectName: "indicatorArea"
1768+
1769+ anchors.fill: parent
1770+
1771+ Behavior on anchors.topMargin { StandardAnimation {} }
1772+
1773+ BorderImage {
1774+ id: dropShadow
1775+ anchors {
1776+ fill: indicators
1777+ leftMargin: -units.gu(1)
1778+ bottomMargin: -units.gu(1)
1779+ }
1780+ visible: indicators.height > indicators.panelHeight
1781+ source: "graphics/rectangular_dropshadow.sci"
1782+ }
1783+
1784+ VerticalThinDivider {
1785+ id: indicatorDividor
1786+ anchors {
1787+ top: indicators.top
1788+ bottom: indicators.bottom
1789+ right: indicators.left
1790+
1791+ topMargin: indicatorArea.anchors.topMargin + indicators.panelHeight
1792+ }
1793+
1794+ width: units.dp(2)
1795+ source: "graphics/VerticalDivider.png"
1796+ }
1797+
1798+ Rectangle {
1799+ id: indicatorAreaBackground
1800+ color: callHint.visible ? "green" : "black"
1801+ anchors {
1802+ top: parent.top
1803+ left: parent.left
1804+ right: parent.right
1805+ }
1806+ height: indicators.panelHeight
1807+
1808+ Behavior on color { ColorAnimation { duration: UbuntuAnimation.FastDuration } }
1809+ }
1810+
1811+ PanelSeparatorLine {
1812+ id: nonIndicatorAreaSeparatorLine
1813+ anchors {
1814+ top: indicatorAreaBackground.bottom
1815+ left: parent.left
1816+ right: indicators.left
1817+ }
1818+ saturation: 1 - indicators.unitProgress
1819+ }
1820+
1821+ MouseArea {
1822+ anchors {
1823+ top: parent.top
1824+ left: parent.left
1825+ right: indicators.left
1826+ }
1827+ height: indicators.panelHeight
1828+ enabled: callHint.visible
1829+ onClicked: callHint.showLiveCall()
1830+ }
1831+
1832+ Indicators {
1833+ id: __indicators
1834+ objectName: "indicators"
1835+
1836+ anchors {
1837+ top: parent.top
1838+ right: parent.right
1839+ }
1840+
1841+ width: root.width
1842+ shown: false
1843+ panelHeight: units.gu(3)
1844+ openedHeight: root.height
1845+ overFlowWidth: {
1846+ if (callHint.visible) {
1847+ return Math.max(root.width - (callHint.width + units.gu(2)), 0)
1848+ }
1849+ return root.width
1850+ }
1851+
1852+ enableHint: !callHint.active && !fullscreenMode
1853+ showHintBottomMargin: fullscreenMode ? -panelHeight : 0
1854+
1855+ onShowTapped: {
1856+ if (callHint.active) {
1857+ callHint.showLiveCall();
1858+ }
1859+ }
1860+ }
1861+
1862+ ActiveCallHint {
1863+ id: __callHint
1864+ anchors {
1865+ top: parent.top
1866+ left: parent.left
1867+ }
1868+ height: indicators.panelHeight
1869+ visible: active && indicators.state == "initial"
1870+ }
1871+
1872+ PanelSeparatorLine {
1873+ id: indicatorsSeparatorLine
1874+ visible: true
1875+ anchors {
1876+ top: indicators.bottom
1877+ left: indicatorDividor.left
1878+ right: indicators.right
1879+ }
1880+ }
1881+ }
1882+
1883+ QtObject {
1884+ id: d
1885+ readonly property real indicatorHeight: indicators.panelHeight + indicatorsSeparatorLine.height
1886 }
1887
1888 states: [
1889 State {
1890- name: "in" //fully opaque and visible at top edge of screen
1891+ name: "onscreen" //fully opaque and visible at top edge of screen
1892 when: !fullscreenMode
1893- PropertyChanges { target: panelBackground; y: 0 }
1894+ PropertyChanges {
1895+ target: indicatorArea;
1896+ anchors.topMargin: 0
1897+ }
1898 },
1899 State {
1900- name: "out" //pushed off screen
1901+ name: "offscreen" //pushed off screen
1902 when: fullscreenMode
1903- PropertyChanges { target: panelBackground; y: -panelHeight }
1904+ PropertyChanges {
1905+ target: indicatorArea;
1906+ anchors.topMargin: indicators.state === "initial" ? -d.indicatorHeight : 0
1907+ }
1908 }
1909 ]
1910 }
1911
1912=== modified file 'qml/ScopeTool.qml'
1913--- qml/ScopeTool.qml 2014-05-19 11:10:58 +0000
1914+++ qml/ScopeTool.qml 2014-07-08 15:02:30 +0000
1915@@ -73,7 +73,6 @@
1916 id: dashContent
1917
1918 model: filteredScopes
1919- searchHistory: SearchHistoryModel { }
1920 property var scope: scopes.getScope(currentIndex)
1921
1922 anchors {
1923
1924=== modified file 'qml/Shell.qml'
1925--- qml/Shell.qml 2014-06-24 16:27:07 +0000
1926+++ qml/Shell.qml 2014-07-08 15:02:30 +0000
1927@@ -109,7 +109,7 @@
1928 anchors.rightMargin: -parent.anchors.rightMargin
1929
1930 // Whether the underlay is fully covered by opaque UI elements.
1931- property bool fullyCovered: panel.indicators.fullyOpened && shell.width <= panel.indicatorsMenuWidth
1932+ property bool fullyCovered: panel.indicators.fullyOpened && shell.width <= panel.indicators.width
1933
1934 // Whether the user should see the topmost application surface (if there's one at all).
1935 readonly property bool applicationSurfaceShouldBeSeen: stages.shown && !stages.painting && !stages.overlayMode
1936@@ -484,16 +484,16 @@
1937 Panel {
1938 id: panel
1939 anchors.fill: parent //because this draws indicator menus
1940- indicatorsMenuWidth: parent.width > units.gu(60) ? units.gu(40) : parent.width
1941 indicators {
1942 hides: [launcher]
1943 available: edgeDemo.panelEnabled
1944 contentEnabled: edgeDemo.panelContentEnabled
1945+ width: parent.width > units.gu(60) ? units.gu(40) : parent.width
1946+ panelHeight: units.gu(3)
1947 }
1948 property string focusedAppId: ApplicationManager.focusedApplicationId
1949 property var focusedApplication: ApplicationManager.findApplication(focusedAppId)
1950 fullscreenMode: focusedApplication && stages.fullscreen && !greeter.shown && !lockscreen.shown
1951- searchVisible: !greeter.shown && !lockscreen.shown && dash.shown && dash.searchable
1952
1953 InputFilterArea {
1954 anchors {
1955@@ -581,12 +581,10 @@
1956 model: NotificationBackend.Model
1957 margin: units.gu(1)
1958
1959- anchors {
1960- top: parent.top
1961- right: parent.right
1962- bottom: parent.bottom
1963- topMargin: panel.panelHeight
1964- }
1965+ y: panel.panelHeight
1966+ width: parent.width
1967+ height: parent.height - panel.panelHeight
1968+
1969 states: [
1970 State {
1971 name: "narrow"
1972
1973=== renamed file 'qml/graphics/applicationIcons/phone-app@18.png' => 'qml/graphics/applicationIcons/dialer-app@18.png'
1974=== modified file 'tests/autopilot/unity8/shell/tests/test_notifications.py'
1975--- tests/autopilot/unity8/shell/tests/test_notifications.py 2014-06-18 01:52:15 +0000
1976+++ tests/autopilot/unity8/shell/tests/test_notifications.py 2014-07-08 15:02:30 +0000
1977@@ -137,7 +137,7 @@
1978 ("x-canonical-switch-to-application", "true"),
1979 (
1980 "x-canonical-secondary-icon",
1981- self._get_icon_path('applicationIcons/phone-app.png')
1982+ self._get_icon_path('applicationIcons/dialer-app.png')
1983 )
1984 ]
1985
1986@@ -172,7 +172,7 @@
1987 hints = [
1988 (
1989 "x-canonical-secondary-icon",
1990- self._get_icon_path('applicationIcons/phone-app.png')
1991+ self._get_icon_path('applicationIcons/dialer-app.png')
1992 ),
1993 ("x-canonical-snap-decisions", "true"),
1994 ]
1995@@ -438,7 +438,7 @@
1996 hints = [
1997 (
1998 "x-canonical-secondary-icon",
1999- self._get_icon_path('applicationIcons/phone-app.png')
2000+ self._get_icon_path('applicationIcons/dialer-app.png')
2001 )
2002 ]
2003
2004@@ -681,7 +681,7 @@
2005 body = 'This bubble uses the icon-title-body layout with a ' \
2006 'secondary icon.'
2007 icon_path = self._get_icon_path('avatars/anna_olsson.png')
2008- hint_icon = self._get_icon_path('applicationIcons/phone-app.png')
2009+ hint_icon = self._get_icon_path('applicationIcons/dialer-app.png')
2010
2011 notification = shell.create_ephemeral_notification(
2012 summary,
2013
2014=== modified file 'tests/mocks/Ubuntu/CMakeLists.txt'
2015--- tests/mocks/Ubuntu/CMakeLists.txt 2014-06-27 20:53:24 +0000
2016+++ tests/mocks/Ubuntu/CMakeLists.txt 2014-07-08 15:02:30 +0000
2017@@ -1,3 +1,4 @@
2018 add_subdirectory(DownloadDaemonListener)
2019 add_subdirectory(Payments)
2020+add_subdirectory(Telephony)
2021 add_subdirectory(Thumbnailer)
2022
2023=== added directory 'tests/mocks/Ubuntu/Telephony'
2024=== added file 'tests/mocks/Ubuntu/Telephony/CMakeLists.txt'
2025--- tests/mocks/Ubuntu/Telephony/CMakeLists.txt 1970-01-01 00:00:00 +0000
2026+++ tests/mocks/Ubuntu/Telephony/CMakeLists.txt 2014-07-08 15:02:30 +0000
2027@@ -0,0 +1,22 @@
2028+set(FakeUbuntuTelephonyQml_SOURCES
2029+ plugin.cpp
2030+ ContactWatcherData.cpp
2031+ MockCallEntry.cpp
2032+ MockCallManager.cpp
2033+ MockContactWatcher.cpp
2034+ MockTelepathyHelper.cpp
2035+)
2036+
2037+add_library(FakeUbuntuTelephonyQml MODULE ${FakeUbuntuTelephonyQml_SOURCES})
2038+
2039+qt5_use_modules(FakeUbuntuTelephonyQml Core Quick)
2040+
2041+# copy files into build directory for shadow builds
2042+add_custom_target(UbuntuTelephonyQmlDirFile ALL
2043+ COMMAND cp "${CMAKE_CURRENT_SOURCE_DIR}/qmldir" ${CMAKE_CURRENT_BINARY_DIR}
2044+ DEPENDS qmldir
2045+)
2046+
2047+install(TARGETS FakeUbuntuTelephonyQml
2048+ DESTINATION ${SHELL_INSTALL_QML}/mocks/Ubuntu/Telephony
2049+ )
2050
2051=== added file 'tests/mocks/Ubuntu/Telephony/ContactWatcherData.cpp'
2052--- tests/mocks/Ubuntu/Telephony/ContactWatcherData.cpp 1970-01-01 00:00:00 +0000
2053+++ tests/mocks/Ubuntu/Telephony/ContactWatcherData.cpp 2014-07-08 15:02:30 +0000
2054@@ -0,0 +1,43 @@
2055+/*
2056+ * Copyright (C) 2014 Canonical, Ltd.
2057+ *
2058+ * This program is free software; you can redistribute it and/or modify
2059+ * it under the terms of the GNU General Public License as published by
2060+ * the Free Software Foundation; version 3.
2061+ *
2062+ * This program is distributed in the hope that it will be useful,
2063+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2064+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2065+ * GNU General Public License for more details.
2066+ *
2067+ * You should have received a copy of the GNU General Public License
2068+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2069+ *
2070+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
2071+ */
2072+
2073+#include "ContactWatcherData.h"
2074+
2075+ContactWatcherData::ContactWatcherData(QObject *parent)
2076+ : QObject(parent)
2077+{
2078+}
2079+
2080+ContactWatcherData *ContactWatcherData::instance()
2081+{
2082+ static ContactWatcherData* contactData = new ContactWatcherData();
2083+ return contactData;
2084+}
2085+
2086+QVariant ContactWatcherData::contactData() const
2087+{
2088+ return m_data;
2089+}
2090+
2091+void ContactWatcherData::setContactData(const QVariant& contactData)
2092+{
2093+ if(m_data != contactData){
2094+ m_data = contactData;
2095+ Q_EMIT contactDataChanged();
2096+ }
2097+}
2098
2099=== added file 'tests/mocks/Ubuntu/Telephony/ContactWatcherData.h'
2100--- tests/mocks/Ubuntu/Telephony/ContactWatcherData.h 1970-01-01 00:00:00 +0000
2101+++ tests/mocks/Ubuntu/Telephony/ContactWatcherData.h 2014-07-08 15:02:30 +0000
2102@@ -0,0 +1,46 @@
2103+/*
2104+ * Copyright (C) 2014 Canonical, Ltd.
2105+ *
2106+ * This program is free software; you can redistribute it and/or modify
2107+ * it under the terms of the GNU General Public License as published by
2108+ * the Free Software Foundation; version 3.
2109+ *
2110+ * This program is distributed in the hope that it will be useful,
2111+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2112+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2113+ * GNU General Public License for more details.
2114+ *
2115+ * You should have received a copy of the GNU General Public License
2116+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2117+ *
2118+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
2119+ */
2120+
2121+#ifndef CONTACTWATCHERDATA_H
2122+#define CONTACTWATCHERDATA_H
2123+
2124+#include <QObject>
2125+#include <QVariant>
2126+
2127+class ContactWatcherData : public QObject
2128+{
2129+ Q_OBJECT
2130+ Q_DISABLE_COPY(ContactWatcherData)
2131+ Q_PROPERTY(QVariant contactData READ contactData WRITE setContactData NOTIFY contactDataChanged)
2132+
2133+public:
2134+ ContactWatcherData(QObject *parent = 0);
2135+
2136+ static ContactWatcherData *instance();
2137+
2138+ QVariant contactData() const;
2139+ void setContactData(const QVariant& contactData);
2140+
2141+Q_SIGNALS:
2142+ void contactDataChanged();
2143+
2144+private:
2145+ QVariant m_data;
2146+};
2147+
2148+#endif // CONTACTWATCHERDATA_H
2149
2150=== added file 'tests/mocks/Ubuntu/Telephony/MockCallEntry.cpp'
2151--- tests/mocks/Ubuntu/Telephony/MockCallEntry.cpp 1970-01-01 00:00:00 +0000
2152+++ tests/mocks/Ubuntu/Telephony/MockCallEntry.cpp 2014-07-08 15:02:30 +0000
2153@@ -0,0 +1,66 @@
2154+/*
2155+ * Copyright (C) 2014 Canonical, Ltd.
2156+ *
2157+ * This program is free software; you can redistribute it and/or modify
2158+ * it under the terms of the GNU General Public License as published by
2159+ * the Free Software Foundation; version 3.
2160+ *
2161+ * This program is distributed in the hope that it will be useful,
2162+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2163+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2164+ * GNU General Public License for more details.
2165+ *
2166+ * You should have received a copy of the GNU General Public License
2167+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2168+ *
2169+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
2170+ */
2171+
2172+#include "MockCallEntry.h"
2173+
2174+MockCallEntry::MockCallEntry(QObject *parent)
2175+ : QObject(parent)
2176+ , m_conference(false)
2177+ , m_elapsed(0)
2178+{
2179+ startTimer(1000);
2180+}
2181+
2182+QString MockCallEntry::phoneNumber() const
2183+{
2184+ return m_phoneNumber;
2185+}
2186+
2187+void MockCallEntry::setPhoneNumber(const QString& phoneNumber)
2188+{
2189+ if(m_phoneNumber != phoneNumber){
2190+ m_phoneNumber = phoneNumber;
2191+ Q_EMIT phoneNumberChanged();
2192+ }
2193+}
2194+
2195+bool MockCallEntry::isConference() const
2196+{
2197+ return m_conference;
2198+}
2199+
2200+void MockCallEntry::setIsConference(bool isConference)
2201+{
2202+ if(m_conference != isConference){
2203+ m_conference = isConference;
2204+ Q_EMIT isConferenceChanged();
2205+ }
2206+}
2207+
2208+int MockCallEntry::elapsedTime() const
2209+{
2210+ return m_elapsed;
2211+}
2212+
2213+void MockCallEntry::timerEvent(QTimerEvent * event)
2214+{
2215+ Q_UNUSED(event);
2216+
2217+ m_elapsed++;
2218+ Q_EMIT elapsedTimeChanged();
2219+}
2220
2221=== added file 'tests/mocks/Ubuntu/Telephony/MockCallEntry.h'
2222--- tests/mocks/Ubuntu/Telephony/MockCallEntry.h 1970-01-01 00:00:00 +0000
2223+++ tests/mocks/Ubuntu/Telephony/MockCallEntry.h 2014-07-08 15:02:30 +0000
2224@@ -0,0 +1,57 @@
2225+/*
2226+ * Copyright (C) 2014 Canonical, Ltd.
2227+ *
2228+ * This program is free software; you can redistribute it and/or modify
2229+ * it under the terms of the GNU General Public License as published by
2230+ * the Free Software Foundation; version 3.
2231+ *
2232+ * This program is distributed in the hope that it will be useful,
2233+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2234+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2235+ * GNU General Public License for more details.
2236+ *
2237+ * You should have received a copy of the GNU General Public License
2238+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2239+ *
2240+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
2241+ */
2242+
2243+#ifndef MOCKCALLENTRY_H
2244+#define MOCKCALLENTRY_H
2245+
2246+#include <QObject>
2247+
2248+class MockCallEntry : public QObject
2249+{
2250+ Q_OBJECT
2251+ Q_DISABLE_COPY(MockCallEntry)
2252+
2253+ Q_PROPERTY(QString phoneNumber READ phoneNumber WRITE setPhoneNumber NOTIFY phoneNumberChanged)
2254+ Q_PROPERTY(bool isConference READ isConference WRITE setIsConference NOTIFY isConferenceChanged)
2255+ Q_PROPERTY(int elapsedTime READ elapsedTime NOTIFY elapsedTimeChanged)
2256+
2257+public:
2258+ MockCallEntry(QObject *parent = 0);
2259+
2260+ QString phoneNumber() const;
2261+ bool isConference() const;
2262+ int elapsedTime() const;
2263+
2264+ void setPhoneNumber(const QString& phoneNumber);
2265+ void setIsConference(bool isConference);
2266+
2267+Q_SIGNALS:
2268+ void phoneNumberChanged();
2269+ void isConferenceChanged();
2270+ void elapsedTimeChanged();
2271+
2272+protected:
2273+ void timerEvent(QTimerEvent * event);
2274+
2275+private:
2276+ QString m_phoneNumber;
2277+ bool m_conference;
2278+ int m_elapsed;
2279+};
2280+
2281+#endif // MOCKCALLENTRY_H
2282
2283=== added file 'tests/mocks/Ubuntu/Telephony/MockCallManager.cpp'
2284--- tests/mocks/Ubuntu/Telephony/MockCallManager.cpp 1970-01-01 00:00:00 +0000
2285+++ tests/mocks/Ubuntu/Telephony/MockCallManager.cpp 2014-07-08 15:02:30 +0000
2286@@ -0,0 +1,80 @@
2287+/*
2288+ * Copyright (C) 2014 Canonical, Ltd.
2289+ *
2290+ * This program is free software; you can redistribute it and/or modify
2291+ * it under the terms of the GNU General Public License as published by
2292+ * the Free Software Foundation; version 3.
2293+ *
2294+ * This program is distributed in the hope that it will be useful,
2295+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2296+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2297+ * GNU General Public License for more details.
2298+ *
2299+ * You should have received a copy of the GNU General Public License
2300+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2301+ *
2302+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
2303+ */
2304+
2305+#include "MockCallManager.h"
2306+
2307+MockCallManager::MockCallManager(QObject *parent)
2308+ : QObject(parent)
2309+ , m_foregroundCall(nullptr)
2310+ , m_backgroundCall(nullptr)
2311+ , m_callIndicatorVisible(false)
2312+{
2313+}
2314+
2315+MockCallManager *MockCallManager::instance()
2316+{
2317+ static MockCallManager* manager = new MockCallManager();
2318+ return manager;
2319+}
2320+
2321+QObject* MockCallManager::foregroundCall() const
2322+{
2323+ return m_foregroundCall;
2324+}
2325+
2326+void MockCallManager::setForegroundCall(QObject* foregroundCall)
2327+{
2328+ if(m_foregroundCall != foregroundCall){
2329+ m_foregroundCall = foregroundCall;
2330+ Q_EMIT foregroundCallChanged();
2331+ Q_EMIT hasCallsChanged();
2332+ }
2333+}
2334+
2335+QObject* MockCallManager::backgroundCall() const
2336+{
2337+ return m_backgroundCall;
2338+}
2339+
2340+void MockCallManager::setBackgroundCall(QObject* backgroundCall)
2341+{
2342+ if(m_backgroundCall != backgroundCall){
2343+ m_backgroundCall = backgroundCall;
2344+ Q_EMIT backgroundCallChanged();
2345+ Q_EMIT hasCallsChanged();
2346+ }
2347+}
2348+
2349+bool MockCallManager::hasCalls() const
2350+{
2351+ return m_foregroundCall || m_backgroundCall;
2352+}
2353+
2354+
2355+bool MockCallManager::callIndicatorVisible() const
2356+{
2357+ return m_callIndicatorVisible;
2358+}
2359+
2360+void MockCallManager::setCallIndicatorVisible(bool callIndicatorVisible)
2361+{
2362+ if(m_callIndicatorVisible != callIndicatorVisible){
2363+ m_callIndicatorVisible = callIndicatorVisible;
2364+ Q_EMIT callIndicatorVisibleChanged();
2365+ }
2366+}
2367
2368=== added file 'tests/mocks/Ubuntu/Telephony/MockCallManager.h'
2369--- tests/mocks/Ubuntu/Telephony/MockCallManager.h 1970-01-01 00:00:00 +0000
2370+++ tests/mocks/Ubuntu/Telephony/MockCallManager.h 2014-07-08 15:02:30 +0000
2371@@ -0,0 +1,60 @@
2372+/*
2373+ * Copyright (C) 2014 Canonical, Ltd.
2374+ *
2375+ * This program is free software; you can redistribute it and/or modify
2376+ * it under the terms of the GNU General Public License as published by
2377+ * the Free Software Foundation; version 3.
2378+ *
2379+ * This program is distributed in the hope that it will be useful,
2380+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2381+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2382+ * GNU General Public License for more details.
2383+ *
2384+ * You should have received a copy of the GNU General Public License
2385+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2386+ *
2387+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
2388+ */
2389+
2390+#ifndef MOCKCALLMANAGER_H
2391+#define MOCKCALLMANAGER_H
2392+
2393+#include <QObject>
2394+
2395+class MockCallManager : public QObject
2396+{
2397+ Q_OBJECT
2398+ Q_DISABLE_COPY(MockCallManager)
2399+
2400+ Q_PROPERTY(QObject *foregroundCall READ foregroundCall WRITE setForegroundCall NOTIFY foregroundCallChanged)
2401+ Q_PROPERTY(QObject *backgroundCall READ backgroundCall WRITE setBackgroundCall NOTIFY backgroundCallChanged)
2402+ Q_PROPERTY(bool hasCalls READ hasCalls NOTIFY hasCallsChanged)
2403+ Q_PROPERTY(bool callIndicatorVisible READ callIndicatorVisible WRITE setCallIndicatorVisible NOTIFY callIndicatorVisibleChanged)
2404+
2405+public:
2406+ explicit MockCallManager(QObject *parent = 0);
2407+
2408+ static MockCallManager *instance();
2409+
2410+ QObject* foregroundCall() const;
2411+ QObject* backgroundCall() const;
2412+ bool hasCalls() const;
2413+ bool callIndicatorVisible() const;
2414+
2415+ void setForegroundCall(QObject* foregroundCall);
2416+ void setBackgroundCall(QObject* backgroundCall);
2417+ void setCallIndicatorVisible(bool callIndicatorVisible);
2418+
2419+Q_SIGNALS:
2420+ void foregroundCallChanged();
2421+ void backgroundCallChanged();
2422+ void hasCallsChanged();
2423+ void callIndicatorVisibleChanged();
2424+
2425+private:
2426+ QObject* m_foregroundCall;
2427+ QObject* m_backgroundCall;
2428+ bool m_callIndicatorVisible;
2429+};
2430+
2431+#endif // MOCKCALLMANAGER_H
2432
2433=== added file 'tests/mocks/Ubuntu/Telephony/MockContactWatcher.cpp'
2434--- tests/mocks/Ubuntu/Telephony/MockContactWatcher.cpp 1970-01-01 00:00:00 +0000
2435+++ tests/mocks/Ubuntu/Telephony/MockContactWatcher.cpp 2014-07-08 15:02:30 +0000
2436@@ -0,0 +1,50 @@
2437+/*
2438+ * Copyright (C) 2014 Canonical, Ltd.
2439+ *
2440+ * This program is free software; you can redistribute it and/or modify
2441+ * it under the terms of the GNU General Public License as published by
2442+ * the Free Software Foundation; version 3.
2443+ *
2444+ * This program is distributed in the hope that it will be useful,
2445+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2446+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2447+ * GNU General Public License for more details.
2448+ *
2449+ * You should have received a copy of the GNU General Public License
2450+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2451+ *
2452+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
2453+ */
2454+
2455+#include "MockContactWatcher.h"
2456+#include "ContactWatcherData.h"
2457+
2458+MockContactWatcher::MockContactWatcher(QObject *parent)
2459+ : QObject(parent)
2460+{
2461+ connect(ContactWatcherData::instance(), &ContactWatcherData::contactDataChanged,
2462+ this, &MockContactWatcher::aliasChanged);
2463+}
2464+
2465+QString MockContactWatcher::phoneNumber() const
2466+{
2467+ return m_phoneNumber;
2468+}
2469+
2470+void MockContactWatcher::setPhoneNumber(const QString& phoneNumber)
2471+{
2472+ if(m_phoneNumber != phoneNumber){
2473+ m_phoneNumber = phoneNumber;
2474+ Q_EMIT phoneNumberChanged();
2475+ Q_EMIT aliasChanged();
2476+ }
2477+}
2478+
2479+QString MockContactWatcher::alias() const
2480+{
2481+ QVariantMap data = ContactWatcherData::instance()->contactData().toMap();
2482+ if (data.contains(m_phoneNumber)) {
2483+ return data[m_phoneNumber].toMap()["alias"].toString();
2484+ }
2485+ return "";
2486+}
2487
2488=== added file 'tests/mocks/Ubuntu/Telephony/MockContactWatcher.h'
2489--- tests/mocks/Ubuntu/Telephony/MockContactWatcher.h 1970-01-01 00:00:00 +0000
2490+++ tests/mocks/Ubuntu/Telephony/MockContactWatcher.h 2014-07-08 15:02:30 +0000
2491@@ -0,0 +1,49 @@
2492+/*
2493+ * Copyright (C) 2014 Canonical, Ltd.
2494+ *
2495+ * This program is free software; you can redistribute it and/or modify
2496+ * it under the terms of the GNU General Public License as published by
2497+ * the Free Software Foundation; version 3.
2498+ *
2499+ * This program is distributed in the hope that it will be useful,
2500+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2501+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2502+ * GNU General Public License for more details.
2503+ *
2504+ * You should have received a copy of the GNU General Public License
2505+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2506+ *
2507+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
2508+ */
2509+
2510+#ifndef MOCKCONTACTWATCHER_H
2511+#define MOCKCONTACTWATCHER_H
2512+
2513+#include <QObject>
2514+#include <QVariant>
2515+
2516+class MockContactWatcher : public QObject
2517+{
2518+ Q_OBJECT
2519+ Q_DISABLE_COPY(MockContactWatcher)
2520+
2521+ Q_PROPERTY(QString phoneNumber READ phoneNumber WRITE setPhoneNumber NOTIFY phoneNumberChanged)
2522+ Q_PROPERTY(QString alias READ alias NOTIFY aliasChanged)
2523+
2524+public:
2525+ MockContactWatcher(QObject *parent = 0);
2526+
2527+ QString phoneNumber() const;
2528+ QString alias() const;
2529+
2530+ void setPhoneNumber(const QString& phoneNumber);
2531+
2532+Q_SIGNALS:
2533+ void phoneNumberChanged();
2534+ void aliasChanged();
2535+
2536+private:
2537+ QString m_phoneNumber;
2538+};
2539+
2540+#endif // MOCKCONTACTWATCHER_H
2541
2542=== added file 'tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.cpp'
2543--- tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.cpp 1970-01-01 00:00:00 +0000
2544+++ tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.cpp 2014-07-08 15:02:30 +0000
2545@@ -0,0 +1,35 @@
2546+/*
2547+ * Copyright (C) 2014 Canonical, Ltd.
2548+ *
2549+ * This program is free software; you can redistribute it and/or modify
2550+ * it under the terms of the GNU General Public License as published by
2551+ * the Free Software Foundation; version 3.
2552+ *
2553+ * This program is distributed in the hope that it will be useful,
2554+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2555+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2556+ * GNU General Public License for more details.
2557+ *
2558+ * You should have received a copy of the GNU General Public License
2559+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2560+ *
2561+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
2562+ */
2563+
2564+#include "MockTelepathyHelper.h"
2565+
2566+MockTelepathyHelper::MockTelepathyHelper(QObject *parent)
2567+ : QObject(parent)
2568+{
2569+}
2570+
2571+MockTelepathyHelper *MockTelepathyHelper::instance()
2572+{
2573+ static MockTelepathyHelper* helper = new MockTelepathyHelper();
2574+ return helper;
2575+}
2576+
2577+void MockTelepathyHelper::registerChannelObserver(const QString& name)
2578+{
2579+ Q_UNUSED(name);
2580+}
2581
2582=== added file 'tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.h'
2583--- tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.h 1970-01-01 00:00:00 +0000
2584+++ tests/mocks/Ubuntu/Telephony/MockTelepathyHelper.h 2014-07-08 15:02:30 +0000
2585@@ -0,0 +1,36 @@
2586+/*
2587+ * Copyright (C) 2014 Canonical, Ltd.
2588+ *
2589+ * This program is free software; you can redistribute it and/or modify
2590+ * it under the terms of the GNU General Public License as published by
2591+ * the Free Software Foundation; version 3.
2592+ *
2593+ * This program is distributed in the hope that it will be useful,
2594+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2595+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2596+ * GNU General Public License for more details.
2597+ *
2598+ * You should have received a copy of the GNU General Public License
2599+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2600+ *
2601+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
2602+ */
2603+
2604+#ifndef MOCKTELEPATHYHELPER_H
2605+#define MOCKTELEPATHYHELPER_H
2606+
2607+#include <QObject>
2608+
2609+class MockTelepathyHelper : public QObject
2610+{
2611+ Q_OBJECT
2612+ Q_DISABLE_COPY(MockTelepathyHelper)
2613+public:
2614+ MockTelepathyHelper(QObject *parent = 0);
2615+
2616+ static MockTelepathyHelper *instance();
2617+
2618+ Q_INVOKABLE void registerChannelObserver(const QString& name);
2619+};
2620+
2621+#endif // MOCKCONTACTWATCHER_H
2622
2623=== added file 'tests/mocks/Ubuntu/Telephony/plugin.cpp'
2624--- tests/mocks/Ubuntu/Telephony/plugin.cpp 1970-01-01 00:00:00 +0000
2625+++ tests/mocks/Ubuntu/Telephony/plugin.cpp 2014-07-08 15:02:30 +0000
2626@@ -0,0 +1,52 @@
2627+/*
2628+ * Copyright (C) 2014 Canonical, Ltd.
2629+ *
2630+ * This program is free software; you can redistribute it and/or modify
2631+ * it under the terms of the GNU General Public License as published by
2632+ * the Free Software Foundation; version 3.
2633+ *
2634+ * This program is distributed in the hope that it will be useful,
2635+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2636+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2637+ * GNU General Public License for more details.
2638+ *
2639+ * You should have received a copy of the GNU General Public License
2640+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2641+ *
2642+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
2643+ */
2644+
2645+#include "plugin.h"
2646+#include "MockCallEntry.h"
2647+#include "MockCallManager.h"
2648+#include "MockContactWatcher.h"
2649+#include "MockTelepathyHelper.h"
2650+#include "ContactWatcherData.h"
2651+
2652+#include <QtQml/QQmlContext>
2653+#include <QtQml/QQmlEngine>
2654+#include <qqml.h>
2655+
2656+void FakeUbuntuTelephonyQmlPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
2657+{
2658+ Q_ASSERT(engine);
2659+
2660+ Q_UNUSED(uri);
2661+
2662+ mRootContext = engine->rootContext();
2663+ Q_ASSERT(mRootContext);
2664+
2665+ mRootContext->setContextProperty("telepathyHelper", MockTelepathyHelper::instance());
2666+ mRootContext->setContextProperty("callManager", MockCallManager::instance());
2667+ mRootContext->setContextProperty("contactWactherData", ContactWatcherData::instance());
2668+}
2669+
2670+void FakeUbuntuTelephonyQmlPlugin::registerTypes(const char *uri)
2671+{
2672+ // @uri Telephony
2673+ qmlRegisterUncreatableType<MockTelepathyHelper>(uri, 0, 1, "TelepathyHelper", "This is a singleton helper class");
2674+ qmlRegisterUncreatableType<MockCallManager>(uri, 0, 1, "CallManager", "This is a singleton manager class");
2675+ qmlRegisterUncreatableType<ContactWatcherData>(uri, 0, 1, "ContactWatcherData", "This is a singleton data class");
2676+ qmlRegisterType<MockCallEntry>(uri, 0, 1, "CallEntry");
2677+ qmlRegisterType<MockContactWatcher>(uri, 0, 1, "ContactWatcher");
2678+}
2679
2680=== added file 'tests/mocks/Ubuntu/Telephony/plugin.h'
2681--- tests/mocks/Ubuntu/Telephony/plugin.h 1970-01-01 00:00:00 +0000
2682+++ tests/mocks/Ubuntu/Telephony/plugin.h 2014-07-08 15:02:30 +0000
2683@@ -0,0 +1,37 @@
2684+/*
2685+ * Copyright (C) 2014 Canonical, Ltd.
2686+ *
2687+ * This program is free software; you can redistribute it and/or modify
2688+ * it under the terms of the GNU General Public License as published by
2689+ * the Free Software Foundation; version 3.
2690+ *
2691+ * This program is distributed in the hope that it will be useful,
2692+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2693+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2694+ * GNU General Public License for more details.
2695+ *
2696+ * You should have received a copy of the GNU General Public License
2697+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2698+ *
2699+ * Authored by: Nick Dedekind <nick.dedekind@canonical.com
2700+ */
2701+
2702+#ifndef PLUGIN_H
2703+#define PLUGIN_H
2704+
2705+#include <QQmlContext>
2706+#include <QQmlExtensionPlugin>
2707+
2708+class FakeUbuntuTelephonyQmlPlugin : public QQmlExtensionPlugin
2709+{
2710+ Q_OBJECT
2711+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
2712+public:
2713+ void initializeEngine(QQmlEngine *engine, const char *uri);
2714+ void registerTypes(const char *uri);
2715+
2716+private:
2717+ QQmlContext *mRootContext;
2718+};
2719+
2720+#endif
2721
2722=== added file 'tests/mocks/Ubuntu/Telephony/qmldir'
2723--- tests/mocks/Ubuntu/Telephony/qmldir 1970-01-01 00:00:00 +0000
2724+++ tests/mocks/Ubuntu/Telephony/qmldir 2014-07-08 15:02:30 +0000
2725@@ -0,0 +1,2 @@
2726+module Ubuntu.Telephony
2727+plugin FakeUbuntuTelephonyQml
2728
2729=== modified file 'tests/mocks/Unity/Application/ApplicationManager.cpp'
2730--- tests/mocks/Unity/Application/ApplicationManager.cpp 2014-03-20 09:45:39 +0000
2731+++ tests/mocks/Unity/Application/ApplicationManager.cpp 2014-07-08 15:02:30 +0000
2732@@ -361,9 +361,9 @@
2733 ApplicationInfo *application;
2734
2735 application = new ApplicationInfo(this);
2736- application->setAppId("phone-app");
2737- application->setName("Phone");
2738- application->setIcon(QUrl("phone"));
2739+ application->setAppId("dialer-app");
2740+ application->setName("Dialer");
2741+ application->setIcon(QUrl("dialer"));
2742 application->setStage(ApplicationInfo::SideStage);
2743 application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
2744 generateQmlStrings(application);
2745
2746=== modified file 'tests/mocks/Unity/Launcher/MockLauncherModel.cpp'
2747--- tests/mocks/Unity/Launcher/MockLauncherModel.cpp 2014-05-29 14:32:07 +0000
2748+++ tests/mocks/Unity/Launcher/MockLauncherModel.cpp 2014-07-08 15:02:30 +0000
2749@@ -22,7 +22,7 @@
2750
2751 MockLauncherModel::MockLauncherModel(QObject* parent): LauncherModelInterface(parent)
2752 {
2753- MockLauncherItem *item = new MockLauncherItem("phone-app", "/usr/share/applications/phone-app.desktop", "Phone", "phone-app", this);
2754+ MockLauncherItem *item = new MockLauncherItem("dialer-app", "/usr/share/applications/dialer-app.desktop", "Dialer", "dialer-app", this);
2755 item->setProgress(0);
2756 m_list.append(item);
2757 item->setFocused(true);
2758
2759=== modified file 'tests/qmltests/CMakeLists.txt'
2760--- tests/qmltests/CMakeLists.txt 2014-06-27 20:53:24 +0000
2761+++ tests/qmltests/CMakeLists.txt 2014-07-08 15:02:30 +0000
2762@@ -32,7 +32,7 @@
2763 add_qml_test(Components ResponsiveVerticalJournal IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
2764 add_qml_test(Components SeeMore)
2765 add_qml_test(Components Showable)
2766-add_qml_test(Components PageHeaderLabel)
2767+add_qml_test(Components PageHeader)
2768 add_qml_test(Components ZoomableImage)
2769 add_qml_test(Dash Dash)
2770 add_qml_test(Dash DashContent)
2771@@ -64,6 +64,7 @@
2772 add_qml_test(Launcher Launcher)
2773 add_qml_test(Notifications Notifications)
2774 add_qml_test(Notifications VisualSnapDecisionsQueue)
2775+add_qml_test(Panel ActiveCallHint)
2776 add_qml_test(Panel IndicatorRow)
2777 add_qml_test(Panel Indicators)
2778 add_qml_test(Panel MenuContent)
2779
2780=== added directory 'tests/qmltests/Components/tst_PageHeader'
2781=== renamed file 'tests/qmltests/Components/tst_PageHeaderLabel.qml' => 'tests/qmltests/Components/tst_PageHeader.qml'
2782--- tests/qmltests/Components/tst_PageHeaderLabel.qml 2014-05-20 15:16:49 +0000
2783+++ tests/qmltests/Components/tst_PageHeader.qml 2014-07-08 15:02:30 +0000
2784@@ -23,13 +23,10 @@
2785 import Unity.Test 0.1 as UT
2786
2787 Item {
2788+ id: root
2789 width: units.gu(110)
2790 height: units.gu(30)
2791
2792- MockScope {
2793- id: scopeMock
2794- }
2795-
2796 UT.UnityTestCase {
2797 name: "PageHeaderLabelTest"
2798 when: windowShown
2799@@ -82,33 +79,6 @@
2800 compare(searchQuery, "", "Reset search did not reset searchQuery correctly.")
2801 }
2802
2803- function test_move_search_by_width()
2804- {
2805- searchEnabled = true
2806- pageHeader.resetSearch()
2807-
2808- var searchContainer = findChild(pageHeader, "searchContainer")
2809-
2810- parent.width = units.gu(40)
2811-
2812- verify(searchContainer !== undefined)
2813- verify(searchContainer.y <= 0)
2814-
2815- pageHeader.triggerSearch()
2816- verify(searchContainer.y >= 0)
2817-
2818- pageHeader.resetSearch()
2819- verify(searchContainer.y <= 0)
2820-
2821- parent.width = units.gu(110)
2822- verify(searchContainer.y >= 0)
2823-
2824- pageHeader.triggerSearch()
2825- tryCompare(searchContainer, "narrowMode", false)
2826- tryCompare(searchContainer, "state", "active")
2827- tryCompare(searchContainer, "width", units.gu(40))
2828- }
2829-
2830 function test_history() {
2831 pageHeader.searchHistory.clear()
2832 compare(pageHeader.searchHistory.count, 0)
2833@@ -144,21 +114,41 @@
2834
2835 function test_search_indicator() {
2836 var searchIndicator = findChild(pageHeader, "searchIndicator")
2837- var primaryImage = findChild(pageHeader, "primaryImage")
2838+ var clearIcon = findChild(pageHeader, "clearIcon")
2839
2840 pageHeader.triggerSearch()
2841
2842- scopeMock.setSearchInProgress(false);
2843+ tryCompare(clearIcon, "visible", false)
2844+ pageHeader.searchQuery = "ubuntu"
2845+ tryCompare(clearIcon, "visible", true)
2846+
2847+ pageHeader.searchInProgress = false
2848 compare(searchIndicator.running, false, "Search indicator is running.")
2849- tryCompare(primaryImage, "visible", true)
2850+ tryCompare(clearIcon, "visible", true)
2851
2852- scopeMock.setSearchInProgress(true);
2853+ pageHeader.searchInProgress = true
2854 compare(searchIndicator.running, true, "Search indicator isn't running.")
2855- tryCompare(primaryImage, "visible", false)
2856+ tryCompare(clearIcon, "visible", false)
2857+
2858+ pageHeader.searchInProgress = false;
2859+ compare(searchIndicator.running, false, "Search indicator is running.")
2860+ tryCompare(clearIcon, "visible", true)
2861+ }
2862+
2863+ function test_titleImage() {
2864+
2865+ var titleImage = findChild(pageHeader, "titleImage");
2866+ verify(titleImage == null);
2867+
2868+ showImageCheckBox.checked = true;
2869+
2870+ titleImage = findChild(pageHeader, "titleImage");
2871+ verify(titleImage !== null);
2872+ compare(titleImage.source, pageHeader.titleImageSource);
2873+
2874 }
2875
2876 function cleanup() {
2877- scopeMock.setSearchInProgress(false);
2878 pageHeader.resetSearch();
2879 }
2880
2881@@ -171,14 +161,21 @@
2882
2883 pageHeader.triggerSearch();
2884
2885- var searchContainer = findChild(pageHeader, "searchContainer");
2886- verify(searchContainer !== undefined, "searchContainer != undefined");
2887- tryCompareFunction(function() { return searchContainer.popover !== null; }, true);
2888-
2889- tryCompare(searchContainer.popover, "visible", true);
2890- }
2891-
2892- function test_resetSearch_onPopupClose() {
2893+ var headerContainer = findChild(pageHeader, "headerContainer");
2894+ verify(headerContainer !== null, "headerContainer != null");
2895+ tryCompareFunction(function() { return headerContainer.popover !== null; }, true);
2896+
2897+ tryCompare(headerContainer.popover, "visible", true);
2898+ }
2899+
2900+ function test_tap_outside_closes_popup_data() {
2901+ return [
2902+ { tag: "with search text", searchText: "foobar", hideSearch: false },
2903+ { tag: "without search text", searchText: "", hideSearch: true }
2904+ ];
2905+ }
2906+
2907+ function test_tap_outside_closes_popup(data) {
2908 searchEnabled = true;
2909 pageHeader.searchHistory.clear();
2910
2911@@ -187,16 +184,19 @@
2912
2913 pageHeader.triggerSearch();
2914
2915- var searchContainer = findChild(pageHeader, "searchContainer");
2916- verify(searchContainer !== undefined, "searchContainer != undefined");
2917- tryCompareFunction(function() { return searchContainer.popover !== null; }, true);
2918- compare(searchContainer.popover.visible, true);
2919-
2920- pageHeader.searchQuery = "test";
2921- tryCompareFunction( function() { return (searchContainer.popover===null || !searchContainer.popover.visible) }, true);
2922+ var headerContainer = findChild(pageHeader, "headerContainer");
2923+ verify(headerContainer !== null, "headerContainer != null");
2924+ tryCompareFunction(function() { return headerContainer.popover !== null; }, true);
2925+ compare(headerContainer.popover.visible, true);
2926+
2927+ pageHeader.searchQuery = data.searchText;
2928+
2929+ mouseClick(root, root.width / 2, root.height - 1);
2930+
2931+ tryCompare(headerContainer, "showSearch", !data.hideSearch);
2932+ tryCompareFunction(function() { return headerContainer.popover === null; }, true);
2933
2934 pageHeader.resetSearch();
2935- compare((searchContainer.popover===null || !searchContainer.popover.visible), true);
2936 }
2937 }
2938
2939@@ -204,18 +204,21 @@
2940 anchors.fill: parent
2941 spacing: units.gu(1)
2942
2943- PageHeaderLabel {
2944+ PageHeader {
2945 id: pageHeader
2946 anchors {
2947 left: parent.left
2948 right: parent.right
2949 }
2950
2951- scope: scopeMock
2952-
2953 searchEntryEnabled: true
2954- searchHistory: SearchHistoryModel {}
2955- text: "%^$%^%^&%^&%^$%GHR%"
2956+ title: "%^$%^%^&%^&%^$%GHR%"
2957+ imageSource: showImageCheckBox.checked ? titleImageSource : ""
2958+ showBackButton: showBackButtonCheckBox.checked
2959+
2960+ property string titleImageSource: Qt.resolvedUrl("tst_PageHeader/logo-ubuntu-orange.svg")
2961+ property date lastBackClicked
2962+ onBackClicked: lastBackClicked = new Date()
2963 }
2964
2965 Row {
2966@@ -251,5 +254,35 @@
2967 anchors.verticalCenter: parent.verticalCenter
2968 }
2969 }
2970+
2971+ Row {
2972+ spacing: units.gu(1)
2973+ anchors {
2974+ left: parent.left
2975+ right: parent.right
2976+ }
2977+ CheckBox {
2978+ id: showBackButtonCheckBox
2979+ }
2980+ Label {
2981+ text: "Back button enabled (Last clicked: " + Qt.formatTime(pageHeader.lastBackClicked, "hh:mm:ss") + ")"
2982+ anchors.verticalCenter: parent.verticalCenter
2983+ }
2984+ }
2985+
2986+ Row {
2987+ spacing: units.gu(1)
2988+ anchors {
2989+ left: parent.left
2990+ right: parent.right
2991+ }
2992+ CheckBox {
2993+ id: showImageCheckBox
2994+ }
2995+ Label {
2996+ text: "Show image instead of title"
2997+ anchors.verticalCenter: parent.verticalCenter
2998+ }
2999+ }
3000 }
3001 }
3002
3003=== added file 'tests/qmltests/Components/tst_PageHeader/logo-ubuntu-orange.svg'
3004--- tests/qmltests/Components/tst_PageHeader/logo-ubuntu-orange.svg 1970-01-01 00:00:00 +0000
3005+++ tests/qmltests/Components/tst_PageHeader/logo-ubuntu-orange.svg 2014-07-08 15:02:30 +0000
3006@@ -0,0 +1,60 @@
3007+<?xml version="1.0" encoding="utf-8"?>
3008+<!-- Generator: Adobe Illustrator 17.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3009+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3010+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
3011+ width="107px" height="25px" viewBox="0 0 107 25" enable-background="new 0 0 107 25" xml:space="preserve">
3012+<g id="BK">
3013+</g>
3014+<g id="Comp">
3015+ <circle fill="#DD4814" cx="100.596" cy="7.374" r="6.403"/>
3016+ <path fill="#FFFFFF" d="M96.6,6.605c-0.424,0-0.768,0.344-0.768,0.77c0,0.423,0.344,0.768,0.768,0.768
3017+ c0.425,0,0.772-0.345,0.772-0.768C97.371,6.949,97.025,6.605,96.6,6.605z M102.094,10.103c-0.365,0.211-0.492,0.682-0.282,1.047
3018+ c0.214,0.372,0.685,0.497,1.051,0.284c0.369-0.21,0.496-0.682,0.281-1.05C102.932,10.014,102.462,9.889,102.094,10.103z
3019+ M98.272,7.375c0-0.76,0.378-1.434,0.956-1.839l-0.562-0.944c-0.675,0.451-1.176,1.138-1.384,1.943
3020+ c0.246,0.2,0.398,0.501,0.398,0.84c0,0.337-0.152,0.639-0.398,0.838c0.208,0.805,0.709,1.492,1.384,1.941l0.562-0.941
3021+ C98.65,8.807,98.272,8.134,98.272,7.375z M100.518,5.125c1.177,0,2.14,0.902,2.24,2.052l1.098-0.019
3022+ c-0.055-0.846-0.425-1.61-0.994-2.166c-0.295,0.108-0.634,0.093-0.925-0.078c-0.292-0.168-0.473-0.452-0.524-0.761
3023+ c-0.285-0.077-0.584-0.12-0.895-0.12c-0.53,0-1.032,0.125-1.48,0.345l0.535,0.958C99.86,5.201,100.182,5.125,100.518,5.125z
3024+ M100.518,9.622c-0.336,0-0.658-0.076-0.945-0.21l-0.535,0.958c0.447,0.221,0.95,0.344,1.48,0.344c0.312,0,0.61-0.039,0.895-0.119
3025+ c0.051-0.311,0.232-0.596,0.524-0.763c0.294-0.168,0.63-0.186,0.925-0.073c0.569-0.562,0.938-1.323,0.994-2.17l-1.098-0.015
3026+ C102.658,8.721,101.695,9.622,100.518,9.622z M102.094,4.646c0.368,0.213,0.838,0.088,1.051-0.282
3027+ c0.214-0.367,0.087-0.839-0.281-1.052c-0.366-0.211-0.837-0.085-1.051,0.283C101.601,3.962,101.728,4.433,102.094,4.646z"/>
3028+ <path fill="#DD4814" d="M12.807,24.177c-0.649,0.162-1.509,0.337-2.577,0.518c-1.068,0.184-2.304,0.276-3.704,0.276
3029+ c-1.222,0-2.247-0.179-3.082-0.535c-0.833-0.355-1.503-0.858-2.01-1.509c-0.509-0.65-0.875-1.419-1.098-2.302
3030+ C0.11,19.739,0,18.76,0,17.68V8.778h2.835v8.293c0,1.932,0.304,3.315,0.916,4.147c0.61,0.834,1.636,1.249,3.079,1.249
3031+ c0.304,0,0.62-0.01,0.945-0.031c0.326-0.02,0.632-0.045,0.914-0.075C8.974,22.33,9.234,22.3,9.468,22.27
3032+ c0.234-0.032,0.401-0.065,0.504-0.108V8.778h2.835V24.177L12.807,24.177z"/>
3033+ <path fill="#DD4814" d="M19.728,9.478c0.347-0.222,0.871-0.458,1.572-0.7c0.7-0.243,1.507-0.367,2.424-0.367
3034+ c1.137,0,2.148,0.205,3.033,0.609c0.886,0.406,1.632,0.977,2.243,1.709c0.607,0.731,1.069,1.605,1.385,2.622
3035+ c0.317,1.016,0.474,2.135,0.474,3.355c0,1.279-0.187,2.433-0.565,3.461c-0.377,1.025-0.909,1.894-1.6,2.605
3036+ c-0.692,0.714-1.524,1.26-2.502,1.647C25.219,24.807,24.121,25,22.899,25c-1.321,0-2.49-0.093-3.506-0.276
3037+ c-1.016-0.183-1.849-0.367-2.501-0.549V1.46l2.837-0.488L19.728,9.478L19.728,9.478z M19.728,22.162
3038+ c0.285,0.084,0.686,0.159,1.206,0.23c0.517,0.073,1.161,0.107,1.935,0.107c1.523,0,2.746-0.504,3.659-1.509
3039+ c0.915-1.007,1.373-2.435,1.373-4.284c0-0.813-0.081-1.575-0.245-2.288c-0.163-0.712-0.428-1.326-0.793-1.845
3040+ c-0.366-0.519-0.839-0.923-1.416-1.219c-0.582-0.297-1.278-0.444-2.09-0.444c-0.774,0-1.484,0.133-2.135,0.395
3041+ c-0.651,0.267-1.149,0.541-1.495,0.825v10.032H19.728z"/>
3042+ <path fill="#DD4814" d="M46.684,24.177c-0.651,0.162-1.509,0.337-2.576,0.518c-1.067,0.184-2.303,0.276-3.707,0.276
3043+ c-1.219,0-2.246-0.179-3.079-0.535c-0.833-0.355-1.504-0.858-2.011-1.509c-0.511-0.65-0.875-1.419-1.098-2.302
3044+ c-0.224-0.886-0.335-1.865-0.335-2.944V8.778h2.835v8.293c0,1.932,0.304,3.315,0.914,4.147c0.611,0.834,1.636,1.249,3.08,1.249
3045+ c0.305,0,0.622-0.01,0.947-0.031c0.325-0.02,0.629-0.045,0.915-0.075c0.284-0.032,0.544-0.062,0.779-0.092
3046+ c0.232-0.032,0.4-0.065,0.503-0.108V8.778h2.835v15.399H46.684z"/>
3047+ <path fill="#DD4814" d="M50.769,9.236c0.651-0.164,1.514-0.335,2.593-0.521c1.077-0.18,2.316-0.272,3.719-0.272
3048+ c1.263,0,2.308,0.178,3.142,0.533c0.834,0.356,1.499,0.853,1.997,1.494c0.498,0.64,0.849,1.408,1.053,2.3
3049+ c0.202,0.898,0.304,1.882,0.304,2.959v8.905h-2.836V16.34c0-0.977-0.067-1.809-0.198-2.501c-0.132-0.693-0.351-1.249-0.656-1.676
3050+ c-0.303-0.429-0.712-0.738-1.221-0.93c-0.506-0.197-1.139-0.292-1.888-0.292c-0.306,0-0.622,0.012-0.944,0.032
3051+ c-0.326,0.021-0.637,0.046-0.931,0.076c-0.298,0.03-0.56,0.067-0.794,0.107c-0.235,0.041-0.402,0.072-0.503,0.091v13.386h-2.837
3052+ L50.769,9.236L50.769,9.236z"/>
3053+ <path fill="#DD4814" d="M70.132,8.778h6.008v2.378h-6.008v7.319c0,0.792,0.062,1.45,0.185,1.966
3054+ c0.121,0.52,0.304,0.927,0.548,1.221c0.244,0.292,0.549,0.501,0.914,0.625c0.367,0.122,0.794,0.182,1.28,0.182
3055+ c0.874,0,1.565-0.096,2.076-0.29c0.507-0.193,0.853-0.329,1.035-0.412l0.609,2.32c-0.283,0.142-0.787,0.324-1.508,0.547
3056+ c-0.722,0.225-1.539,0.338-2.454,0.338c-1.078,0-1.968-0.137-2.669-0.413c-0.701-0.275-1.265-0.685-1.692-1.234
3057+ c-0.427-0.548-0.727-1.224-0.898-2.027c-0.175-0.805-0.26-1.734-0.26-2.79V4.356l2.833-0.489v4.911H70.132z"/>
3058+ <path fill="#DD4814" d="M91.57,24.177c-0.653,0.162-1.51,0.337-2.579,0.518c-1.067,0.184-2.3,0.276-3.701,0.276
3059+ c-1.222,0-2.247-0.179-3.081-0.535c-0.836-0.355-1.506-0.858-2.013-1.509c-0.509-0.65-0.873-1.419-1.1-2.302
3060+ c-0.221-0.886-0.335-1.865-0.335-2.944V8.778h2.838v8.293c0,1.932,0.305,3.315,0.914,4.147c0.609,0.834,1.637,1.249,3.081,1.249
3061+ c0.304,0,0.618-0.01,0.945-0.031c0.323-0.02,0.629-0.045,0.914-0.075c0.284-0.032,0.546-0.062,0.777-0.092
3062+ c0.234-0.032,0.403-0.065,0.505-0.108V8.778h2.837v15.399H91.57z"/>
3063+</g>
3064+<g id="Grid" display="none">
3065+</g>
3066+</svg>
3067
3068=== modified file 'tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml'
3069--- tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml 2014-02-06 19:12:15 +0000
3070+++ tests/qmltests/Dash/Apps/tst_RunningApplicationsGrid.qml 2014-07-08 15:02:30 +0000
3071@@ -30,7 +30,7 @@
3072 ApplicationManager.stopApplication(ApplicationManager.get(0).appId)
3073 }
3074
3075- ApplicationManager.startApplication("phone-app");
3076+ ApplicationManager.startApplication("dialer-app");
3077 ApplicationManager.startApplication("webbrowser-app");
3078 }
3079
3080@@ -70,7 +70,7 @@
3081 verify(browserTile != undefined)
3082 browserTile.onPressAndHold.connect(onBrowserLongPressed)
3083
3084- phoneTile = findChild(runningApplicationsGrid, "runningAppTile Phone")
3085+ phoneTile = findChild(runningApplicationsGrid, "runningAppTile Dialer")
3086 verify(phoneTile != undefined)
3087 phoneTile.onPressAndHold.connect(onPhoneLongPressed)
3088
3089
3090=== modified file 'tests/qmltests/Dash/tst_Dash.qml'
3091--- tests/qmltests/Dash/tst_Dash.qml 2014-05-13 07:44:27 +0000
3092+++ tests/qmltests/Dash/tst_Dash.qml 2014-07-08 15:02:30 +0000
3093@@ -70,24 +70,6 @@
3094 ]
3095 }
3096
3097- function test_set_current_scope_data() {
3098- return get_scope_data()
3099- }
3100-
3101- function test_set_current_scope(data) {
3102- // wait for scopes to load
3103- tryCompare(scopes, "loaded", true);
3104-
3105- var tabbar = findChild(dash, "tabbar");
3106- verify(tabbar != undefined)
3107- var dashContent = findChild(dash, "dashContent");
3108- var current_index = dashContent.currentIndex;
3109-
3110- dash.setCurrentScope(data.tag, true /* animate */, false /* reset */);
3111- compare(dashContent.currentIndex, data.shouldBeVisible ? data.visualIndex : current_index);
3112- compare(tabbar.selectedIndex, data.shouldBeVisible ? data.visualIndex : current_index);
3113- }
3114-
3115 function test_show_scope_on_load_data() {
3116 return get_scope_data()
3117 }
3118@@ -109,26 +91,5 @@
3119 verify(dashContentList != undefined);
3120 tryCompare(dashContentList, "currentIndex", data.visualIndex);
3121 }
3122-
3123- function test_dash_bar_set_index_connection_data() {
3124- return get_scope_data()
3125- }
3126-
3127- function test_dash_bar_set_index_connection(data) {
3128- if (data.shouldBeVisible == false) {
3129- console.log("Not testing " + data.tag + ": not visible");
3130- return;
3131- }
3132- // wait for scopes to load
3133- tryCompare(scopes, "loaded", true);
3134-
3135- var tabbar = findChild(dash, "tabbar");
3136- verify(tabbar != undefined)
3137- var dashContent = findChild(dash, "dashContent");
3138- var current_index = dashContent.currentIndex;
3139-
3140- tabbar.model.selectedIndex = data.visualIndex;
3141- compare(dashContent.currentIndex, data.shouldBeVisible ? data.visualIndex : current_index);
3142- }
3143 }
3144 }
3145
3146=== modified file 'tests/qmltests/Dash/tst_DashContent.qml'
3147--- tests/qmltests/Dash/tst_DashContent.qml 2014-06-18 13:48:32 +0000
3148+++ tests/qmltests/Dash/tst_DashContent.qml 2014-07-08 15:02:30 +0000
3149@@ -47,8 +47,6 @@
3150 model: scopesModel
3151 }
3152 scopes : scopesModel
3153-
3154- searchHistory: SearchHistoryModel {}
3155 }
3156
3157 SignalSpy {
3158@@ -195,7 +193,7 @@
3159 dashContent.setCurrentScopeAtIndex(data.index, true, false);
3160 tryCompareFunction(get_current_item_object_name, data.objectName)
3161 var pageHeader = findChild(dashContent, "pageHeader");
3162- compare(pageHeader.scope, scopesModel.getScope(data.index));
3163+ compare(pageHeader.title, scopesModel.getScope(data.index).name);
3164 }
3165
3166 function test_is_active_data() {
3167@@ -217,67 +215,6 @@
3168 tryCompare(scopesModel.getScope(2), "isActive", data.active2);
3169 }
3170
3171- function doFindMusicButton(parent) {
3172- for (var i = 0; i < parent.children.length; i++) {
3173- var c = parent.children[i];
3174- if (UT.Util.isInstanceOf(c, "AbstractButton") && parent.x >= 0) {
3175- for (var ii = 0; ii < c.children.length; ii++) {
3176- var cc = c.children[ii];
3177- if (UT.Util.isInstanceOf(cc, "Label") && cc.text == "Music") {
3178- return c;
3179- }
3180- }
3181- }
3182- var r = doFindMusicButton(c);
3183- if (r !== undefined) {
3184- return r;
3185- }
3186- }
3187- return undefined;
3188- }
3189-
3190- function findMusicButton() {
3191- // We need to find a AbstractButton that has a Label child
3192- // with text Music and it's parent x is >= 0
3193- var tabbar = findChild(dashContent, "tabbar");
3194- return doFindMusicButton(tabbar);
3195- }
3196-
3197- function test_tabBar_index_change() {
3198- tryCompare(scopesModel, "loaded", true);
3199- var tabbar = findChild(dashContent, "tabbar");
3200-
3201- tryCompare(dashContent, "currentIndex", 0);
3202- tryCompare(tabbar, "selectedIndex", 0);
3203- tryCompare(tabbar, "selectionMode", false);
3204-
3205- mouseClick(tabbar, units.gu(5), units.gu(5))
3206-
3207- tryCompare(tabbar, "selectionMode", true);
3208- tryCompare(tabbar, "selectedIndex", 0);
3209- tryCompare(dashContent, "currentIndex", 0);
3210-
3211- var button;
3212- tryCompareFunction(function() { button = findMusicButton(); return button != undefined; }, true);
3213- waitForRendering(button);
3214-
3215- tryCompareFunction(function() { return button.opacity > 0; }, true);
3216- mouseClick(button, button.width / 2, button.height / 2)
3217-
3218- tryCompare(tabbar, "selectionMode", false);
3219- tryCompare(tabbar, "selectedIndex", 1);
3220- tryCompare(dashContent, "currentIndex", 1);
3221- }
3222-
3223- function test_tabBar_listens_to_index_change() {
3224- var tabbar = findChild(dashContent, "tabbar");
3225- tryCompare(dashContent, "currentIndex", 0);
3226- compare(tabbar.selectedIndex, 0);
3227- var dashContentList = findChild(dashContent, "dashContentList");
3228- dashContentList.currentIndex = 1;
3229- compare(tabbar.selectedIndex, 1);
3230- }
3231-
3232 function checkFlickMovingAndNotInteractive()
3233 {
3234 var dashContentList = findChild(dashContent, "dashContentList");
3235@@ -318,8 +255,8 @@
3236 }
3237
3238 function closePreview() {
3239- var closePreviewMouseArea = findChild(dashContent, "dashContentPreviewList_pageHeader_backButton");
3240- mouseClick(closePreviewMouseArea, closePreviewMouseArea.width / 2, closePreviewMouseArea.height / 2);
3241+ var closePreviewMouseArea = findChild(dashContent, "pageHeader");
3242+ mouseClick(closePreviewMouseArea, units.gu(2), units.gu(2));
3243
3244 var previewListView = findChild(dashContent, "dashContentPreviewList");
3245 tryCompare(previewListView, "open", false);
3246@@ -461,6 +398,7 @@
3247 compare(allButton.visible, true);
3248 compare(backButton.visible, true);
3249
3250+ waitForRendering(departmentListView);
3251 mouseClick(allButton, 0, 0);
3252 compare(dashDepartments.showList, false);
3253 tryCompare(dashDepartments.currentDepartment, "departmentId", "middle2");
3254
3255=== modified file 'tests/qmltests/Dash/tst_GenericScopeView.qml'
3256--- tests/qmltests/Dash/tst_GenericScopeView.qml 2014-05-28 07:17:08 +0000
3257+++ tests/qmltests/Dash/tst_GenericScopeView.qml 2014-07-08 15:02:30 +0000
3258@@ -48,19 +48,11 @@
3259 signal mainStageFocusedApplicationChanged()
3260 }
3261
3262- PageHeaderLabel {
3263- id: testPageHeader
3264- searchHistory: SearchHistoryModel {}
3265- text: genericScopeView.scope ? genericScopeView.scope.name : ""
3266- width: parent.width
3267- }
3268
3269 GenericScopeView {
3270 id: genericScopeView
3271 anchors.fill: parent
3272 previewListView: previewListView
3273- pageHeader: testPageHeader
3274- tabBarHeight: testPageHeader.implicitHeight
3275
3276 UT.UnityTestCase {
3277 name: "GenericScopeView"
3278@@ -73,15 +65,6 @@
3279 tryCompare(genericScopeView.categoryView, "contentY", 0)
3280 }
3281
3282- function test_isCurrent() {
3283- genericScopeView.isCurrent = true
3284- testPageHeader.searchQuery = "test"
3285- previewListView.open = true
3286- genericScopeView.isCurrent = false
3287- tryCompare(testPageHeader, "searchQuery", "")
3288- tryCompare(previewListView, "open", false);
3289- }
3290-
3291 function test_isActive() {
3292 tryCompare(genericScopeView.scope, "isActive", false)
3293 genericScopeView.isCurrent = true
3294@@ -170,14 +153,6 @@
3295
3296 categoryListView.positionAtBeginning();
3297
3298- // wait for the header0 to be on its position
3299- tryCompareFunction(
3300- function() {
3301- var header0 = findChild(genericScopeView, "dashSectionHeader0")
3302- return header0.y == testPageHeader.height;
3303- },
3304- true);
3305-
3306 var header0 = findChild(genericScopeView, "dashSectionHeader0")
3307 var category0 = findChild(genericScopeView, "dashCategory0")
3308 mouseClick(header0, header0.width / 2, header0.height / 2);
3309@@ -211,7 +186,6 @@
3310 id: previewListView
3311 anchors.fill: parent
3312 visible: false
3313- pageHeader: testPageHeader
3314 scope: genericScopeView.scope
3315 }
3316 }
3317
3318=== modified file 'tests/qmltests/Launcher/tst_Launcher.qml'
3319--- tests/qmltests/Launcher/tst_Launcher.qml 2014-04-14 17:26:06 +0000
3320+++ tests/qmltests/Launcher/tst_Launcher.qml 2014-07-08 15:02:30 +0000
3321@@ -115,7 +115,7 @@
3322 /* If I click on the icon of an application on the launcher
3323 Launcher::launcherApplicationSelected signal should be emitted with the
3324 corresponding desktop file. E.g. clicking on phone icon should yield
3325- launcherApplicationSelected("[...]phone-app.desktop") */
3326+ launcherApplicationSelected("[...]dialer-app.desktop") */
3327 function test_clickingOnAppIconCausesSignalEmission() {
3328 launcher.lastSelectedApplication = ""
3329
3330@@ -131,7 +131,7 @@
3331 mouseClick(appIcon, appIcon.width/2, appIcon.height/2)
3332
3333 tryCompare(launcher, "lastSelectedApplication",
3334- "phone-app")
3335+ "dialer-app")
3336
3337 // Tapping on an application icon also dismisses the launcher
3338 revealer.waitUntilLauncherDisappears()
3339
3340=== modified file 'tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml'
3341--- tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml 2014-03-31 10:47:51 +0000
3342+++ tests/qmltests/Notifications/tst_VisualSnapDecisionsQueue.qml 2014-07-08 15:02:30 +0000
3343@@ -67,7 +67,7 @@
3344 summary: "Incoming call",
3345 body: "Frank Zappa\n+44 (0)7736 027340",
3346 icon: "../graphics/avatars/funky.png",
3347- secondaryIcon: "../graphics/applicationIcons/phone-app.png",
3348+ secondaryIcon: "../graphics/applicationIcons/dialer-app.png",
3349 actions: [{ id: "pickup_id", label: "Pick up"},
3350 { id: "decline_1_id", label: "Decline"},
3351 { id: "decline_2_id", label: "Can't talk now, what's up?"},
3352
3353=== added file 'tests/qmltests/Panel/tst_ActiveCallHint.qml'
3354--- tests/qmltests/Panel/tst_ActiveCallHint.qml 1970-01-01 00:00:00 +0000
3355+++ tests/qmltests/Panel/tst_ActiveCallHint.qml 2014-07-08 15:02:30 +0000
3356@@ -0,0 +1,165 @@
3357+/*
3358+ * Copyright 2014 Canonical Ltd.
3359+ *
3360+ * This program is free software; you can redistribute it and/or modify
3361+ * it under the terms of the GNU General Public License as published by
3362+ * the Free Software Foundation; version 3.
3363+ *
3364+ * This program is distributed in the hope that it will be useful,
3365+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3366+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3367+ * GNU General Public License for more details.
3368+ *
3369+ * You should have received a copy of the GNU General Public License
3370+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3371+ */
3372+
3373+import QtQuick 2.0
3374+import QtTest 1.0
3375+import Unity.Test 0.1 as UT
3376+import Ubuntu.Telephony 0.1 as Telephony
3377+import Unity.Application 0.1
3378+import ".."
3379+import "../../../qml/Panel"
3380+
3381+Item {
3382+ width: units.gu(40)
3383+ height: units.gu(20)
3384+
3385+ Telephony.CallEntry {
3386+ id: call1
3387+ phoneNumber: "+447812221111"
3388+ }
3389+
3390+ Telephony.CallEntry {
3391+ id: call2
3392+ phoneNumber: "+447812221112"
3393+ }
3394+
3395+ Telephony.CallEntry {
3396+ id: call3
3397+ phoneNumber: "+447812221113"
3398+ }
3399+
3400+ ActiveCallHint {
3401+ id: callHint
3402+ anchors {
3403+ top: parent.top
3404+ left:parent.left
3405+ right:parent.right
3406+ }
3407+ height: units.gu(3)
3408+ labelSwitchInterval: 2000
3409+ }
3410+
3411+ Component.onCompleted: {
3412+ contactWactherData.contactData = {
3413+ "+447812221113": {
3414+ "alias": "Bob's Uncle"
3415+ }
3416+ };
3417+ callManager.foregroundCall = call3;
3418+ }
3419+
3420+ UT.UnityTestCase {
3421+ name: "ActiveCallHint"
3422+ when: windowShown
3423+
3424+ function init() {
3425+ callManager.foregroundCall = null;
3426+ callManager.backgroundCall = null;
3427+ callHint.labelSwitchInterval = 300;
3428+
3429+ ApplicationManager.stopApplication("dialer-app");
3430+ }
3431+
3432+ function test_activeHint_data() {
3433+ return [
3434+ { tag: "noCall-callNotVisible", dialer: false, call: null, visible: false, expected: false },
3435+ { tag: "noCall-callVisible", dialer: false, call: null, visible: true, expected: false },
3436+ { tag: "hasCall-callNotVisible", dialer: false, call: call1, visible: false, expected: true },
3437+ { tag: "hasCall-callVisible", dialer: false, call: call1, visible: true, expected: true },
3438+
3439+ { tag: "dialerNotFocused-noCall-callNotVisible", dialer: true, focused: false, call: null, visible: false, expected: false },
3440+ { tag: "dialerNotFocused-noCall-callVisible", dialer: true, focused: false, call: null, visible: true, expected: false },
3441+ { tag: "dialerNotFocused-hasCall-callNotVisible", dialer: true, focused: false, call: call1, visible: false, expected: true },
3442+ { tag: "dialerNotFocused-hasCall-callVisible", dialer: true, focused: false, call: call1, visible: true, expected: true },
3443+
3444+ { tag: "dialerFocused-noCall-callNotVisible", dialer: true, focused: true, call: null, visible: false, expected: false },
3445+ { tag: "dialerFocused-noCall-callVisible", dialer: true, focused: true, call: null, visible: true, expected: true },
3446+ { tag: "dialerFocused-hasCall-callNotVisible", dialer: true, focused: true, call: call1, visible: false, expected: false },
3447+ { tag: "dialerFocused-hasCall-callVisible", dialer: true, focused: true, call: call1, visible: true, expected: true },
3448+ ];
3449+ }
3450+
3451+ function test_activeHint(data) {
3452+ if (data.dialer) {
3453+ var application = ApplicationManager.startApplication("dialer-app");
3454+ tryCompare(ApplicationManager, "focusedApplicationId", "dialer-app");
3455+ tryCompare(application, "state", ApplicationInfo.Running);
3456+
3457+ if (!data.focused) { ApplicationManager.unfocusCurrentApplication(); }
3458+ }
3459+ callManager.foregroundCall = data.call;
3460+ callManager.callIndicatorVisible = data.visible;
3461+
3462+ compare(callHint.active, data.expected, "Call hint should be active when callIndicatorVisible=true");
3463+ }
3464+
3465+ function test_currentCall_data() {
3466+ return [
3467+ { tag: "empty", foreground: null, background: null, active: false, label: "" },
3468+ { tag: "foreground", foreground: call1, background: null, active: true, label: "+447812221111" },
3469+ { tag: "background", foreground: null, background: call2, active: true, label: "+447812221112" },
3470+ { tag: "multiple", foreground: call1, background: call2, active: true, label: "+447812221111" },
3471+ ];
3472+ }
3473+
3474+ function test_currentCall(data) {
3475+ callManager.foregroundCall = data.foreground;
3476+ callManager.backgroundCall = data.background;
3477+
3478+ var contactLabel = findChild(callHint, "contactLabel");
3479+ verify(contactLabel !== null);
3480+
3481+ compare(contactLabel.text, data.label, "Contact label does not match call");
3482+ }
3483+
3484+ function test_changeContactData() {
3485+ callManager.backgroundCall = call3;
3486+
3487+ var contactLabel = findChild(callHint, "contactLabel");
3488+ verify(contactLabel !== null);
3489+
3490+ contactWactherData.contactData = { "+447812221113": { "alias": "Bob's Uncle" } };
3491+ compare(contactLabel.text, "Bob's Uncle", "Contact label does not match call");
3492+
3493+ contactWactherData.contactData = { "+447812221113": { "alias": "Freddy" } };
3494+ compare(contactLabel.text, "Freddy", "Contact label does not match call");
3495+ }
3496+
3497+ function test_timeLapse() {
3498+ callManager.backgroundCall = call3;
3499+
3500+ var timeLabel = findChild(callHint, "timeLabel");
3501+ verify(timeLabel !== null);
3502+
3503+ var currentLabel = timeLabel.text;
3504+ tryCompareFunction(function() { return timeLabel.text !== currentLabel }, true);
3505+ currentLabel = timeLabel.text;
3506+ tryCompareFunction(function() { return timeLabel.text !== currentLabel }, true);
3507+ }
3508+
3509+ function test_displayedLabelChangesOverTime() {
3510+ callManager.backgroundCall = call3;
3511+
3512+ var labelPathView = findChild(callHint, "labelPathView");
3513+ verify(labelPathView !== null);
3514+
3515+ var currentOffset = labelPathView.offset
3516+ tryCompareFunction(function() { return labelPathView.offset !== currentOffset }, true);
3517+ currentOffset = labelPathView.offset
3518+ tryCompareFunction(function() { return labelPathView.offset !== currentOffset }, true);
3519+ }
3520+ }
3521+}
3522
3523=== modified file 'tests/qmltests/Panel/tst_Indicators.qml'
3524--- tests/qmltests/Panel/tst_Indicators.qml 2014-01-30 14:58:20 +0000
3525+++ tests/qmltests/Panel/tst_Indicators.qml 2014-07-08 15:02:30 +0000
3526@@ -17,6 +17,7 @@
3527 import QtQuick 2.0
3528 import QtTest 1.0
3529 import Unity.Test 0.1 as UT
3530+import Ubuntu.Components 0.1 as UC
3531 import ".."
3532 import "../../../qml/Panel"
3533 import "../../../qml/Components"
3534@@ -45,13 +46,12 @@
3535 shown: false
3536 profile: "test1"
3537
3538- openedHeight: parent.height - click_me.height
3539+ openedHeight: parent.height - button.height
3540 }
3541
3542- // Just a rect for clicking to open the indicators.
3543- Rectangle {
3544- id: click_me
3545- color: "red"
3546+ UC.Button {
3547+ id: button
3548+ text: indicators.shown ? "Hide" : "Show"
3549 anchors {
3550 bottom: shell.bottom
3551 left: parent.left
3552@@ -59,22 +59,11 @@
3553 }
3554 height: 50
3555
3556- Text {
3557- text: "Click Me"
3558- horizontalAlignment: Text.AlignHCenter
3559- verticalAlignment: Text.AlignVCenter
3560- anchors.fill: parent
3561-
3562- MouseArea {
3563- anchors.fill: parent
3564-
3565- onClicked: {
3566- if (!indicators.shown) {
3567- indicators.show();
3568- } else {
3569- indicators.hide();
3570- }
3571- }
3572+ onClicked: {
3573+ if (!indicators.shown) {
3574+ indicators.show();
3575+ } else {
3576+ indicators.hide();
3577 }
3578 }
3579 }
3580
3581=== modified file 'tests/qmltests/Panel/tst_Panel.qml'
3582--- tests/qmltests/Panel/tst_Panel.qml 2014-01-30 14:58:20 +0000
3583+++ tests/qmltests/Panel/tst_Panel.qml 2014-07-08 15:02:30 +0000
3584@@ -17,6 +17,8 @@
3585 import QtQuick 2.0
3586 import QtTest 1.0
3587 import Unity.Test 0.1 as UT
3588+import Ubuntu.Components 0.1 as UC
3589+import Ubuntu.Telephony 0.1 as Telephony
3590 import ".."
3591 import "../../../qml/Panel"
3592
3593@@ -30,42 +32,104 @@
3594 width: units.gu(40)
3595 height: units.gu(80)
3596
3597- property bool searchClicked: false
3598-
3599- Connections {
3600- target: panel
3601- onSearchClicked: searchClicked = true
3602- }
3603-
3604 Panel {
3605 id: panel
3606- anchors.fill: parent
3607+ anchors {
3608+ left: parent.left
3609+ right: parent.right
3610+ }
3611+ height: parent.height - row.height
3612+ fullscreenMode: false
3613
3614 indicators {
3615 profile: "test1"
3616- }
3617+ panelHeight: units.gu(5)
3618+ }
3619+ callHint {
3620+ height: units.gu(4)
3621+ }
3622+
3623+ property real panelAndSeparatorHeight: panel.indicators.panelHeight + units.dp(2)
3624+ }
3625+
3626+
3627+ Row {
3628+ id: row
3629+ anchors {
3630+ bottom: shell.bottom
3631+ left: parent.left
3632+ right: parent.right
3633+ }
3634+ height: 50
3635+
3636+ UC.Button {
3637+ text: panel.indicators.shown ? "Hide" : "Show"
3638+ anchors {
3639+ top: parent.top
3640+ bottom: parent.bottom
3641+ }
3642+ width: parent.width/3
3643+
3644+ onClicked: {
3645+ if (panel.indicators.shown) {
3646+ panel.indicators.hide();
3647+ } else {
3648+ panel.indicators.show();
3649+ }
3650+ }
3651+ }
3652+
3653+ UC.Button {
3654+ text: panel.fullscreenMode ? "Maximize" : "FullScreen"
3655+ anchors {
3656+ top: parent.top
3657+ bottom: parent.bottom
3658+ }
3659+ width: parent.width/3
3660+
3661+ onClicked: panel.fullscreenMode = !panel.fullscreenMode
3662+ }
3663+
3664+ UC.Button {
3665+ text: callManager.hasCalls ? "Called" : "No Calls"
3666+ anchors {
3667+ top: parent.top
3668+ bottom: parent.bottom
3669+ }
3670+ width: parent.width/3
3671+
3672+ onClicked: {
3673+ if (callManager.foregroundCall) {
3674+ callManager.foregroundCall = null;
3675+ } else {
3676+ callManager.foregroundCall = phoneCall;
3677+ }
3678+ }
3679+ }
3680+ }
3681+
3682+ Telephony.CallEntry {
3683+ id: phoneCall
3684+ phoneNumber: "+447812221111"
3685 }
3686
3687 UT.UnityTestCase {
3688 name: "Panel"
3689 when: windowShown
3690
3691- function get_window_data() {
3692- return [
3693- {tag: "pinned", fullscreenFlag: false, alreadyOpen: false },
3694- {tag: "fullscreen", fullscreenFlag: true, alreadyOpen: false },
3695- {tag: "pinned-alreadyOpen", fullscreenFlag: false, alreadyOpen: true },
3696- {tag: "fullscreen-alreadyOpen", fullscreenFlag: true, alreadyOpen: true }
3697- ];
3698- }
3699-
3700 function init() {
3701 panel.indicators.initialise();
3702+ panel.fullscreenMode = false;
3703
3704- searchClicked = false;
3705 panel.indicators.hide();
3706+ // Wait for animation to complete
3707 tryCompare(panel.indicators.hideAnimation, "running", false);
3708- tryCompare(panel.indicators, "state", "initial");
3709+ callManager.foregroundCall = null;
3710+
3711+ // Wait for the indicators to get into position.
3712+ // (switches between normal and fullscreen modes are animated)
3713+ var indicatorArea = findChild(panel, "indicatorArea");
3714+ tryCompare(indicatorArea, "y", 0);
3715 }
3716
3717 function get_indicator_item(index) {
3718@@ -88,83 +152,109 @@
3719 // Pressing on the indicator panel should activate the indicator hints
3720 // and expose a portion of the conent.
3721 function test_hint() {
3722- panel.fullscreenMode = false;
3723- // Wait for the indicators to get into position.
3724- // (switches between normal and fullscreen modes are animated)
3725- tryCompare(panel.indicators, "y", 0);
3726-
3727 var indicatorItemCoord = get_indicator_item_position(0);
3728
3729- touchPress(panel, indicatorItemCoord.x, panel.panelHeight / 2);
3730+ touchPress(panel, indicatorItemCoord.x, panel.indicators.panelHeight / 2);
3731
3732 // hint animation should be run, meaning that indicators will move downwards
3733 // by hintValue pixels without any drag taking place
3734- tryCompare(panel.indicators, "height",
3735- panel.indicators.panelHeight + panel.indicators.hintValue);
3736+ tryCompareFunction(function() { return panel.indicators.height },
3737+ panel.indicators.panelHeight + panel.indicators.hintValue);
3738 tryCompare(panel.indicators, "partiallyOpened", true);
3739 tryCompare(panel.indicators, "fullyOpened", false);
3740
3741- touchRelease(panel, indicatorItemCoord.x, panel.panelHeight/2);
3742+ touchRelease(panel, indicatorItemCoord.x, panel.indicators.panelHeight/2);
3743 }
3744
3745 // Pressing on the top edge of the screen should have no effect if the panel
3746- // is hidden (!pinned), which is the case when a fullscreen app is being shown
3747+ // is hidden (fullscreen), which is the case when a fullscreen app is being shown
3748 function test_noHintOnFullscreenMode() {
3749 panel.fullscreenMode = true;
3750 // Wait for the indicators to get into position.
3751 // (switches between normal and fullscreen modes are animated)
3752- tryCompare(panel.indicators, "y", -panel.panelHeight);
3753-
3754- var indicatorItemCoord = get_indicator_item_position(0);
3755-
3756- touchPress(panel, indicatorItemCoord.x, panel.panelHeight / 2);
3757-
3758- // Give some time for a hint animation to change things, if any
3759- wait(500);
3760-
3761- // no hint animation when fullscreen
3762- compare(panel.indicators.y, -panel.panelHeight);
3763- var indicatorRow = findChild(panel.indicators, "indicatorRow");
3764- verify(indicatorRow !== null);
3765- compare(indicatorRow.y, 0);
3766- compare(panel.indicators.height, panel.indicators.panelHeight);
3767- compare(panel.indicators.partiallyOpened, false,
3768- "Indicator should not be partially opened when panel is pressed in" +
3769- " fullscreenmode");
3770- compare(panel.indicators.fullyOpened, false, "Indicator should not be partially" +
3771- " opened when panel is pressed in fullscreenmode");
3772-
3773- touchRelease(panel, indicatorItemCoord.x, panel.panelHeight/2);
3774- }
3775-
3776- function test_drag_show_data() { return get_window_data(); }
3777+ var indicatorArea = findChild(panel, "indicatorArea");
3778+ tryCompare(indicatorArea, "y", -panel.panelHeight);
3779+
3780+ var indicatorItemCoord = get_indicator_item_position(0);
3781+
3782+ touchPress(panel, indicatorItemCoord.x, panel.indicators.panelHeight / 2);
3783+
3784+ // Give some time for a hint animation to change things, if any
3785+ wait(500);
3786+
3787+ // no hint animation when fullscreen
3788+ compare(panel.indicators.partiallyOpened, false,
3789+ "Indicator should not be partially opened when panel is pressed in" +
3790+ " fullscreenmode");
3791+ compare(panel.indicators.fullyOpened, false, "Indicator should not be partially" +
3792+ " opened when panel is pressed in fullscreenmode");
3793+
3794+ touchRelease(panel, indicatorItemCoord.x, panel.panelHeight/2);
3795+ }
3796+
3797+ // Pressing on the top edge of the indicator should have no effect if the panel
3798+ // has an active call
3799+ function test_noHintOnActiveCall() {
3800+ callManager.foregroundCall = phoneCall;
3801+
3802+ var indicatorItemCoord = get_indicator_item_position(0);
3803+
3804+ touchPress(panel, indicatorItemCoord.x, panel.callHint.height + panel.indicators.panelHeight / 2);
3805+
3806+ // Give some time for a hint animation to change things, if any
3807+ wait(500);
3808+
3809+ // no hint animation when fullscreen
3810+ compare(panel.indicators.partiallyOpened, false,
3811+ "Indicator should not be partially opened when panel is pressed in" +
3812+ " fullscreenmode");
3813+ compare(panel.indicators.fullyOpened, false, "Indicator should not be partially" +
3814+ " opened when panel is pressed in fullscreenmode");
3815+
3816+ touchRelease(panel, indicatorItemCoord.x, panel.panelHeight/2);
3817+ }
3818+
3819+ function test_drag_show_data() {
3820+ return [
3821+ { tag: "pinned", fullscreenFlag: false, alreadyOpen: false, call: null,
3822+ indicatorY: 0 },
3823+ { tag: "fullscreen", fullscreenFlag: true, alreadyOpen: false, call: null,
3824+ indicatorY: -panel.panelAndSeparatorHeight },
3825+ { tag: "pinned-alreadyOpen", fullscreenFlag: false, alreadyOpen: true, call: null,
3826+ indicatorY: 0 },
3827+ { tag: "fullscreen-alreadyOpen", fullscreenFlag: true, alreadyOpen: true, call: null,
3828+ indicatorY: 0 },
3829+ { tag: "pinned-callActive", fullscreenFlag: false, alreadyOpen: false, call: phoneCall,
3830+ indicatorY: 0},
3831+ { tag: "fullscreen-callActive", fullscreenFlag: true, alreadyOpen: false, call: phoneCall,
3832+ indicatorY: -panel.panelAndSeparatorHeight }
3833+ ];
3834+ }
3835
3836 // Dragging from a indicator item in the panel will gradually expose the
3837 // indicators, first by running the hint animation, then after dragging down will
3838 // expose more of the panel, binding it to the selected indicator and opening it's menu.
3839 function test_drag_show(data) {
3840 panel.fullscreenMode = data.fullscreenFlag;
3841+ callManager.foregroundCall = data.call;
3842+
3843 if (data.alreadyOpen) {
3844 panel.indicators.show();
3845 tryCompare(panel.indicators, "fullyOpened", true);
3846 }
3847
3848- var indicatorRow = findChild(panel.indicators, "indicatorRow");
3849- verify(indicatorRow !== null);
3850-
3851- var menuContent = findChild(panel.indicators, "menuContent");
3852- verify(indicatorRow !== null);
3853-
3854- var menuContent = findChild(panel.indicators, "menuContent");
3855- verify(indicatorRow !== null);
3856+ var indicatorRow = findChild(panel.indicators, "indicatorRow");
3857+ verify(indicatorRow !== null);
3858+
3859+ var menuContent = findChild(panel.indicators, "menuContent");
3860+ verify(menuContent !== null);
3861+
3862+ var indicatorArea = findChild(panel, "indicatorArea");
3863+ verify(indicatorArea !== null);
3864
3865 // Wait for the indicators to get into position.
3866 // (switches between normal and fullscreen modes are animated)
3867- if (data.fullscreenFlag) {
3868- tryCompare(panel.indicators, "y", -panel.panelHeight);
3869- } else {
3870- tryCompare(panel.indicators, "y", 0);
3871- }
3872+ tryCompareFunction(function() { return indicatorArea.y }, data.indicatorY);
3873
3874 // do this for each indicator item
3875 for (var i = 0; i < indicatorRow.row.count; i++) {
3876@@ -178,12 +268,12 @@
3877 var indicatorItemCoord = get_indicator_item_position(i);
3878
3879 touchPress(panel,
3880- indicatorItemCoord.x, panel.panelHeight / 2);
3881+ indicatorItemCoord.x, panel.indicators.panelHeight / 2);
3882
3883 // 1) Drag the mouse down
3884 touchFlick(panel,
3885- indicatorItemCoord.x, panel.panelHeight / 2,
3886- indicatorItemCoord.x, panel.height * 0.8,
3887+ indicatorItemCoord.x, panel.indicators.panelHeight / 2,
3888+ indicatorItemCoord.x, panel.height,
3889 false /* beginTouch */, false /* endTouch */);
3890
3891 // Indicators height should follow the drag, and therefore increase accordingly.
3892@@ -192,7 +282,7 @@
3893 function() {return panel.indicators.height >= panel.height * 0.5},
3894 true);
3895
3896- touchRelease(panel, indicatorItemCoord.x, panel.height * 0.8);
3897+ touchRelease(panel, indicatorItemCoord.x, panel.height);
3898
3899 compare(indicatorRow.currentItem, indicatorItem,
3900 "Incorrect item activated at position " + i);
3901@@ -200,43 +290,18 @@
3902
3903 // init for next indicatorItem
3904 if (!data.alreadyOpen) {
3905- init();
3906+ panel.indicators.hide();
3907+ tryCompare(panel.indicators.hideAnimation, "running", false);
3908+ tryCompare(panel.indicators, "state", "initial");
3909 }
3910 }
3911 }
3912
3913- function test_search_click_when_visible() {
3914- panel.fullscreenMode = false;
3915- panel.searchVisible = true;
3916-
3917- var searchIndicator = findChild(panel, "search");
3918- verify(searchIndicator !== null);
3919-
3920- tap(searchIndicator, 1, 1);
3921-
3922- compare(searchClicked, true,
3923- "Tapping search indicator while it was enabled did not emit searchClicked signal");
3924- }
3925-
3926- function test_search_click_when_not_visible() {
3927- panel.fullscreenMode = false;
3928- panel.searchVisible = false;
3929-
3930- var searchIndicator = findChild(panel, "search");
3931- verify(searchIndicator !== null);
3932-
3933- tap(searchIndicator, 1, 1);
3934-
3935- compare(searchClicked, false,
3936- "Tapping search indicator while it was not visible emitted searchClicked signal");
3937- }
3938-
3939 // Test the vertical velocity check when flicking the indicators open at an angle.
3940 // If the vertical velocity is above a specific point, we shouldnt change active indicators
3941 // if the x position changes
3942 function test_vertical_velocity_detector() {
3943 panel.fullscreenMode = false;
3944- panel.searchVisible = false;
3945
3946 var indicatorRow = findChild(panel.indicators, "indicatorRow");
3947 verify(indicatorRow !== null);
3948@@ -249,19 +314,19 @@
3949 var indicatorItemCoordNext = get_indicator_item_position(indicatorRow.row.count - 1);
3950
3951 touchPress(panel,
3952- indicatorItemCoordFirst.x, panel.panelHeight / 2);
3953+ indicatorItemCoordFirst.x, panel.indicators.panelHeight / 2);
3954
3955 // 1) Drag the mouse down to hint a bit
3956 touchFlick(panel,
3957- indicatorItemCoordFirst.x, panel.panelHeight / 2,
3958- indicatorItemCoordFirst.x, panel.panelHeight * 2,
3959+ indicatorItemCoordFirst.x, panel.indicators.panelHeight / 2,
3960+ indicatorItemCoordFirst.x, panel.indicators.panelHeight * 2,
3961 false /* beginTouch */, false /* endTouch */);
3962
3963 tryCompare(indicatorRow, "currentItem", indicatorItemFirst)
3964
3965 // 1) Flick mouse down to bottom
3966 touchFlick(panel,
3967- indicatorItemCoordFirst.x, panel.panelHeight * 2,
3968+ indicatorItemCoordFirst.x, panel.indicators.panelHeight * 2,
3969 indicatorItemCoordNext.x, panel.height,
3970 false /* beginTouch */, true /* endTouch */,
3971 units.gu(10) /* speed */, 30 /* iterations */); // more samples needed for accurate velocity
3972
3973=== modified file 'tests/qmltests/tst_Shell.qml'
3974--- tests/qmltests/tst_Shell.qml 2014-06-17 03:52:58 +0000
3975+++ tests/qmltests/tst_Shell.qml 2014-07-08 15:02:30 +0000
3976@@ -510,42 +510,6 @@
3977 tryCompare(dash, "shown", data.expectedShown);
3978 }
3979
3980- function test_searchIndicatorHidesOnAppFocus() {
3981- var searchIndicator = findChild(shell, "container")
3982- tryCompare(searchIndicator, "opacity", 1)
3983- dragLauncherIntoView();
3984-
3985- // Launch an app from the launcher
3986- tapOnAppIconInLauncher();
3987- waitUntilApplicationWindowIsFullyVisible();
3988-
3989- tryCompare(searchIndicator, "opacity", 0);
3990- }
3991-
3992- function test_searchIndicatorHidesOnGreeterShown() {
3993- var searchIndicator = findChild(shell, "container")
3994- var greeter = findChild(shell, "greeter");
3995-
3996- tryCompare(searchIndicator, "opacity", 1)
3997-
3998- greeter.show()
3999- tryCompare(greeter, "shown", true)
4000- tryCompare(searchIndicator, "opacity", 0)
4001- }
4002-
4003- function test_searchIndicatorHideOnPreviewShown() {
4004- var searchIndicator = findChild(shell, "container");
4005- var dashContent = findChild(shell, "dashContent");
4006-
4007- verify(dashContent != null);
4008-
4009- tryCompare(searchIndicator, "opacity", 1);
4010-
4011- dashContent.previewOpen = true;
4012-
4013- tryCompare(searchIndicator, "opacity", 0);
4014- }
4015-
4016 function test_focusRequestedHidesGreeter() {
4017 var greeter = findChild(shell, "greeter")
4018

Subscribers

People subscribed via source and target branches