Merge lp:~saviq/unity8/dash-activity-indicator into lp:unity8

Proposed by Michał Sawicz
Status: Superseded
Proposed branch: lp:~saviq/unity8/dash-activity-indicator
Merge into: lp:unity8
Diff against target: 1995 lines (+588/-444)
25 files modified
debian/control (+2/-2)
plugins/Dash/ScopeStyle.qml (+11/-8)
qml/Components/PageHeader.qml (+1/-14)
qml/Dash/Dash.qml (+77/-12)
qml/Dash/DashContent.qml (+5/-4)
qml/Dash/DashNavigation.qml (+50/-43)
qml/Dash/DashNavigationList.qml (+14/-18)
qml/Dash/GenericScopeView.qml (+6/-12)
qml/Dash/PreviewListView.qml (+27/-31)
qml/ScopeTool.qml (+1/-11)
tests/autopilot/unity8/shell/emulators/dash.py (+1/-1)
tests/mocks/Unity/CMakeLists.txt (+3/-3)
tests/mocks/Unity/Unity.qmltypes (+87/-35)
tests/mocks/Unity/fake_navigation.cpp (+36/-44)
tests/mocks/Unity/fake_navigation.h (+13/-13)
tests/mocks/Unity/fake_scope.cpp (+73/-25)
tests/mocks/Unity/fake_scope.h (+16/-8)
tests/mocks/Unity/fake_scopes.cpp (+10/-2)
tests/mocks/Unity/fake_scopes.h (+1/-0)
tests/mocks/Unity/fake_unity_plugin.cpp (+2/-2)
tests/plugins/Dash/tst_ScopeStyle.qml (+14/-7)
tests/qmltests/Components/tst_PageHeader.qml (+0/-23)
tests/qmltests/Dash/tst_Dash.qml (+28/-15)
tests/qmltests/Dash/tst_DashContent.qml (+109/-110)
tests/qmltests/Dash/tst_GenericScopeView.qml (+1/-1)
To merge this branch: bzr merge lp:~saviq/unity8/dash-activity-indicator
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Albert Astals Cid (community) Needs Fixing
Andrea Cimitan (community) Needs Fixing
Review via email: mp+228718@code.launchpad.net

This proposal has been superseded by a proposal from 2014-08-06.

Commit message

Refactor dash activity indicator.

Description of the change

 * Are there any related MPs required for this MP to build/function as expected? Please list.
No.

 * 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, there was. And will be again.

To post a comment you must log in.
1078. By Michał Sawicz

Add one more step to verify that indicator goes away.

1079. By Michał Sawicz

Drop departments id, unused.

1080. By Michał Sawicz

Re-add newline.

1081. By Michał Sawicz

Newline--

1082. By Michał Sawicz

Undo divider changes.

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)
1083. By Michał Sawicz

Merge trunk.

Revision history for this message
Andrea Cimitan (cimi) wrote :

See inline

review: Needs Fixing
1084. By Michał Sawicz

Fix review comments.

Revision history for this message
Michał Sawicz (saviq) :
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 tests/qmltests/Dash/tst_Dash.qml
1 conflicts encountered.

review: Needs Fixing
1085. By Michał Sawicz

Merge.

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 :

There are autopilot failures related to autopilot, can you have a look?

review: Needs Fixing
Revision history for this message
Albert Astals Cid (aacid) wrote :

err, autopilot failures related to indicators i mean :D

review: Needs Fixing
1086. By Michał Sawicz

Fix search emulator.

1087. By Michał Sawicz

