Merge lp:~aacid/unity8/scopeSearchHintText into lp:unity8

Proposed by Albert Astals Cid
Status: Superseded
Proposed branch: lp:~aacid/unity8/scopeSearchHintText
Merge into: lp:unity8
Diff against target: 2711 lines (+1789/-111)
35 files modified
data/unity8.conf (+1/-1)
debian/control (+1/-1)
plugins/Dash/CardCreator.js (+2/-1)
plugins/Dash/ScopeStyle.qml (+2/-2)
plugins/Dash/listviewwithpageheader.cpp (+2/-2)
po/unity8.pot (+44/-12)
qml/Components/PageHeader.qml (+27/-8)
qml/Components/ResponsiveGridView.qml (+3/-3)
qml/Dash/CardCarousel.qml (+2/-2)
qml/Dash/CardGrid.qml (+14/-3)
qml/Dash/CardVerticalJournal.qml (+2/-2)
qml/Dash/Dash.qml (+138/-7)
qml/Dash/DashBackground.qml (+24/-0)
qml/Dash/DashContent.qml (+7/-4)
qml/Dash/DashRenderer.qml (+5/-2)
qml/Dash/GenericScopeView.qml (+57/-26)
qml/Dash/PreviewListView.qml (+2/-2)
qml/Dash/ScopesOverview.qml (+518/-0)
qml/Dash/ScopesOverviewAll.qml (+54/-0)
qml/Dash/ScopesOverviewFavorites.qml (+73/-0)
qml/Dash/ScopesOverviewTab.qml (+74/-0)
qml/Shell.qml (+2/-8)
tests/autopilot/unity8/shell/emulators/dash.py (+9/-0)
tests/mocks/Unity/CMakeLists.txt (+2/-1)
tests/mocks/Unity/fake_resultsmodel.cpp (+2/-1)
tests/mocks/Unity/fake_scope.cpp (+19/-6)
tests/mocks/Unity/fake_scope.h (+6/-3)
tests/mocks/Unity/fake_scopes.cpp (+43/-2)
tests/mocks/Unity/fake_scopes.h (+6/-0)
tests/mocks/Unity/fake_scopesoverview.cpp (+280/-0)
tests/mocks/Unity/fake_scopesoverview.h (+104/-0)
tests/plugins/Dash/cardcreator/5.res (+1/-0)
tests/qmltests/Components/tst_PageHeader.qml (+36/-6)
tests/qmltests/Dash/tst_Dash.qml (+211/-3)
tests/qmltests/Dash/tst_DashContent.qml (+16/-3)
To merge this branch: bzr merge lp:~aacid/unity8/scopeSearchHintText
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Michael Zanetti (community) Approve
Review via email: mp+228279@code.launchpad.net

This proposal has been superseded by a proposal from 2014-07-29.

Commit message

Pass the scope search hint up to the search line

Description of the change

* Are there any related MPs required for this MP to build/function as expected?
https://code.launchpad.net/~unity-team/unity-scopes-shell/catch-no-search-hint/+merge/228288
No, but there is a crash somewhere in scopes plugin that makes it crash for some scopes and also we have a white on white text problem, so it eihter needs the SDK team to fix the color on SuruDark or the Dash being a separate app so we can not use SuruDark theme

 * Did you perform an exploratory manual test run of your code change and any related functionality?
Yes, changed hint color of /usr/lib/x86_64-linux-gnu/qt5/qml/Ubuntu/Components/TextField.qml to be red manually and it is showing up fine

 * 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?
This is requested by design

To post a comment you must log in.
Revision history for this message
Michael Zanetti (mzanetti) wrote :

I think we could add a simple test here to make sure the value from the scope ends up in the placeholderText.

review: Needs Fixing
Revision history for this message
Michael Zanetti (mzanetti) wrote :

Otherwise it works fine except the above mentioned issues. I tried to merge it into the dash-as-app branch but that makes me hit the mentioned crash.

lp:~aacid/unity8/scopeSearchHintText updated
1082. By Albert Astals Cid

Check the searchhint travels up correcly through the layers

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

> I think we could add a simple test here to make sure the value from the scope
> ends up in the placeholderText.

Added.

lp:~aacid/unity8/scopeSearchHintText updated
1083. By Albert Astals Cid

Merge

Revision history for this message
Michael Zanetti (mzanetti) wrote :

thanks. looks good.

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

yeah man!

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

CI? what's that?

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~aacid/unity8/scopeSearchHintText updated
1084. By Albert Astals Cid

Merge

1085. By Albert Astals Cid

Merge lp:~aacid/unity8/scopeActivatePreview

1086. By Albert Astals Cid

Merge

1087. By Albert Astals Cid

Merge

1088. By Albert Astals Cid

Merge

1089. By Albert Astals Cid

Merge

1090. By Albert Astals Cid

Merge

1091. By Albert Astals Cid

Merge

1092. By Albert Astals Cid

Merge

1093. By Albert Astals Cid

Merge

1094. By Albert Astals Cid

Merge

1095. By Albert Astals Cid