Merge lp:~unity-team/unity8/scopes-v4

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

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/control'
--- debian/control 2014-07-31 16:48:11 +0000
+++ debian/control 2014-08-06 14:50:38 +0000
@@ -24,7 +24,7 @@
24 libpulse-dev,24 libpulse-dev,
25 libqmenumodel-dev (>= 0.2.8),25 libqmenumodel-dev (>= 0.2.8),
26 libqt5xmlpatterns5-dev,26 libqt5xmlpatterns5-dev,
27 libunity-api-dev (>= 7.87),27 libunity-api-dev (>= 7.88),
28 libusermetricsoutput1-dev,28 libusermetricsoutput1-dev,
29 libxcb1-dev,29 libxcb1-dev,
30 pkg-config,30 pkg-config,
@@ -112,7 +112,7 @@
112 unity-application-impl-2,112 unity-application-impl-2,
113 unity-notifications-impl-3,113 unity-notifications-impl-3,
114 unity-plugin-scopes | unity-scopes-impl,114 unity-plugin-scopes | unity-scopes-impl,
115 unity-scopes-impl-2,115 unity-scopes-impl-4,
116 unity8-fake-env | unity-application-impl,116 unity8-fake-env | unity-application-impl,
117 ${misc:Depends},117 ${misc:Depends},
118Breaks: unity8 (<< 7.86),118Breaks: unity8 (<< 7.86),
119119
=== modified file 'plugins/Dash/ScopeStyle.qml'
--- plugins/Dash/ScopeStyle.qml 2014-07-18 18:09:13 +0000
+++ plugins/Dash/ScopeStyle.qml 2014-08-06 14:50:38 +0000
@@ -38,14 +38,20 @@
38 /// Color used for text and symbolic icons38 /// Color used for text and symbolic icons
39 readonly property color foreground: "foreground-color" in style ? style["foreground-color"] : d.defaultDark39 readonly property color foreground: "foreground-color" in style ? style["foreground-color"] : d.defaultDark
4040
41 /// Luminance of the foreground color
42 readonly property real foregroundLuminance: foreground ? luminance(foreground) : d.defaultForegroundLuminance
43
41 /// Color used for the overall background44 /// Color used for the overall background
42 readonly property color background: "background-color" in style ? style["background-color"] : "transparent"45 readonly property color background: "background-color" in style ? style["background-color"] : "transparent"
4346
47 /// Luminance of the foreground color
48 readonly property real backgroundLuminance: background ? luminance(background) : d.defaultBackgroundLuminance
49
44 /*! \brief Luminance threshold for switching between fore and background color50 /*! \brief Luminance threshold for switching between fore and background color
4551
46 \note If background colour is not fully opaque, it's not taken into account.52 \note If background colour is not fully opaque, it's not taken into account.
47 */53 */
48 readonly property real threshold: background.a !== 1.0 ? d.foregroundLuminance : (d.foregroundLuminance + d.backgroundLuminance) / 254 readonly property real threshold: background.a !== 1.0 ? foregroundLuminance : (foregroundLuminance + backgroundLuminance) / 2
4955
50 /*! \brief The lighter of foreground and background colors56 /*! \brief The lighter of foreground and background colors
5157
@@ -53,8 +59,8 @@
53 and defaults to the theme-provided light color.59 and defaults to the theme-provided light color.
54 */60 */
55 readonly property color light: {61 readonly property color light: {
56 if (background.a !== 1.0) return d.foregroundLuminance > d.defaultLightLuminance ? foreground : d.defaultLight;62 if (background.a !== 1.0) return foregroundLuminance > d.defaultLightLuminance ? foreground : d.defaultLight;
57 return d.foregroundLuminance > d.backgroundLuminance ? foreground : background;63 return foregroundLuminance > backgroundLuminance ? foreground : background;
58 }64 }
5965
60 /*! \brief The darker of foreground and background colors66 /*! \brief The darker of foreground and background colors
@@ -63,8 +69,8 @@
63 and defaults to the theme-provided dark color.69 and defaults to the theme-provided dark color.
64 */70 */
65 readonly property color dark: {71 readonly property color dark: {
66 if (background.a !== 1.0) return d.foregroundLuminance < d.defaultDarkLuminance ? foreground : d.defaultDark;72 if (background.a !== 1.0) return foregroundLuminance < d.defaultDarkLuminance ? foreground : d.defaultDark;
67 return d.foregroundLuminance < d.backgroundLuminance ? foreground : background;73 return foregroundLuminance < backgroundLuminance ? foreground : background;
68 }74 }
6975
70 /// Source of the logo image for the header76 /// Source of the logo image for the header
@@ -78,9 +84,6 @@
7884
79 //! @cond85 //! @cond
80 property var d: QtObject {86 property var d: QtObject {
81 readonly property real foregroundLuminance: luminance(foreground)
82 readonly property real backgroundLuminance: luminance(background)
83
84 // FIXME: should be taken from the theme87 // FIXME: should be taken from the theme
85 readonly property color defaultLight: "white"88 readonly property color defaultLight: "white"
86 readonly property color defaultDark: "grey"89 readonly property color defaultDark: "grey"
8790
=== modified file 'qml/Components/PageHeader.qml'
--- qml/Components/PageHeader.qml 2014-07-31 16:49:50 +0000
+++ qml/Components/PageHeader.qml 2014-08-06 14:50:38 +0000
@@ -32,7 +32,6 @@
32 property bool searchEntryEnabled: false32 property bool searchEntryEnabled: false
33 property ListModel searchHistory: SearchHistoryModel33 property ListModel searchHistory: SearchHistoryModel
34 property alias searchQuery: searchTextField.text34 property alias searchQuery: searchTextField.text
35 property bool searchInProgress: false
3635
37 property alias bottomItem: bottomContainer.children36 property alias bottomItem: bottomContainer.children
3837
@@ -200,25 +199,13 @@
200 anchors.fill: parent199 anchors.fill: parent
201 anchors.margins: units.gu(.75)200 anchors.margins: units.gu(.75)
202 source: "image://theme/clear"201 source: "image://theme/clear"
203 opacity: searchTextField.text.length > 0 && !searchActivityIndicator.running202 opacity: searchTextField.text.length > 0
204 visible: opacity > 0203 visible: opacity > 0
205 Behavior on opacity {204 Behavior on opacity {
206 UbuntuNumberAnimation { duration: UbuntuAnimation.FastDuration }205 UbuntuNumberAnimation { duration: UbuntuAnimation.FastDuration }
207 }206 }
208 }207 }
209208
210 ActivityIndicator {
211 id: searchActivityIndicator
212 objectName: "searchIndicator"
213 anchors.fill: parent
214 anchors.margins: units.gu(.75)
215 running: root.searchInProgress
216 opacity: running ? 1 : 0
217 Behavior on opacity {
218 UbuntuNumberAnimation { duration: UbuntuAnimation.FastDuration }
219 }
220 }
221
222 onClicked: {209 onClicked: {
223 root.resetSearch(true);210 root.resetSearch(true);
224 root.openSearchHistory();211 root.openSearchHistory();
225212
=== modified file 'qml/Dash/Dash.qml'
--- qml/Dash/Dash.qml 2014-07-29 11:35:10 +0000
+++ qml/Dash/Dash.qml 2014-08-06 14:50:38 +0000
@@ -14,7 +14,7 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */15 */
1616
17import QtQuick 2.017import QtQuick 2.2
18import Ubuntu.Components 0.118import Ubuntu.Components 0.1
19import Unity 0.219import Unity 0.2
20import Utils 0.120import Utils 0.1
@@ -38,7 +38,13 @@
38 }38 }
3939
40 function setCurrentScope(scopeId, animate, reset) {40 function setCurrentScope(scopeId, animate, reset) {
41 var scopeIndex = filteredScopes.findFirst(Scopes.RoleId, scopeId)41 var scopeIndex = -1;
42 for (var i = 0; i < scopes.count; ++i) {
43 if (scopes.getScope(i).id == scopeId) {
44 scopeIndex = i;
45 break;
46 }
47 }
4248
43 if (scopeIndex == -1) {49 if (scopeIndex == -1) {
44 console.warn("No match for scope with id: %1".arg(scopeId))50 console.warn("No match for scope with id: %1".arg(scopeId))
@@ -63,15 +69,8 @@
63 }69 }
64 }70 }
6571
66 SortFilterProxyModel {72 Scopes {
67 id: filteredScopes73 id: scopes
68 model: Scopes {
69 id: scopes
70 }
71 dynamicSortFilter: true
72
73 filterRole: Scopes.RoleVisible
74 filterRegExp: RegExp("^true$")
75 }74 }
7675
77 DashContent {76 DashContent {
@@ -79,7 +78,6 @@
79 objectName: "dashContent"78 objectName: "dashContent"
80 width: parent.width79 width: parent.width
81 height: parent.height80 height: parent.height
82 model: filteredScopes
83 scopes: scopes81 scopes: scopes
84 visible: x != -width82 visible: x != -width
85 onGotoScope: {83 onGotoScope: {
@@ -134,4 +132,71 @@
134 }132 }
135 }133 }
136 }134 }
135
136 Rectangle {
137 id: indicator
138 objectName: "processingIndicator"
139 anchors {
140 left: parent.left
141 right: parent.right
142 bottom: parent.bottom
143 }
144 height: units.dp(3)
145 color: scopeStyle.backgroundLuminance > 0.7 ? "#50000000" : "#50ffffff"
146 opacity: 0
147 visible: opacity > 0
148
149 readonly property bool processing: dashContent.processing || scopeItem.processing
150
151 Behavior on opacity {
152 UbuntuNumberAnimation { duration: UbuntuAnimation.FastDuration }
153 }
154
155 onProcessingChanged: {
156 if (processing) delay.start();
157 else if (!persist.running) indicator.opacity = 0;
158 }
159
160 Timer {
161 id: delay
162 interval: 200
163 onTriggered: if (indicator.processing) {
164 persist.restart();
165 indicator.opacity = 1;
166 }
167 }
168
169 Timer {
170 id: persist
171 interval: 2 * UbuntuAnimation.SleepyDuration - UbuntuAnimation.FastDuration
172 onTriggered: if (!indicator.processing) indicator.opacity = 0
173 }
174
175 Rectangle {
176 id: orange
177 anchors { top: parent.top; bottom: parent.bottom }
178 width: parent.width / 4
179 color: Theme.palette.selected.foreground
180
181 SequentialAnimation {
182 running: indicator.visible
183 loops: Animation.Infinite
184 XAnimator {
185 from: -orange.width / 2
186 to: indicator.width - orange.width / 2
187 duration: UbuntuAnimation.SleepyDuration
188 easing.type: Easing.InOutSine
189 target: orange
190 }
191 XAnimator {
192 from: indicator.width - orange.width / 2
193 to: -orange.width / 2
194 duration: UbuntuAnimation.SleepyDuration
195 easing.type: Easing.InOutSine
196 target: orange
197 }
198 }
199 }
200 }
201
137}202}
138203
=== modified file 'qml/Dash/DashContent.qml'
--- qml/Dash/DashContent.qml 2014-07-24 23:31:44 +0000
+++ qml/Dash/DashContent.qml 2014-08-06 14:50:38 +0000
@@ -23,9 +23,10 @@
23Item {23Item {
24 id: dashContent24 id: dashContent
2525
26 property var model: null26 property alias scopes: dashContentList.model
27 property var scopes: null
28 readonly property alias currentIndex: dashContentList.currentIndex27 readonly property alias currentIndex: dashContentList.currentIndex
28 readonly property bool processing: dashContentList.currentItem && dashContentList.currentItem.item
29 && dashContentList.currentItem.item.processing || false
2930
30 signal scopeLoaded(string scopeId)31 signal scopeLoaded(string scopeId)
31 signal gotoScope(string scopeId)32 signal gotoScope(string scopeId)
@@ -89,10 +90,9 @@
89 id: dashContentList90 id: dashContentList
90 objectName: "dashContentList"91 objectName: "dashContentList"
9192
92 interactive: dashContent.scopes.loaded && currentItem && !currentItem.moving93 interactive: dashContent.scopes.loaded && currentItem && !currentItem.moving && !currentItem.navigationShown
9394
94 anchors.fill: parent95 anchors.fill: parent
95 model: dashContent.model
96 orientation: ListView.Horizontal96 orientation: ListView.Horizontal
97 boundsBehavior: Flickable.DragAndOvershootBounds97 boundsBehavior: Flickable.DragAndOvershootBounds
98 flickDeceleration: units.gu(625)98 flickDeceleration: units.gu(625)
@@ -130,6 +130,7 @@
130 objectName: scope.id + " loader"130 objectName: scope.id + " loader"
131131
132 readonly property bool moving: item ? item.moving : false132 readonly property bool moving: item ? item.moving : false
133 readonly property bool navigationShown: item ? item.navigationShown : false
133 readonly property var categoryView: item ? item.categoryView : null134 readonly property var categoryView: item ? item.categoryView : null
134 readonly property var theScope: scope135 readonly property var theScope: scope
135136
136137
=== renamed file 'qml/Dash/DashDepartments.qml' => 'qml/Dash/DashNavigation.qml'
--- qml/Dash/DashDepartments.qml 2014-07-08 11:08:19 +0000
+++ qml/Dash/DashNavigation.qml 2014-08-06 14:50:38 +0000
@@ -15,17 +15,17 @@
15 */15 */
1616
17import QtQuick 2.217import QtQuick 2.2
18import Ubuntu.Components 0.118import Ubuntu.Components 1.1
1919
20AbstractButton {20AbstractButton {
21 id: root21 id: root
22 objectName: "dashDepartments"22 objectName: "dashNavigation"
2323
24 property var scope: null24 property var scope: null
2525
26 property bool showList: false26 property bool showList: false
2727
28 readonly property var currentDepartment: scope && scope.hasDepartments ? scope.getDepartment(scope.currentDepartmentId) : null28 readonly property var currentNavigation: scope && scope.hasNavigation ? scope.getNavigation(scope.currentNavigationId) : null
2929
30 property alias windowWidth: blackRect.width30 property alias windowWidth: blackRect.width
31 property alias windowHeight: blackRect.height31 property alias windowHeight: blackRect.height
@@ -34,20 +34,21 @@
34 // Are we drilling down the tree or up?34 // Are we drilling down the tree or up?
35 property bool isGoingBack: false35 property bool isGoingBack: false
3636
37 visible: root.currentDepartment != null37 visible: root.currentNavigation != null
3838
39 height: visible ? units.gu(5) : 039 height: visible ? units.gu(5) : 0
4040
41 onClicked: {41 onClicked: {
42 navigationListView.updateMaxHeight();
42 root.showList = !root.showList;43 root.showList = !root.showList;
43 }44 }
4445
45 Rectangle {46 Rectangle {
46 id: blackRect47 id: blackRect
47 color: "black"48 color: "black"
48 opacity: departmentListView.currentItem && departmentListView.currentItem.visible ? 0.3 : 049 opacity: navigationListView.currentItem && navigationListView.currentItem.visible ? 0.3 : 0
49 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }50 Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
50 anchors.top: departmentListView.top51 anchors.top: navigationListView.top
51 anchors.right: parent.right52 anchors.right: parent.right
52 visible: opacity != 053 visible: opacity != 0
53 }54 }
@@ -78,7 +79,7 @@
78 anchors.fill: parent79 anchors.fill: parent
79 anchors.margins: units.gu(2)80 anchors.margins: units.gu(2)
80 verticalAlignment: Text.AlignVCenter81 verticalAlignment: Text.AlignVCenter
81 text: root.currentDepartment ? root.currentDepartment.label : ""82 text: root.currentNavigation ? root.currentNavigation.label : ""
82 color: root.scopeStyle ? root.scopeStyle.foreground : "grey"83 color: root.scopeStyle ? root.scopeStyle.foreground : "grey"
83 }84 }
8485
@@ -92,18 +93,18 @@
92 color: root.scopeStyle ? root.scopeStyle.foreground : "grey"93 color: root.scopeStyle ? root.scopeStyle.foreground : "grey"
93 }94 }
9495
95 // departmentListView is outside root96 // navigationListView is outside root
96 ListView {97 ListView {
97 id: departmentListView98 id: navigationListView
98 objectName: "departmentListView"99 objectName: "navigationListView"
99 orientation: ListView.Horizontal100 orientation: ListView.Horizontal
100 interactive: false101 interactive: false
101 clip: root.width != windowWidth102 clip: root.width != windowWidth
102 model: ListModel {103 model: ListModel {
103 id: departmentModel104 id: navigationModel
104 // We have two roles105 // We have two roles
105 // departmentId: the department id of the department the list represents106 // navigationId: the navigation id of the navigation the list represents
106 // nullifyDepartment: overrides departmentId to be null107 // nullifyNavigation: overrides navigationId to be null
107 // This is used to "clear" the delegate when going "right" on the tree108 // This is used to "clear" the delegate when going "right" on the tree
108 }109 }
109 anchors {110 anchors {
@@ -111,7 +112,12 @@
111 right: parent.right112 right: parent.right
112 top: root.bottom113 top: root.bottom
113 }114 }
114 readonly property int maxHeight: (windowHeight - mapToItem(null, root.x, root.y).y) - units.gu(8)115 property int maxHeight: -1
116 Component.onCompleted: updateMaxHeight();
117 function updateMaxHeight()
118 {
119 maxHeight = (windowHeight - mapToItem(null, 0, 0).y) - units.gu(8);
120 }
115 property int prevHeight: maxHeight121 property int prevHeight: maxHeight
116 height: currentItem ? currentItem.height : maxHeight122 height: currentItem ? currentItem.height : maxHeight
117 onHeightChanged: {123 onHeightChanged: {
@@ -120,83 +126,84 @@
120 }126 }
121 }127 }
122 highlightMoveDuration: UbuntuAnimation.FastDuration128 highlightMoveDuration: UbuntuAnimation.FastDuration
123 delegate: DashDepartmentsList {129 delegate: DashNavigationList {
124 objectName: "department" + index130 objectName: "navigation" + index
125 visible: height != 0131 visible: height != 0
126 width: departmentListView.width132 width: navigationListView.width
127 scopeStyle: root.scopeStyle133 scopeStyle: root.scopeStyle
128 property real desiredHeight: {134 property real desiredHeight: {
129 if (root.showList) {135 if (root.showList) {
130 if (department && department.loaded && x == departmentListView.contentX)136 if (navigation && navigation.loaded && x == navigationListView.contentX)
131 {137 {
132 return Math.min(implicitHeight, departmentListView.maxHeight);138 navigationListView.updateMaxHeight();
139 return Math.min(implicitHeight, navigationListView.maxHeight);
133 } else {140 } else {
134 return departmentListView.prevHeight;141 return navigationListView.prevHeight;
135 }142 }
136 } else {143 } else {
137 return 0;144 return 0;
138 }145 }
139 }146 }
140 height: desiredHeight147 height: desiredHeight
141 department: (nullifyDepartment || !scope) ? null : scope.getDepartment(departmentId)148 navigation: (nullifyNavigation || !scope) ? null : scope.getNavigation(navigationId)
142 currentDepartment: root.currentDepartment149 currentNavigation: root.currentNavigation
143 onEnterDepartment: {150 onEnterNavigation: {
144 scope.loadDepartment(newDepartmentId);151 scope.setNavigationState(newNavigationId, false);
145 // We only need to add a new item to the model152 // We only need to add a new item to the model
146 // if we have children, otherwise just load it153 // if we have children, otherwise just load it
147 if (hasChildren) {154 if (hasChildren) {
148 isGoingBack = false;155 isGoingBack = false;
149 departmentModel.append({"departmentId": newDepartmentId, "nullifyDepartment": false});156 navigationModel.append({"navigationId": newNavigationId, "nullifyNavigation": false});
150 departmentListView.currentIndex++;157 navigationListView.currentIndex++;
151 } else {158 } else {
152 showList = false;159 showList = false;
153 }160 }
154 }161 }
155 onGoBackToParentClicked: {162 onGoBackToParentClicked: {
156 scope.loadDepartment(department.parentDepartmentId);163 scope.setNavigationState(navigation.parentNavigationId, false);
157 isGoingBack = true;164 isGoingBack = true;
158 departmentModel.setProperty(departmentListView.currentIndex - 1, "nullifyDepartment", false);165 navigationModel.setProperty(navigationListView.currentIndex - 1, "nullifyNavigation", false);
159 departmentListView.currentIndex--;166 navigationListView.currentIndex--;
160 }167 }
161 onAllDepartmentClicked: {168 onAllNavigationClicked: {
162 showList = false;169 showList = false;
163 if (root.currentDepartment.parentDepartmentId == department.departmentId) {170 if (root.currentNavigation.parentNavigationId == navigation.navigationId) {
164 // For leaves we have to go to the parent too171 // For leaves we have to go to the parent too
165 scope.loadDepartment(root.currentDepartment.parentDepartmentId);172 scope.setNavigationState(root.currentNavigation.parentNavigationId, false);
166 }173 }
167 }174 }
168 }175 }
169 onContentXChanged: {176 onContentXChanged: {
170 if (contentX == width * departmentListView.currentIndex) {177 if (contentX == width * navigationListView.currentIndex) {
171 if (isGoingBack) {178 if (isGoingBack) {
172 departmentModel.remove(departmentListView.currentIndex + 1);179 navigationModel.remove(navigationListView.currentIndex + 1);
173 } else {180 } else {
174 departmentModel.setProperty(departmentListView.currentIndex - 1, "nullifyDepartment", true);181 navigationModel.setProperty(navigationListView.currentIndex - 1, "nullifyNavigation", true);
175 }182 }
176 }183 }
177 }184 }
178 }185 }
179186
180 InverseMouseArea {187 InverseMouseArea {
181 anchors.fill: departmentListView188 anchors.fill: navigationListView
182 enabled: root.showList189 enabled: root.showList
183 onClicked: root.showList = false190 onClicked: root.showList = false
184 }191 }
185192
186 onScopeChanged: {193 onScopeChanged: {
187 departmentModel.clear();194 navigationModel.clear();
188 if (scope && scope.hasDepartments) {195 if (scope && scope.hasNavigation) {
189 departmentModel.append({"departmentId": scope.currentDepartmentId, "nullifyDepartment": false});196 navigationModel.append({"navigationId": scope.currentNavigationId, "nullifyNavigation": false});
190 }197 }
191 }198 }
192199
193 Connections {200 Connections {
194 target: scope201 target: scope
195 onHasDepartmentsChanged: {202 onHasNavigationChanged: {
196 if (scope.hasDepartments) {203 if (scope.hasNavigation) {
197 departmentModel.append({"departmentId": scope.currentDepartmentId, "nullifyDepartment": false});204 navigationModel.append({"navigationId": scope.currentNavigationId, "nullifyNavigation": false});
198 } else {205 } else {
199 departmentModel.clear();206 navigationModel.clear();
200 }207 }
201 }208 }
202 }209 }
203210
=== renamed file 'qml/Dash/DashDepartmentsList.qml' => 'qml/Dash/DashNavigationList.qml'
--- qml/Dash/DashDepartmentsList.qml 2014-07-08 11:08:19 +0000
+++ qml/Dash/DashNavigationList.qml 2014-08-06 14:50:38 +0000
@@ -15,16 +15,16 @@
15 */15 */
1616
17import QtQuick 2.217import QtQuick 2.2
18import Ubuntu.Components 0.118import Ubuntu.Components 1.1
1919
20Item {20Item {
21 id: root21 id: root
22 property var department: null22 property var navigation: null
23 property var currentDepartment: null23 property var currentNavigation: null
24 property var scopeStyle: null24 property var scopeStyle: null
25 signal enterDepartment(var newDepartmentId, bool hasChildren)25 signal enterNavigation(var newNavigationId, bool hasChildren)
26 signal goBackToParentClicked()26 signal goBackToParentClicked()
27 signal allDepartmentClicked()27 signal allNavigationClicked()
2828
29 readonly property int itemHeight: units.gu(5)29 readonly property int itemHeight: units.gu(5)
30 readonly property color foregroundColor: root.scopeStyle ? root.scopeStyle.foreground : "grey"30 readonly property color foregroundColor: root.scopeStyle ? root.scopeStyle.foreground : "grey"
@@ -35,11 +35,6 @@
35 anchors.fill: parent35 anchors.fill: parent
36 }36 }
3737
38 ActivityIndicator {
39 id: loadingIndicator
40 anchors.centerIn: parent
41 running: !(department && department.loaded)
42 }
43 clip: true38 clip: true
4439
45 Behavior on height {40 Behavior on height {
@@ -54,6 +49,7 @@
5449
55 anchors.fill: parent50 anchors.fill: parent
5651
52 flickableDirection: Flickable.VerticalFlick
57 contentHeight: column.height53 contentHeight: column.height
58 contentWidth: width54 contentWidth: width
5955
@@ -68,7 +64,7 @@
68 id: backButton64 id: backButton
69 objectName: "backButton"65 objectName: "backButton"
70 width: parent.width66 width: parent.width
71 visible: department && !department.isRoot || false67 visible: navigation && !navigation.isRoot || false
72 height: itemHeight68 height: itemHeight
7369
74 onClicked: root.goBackToParentClicked();70 onClicked: root.goBackToParentClicked();
@@ -92,7 +88,7 @@
92 left: backImage.right88 left: backImage.right
93 leftMargin: units.gu(0.5)89 leftMargin: units.gu(0.5)
94 }90 }
95 text: department ? department.parentLabel : ""91 text: navigation ? navigation.parentLabel : ""
96 color: root.foregroundColor92 color: root.foregroundColor
97 }93 }
9894
@@ -114,7 +110,7 @@
114 id: allButton110 id: allButton
115 objectName: "allButton"111 objectName: "allButton"
116 width: parent.width112 width: parent.width
117 visible: department && (!department.isRoot || (root.currentDepartment && !root.currentDepartment.isRoot && root.currentDepartment.parentDepartmentId == department.departmentId)) || false113 visible: navigation && (!navigation.isRoot || (root.currentNavigation && !root.currentNavigation.isRoot && root.currentNavigation.parentNavigationId == navigation.navigationId)) || false
118 height: itemHeight114 height: itemHeight
119115
120 Label {116 Label {
@@ -123,7 +119,7 @@
123 left: parent.left119 left: parent.left
124 leftMargin: units.gu(2)120 leftMargin: units.gu(2)
125 }121 }
126 text: department ? (department.allLabel != "" ? department.allLabel : department.label) : ""122 text: navigation ? (navigation.allLabel != "" ? navigation.allLabel : navigation.label) : ""
127 font.bold: true123 font.bold: true
128 color: root.foregroundColor124 color: root.foregroundColor
129 }125 }
@@ -141,18 +137,18 @@
141 height: units.dp(1)137 height: units.dp(1)
142 }138 }
143139
144 onClicked: root.allDepartmentClicked();140 onClicked: root.allNavigationClicked();
145 }141 }
146142
147 Repeater {143 Repeater {
148 model: department && department.loaded ? department : null144 model: navigation && navigation.loaded ? navigation : null
149 clip: true145 clip: true
150 delegate: AbstractButton {146 delegate: AbstractButton {
151 objectName: root.objectName + "child" + index147 objectName: root.objectName + "child" + index
152 height: root.itemHeight148 height: root.itemHeight
153 width: root.width149 width: root.width
154150
155 onClicked: root.enterDepartment(departmentId, hasChildren)151 onClicked: root.enterNavigation(navigationId, hasChildren)
156152
157 Label {153 Label {
158 anchors {154 anchors {
@@ -188,7 +184,7 @@
188 color: root.foregroundColor184 color: root.foregroundColor
189 opacity: 0.1185 opacity: 0.1
190 height: units.dp(1)186 height: units.dp(1)
191 visible: index != department.count - 1187 visible: index != navigation.count - 1
192 }188 }
193 }189 }
194 }190 }
195191
=== modified file 'qml/Dash/GenericScopeView.qml'
--- qml/Dash/GenericScopeView.qml 2014-07-29 11:35:10 +0000
+++ qml/Dash/GenericScopeView.qml 2014-08-06 14:50:38 +0000
@@ -25,6 +25,7 @@
25FocusScope {25FocusScope {
26 id: scopeView26 id: scopeView
2727
28 readonly property alias navigationShown: dashNavigation.showList
28 property var scope: null29 property var scope: null
29 property SortFilterProxyModel categories: categoryFilter30 property SortFilterProxyModel categories: categoryFilter
30 property bool isCurrent: false31 property bool isCurrent: false
@@ -37,18 +38,10 @@
37 style: scope ? scope.customizations : {}38 style: scope ? scope.customizations : {}
38 }39 }
3940
41 readonly property bool processing: scope ? scope.searchInProgress || previewListView.processing : false
42
40 signal backClicked()43 signal backClicked()
4144
42 onScopeChanged: {
43 if (scope) {
44 scope.activateApplication.connect(activateApp);
45 }
46 }
47
48 function activateApp(appId) {
49 Qt.openUrlExternally(appId);
50 }
51
52 function positionAtBeginning() {45 function positionAtBeginning() {
53 categoryView.positionAtBeginning()46 categoryView.positionAtBeginning()
54 }47 }
@@ -119,6 +112,7 @@
119 model: scopeView.categories112 model: scopeView.categories
120 forceNoClip: previewListView.open113 forceNoClip: previewListView.open
121 pixelAligned: true114 pixelAligned: true
115 interactive: !dashNavigation.showList
122116
123 property string expandedCategoryId: ""117 property string expandedCategoryId: ""
124118
@@ -387,10 +381,10 @@
387 title: scopeView.scope ? scopeView.scope.name : ""381 title: scopeView.scope ? scopeView.scope.name : ""
388 showBackButton: scopeView.hasBackAction382 showBackButton: scopeView.hasBackAction
389 searchEntryEnabled: true383 searchEntryEnabled: true
390 searchInProgress: scopeView.scope ? scopeView.scope.searchInProgress : false
391 scopeStyle: scopeView.scopeStyle384 scopeStyle: scopeView.scopeStyle
392385
393 bottomItem: DashDepartments {386 bottomItem: DashNavigation {
387 id: dashNavigation
394 scope: scopeView.scope388 scope: scopeView.scope
395 width: parent.width <= units.gu(60) ? parent.width : units.gu(40)389 width: parent.width <= units.gu(60) ? parent.width : units.gu(40)
396 anchors.right: parent.right390 anchors.right: parent.right
397391
=== modified file 'qml/Dash/PreviewListView.qml'
--- qml/Dash/PreviewListView.qml 2014-07-17 13:10:45 +0000
+++ qml/Dash/PreviewListView.qml 2014-08-06 14:50:38 +0000
@@ -32,6 +32,9 @@
32 property alias currentItem: previewListView.currentItem32 property alias currentItem: previewListView.currentItem
33 property alias count: previewListView.count33 property alias count: previewListView.count
3434
35 readonly property bool processing: currentItem && (!currentItem.previewModel.loaded
36 || currentItem.previewModel.processingAction)
37
35 PageHeader {38 PageHeader {
36 id: header39 id: header
37 objectName: "pageHeader"40 objectName: "pageHeader"
@@ -83,39 +86,32 @@
83 }86 }
84 }87 }
8588
86 delegate: Item {89 delegate: Previews.Preview {
87 objectName: "previewItem" + index90 id: preview
91 objectName: "preview" + index
88 height: previewListView.height92 height: previewListView.height
89 width: previewListView.width93 width: previewListView.width
9094
91 readonly property bool ready: preview.previewModel.loaded95 isCurrent: ListView.isCurrentItem
9296
93 Previews.Preview {97 previewModel: {
94 id: preview98 var previewStack = root.scope.preview(result);
95 objectName: "preview" + index99 return previewStack.getPreviewModel(0);
96 anchors.fill: parent100 }
97101 scopeStyle: root.scopeStyle
98 isCurrent: parent.ListView.isCurrentItem102 }
99103 }
100 previewModel: {104
101 var previewStack = root.scope.preview(result);105 MouseArea {
102 return previewStack.getPreviewModel(0);106 id: processingMouseArea
103 }107 objectName: "processingMouseArea"
104 scopeStyle: root.scopeStyle108 anchors {
105 }109 left: parent.left
106110 right: parent.right
107 MouseArea {111 top: pageHeader.bottom
108 id: processingMouseArea112 bottom: parent.bottom
109 objectName: "processingMouseArea"113 }
110 anchors.fill: parent114
111 enabled: !preview.previewModel.loaded || preview.previewModel.processingAction115 enabled: root.processing
112
113 ActivityIndicator {
114 anchors.centerIn: parent
115 visible: root.open && parent.enabled
116 running: visible
117 }
118 }
119 }
120 }116 }
121}117}
122118
=== modified file 'qml/ScopeTool.qml'
--- qml/ScopeTool.qml 2014-07-03 09:08:22 +0000
+++ qml/ScopeTool.qml 2014-08-06 14:50:38 +0000
@@ -45,16 +45,6 @@
45 signal searchClicked45 signal searchClicked
46 }46 }
4747
48 SortFilterProxyModel {
49 id: filteredScopes
50 model: Scopes {
51 id: scopes
52 }
53 dynamicSortFilter: true
54
55 filterRole: Scopes.RoleVisible
56 filterRegExp: RegExp("^true$")
57 }
5848
59 Rectangle {49 Rectangle {
60 anchors.fill: dashContent50 anchors.fill: dashContent
@@ -72,8 +62,8 @@
72 DashContent {62 DashContent {
73 id: dashContent63 id: dashContent
7464
75 model: filteredScopes
76 property var scope: scopes.getScope(currentIndex)65 property var scope: scopes.getScope(currentIndex)
66 scopes: Scopes { }
7767
78 anchors {68 anchors {
79 top: parent.top69 top: parent.top
8070
=== modified file 'tests/autopilot/unity8/shell/emulators/dash.py'
--- tests/autopilot/unity8/shell/emulators/dash.py 2014-07-29 19:49:36 +0000
+++ tests/autopilot/unity8/shell/emulators/dash.py 2014-08-06 14:50:38 +0000
@@ -150,7 +150,7 @@
150 headerContainer.contentY.wait_for(0)150 headerContainer.contentY.wait_for(0)
151 search_text_field = self._get_search_text_field()151 search_text_field = self._get_search_text_field()
152 search_text_field.write(query)152 search_text_field.write(query)
153 current_header.select_single(objectName="searchIndicator").running.wait_for(False)153 self.select_single(objectName="processingIndicator").visible.wait_for(False)
154154
155 def _get_search_text_field(self):155 def _get_search_text_field(self):
156 page_header = self._get_current_page_header()156 page_header = self._get_current_page_header()
157157
=== modified file 'tests/mocks/Unity/CMakeLists.txt'
--- tests/mocks/Unity/CMakeLists.txt 2014-08-05 12:06:16 +0000
+++ tests/mocks/Unity/CMakeLists.txt 2014-08-06 14:50:38 +0000
@@ -7,7 +7,7 @@
7pkg_search_module(DEE dee-1.0 REQUIRED)7pkg_search_module(DEE dee-1.0 REQUIRED)
8pkg_search_module(GOBJECT gobject-2.0 REQUIRED)8pkg_search_module(GOBJECT gobject-2.0 REQUIRED)
9pkg_search_module(DEEQT libdee-qt5 REQUIRED)9pkg_search_module(DEEQT libdee-qt5 REQUIRED)
10pkg_check_modules(SCOPES_API REQUIRED unity-shell-scopes=3)10pkg_check_modules(SCOPES_API REQUIRED unity-shell-scopes=4)
1111
12include_directories(12include_directories(
13 ${CMAKE_CURRENT_BINARY_DIR}13 ${CMAKE_CURRENT_BINARY_DIR}
@@ -23,14 +23,14 @@
23 fake_scope.cpp23 fake_scope.cpp
24 fake_scopes.cpp24 fake_scopes.cpp
25 fake_categories.cpp25 fake_categories.cpp
26 fake_department.cpp26 fake_navigation.cpp
27 fake_resultsmodel.cpp27 fake_resultsmodel.cpp
28 fake_previewmodel.cpp28 fake_previewmodel.cpp
29 fake_previewstack.cpp29 fake_previewstack.cpp
30 fake_previewwidgetmodel.cpp30 fake_previewwidgetmodel.cpp
31 fake_unity_plugin.cpp31 fake_unity_plugin.cpp
32 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/CategoriesInterface.h32 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/CategoriesInterface.h
33 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/DepartmentInterface.h33 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/NavigationInterface.h
34 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/PreviewModelInterface.h34 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/PreviewModelInterface.h
35 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/PreviewStackInterface.h35 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/PreviewStackInterface.h
36 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/PreviewWidgetModelInterface.h36 ${SCOPES_API_INCLUDEDIR}/unity/shell/scopes/PreviewWidgetModelInterface.h
3737
=== modified file 'tests/mocks/Unity/Unity.qmltypes'
--- tests/mocks/Unity/Unity.qmltypes 2014-07-10 10:59:08 +0000
+++ tests/mocks/Unity/Unity.qmltypes 2014-08-06 14:50:38 +0000
@@ -24,6 +24,12 @@
24 Parameter { name: "categoryId"; type: "string" }24 Parameter { name: "categoryId"; type: "string" }
25 Parameter { name: "json"; type: "string" }25 Parameter { name: "json"; type: "string" }
26 }26 }
27 Method {
28 name: "data"
29 type: "QVariant"
30 Parameter { name: "row"; type: "int" }
31 Parameter { name: "role"; type: "int" }
32 }
27 }33 }
28 Component {34 Component {
29 name: "PreviewModel"35 name: "PreviewModel"
@@ -62,6 +68,10 @@
62 prototype: "unity::shell::scopes::ScopeInterface"68 prototype: "unity::shell::scopes::ScopeInterface"
63 exports: ["Unity/MockScope 0.2"]69 exports: ["Unity/MockScope 0.2"]
64 exportMetaObjectRevisions: [0]70 exportMetaObjectRevisions: [0]
71 Signal {
72 name: "performQuery"
73 Parameter { name: "query"; type: "string" }
74 }
65 Method {75 Method {
66 name: "setSearchInProgress"76 name: "setSearchInProgress"
67 Parameter { name: "inProg"; type: "bool" }77 Parameter { name: "inProg"; type: "bool" }
@@ -81,18 +91,21 @@
81 Parameter { name: "scope"; type: "unity::shell::scopes::ScopeInterface"; isPointer: true }91 Parameter { name: "scope"; type: "unity::shell::scopes::ScopeInterface"; isPointer: true }
82 }92 }
83 Method {93 Method {
84 name: "getDepartment"94 name: "getNavigation"
85 type: "unity::shell::scopes::DepartmentInterface*"95 type: "unity::shell::scopes::NavigationInterface*"
86 Parameter { name: "id"; type: "string" }96 Parameter { name: "navigationId"; type: "string" }
87 }97 }
88 Method {98 Method {
89 name: "loadDepartment"99 name: "getAltNavigation"
90 Parameter { name: "id"; type: "string" }100 type: "unity::shell::scopes::NavigationInterface*"
91 }101 Parameter { name: "altNavigationId"; type: "string" }
92 Method {102 }
93 name: "performQuery"103 Method {
94 Parameter { name: "query"; type: "string" }104 name: "setNavigationState"
95 }105 Parameter { name: "navigationId"; type: "string" }
106 Parameter { name: "isAltNavigation"; type: "bool" }
107 }
108 Method { name: "refresh" }
96 }109 }
97 Component {110 Component {
98 name: "Scopes"111 name: "Scopes"
@@ -137,6 +150,7 @@
137 "RoleRawRendererTemplate": 3,150 "RoleRawRendererTemplate": 3,
138 "RoleRenderer": 4,151 "RoleRenderer": 4,
139 "RoleComponents": 5,152 "RoleComponents": 5,
153 "RoleHeaderLink": 6,
140 "RoleResults": 7,154 "RoleResults": 7,
141 "RoleCount": 8155 "RoleCount": 8
142 }156 }
@@ -157,27 +171,28 @@
157 }171 }
158 }172 }
159 Component {173 Component {
160 name: "unity::shell::scopes::DepartmentInterface"174 name: "unity::shell::scopes::NavigationInterface"
161 prototype: "QAbstractListModel"175 prototype: "QAbstractListModel"
162 exports: ["Unity/Department 0.2"]176 exports: ["Unity/Navigation 0.2"]
163 isCreatable: false177 isCreatable: false
164 exportMetaObjectRevisions: [0]178 exportMetaObjectRevisions: [0]
165 Enum {179 Enum {
166 name: "Roles"180 name: "Roles"
167 values: {181 values: {
168 "RoleDepartmentId": 0,182 "RoleNavigationId": 0,
169 "RoleLabel": 1,183 "RoleLabel": 1,
170 "RoleHasChildren": 2,184 "RoleHasChildren": 2,
171 "RoleIsActive": 3185 "RoleIsActive": 3
172 }186 }
173 }187 }
174 Property { name: "departmentId"; type: "string"; isReadonly: true }188 Property { name: "navigationId"; type: "string"; isReadonly: true }
175 Property { name: "label"; type: "string"; isReadonly: true }189 Property { name: "label"; type: "string"; isReadonly: true }
176 Property { name: "allLabel"; type: "string"; isReadonly: true }190 Property { name: "allLabel"; type: "string"; isReadonly: true }
177 Property { name: "parentDepartmentId"; type: "string"; isReadonly: true }191 Property { name: "parentNavigationId"; type: "string"; isReadonly: true }
178 Property { name: "parentLabel"; type: "string"; isReadonly: true }192 Property { name: "parentLabel"; type: "string"; isReadonly: true }
179 Property { name: "loaded"; type: "bool"; isReadonly: true }193 Property { name: "loaded"; type: "bool"; isReadonly: true }
180 Property { name: "isRoot"; type: "bool"; isReadonly: true }194 Property { name: "isRoot"; type: "bool"; isReadonly: true }
195 Property { name: "hidden"; type: "bool"; isReadonly: true }
181 Property { name: "count"; type: "int"; isReadonly: true }196 Property { name: "count"; type: "int"; isReadonly: true }
182 }197 }
183 Component {198 Component {
@@ -247,7 +262,8 @@
247 "RoleEmblem": 8,262 "RoleEmblem": 8,
248 "RoleSummary": 9,263 "RoleSummary": 9,
249 "RoleAttributes": 10,264 "RoleAttributes": 10,
250 "RoleBackground": 11265 "RoleBackground": 11,
266 "RoleOverlayColor": 12
251 }267 }
252 }268 }
253 Property { name: "categoryId"; type: "string" }269 Property { name: "categoryId"; type: "string" }
@@ -259,13 +275,22 @@
259 exports: ["Unity/Scope 0.2"]275 exports: ["Unity/Scope 0.2"]
260 isCreatable: false276 isCreatable: false
261 exportMetaObjectRevisions: [0]277 exportMetaObjectRevisions: [0]
278 Enum {
279 name: "Status"
280 values: {
281 "Okay": 0,
282 "NoInternet": 1,
283 "NoLocationData": 2,
284 "Unknown": 3
285 }
286 }
262 Property { name: "id"; type: "string"; isReadonly: true }287 Property { name: "id"; type: "string"; isReadonly: true }
263 Property { name: "name"; type: "string"; isReadonly: true }288 Property { name: "name"; type: "string"; isReadonly: true }
264 Property { name: "iconHint"; type: "string"; isReadonly: true }289 Property { name: "iconHint"; type: "string"; isReadonly: true }
265 Property { name: "description"; type: "string"; isReadonly: true }290 Property { name: "description"; type: "string"; isReadonly: true }
266 Property { name: "searchHint"; type: "string"; isReadonly: true }291 Property { name: "searchHint"; type: "string"; isReadonly: true }
267 Property { name: "searchInProgress"; type: "bool"; isReadonly: true }292 Property { name: "searchInProgress"; type: "bool"; isReadonly: true }
268 Property { name: "visible"; type: "bool"; isReadonly: true }293 Property { name: "favorite"; type: "bool" }
269 Property { name: "shortcut"; type: "string"; isReadonly: true }294 Property { name: "shortcut"; type: "string"; isReadonly: true }
270 Property {295 Property {
271 name: "categories"296 name: "categories"
@@ -273,13 +298,27 @@
273 isReadonly: true298 isReadonly: true
274 isPointer: true299 isPointer: true
275 }300 }
301 Property {
302 name: "settings"
303 type: "unity::shell::scopes::SettingsModelInterface"
304 isReadonly: true
305 isPointer: true
306 }
276 Property { name: "searchQuery"; type: "string" }307 Property { name: "searchQuery"; type: "string" }
277 Property { name: "noResultsHint"; type: "string" }308 Property { name: "noResultsHint"; type: "string" }
278 Property { name: "formFactor"; type: "string" }309 Property { name: "formFactor"; type: "string" }
279 Property { name: "isActive"; type: "bool" }310 Property { name: "isActive"; type: "bool" }
280 Property { name: "currentDepartmentId"; type: "string"; isReadonly: true }311 Property { name: "currentNavigationId"; type: "string"; isReadonly: true }
281 Property { name: "hasDepartments"; type: "bool"; isReadonly: true }312 Property { name: "hasNavigation"; type: "bool"; isReadonly: true }
313 Property { name: "currentAltNavigationId"; type: "string"; isReadonly: true }
314 Property { name: "hasAltNavigation"; type: "bool"; isReadonly: true }
282 Property { name: "customizations"; type: "QVariantMap"; isReadonly: true }315 Property { name: "customizations"; type: "QVariantMap"; isReadonly: true }
316 Property {
317 name: "status"
318 type: "unity::shell::scopes::ScopeInterface::Status"
319 isReadonly: true
320 }
321 Signal { name: "detailsChanged" }
283 Signal { name: "showDash" }322 Signal { name: "showDash" }
284 Signal { name: "hideDash" }323 Signal { name: "hideDash" }
285 Signal {324 Signal {
@@ -298,10 +337,6 @@
298 name: "openScope"337 name: "openScope"
299 Parameter { name: "scope"; type: "unity::shell::scopes::ScopeInterface"; isPointer: true }338 Parameter { name: "scope"; type: "unity::shell::scopes::ScopeInterface"; isPointer: true }
300 }339 }
301 Signal {
302 name: "activateApplication"
303 Parameter { name: "desktop"; type: "string" }
304 }
305 Method {340 Method {
306 name: "activate"341 name: "activate"
307 Parameter { name: "result"; type: "QVariant" }342 Parameter { name: "result"; type: "QVariant" }
@@ -317,14 +352,25 @@
317 Parameter { name: "scope"; type: "unity::shell::scopes::ScopeInterface"; isPointer: true }352 Parameter { name: "scope"; type: "unity::shell::scopes::ScopeInterface"; isPointer: true }
318 }353 }
319 Method {354 Method {
320 name: "getDepartment"355 name: "getNavigation"
321 type: "unity::shell::scopes::DepartmentInterface*"356 type: "unity::shell::scopes::NavigationInterface*"
322 Parameter { name: "departmentId"; type: "string" }357 Parameter { name: "navigationId"; type: "string" }
323 }358 }
324 Method {359 Method {
325 name: "loadDepartment"360 name: "getAltNavigation"
326 Parameter { name: "departmentId"; type: "string" }361 type: "unity::shell::scopes::NavigationInterface*"
327 }362 Parameter { name: "altNavigationId"; type: "string" }
363 }
364 Method {
365 name: "setNavigationState"
366 Parameter { name: "navId"; type: "string" }
367 Parameter { name: "altNavigation"; type: "bool" }
368 }
369 Method {
370 name: "performQuery"
371 Parameter { name: "cannedQuery"; type: "string" }
372 }
373 Method { name: "refresh" }
328 }374 }
329 Component {375 Component {
330 name: "unity::shell::scopes::ScopesInterface"376 name: "unity::shell::scopes::ScopesInterface"
@@ -334,11 +380,17 @@
334 values: {380 values: {
335 "RoleScope": 0,381 "RoleScope": 0,
336 "RoleId": 1,382 "RoleId": 1,
337 "RoleVisible": 2,383 "RoleTitle": 2
338 "RoleTitle": 3
339 }384 }
340 }385 }
341 Property { name: "loaded"; type: "bool"; isReadonly: true }386 Property { name: "loaded"; type: "bool"; isReadonly: true }
387 Property { name: "count"; type: "int"; isReadonly: true }
388 Property {
389 name: "overviewScope"
390 type: "unity::shell::scopes::ScopeInterface"
391 isReadonly: true
392 isPointer: true
393 }
342 Method {394 Method {
343 name: "getScope"395 name: "getScope"
344 type: "unity::shell::scopes::ScopeInterface*"396 type: "unity::shell::scopes::ScopeInterface*"
345397
=== renamed file 'tests/mocks/Unity/fake_department.cpp' => 'tests/mocks/Unity/fake_navigation.cpp'
--- tests/mocks/Unity/fake_department.cpp 2014-06-18 13:48:32 +0000
+++ tests/mocks/Unity/fake_navigation.cpp 2014-08-06 14:50:38 +0000
@@ -14,14 +14,15 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */15 */
1616
17#include "fake_department.h"17#include "fake_navigation.h"
1818
19#include "fake_scope.h"19#include "fake_scope.h"
2020
21#include <QDebug>
21#include <QTimer>22#include <QTimer>
2223
23Department::Department(const QString& departmentId, const QString& label, const QString& allLabel, const QString& parentId, const QString& parentLabel, Scope* scope)24Navigation::Navigation(const QString& navigationId, const QString& label, const QString& allLabel, const QString& parentId, const QString& parentLabel, Scope* scope)
24 : m_departmentId(departmentId)25 : m_navigationId(navigationId)
25 , m_label(label)26 , m_label(label)
26 , m_allLabel(allLabel)27 , m_allLabel(allLabel)
27 , m_parentId(parentId)28 , m_parentId(parentId)
@@ -30,96 +31,87 @@
30 , m_scope(scope)31 , m_scope(scope)
31{32{
32 QTimer::singleShot(1500, this, SLOT(slotLoaded()));33 QTimer::singleShot(1500, this, SLOT(slotLoaded()));
33 connect(scope, SIGNAL(currentDepartmentIdChanged()), this, SLOT(slotCurrentDepartmentChanged()));34 connect(scope, SIGNAL(currentNavigationIdChanged()), this, SLOT(slotCurrentNavigationChanged()));
34}35}
3536
36QString Department::departmentId() const37QString Navigation::navigationId() const
37{38{
38 return m_departmentId;39 return m_navigationId;
39}40}
4041
41QString Department::label() const42QString Navigation::label() const
42{43{
43 return m_label;44 return m_label;
44}45}
4546
46QString Department::allLabel() const47QString Navigation::allLabel() const
47{48{
48 return m_allLabel;49 return m_allLabel;
49}50}
5051
51QString Department::parentDepartmentId() const52QString Navigation::parentNavigationId() const
52{53{
53 return m_parentId;54 return m_parentId;
54}55}
5556
56QString Department::parentLabel() const57QString Navigation::parentLabel() const
57{58{
58 return m_parentLabel;59 return m_parentLabel;
59}60}
6061
61void Department::slotLoaded()62void Navigation::slotLoaded()
62{63{
63 m_loaded = true;64 m_loaded = true;
64 Q_EMIT loadedChanged();65 Q_EMIT loadedChanged();
65}66}
6667
67bool Department::loaded() const68bool Navigation::loaded() const
68{69{
69 return m_loaded;70 return m_loaded;
70}71}
7172
72int Department::count() const73int Navigation::count() const
73{74{
74 return rowCount();75 return rowCount();
75}76}
7677
77bool Department::isRoot() const78bool Navigation::isRoot() const
78{79{
79 return m_departmentId == "root";80 return m_navigationId == "root" || m_navigationId == "altroot";
80}81}
8182
82int Department::rowCount(const QModelIndex & /*parent*/) const83bool Navigation::hidden() const
83{84{
84 if (!m_loaded || m_departmentId.startsWith("child") || m_departmentId == "middle3")85 return m_navigationId == "altroot";
86}
87
88int Navigation::rowCount(const QModelIndex & /*parent*/) const
89{
90 if (!m_loaded || m_navigationId.startsWith("child") || m_navigationId == "middle3")
85 return 0;91 return 0;
86 else92 else
87 return 8;93 return 8;
88}94}
8995
90QHash<int, QByteArray> Department::roleNames() const96QVariant Navigation::data(const QModelIndex &index, int role) const
91{
92 QHash<int, QByteArray> res;
93 res[RoleDepartmentId] = "departmentId";
94 res[RoleLabel] = "label";
95 res[RoleHasChildren] = "hasChildren";
96 res[RoleIsActive] = "isActive";
97 return res;
98}
99
100QVariant Department::data(const QModelIndex &index, int role) const
101{97{
102 switch (role) {98 switch (role) {
103 case RoleDepartmentId:99 case RoleNavigationId:
104 if (m_departmentId == "root")100 if (m_navigationId == "root")
105 return QString("middle%1").arg(index.row());101 return QString("middle%1").arg(index.row());
106 else if (m_departmentId.startsWith("middle"))102 else if (m_navigationId.startsWith("middle"))
107 return QString("child%1%2").arg(m_departmentId).arg(index.row());103 return QString("child%1%2").arg(m_navigationId).arg(index.row());
108 break;
109 case RoleLabel:104 case RoleLabel:
110 return QString("%1Child%2").arg(m_departmentId).arg(index.row());105 return QString("%1Child%2").arg(m_navigationId).arg(index.row());
111 break;
112 case RoleHasChildren:106 case RoleHasChildren:
113 return m_departmentId == "root" && index.row() != 3;107 return m_navigationId == "root" && index.row() != 3;
114 break;
115 case RoleIsActive:108 case RoleIsActive:
116 return m_scope->currentDepartmentId() == data(index, RoleDepartmentId);109 return m_scope->currentNavigationId() == data(index, RoleNavigationId);
117 break;
118 }110 }
119 return QVariant();111 return QVariant();
120}112}
121113
122void Department::slotCurrentDepartmentChanged()114void Navigation::slotCurrentNavigationChanged()
123{115{
124 // This is wasteful, should only emit it if really something changed in this116 // This is wasteful, should only emit it if really something changed in this
125 // deparment, but this is a mock, so no need to optimize117 // deparment, but this is a mock, so no need to optimize
126118
=== renamed file 'tests/mocks/Unity/fake_department.h' => 'tests/mocks/Unity/fake_navigation.h'
--- tests/mocks/Unity/fake_department.h 2014-05-29 10:25:21 +0000
+++ tests/mocks/Unity/fake_navigation.h 2014-08-06 14:50:38 +0000
@@ -14,48 +14,48 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */15 */
1616
17#ifndef FAKE_DEPARTMENT_H17#ifndef FAKE_NAVIGATION_H
18#define FAKE_DEPARTMENT_H18#define FAKE_NAVIGATION_H
1919
20#include <unity/shell/scopes/DepartmentInterface.h>20#include <unity/shell/scopes/NavigationInterface.h>
2121
22class Scope;22class Scope;
2323
24class Department : public unity::shell::scopes::DepartmentInterface24class Navigation : public unity::shell::scopes::NavigationInterface
25{25{
26 Q_OBJECT26 Q_OBJECT
2727
28public:28public:
29 Department(const QString& departmentId, const QString& label, const QString& allLabel, const QString& parentId, const QString& parentLabel, Scope* scope);29 Navigation(const QString& navigationId, const QString& label, const QString& allLabel, const QString& parentId, const QString& parentLabel, Scope* scope);
3030
31 QString departmentId() const override;31 QString navigationId() const override;
32 QString label() const override;32 QString label() const override;
33 QString allLabel() const override;33 QString allLabel() const override;
34 QString parentDepartmentId() const override;34 QString parentNavigationId() const override;
35 QString parentLabel() const override;35 QString parentLabel() const override;
36 bool loaded() const override;36 bool loaded() const override;
37 bool isRoot() const override;
38 bool hidden() const override;
37 int count() const override;39 int count() const override;
38 bool isRoot() const override;
3940
40 int rowCount(const QModelIndex &parent = QModelIndex()) const override;41 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
41 QHash<int, QByteArray> roleNames() const;
42 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;42 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
4343
44public Q_SLOTS:44public Q_SLOTS:
45 void slotCurrentDepartmentChanged();45 void slotCurrentNavigationChanged();
4646
47private Q_SLOTS:47private Q_SLOTS:
48 void slotLoaded();48 void slotLoaded();
4949
50private:50private:
51 QString m_departmentId;51 QString m_navigationId;
52 QString m_label;52 QString m_label;
53 QString m_allLabel;53 QString m_allLabel;
54 QString m_parentId;54 QString m_parentId;
55 QString m_parentLabel;55 QString m_parentLabel;
56 bool m_loaded;56 bool m_loaded;
57 QString m_currentDepartment;57 QString m_currentNavigation;
58 Scope *m_scope;58 Scope *m_scope;
59};59};
6060
61#endif // FAKE_DEPARTMENT_H61#endif // FAKE_NAVIGATION_H
6262
=== modified file 'tests/mocks/Unity/fake_scope.cpp'
--- tests/mocks/Unity/fake_scope.cpp 2014-07-24 20:40:57 +0000
+++ tests/mocks/Unity/fake_scope.cpp 2014-08-06 14:50:38 +0000
@@ -14,24 +14,26 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */15 */
1616
17#include <QDebug>
17#include <QUrl>18#include <QUrl>
1819
19#include "fake_scope.h"20#include "fake_scope.h"
20#include "fake_department.h"21#include "fake_navigation.h"
21#include "fake_resultsmodel.h"22#include "fake_resultsmodel.h"
2223
23Scope::Scope(QObject* parent) : Scope(QString(), QString(), false, parent)24Scope::Scope(QObject* parent) : Scope(QString(), QString(), false, parent)
24{25{
25}26}
2627
27Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent, int categories)28Scope::Scope(QString const& id, QString const& name, bool favorite, QObject* parent, int categories)
28 : unity::shell::scopes::ScopeInterface(parent)29 : unity::shell::scopes::ScopeInterface(parent)
29 , m_id(id)30 , m_id(id)
30 , m_name(name)31 , m_name(name)
31 , m_visible(visible)
32 , m_searching(false)32 , m_searching(false)
33 , m_favorite(favorite)
33 , m_isActive(false)34 , m_isActive(false)
34 , m_currentDeparment("root")35 , m_currentNavigationId("root")
36 , m_currentAltNavigationId("altroot")
35 , m_previewRendererName("preview-generic")37 , m_previewRendererName("preview-generic")
36 , m_categories(new Categories(categories, this))38 , m_categories(new Categories(categories, this))
37{39{
@@ -77,6 +79,11 @@
77 return m_searching;79 return m_searching;
78}80}
7981
82bool Scope::favorite() const
83{
84 return m_favorite;
85}
86
80unity::shell::scopes::CategoriesInterface* Scope::categories() const87unity::shell::scopes::CategoriesInterface* Scope::categories() const
81{88{
82 return m_categories;89 return m_categories;
@@ -97,11 +104,6 @@
97 return m_formFactor;104 return m_formFactor;
98}105}
99106
100bool Scope::visible() const
101{
102 return m_visible;
103}
104
105bool Scope::isActive() const107bool Scope::isActive() const
106{108{
107 return m_isActive;109 return m_isActive;
@@ -131,6 +133,13 @@
131 }133 }
132}134}
133135
136void Scope::setFavorite(const bool favorite)
137{
138 if (favorite != m_favorite) {
139 m_favorite = favorite;
140 Q_EMIT favoriteChanged();
141 }
142}
134void Scope::setSearchInProgress(const bool inProg)143void Scope::setSearchInProgress(const bool inProg)
135{144{
136 if (inProg != m_searching) {145 if (inProg != m_searching) {
@@ -170,14 +179,29 @@
170 qFatal("Scope::closeScope is not implemented");179 qFatal("Scope::closeScope is not implemented");
171}180}
172181
173QString Scope::currentDepartmentId() const182QString Scope::currentNavigationId() const
174{183{
175 return m_currentDeparment;184 return m_currentNavigationId;
176}185}
177186
178bool Scope::hasDepartments() const187bool Scope::hasNavigation() const
179{188{
180 return true;189 return true;
190}
191
192QString Scope::currentAltNavigationId() const
193{
194 return m_currentAltNavigationId;
195}
196
197bool Scope::hasAltNavigation() const
198{
199 return true;
200}
201
202Scope::Status Scope::status() const
203{
204 return Status::Okay;
181}205}
182206
183QVariantMap Scope::customizations() const207QVariantMap Scope::customizations() const
@@ -196,7 +220,12 @@
196 return m;220 return m;
197}221}
198222
199unity::shell::scopes::DepartmentInterface* Scope::getDepartment(const QString& id)223void Scope::refresh()
224{
225 qDebug() << "Scope::refresh is currently not implmented in the fake scopes plugin";
226}
227
228unity::shell::scopes::NavigationInterface* Scope::getNavigation(const QString& id)
200{229{
201 if (id.isEmpty())230 if (id.isEmpty())
202 return nullptr;231 return nullptr;
@@ -210,11 +239,30 @@
210 parentId = id.mid(5, 7);239 parentId = id.mid(5, 7);
211 parentLabel = parentId;240 parentLabel = parentId;
212 }241 }
213 return new Department(id, id, "all"+id, parentId, parentLabel, this);242 return new Navigation(id, id, "all"+id, parentId, parentLabel, this);
214}243}
215244
216void Scope::loadDepartment(const QString& id)245unity::shell::scopes::NavigationInterface* Scope::getAltNavigation(QString const& id)
217{246{
218 m_currentDeparment = id;247 if (id.isEmpty())
219 Q_EMIT currentDepartmentIdChanged();248 return nullptr;
249
250 QString parentId;
251 QString parentLabel;
252 if (id.startsWith("altmiddle")) {
253 parentId = "altroot";
254 parentLabel = "altroot";
255 }
256 return new Navigation(id, id, "all"+id, parentId, parentLabel, this);
257}
258
259void Scope::setNavigationState(const QString &navigationId, bool isAltNavigation)
260{
261 if (isAltNavigation) {
262 m_currentAltNavigationId = navigationId;
263 Q_EMIT currentAltNavigationIdChanged();
264 } else {
265 m_currentNavigationId = navigationId;
266 Q_EMIT currentNavigationIdChanged();
267 }
220}268}
221269
=== modified file 'tests/mocks/Unity/fake_scope.h'
--- tests/mocks/Unity/fake_scope.h 2014-07-11 16:39:33 +0000
+++ tests/mocks/Unity/fake_scope.h 2014-08-06 14:50:38 +0000
@@ -30,7 +30,7 @@
3030
31public:31public:
32 Scope(QObject* parent = 0);32 Scope(QObject* parent = 0);
33 Scope(QString const& id, QString const& name, bool visible, QObject* parent = 0, int categories = 20);33 Scope(QString const& id, QString const& name, bool favorite, QObject* parent = 0, int categories = 20);
3434
35 /* getters */35 /* getters */
36 QString id() const override;36 QString id() const override;
@@ -38,9 +38,9 @@
38 QString iconHint() const override;38 QString iconHint() const override;
39 QString description() const override;39 QString description() const override;
40 QString searchHint() const override;40 QString searchHint() const override;
41 bool visible() const override;
42 QString shortcut() const override;41 QString shortcut() const override;
43 bool searchInProgress() const override;42 bool searchInProgress() const override;
43 bool favorite() const override;
44 unity::shell::scopes::CategoriesInterface* categories() const override;44 unity::shell::scopes::CategoriesInterface* categories() const override;
45 QString searchQuery() const override;45 QString searchQuery() const override;
46 QString noResultsHint() const override;46 QString noResultsHint() const override;
@@ -53,6 +53,7 @@
53 void setNoResultsHint(const QString& hint) override;53 void setNoResultsHint(const QString& hint) override;
54 void setFormFactor(const QString& form_factor) override;54 void setFormFactor(const QString& form_factor) override;
55 void setActive(const bool) override;55 void setActive(const bool) override;
56 void setFavorite(const bool) override;
56 Q_INVOKABLE void setSearchInProgress(const bool inProg); // This is not invokable in the Interface, here for testing benefits57 Q_INVOKABLE void setSearchInProgress(const bool inProg); // This is not invokable in the Interface, here for testing benefits
5758
58 Q_INVOKABLE void activate(QVariant const& result) override;59 Q_INVOKABLE void activate(QVariant const& result) override;
@@ -60,14 +61,20 @@
60 Q_INVOKABLE void cancelActivation() override;61 Q_INVOKABLE void cancelActivation() override;
61 Q_INVOKABLE void closeScope(unity::shell::scopes::ScopeInterface* scope) override;62 Q_INVOKABLE void closeScope(unity::shell::scopes::ScopeInterface* scope) override;
6263
63 QString currentDepartmentId() const override;64 QString currentNavigationId() const override;
64 bool hasDepartments() const override;65 bool hasNavigation() const override;
65 Q_INVOKABLE unity::shell::scopes::DepartmentInterface* getDepartment(const QString& id) override;66 QString currentAltNavigationId() const override;
66 Q_INVOKABLE void loadDepartment(const QString& id) override;67 bool hasAltNavigation() const override;
68 Q_INVOKABLE unity::shell::scopes::NavigationInterface* getNavigation(QString const& navigationId) override;
69 Q_INVOKABLE unity::shell::scopes::NavigationInterface* getAltNavigation(QString const& altNavigationId) override;
70 Q_INVOKABLE void setNavigationState(const QString &navigationId, bool isAltNavigation) override;
67 Q_SIGNAL void performQuery(const QString& query) override;71 Q_SIGNAL void performQuery(const QString& query) override;
6872
73 Status status() const override;
69 QVariantMap customizations() const override;74 QVariantMap customizations() const override;
7075
76 Q_INVOKABLE void refresh() override;
77
71protected:78protected:
7279
73 QString m_id;80 QString m_id;
@@ -77,10 +84,11 @@
77 QString m_searchQuery;84 QString m_searchQuery;
78 QString m_noResultsHint;85 QString m_noResultsHint;
79 QString m_formFactor;86 QString m_formFactor;
80 bool m_visible;
81 bool m_searching;87 bool m_searching;
88 bool m_favorite;
82 bool m_isActive;89 bool m_isActive;
83 QString m_currentDeparment;90 QString m_currentNavigationId;
91 QString m_currentAltNavigationId;
8492
85 QString m_previewRendererName;93 QString m_previewRendererName;
8694
8795
=== modified file 'tests/mocks/Unity/fake_scopes.cpp'
--- tests/mocks/Unity/fake_scopes.cpp 2014-07-25 13:25:45 +0000
+++ tests/mocks/Unity/fake_scopes.cpp 2014-08-06 14:50:38 +0000
@@ -32,6 +32,11 @@
32 timer.setSingleShot(true);32 timer.setSingleShot(true);
33 timer.setInterval(100);33 timer.setInterval(100);
34 QObject::connect(&timer, SIGNAL(timeout()), this, SLOT(updateScopes()));34 QObject::connect(&timer, SIGNAL(timeout()), this, SLOT(updateScopes()));
35
36 QObject::connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
37 QObject::connect(this, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SIGNAL(countChanged()));
38 QObject::connect(this, SIGNAL(modelReset()), this, SIGNAL(countChanged()));
39
35 load();40 load();
36}41}
3742
@@ -92,8 +97,6 @@
92 return QVariant::fromValue(scope);97 return QVariant::fromValue(scope);
93 } else if (role == Scopes::RoleId) {98 } else if (role == Scopes::RoleId) {
94 return QVariant::fromValue(scope->id());99 return QVariant::fromValue(scope->id());
95 } else if (role == Scopes::RoleVisible) {
96 return QVariant::fromValue(scope->visible());
97 } else if (role == Scopes::RoleTitle) {100 } else if (role == Scopes::RoleTitle) {
98 return QVariant::fromValue(scope->name());101 return QVariant::fromValue(scope->name());
99 } else {102 } else {
@@ -125,6 +128,11 @@
125 return m_loaded;128 return m_loaded;
126}129}
127130
131int Scopes::count() const
132{
133 return rowCount();
134}
135
128unity::shell::scopes::ScopeInterface* Scopes::overviewScope() const136unity::shell::scopes::ScopeInterface* Scopes::overviewScope() const
129{137{
130 return nullptr;138 return nullptr;
131139
=== modified file 'tests/mocks/Unity/fake_scopes.h'
--- tests/mocks/Unity/fake_scopes.h 2014-07-25 13:25:45 +0000
+++ tests/mocks/Unity/fake_scopes.h 2014-08-06 14:50:38 +0000
@@ -50,6 +50,7 @@
50 QModelIndex parent ( const QModelIndex & index ) const;50 QModelIndex parent ( const QModelIndex & index ) const;
5151
52 bool loaded() const override;52 bool loaded() const override;
53 int count() const override;
53 unity::shell::scopes::ScopeInterface* overviewScope() const override;54 unity::shell::scopes::ScopeInterface* overviewScope() const override;
5455
55private Q_SLOTS:56private Q_SLOTS:
5657
=== modified file 'tests/mocks/Unity/fake_unity_plugin.cpp'
--- tests/mocks/Unity/fake_unity_plugin.cpp 2014-07-08 11:26:44 +0000
+++ tests/mocks/Unity/fake_unity_plugin.cpp 2014-08-06 14:50:38 +0000
@@ -22,7 +22,7 @@
22// local22// local
23#include "fake_scopes.h"23#include "fake_scopes.h"
24#include "fake_categories.h"24#include "fake_categories.h"
25#include "fake_department.h"25#include "fake_navigation.h"
26#include "fake_previewmodel.h"26#include "fake_previewmodel.h"
27#include "fake_previewwidgetmodel.h"27#include "fake_previewwidgetmodel.h"
28#include "fake_resultsmodel.h"28#include "fake_resultsmodel.h"
@@ -43,7 +43,7 @@
43 qmlRegisterType<Scopes>(uri, 0, 2, "Scopes");43 qmlRegisterType<Scopes>(uri, 0, 2, "Scopes");
44 qmlRegisterType<Scope>(uri, 0, 2, "MockScope");44 qmlRegisterType<Scope>(uri, 0, 2, "MockScope");
45 qmlRegisterUncreatableType<unity::shell::scopes::ScopeInterface>(uri, 0, 2, "Scope", "Can't create Scope object in QML.");45 qmlRegisterUncreatableType<unity::shell::scopes::ScopeInterface>(uri, 0, 2, "Scope", "Can't create Scope object in QML.");
46 qmlRegisterUncreatableType<unity::shell::scopes::DepartmentInterface>(uri, 0, 2, "Department", "Can't create Department object in QML.");46 qmlRegisterUncreatableType<unity::shell::scopes::NavigationInterface>(uri, 0, 2, "Navigation", "Can't create Navigation object in QML.");
47 qmlRegisterUncreatableType<unity::shell::scopes::CategoriesInterface>(uri, 0, 2, "Categories", "Can't create Categories object in QML.");47 qmlRegisterUncreatableType<unity::shell::scopes::CategoriesInterface>(uri, 0, 2, "Categories", "Can't create Categories object in QML.");
48 qmlRegisterUncreatableType<unity::shell::scopes::PreviewModelInterface>(uri, 0, 2, "PreviewModel", "Can't create new PreviewModel in QML. Get them from PreviewStack instance.");48 qmlRegisterUncreatableType<unity::shell::scopes::PreviewModelInterface>(uri, 0, 2, "PreviewModel", "Can't create new PreviewModel in QML. Get them from PreviewStack instance.");
49 qmlRegisterUncreatableType<ResultsModel>(uri, 0, 2, "ResultsModel", "Can't create ResultsModel object in QML.");49 qmlRegisterUncreatableType<ResultsModel>(uri, 0, 2, "ResultsModel", "Can't create ResultsModel object in QML.");
5050
=== modified file 'tests/plugins/Dash/tst_ScopeStyle.qml'
--- tests/plugins/Dash/tst_ScopeStyle.qml 2014-07-19 07:56:55 +0000
+++ tests/plugins/Dash/tst_ScopeStyle.qml 2014-08-06 14:50:38 +0000
@@ -54,6 +54,9 @@
54 { tag: "lightgrey", luminance: 0.8275 },54 { tag: "lightgrey", luminance: 0.8275 },
55 { tag: "grey", luminance: 0.5020 },55 { tag: "grey", luminance: 0.5020 },
56 { tag: "darkgrey", luminance: 0.6627 },56 { tag: "darkgrey", luminance: 0.6627 },
57 { tag: "red", luminance: 0.2126 },
58 { tag: "green", luminance: 0.3590 },
59 { tag: "blue", luminance: 0.0722 },
57 ];60 ];
58 }61 }
5962
@@ -64,10 +67,10 @@
6467
65 function test_foreground_data() {68 function test_foreground_data() {
66 return [69 return [
67 { tag: "default", index: 0, foreground: "grey" },70 { tag: "default", index: 0, foreground: "grey", luminance: 0.5020 },
68 { tag: "red on black", index: 1, foreground: "red" },71 { tag: "red on black", index: 1, foreground: "red", luminance: 0.2126 },
69 { tag: "green on white", index: 2, foreground: "green" },72 { tag: "green on white", index: 2, foreground: "green", luminance: 0.3590 },
70 { tag: "blue on darkgrey", index: 3, foreground: "blue" },73 { tag: "blue on darkgrey", index: 3, foreground: "blue", luminance: 0.0722 },
71 ];74 ];
72 }75 }
7376
@@ -75,14 +78,15 @@
75 tool.style = testCase.styles[data.index];78 tool.style = testCase.styles[data.index];
76 verify(Qt.colorEqual(tool.foreground, data.foreground),79 verify(Qt.colorEqual(tool.foreground, data.foreground),
77 "Foreground color not equal: %1 != %2".arg(tool.foreground).arg(data.foreground));80 "Foreground color not equal: %1 != %2".arg(tool.foreground).arg(data.foreground));
81 compare(tool.foregroundLuminance.toFixed(4), data.luminance.toFixed(4));
78 }82 }
7983
80 function test_background_data() {84 function test_background_data() {
81 return [85 return [
82 { tag: "default", index: 0, background: "transparent" },86 { tag: "default", index: 0, background: "transparent" },
83 { tag: "red on black", index: 1, background: "black" },87 { tag: "red on black", index: 1, background: "black", luminance: 0 },
84 { tag: "green on white", index: 2, background: "white" },88 { tag: "green on white", index: 2, background: "white", luminance: 1 },
85 { tag: "blue on darkgrey", index: 3, background: "darkgrey" },89 { tag: "blue on darkgrey", index: 3, background: "darkgrey", luminance: 0.6627 },
86 ];90 ];
87 }91 }
8892
@@ -90,6 +94,9 @@
90 tool.style = testCase.styles[data.index];94 tool.style = testCase.styles[data.index];
91 verify(Qt.colorEqual(tool.background, data.background),95 verify(Qt.colorEqual(tool.background, data.background),
92 "Background color not equal: %1 != %2".arg(tool.background).arg(data.background));96 "Background color not equal: %1 != %2".arg(tool.background).arg(data.background));
97 if (data.hasOwnProperty("luminance")) {
98 compare(tool.backgroundLuminance.toFixed(4), data.luminance.toFixed(4));
99 }
93 }100 }
94101
95 function test_threshold_data() {102 function test_threshold_data() {
96103
=== modified file 'tests/qmltests/Components/tst_PageHeader.qml'
--- tests/qmltests/Components/tst_PageHeader.qml 2014-07-28 09:14:23 +0000
+++ tests/qmltests/Components/tst_PageHeader.qml 2014-08-06 14:50:38 +0000
@@ -119,29 +119,6 @@
119 compare(pageHeader.searchHistory.get(0).query, "humppa4")119 compare(pageHeader.searchHistory.get(0).query, "humppa4")
120 }120 }
121121
122 function test_search_indicator() {
123 var searchIndicator = findChild(pageHeader, "searchIndicator")
124 var clearIcon = findChild(pageHeader, "clearIcon")
125
126 pageHeader.triggerSearch()
127
128 tryCompare(clearIcon, "visible", false)
129 pageHeader.searchQuery = "ubuntu"
130 tryCompare(clearIcon, "visible", true)
131
132 pageHeader.searchInProgress = false
133 compare(searchIndicator.running, false, "Search indicator is running.")
134 tryCompare(clearIcon, "visible", true)
135
136 pageHeader.searchInProgress = true
137 compare(searchIndicator.running, true, "Search indicator isn't running.")
138 tryCompare(clearIcon, "visible", false)
139
140 pageHeader.searchInProgress = false;
141 compare(searchIndicator.running, false, "Search indicator is running.")
142 tryCompare(clearIcon, "visible", true)
143 }
144
145 function test_titleImage() {122 function test_titleImage() {
146123
147 var titleImage = findChild(pageHeader, "titleImage");124 var titleImage = findChild(pageHeader, "titleImage");
148125
=== modified file 'tests/qmltests/Dash/tst_Dash.qml'
--- tests/qmltests/Dash/tst_Dash.qml 2014-07-29 11:35:10 +0000
+++ tests/qmltests/Dash/tst_Dash.qml 2014-08-06 14:50:38 +0000
@@ -45,12 +45,8 @@
45 name: "Dash"45 name: "Dash"
46 when: windowShown46 when: windowShown
4747
48 property var scopes48 readonly property Item dashContent: findChild(dash, "dashContent");
4949 readonly property var scopes: dashContent.scopes
50 Component.onCompleted: {
51 var dashContent = findChild(dash, "dashContent");
52 scopes = dashContent.scopes;
53 }
5450
55 function init() {51 function init() {
56 // clear and reload the scopes.52 // clear and reload the scopes.
@@ -64,10 +60,10 @@
6460
65 function get_scope_data() {61 function get_scope_data() {
66 return [62 return [
67 { tag: "MockScope1", visualIndex: 0, shouldBeVisible: true },63 { tag: "MockScope1", visualIndex: 0 },
68 { tag: "MockScope2", visualIndex: -1, shouldBeVisible: false },64 { tag: "MockScope2", visualIndex: 1 },
69 { tag: "clickscope", visualIndex: 1, shouldBeVisible: true },65 { tag: "clickscope", visualIndex: 2 },
70 { tag: "MockScope5", visualIndex: 2, shouldBeVisible: true },66 { tag: "MockScope5", visualIndex: 3 },
71 ]67 ]
72 }68 }
7369
@@ -76,10 +72,6 @@
76 }72 }
7773
78 function test_show_scope_on_load(data) {74 function test_show_scope_on_load(data) {
79 if (data.shouldBeVisible == false) {
80 console.log("Not testing " + data.tag + ": not visible");
81 return;
82 }
83 var dashContentList = findChild(dash, "dashContentList");75 var dashContentList = findChild(dash, "dashContentList");
8476
85 dash.showScopeOnLoaded = data.tag77 dash.showScopeOnLoaded = data.tag
@@ -87,7 +79,7 @@
87 tryCompare(dashContentList, "count", 0);79 tryCompare(dashContentList, "count", 0);
88 scopes.load();80 scopes.load();
89 tryCompare(scopes, "loaded", true);81 tryCompare(scopes, "loaded", true);
90 tryCompare(dashContentList, "count", 4);82 tryCompare(dashContentList, "count", 5);
9183
92 verify(dashContentList != undefined);84 verify(dashContentList != undefined);
93 tryCompare(dashContentList, "currentIndex", data.visualIndex);85 tryCompare(dashContentList, "currentIndex", data.visualIndex);
@@ -110,5 +102,26 @@
110 dashCommunicatorService.mockSetCurrentScope("clickscope", true, true);102 dashCommunicatorService.mockSetCurrentScope("clickscope", true, true);
111 tryCompare(dashContentList, "currentIndex", 1)103 tryCompare(dashContentList, "currentIndex", 1)
112 }104 }
105
106 function test_processing_indicator() {
107 tryCompare(scopes, "loaded", true);
108
109 var processingIndicator = findChild(dash, "processingIndicator");
110 verify(processingIndicator, "Can't find the processing indicator.");
111
112 verify(!processingIndicator.visible, "Processing indicator should be visible.");
113
114 tryCompareFunction(function() {
115 return scopes.getScope(dashContent.currentIndex) != null;
116 }, true);
117 var currentScope = scopes.getScope(dashContent.currentIndex);
118 verify(currentScope, "Can't find the current scope.");
119
120 currentScope.setSearchInProgress(true);
121 tryCompare(processingIndicator, "visible", true);
122
123 currentScope.setSearchInProgress(false);
124 tryCompare(processingIndicator, "visible", false);
125 }
113 }126 }
114}127}
115128
=== modified file 'tests/qmltests/Dash/tst_DashContent.qml'
--- tests/qmltests/Dash/tst_DashContent.qml 2014-07-21 13:28:35 +0000
+++ tests/qmltests/Dash/tst_DashContent.qml 2014-08-06 14:50:38 +0000
@@ -43,9 +43,6 @@
43 id: dashContent43 id: dashContent
44 anchors.fill: parent44 anchors.fill: parent
4545
46 model: SortFilterProxyModel {
47 model: scopesModel
48 }
49 scopes : scopesModel46 scopes : scopesModel
50 }47 }
5148
@@ -268,117 +265,119 @@
268 verify(carouselLV.tileWidth / carouselLV.tileHeight == cardTool.components["art"]["aspect-ratio"]);265 verify(carouselLV.tileWidth / carouselLV.tileHeight == cardTool.components["art"]["aspect-ratio"]);
269 }266 }
270267
271 function test_departments() {268 function test_navigations() {
272 var dashDepartments = findChild(dashContent, "dashDepartments");269 var dashContentList = findChild(dashContent, "dashContentList");
273 compare(dashDepartments.visible, true);270 tryCompareFunction(function() { return findChild(dashContentList.currentItem, "dashNavigation") != null; }, true);
274 compare(dashDepartments.showList, false);271 var dashNavigation = findChild(dashContentList.currentItem, "dashNavigation");
275 waitForRendering(dashDepartments);272 tryCompare(dashNavigation, "visible", true);
276 mouseClick(dashDepartments, 0, 0);273 compare(dashNavigation.showList, false);
277 compare(dashDepartments.showList, true);274 waitForRendering(dashNavigation);
278275 mouseClick(dashNavigation, 0, 0);
279 var departmentListView = findChild(dashDepartments, "departmentListView");276 compare(dashNavigation.showList, true);
280 compare(departmentListView.count, 1);277
281 tryCompare(departmentListView.currentItem.department, "loaded", true);278 var navigationListView = findChild(dashNavigation, "navigationListView");
282279 compare(navigationListView.count, 1);
283 waitForRendering(departmentListView);280 tryCompare(navigationListView.currentItem.navigation, "loaded", true);
284 waitForRendering(departmentListView.currentItem);281
285282 waitForRendering(navigationListView);
286 var allButton = findChild(dashDepartments, "allButton");283 waitForRendering(navigationListView.currentItem);
287 compare(allButton.visible, false);284
288285 var allButton = findChild(dashNavigation, "allButton");
289 var department = findChild(dashDepartments, "department0child3");286 compare(allButton.visible, false);
290 mouseClick(department, 0, 0);287
291 compare(dashDepartments.showList, false);288 var navigation = findChild(dashNavigation, "navigation0child3");
292 tryCompare(dashDepartments.currentDepartment, "departmentId", "middle3");289 mouseClick(navigation, 0, 0);
293 tryCompare(departmentListView.currentItem.department, "departmentId", "root");290 compare(dashNavigation.showList, false);
294291 tryCompare(dashNavigation.currentNavigation, "navigationId", "middle3");
295 mouseClick(dashDepartments, 0, 0);292 tryCompare(navigationListView.currentItem.navigation, "navigationId", "root");
296 compare(dashDepartments.showList, true);293
297 waitForRendering(departmentListView);294 mouseClick(dashNavigation, 0, 0);
298 waitForRendering(departmentListView.currentItem);295 compare(dashNavigation.showList, true);
299 compare(allButton.visible, true);296 waitForRendering(navigationListView);
300297 waitForRendering(navigationListView.currentItem);
301 mouseClick(allButton, 0, 0);298 compare(allButton.visible, true);
302 compare(dashDepartments.showList, false);299
303 tryCompare(dashDepartments.currentDepartment, "departmentId", "root");300 mouseClick(allButton, 0, 0);
304 tryCompare(departmentListView.currentItem.department, "departmentId", "root");301 compare(dashNavigation.showList, false);
305302 tryCompare(dashNavigation.currentNavigation, "navigationId", "root");
306 mouseClick(dashDepartments, 0, 0);303 tryCompare(navigationListView.currentItem.navigation, "navigationId", "root");
307 compare(dashDepartments.showList, true);304
308 waitForRendering(departmentListView);305 mouseClick(dashNavigation, 0, 0);
309 waitForRendering(departmentListView.currentItem);306 compare(dashNavigation.showList, true);
310 compare(allButton.visible, false);307 waitForRendering(navigationListView);
311308 waitForRendering(navigationListView.currentItem);
312 department = findChild(dashDepartments, "department0child2");309 compare(allButton.visible, false);
313 mouseClick(department, 0, 0);310
314 compare(dashDepartments.showList, true);311 navigation = findChild(dashNavigation, "navigation0child2");
315 tryCompare(dashDepartments.currentDepartment, "departmentId", "middle2");312 mouseClick(navigation, 0, 0);
316 tryCompare(departmentListView.currentItem.department, "departmentId", "middle2");313 compare(dashNavigation.showList, true);
317314 tryCompare(dashNavigation.currentNavigation, "navigationId", "middle2");
318 var departmentList1 = findChild(dashDepartments, "department1");315 tryCompare(navigationListView.currentItem.navigation, "navigationId", "middle2");
319 allButton = findChild(departmentList1, "allButton");316
320 var backButton = findChild(findChild(departmentList1, "department1"), "backButton");317 var navigationList1 = findChild(dashNavigation, "navigation1");
321 compare(allButton.visible, true);318 allButton = findChild(navigationList1, "allButton");
322 compare(backButton.visible, true);319 var backButton = findChild(findChild(navigationList1, "navigation1"), "backButton");
323320 compare(allButton.visible, true);
324 tryCompare(departmentListView, "contentX", departmentList1.x);321 compare(backButton.visible, true);
325 waitForRendering(departmentListView);322
326 mouseClick(allButton, 0, 0);323 tryCompare(navigationListView, "contentX", navigationList1.x);
327 compare(dashDepartments.showList, false);324 waitForRendering(navigationListView);
328 tryCompare(dashDepartments.currentDepartment, "departmentId", "middle2");325 mouseClick(allButton, 0, 0);
329 tryCompare(departmentListView.currentItem.department, "departmentId", "middle2");326 compare(dashNavigation.showList, false);
330327 tryCompare(dashNavigation.currentNavigation, "navigationId", "middle2");
331 mouseClick(dashDepartments, 0, 0);328 tryCompare(navigationListView.currentItem.navigation, "navigationId", "middle2");
332 compare(dashDepartments.showList, true);329
333 waitForRendering(departmentListView);330 mouseClick(dashNavigation, 0, 0);
334 waitForRendering(departmentListView.currentItem);331 compare(dashNavigation.showList, true);
335 compare(allButton.visible, true);332 waitForRendering(navigationListView);
336 compare(backButton.visible, true);333 waitForRendering(navigationListView.currentItem);
337334 compare(allButton.visible, true);
338 tryCompare(departmentList1.department, "loaded", true);335 compare(backButton.visible, true);
339 department = findChild(dashDepartments, "department1child2");336
340 mouseClick(department, 0, 0);337 tryCompare(navigationList1.navigation, "loaded", true);
341 compare(dashDepartments.showList, false);338 navigation = findChild(dashNavigation, "navigation1child2");
342 tryCompare(dashDepartments.currentDepartment, "departmentId", "childmiddle22");339 mouseClick(navigation, 0, 0);
343 tryCompare(departmentListView.currentItem.department, "departmentId", "middle2");340 compare(dashNavigation.showList, false);
344341 tryCompare(dashNavigation.currentNavigation, "navigationId", "childmiddle22");
345 mouseClick(dashDepartments, 0, 0);342 tryCompare(navigationListView.currentItem.navigation, "navigationId", "middle2");
346 compare(dashDepartments.showList, true);343
347 waitForRendering(departmentListView);344 mouseClick(dashNavigation, 0, 0);
348 waitForRendering(departmentListView.currentItem);345 compare(dashNavigation.showList, true);
349346 waitForRendering(navigationListView);
350 tryCompare(departmentList1.department, "loaded", true);347 waitForRendering(navigationListView.currentItem);
351 department = findChild(dashDepartments, "department1child3");348
352 mouseClick(department, 0, 0);349 tryCompare(navigationList1.navigation, "loaded", true);
353 compare(dashDepartments.showList, false);350 navigation = findChild(dashNavigation, "navigation1child3");
354 tryCompare(dashDepartments.currentDepartment, "departmentId", "childmiddle23");351 mouseClick(navigation, 0, 0);
355 tryCompare(departmentListView.currentItem.department, "departmentId", "middle2");352 compare(dashNavigation.showList, false);
356353 tryCompare(dashNavigation.currentNavigation, "navigationId", "childmiddle23");
357 mouseClick(dashDepartments, 0, 0);354 tryCompare(navigationListView.currentItem.navigation, "navigationId", "middle2");
358 compare(dashDepartments.showList, true);355
359 waitForRendering(departmentListView);356 mouseClick(dashNavigation, 0, 0);
360 waitForRendering(departmentListView.currentItem);357 compare(dashNavigation.showList, true);
358 waitForRendering(navigationListView);
359 waitForRendering(navigationListView.currentItem);
361 mouseClick(backButton, 0, 0);360 mouseClick(backButton, 0, 0);
362361
363 tryCompare(dashDepartments.currentDepartment, "departmentId", "root");362 tryCompare(dashNavigation.currentNavigation, "navigationId", "root");
364 tryCompare(departmentListView.currentItem.department, "departmentId", "root");363 tryCompare(navigationListView.currentItem.navigation, "navigationId", "root");
365 compare(dashDepartments.showList, true);364 compare(dashNavigation.showList, true);
366 mouseClick(dashDepartments, 0, 0);365 mouseClick(dashNavigation, 0, 0);
367 compare(dashDepartments.showList, false);366 compare(dashNavigation.showList, false);
368367
369 mouseClick(dashDepartments, 0, 0);368 mouseClick(dashNavigation, 0, 0);
370 compare(dashDepartments.showList, true);369 compare(dashNavigation.showList, true);
371 tryCompare(departmentListView.currentItem.department, "loaded", true);370 tryCompare(navigationListView.currentItem.navigation, "loaded", true);
372 department = findChild(dashDepartments, "department0child2");371 navigation = findChild(dashNavigation, "navigation0child2");
373 mouseClick(department, 0, 0);372 mouseClick(navigation, 0, 0);
374 compare(dashDepartments.showList, true);373 compare(dashNavigation.showList, true);
375 departmentList1 = findChild(dashDepartments, "department1");374 navigationList1 = findChild(dashNavigation, "navigation1");
376 compare(departmentList1.department.loaded, false);375 compare(navigationList1.navigation.loaded, false);
377 tryCompare(dashDepartments.currentDepartment, "departmentId", "middle2");376 tryCompare(dashNavigation.currentNavigation, "navigationId", "middle2");
378 allButton = findChild(departmentList1, "allButton");377 allButton = findChild(navigationList1, "allButton");
379 tryCompare(dashDepartments.currentDepartment, "departmentId", "middle2");378 tryCompare(dashNavigation.currentNavigation, "navigationId", "middle2");
380 mouseClick(allButton, 0, 0);379 mouseClick(allButton, 0, 0);
381 tryCompare(dashDepartments.currentDepartment, "departmentId", "middle2");380 tryCompare(dashNavigation.currentNavigation, "navigationId", "middle2");
382 }381 }
383 }382 }
384}383}
385384
=== modified file 'tests/qmltests/Dash/tst_GenericScopeView.qml'
--- tests/qmltests/Dash/tst_GenericScopeView.qml 2014-07-24 20:40:57 +0000
+++ tests/qmltests/Dash/tst_GenericScopeView.qml 2014-08-06 14:50:38 +0000
@@ -319,7 +319,7 @@
319 units.gu(2),319 units.gu(2),
320 testCase.previewListView.height / 2);320 testCase.previewListView.height / 2);
321 tryCompare(previewListViewList, "moving", false);321 tryCompare(previewListViewList, "moving", false);
322 tryCompare(testCase.previewListView.currentItem, "objectName", "previewItem" + i);322 tryCompare(testCase.previewListView.currentItem, "objectName", "preview" + i);
323323
324 }324 }
325 closePreview();325 closePreview();

Subscribers

People subscribed via source and target branches