Merge

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'data/unity8.conf'
--- data/unity8.conf 2014-07-16 15:51:56 +0000
+++ data/unity8.conf 2014-07-29 11:27:22 +0000
@@ -36,7 +36,7 @@
3636
37 if [ -z "$UNITY_SCOPES_LIST" ]; then37 if [ -z "$UNITY_SCOPES_LIST" ]; then
38 # FIXME: remove once we have this in dconf38 # FIXME: remove once we have this in dconf
39 initctl set-env UNITY_SCOPES_LIST="scopes;clickscope;musicaggregator;videoaggregator"39 initctl set-env UNITY_SCOPES_LIST="clickscope;musicaggregator;videoaggregator"
40 fi40 fi
4141
42 # Remove the socket if still there42 # Remove the socket if still there
4343
=== modified file 'debian/control'
--- debian/control 2014-07-24 20:40:44 +0000
+++ debian/control 2014-07-29 11:27:22 +0000
@@ -23,7 +23,7 @@
23 libpulse-dev,23 libpulse-dev,
24 libqmenumodel-dev (>= 0.2.8),24 libqmenumodel-dev (>= 0.2.8),
25 libqt5xmlpatterns5-dev,25 libqt5xmlpatterns5-dev,
26 libunity-api-dev (>= 7.85),26 libunity-api-dev (>= 7.87),
27 libunity-mir-dev,27 libunity-mir-dev,
28 libusermetricsoutput1-dev,28 libusermetricsoutput1-dev,
29 libxcb1-dev,29 libxcb1-dev,
3030
=== modified file 'plugins/Dash/CardCreator.js'
--- plugins/Dash/CardCreator.js 2014-07-09 19:44:44 +0000
+++ plugins/Dash/CardCreator.js 2014-07-29 11:27:22 +0000
@@ -408,7 +408,7 @@
408 mascotCode = kMascotImageCode.arg(anchors).arg(mascotImageVisible);408 mascotCode = kMascotImageCode.arg(anchors).arg(mascotImageVisible);
409 }409 }
410410
411 var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey")';411 var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < (root.scopeStyle ? root.scopeStyle.threshold : 0.7) ? (root.scopeStyle ? root.scopeStyle.light : "white") : (root.scopeStyle ? root.scopeStyle.dark : "grey")';
412412
413 var titleSubtitleCode = "";413 var titleSubtitleCode = "";
414 if (hasTitle) {414 if (hasTitle) {
@@ -438,6 +438,7 @@
438 titleAnchors = 'left: parent.left; \n\438 titleAnchors = 'left: parent.left; \n\
439 leftMargin: units.gu(1); \n\439 leftMargin: units.gu(1); \n\
440 right: parent.right; \n\440 right: parent.right; \n\
441 rightMargin: units.gu(1); \n\
441 top: overlayLoader.top; \n\442 top: overlayLoader.top; \n\
442 topMargin: units.gu(1);\n';443 topMargin: units.gu(1);\n';
443 } else {444 } else {
444445
=== modified file 'plugins/Dash/ScopeStyle.qml'
--- plugins/Dash/ScopeStyle.qml 2014-07-18 18:09:13 +0000
+++ plugins/Dash/ScopeStyle.qml 2014-07-29 11:27:22 +0000
@@ -43,9 +43,9 @@
4343
44 /*! \brief Luminance threshold for switching between fore and background color44 /*! \brief Luminance threshold for switching between fore and background color
4545
46 \note If background colour is not fully opaque, it's not taken into account.46 \note If background colour is not fully opaque, the defaultLightLuminance it's taken into account instead of it.
47 */47 */
48 readonly property real threshold: background.a !== 1.0 ? d.foregroundLuminance : (d.foregroundLuminance + d.backgroundLuminance) / 248 readonly property real threshold: background.a !== 1.0 ? (d.foregroundLuminance + d.defaultLightLuminance) / 2: (d.foregroundLuminance + d.backgroundLuminance) / 2
4949
50 /*! \brief The lighter of foreground and background colors50 /*! \brief The lighter of foreground and background colors
5151
5252
=== modified file 'plugins/Dash/listviewwithpageheader.cpp'
--- plugins/Dash/listviewwithpageheader.cpp 2014-07-25 10:47:08 +0000
+++ plugins/Dash/listviewwithpageheader.cpp 2014-07-29 11:27:22 +0000
@@ -822,8 +822,8 @@
822 ListItem *nextItem = itemAtIndex(modelIndex + 1);822 ListItem *nextItem = itemAtIndex(modelIndex + 1);
823 if (nextItem) {823 if (nextItem) {
824 listItem->setY(nextItem->y() - listItem->height());824 listItem->setY(nextItem->y() - listItem->height());
825 } else if (modelIndex == 0 && m_headerItem) {825 } else if (modelIndex == 0) {
826 listItem->setY(m_headerItem->height());826 listItem->setY(m_headerItem ? m_headerItem->height() : 0);
827 } else if (!m_visibleItems.isEmpty()) {827 } else if (!m_visibleItems.isEmpty()) {
828 lostItem = true;828 lostItem = true;
829 }829 }
830830
=== modified file 'po/unity8.pot'
--- po/unity8.pot 2014-07-11 14:20:12 +0000
+++ po/unity8.pot 2014-07-29 11:27:22 +0000
@@ -8,7 +8,7 @@
8msgstr ""8msgstr ""
9"Project-Id-Version: unity8\n"9"Project-Id-Version: unity8\n"
10"Report-Msgid-Bugs-To: \n"10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2014-07-11 14:59+0200\n"11"POT-Creation-Date: 2014-07-21 15:41+0200\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -101,7 +101,7 @@
101msgid "See more"101msgid "See more"
102msgstr ""102msgstr ""
103103
104#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330104#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:356
105msgid "See less"105msgid "See less"
106msgstr ""106msgstr ""
107107
@@ -109,7 +109,7 @@
109msgid "Recent"109msgid "Recent"
110msgstr ""110msgstr ""
111111
112#: qml/Dash/GenericScopeView.qml:330112#: qml/Dash/GenericScopeView.qml:356
113msgid "See all"113msgid "See all"
114msgstr ""114msgstr ""
115115
@@ -133,6 +133,22 @@
133msgid "Send"133msgid "Send"
134msgstr ""134msgstr ""
135135
136#: qml/Dash/ScopesOverview.qml:185
137msgid "Manage Dash"
138msgstr ""
139
140#: qml/Dash/ScopesOverview.qml:390
141msgid "Done"
142msgstr ""
143
144#: qml/Dash/ScopesOverviewTab.qml:36
145msgid "Favorites"
146msgstr ""
147
148#: qml/Dash/ScopesOverviewTab.qml:54
149msgid "All"
150msgstr ""
151
136#: qml/Greeter/Greeter.qml:157152#: qml/Greeter/Greeter.qml:157
137msgid "Swipe to unlock"153msgid "Swipe to unlock"
138msgstr ""154msgstr ""
@@ -157,11 +173,11 @@
157msgid "Speaking..."173msgid "Speaking..."
158msgstr ""174msgstr ""
159175
160#: qml/Notifications/NotificationMenuItemFactory.qml:91176#: qml/Notifications/NotificationMenuItemFactory.qml:97
161msgid "Show password"177msgid "Show password"
162msgstr ""178msgstr ""
163179
164#: qml/Notifications/NotificationMenuItemFactory.qml:103180#: qml/Notifications/NotificationMenuItemFactory.qml:112
165msgid "Please enter SIM PIN"181msgid "Please enter SIM PIN"
166msgstr ""182msgstr ""
167183
@@ -173,27 +189,27 @@
173msgid "Conference"189msgid "Conference"
174msgstr ""190msgstr ""
175191
176#: qml/Panel/Indicators/MenuItemFactory.qml:583192#: qml/Panel/Indicators/MenuItemFactory.qml:577
177msgid "In queue…"193msgid "In queue…"
178msgstr ""194msgstr ""
179195
180#: qml/Panel/Indicators/MenuItemFactory.qml:587196#: qml/Panel/Indicators/MenuItemFactory.qml:581
181msgid "Downloading"197msgid "Downloading"
182msgstr ""198msgstr ""
183199
184#: qml/Panel/Indicators/MenuItemFactory.qml:589200#: qml/Panel/Indicators/MenuItemFactory.qml:583
185msgid "Paused, tap to resume"201msgid "Paused, tap to resume"
186msgstr ""202msgstr ""
187203
188#: qml/Panel/Indicators/MenuItemFactory.qml:591204#: qml/Panel/Indicators/MenuItemFactory.qml:585
189msgid "Canceled"205msgid "Canceled"
190msgstr ""206msgstr ""
191207
192#: qml/Panel/Indicators/MenuItemFactory.qml:593208#: qml/Panel/Indicators/MenuItemFactory.qml:587
193msgid "Finished"209msgid "Finished"
194msgstr ""210msgstr ""
195211
196#: qml/Panel/Indicators/MenuItemFactory.qml:595212#: qml/Panel/Indicators/MenuItemFactory.qml:589
197msgid "Failed, tap to retry"213msgid "Failed, tap to retry"
198msgstr ""214msgstr ""
199215
@@ -201,7 +217,23 @@
201msgid "Search"217msgid "Search"
202msgstr ""218msgstr ""
203219
204#: qml/Shell.qml:359220#: qml/Shell.qml:347
221msgid "Are you sure you would like to turn power off?"
222msgstr ""
223
224#: qml/Shell.qml:349
225msgid "Power off"
226msgstr ""
227
228#: qml/Shell.qml:360
229msgid "Restart"
230msgstr ""
231
232#: qml/Shell.qml:369
233msgid "Cancel"
234msgstr ""
235
236#: qml/Shell.qml:496
205#, qt-format237#, qt-format
206msgid "Please enter %1"238msgid "Please enter %1"
207msgstr ""239msgstr ""
208240
=== modified file 'qml/Components/PageHeader.qml'
--- qml/Components/PageHeader.qml 2014-07-21 09:49:41 +0000
+++ qml/Components/PageHeader.qml 2014-07-29 11:27:22 +0000
@@ -24,7 +24,7 @@
24Item {24Item {
25 id: root25 id: root
26 objectName: "pageHeader"26 objectName: "pageHeader"
27 implicitHeight: headerContainer.height + units.gu(2) + bottomContainer.height27 implicitHeight: headerContainer.height + bottomContainer.height + (showSignatureLine ? units.gu(2) : 0)
2828
29 property bool showBackButton: false29 property bool showBackButton: false
30 property string title30 property string title
@@ -32,7 +32,9 @@
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 alias searchHint: searchTextField.placeholderText
35 property bool searchInProgress: false36 property bool searchInProgress: false
37 property alias showSignatureLine: bottomBorder.visible
3638
37 property alias bottomItem: bottomContainer.children39 property alias bottomItem: bottomContainer.children
3840
@@ -44,6 +46,12 @@
44 signal backClicked()46 signal backClicked()
4547
46 onScopeStyleChanged: refreshLogo()48 onScopeStyleChanged: refreshLogo()
49 onSearchQueryChanged: {
50 // Make sure we are at the search page if the search query changes behind our feet
51 if (searchQuery) {
52 headerContainer.showSearch = true;
53 }
54 }
4755
48 function triggerSearch() {56 function triggerSearch() {
49 if (searchEntryEnabled) {57 if (searchEntryEnabled) {
@@ -52,6 +60,12 @@
52 }60 }
53 }61 }
5462
63 function closePopup() {
64 if (headerContainer.popover != null) {
65 PopupUtils.close(headerContainer.popover);
66 }
67 }
68
55 function resetSearch(keepFocus) {69 function resetSearch(keepFocus) {
56 if (searchHistory) {70 if (searchHistory) {
57 searchHistory.addQuery(searchTextField.text);71 searchHistory.addQuery(searchTextField.text);
@@ -60,9 +74,7 @@
60 unfocus();74 unfocus();
61 }75 }
62 searchTextField.text = "";76 searchTextField.text = "";
63 if (headerContainer.popover != null) {77 closePopup();
64 PopupUtils.close(headerContainer.popover);
65 }
66 }78 }
6779
68 function unfocus() {80 function unfocus() {
@@ -103,9 +115,7 @@
103 anchors { fill: parent; margins: units.gu(1); bottomMargin: units.gu(3) + bottomContainer.height }115 anchors { fill: parent; margins: units.gu(1); bottomMargin: units.gu(3) + bottomContainer.height }
104 visible: headerContainer.showSearch116 visible: headerContainer.showSearch
105 onPressed: {117 onPressed: {
106 if (headerContainer.popover) {118 closePopup();
107 PopupUtils.close(headerContainer.popover);
108 }
109 if (!searchTextField.text) {119 if (!searchTextField.text) {
110 headerContainer.showSearch = false;120 headerContainer.showSearch = false;
111 }121 }
@@ -220,6 +230,12 @@
220 root.openSearchHistory();230 root.openSearchHistory();
221 }231 }
222 }232 }
233
234 onTextChanged: {
235 if (text != "") {
236 closePopup();
237 }
238 }
223 }239 }
224 }240 }
225241
@@ -244,6 +260,7 @@
244260
245 actions: [261 actions: [
246 Action {262 Action {
263 objectName: "search"
247 iconName: "search"264 iconName: "search"
248 visible: root.searchEntryEnabled265 visible: root.searchEntryEnabled
249 onTriggered: {266 onTriggered: {
@@ -296,6 +313,7 @@
296313
297 Repeater {314 Repeater {
298 id: recentSearches315 id: recentSearches
316 objectName: "recentSearches"
299 model: searchHistory317 model: searchHistory
300318
301 delegate: Standard {319 delegate: Standard {
@@ -304,7 +322,8 @@
304 onClicked: {322 onClicked: {
305 searchHistory.addQuery(text);323 searchHistory.addQuery(text);
306 searchTextField.text = text;324 searchTextField.text = text;
307 PopupUtils.close(popover);325 closePopup();
326 unfocus();
308 }327 }
309 }328 }
310 }329 }
311330
=== modified file 'qml/Components/ResponsiveGridView.qml'
--- qml/Components/ResponsiveGridView.qml 2014-07-11 12:12:50 +0000
+++ qml/Components/ResponsiveGridView.qml 2014-07-29 11:27:22 +0000
@@ -34,7 +34,7 @@
34 readonly property int cellWidth: gridView.cellWidth34 readonly property int cellWidth: gridView.cellWidth
35 readonly property int cellHeight: gridView.cellHeight35 readonly property int cellHeight: gridView.cellHeight
36 readonly property int totalContentHeight: {36 readonly property int totalContentHeight: {
37 return contentHeightForRows(Math.ceil(gridView.model.count / columns))37 return contentHeightForRows(Math.ceil(gridView.model.count / columns), cellHeight)
38 }38 }
39 property alias interactive: gridView.interactive39 property alias interactive: gridView.interactive
40 readonly property alias flicking: gridView.flicking40 readonly property alias flicking: gridView.flicking
@@ -47,8 +47,8 @@
47 property alias cacheBuffer: gridView.cacheBuffer47 property alias cacheBuffer: gridView.cacheBuffer
48 readonly property alias currentItem: gridView.currentItem48 readonly property alias currentItem: gridView.currentItem
4949
50 function contentHeightForRows(rows) {50 function contentHeightForRows(rows, height) {
51 return rows * cellHeight;51 return rows * height
52 }52 }
5353
54 GridView {54 GridView {
5555
=== modified file 'qml/Dash/CardCarousel.qml'
--- qml/Dash/CardCarousel.qml 2014-07-11 12:13:08 +0000
+++ qml/Dash/CardCarousel.qml 2014-07-29 11:27:22 +0000
@@ -48,8 +48,8 @@
4848
49 objectName: "carouselDelegate" + index49 objectName: "carouselDelegate" + index
5050
51 function clicked() { cardCarousel.clicked(index, model.result) }51 function clicked() { cardCarousel.clicked(index, model.result, loader.item, model) }
52 function pressAndHold() { cardCarousel.pressAndHold(index, model.result) }52 function pressAndHold() { cardCarousel.pressAndHold(index, model) }
5353
54 sourceComponent: cardTool.cardComponent54 sourceComponent: cardTool.cardComponent
55 onLoaded: {55 onLoaded: {
5656
=== modified file 'qml/Dash/CardGrid.qml'
--- qml/Dash/CardGrid.qml 2014-07-18 11:35:47 +0000
+++ qml/Dash/CardGrid.qml 2014-07-29 11:27:22 +0000
@@ -26,10 +26,20 @@
26 }26 }
2727
28 expandedHeight: grid.totalContentHeight28 expandedHeight: grid.totalContentHeight
29 collapsedHeight: Math.min(grid.contentHeightForRows(collapsedRows), expandedHeight)29 collapsedHeight: Math.min(grid.contentHeightForRows(collapsedRows, grid.cellHeight), expandedHeight)
30 collapsedItemCount: collapsedRows * grid.columns30 collapsedItemCount: collapsedRows * grid.columns
31 originY: grid.originY31 originY: grid.originY
3232
33 function cardPosition(index) {
34 var pos = {};
35 var row = Math.floor(index / grid.columns);
36 var column = index % grid.columns;
37 // Bit sad this is not symmetrical
38 pos.x = column * grid.cellWidth + grid.margins;
39 pos.y = row * grid.cellHeight;
40 return pos;
41 }
42
33 ResponsiveGridView {43 ResponsiveGridView {
34 id: grid44 id: grid
35 anchors.fill: parent45 anchors.fill: parent
@@ -53,6 +63,7 @@
53 item.objectName = "delegate" + index;63 item.objectName = "delegate" + index;
54 item.width = Qt.binding(function() { return cardTool.cardWidth; });64 item.width = Qt.binding(function() { return cardTool.cardWidth; });
55 item.height = Qt.binding(function() { return cardTool.cardHeight; });65 item.height = Qt.binding(function() { return cardTool.cardHeight; });
66 item.fixedHeaderHeight = Qt.binding(function() { return cardTool.headerHeight; });
56 item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });67 item.fixedArtShapeSize = Qt.binding(function() { return cardTool.artShapeSize; });
57 item.cardData = Qt.binding(function() { return model; });68 item.cardData = Qt.binding(function() { return model; });
58 item.template = Qt.binding(function() { return cardTool.template; });69 item.template = Qt.binding(function() { return cardTool.template; });
@@ -62,8 +73,8 @@
62 }73 }
63 Connections {74 Connections {
64 target: loader.item75 target: loader.item
65 onClicked: root.clicked(index, result)76 onClicked: root.clicked(index, result, loader.item, model)
66 onPressAndHold: root.pressAndHold(index)77 onPressAndHold: root.pressAndHold(index, model)
67 }78 }
68 }79 }
69 }80 }
7081
=== modified file 'qml/Dash/CardVerticalJournal.qml'
--- qml/Dash/CardVerticalJournal.qml 2014-07-22 12:17:34 +0000
+++ qml/Dash/CardVerticalJournal.qml 2014-07-29 11:27:22 +0000
@@ -61,8 +61,8 @@
61 }61 }
62 Connections {62 Connections {
63 target: loader.item63 target: loader.item
64 onClicked: root.clicked(index, result)64 onClicked: root.clicked(index, result, loader.item, model)
65 onPressAndHold: root.pressAndHold(index)65 onPressAndHold: root.pressAndHold(index, model)
66 }66 }
67 }67 }
68 }68 }
6969
=== modified file 'qml/Dash/Dash.qml'
--- qml/Dash/Dash.qml 2014-07-07 08:20:04 +0000
+++ qml/Dash/Dash.qml 2014-07-29 11:27:22 +0000
@@ -16,6 +16,7 @@
1616
17import QtQuick 2.017import QtQuick 2.0
18import Ubuntu.Components 0.118import Ubuntu.Components 0.1
19import Ubuntu.Gestures 0.1
19import Unity 0.220import Unity 0.2
20import Utils 0.121import Utils 0.1
21import "../Components"22import "../Components"
@@ -29,6 +30,8 @@
29 property string showScopeOnLoaded: "clickscope"30 property string showScopeOnLoaded: "clickscope"
30 property real contentScale: 1.031 property real contentScale: 1.0
3132
33 property alias overviewHandleHeight: overviewDragHandle.height
34
32 function setCurrentScope(scopeId, animate, reset) {35 function setCurrentScope(scopeId, animate, reset) {
33 var scopeIndex = filteredScopes.findFirst(Scopes.RoleId, scopeId)36 var scopeIndex = filteredScopes.findFirst(Scopes.RoleId, scopeId)
3437
@@ -66,19 +69,85 @@
66 filterRegExp: RegExp("^true$")69 filterRegExp: RegExp("^true$")
67 }70 }
6871
72 QtObject {
73 id: overviewController
74 objectName: "overviewController"
75
76 property alias enableAnimation: progressAnimation.enabled
77 property real progress: 0
78 Behavior on progress {
79 id: progressAnimation
80 UbuntuNumberAnimation { }
81 }
82 }
83
84 ScopesOverview {
85 id: scopesOverview
86 objectName: "scopesOverview"
87 anchors.fill: parent
88 scope: scopes.overviewScope
89 progress: overviewController.progress
90 scopeScale: scopeItem.scope ? 0.4 : (1 - overviewController.progress * 0.6)
91 visible: scopeScale != 1
92 currentIndex: dashContent.currentIndex
93 onDone: {
94 if (currentTab == 1) {
95 animateDashFromAll(dashContent.currentScopeId);
96 }
97 hide();
98 }
99 onFavoriteSelected: {
100 setCurrentScope(scopeId, false, false);
101 hide();
102 }
103 onAllFavoriteSelected: {
104 setCurrentScope(scopeId, false, false);
105 animateDashFromAll(dashContent.currentScopeId);
106 hide();
107 }
108 onSearchSelected: {
109 var scopeIndex = filteredScopes.findFirst(Scopes.RoleId, scopeId);
110 if (scopeIndex >= 0) {
111 // Is a favorite one
112 setCurrentScope(scopeId, false, false);
113 showDashFromPos(pos, size);
114 hide();
115 } else {
116 // Is not a favorite one, activate and get openScope
117 scope.activate(result);
118 }
119 }
120 function hide() {
121 overviewController.enableAnimation = true;
122 overviewController.progress = 0;
123 }
124 onProgressChanged: {
125 if (progress == 0) {
126 currentTab = scopeItem.scope ? 1 : 0;
127 }
128 }
129 }
130
69 DashContent {131 DashContent {
70 id: dashContent132 id: dashContent
133
134 property var scopeThatOpenedScope: null
135
136 parent: overviewController.progress == 0 ? dash : scopesOverview.dashItemEater
71 objectName: "dashContent"137 objectName: "dashContent"
72 width: parent.width138 width: dash.width
73 height: parent.height139 height: dash.height
74 model: filteredScopes140 model: filteredScopes
75 scopes: scopes141 scopes: scopes
76 visible: x != -width142 visible: !scopesOverview.showingNonFavoriteScope && x != -width
77 onGotoScope: {143 onGotoScope: {
78 dash.setCurrentScope(scopeId, true, false);144 dash.setCurrentScope(scopeId, true, false);
79 }145 }
80 onOpenScope: {146 onOpenScope: {
147 scopeThatOpenedScope = currentScope;
81 scopeItem.scope = scope;148 scopeItem.scope = scope;
149 scopesOverview.currentTab = 1;
150 scopesOverview.ensureAllScopeVisible(scope.id);
82 x = -width;151 x = -width;
83 }152 }
84 onScopeLoaded: {153 onScopeLoaded: {
@@ -88,25 +157,63 @@
88 }157 }
89 }158 }
90 scale: dash.contentScale159 scale: dash.contentScale
91 clip: scale != 1.0 || scopeItem.visible160 clip: scale != 1.0 || scopeItem.visible || overviewController.progress != 0
92 Behavior on x {161 Behavior on x {
93 UbuntuNumberAnimation {162 UbuntuNumberAnimation {
163 duration: overviewController.progress != 0 ? 0 : UbuntuAnimation.FastDuration
94 onRunningChanged: {164 onRunningChanged: {
95 if (!running && dashContent.x == 0) {165 if (!running && dashContent.x == 0) {
96 dashContent.closeScope(scopeItem.scope);166 dashContent.scopeThatOpenedScope.closeScope(scopeItem.scope);
97 scopeItem.scope = null;167 scopeItem.scope = null;
168 if (overviewController.progress == 0) {
169 // Set tab to Favorites only if we are not showing the overview
170 scopesOverview.currentTab = 0;
171 }
98 }172 }
99 }173 }
100 }174 }
101 }175 }
176
177 enabled: opacity == 1
178 opacity: scopesOverview.growingDashFromPos ? 1 : 1 - overviewController.progress
179 }
180
181 DashBackground
182 {
183 anchors.fill: scopeItem
184 visible: scopeItem.visible
185 parent: scopeItem.parent
186 scale: scopeItem.scale
187 opacity: scopeItem.opacity
102 }188 }
103189
104 GenericScopeView {190 GenericScopeView {
105 id: scopeItem191 id: scopeItem
106 anchors.left: dashContent.right192 objectName: "dashTempScopeItem"
193
194 readonly property real targetOverviewScale: {
195 if (scopesOverview.currentTab == 0) {
196 return 0.4;
197 } else {
198 return scopesOverview.allCardSize.width / scopeItem.width;
199 }
200 }
201 readonly property real overviewProgressScale: (1 - overviewController.progress * (1 - targetOverviewScale))
202 readonly property var targetOverviewPosition: scope ? scopesOverview.allScopeCardPosition(scope.id) : null
203 readonly property real overviewProgressX: scope && scopesOverview.currentTab == 1 && targetOverviewPosition ?
204 overviewController.progress * (targetOverviewPosition.x - (width - scopesOverview.allCardSize.width) / 2)
205 : 0
206 readonly property real overviewProgressY: scope && scopesOverview.currentTab == 1 && targetOverviewPosition ?
207 overviewController.progress * (targetOverviewPosition.y - (height - scopesOverview.allCardSize.height) / 2)
208 : 0
209
210 x: overviewController.progress == 0 ? dashContent.x + width : overviewProgressX
211 y: overviewController.progress == 0 ? dashContent.y : overviewProgressY
107 width: parent.width212 width: parent.width
108 height: parent.height213 height: parent.height
109 scale: dash.contentScale214 scale: dash.contentScale * overviewProgressScale
215 enabled: opacity == 1
216 opacity: 1 - overviewController.progress
110 clip: scale != 1.0217 clip: scale != 1.0
111 visible: scope != null218 visible: scope != null
112 hasBackAction: true219 hasBackAction: true
@@ -126,4 +233,28 @@
126 }233 }
127 }234 }
128 }235 }
236
237 EdgeDragArea {
238 id: overviewDragHandle
239 objectName: "overviewDragHandle"
240 z: 1
241 direction: Direction.Upwards
242 enabled: !dashContent.previewShown && dashContent.currentScope && dashContent.currentScope.searchQuery == "" && (overviewController.progress == 0 || dragging)
243
244 readonly property real fullMovement: units.gu(20)
245
246 anchors { left: parent.left; right: parent.right; bottom: parent.bottom }
247 height: units.gu(2)
248
249 onSceneDistanceChanged: {
250 overviewController.enableAnimation = false;
251 overviewController.progress = Math.max(0, Math.min(1, sceneDistance / fullMovement));
252 }
253
254 onDraggingChanged: {
255 overviewController.enableAnimation = true;
256 overviewController.progress = (overviewController.progress > 0.7) ? 1 : 0;
257 }
258 }
259
129}260}
130261
=== added file 'qml/Dash/DashBackground.qml'
--- qml/Dash/DashBackground.qml 1970-01-01 00:00:00 +0000
+++ qml/Dash/DashBackground.qml 2014-07-29 11:27:22 +0000
@@ -0,0 +1,24 @@
1/*
2 * Copyright (C) 2013, 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.0
18
19Image {
20 source: anchors.fill.width > anchors.fill.height ? "graphics/paper_landscape.png" : "graphics/paper_portrait.png"
21 fillMode: Image.PreserveAspectCrop
22 horizontalAlignment: Image.AlignRight
23 verticalAlignment: Image.AlignTop
24}
025
=== modified file 'qml/Dash/DashContent.qml'
--- qml/Dash/DashContent.qml 2014-07-08 19:35:59 +0000
+++ qml/Dash/DashContent.qml 2014-07-29 11:27:22 +0000
@@ -26,6 +26,9 @@
26 property var model: null26 property var model: null
27 property var scopes: null27 property var scopes: null
28 readonly property alias currentIndex: dashContentList.currentIndex28 readonly property alias currentIndex: dashContentList.currentIndex
29 readonly property string currentScopeId: dashContentList.currentItem ? dashContentList.currentItem.scopeId : ""
30 readonly property var currentScope: dashContentList.currentItem ? dashContentList.currentItem.theScope : null
31 readonly property bool previewShown: dashContentList.currentItem && dashContentList.currentItem.item ? dashContentList.currentItem.item.previewShown : false
2932
30 signal scopeLoaded(string scopeId)33 signal scopeLoaded(string scopeId)
31 signal gotoScope(string scopeId)34 signal gotoScope(string scopeId)
@@ -76,15 +79,15 @@
76 }79 }
77 }80 }
7881
79 function closeScope(scope) {
80 dashContentList.currentItem.theScope.closeScope(scope)
81 }
82
83 Item {82 Item {
84 id: dashContentListHolder83 id: dashContentListHolder
8584
86 anchors.fill: parent85 anchors.fill: parent
8786
87 DashBackground {
88 anchors.fill: parent
89 }
90
88 ListView {91 ListView {
89 id: dashContentList92 id: dashContentList
90 objectName: "dashContentList"93 objectName: "dashContentList"
9194
=== modified file 'qml/Dash/DashRenderer.qml'
--- qml/Dash/DashRenderer.qml 2014-07-22 12:17:34 +0000
+++ qml/Dash/DashRenderer.qml 2014-07-29 11:27:22 +0000
@@ -41,9 +41,12 @@
41 /// Emitted when the user clicked on an item41 /// Emitted when the user clicked on an item
42 /// @param index is the index of the clicked item42 /// @param index is the index of the clicked item
43 /// @param result result model of the cliked item, used for activation43 /// @param result result model of the cliked item, used for activation
44 signal clicked(int index, var result)44 /// @param item item that has been clicked
45 /// @param itemModel model of the item
46 signal clicked(int index, var result, var item, var itemModel)
4547
46 /// Emitted when the user pressed and held on an item48 /// Emitted when the user pressed and held on an item
47 /// @param index is the index of the held item49 /// @param index is the index of the held item
48 signal pressAndHold(int index)50 /// @param itemModel model of the item
51 signal pressAndHold(int index, var itemModel)
49}52}
5053
=== modified file 'qml/Dash/GenericScopeView.qml'
--- qml/Dash/GenericScopeView.qml 2014-07-24 20:40:44 +0000
+++ qml/Dash/GenericScopeView.qml 2014-07-29 11:27:22 +0000
@@ -33,6 +33,10 @@
33 property bool hasBackAction: false33 property bool hasBackAction: false
34 property bool enableHeightBehaviorOnNextCreation: false34 property bool enableHeightBehaviorOnNextCreation: false
35 property var categoryView: categoryView35 property var categoryView: categoryView
36 property bool showPageHeader: true
37 property var clickOverride: null
38 property var pressAndHoldOverride: null
39 readonly property alias previewShown: previewListView.open
3640
37 property var scopeStyle: ScopeStyle {41 property var scopeStyle: ScopeStyle {
38 style: scope ? scope.customizations : {}42 style: scope ? scope.customizations : {}
@@ -78,22 +82,24 @@
78 }82 }
7983
80 onIsCurrentChanged: {84 onIsCurrentChanged: {
81 pageHeader.resetSearch();85 if (showPageHeader) {
86 pageHeaderLoader.item.resetSearch();
87 }
82 previewListView.open = false;88 previewListView.open = false;
83 }89 }
8490
85 Binding {91 Binding {
86 target: scopeView.scope92 target: scopeView.scope
87 property: "searchQuery"93 property: "searchQuery"
88 value: pageHeader.searchQuery94 value: pageHeaderLoader.item ? pageHeaderLoader.item.searchQuery : ""
89 when: isCurrent95 when: isCurrent && showPageHeader
90 }96 }
9197
92 Binding {98 Binding {
93 target: pageHeader99 target: pageHeaderLoader.item
94 property: "searchQuery"100 property: "searchQuery"
95 value: scopeView.scope ? scopeView.scope.searchQuery : ""101 value: scopeView.scope ? scopeView.scope.searchQuery : ""
96 when: isCurrent102 when: isCurrent && showPageHeader
97 }103 }
98104
99 Connections {105 Connections {
@@ -232,7 +238,12 @@
232 Connections {238 Connections {
233 target: rendererLoader.item239 target: rendererLoader.item
234 onClicked: {240 onClicked: {
235 if (scopeView.scope.id === "scopes" || scopeView.scope.id == "clickscope") {241 if (scopeView.clickOverride) {
242 scopeView.clickOverride(index, result, item, itemModel);
243 return;
244 }
245
246 if (itemModel.uri.indexOf("scope://") === 0 || scopeView.scope.id === "clickscope") {
236 // TODO Technically it is possible that calling activate() will make the scope emit247 // TODO Technically it is possible that calling activate() will make the scope emit
237 // previewRequested so that we show a preview but there's no scope that does that yet248 // previewRequested so that we show a preview but there's no scope that does that yet
238 // so it's not implemented249 // so it's not implemented
@@ -241,7 +252,16 @@
241 openPreview(index);252 openPreview(index);
242 }253 }
243 }254 }
244 onPressAndHold: openPreview(index)255
256 onPressAndHold: {
257 if (scopeView.pressAndHoldOverride) {
258 scopeView.pressAndHoldOverride(index);
259 } else {
260 if (itemModel.uri.indexOf("scope://") !== 0) {
261 openPreview(index)
262 }
263 }
264 }
245265
246 function openPreview(index) {266 function openPreview(index) {
247 if (!rendererLoader.expanded && !seeAllLabel.visible && target.collapsedItemCount > 0) {267 if (!rendererLoader.expanded && !seeAllLabel.visible && target.collapsedItemCount > 0) {
@@ -389,26 +409,35 @@
389 }409 }
390 }410 }
391411
392 pageHeader: PageHeader {412 pageHeader: scopeView.showPageHeader ? pageHeaderLoader : null
393 id: pageHeader413 Loader {
394 objectName: "scopePageHeader"414 id: pageHeaderLoader
395 width: parent.width415 width: parent.width
396 title: scopeView.scope ? scopeView.scope.name : ""416 sourceComponent: scopeView.showPageHeader ? pageHeaderComponent : undefined
397 showBackButton: scopeView.hasBackAction417 Component {
398 searchEntryEnabled: true418 id: pageHeaderComponent
399 searchInProgress: scopeView.scope ? scopeView.scope.searchInProgress : false419 PageHeader {
400 scopeStyle: scopeView.scopeStyle420 objectName: "scopePageHeader"
401421 width: parent.width
402 bottomItem: DashDepartments {422 title: scopeView.scope ? scopeView.scope.name : ""
403 scope: scopeView.scope423 searchHint: scopeView.scope && scopeView.scope.searchHint || i18n.tr("Search")
404 width: parent.width <= units.gu(60) ? parent.width : units.gu(40)424 showBackButton: scopeView.hasBackAction
405 anchors.right: parent.right425 searchEntryEnabled: true
406 windowHeight: scopeView.height426 searchInProgress: scopeView.scope ? scopeView.scope.searchInProgress : false
407 windowWidth: scopeView.width427 scopeStyle: scopeView.scopeStyle
408 scopeStyle: scopeView.scopeStyle428
429 bottomItem: DashDepartments {
430 scope: scopeView.scope
431 width: parent.width <= units.gu(60) ? parent.width : units.gu(40)
432 anchors.right: parent.right
433 windowHeight: scopeView.height
434 windowWidth: scopeView.width
435 scopeStyle: scopeView.scopeStyle
436 }
437
438 onBackClicked: scopeView.backClicked()
439 }
409 }440 }
410
411 onBackClicked: scopeView.backClicked()
412 }441 }
413 }442 }
414443
@@ -427,7 +456,9 @@
427 anchors.left: categoryView.right456 anchors.left: categoryView.right
428457
429 onOpenChanged: {458 onOpenChanged: {
430 pageHeader.unfocus();459 if (showPageHeader) {
460 pageHeaderLoader.item.unfocus();
461 }
431 }462 }
432 }463 }
433464
434465
=== modified file 'qml/Dash/PreviewListView.qml'
--- qml/Dash/PreviewListView.qml 2014-07-17 13:10:45 +0000
+++ qml/Dash/PreviewListView.qml 2014-07-29 11:27:22 +0000
@@ -88,7 +88,7 @@
88 height: previewListView.height88 height: previewListView.height
89 width: previewListView.width89 width: previewListView.width
9090
91 readonly property bool ready: preview.previewModel.loaded91 readonly property bool ready: preview.previewModel && preview.previewModel.loaded
9292
93 Previews.Preview {93 Previews.Preview {
94 id: preview94 id: preview
@@ -108,7 +108,7 @@
108 id: processingMouseArea108 id: processingMouseArea
109 objectName: "processingMouseArea"109 objectName: "processingMouseArea"
110 anchors.fill: parent110 anchors.fill: parent
111 enabled: !preview.previewModel.loaded || preview.previewModel.processingAction111 enabled: preview.previewModel && (!preview.previewModel.loaded || preview.previewModel.processingAction)
112112
113 ActivityIndicator {113 ActivityIndicator {
114 anchors.centerIn: parent114 anchors.centerIn: parent
115115
=== added file 'qml/Dash/ScopesOverview.qml'
--- qml/Dash/ScopesOverview.qml 1970-01-01 00:00:00 +0000
+++ qml/Dash/ScopesOverview.qml 2014-07-29 11:27:22 +0000
@@ -0,0 +1,518 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.0
18import Dash 0.1
19import Ubuntu.Components 0.1
20import "../Components"
21
22Item {
23 id: root
24
25 // Properties set by parent
26 property real progress: 0
27 property var scope: null
28 property int currentIndex: 0
29 property real scopeScale: 1
30
31 // Properties set and used by parent
32 property alias currentTab: tabBar.currentTab
33
34 // Properties used by parent
35 property bool growingDashFromPos: false
36 readonly property bool searching: scope && scope.searchQuery == ""
37 readonly property bool showingNonFavoriteScope: tempScopeItem.scope != null
38 readonly property var dashItemEater: {
39 if (!forceXYScalerEater && tabBar.currentTab == 0 && middleItems.count > 0) {
40 var loaderItem = middleItems.itemAt(0).item;
41 return loaderItem && loaderItem.currentItem ? loaderItem.currentItem : null;
42 }
43 return scopesOverviewXYScaler;
44 }
45 readonly property size allCardSize: {
46 if (middleItems.count > 1) {
47 var loaderItem = middleItems.itemAt(1).item;
48 if (loaderItem) {
49 var cardTool = loaderItem.cardTool;
50 return Qt.size(cardTool.cardWidth, cardTool.cardHeight);
51 }
52 }
53 return Qt.size(0, 0);
54 }
55
56 // Internal properties
57 property bool forceXYScalerEater: false
58
59 signal done()
60 signal favoriteSelected(var scopeId)
61 signal allFavoriteSelected(var scopeId)
62 signal searchSelected(var scopeId, var result, var pos, var size)
63
64 Connections {
65 target: scope
66 onOpenScope: {
67 var itemPos = scopesOverviewXYScaler.restorePosition;
68 var itemSize = scopesOverviewXYScaler.restoreSize;
69 scopesOverviewXYScaler.scale = itemSize.width / scopesOverviewXYScaler.width;
70 if (itemPos) {
71 scopesOverviewXYScaler.x = itemPos.x -(scopesOverviewXYScaler.width - scopesOverviewXYScaler.width * scopesOverviewXYScaler.scale) / 2;
72 scopesOverviewXYScaler.y = itemPos.y -(scopesOverviewXYScaler.height - scopesOverviewXYScaler.height * scopesOverviewXYScaler.scale) / 2;
73 } else {
74 scopesOverviewXYScaler.x = 0;
75 scopesOverviewXYScaler.y = 0;
76 }
77 scopesOverviewXYScaler.opacity = 0;
78 tempScopeItem.scope = scope;
79 middleItems.overrideOpacity = 0;
80 scopesOverviewXYScaler.scale = 1;
81 scopesOverviewXYScaler.x = 0;
82 scopesOverviewXYScaler.y = 0;
83 scopesOverviewXYScaler.opacity = 1;
84 }
85 }
86
87 function animateDashFromAll(scopeId) {
88 var currentScopePos = allScopeCardPosition(scopeId);
89 if (currentScopePos) {
90 showDashFromPos(currentScopePos, allCardSize);
91 } else {
92 console.log("Warning: Could not find Dash OverView All card position for scope", dashContent.currentScopeId);
93 }
94 }
95
96 function showDashFromPos(itemPos, itemSize) {
97 scopesOverviewXYScaler.scale = itemSize.width / scopesOverviewXYScaler.width;
98 scopesOverviewXYScaler.x = itemPos.x -(scopesOverviewXYScaler.width - scopesOverviewXYScaler.width * scopesOverviewXYScaler.scale) / 2;
99 scopesOverviewXYScaler.y = itemPos.y -(scopesOverviewXYScaler.height - scopesOverviewXYScaler.height * scopesOverviewXYScaler.scale) / 2;
100 scopesOverviewXYScaler.opacity = 0;
101 root.growingDashFromPos = true;
102 scopesOverviewXYScaler.scale = 1;
103 scopesOverviewXYScaler.x = 0;
104 scopesOverviewXYScaler.y = 0;
105 scopesOverviewXYScaler.opacity = 1;
106 }
107
108 function allScopeCardPosition(scopeId) {
109 if (middleItems.count > 1) {
110 var loaderItem = middleItems.itemAt(1).item;
111 if (loaderItem) {
112 var pos = loaderItem.scopeCardPosition(scopeId);
113 return loaderItem.mapToItem(null, pos.x, pos.y);
114 }
115 }
116 }
117
118 function ensureAllScopeVisible(scopeId) {
119 if (middleItems.count > 1) {
120 var loaderItem = middleItems.itemAt(1).item;
121 if (loaderItem) {
122 var pos = loaderItem.scopeCardPosition(scopeId);
123 loaderItem.contentY = Math.min(pos.y, loaderItem.contentHeight - loaderItem.height);
124 }
125 }
126 }
127
128 onProgressChanged: {
129 if (progress == 0) {
130 pageHeader.resetSearch();
131 pageHeader.unfocus(); // Shouldn't the previous call do this too?
132 }
133 }
134
135 ScopeStyle {
136 id: overviewScopeStyle
137 style: { "foreground-color" : "white", "background-color" : "transparent" }
138 }
139
140 DashBackground {
141 anchors.fill: parent
142 source: "graphics/dark_background.jpg"
143 }
144
145 Connections {
146 target: pageHeader
147 onSearchQueryChanged: {
148 // Need this in order, otherwise something gets unhappy in rendering
149 // of the overlay in carousels because the parent of the dash dies for
150 // a moment, this way we make sure it's reparented first
151 // by forceXYScalerEater making dashItemEater return scopesOverviewXYScaler
152 // before we kill the previous parent by scope.searchQuery
153 root.forceXYScalerEater = true;
154 root.scope.searchQuery = pageHeader.searchQuery;
155 root.forceXYScalerEater = false;
156 }
157 }
158
159 Binding {
160 target: pageHeader
161 property: "searchQuery"
162 value: scope ? scope.searchQuery : ""
163 }
164
165 Item {
166 id: scopesOverviewContent
167 x: previewListView.open ? -width : 0
168 Behavior on x { UbuntuNumberAnimation { } }
169 width: parent.width
170 height: parent.height
171
172 PageHeader {
173 id: pageHeader
174 objectName: "scopesOverviewPageHeader"
175
176 readonly property real yDisplacement: pageHeader.height + tabBar.height + tabBar.anchors.margins
177
178 y: {
179 if (root.progress < 0.5) {
180 return -yDisplacement;
181 } else {
182 return -yDisplacement + (root.progress - 0.5) * yDisplacement * 2;
183 }
184 }
185 width: parent.width
186 clip: true
187 title: i18n.tr("Manage Dash")
188 scopeStyle: overviewScopeStyle
189 showSignatureLine: false
190 searchEntryEnabled: true
191 searchInProgress: root.scope ? root.scope.searchInProgress : false
192 }
193
194 ScopesOverviewTab {
195 id: tabBar
196 anchors {
197 left: parent.left
198 right: parent.right
199 top: pageHeader.bottom
200 margins: units.gu(2)
201 }
202 height: units.gu(4)
203
204 enabled: opacity == 1
205 opacity: !scope || scope.searchQuery == "" ? 1 : 0
206 Behavior on opacity { UbuntuNumberAnimation { } }
207 }
208
209 Repeater {
210 id: middleItems
211 objectName: "scopesOverviewRepeater"
212 property real overrideOpacity: -1
213 model: scope && scope.searchQuery == "" ? scope.categories : null
214 delegate: Loader {
215 id: loader
216 objectName: "scopesOverviewRepeaterChild" + index
217
218 height: {
219 if (index == 0) {
220 return root.height;
221 } else {
222 return root.height - pageHeader.height - tabBar.height - tabBar.anchors.margins - units.gu(2)
223 }
224 }
225 width: {
226 if (index == 0) {
227 return root.width / scopeScale
228 } else {
229 return root.width
230 }
231 }
232 x: {
233 if (index == 0) {
234 return (root.width - width) / 2;
235 } else {
236 return 0;
237 }
238 }
239 anchors {
240 bottom: scopesOverviewContent.bottom
241 }
242
243 scale: index == 0 ? scopeScale : 1
244
245 opacity: {
246 if (middleItems.overrideOpacity >= 0)
247 return middleItems.overrideOpacity;
248
249 if (tabBar.currentTab != index)
250 return 0;
251
252 return index == 0 ? 1 : root.progress;
253 }
254 Behavior on opacity {
255 enabled: root.progress == 1
256 UbuntuNumberAnimation { }
257 }
258 enabled: opacity == 1
259
260 clip: index == 1
261
262 CardTool {
263 id: cardTool
264 objectName: "cardTool"
265 count: results.count
266 template: model.renderer
267 components: model.components
268 viewWidth: parent.width
269 }
270
271 source: {
272 if (index == 0 && categoryId == "favorites") return "ScopesOverviewFavorites.qml";
273 else if (index == 1 && categoryId == "all") return "ScopesOverviewAll.qml";
274 else return "";
275 }
276
277 onLoaded: {
278 item.model = Qt.binding(function() { return results })
279 item.cardTool = cardTool;
280 if (index == 0) {
281 item.scopeWidth = Qt.binding(function() { return root.width; });
282 item.scopeHeight = Qt.binding(function() { return root.height; });
283 item.appliedScale = Qt.binding(function() { return loader.scale });
284 item.currentIndex = Qt.binding(function() { return root.currentIndex });
285 } else if (index == 1) {
286 item.extraHeight = bottomBar.height;
287 }
288 }
289
290 Connections {
291 target: loader.item
292 onClicked: {
293 if (tabBar.currentTab == 0) {
294 root.favoriteSelected(itemModel.scopeId)
295 } else {
296 var favoriteScopesItem = middleItems.itemAt(0).item;
297 var scopeIndex = favoriteScopesItem.model.scopeIndex(itemModel.scopeId);
298 if (scopeIndex >= 0) {
299 root.allFavoriteSelected(itemModel.scopeId);
300 } else {
301 // Will result in an openScope from root.scope
302 scopesOverviewXYScaler.restorePosition = item.mapToItem(null, 0, 0);
303 scopesOverviewXYScaler.restoreSize = allCardSize;
304 root.scope.activate(result);
305 }
306 }
307 }
308 onPressAndHold: {
309 // Preview can call openScope so make sure restorePosition and restoreSize are set
310 scopesOverviewXYScaler.restorePosition = undefined;
311 scopesOverviewXYScaler.restoreSize = allCardSize;
312
313 previewListView.model = target.model;
314 previewListView.currentIndex = -1
315 previewListView.currentIndex = index;
316 previewListView.open = true
317 }
318 }
319 }
320 }
321
322 GenericScopeView {
323 id: searchResultsViewer
324 objectName: "searchResultsViewer"
325 anchors {
326 top: pageHeader.bottom
327 right: parent.right
328 left: parent.left
329 bottom: parent.bottom
330 }
331 scope: root.scope && root.scope.searchQuery != "" ? root.scope : null
332 scopeStyle: overviewScopeStyle
333 enabled: opacity == 1
334 showPageHeader: false
335 clip: true
336 opacity: searchResultsViewer.scope ? 1 : 0
337 Behavior on opacity { UbuntuNumberAnimation { } }
338
339 clickOverride: function (index, result, item, itemModel) {
340 pageHeader.closePopup();
341 if (itemModel.scopeId) {
342 // This can end up in openScope so save restorePosition and restoreSize
343 scopesOverviewXYScaler.restorePosition = item.mapToItem(null, 0, 0);
344 scopesOverviewXYScaler.restoreSize = Qt.size(item.width, item.height);
345 root.searchSelected(itemModel.scopeId, result, item.mapToItem(null, 0, 0), Qt.size(item.width, item.height));
346 } else {
347 // Not a scope, just activate it
348 searchResultsViewer.scope.activate(result);
349 }
350 }
351
352 pressAndHoldOverride: function (index) {
353 // Do nothing
354 }
355 }
356
357 Rectangle {
358 id: bottomBar
359 color: "black"
360 height: units.gu(6)
361 width: parent.width
362 enabled: opacity == 0.4
363 opacity: scope && scope.searchQuery == "" ? 0.4 : 0
364 Behavior on opacity { UbuntuNumberAnimation { } }
365 y: {
366 if (root.progress < 0.5) {
367 return parent.height;
368 } else {
369 return parent.height - (root.progress - 0.5) * height * 2;
370 }
371 }
372
373 AbstractButton {
374 objectName: "scopesOverviewDoneButton"
375 width: Math.max(label.width + units.gu(2), units.gu(10))
376 height: units.gu(4)
377 anchors {
378 left: parent.left
379 leftMargin: units.gu(2)
380 verticalCenter: parent.verticalCenter
381 }
382 Rectangle {
383 anchors.fill: parent
384 border.color: "white"
385 border.width: units.dp(1)
386 radius: units.dp(10)
387 color: parent.pressed ? "gray" : "transparent"
388 }
389 Label {
390 id: label
391 anchors.centerIn: parent
392 text: i18n.tr("Done")
393 color: parent.pressed ? "black" : "white"
394 }
395 onClicked: root.done();
396 }
397
398 AbstractButton {
399 objectName: "scopesOverviewStoreButton"
400 width: Math.max(storeLabel.width, units.gu(10))
401 height: units.gu(4)
402 anchors {
403 right: parent.right
404 verticalCenter: parent.verticalCenter
405 }
406 Image {
407 id: storeImage
408 source: "graphics/apps-scope.png"
409 anchors.horizontalCenter: parent.horizontalCenter
410 width: units.gu(2)
411 height: units.gu(2)
412 fillMode: Image.Stretch
413 }
414 Label {
415 id: storeLabel
416 anchors.horizontalCenter: parent.horizontalCenter
417 anchors.top: storeImage.bottom
418 text: i18n.tr("Store")
419 color: "white"
420 }
421 onClicked: {
422 // Just zoom from the middle
423 scopesOverviewXYScaler.restorePosition = undefined;
424 scopesOverviewXYScaler.restoreSize = allCardSize;
425 scope.performQuery("scope://com.canonical.scopes.clickstore");
426 }
427 }
428 }
429 }
430
431 PreviewListView {
432 id: previewListView
433 objectName: "scopesOverviewPreviewListView"
434 scope: root.scope
435 scopeStyle: overviewScopeStyle
436 visible: x != width
437 width: parent.width
438 height: parent.height
439 anchors.left: scopesOverviewContent.right
440 }
441
442
443
444 Item {
445 id: scopesOverviewXYScaler
446 width: parent.width
447 height: parent.height
448
449 clip: scale != 1.0
450 enabled: scale == 1
451
452 property bool animationsEnabled: root.showingNonFavoriteScope || root.growingDashFromPos
453
454 property var restorePosition
455 property var restoreSize
456
457 Behavior on x {
458 enabled: scopesOverviewXYScaler.animationsEnabled
459 UbuntuNumberAnimation { }
460 }
461 Behavior on y {
462 enabled: scopesOverviewXYScaler.animationsEnabled
463 UbuntuNumberAnimation { }
464 }
465 Behavior on opacity {
466 enabled: scopesOverviewXYScaler.animationsEnabled
467 UbuntuNumberAnimation { }
468 }
469 Behavior on scale {
470 enabled: scopesOverviewXYScaler.animationsEnabled
471 UbuntuNumberAnimation {
472 onRunningChanged: {
473 if (!running) {
474 if (root.showingNonFavoriteScope && scopesOverviewXYScaler.scale != 1) {
475 root.scope.closeScope(tempScopeItem.scope);
476 tempScopeItem.scope = null;
477 } else if (root.growingDashFromPos) {
478 root.growingDashFromPos = false;
479 }
480 }
481 }
482 }
483 }
484
485 DashBackground
486 {
487 anchors.fill: tempScopeItem
488 visible: tempScopeItem.visible
489 parent: tempScopeItem.parent
490 }
491
492 GenericScopeView {
493 id: tempScopeItem
494 objectName: "scopesOverviewTempScopeItem"
495
496 width: parent.width
497 height: parent.height
498 scale: dash.contentScale
499 clip: scale != 1.0
500 visible: scope != null
501 hasBackAction: true
502 isCurrent: visible
503 onBackClicked: {
504 var v = scopesOverviewXYScaler.restoreSize.width / tempScopeItem.width;
505 scopesOverviewXYScaler.scale = v;
506 if (scopesOverviewXYScaler.restorePosition) {
507 scopesOverviewXYScaler.x = scopesOverviewXYScaler.restorePosition.x -(tempScopeItem.width - tempScopeItem.width * v) / 2;
508 scopesOverviewXYScaler.y = scopesOverviewXYScaler.restorePosition.y -(tempScopeItem.height - tempScopeItem.height * v) / 2;
509 } else {
510 scopesOverviewXYScaler.x = 0;
511 scopesOverviewXYScaler.y = 0;
512 }
513 scopesOverviewXYScaler.opacity = 0;
514 middleItems.overrideOpacity = -1;
515 }
516 }
517 }
518}
0519
=== added file 'qml/Dash/ScopesOverviewAll.qml'
--- qml/Dash/ScopesOverviewAll.qml 1970-01-01 00:00:00 +0000
+++ qml/Dash/ScopesOverviewAll.qml 2014-07-29 11:27:22 +0000
@@ -0,0 +1,54 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.0
18import Ubuntu.Components 0.1
19
20Flickable {
21 id: root
22
23 property alias model: cardGrid.model
24 property alias cardTool: cardGrid.cardTool
25
26 property real extraHeight: 0
27
28 signal clicked(int index, var result, var item, var itemModel)
29 signal pressAndHold(int index)
30
31 contentHeight: cardGrid.expandedHeight + extraHeight
32 contentWidth: cardGrid.width
33 flickableDirection: Flickable.VerticalFlick
34
35 function scopeCardPosition(scopeId) {
36 var index = model.scopeIndex(scopeId);
37 var pos = cardGrid.cardPosition(index);
38 pos.y = pos.y - root.contentY;
39 return pos;
40 }
41
42 CardGrid {
43 id: cardGrid
44 width: root.width
45 height: parent.height
46
47 onClicked: {
48 root.clicked(index, result, item, itemModel);
49 }
50 onPressAndHold: {
51 root.pressAndHold(index);
52 }
53 }
54}
055
=== added file 'qml/Dash/ScopesOverviewFavorites.qml'
--- qml/Dash/ScopesOverviewFavorites.qml 1970-01-01 00:00:00 +0000
+++ qml/Dash/ScopesOverviewFavorites.qml 2014-07-29 11:27:22 +0000
@@ -0,0 +1,73 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.0
18
19Flickable {
20 id: root
21
22 signal clicked(int index, var result, var itemModel)
23 signal pressAndHold(int index)
24
25 property var cardTool: null
26 property real scopeHeight: 0
27 property real scopeWidth: 0
28 property real appliedScale: 1
29 property int currentIndex: -1
30 property var currentItem: repeater.itemAt(currentIndex);
31
32 property alias model: repeater.model
33
34 contentHeight: height
35 contentWidth: repeater.count * root.scopeWidth + units.gu(2) / appliedScale * (repeater.count - 1)
36
37 contentX: {
38 var indexX = currentIndex * scopeWidth + units.gu(2) / appliedScale * currentIndex;
39 var newContentX = indexX - (width - scopeWidth) / 2;
40 newContentX = Math.min(Math.max(newContentX, 0), contentWidth - width);
41 return newContentX;
42 }
43
44 Repeater {
45 id: repeater
46 objectName: "scopesOverviewFavoritesRepeater"
47
48 delegate: Loader {
49 id: loader
50
51 x: index * root.scopeWidth + units.gu(2) / appliedScale * index
52 asynchronous: true
53
54 sourceComponent: cardTool.cardComponent
55 onLoaded: {
56 item.fixedArtShapeSize = Qt.binding(function() { return Qt.size(root.scopeWidth, root.scopeHeight); });
57 item.fixedHeaderHeight = Qt.binding(function() { return cardTool.headerHeight / appliedScale; });
58 item.fontScale = Qt.binding(function() { return 1 / appliedScale; });
59 item.height = Qt.binding(function() { return root.scopeHeight; });
60 item.width = Qt.binding(function() { return root.scopeWidth; });
61 item.cardData = Qt.binding(function() { return model; });
62 item.template = Qt.binding(function() { return cardTool.template; });
63 item.components = Qt.binding(function() { return cardTool.components; });
64 item.headerAlignment = Qt.binding(function() { return cardTool.headerAlignment; });
65 }
66
67 Connections {
68 target: loader.item
69 onClicked: root.clicked(index, result, model)
70 }
71 }
72 }
73}
074
=== added file 'qml/Dash/ScopesOverviewTab.qml'
--- qml/Dash/ScopesOverviewTab.qml 1970-01-01 00:00:00 +0000
+++ qml/Dash/ScopesOverviewTab.qml 2014-07-29 11:27:22 +0000
@@ -0,0 +1,74 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.3
18import Ubuntu.Components 0.1
19
20Item {
21 id: root
22
23 property int currentTab: 0
24
25 AbstractButton {
26 id: tab1
27 height: parent.height
28 width: parent.width / 2
29 Rectangle {
30 anchors.fill: parent
31 color: root.currentTab == 0 && root.enabled ? "white" : "transparent"
32 radius: units.dp(10)
33 }
34 Label {
35 anchors.centerIn: parent
36 text: i18n.tr("Favorites")
37 color: root.currentTab == 0 && root.enabled ? "black" : "white"
38 }
39 onClicked: root.currentTab = 0
40 }
41 AbstractButton {
42 id: tab2
43 objectName: "scopesOverviewAllTabButton"
44 x: width
45 height: parent.height
46 width: parent.width / 2
47 Rectangle {
48 anchors.fill: parent
49 color: root.currentTab == 1 && root.enabled ? "white" : "transparent"
50 radius: units.dp(10)
51 }
52 Label {
53 anchors.centerIn: parent
54 text: i18n.tr("All")
55 color: root.currentTab == 1 && root.enabled ? "black" : "white"
56 }
57 onClicked: root.currentTab = 1
58 }
59 Rectangle {
60 id: centerPiece
61 width: root.enabled ? units.dp(10) : units.dp(1)
62 height: parent.height
63 color: "white"
64 x: root.currentTab == 1 ? tab2.x : tab2.x - width
65 }
66 Rectangle {
67 id: border
68 anchors.fill: parent
69 radius: units.dp(10)
70 color: "transparent"
71 border.color: centerPiece.color
72 border.width: units.dp(1)
73 }
74}
075
=== added file 'qml/Dash/graphics/apps-scope.png'
1Binary files qml/Dash/graphics/apps-scope.png 1970-01-01 00:00:00 +0000 and qml/Dash/graphics/apps-scope.png 2014-07-29 11:27:22 +0000 differ76Binary files qml/Dash/graphics/apps-scope.png 1970-01-01 00:00:00 +0000 and qml/Dash/graphics/apps-scope.png 2014-07-29 11:27:22 +0000 differ
=== added file 'qml/Dash/graphics/dark_background.jpg'
2Binary files qml/Dash/graphics/dark_background.jpg 1970-01-01 00:00:00 +0000 and qml/Dash/graphics/dark_background.jpg 2014-07-29 11:27:22 +0000 differ77Binary files qml/Dash/graphics/dark_background.jpg 1970-01-01 00:00:00 +0000 and qml/Dash/graphics/dark_background.jpg 2014-07-29 11:27:22 +0000 differ
=== modified file 'qml/Shell.qml'
--- qml/Shell.qml 2014-07-18 15:13:35 +0000
+++ qml/Shell.qml 2014-07-29 11:27:22 +0000
@@ -125,14 +125,6 @@
125 opacity: dash.disappearingAnimationProgress125 opacity: dash.disappearingAnimationProgress
126 }126 }
127127
128 Image {
129 anchors.fill: dash
130 source: shell.width > shell.height ? "Dash/graphics/paper_landscape.png" : "Dash/graphics/paper_portrait.png"
131 fillMode: Image.PreserveAspectCrop
132 horizontalAlignment: Image.AlignRight
133 verticalAlignment: Image.AlignTop
134 }
135
136 Dash {128 Dash {
137 id: dash129 id: dash
138 objectName: "dash"130 objectName: "dash"
@@ -142,6 +134,8 @@
142 shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0134 shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0
143 enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled135 enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled
144136
137 overviewHandleHeight: shell.edgeSize
138
145 anchors {139 anchors {
146 fill: parent140 fill: parent
147 topMargin: panel.panelHeight141 topMargin: panel.panelHeight
148142
=== modified file 'tests/autopilot/unity8/shell/emulators/dash.py'
--- tests/autopilot/unity8/shell/emulators/dash.py 2014-07-25 10:47:19 +0000
+++ tests/autopilot/unity8/shell/emulators/dash.py 2014-07-29 11:27:22 +0000
@@ -18,6 +18,7 @@
18#18#
1919
20import logging20import logging
21import time
21import ubuntuuitoolkit22import ubuntuuitoolkit
2223
23from unity8.shell import emulators24from unity8.shell import emulators
@@ -68,7 +69,9 @@
6869
69 """70 """
70 scope_loader = self._get_scope_loader(scope_id)71 scope_loader = self._get_scope_loader(scope_id)
72 print ("open_scope", scope_id, scope_loader)
71 if scope_loader.isCurrent:73 if scope_loader.isCurrent:
74 print ("scope_loader.isCurrent")
72 logger.info('The scope is already open.')75 logger.info('The scope is already open.')
73 return self._get_scope_from_loader(scope_loader)76 return self._get_scope_from_loader(scope_loader)
74 else:77 else:
@@ -83,6 +86,12 @@
83 'No scope found with id {0}'.format(scope_id))86 'No scope found with id {0}'.format(scope_id))
8487
85 def _get_scope_from_loader(self, loader):88 def _get_scope_from_loader(self, loader):
89 print ("_get_scope_from_loader", loader, loader.isCurrent, loader.isLoaded, loader.get_children())
90 i = 0
91 time.sleep(1)
92 while len(loader.get_children()) < 1 and i < 5:
93 time.sleep(1)
94 i = i + 1
86 return loader.get_children()[0]95 return loader.get_children()[0]
8796
88 def _open_scope_scrolling(self, scope_loader):97 def _open_scope_scrolling(self, scope_loader):
8998
=== modified file 'tests/mocks/Unity/CMakeLists.txt'
--- tests/mocks/Unity/CMakeLists.txt 2014-07-08 09:23:14 +0000
+++ tests/mocks/Unity/CMakeLists.txt 2014-07-29 11:27:22 +0000
@@ -6,7 +6,7 @@
6pkg_search_module(DEE dee-1.0 REQUIRED)6pkg_search_module(DEE dee-1.0 REQUIRED)
7pkg_search_module(GOBJECT gobject-2.0 REQUIRED)7pkg_search_module(GOBJECT gobject-2.0 REQUIRED)
8pkg_search_module(DEEQT libdee-qt5 REQUIRED)8pkg_search_module(DEEQT libdee-qt5 REQUIRED)
9pkg_check_modules(SCOPES_API REQUIRED unity-shell-scopes=2)9pkg_check_modules(SCOPES_API REQUIRED unity-shell-scopes=3)
1010
11include_directories(11include_directories(
12 ${CMAKE_CURRENT_BINARY_DIR}12 ${CMAKE_CURRENT_BINARY_DIR}
@@ -21,6 +21,7 @@
21set(UnityQML_SOURCES21set(UnityQML_SOURCES
22 fake_scope.cpp22 fake_scope.cpp
23 fake_scopes.cpp23 fake_scopes.cpp
24 fake_scopesoverview.cpp
24 fake_categories.cpp25 fake_categories.cpp
25 fake_department.cpp26 fake_department.cpp
26 fake_resultsmodel.cpp27 fake_resultsmodel.cpp
2728
=== modified file 'tests/mocks/Unity/fake_resultsmodel.cpp'
--- tests/mocks/Unity/fake_resultsmodel.cpp 2014-05-20 10:29:20 +0000
+++ tests/mocks/Unity/fake_resultsmodel.cpp 2014-07-29 11:27:22 +0000
@@ -58,8 +58,9 @@
58 case RoleUri:58 case RoleUri:
59 case RoleCategoryId:59 case RoleCategoryId:
60 case RoleDndUri:60 case RoleDndUri:
61 return QString();
61 case RoleResult:62 case RoleResult:
62 return QString();63 return QString("Result.%1.%2").arg(m_categoryId).arg(index.row());
63 case RoleTitle:64 case RoleTitle:
64 return QString("Title.%1.%2").arg(m_categoryId).arg(index.row());65 return QString("Title.%1.%2").arg(m_categoryId).arg(index.row());
65 case RoleArt:66 case RoleArt:
6667
=== 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-07-29 11:27:22 +0000
@@ -14,17 +14,20 @@
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"
21
20#include "fake_department.h"22#include "fake_department.h"
21#include "fake_resultsmodel.h"23#include "fake_resultsmodel.h"
24#include "fake_scopes.h"
2225
23Scope::Scope(QObject* parent) : Scope(QString(), QString(), false, parent)26Scope::Scope(Scopes* parent) : Scope(QString(), QString(), false, parent)
24{27{
25}28}
2629
27Scope::Scope(QString const& id, QString const& name, bool visible, QObject* parent, int categories)30Scope::Scope(QString const& id, QString const& name, bool visible, Scopes* parent, int categories)
28 : unity::shell::scopes::ScopeInterface(parent)31 : unity::shell::scopes::ScopeInterface(parent)
29 , m_id(id)32 , m_id(id)
30 , m_name(name)33 , m_name(name)
@@ -34,6 +37,7 @@
34 , m_currentDeparment("root")37 , m_currentDeparment("root")
35 , m_previewRendererName("preview-generic")38 , m_previewRendererName("preview-generic")
36 , m_categories(new Categories(categories, this))39 , m_categories(new Categories(categories, this))
40 , m_openScope(nullptr)
37{41{
38}42}
3943
@@ -64,7 +68,7 @@
6468
65QString Scope::searchHint() const69QString Scope::searchHint() const
66{70{
67 return QString("");71 return QString("Search %1").arg(m_name);
68}72}
6973
70QString Scope::shortcut() const74QString Scope::shortcut() const
@@ -149,7 +153,12 @@
149153
150void Scope::activate(QVariant const& result)154void Scope::activate(QVariant const& result)
151{155{
152 Q_UNUSED(result);156 qDebug() << "Called activate on scope" << m_id << "with result" << result;
157 if (result.toString() == "Result.2.2") {
158 Scopes *scopes = dynamic_cast<Scopes*>(parent());
159 m_openScope = scopes->getScopeFromAll("MockScope9");
160 Q_EMIT openScope(m_openScope);
161 }
153}162}
154163
155PreviewStack* Scope::preview(QVariant const& result)164PreviewStack* Scope::preview(QVariant const& result)
@@ -165,9 +174,13 @@
165{174{
166}175}
167176
168void Scope::closeScope(unity::shell::scopes::ScopeInterface* /*scope*/)177void Scope::closeScope(unity::shell::scopes::ScopeInterface* scope)
169{178{
170 qFatal("Scope::closeScope is not implemented");179 if (scope != m_openScope) {
180 qDebug() << scope << m_openScope;
181 qFatal("Scope::closeScope got wrong scope in closeScope");
182 }
183 m_openScope = nullptr;
171}184}
172185
173QString Scope::currentDepartmentId() const186QString Scope::currentDepartmentId() const
174187
=== 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-07-29 11:27:22 +0000
@@ -24,13 +24,15 @@
2424
25#include <QTimer>25#include <QTimer>
2626
27class Scopes;
28
27class Scope : public unity::shell::scopes::ScopeInterface29class Scope : public unity::shell::scopes::ScopeInterface
28{30{
29 Q_OBJECT31 Q_OBJECT
3032
31public:33public:
32 Scope(QObject* parent = 0);34 Scope(Scopes* parent = 0);
33 Scope(QString const& id, QString const& name, bool visible, QObject* parent = 0, int categories = 20);35 Scope(QString const& id, QString const& name, bool visible, Scopes* parent = 0, int categories = 20);
3436
35 /* getters */37 /* getters */
36 QString id() const override;38 QString id() const override;
@@ -84,7 +86,8 @@
8486
85 QString m_previewRendererName;87 QString m_previewRendererName;
8688
87 Categories* m_categories;89 unity::shell::scopes::CategoriesInterface* m_categories;
90 unity::shell::scopes::ScopeInterface* m_openScope;
88};91};
8992
90#endif // FAKE_SCOPE_H93#endif // FAKE_SCOPE_H
9194
=== modified file 'tests/mocks/Unity/fake_scopes.cpp'
--- tests/mocks/Unity/fake_scopes.cpp 2014-07-11 11:45:45 +0000
+++ tests/mocks/Unity/fake_scopes.cpp 2014-07-29 11:27:22 +0000
@@ -18,6 +18,7 @@
1818
19// Self19// Self
20#include "fake_scopes.h"20#include "fake_scopes.h"
21#include "fake_scopesoverview.h"
2122
22// TODO: Implement remaining pieces, like Categories (i.e. LensView now gives warnings)23// TODO: Implement remaining pieces, like Categories (i.e. LensView now gives warnings)
2324
@@ -26,6 +27,7 @@
2627
27Scopes::Scopes(QObject *parent)28Scopes::Scopes(QObject *parent)
28 : unity::shell::scopes::ScopesInterface(parent)29 : unity::shell::scopes::ScopesInterface(parent)
30 , m_scopesOverview(nullptr)
29 , m_loaded(false)31 , m_loaded(false)
30 , timer(this)32 , timer(this)
31{33{
@@ -47,10 +49,17 @@
47 addScope(new Scope("clickscope", "Apps", true, this));49 addScope(new Scope("clickscope", "Apps", true, this));
48 addScope(new Scope("MockScope5", "Videos", true, this));50 addScope(new Scope("MockScope5", "Videos", true, this));
49 addScope(new Scope("SingleCategoryScope", "Single", true, this, 1));51 addScope(new Scope("SingleCategoryScope", "Single", true, this, 1));
52 addScope(new Scope("MockScope4", "MS4", true, this));
53 addScope(new Scope("MockScope6", "MS6", true, this));
54 addScope(new Scope("MockScope7", "MS7", false, this));
55 addScope(new Scope("MockScope8", "MS8", false, this));
56 addScope(new Scope("MockScope9", "MS9", false, this));
57 m_scopesOverview = new ScopesOverview(this);
5058
51 if (!m_loaded) {59 if (!m_loaded) {
52 m_loaded = true;60 m_loaded = true;
53 Q_EMIT loadedChanged();61 Q_EMIT loadedChanged();
62 Q_EMIT overviewScopeChanged();
54 }63 }
55}64}
5665
@@ -63,6 +72,8 @@
63 m_scopes.clear();72 m_scopes.clear();
64 endRemoveRows();73 endRemoveRows();
65 }74 }
75 delete m_scopesOverview;
76 m_scopesOverview = nullptr;
6677
67 if (m_loaded) {78 if (m_loaded) {
68 m_loaded = false;79 m_loaded = false;
@@ -110,8 +121,22 @@
110 return m_scopes[row];121 return m_scopes[row];
111}122}
112123
113unity::shell::scopes::ScopeInterface* Scopes::getScope(QString const&) const124unity::shell::scopes::ScopeInterface* Scopes::getScope(QString const &scope_id) const
114{125{
126 for (Scope *scope : m_scopes) {
127 // According to mh3 Scopes::getScope should only return non null for visible scopes
128 if (scope->id() == scope_id && scope->visible())
129 return scope;
130 }
131 return nullptr;
132}
133
134unity::shell::scopes::ScopeInterface* Scopes::getScopeFromAll(const QString& scope_id) const
135{
136 for (Scope *scope : m_scopes) {
137 if (scope->id() == scope_id)
138 return scope;
139 }
115 return nullptr;140 return nullptr;
116}141}
117142
@@ -125,6 +150,22 @@
125 return m_loaded;150 return m_loaded;
126}151}
127152
153unity::shell::scopes::ScopeInterface* Scopes::overviewScope() const
154{
155 return m_scopesOverview;
156}
157
158QList<unity::shell::scopes::ScopeInterface *> Scopes::scopes(bool onlyVisible) const
159{
160 QList<unity::shell::scopes::ScopeInterface *> res;
161 for (Scope *scope : m_scopes) {
162 if (!onlyVisible || scope->visible()) {
163 res << scope;
164 }
165 }
166 return res;
167}
168
128void Scopes::addScope(Scope* scope)169void Scopes::addScope(Scope* scope)
129{170{
130 int index = rowCount();171 int index = rowCount();
131172
=== modified file 'tests/mocks/Unity/fake_scopes.h'
--- tests/mocks/Unity/fake_scopes.h 2014-05-20 14:48:08 +0000
+++ tests/mocks/Unity/fake_scopes.h 2014-07-29 11:27:22 +0000
@@ -50,12 +50,18 @@
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 unity::shell::scopes::ScopeInterface* overviewScope() const override;
54
55 // This is used as part of implementation of the other C++ code, not API
56 QList<unity::shell::scopes::ScopeInterface *> scopes(bool onlyVisible) const;
57 unity::shell::scopes::ScopeInterface* getScopeFromAll(const QString& scope_id) const;
5358
54private Q_SLOTS:59private Q_SLOTS:
55 void updateScopes();60 void updateScopes();
5661
57private:62private:
58 QList<Scope*> m_scopes;63 QList<Scope*> m_scopes;
64 Scope *m_scopesOverview;
59 bool m_loaded;65 bool m_loaded;
60 QTimer timer;66 QTimer timer;
61};67};
6268
=== added file 'tests/mocks/Unity/fake_scopesoverview.cpp'
--- tests/mocks/Unity/fake_scopesoverview.cpp 1970-01-01 00:00:00 +0000
+++ tests/mocks/Unity/fake_scopesoverview.cpp 2014-07-29 11:27:22 +0000
@@ -0,0 +1,280 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "fake_scopesoverview.h"
18
19#include "fake_scopes.h"
20
21#include <paths.h>
22
23ScopesOverview::ScopesOverview(Scopes* parent)
24 : Scope("scopesOverview", "Scopes Overview", false, parent)
25{
26 delete m_categories; // delete the usual categories, we're not going to use it
27 m_scopesOverviewCategories = new ScopesOverviewCategories(parent, this);
28 m_searchCategories = new ScopesOverviewSearchCategories(parent, this);
29 m_categories = m_scopesOverviewCategories;
30}
31
32void ScopesOverview::setSearchQuery(const QString& search_query)
33{
34 Scope::setSearchQuery(search_query);
35
36 auto origCategories = m_categories;
37 if (search_query.isEmpty()) m_categories = m_scopesOverviewCategories;
38 else m_categories = m_searchCategories;
39
40 if (m_categories != origCategories)
41 Q_EMIT categoriesChanged();
42}
43
44Q_INVOKABLE void ScopesOverview::activate(QVariant const& result)
45{
46 Scopes *scopes = dynamic_cast<Scopes*>(parent());
47 m_openScope = scopes->getScopeFromAll(result.toString());
48 Q_EMIT openScope(m_openScope);
49}
50
51ScopesOverviewCategories::ScopesOverviewCategories(Scopes *scopes, QObject* parent)
52 : unity::shell::scopes::CategoriesInterface(parent)
53 , m_scopes(scopes)
54{
55}
56
57int ScopesOverviewCategories::rowCount(const QModelIndex& /*parent*/) const
58{
59 return 2;
60}
61
62void ScopesOverviewCategories::addSpecialCategory(QString const&, QString const&, QString const&, QString const&, QObject*)
63{
64 qFatal("Using un-implemented ScopesOverviewCategories::addSpecialCategory");
65}
66
67bool ScopesOverviewCategories::overrideCategoryJson(QString const& /* categoryId */, QString const& /* json */)
68{
69 qFatal("Using un-implemented ScopesOverviewCategories::overrideCategoryJson");
70}
71
72QVariant
73ScopesOverviewCategories::data(const QModelIndex& index, int role) const
74{
75 if (!index.isValid()) {
76 return QVariant();
77 }
78
79 const QString categoryId = index.row() == 0 ? "favorites" : "all";
80
81 unity::shell::scopes::ResultsModelInterface *resultsModel = m_resultsModels[index.row()];
82 if (!resultsModel) {
83 QObject *that = const_cast<ScopesOverviewCategories*>(this);
84 resultsModel = new ScopesOverviewResultsModel(m_scopes->scopes(index.row() == 0), categoryId, that);
85 m_resultsModels[index.row()] = resultsModel;
86 }
87 switch (role) {
88 case RoleCategoryId:
89 return categoryId;
90 case RoleName:
91 return index.row() == 0 ? "Favorites" : "All";
92 case RoleIcon:
93 return QVariant();
94 case RoleRawRendererTemplate:
95 qFatal("Using un-implemented RoleRawRendererTemplate Categories role");
96 return QVariant();
97 case RoleRenderer:
98 {
99 QVariantMap map;
100 map["category-layout"] = "grid";
101 map["card-size"] = "small";
102 map["overlay"] = true;
103 return map;
104 }
105 case RoleComponents:
106 {
107 QVariantMap map, artMap;
108 artMap["aspect-ratio"] = "0.5";
109 artMap["field"] = "art";
110 map["art"] = artMap;
111 map["title"] = "HOLA";
112 return map;
113 }
114 case RoleResults:
115 return QVariant::fromValue(resultsModel);
116 case RoleCount:
117 return resultsModel->rowCount();
118 case RoleHeaderLink:
119 return QString();
120 default:
121 qFatal("Using un-implemented Categories role");
122 return QVariant();
123 }
124}
125
126
127
128ScopesOverviewSearchCategories::ScopesOverviewSearchCategories(Scopes *scopes, QObject* parent)
129 : unity::shell::scopes::CategoriesInterface(parent)
130 , m_scopes(scopes)
131{
132}
133
134int ScopesOverviewSearchCategories::rowCount(const QModelIndex& /*parent*/) const
135{
136 return 2;
137}
138
139void ScopesOverviewSearchCategories::addSpecialCategory(QString const&, QString const&, QString const&, QString const&, QObject*)
140{
141 qFatal("Using un-implemented ScopesOverviewSearchCategories::addSpecialCategory");
142}
143
144bool ScopesOverviewSearchCategories::overrideCategoryJson(QString const& /* categoryId */, QString const& /* json */)
145{
146 qFatal("Using un-implemented ScopesOverviewSearchCategories::overrideCategoryJson");
147}
148
149QVariant
150ScopesOverviewSearchCategories::data(const QModelIndex& index, int role) const
151{
152 if (!index.isValid()) {
153 return QVariant();
154 }
155
156 const QString categoryId = index.row() == 0 ? "searchA" : "searchB";
157
158 unity::shell::scopes::ResultsModelInterface *resultsModel = m_resultsModels[index.row()];
159 if (!resultsModel) {
160 QObject *that = const_cast<ScopesOverviewSearchCategories*>(this);
161 QList<unity::shell::scopes::ScopeInterface *> scopes;
162 if (index.row() == 0) {
163 scopes << m_scopes->getScopeFromAll("clickscope") << nullptr << m_scopes->getScopeFromAll("MockScope2");
164 } else {
165 scopes << nullptr << m_scopes->getScopeFromAll("MockScope7") << nullptr << m_scopes->getScopeFromAll("MockScope1");
166 }
167 resultsModel = new ScopesOverviewResultsModel(scopes, categoryId, that);
168 m_resultsModels[index.row()] = resultsModel;
169 }
170 switch (role) {
171 case RoleCategoryId:
172 return categoryId;
173 case RoleName:
174 return index.row() == 0 ? "SearchA" : "SearchB";
175 case RoleIcon:
176 return QVariant();
177 case RoleRawRendererTemplate:
178 qFatal("Using un-implemented RoleRawRendererTemplate Categories role");
179 return QVariant();
180 case RoleRenderer:
181 {
182 QVariantMap map;
183 map["category-layout"] = "grid";
184 map["card-size"] = "small";
185 map["overlay"] = true;
186 return map;
187 }
188 case RoleComponents:
189 {
190 QVariantMap map, artMap;
191 artMap["aspect-ratio"] = "1";
192 artMap["field"] = "art";
193 map["art"] = artMap;
194 map["title"] = "HOLA";
195 return map;
196 }
197 case RoleResults:
198 return QVariant::fromValue(resultsModel);
199 case RoleCount:
200 return resultsModel->rowCount();
201 case RoleHeaderLink:
202 return QString();
203 default:
204 qFatal("Using un-implemented Categories role");
205 return QVariant();
206 }
207}
208
209
210ScopesOverviewResultsModel::ScopesOverviewResultsModel(const QList<unity::shell::scopes::ScopeInterface *> &scopes, const QString &categoryId, QObject* parent)
211 : unity::shell::scopes::ResultsModelInterface(parent)
212 , m_scopes(scopes)
213 , m_categoryId(categoryId)
214{
215}
216
217QString ScopesOverviewResultsModel::categoryId() const
218{
219 return m_categoryId;
220}
221
222void ScopesOverviewResultsModel::setCategoryId(QString const& /*id*/)
223{
224 qFatal("Calling un-implemented ScopesOverviewResultsModel::setCategoryId");
225}
226
227int ScopesOverviewResultsModel::scopeIndex(QString const& id) const
228{
229 const int scopeCount = count();
230 for (int i = 0; i < scopeCount; ++i) {
231 if (m_scopes[i]->id() == id)
232 return i;
233 }
234 return -1;
235}
236
237QHash<int, QByteArray> ScopesOverviewResultsModel::roleNames() const
238{
239 QHash<int, QByteArray> roles = unity::shell::scopes::ResultsModelInterface::roleNames();
240 roles[RoleBackground + 1] = "scopeId";
241 return roles;
242}
243
244int ScopesOverviewResultsModel::rowCount(const QModelIndex& parent) const
245{
246 Q_UNUSED(parent);
247
248 return m_scopes.count();
249}
250
251int ScopesOverviewResultsModel::count() const
252{
253 return rowCount();
254}
255
256QVariant
257ScopesOverviewResultsModel::data(const QModelIndex& index, int role) const
258{
259 unity::shell::scopes::ScopeInterface *scope = m_scopes[index.row()];
260 switch (role) {
261 case RoleUri:
262 case RoleCategoryId:
263 case RoleDndUri:
264 return QString();
265 case RoleResult:
266 return scope ? scope->id() : QString("Result.%1.%2").arg(categoryId()).arg(index.row());
267 case RoleTitle:
268 return scope ? scope->name() : QString("Title.%1.%2").arg(categoryId()).arg(index.row());
269 case RoleArt:
270 return qmlDirectory() + "graphics/applicationIcons/dash.png";
271 case RoleMascot:
272 case RoleEmblem:
273 case RoleSummary:
274 case RoleBackground + 1: // scopeId
275 return scope ? scope->id() : nullptr;
276 break;
277 default:
278 return QVariant();
279 }
280}
0281
=== added file 'tests/mocks/Unity/fake_scopesoverview.h'
--- tests/mocks/Unity/fake_scopesoverview.h 1970-01-01 00:00:00 +0000
+++ tests/mocks/Unity/fake_scopesoverview.h 2014-07-29 11:27:22 +0000
@@ -0,0 +1,104 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef FAKE_SCOPESOVERVIEW_H
18#define FAKE_SCOPESOVERVIEW_H
19
20#include "fake_scope.h"
21#include <unity/shell/scopes/ResultsModelInterface.h>
22
23class Scopes;
24
25class ScopesOverview : public Scope
26{
27 Q_OBJECT
28
29public:
30 ScopesOverview(Scopes* parent = 0);
31
32 void setSearchQuery(const QString& search_query) override;
33 Q_INVOKABLE void activate(QVariant const& result) override;
34
35private:
36 unity::shell::scopes::CategoriesInterface *m_scopesOverviewCategories;
37 unity::shell::scopes::CategoriesInterface *m_searchCategories;
38};
39
40class ScopesOverviewCategories : public unity::shell::scopes::CategoriesInterface
41{
42 Q_OBJECT
43
44public:
45 ScopesOverviewCategories(Scopes *scopes, QObject* parent = 0);
46
47 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
48 int rowCount(const QModelIndex& parent = QModelIndex()) const override;
49
50 Q_INVOKABLE void addSpecialCategory(QString const& categoryId, QString const& name, QString const& icon, QString const& rawTemplate, QObject* countObject) override;
51 Q_INVOKABLE bool overrideCategoryJson(QString const& categoryId, QString const& json) override;
52
53private:
54 mutable QHash<int, unity::shell::scopes::ResultsModelInterface*> m_resultsModels;
55
56 Scopes *m_scopes;
57};
58
59class ScopesOverviewSearchCategories : public unity::shell::scopes::CategoriesInterface
60{
61 Q_OBJECT
62
63public:
64 ScopesOverviewSearchCategories(Scopes *scopes, QObject* parent = 0);
65
66 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
67 int rowCount(const QModelIndex& parent = QModelIndex()) const override;
68
69 Q_INVOKABLE void addSpecialCategory(QString const& categoryId, QString const& name, QString const& icon, QString const& rawTemplate, QObject* countObject) override;
70 Q_INVOKABLE bool overrideCategoryJson(QString const& categoryId, QString const& json) override;
71
72private:
73 mutable QHash<int, unity::shell::scopes::ResultsModelInterface*> m_resultsModels;
74
75 Scopes *m_scopes;
76};
77
78class ScopesOverviewResultsModel : public unity::shell::scopes::ResultsModelInterface
79{
80 Q_OBJECT
81
82public:
83 explicit ScopesOverviewResultsModel(const QList<unity::shell::scopes::ScopeInterface *> &scopes, const QString &categoryId, QObject* parent = 0);
84
85 int rowCount(const QModelIndex& parent = QModelIndex()) const override;
86 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
87
88 /* getters */
89 QString categoryId() const override;
90 int count() const override;
91
92 /* setters */
93 void setCategoryId(QString const& id) override;
94
95 /* Special API */
96 Q_INVOKABLE int scopeIndex(QString const& id) const;
97 QHash<int, QByteArray> roleNames() const override;
98
99private:
100 QList<unity::shell::scopes::ScopeInterface *> m_scopes;
101 QString m_categoryId;
102};
103
104#endif // FAKE_SCOPESOVERVIEW_H
0105
=== modified file 'tests/plugins/Dash/cardcreator/5.res'
--- tests/plugins/Dash/cardcreator/5.res 2014-07-08 12:37:34 +0000
+++ tests/plugins/Dash/cardcreator/5.res 2014-07-29 11:27:22 +0000
@@ -109,6 +109,7 @@
109 anchors { left: parent.left; 109 anchors { left: parent.left;
110 leftMargin: units.gu(1); 110 leftMargin: units.gu(1);
111 right: parent.right; 111 right: parent.right;
112 rightMargin: units.gu(1);
112 top: overlayLoader.top; 113 top: overlayLoader.top;
113 topMargin: units.gu(1);114 topMargin: units.gu(1);
114}115}
115116
=== modified file 'tests/qmltests/Components/tst_PageHeader.qml'
--- tests/qmltests/Components/tst_PageHeader.qml 2014-07-08 08:30:46 +0000
+++ tests/qmltests/Components/tst_PageHeader.qml 2014-07-29 11:27:22 +0000
@@ -36,6 +36,16 @@
3636
37 function init() {37 function init() {
38 searchEnabled = true;38 searchEnabled = true;
39
40 // Reset to initial state
41 pageHeader.searchQuery = "";
42 pageHeader.closePopup();
43 pageHeader.searchHistory.clear();
44
45 // Check initial state
46 var headerContainer = findChild(pageHeader, "headerContainer");
47 tryCompareFunction(function() { return headerContainer.popover === null; }, true);
48 compare(pageHeader.searchHistory.count, 0);
39 }49 }
4050
41 function test_search_disabled() {51 function test_search_disabled() {
@@ -80,9 +90,6 @@
80 }90 }
8191
82 function test_history() {92 function test_history() {
83 pageHeader.searchHistory.clear()
84 compare(pageHeader.searchHistory.count, 0)
85
86 pageHeader.triggerSearch()93 pageHeader.triggerSearch()
87 typeString("humppa1")94 typeString("humppa1")
88 pageHeader.resetSearch()95 pageHeader.resetSearch()
@@ -166,16 +173,26 @@
166 tryCompareFunction(function() { return headerContainer.popover !== null; }, true);173 tryCompareFunction(function() { return headerContainer.popover !== null; }, true);
167174
168 tryCompare(headerContainer.popover, "visible", true);175 tryCompare(headerContainer.popover, "visible", true);
176
177 var searchTextField = findChild(pageHeader, "searchTextField");
178 compare(searchTextField.focus, true);
179
180 var recentSearches = findChild(headerContainer.popover, "recentSearches");
181 mouseClick(recentSearches.itemAt(0), 0, 0);
182
183 compare(pageHeader.searchQuery, "Search2");
184 tryCompareFunction(function() { return headerContainer.popover === null; }, true);
185 compare(searchTextField.focus, false);
169 }186 }
170187
171 function test_tap_outside_closes_popup_data() {188 function test_popup_closing_data() {
172 return [189 return [
173 { tag: "with search text", searchText: "foobar", hideSearch: false },190 { tag: "with search text", searchText: "foobar", hideSearch: false },
174 { tag: "without search text", searchText: "", hideSearch: true }191 { tag: "without search text", searchText: "", hideSearch: true }
175 ];192 ];
176 }193 }
177194
178 function test_tap_outside_closes_popup(data) {195 function test_popup_closing(data) {
179 searchEnabled = true;196 searchEnabled = true;
180 pageHeader.searchHistory.clear();197 pageHeader.searchHistory.clear();
181198
@@ -191,13 +208,26 @@
191208
192 pageHeader.searchQuery = data.searchText;209 pageHeader.searchQuery = data.searchText;
193210
194 mouseClick(root, root.width / 2, root.height - 1);211 if (data.searchText == "") {
212 // When the text is empty the user can also close the
213 // popup by clicking outside the header instead of by starting a search
214 mouseClick(root, root.width / 2, root.height - 1);
215 }
195216
196 tryCompare(headerContainer, "showSearch", !data.hideSearch);217 tryCompare(headerContainer, "showSearch", !data.hideSearch);
197 tryCompareFunction(function() { return headerContainer.popover === null; }, true);218 tryCompareFunction(function() { return headerContainer.popover === null; }, true);
198219
199 pageHeader.resetSearch();220 pageHeader.resetSearch();
200 }221 }
222
223 function test_search_change_shows_search() {
224 var headerContainer = findChild(pageHeader, "headerContainer");
225 compare(headerContainer.showSearch, false);
226 compare(searchQuery, "");
227
228 searchQuery = "H";
229 compare(headerContainer.showSearch, true);
230 }
201 }231 }
202232
203 Column {233 Column {
204234
=== modified file 'tests/qmltests/Dash/tst_Dash.qml'
--- tests/qmltests/Dash/tst_Dash.qml 2014-07-11 11:45:45 +0000
+++ tests/qmltests/Dash/tst_Dash.qml 2014-07-29 11:27:22 +0000
@@ -20,8 +20,6 @@
20import Ubuntu.Components 0.120import Ubuntu.Components 0.1
21import Unity.Test 0.1 as UT21import Unity.Test 0.1 as UT
2222
23// TODO We don't have any tests for the overlay scope functionality.
24
25Item {23Item {
26 id: shell24 id: shell
27 width: units.gu(40)25 width: units.gu(40)
@@ -86,10 +84,220 @@
86 tryCompare(dashContentList, "count", 0);84 tryCompare(dashContentList, "count", 0);
87 scopes.load();85 scopes.load();
88 tryCompare(scopes, "loaded", true);86 tryCompare(scopes, "loaded", true);
89 tryCompare(dashContentList, "count", 4);87 tryCompare(dashContentList, "count", 6);
9088
91 verify(dashContentList != undefined);89 verify(dashContentList != undefined);
92 tryCompare(dashContentList, "currentIndex", data.visualIndex);90 tryCompare(dashContentList, "currentIndex", data.visualIndex);
93 }91 }
92
93 function test_dash_overview_show_select_same_favorite() {
94 // Wait for stuff to be loaded
95 tryCompare(scopes, "loaded", true);
96 var dashContentList = findChild(dash, "dashContentList");
97 tryCompare(dashContentList, "count", 6);
98 var mockScope1Loader = findChild(dash, "MockScope1 loader");
99 tryCompareFunction(function() { return mockScope1Loader.item != null; }, true);
100
101 // Show the overview
102 touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
103 var overviewController = findInvisibleChild(dash, "overviewController");
104 tryCompare(overviewController, "progress", 1);
105
106 // Make sure tab is where it should
107 var scopesOverview = findChild(dash, "scopesOverview");
108 compare(scopesOverview.currentTab, 0);
109
110 // Make sure stuff is loaded
111 var scopesOverviewFavoritesRepeater = findChild(dash, "scopesOverviewFavoritesRepeater");
112 tryCompare(scopesOverviewFavoritesRepeater, "count", 6);
113 tryCompareFunction(function() { return scopesOverviewFavoritesRepeater.itemAt(0).item != null; }, true);
114 waitForRendering(scopesOverviewFavoritesRepeater.itemAt(0).item);
115
116 // Click in first item
117 mouseClick(scopesOverviewFavoritesRepeater.itemAt(0).item, 0, 0);
118
119 // Make sure animation went back
120 tryCompare(overviewController, "progress", 0);
121 compare(dashContentList.currentIndex, 0);
122 }
123
124 function test_dash_overview_show_select_different_favorite() {
125 // Wait for stuff to be loaded
126 tryCompare(scopes, "loaded", true);
127 var dashContentList = findChild(dash, "dashContentList");
128 tryCompare(dashContentList, "count", 6);
129 var mockScope1Loader = findChild(dash, "MockScope1 loader");
130 tryCompareFunction(function() { return mockScope1Loader.item != null; }, true);
131
132 // Show the overview
133 touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
134 var overviewController = findInvisibleChild(dash, "overviewController");
135 tryCompare(overviewController, "progress", 1);
136
137 // Make sure tab is where it should
138 var scopesOverview = findChild(dash, "scopesOverview");
139 compare(scopesOverview.currentTab, 0);
140
141 // Make sure stuff is loaded
142 var scopesOverviewFavoritesRepeater = findChild(dash, "scopesOverviewFavoritesRepeater");
143 tryCompare(scopesOverviewFavoritesRepeater, "count", 6);
144 tryCompareFunction(function() { return scopesOverviewFavoritesRepeater.itemAt(0).item != null; }, true);
145 waitForRendering(scopesOverviewFavoritesRepeater.itemAt(1).item);
146
147 // Click in first item
148 mouseClick(scopesOverviewFavoritesRepeater.itemAt(1).item, 0, 0);
149
150 // Make sure animation went back
151 tryCompare(overviewController, "progress", 0);
152 compare(dashContentList.currentIndex, 1);
153 }
154
155 function test_dash_overview_all_temp_scope_done_from_all() {
156 // Wait for stuff to be loaded
157 tryCompare(scopes, "loaded", true);
158 var dashContentList = findChild(dash, "dashContentList");
159 tryCompare(dashContentList, "count", 6);
160 var mockScope1Loader = findChild(dash, "MockScope1 loader");
161 tryCompareFunction(function() { return mockScope1Loader.item != null; }, true);
162
163 // Show the overview
164 touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
165 var overviewController = findInvisibleChild(dash, "overviewController");
166 tryCompare(overviewController, "progress", 1);
167
168 // Make sure tab is where it should
169 var scopesOverview = findChild(dash, "scopesOverview");
170 compare(scopesOverview.currentTab, 0);
171
172 // Make sure stuff is loaded
173 var scopesOverviewFavoritesRepeater = findChild(dash, "scopesOverviewFavoritesRepeater");
174 tryCompare(scopesOverviewFavoritesRepeater, "count", 6);
175 tryCompareFunction(function() { return scopesOverviewFavoritesRepeater.itemAt(0).item != null; }, true);
176 waitForRendering(scopesOverviewFavoritesRepeater.itemAt(1).item);
177
178 // Click on the all tab
179 var scopesOverviewAllTabButton = findChild(dash, "scopesOverviewAllTabButton");
180 mouseClick(scopesOverviewAllTabButton, 0, 0);
181
182 // Wait for all tab to be enabled (animation finish)
183 var scopesOverviewAllView = findChild(dash, "scopesOverviewRepeaterChild1");
184 tryCompare(scopesOverviewAllView, "enabled", true);
185
186 // Click on a temp scope
187 var tempScopeCard = findChild(scopesOverviewAllView, "delegate1");
188 mouseClick(tempScopeCard, 0, 0);
189
190 // Check the bottom edge (overview) is disabled from temp scope
191 var overviewDragHandle = findChild(dash, "overviewDragHandle");
192 compare(overviewDragHandle.enabled, false);
193
194 // Check temp scope is there
195 var scopesOverviewTempScopeItem = findChild(dash, "scopesOverviewTempScopeItem");
196 tryCompareFunction( function() { return scopesOverviewTempScopeItem.scope != null; }, true);
197 tryCompare(scopesOverviewTempScopeItem, "enabled", true);
198
199 // Go back
200 var scopesOverviewTempScopeItemHeader = findChild(scopesOverviewTempScopeItem, "scopePageHeader");
201 var backButton = findChild(findChild(scopesOverviewTempScopeItemHeader, "innerPageHeader"), "backButton");
202 mouseClick(backButton, 0, 0);
203
204 // Check temp scope is gone
205 var scopesOverviewTempScopeItem = findChild(dash, "scopesOverviewTempScopeItem");
206 tryCompareFunction( function() { return scopesOverviewTempScopeItem.scope == null; }, true);
207 tryCompare(scopesOverviewTempScopeItem, "enabled", false);
208
209 // Press on done
210 var scopesOverviewDoneButton = findChild(scopesOverview, "scopesOverviewDoneButton");
211 mouseClick(scopesOverviewDoneButton, 0, 0);
212
213 // Check the dash overview is gone
214 tryCompare(overviewController, "progress", 0);
215
216 // Original list is still on 0
217 compare(dashContentList.currentIndex, 0);
218 }
219
220 function test_temp_scope_dash_overview_all_search_temp_scope_favorite_from_all() {
221 // Wait for stuff to be loaded
222 tryCompare(scopes, "loaded", true);
223 var dashContentList = findChild(dash, "dashContentList");
224 tryCompare(dashContentList, "count", 6);
225 var mockScope1Loader = findChild(dash, "MockScope1 loader");
226 tryCompareFunction(function() { return mockScope1Loader.item != null; }, true);
227
228 // Swipe right to Apps scope
229 touchFlick(dash, dash.width - 1, units.gu(1), dash.width - units.gu(10), units.gu(1));
230 tryCompare(dashContentList, "contentX", dashContentList.width);
231 tryCompare(dashContentList, "currentIndex", 1);
232
233 // Click on card that opens temp scope
234 var dashCategory2 = findChild(dashContentList.currentItem, "dashCategory2");
235 var card2 = findChild(dashCategory2, "delegate2");
236 waitForRendering(card2);
237 mouseClick(card2, card2.width / 2, card2.height / 2);
238
239 // Wait for temp scope to be there
240 var dashTempScopeItem = findChild(dash, "dashTempScopeItem");
241 tryCompare(dashTempScopeItem, "x", 0);
242
243 // Show the overview
244 touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
245 var overviewController = findInvisibleChild(dash, "overviewController");
246 tryCompare(overviewController, "progress", 1);
247
248 // Make sure tab is where it should
249 var scopesOverview = findChild(dash, "scopesOverview");
250 compare(scopesOverview.currentTab, 1);
251
252 // Do a search
253 var scopesOverviewPageHeader = findChild(scopesOverview, "scopesOverviewPageHeader");
254 var searchButton = findChild(scopesOverviewPageHeader, "search_header_button");
255 mouseClick(searchButton, 0, 0);
256
257 // Type something
258 keyClick(Qt.Key_H);
259
260 // Check results grid is there and the other lists are not
261 var searchResultsViewer = findChild(scopesOverview, "searchResultsViewer");
262 var scopesOverviewRepeater = findChild(dash, "scopesOverviewRepeater");
263 tryCompare(searchResultsViewer, "opacity", 1);
264 tryCompare(scopesOverviewRepeater, "count", 0);
265
266 // Click on a temp scope in the search
267 var dashCategorysearchA = findChild(searchResultsViewer, "dashCategorysearchA");
268 var cardTempScope = findChild(dashCategorysearchA, "delegate2");
269 waitForRendering(cardTempScope);
270 mouseClick(cardTempScope, cardTempScope.width / 2, cardTempScope.height / 2);
271
272 // Check the bottom edge (overview) is disabled from temp scope
273 var overviewDragHandle = findChild(dash, "overviewDragHandle");
274 compare(overviewDragHandle.enabled, false);
275
276 // Check temp scope is there
277 var scopesOverviewTempScopeItem = findChild(dash, "scopesOverviewTempScopeItem");
278 tryCompareFunction( function() { return scopesOverviewTempScopeItem.scope != null; }, true);
279 tryCompare(scopesOverviewTempScopeItem, "enabled", true);
280
281 // Go back
282 var scopesOverviewTempScopeItemHeader = findChild(scopesOverviewTempScopeItem, "scopePageHeader");
283 var backButton = findChild(findChild(scopesOverviewTempScopeItemHeader, "innerPageHeader"), "backButton");
284 mouseClick(backButton, 0, 0);
285
286 // Check temp scope is gone
287 var scopesOverviewTempScopeItem = findChild(dash, "scopesOverviewTempScopeItem");
288 tryCompareFunction( function() { return scopesOverviewTempScopeItem.scope == null; }, true);
289 tryCompare(scopesOverviewTempScopeItem, "enabled", false);
290
291 // Press on a favorite
292 var dashCategorysearchB = findChild(searchResultsViewer, "dashCategorysearchB");
293 var cardFavSearch = findChild(dashCategorysearchB, "delegate3");
294 mouseClick(cardFavSearch, 0, 0);
295
296 // Check the dash overview is gone
297 tryCompare(overviewController, "progress", 0);
298
299 // Original list went to the favorite
300 compare(dashContentList.currentIndex, 0);
301 }
94 }302 }
95}303}
96304
=== 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-07-29 11:27:22 +0000
@@ -73,7 +73,7 @@
73 function loadScopes() {73 function loadScopes() {
74 scopeLoadedSpy.clear();74 scopeLoadedSpy.clear();
75 scopesModel.load();75 scopesModel.load();
76 tryCompare(scopeLoadedSpy, "count", 4);76 tryCompare(scopeLoadedSpy, "count", 10);
77 }77 }
7878
79 function init() {79 function init() {
@@ -117,7 +117,8 @@
117117
118 loadScopes();118 loadScopes();
119119
120 verify(dashContentList.currentIndex >= 0 && dashContentList.currentIndex < 5);120 compare(dashContentList.count, 10);
121 verify(dashContentList.currentIndex >= 0 && dashContentList.currentIndex < dashContentList.count);
121 }122 }
122123
123 function test_show_header_on_list_movement() {124 function test_show_header_on_list_movement() {
@@ -173,7 +174,7 @@
173174
174 // test greater than scope count.175 // test greater than scope count.
175 var currentScopeIndex = dashContent.currentIndex;176 var currentScopeIndex = dashContent.currentIndex;
176 dashContent.setCurrentScopeAtIndex(8, true, false);177 dashContent.setCurrentScopeAtIndex(18, true, false);
177 compare(dashContent.currentIndex, currentScopeIndex, "Scope should not change if changing to greater index than count");178 compare(dashContent.currentIndex, currentScopeIndex, "Scope should not change if changing to greater index than count");
178 }179 }
179180
@@ -380,5 +381,17 @@
380 mouseClick(allButton, 0, 0);381 mouseClick(allButton, 0, 0);
381 tryCompare(dashDepartments.currentDepartment, "departmentId", "middle2");382 tryCompare(dashDepartments.currentDepartment, "departmentId", "middle2");
382 }383 }
384
385 function test_searchHint() {
386 var dashContentList = findChild(dashContent, "dashContentList");
387 verify(dashContentList !== null);
388 var scope = findChild(dashContent, "MockScope1 loader");
389 waitForRendering(scope);
390
391 var categoryListView = findChild(scope, "categoryListView");
392 waitForRendering(categoryListView);
393
394 compare(categoryListView.pageHeader.searchHint, "Search People");
395 }
383 }396 }
384}397}

Subscribers

People subscribed via source and target branches