on xenial help sign in
Merge ~aacid/unity8/tablePreviewWidget
34fa939Albert Astals
data/unity8-dash.conf+1−1
@@ -13,7 +13,7 @@ respawn
13pre-start script
13pre-start script
14 if [ -z "$UNITY_SCOPES_LIST" ]; then
14 if [ -z "$UNITY_SCOPES_LIST" ]; then
15 # FIXME: remove once we have this in dconf
15 # FIXME: remove once we have this in dconf
16− initctl set-env UNITY_SCOPES_LIST="scopes;clickscope;musicaggregator;videoaggregator"
16+ initctl set-env UNITY_SCOPES_LIST="clickscope;musicaggregator;videoaggregator"
17 fi
17 fi
18
18
19 initctl emit scope-ui-starting
19 initctl emit scope-ui-starting
plugins/Dash/CardCreator.js+3−2
@@ -108,6 +108,7 @@ var kOverlayLoaderCode = 'Loader { \n\
108 sourceComponent: ShaderEffect { \n\
108 sourceComponent: ShaderEffect { \n\
109 id: overlay; \n\
109 id: overlay; \n\
110 height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2); \n\
110 height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2); \n\
111+ property real luminance: 0.2126 * overlayColor.r + 0.7152 * overlayColor.g + 0.0722 * overlayColor.b; \n\
111 property color overlayColor: cardData && cardData["overlayColor"] || "#99000000"; \n\
112 property color overlayColor: cardData && cardData["overlayColor"] || "#99000000"; \n\
112 property var source: ShaderEffectSource { \n\
113 property var source: ShaderEffectSource { \n\
113 id: shaderSource; \n\
114 id: shaderSource; \n\
@@ -446,13 +447,13 @@ function cardString(template, components) {
446 mascotCode = kMascotImageCode.arg(anchors).arg(mascotImageVisible);
447 mascotCode = kMascotImageCode.arg(anchors).arg(mascotImageVisible);
447 }
448 }
448
449
449− var summaryColorWithBackground = 'backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey")';
450+ 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")';
450
451
451 var titleSubtitleCode = "";
452 var titleSubtitleCode = "";
452 if (hasTitle) {
453 if (hasTitle) {
453 var color;
454 var color;
454 if (headerAsOverlay) {
455 if (headerAsOverlay) {
455− color = '"white"';
456+ color = 'overlayLoader.item.luminance < (root.scopeStyle ? root.scopeStyle.threshold : 0.7) ? (root.scopeStyle ? root.scopeStyle.light : "white") : (root.scopeStyle ? root.scopeStyle.dark : "grey")';
456 } else if (hasSummary) {
457 } else if (hasSummary) {
457 color = 'summary.color';
458 color = 'summary.color';
458 } else if (hasBackground) {
459 } else if (hasBackground) {
plugins/Dash/ScopeStyle.qml+3−2
@@ -49,9 +49,10 @@ QtObject {
49
49
50 /*! \brief Luminance threshold for switching between fore and background color
50 /*! \brief Luminance threshold for switching between fore and background color
51
51
52− \note If background colour is not fully opaque, it's not taken into account.
52+ \note If background colour is not fully opaque, the defaultLightLuminance it's taken into account instead of it.
53 */
53 */
54− readonly property real threshold: background.a !== 1.0 ? foregroundLuminance : (foregroundLuminance + backgroundLuminance) / 2
54+ readonly property real threshold: background.a !== 1.0 ? (foregroundLuminance + d.defaultLightLuminance) / 2
55+ : (foregroundLuminance + backgroundLuminance) / 2
55
56
56 /*! \brief The lighter of foreground and background colors
57 /*! \brief The lighter of foreground and background colors
57
58
plugins/Dash/listviewwithpageheader.cpp+2−2
@@ -822,8 +822,8 @@ ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIn
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 }
po/hu.po+69−33
@@ -6,11 +6,12 @@
6msgid ""
6msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9−"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9+"Report-Msgid-Bugs-To: \n"
10−"POT-Creation-Date: 2014-07-11 14:59+0200\n"
10+"POT-Creation-Date: 2014-08-05 19:54+0200\n"
11"PO-Revision-Date: 2014-08-06 07:41+0000\n"
11"PO-Revision-Date: 2014-08-06 07:41+0000\n"
12"Last-Translator: Richard Somlói <ricsipontaz@gmail.com>\n"
12"Last-Translator: Richard Somlói <ricsipontaz@gmail.com>\n"
13"Language-Team: Hungarian <hu@li.org>\n"
13"Language-Team: Hungarian <hu@li.org>\n"
14+"Language: hu\n"
14"MIME-Version: 1.0\n"
15"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Content-Transfer-Encoding: 8bit\n"
@@ -26,70 +27,86 @@ msgstr "Indító rögzítése"
26msgid "Unpin shortcut"
27msgid "Unpin shortcut"
27msgstr "Indító feloldása"
28msgstr "Indító feloldása"
28
29
30+#: qml/Components/Dialogs.qml:142
31+msgid "Are you sure you would like to turn power off?"
32+msgstr ""
33+
34+#: qml/Components/Dialogs.qml:144
35+msgid "Power off"
36+msgstr ""
37+
38+#: qml/Components/Dialogs.qml:153
39+msgid "Restart"
40+msgstr ""
41+
42+#: qml/Components/Dialogs.qml:162
43+msgid "Cancel"
44+msgstr ""
45+
29#: qml/Components/EdgeDemoOverlay.qml:151
46#: qml/Components/EdgeDemoOverlay.qml:151
30msgid "Skip intro"
47msgid "Skip intro"
31msgstr "A bemutató kihagyása"
48msgstr "A bemutató kihagyása"
32
49
33−#: qml/Components/EdgeDemo.qml:113
50+#: qml/Components/EdgeDemo.qml:112
34msgid "Right edge"
51msgid "Right edge"
35msgstr "Jobb szél"
52msgstr "Jobb szél"
36
53
37−#: qml/Components/EdgeDemo.qml:114
54+#: qml/Components/EdgeDemo.qml:113
38msgid "Try swiping from the right edge to unlock the phone"
55msgid "Try swiping from the right edge to unlock the phone"
39msgstr "A telefon feloldásához csúsztassa ujját a jobb szélről"
56msgstr "A telefon feloldásához csúsztassa ujját a jobb szélről"
40
57
41−#: qml/Components/EdgeDemo.qml:145
58+#: qml/Components/EdgeDemo.qml:144
42msgid "Top edge"
59msgid "Top edge"
43msgstr "Felső szél"
60msgstr "Felső szél"
44
61
45−#: qml/Components/EdgeDemo.qml:146
62+#: qml/Components/EdgeDemo.qml:145
46msgid "Try swiping from the top edge to access the indicators"
63msgid "Try swiping from the top edge to access the indicators"
47msgstr "Az állapotmenük eléréséhez csúsztassa ujját a felső szélről"
64msgstr "Az állapotmenük eléréséhez csúsztassa ujját a felső szélről"
48
65
49−#: qml/Components/EdgeDemo.qml:171
66+#: qml/Components/EdgeDemo.qml:170
50msgid "Close"
67msgid "Close"
51msgstr "Bezárás"
68msgstr "Bezárás"
52
69
53−#: qml/Components/EdgeDemo.qml:172
70+#: qml/Components/EdgeDemo.qml:171
54msgid "Swipe up again to close the settings screen"
71msgid "Swipe up again to close the settings screen"
55msgstr "A beállítások bezárásához csúsztassa ujját újra felfelé"
72msgstr "A beállítások bezárásához csúsztassa ujját újra felfelé"
56
73
57−#: qml/Components/EdgeDemo.qml:199
74+#: qml/Components/EdgeDemo.qml:198
58msgid "Left edge"
75msgid "Left edge"
59msgstr "Bal szél"
76msgstr "Bal szél"
60
77
61−#: qml/Components/EdgeDemo.qml:200
78+#: qml/Components/EdgeDemo.qml:199
62msgid "Swipe from the left to reveal the launcher for quick access to apps"
79msgid "Swipe from the left to reveal the launcher for quick access to apps"
63msgstr ""
80msgstr ""
64"Csúsztassa ujját a bal szélről az indítón található alkalmazások gyors "
81"Csúsztassa ujját a bal szélről az indítón található alkalmazások gyors "
65"eléréséhez"
82"eléréséhez"
66
83
67−#: qml/Components/EdgeDemo.qml:227
84+#: qml/Components/EdgeDemo.qml:226
68msgid "Well done"
85msgid "Well done"
69msgstr "Rendben"
86msgstr "Rendben"
70
87
71−#: qml/Components/EdgeDemo.qml:228
88+#: qml/Components/EdgeDemo.qml:227
72msgid ""
89msgid ""
73"You have now mastered the edge gestures and can start using the "
90"You have now mastered the edge gestures and can start using the "
74"phone<br><br>Tap on the screen to start"
91"phone<br><br>Tap on the screen to start"
75msgstr ""
92msgstr ""
76−"Elsajátította a gesztusokat, és megkezdheti a telefon "
93+"Elsajátította a gesztusokat, és megkezdheti a telefon használatát."
77−"használatát.<br><br>Koppintson a képernyőre a kezdéshez."
94+"<br><br>Koppintson a képernyőre a kezdéshez."
78
95
79−#: qml/Components/Lockscreen.qml:214
96+#: qml/Components/Lockscreen.qml:220
80msgid "Emergency Call"
97msgid "Emergency Call"
81msgstr "Vészhívás"
98msgstr "Vészhívás"
82
99
83−#: qml/Components/Lockscreen.qml:231
100+#: qml/Components/Lockscreen.qml:243
84msgid "OK"
101msgid "OK"
85msgstr "Ok"
102msgstr "Ok"
86
103
87−#: qml/Components/PassphraseLockscreen.qml:60
104+#: qml/Components/PassphraseLockscreen.qml:62
88#, qt-format
105#, qt-format
89msgid "Hello %1"
106msgid "Hello %1"
90msgstr "Üdv %1"
107msgstr "Üdv %1"
91
108
92−#: qml/Components/PassphraseLockscreen.qml:60
109+#: qml/Components/PassphraseLockscreen.qml:62
93msgid "Hello"
110msgid "Hello"
94msgstr "Üdvözöljük"
111msgstr "Üdvözöljük"
95
112
@@ -105,15 +122,11 @@ msgstr "KÉSZ"
105msgid "See more"
122msgid "See more"
106msgstr "Több"
123msgstr "Több"
107
124
108−#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
125+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:354
109msgid "See less"
126msgid "See less"
110msgstr "Kevesebb"
127msgstr "Kevesebb"
111
128
112−#: qml/Dash/DashApps.qml:37
113−msgid "Recent"
114−msgstr "Legutóbbi"
115−
116−#: qml/Dash/GenericScopeView.qml:330
129+#: qml/Dash/GenericScopeView.qml:354
117msgid "See all"
130msgid "See all"
118msgstr "Összes megtekintése"
131msgstr "Összes megtekintése"
119
132
@@ -137,6 +150,26 @@ msgstr "Értékelés hozzáadása"
137msgid "Send"
150msgid "Send"
138msgstr "Küldés"
151msgstr "Küldés"
139
152
153+#: qml/Dash/ScopesOverview.qml:187
154+msgid "Manage Dash"
155+msgstr ""
156+
157+#: qml/Dash/ScopesOverview.qml:392
158+msgid "Done"
159+msgstr ""
160+
161+#: qml/Dash/ScopesOverview.qml:418
162+msgid "Store"
163+msgstr ""
164+
165+#: qml/Dash/ScopesOverviewTab.qml:36
166+msgid "Favorites"
167+msgstr ""
168+
169+#: qml/Dash/ScopesOverviewTab.qml:54
170+msgid "All"
171+msgstr ""
172+
140#: qml/Greeter/Greeter.qml:157
173#: qml/Greeter/Greeter.qml:157
141msgid "Swipe to unlock"
174msgid "Swipe to unlock"
142msgstr "Csúsztasson a feloldáshoz"
175msgstr "Csúsztasson a feloldáshoz"
@@ -161,11 +194,11 @@ msgstr "Most beszéljen…"
161msgid "Speaking..."
194msgid "Speaking..."
162msgstr "Beszéd…"
195msgstr "Beszéd…"
163
196
164−#: qml/Notifications/NotificationMenuItemFactory.qml:91
197+#: qml/Notifications/NotificationMenuItemFactory.qml:97
165msgid "Show password"
198msgid "Show password"
166msgstr "Jelszó megjelenítése"
199msgstr "Jelszó megjelenítése"
167
200
168−#: qml/Notifications/NotificationMenuItemFactory.qml:103
201+#: qml/Notifications/NotificationMenuItemFactory.qml:112
169msgid "Please enter SIM PIN"
202msgid "Please enter SIM PIN"
170msgstr "Adja meg a SIM PIN kódját"
203msgstr "Adja meg a SIM PIN kódját"
171
204
@@ -177,27 +210,27 @@ msgstr "Érintse meg, hogy visszatérjen a híváshoz..."
177msgid "Conference"
210msgid "Conference"
178msgstr "Konferencia"
211msgstr "Konferencia"
179
212
180−#: qml/Panel/Indicators/MenuItemFactory.qml:583
213+#: qml/Panel/Indicators/MenuItemFactory.qml:577
181msgid "In queue…"
214msgid "In queue…"
182msgstr "Sorban…"
215msgstr "Sorban…"
183
216
184−#: qml/Panel/Indicators/MenuItemFactory.qml:587
217+#: qml/Panel/Indicators/MenuItemFactory.qml:581
185msgid "Downloading"
218msgid "Downloading"
186msgstr "Letöltés"
219msgstr "Letöltés"
187
220
188−#: qml/Panel/Indicators/MenuItemFactory.qml:589
221+#: qml/Panel/Indicators/MenuItemFactory.qml:583
189msgid "Paused, tap to resume"
222msgid "Paused, tap to resume"
190msgstr "Szüneteltetve, koppintson a folytatáshoz"
223msgstr "Szüneteltetve, koppintson a folytatáshoz"
191
224
192−#: qml/Panel/Indicators/MenuItemFactory.qml:591
225+#: qml/Panel/Indicators/MenuItemFactory.qml:585
193msgid "Canceled"
226msgid "Canceled"
194msgstr "Megszakítva"
227msgstr "Megszakítva"
195
228
196−#: qml/Panel/Indicators/MenuItemFactory.qml:593
229+#: qml/Panel/Indicators/MenuItemFactory.qml:587
197msgid "Finished"
230msgid "Finished"
198msgstr "Befejeződött"
231msgstr "Befejeződött"
199
232
200−#: qml/Panel/Indicators/MenuItemFactory.qml:595
233+#: qml/Panel/Indicators/MenuItemFactory.qml:589
201msgid "Failed, tap to retry"
234msgid "Failed, tap to retry"
202msgstr "Sikertelen, koppintson az újrapróbáláshoz"
235msgstr "Sikertelen, koppintson az újrapróbáláshoz"
203
236
@@ -205,7 +238,10 @@ msgstr "Sikertelen, koppintson az újrapróbáláshoz"
205msgid "Search"
238msgid "Search"
206msgstr "Keresés"
239msgstr "Keresés"
207
240
208−#: qml/Shell.qml:359
241+#: qml/Shell.qml:256
209#, qt-format
242#, qt-format
210msgid "Please enter %1"
243msgid "Please enter %1"
211msgstr "Adja meg a következőt: %1"
244msgstr "Adja meg a következőt: %1"
245+
246+#~ msgid "Recent"
247+#~ msgstr "Legutóbbi"
po/sl.po+67−31
@@ -6,11 +6,12 @@
6msgid ""
6msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9−"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9+"Report-Msgid-Bugs-To: \n"
10−"POT-Creation-Date: 2014-07-11 14:59+0200\n"
10+"POT-Creation-Date: 2014-08-05 19:54+0200\n"
11"PO-Revision-Date: 2014-08-06 06:11+0000\n"
11"PO-Revision-Date: 2014-08-06 06:11+0000\n"
12"Last-Translator: Damir Jerovšek <Unknown>\n"
12"Last-Translator: Damir Jerovšek <Unknown>\n"
13"Language-Team: Slovenian <sl@li.org>\n"
13"Language-Team: Slovenian <sl@li.org>\n"
14+"Language: sl\n"
14"MIME-Version: 1.0\n"
15"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Content-Transfer-Encoding: 8bit\n"
@@ -26,49 +27,65 @@ msgstr "Pripni bližnjico"
26msgid "Unpin shortcut"
27msgid "Unpin shortcut"
27msgstr "Odpni bližnjico"
28msgstr "Odpni bližnjico"
28
29
30+#: qml/Components/Dialogs.qml:142
31+msgid "Are you sure you would like to turn power off?"
32+msgstr ""
33+
34+#: qml/Components/Dialogs.qml:144
35+msgid "Power off"
36+msgstr ""
37+
38+#: qml/Components/Dialogs.qml:153
39+msgid "Restart"
40+msgstr ""
41+
42+#: qml/Components/Dialogs.qml:162
43+msgid "Cancel"
44+msgstr ""
45+
29#: qml/Components/EdgeDemoOverlay.qml:151
46#: qml/Components/EdgeDemoOverlay.qml:151
30msgid "Skip intro"
47msgid "Skip intro"
31msgstr "Preskoči uvod"
48msgstr "Preskoči uvod"
32
49
33−#: qml/Components/EdgeDemo.qml:113
50+#: qml/Components/EdgeDemo.qml:112
34msgid "Right edge"
51msgid "Right edge"
35msgstr "Desni rob"
52msgstr "Desni rob"
36
53
37−#: qml/Components/EdgeDemo.qml:114
54+#: qml/Components/EdgeDemo.qml:113
38msgid "Try swiping from the right edge to unlock the phone"
55msgid "Try swiping from the right edge to unlock the phone"
39msgstr "Poskusite povleči od desnega roba za odklep telefona"
56msgstr "Poskusite povleči od desnega roba za odklep telefona"
40
57
41−#: qml/Components/EdgeDemo.qml:145
58+#: qml/Components/EdgeDemo.qml:144
42msgid "Top edge"
59msgid "Top edge"
43msgstr "Zgornji rob"
60msgstr "Zgornji rob"
44
61
45−#: qml/Components/EdgeDemo.qml:146
62+#: qml/Components/EdgeDemo.qml:145
46msgid "Try swiping from the top edge to access the indicators"
63msgid "Try swiping from the top edge to access the indicators"
47msgstr "Poskusite povleči od zgornjega roba za dostop do kazalnikov"
64msgstr "Poskusite povleči od zgornjega roba za dostop do kazalnikov"
48
65
49−#: qml/Components/EdgeDemo.qml:171
66+#: qml/Components/EdgeDemo.qml:170
50msgid "Close"
67msgid "Close"
51msgstr "Zapri"
68msgstr "Zapri"
52
69
53−#: qml/Components/EdgeDemo.qml:172
70+#: qml/Components/EdgeDemo.qml:171
54msgid "Swipe up again to close the settings screen"
71msgid "Swipe up again to close the settings screen"
55msgstr "Povlecite ponovno navzgor za zaprtje zaslona z nastavitvami"
72msgstr "Povlecite ponovno navzgor za zaprtje zaslona z nastavitvami"
56
73
57−#: qml/Components/EdgeDemo.qml:199
74+#: qml/Components/EdgeDemo.qml:198
58msgid "Left edge"
75msgid "Left edge"
59msgstr "Levi rob"
76msgstr "Levi rob"
60
77
61−#: qml/Components/EdgeDemo.qml:200
78+#: qml/Components/EdgeDemo.qml:199
62msgid "Swipe from the left to reveal the launcher for quick access to apps"
79msgid "Swipe from the left to reveal the launcher for quick access to apps"
63msgstr ""
80msgstr ""
64"Poskusite povleči od leve za razkritje zaganjalnika za hiter dostop do "
81"Poskusite povleči od leve za razkritje zaganjalnika za hiter dostop do "
65"programov"
82"programov"
66
83
67−#: qml/Components/EdgeDemo.qml:227
84+#: qml/Components/EdgeDemo.qml:226
68msgid "Well done"
85msgid "Well done"
69msgstr "Odlično"
86msgstr "Odlično"
70
87
71−#: qml/Components/EdgeDemo.qml:228
88+#: qml/Components/EdgeDemo.qml:227
72msgid ""
89msgid ""
73"You have now mastered the edge gestures and can start using the "
90"You have now mastered the edge gestures and can start using the "
74"phone<br><br>Tap on the screen to start"
91"phone<br><br>Tap on the screen to start"
@@ -76,20 +93,20 @@ msgstr ""
76"Sedaj, ko ste osvojili poteze robov, lahko začnete uporabljati "
93"Sedaj, ko ste osvojili poteze robov, lahko začnete uporabljati "
77"telefon<br><br>Tapnite na zaslon za začetek"
94"telefon<br><br>Tapnite na zaslon za začetek"
78
95
79−#: qml/Components/Lockscreen.qml:214
96+#: qml/Components/Lockscreen.qml:220
80msgid "Emergency Call"
97msgid "Emergency Call"
81msgstr "Klic v sili"
98msgstr "Klic v sili"
82
99
83−#: qml/Components/Lockscreen.qml:231
100+#: qml/Components/Lockscreen.qml:243
84msgid "OK"
101msgid "OK"
85msgstr "V REDU"
102msgstr "V REDU"
86
103
87−#: qml/Components/PassphraseLockscreen.qml:60
104+#: qml/Components/PassphraseLockscreen.qml:62
88#, qt-format
105#, qt-format
89msgid "Hello %1"
106msgid "Hello %1"
90msgstr "Pozdravljeni, %1"
107msgstr "Pozdravljeni, %1"
91
108
92−#: qml/Components/PassphraseLockscreen.qml:60
109+#: qml/Components/PassphraseLockscreen.qml:62
93msgid "Hello"
110msgid "Hello"
94msgstr "Pozdravljeni"
111msgstr "Pozdravljeni"
95
112
@@ -105,15 +122,11 @@ msgstr "KONČANO"
105msgid "See more"
122msgid "See more"
106msgstr "Pokaži več"
123msgstr "Pokaži več"
107
124
108−#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
125+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:354
109msgid "See less"
126msgid "See less"
110msgstr "Pokaži manj"
127msgstr "Pokaži manj"
111
128
112−#: qml/Dash/DashApps.qml:37
113−msgid "Recent"
114−msgstr "Nedavno"
115−
116−#: qml/Dash/GenericScopeView.qml:330
129+#: qml/Dash/GenericScopeView.qml:354
117msgid "See all"
130msgid "See all"
118msgstr "Ogled vsega"
131msgstr "Ogled vsega"
119
132
@@ -137,6 +150,26 @@ msgstr "Dodaj oceno"
137msgid "Send"
150msgid "Send"
138msgstr "Pošlji"
151msgstr "Pošlji"
139
152
153+#: qml/Dash/ScopesOverview.qml:187
154+msgid "Manage Dash"
155+msgstr ""
156+
157+#: qml/Dash/ScopesOverview.qml:392
158+msgid "Done"
159+msgstr ""
160+
161+#: qml/Dash/ScopesOverview.qml:418
162+msgid "Store"
163+msgstr ""
164+
165+#: qml/Dash/ScopesOverviewTab.qml:36
166+msgid "Favorites"
167+msgstr ""
168+
169+#: qml/Dash/ScopesOverviewTab.qml:54
170+msgid "All"
171+msgstr ""
172+
140#: qml/Greeter/Greeter.qml:157
173#: qml/Greeter/Greeter.qml:157
141msgid "Swipe to unlock"
174msgid "Swipe to unlock"
142msgstr "Podrsajte za odklenitev"
175msgstr "Podrsajte za odklenitev"
@@ -161,11 +194,11 @@ msgstr "Govorite zdaj ..."
161msgid "Speaking..."
194msgid "Speaking..."
162msgstr "Govorjenje ..."
195msgstr "Govorjenje ..."
163
196
164−#: qml/Notifications/NotificationMenuItemFactory.qml:91
197+#: qml/Notifications/NotificationMenuItemFactory.qml:97
165msgid "Show password"
198msgid "Show password"
166msgstr "Pokaži geslo"
199msgstr "Pokaži geslo"
167
200
168−#: qml/Notifications/NotificationMenuItemFactory.qml:103
201+#: qml/Notifications/NotificationMenuItemFactory.qml:112
169msgid "Please enter SIM PIN"
202msgid "Please enter SIM PIN"
170msgstr "Vnesite PIN kartice SIM"
203msgstr "Vnesite PIN kartice SIM"
171
204
@@ -177,27 +210,27 @@ msgstr "Tapnite za vrnitev v klic ..."
177msgid "Conference"
210msgid "Conference"
178msgstr "Konferenca"
211msgstr "Konferenca"
179
212
180−#: qml/Panel/Indicators/MenuItemFactory.qml:583
213+#: qml/Panel/Indicators/MenuItemFactory.qml:577
181msgid "In queue…"
214msgid "In queue…"
182msgstr "V vrsti ..."
215msgstr "V vrsti ..."
183
216
184−#: qml/Panel/Indicators/MenuItemFactory.qml:587
217+#: qml/Panel/Indicators/MenuItemFactory.qml:581
185msgid "Downloading"
218msgid "Downloading"
186msgstr "Prejemanje"
219msgstr "Prejemanje"
187
220
188−#: qml/Panel/Indicators/MenuItemFactory.qml:589
221+#: qml/Panel/Indicators/MenuItemFactory.qml:583
189msgid "Paused, tap to resume"
222msgid "Paused, tap to resume"
190msgstr "Premor, tapnite za nadaljevanje"
223msgstr "Premor, tapnite za nadaljevanje"
191
224
192−#: qml/Panel/Indicators/MenuItemFactory.qml:591
225+#: qml/Panel/Indicators/MenuItemFactory.qml:585
193msgid "Canceled"
226msgid "Canceled"
194msgstr "Preklicano"
227msgstr "Preklicano"
195
228
196−#: qml/Panel/Indicators/MenuItemFactory.qml:593
229+#: qml/Panel/Indicators/MenuItemFactory.qml:587
197msgid "Finished"
230msgid "Finished"
198msgstr "Končano"
231msgstr "Končano"
199
232
200−#: qml/Panel/Indicators/MenuItemFactory.qml:595
233+#: qml/Panel/Indicators/MenuItemFactory.qml:589
201msgid "Failed, tap to retry"
234msgid "Failed, tap to retry"
202msgstr "Spodletelo, tapnite za ponovni poskus"
235msgstr "Spodletelo, tapnite za ponovni poskus"
203
236
@@ -205,7 +238,10 @@ msgstr "Spodletelo, tapnite za ponovni poskus"
205msgid "Search"
238msgid "Search"
206msgstr "Iskanje"
239msgstr "Iskanje"
207
240
208−#: qml/Shell.qml:359
241+#: qml/Shell.qml:256
209#, qt-format
242#, qt-format
210msgid "Please enter %1"
243msgid "Please enter %1"
211msgstr "Vnesite %1"
244msgstr "Vnesite %1"
245+
246+#~ msgid "Recent"
247+#~ msgstr "Nedavno"
po/unity8.pot+62−30
@@ -8,7 +8,7 @@ msgid ""
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-08-05 19:54+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"
@@ -26,66 +26,82 @@ msgstr ""
26msgid "Unpin shortcut"
26msgid "Unpin shortcut"
27msgstr ""
27msgstr ""
28
28
29+#: qml/Components/Dialogs.qml:142
30+msgid "Are you sure you would like to turn power off?"
31+msgstr ""
32+
33+#: qml/Components/Dialogs.qml:144
34+msgid "Power off"
35+msgstr ""
36+
37+#: qml/Components/Dialogs.qml:153
38+msgid "Restart"
39+msgstr ""
40+
41+#: qml/Components/Dialogs.qml:162
42+msgid "Cancel"
43+msgstr ""
44+
29#: qml/Components/EdgeDemoOverlay.qml:151
45#: qml/Components/EdgeDemoOverlay.qml:151
30msgid "Skip intro"
46msgid "Skip intro"
31msgstr ""
47msgstr ""
32
48
33−#: qml/Components/EdgeDemo.qml:113
49+#: qml/Components/EdgeDemo.qml:112
34msgid "Right edge"
50msgid "Right edge"
35msgstr ""
51msgstr ""
36
52
37−#: qml/Components/EdgeDemo.qml:114
53+#: qml/Components/EdgeDemo.qml:113
38msgid "Try swiping from the right edge to unlock the phone"
54msgid "Try swiping from the right edge to unlock the phone"
39msgstr ""
55msgstr ""
40
56
41−#: qml/Components/EdgeDemo.qml:145
57+#: qml/Components/EdgeDemo.qml:144
42msgid "Top edge"
58msgid "Top edge"
43msgstr ""
59msgstr ""
44
60
45−#: qml/Components/EdgeDemo.qml:146
61+#: qml/Components/EdgeDemo.qml:145
46msgid "Try swiping from the top edge to access the indicators"
62msgid "Try swiping from the top edge to access the indicators"
47msgstr ""
63msgstr ""
48
64
49−#: qml/Components/EdgeDemo.qml:171
65+#: qml/Components/EdgeDemo.qml:170
50msgid "Close"
66msgid "Close"
51msgstr ""
67msgstr ""
52
68
53−#: qml/Components/EdgeDemo.qml:172
69+#: qml/Components/EdgeDemo.qml:171
54msgid "Swipe up again to close the settings screen"
70msgid "Swipe up again to close the settings screen"
55msgstr ""
71msgstr ""
56
72
57−#: qml/Components/EdgeDemo.qml:199
73+#: qml/Components/EdgeDemo.qml:198
58msgid "Left edge"
74msgid "Left edge"
59msgstr ""
75msgstr ""
60
76
61−#: qml/Components/EdgeDemo.qml:200
77+#: qml/Components/EdgeDemo.qml:199
62msgid "Swipe from the left to reveal the launcher for quick access to apps"
78msgid "Swipe from the left to reveal the launcher for quick access to apps"
63msgstr ""
79msgstr ""
64
80
65−#: qml/Components/EdgeDemo.qml:227
81+#: qml/Components/EdgeDemo.qml:226
66msgid "Well done"
82msgid "Well done"
67msgstr ""
83msgstr ""
68
84
69−#: qml/Components/EdgeDemo.qml:228
85+#: qml/Components/EdgeDemo.qml:227
70msgid ""
86msgid ""
71"You have now mastered the edge gestures and can start using the "
87"You have now mastered the edge gestures and can start using the "
72"phone<br><br>Tap on the screen to start"
88"phone<br><br>Tap on the screen to start"
73msgstr ""
89msgstr ""
74
90
75−#: qml/Components/Lockscreen.qml:214
91+#: qml/Components/Lockscreen.qml:220
76msgid "Emergency Call"
92msgid "Emergency Call"
77msgstr ""
93msgstr ""
78
94
79−#: qml/Components/Lockscreen.qml:231
95+#: qml/Components/Lockscreen.qml:243
80msgid "OK"
96msgid "OK"
81msgstr ""
97msgstr ""
82
98
83−#: qml/Components/PassphraseLockscreen.qml:60
99+#: qml/Components/PassphraseLockscreen.qml:62
84#, qt-format
100#, qt-format
85msgid "Hello %1"
101msgid "Hello %1"
86msgstr ""
102msgstr ""
87
103
88−#: qml/Components/PassphraseLockscreen.qml:60
104+#: qml/Components/PassphraseLockscreen.qml:62
89msgid "Hello"
105msgid "Hello"
90msgstr ""
106msgstr ""
91
107
@@ -101,15 +117,11 @@ msgstr ""
101msgid "See more"
117msgid "See more"
102msgstr ""
118msgstr ""
103
119
104−#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:330
120+#: qml/Components/SeeMore.qml:58 qml/Dash/GenericScopeView.qml:354
105msgid "See less"
121msgid "See less"
106msgstr ""
122msgstr ""
107
123
108−#: qml/Dash/DashApps.qml:37
109−msgid "Recent"
110−msgstr ""
111−
112−#: qml/Dash/GenericScopeView.qml:330
124+#: qml/Dash/GenericScopeView.qml:354
113msgid "See all"
125msgid "See all"
114msgstr ""
126msgstr ""
115
127
@@ -133,6 +145,26 @@ msgstr ""
133msgid "Send"
145msgid "Send"
134msgstr ""
146msgstr ""
135
147
148+#: qml/Dash/ScopesOverview.qml:187
149+msgid "Manage Dash"
150+msgstr ""
151+
152+#: qml/Dash/ScopesOverview.qml:392
153+msgid "Done"
154+msgstr ""
155+
156+#: qml/Dash/ScopesOverview.qml:418
157+msgid "Store"
158+msgstr ""
159+
160+#: qml/Dash/ScopesOverviewTab.qml:36
161+msgid "Favorites"
162+msgstr ""
163+
164+#: qml/Dash/ScopesOverviewTab.qml:54
165+msgid "All"
166+msgstr ""
167+
136#: qml/Greeter/Greeter.qml:157
168#: qml/Greeter/Greeter.qml:157
137msgid "Swipe to unlock"
169msgid "Swipe to unlock"
138msgstr ""
170msgstr ""
@@ -157,11 +189,11 @@ msgstr ""
157msgid "Speaking..."
189msgid "Speaking..."
158msgstr ""
190msgstr ""
159
191
160−#: qml/Notifications/NotificationMenuItemFactory.qml:91
192+#: qml/Notifications/NotificationMenuItemFactory.qml:97
161msgid "Show password"
193msgid "Show password"
162msgstr ""
194msgstr ""
163
195
164−#: qml/Notifications/NotificationMenuItemFactory.qml:103
196+#: qml/Notifications/NotificationMenuItemFactory.qml:112
165msgid "Please enter SIM PIN"
197msgid "Please enter SIM PIN"
166msgstr ""
198msgstr ""
167
199
@@ -173,27 +205,27 @@ msgstr ""
173msgid "Conference"
205msgid "Conference"
174msgstr ""
206msgstr ""
175
207
176−#: qml/Panel/Indicators/MenuItemFactory.qml:583
208+#: qml/Panel/Indicators/MenuItemFactory.qml:577
177msgid "In queue…"
209msgid "In queue…"
178msgstr ""
210msgstr ""
179
211
180−#: qml/Panel/Indicators/MenuItemFactory.qml:587
212+#: qml/Panel/Indicators/MenuItemFactory.qml:581
181msgid "Downloading"
213msgid "Downloading"
182msgstr ""
214msgstr ""
183
215
184−#: qml/Panel/Indicators/MenuItemFactory.qml:589
216+#: qml/Panel/Indicators/MenuItemFactory.qml:583
185msgid "Paused, tap to resume"
217msgid "Paused, tap to resume"
186msgstr ""
218msgstr ""
187
219
188−#: qml/Panel/Indicators/MenuItemFactory.qml:591
220+#: qml/Panel/Indicators/MenuItemFactory.qml:585
189msgid "Canceled"
221msgid "Canceled"
190msgstr ""
222msgstr ""
191
223
192−#: qml/Panel/Indicators/MenuItemFactory.qml:593
224+#: qml/Panel/Indicators/MenuItemFactory.qml:587
193msgid "Finished"
225msgid "Finished"
194msgstr ""
226msgstr ""
195
227
196−#: qml/Panel/Indicators/MenuItemFactory.qml:595
228+#: qml/Panel/Indicators/MenuItemFactory.qml:589
197msgid "Failed, tap to retry"
229msgid "Failed, tap to retry"
198msgstr ""
230msgstr ""
199
231
@@ -201,7 +233,7 @@ msgstr ""
201msgid "Search"
233msgid "Search"
202msgstr ""
234msgstr ""
203
235
204−#: qml/Shell.qml:359
236+#: qml/Shell.qml:256
205#, qt-format
237#, qt-format
206msgid "Please enter %1"
238msgid "Please enter %1"
207msgstr ""
239msgstr ""
qml/Components/PageHeader.qml+4−1
@@ -24,7 +24,7 @@ import "SearchHistoryModel"
24Item {
24Item {
25 id: root
25 id: root
26 objectName: "pageHeader"
26 objectName: "pageHeader"
27− implicitHeight: headerContainer.height + units.gu(2) + bottomContainer.height
27+ implicitHeight: headerContainer.height + bottomContainer.height + (showSignatureLine ? units.gu(2) : 0)
28
28
29 property bool showBackButton: false
29 property bool showBackButton: false
30 property string title
30 property string title
@@ -32,6 +32,8 @@ Item {
32 property bool searchEntryEnabled: false
32 property bool searchEntryEnabled: false
33 property ListModel searchHistory: SearchHistoryModel
33 property ListModel searchHistory: SearchHistoryModel
34 property alias searchQuery: searchTextField.text
34 property alias searchQuery: searchTextField.text
35+ property alias searchHint: searchTextField.placeholderText
36+ property alias showSignatureLine: bottomBorder.visible
35
37
36 property alias bottomItem: bottomContainer.children
38 property alias bottomItem: bottomContainer.children
37 property int paginationCount: 0
39 property int paginationCount: 0
@@ -251,6 +253,7 @@ Item {
251
253
252 actions: [
254 actions: [
253 Action {
255 Action {
256+ objectName: "search"
254 iconName: "search"
257 iconName: "search"
255 visible: root.searchEntryEnabled
258 visible: root.searchEntryEnabled
256 onTriggered: {
259 onTriggered: {
qml/Components/ResponsiveGridView.qml+3−3
@@ -34,7 +34,7 @@ Item {
34 readonly property int cellWidth: gridView.cellWidth
34 readonly property int cellWidth: gridView.cellWidth
35 readonly property int cellHeight: gridView.cellHeight
35 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.interactive
39 property alias interactive: gridView.interactive
40 readonly property alias flicking: gridView.flicking
40 readonly property alias flicking: gridView.flicking
@@ -47,8 +47,8 @@ Item {
47 property alias cacheBuffer: gridView.cacheBuffer
47 property alias cacheBuffer: gridView.cacheBuffer
48 readonly property alias currentItem: gridView.currentItem
48 readonly property alias currentItem: gridView.currentItem
49
49
50− function contentHeightForRows(rows) {
50+ function contentHeightForRows(rows, height) {
51− return rows * cellHeight;
51+ return rows * height
52 }
52 }
53
53
54 GridView {
54 GridView {
qml/Dash/CardCarousel.qml+2−2
@@ -48,8 +48,8 @@ DashRenderer {
48
48
49 objectName: "carouselDelegate" + index
49 objectName: "carouselDelegate" + index
50
50
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) }
53
53
54 sourceComponent: cardTool.cardComponent
54 sourceComponent: cardTool.cardComponent
55 onLoaded: {
55 onLoaded: {
qml/Dash/CardGrid.qml+14−3
@@ -26,10 +26,20 @@ DashRenderer {
26 }
26 }
27
27
28 expandedHeight: grid.totalContentHeight
28 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.columns
30 collapsedItemCount: collapsedRows * grid.columns
31 originY: grid.originY
31 originY: grid.originY
32
32
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: grid
44 id: grid
35 anchors.fill: parent
45 anchors.fill: parent
@@ -53,6 +63,7 @@ DashRenderer {
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 @@ DashRenderer {
62 }
73 }
63 Connections {
74 Connections {
64 target: loader.item
75 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 }
qml/Dash/CardVerticalJournal.qml+2−2
@@ -61,8 +61,8 @@ DashRenderer {
61 }
61 }
62 Connections {
62 Connections {
63 target: loader.item
63 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 }
qml/Dash/Dash.qml+158−12
@@ -16,6 +16,7 @@
16
16
17import QtQuick 2.2
17import QtQuick 2.2
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19+import Ubuntu.Gestures 0.1
19import Unity 0.2
20import Unity 0.2
20import Utils 0.1
21import Utils 0.1
21import Unity.DashCommunicator 0.1
22import Unity.DashCommunicator 0.1
@@ -73,26 +74,104 @@ Showable {
73 id: scopes
74 id: scopes
74 }
75 }
75
76
76− Image {
77+ QtObject {
78+ id: overviewController
79+ objectName: "overviewController"
80+
81+ property alias enableAnimation: progressAnimation.enabled
82+ property real progress: 0
83+ Behavior on progress {
84+ id: progressAnimation
85+ UbuntuNumberAnimation { }
86+ }
87+ }
88+
89+ ScopesOverview {
90+ id: scopesOverview
91+ objectName: "scopesOverview"
77 anchors.fill: parent
92 anchors.fill: parent
78− source: parent.width > parent.height ? "graphics/paper_landscape.png" : "graphics/paper_portrait.png"
93+ scope: scopes.overviewScope
79− fillMode: Image.PreserveAspectCrop
94+ progress: overviewController.progress
80− horizontalAlignment: Image.AlignRight
95+ scopeScale: scopeItem.scope ? 0.4 : (1 - overviewController.progress * 0.6)
81− verticalAlignment: Image.AlignTop
96+ visible: scopeScale != 1
97+ currentIndex: dashContent.currentIndex
98+ onDone: {
99+ if (currentTab == 1) {
100+ animateDashFromAll(dashContent.currentScopeId);
101+ }
102+ hide();
103+ }
104+ onFavoriteSelected: {
105+ setCurrentScope(scopeId, false, false);
106+ dashContentCache.scheduleUpdate();
107+ hide();
108+ }
109+ onAllFavoriteSelected: {
110+ setCurrentScope(scopeId, false, false);
111+ dashContentCache.scheduleUpdate();
112+ animateDashFromAll(dashContent.currentScopeId);
113+ hide();
114+ }
115+ onSearchSelected: {
116+ var scopeIndex = -1;
117+ for (var i = 0; i < scopes.count; ++i) {
118+ if (scopes.getScope(i).id == scopeId) {
119+ scopeIndex = i;
120+ break;
121+ }
122+ }
123+ if (scopeIndex >= 0) {
124+ // Is a favorite one
125+ setCurrentScope(scopeId, false, false);
126+ dashContentCache.scheduleUpdate();
127+ showDashFromPos(pos, size);
128+ hide();
129+ } else {
130+ // Is not a favorite one, activate and get openScope
131+ scope.activate(result);
132+ }
133+ }
134+ function hide() {
135+ overviewController.enableAnimation = true;
136+ overviewController.progress = 0;
137+ }
138+ onProgressChanged: {
139+ if (progress == 0) {
140+ currentTab = scopeItem.scope ? 1 : 0;
141+ }
142+ }
143+ }
144+
145+ ShaderEffectSource {
146+ id: dashContentCache
147+ parent: scopesOverview.dashItemEater
148+ z: 1
149+ sourceItem: dashContent
150+ height: sourceItem.height
151+ width: sourceItem.width
152+ opacity: 1 - overviewController.progress
153+ visible: overviewController.progress != 0
154+ live: false
82 }
155 }
83
156
84 DashContent {
157 DashContent {
85 id: dashContent
158 id: dashContent
159+
160+ property var scopeThatOpenedScope: null
161+
86 objectName: "dashContent"
162 objectName: "dashContent"
87− width: parent.width
163+ width: dash.width
88− height: parent.height
164+ height: dash.height
89 scopes: scopes
165 scopes: scopes
90− visible: x != -width
166+ visible: !scopesOverview.showingNonFavoriteScope && x != -width
91 onGotoScope: {
167 onGotoScope: {
92 dash.setCurrentScope(scopeId, true, false);
168 dash.setCurrentScope(scopeId, true, false);
93 }
169 }
94 onOpenScope: {
170 onOpenScope: {
171+ scopeThatOpenedScope = currentScope;
95 scopeItem.scope = scope;
172 scopeItem.scope = scope;
173+ scopesOverview.currentTab = 1;
174+ scopesOverview.ensureAllScopeVisible(scope.id);
96 x = -width;
175 x = -width;
97 }
176 }
98 onScopeLoaded: {
177 onScopeLoaded: {
@@ -102,25 +181,63 @@ Showable {
102 }
181 }
103 }
182 }
104 scale: dash.contentScale
183 scale: dash.contentScale
105− clip: scale != 1.0 || scopeItem.visible
184+ clip: scale != 1.0 || scopeItem.visible || overviewController.progress != 0
106 Behavior on x {
185 Behavior on x {
107 UbuntuNumberAnimation {
186 UbuntuNumberAnimation {
187+ duration: overviewController.progress != 0 ? 0 : UbuntuAnimation.FastDuration
108 onRunningChanged: {
188 onRunningChanged: {
109 if (!running && dashContent.x == 0) {
189 if (!running && dashContent.x == 0) {
110− dashContent.closeScope(scopeItem.scope);
190+ dashContent.scopeThatOpenedScope.closeScope(scopeItem.scope);
111 scopeItem.scope = null;
191 scopeItem.scope = null;
192+ if (overviewController.progress == 0) {
193+ // Set tab to Favorites only if we are not showing the overview
194+ scopesOverview.currentTab = 0;
195+ }
112 }
196 }
113 }
197 }
114 }
198 }
115 }
199 }
200+
201+ enabled: overviewController.progress == 0
202+ opacity: enabled ? 1 : 0
203+ }
204+
205+ DashBackground
206+ {
207+ anchors.fill: scopeItem
208+ visible: scopeItem.visible
209+ parent: scopeItem.parent
210+ scale: scopeItem.scale
211+ opacity: scopeItem.opacity
116 }
212 }
117
213
118 GenericScopeView {
214 GenericScopeView {
119 id: scopeItem
215 id: scopeItem
120− anchors.left: dashContent.right
216+ objectName: "dashTempScopeItem"
217+
218+ readonly property real targetOverviewScale: {
219+ if (scopesOverview.currentTab == 0) {
220+ return 0.4;
221+ } else {
222+ return scopesOverview.allCardSize.width / scopeItem.width;
223+ }
224+ }
225+ readonly property real overviewProgressScale: (1 - overviewController.progress * (1 - targetOverviewScale))
226+ readonly property var targetOverviewPosition: scope ? scopesOverview.allScopeCardPosition(scope.id) : null
227+ readonly property real overviewProgressX: scope && scopesOverview.currentTab == 1 && targetOverviewPosition ?
228+ overviewController.progress * (targetOverviewPosition.x - (width - scopesOverview.allCardSize.width) / 2)
229+ : 0
230+ readonly property real overviewProgressY: scope && scopesOverview.currentTab == 1 && targetOverviewPosition ?
231+ overviewController.progress * (targetOverviewPosition.y - (height - scopesOverview.allCardSize.height) / 2)
232+ : 0
233+
234+ x: overviewController.progress == 0 ? dashContent.x + width : overviewProgressX
235+ y: overviewController.progress == 0 ? dashContent.y : overviewProgressY
121 width: parent.width
236 width: parent.width
122 height: parent.height
237 height: parent.height
123− scale: dash.contentScale
238+ scale: dash.contentScale * overviewProgressScale
239+ enabled: opacity == 1
240+ opacity: 1 - overviewController.progress
124 clip: scale != 1.0
241 clip: scale != 1.0
125 visible: scope != null
242 visible: scope != null
126 hasBackAction: true
243 hasBackAction: true
@@ -207,4 +324,33 @@ Showable {
207 }
324 }
208 }
325 }
209
326
327+ EdgeDragArea {
328+ id: overviewDragHandle
329+ objectName: "overviewDragHandle"
330+ z: 1
331+ direction: Direction.Upwards
332+ enabled: !dashContent.previewShown &&
333+ dashContent.currentScope &&
334+ dashContent.currentScope.searchQuery == "" &&
335+ (overviewController.progress == 0 || dragging)
336+
337+ readonly property real fullMovement: units.gu(20)
338+
339+ anchors { left: parent.left; right: parent.right; bottom: parent.bottom }
340+ height: units.gu(2)
341+
342+ onSceneDistanceChanged: {
343+ if (overviewController.enableAnimation) {
344+ dashContentCache.scheduleUpdate();
345+ }
346+ overviewController.enableAnimation = false;
347+ overviewController.progress = Math.max(0, Math.min(1, sceneDistance / fullMovement));
348+ }
349+
350+ onDraggingChanged: {
351+ overviewController.enableAnimation = true;
352+ overviewController.progress = (overviewController.progress > 0.7) ? 1 : 0;
353+ }
354+ }
355+
210}
356}
qml/Dash/DashBackground.qmlnew file+24
@@ -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+
17+import QtQuick 2.0
18+
19+Image {
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+}
qml/Dash/DashContent.qml+8−4
@@ -25,6 +25,10 @@ Item {
25
25
26 property alias scopes: dashContentList.model
26 property alias scopes: dashContentList.model
27 readonly property alias currentIndex: dashContentList.currentIndex
27 readonly property alias currentIndex: dashContentList.currentIndex
28+ readonly property string currentScopeId: dashContentList.currentItem ? dashContentList.currentItem.scopeId : ""
29+ readonly property var currentScope: dashContentList.currentItem ? dashContentList.currentItem.theScope : null
30+ readonly property bool previewShown: dashContentList.currentItem && dashContentList.currentItem.item ?
31+ dashContentList.currentItem.item.previewShown : false
28 readonly property bool processing: dashContentList.currentItem && dashContentList.currentItem.item
32 readonly property bool processing: dashContentList.currentItem && dashContentList.currentItem.item
29 && dashContentList.currentItem.item.processing || false
33 && dashContentList.currentItem.item.processing || false
30
34
@@ -77,15 +81,15 @@ Item {
77 }
81 }
78 }
82 }
79
83
80− function closeScope(scope) {
81− dashContentList.currentItem.theScope.closeScope(scope)
82− }
83−
84 Item {
84 Item {
85 id: dashContentListHolder
85 id: dashContentListHolder
86
86
87 anchors.fill: parent
87 anchors.fill: parent
88
88
89+ DashBackground {
90+ anchors.fill: parent
91+ }
92+
89 ListView {
93 ListView {
90 id: dashContentList
94 id: dashContentList
91 objectName: "dashContentList"
95 objectName: "dashContentList"
qml/Dash/DashRenderer.qml+5−2
@@ -41,9 +41,12 @@ Item {
41 /// Emitted when the user clicked on an item
41 /// Emitted when the user clicked on an item
42 /// @param index is the index of the clicked item
42 /// @param index is the index of the clicked item
43 /// @param result result model of the cliked item, used for activation
43 /// @param result result model of the cliked item, used for activation
44+ /// @param item item that has been clicked
45+ /// @param itemModel model of the item
44− signal clicked(int index, var result)
46+ signal clicked(int index, var result, var item, var itemModel)
45
47
46 /// Emitted when the user pressed and held on an item
48 /// Emitted when the user pressed and held on an item
47 /// @param index is the index of the held item
49 /// @param index is the index of the held item
50+ /// @param itemModel model of the item
48− signal pressAndHold(int index)
51+ signal pressAndHold(int index, var itemModel)
49}
52}
qml/Dash/GenericScopeView.qml+83−46
@@ -25,7 +25,7 @@ import "../Components/ListItems" as ListItems
25FocusScope {
25FocusScope {
26 id: scopeView
26 id: scopeView
27
27
28− readonly property alias navigationShown: dashNavigation.showList
28+ readonly property bool navigationShown: pageHeaderLoader.item ? pageHeaderLoader.item.bottomItem[0].showList : false
29 property var scope: null
29 property var scope: null
30 property SortFilterProxyModel categories: categoryFilter
30 property SortFilterProxyModel categories: categoryFilter
31 property bool isCurrent: false
31 property bool isCurrent: false
@@ -33,8 +33,10 @@ FocusScope {
33 property bool hasBackAction: false
33 property bool hasBackAction: false
34 property bool enableHeightBehaviorOnNextCreation: false
34 property bool enableHeightBehaviorOnNextCreation: false
35 property var categoryView: categoryView
35 property var categoryView: categoryView
36− property alias paginationCount: pageHeader.paginationCount
36+ property bool showPageHeader: true
37+ readonly property alias previewShown: previewListView.open
38+ property int paginationCount: 0
37− property alias paginationIndex: pageHeader.paginationIndex
39+ property int paginationIndex: 0
38
40
39 property var scopeStyle: ScopeStyle {
41 property var scopeStyle: ScopeStyle {
40 style: scope ? scope.customizations : {}
42 style: scope ? scope.customizations : {}
@@ -61,6 +63,36 @@ FocusScope {
61 previewListView.open = false;
63 previewListView.open = false;
62 }
64 }
63
65
66+ function itemClicked(index, result, item, itemModel, resultsModel, limitedCategoryItemCount) {
67+ if (itemModel.uri.indexOf("scope://") === 0 || scope.id === "clickscope") {
68+ // TODO Technically it is possible that calling activate() will make the scope emit
69+ // previewRequested so that we show a preview but there's no scope that does that yet
70+ // so it's not implemented
71+ scope.activate(result)
72+ } else {
73+ openPreview(index, resultsModel, limitedCategoryItemCount);
74+ }
75+ }
76+
77+ function itemPressedAndHeld(index, itemModel, resultsModel, limitedCategoryItemCount) {
78+ if (itemModel.uri.indexOf("scope://") !== 0) {
79+ openPreview(index, resultsModel, limitedCategoryItemCount);
80+ }
81+ }
82+
83+ function openPreview(index, resultsModel, limitedCategoryItemCount) {
84+ if (limitedCategoryItemCount > 0) {
85+ previewLimitModel.model = resultsModel;
86+ previewLimitModel.limit = limitedCategoryItemCount;
87+ previewListView.model = previewLimitModel;
88+ } else {
89+ previewListView.model = resultsModel;
90+ }
91+ previewListView.currentIndex = -1;
92+ previewListView.currentIndex = index;
93+ previewListView.open = true;
94+ }
95+
64 Binding {
96 Binding {
65 target: scope
97 target: scope
66 property: "isActive"
98 property: "isActive"
@@ -77,22 +109,24 @@ FocusScope {
77 }
109 }
78
110
79 onIsCurrentChanged: {
111 onIsCurrentChanged: {
112+ if (showPageHeader) {
80− pageHeader.resetSearch();
113+ pageHeaderLoader.item.resetSearch();
114+ }
81 previewListView.open = false;
115 previewListView.open = false;
82 }
116 }
83
117
84 Binding {
118 Binding {
85 target: scopeView.scope
119 target: scopeView.scope
86 property: "searchQuery"
120 property: "searchQuery"
87− value: pageHeader.searchQuery
121+ value: pageHeaderLoader.item ? pageHeaderLoader.item.searchQuery : ""
88− when: isCurrent
122+ when: isCurrent && showPageHeader
89 }
123 }
90
124
91 Binding {
125 Binding {
92− target: pageHeader
126+ target: pageHeaderLoader.item
93 property: "searchQuery"
127 property: "searchQuery"
94 value: scopeView.scope ? scopeView.scope.searchQuery : ""
128 value: scopeView.scope ? scopeView.scope.searchQuery : ""
95− when: isCurrent
129+ when: isCurrent && showPageHeader
96 }
130 }
97
131
98 Connections {
132 Connections {
@@ -120,7 +154,7 @@ FocusScope {
120 model: scopeView.categories
154 model: scopeView.categories
121 forceNoClip: previewListView.open
155 forceNoClip: previewListView.open
122 pixelAligned: true
156 pixelAligned: true
123− interactive: !dashNavigation.showList
157+ interactive: !navigationShown
124
158
125 property string expandedCategoryId: ""
159 property string expandedCategoryId: ""
126
160
@@ -229,28 +263,19 @@ FocusScope {
229 Connections {
263 Connections {
230 target: rendererLoader.item
264 target: rendererLoader.item
231 onClicked: {
265 onClicked: {
232− if (scopeView.scope.id === "scopes" || scopeView.scope.id == "clickscope") {
266+ scopeView.itemClicked(index, result, item, itemModel, target.model, categoryItemCount());
233− // TODO Technically it is possible that calling activate() will make the scope emit
234− // previewRequested so that we show a preview but there's no scope that does that yet
235− // so it's not implemented
236− scopeView.scope.activate(result)
237− } else {
238− openPreview(index);
239− }
240 }
267 }
241− onPressAndHold: openPreview(index)
242
268
243− function openPreview(index) {
269+ onPressAndHold: {
270+ scopeView.itemPressedAndHeld(index, itemModel, target.model, categoryItemCount());
271+ }
272+
273+ function categoryItemCount() {
274+ var categoryItemCount = -1;
244 if (!rendererLoader.expanded && !seeAllLabel.visible && target.collapsedItemCount > 0) {
275 if (!rendererLoader.expanded && !seeAllLabel.visible && target.collapsedItemCount > 0) {
245− previewLimitModel.model = target.model;
246− previewLimitModel.limit = target.collapsedItemCount;
276+ categoryItemCount = target.collapsedItemCount;
247− previewListView.model = previewLimitModel;
248− } else {
249− previewListView.model = target.model;
250 }
277 }
251− previewListView.currentIndex = -1;
278+ return categoryItemCount;
252− previewListView.currentIndex = index;
253− previewListView.open = true;
254 }
279 }
255 }
280 }
256 Connections {
281 Connections {
@@ -388,26 +413,36 @@ FocusScope {
388 }
413 }
389 }
414 }
390
415
391− pageHeader: PageHeader {
416+ pageHeader: scopeView.showPageHeader ? pageHeaderLoader : null
392− id: pageHeader
417+ Loader {
393− objectName: "scopePageHeader"
418+ id: pageHeaderLoader
394 width: parent.width
419 width: parent.width
420+ sourceComponent: scopeView.showPageHeader ? pageHeaderComponent : undefined
421+ Component {
422+ id: pageHeaderComponent
423+ PageHeader {
424+ objectName: "scopePageHeader"
425+ width: parent.width
395− title: scopeView.scope ? scopeView.scope.name : ""
426+ title: scopeView.scope ? scopeView.scope.name : ""
427+ searchHint: scopeView.scope && scopeView.scope.searchHint || i18n.tr("Search")
396− showBackButton: scopeView.hasBackAction
428+ showBackButton: scopeView.hasBackAction
397− searchEntryEnabled: true
429+ searchEntryEnabled: true
398− scopeStyle: scopeView.scopeStyle
430+ scopeStyle: scopeView.scopeStyle
399−
431+ paginationCount: scopeView.paginationCount
432+ paginationIndex: scopeView.paginationIndex
433+
400− bottomItem: DashNavigation {
434+ bottomItem: DashNavigation {
401− id: dashNavigation
402− scope: scopeView.scope
435+ scope: scopeView.scope
403− width: parent.width <= units.gu(60) ? parent.width : units.gu(40)
436+ width: parent.width <= units.gu(60) ? parent.width : units.gu(40)
404− anchors.right: parent.right
437+ anchors.right: parent.right
405− windowHeight: scopeView.height
438+ windowHeight: scopeView.height
406− windowWidth: scopeView.width
439+ windowWidth: scopeView.width
407− scopeStyle: scopeView.scopeStyle
440+ scopeStyle: scopeView.scopeStyle
408− }
441+ }
409
442
410− onBackClicked: scopeView.backClicked()
443+ onBackClicked: scopeView.backClicked()
444+ }
445+ }
411 }
446 }
412 }
447 }
413
448
@@ -482,7 +517,9 @@ FocusScope {
482 anchors.left: categoryView.right
517 anchors.left: categoryView.right
483
518
484 onOpenChanged: {
519 onOpenChanged: {
485− pageHeader.unfocus();
520+ if (showPageHeader) {
521+ pageHeaderLoader.item.unfocus();
522+ }
486 }
523 }
487 }
524 }
488
525
qml/Dash/PreviewListView.qml+1−1
@@ -108,7 +108,7 @@ Item {
108 anchors {
108 anchors {
109 left: parent.left
109 left: parent.left
110 right: parent.right
110 right: parent.right
111− top: pageHeader.bottom
111+ top: header.bottom
112 bottom: parent.bottom
112 bottom: parent.bottom
113 }
113 }
114
114
qml/Dash/Previews/PreviewTable.qmlnew file+80
@@ -0,0 +1,80 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import QtQuick.Layouts 1.1
19+import Ubuntu.Components 0.1
20+import "../../Components"
21+
22+/*! \brief Preview widget for table.
23+
24+ This widget shows two columns contained in widgetData["values"]
25+ as arrays of label,value along with a title that comes from widgetData["title"].
26+
27+ In case the widget is collapsed it only shows 3 lines of values.
28+ */
29+
30+PreviewWidget {
31+ id: root
32+ implicitHeight: column.implicitHeight
33+
34+ readonly property int maximumCollapsedRowCount: 3
35+
36+ Column {
37+ id: column
38+ objectName: "column"
39+ spacing: units.gu(1)
40+
41+ Label {
42+ id: titleLabel
43+ objectName: "titleLabel"
44+ anchors {
45+ left: parent.left
46+ right: parent.right
47+ }
48+ height: visible ? implicitHeight : 0
49+ fontSize: "large"
50+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey"
51+ visible: text !== ""
52+ opacity: .8
53+ text: widgetData["title"] || ""
54+ }
55+
56+ GridLayout {
57+ objectName: "gridLayout"
58+ columns: 2
59+ columnSpacing: units.gu(2)
60+ Repeater {
61+ id: rowsRepeater
62+ model: widgetData["values"]
63+
64+ delegate: Repeater {
65+ id: perRowRepeater
66+ readonly property int rowIndex: index
67+ model: widgetData["values"][index]
68+ delegate: Label {
69+ objectName: "label"+rowIndex+index
70+ fontSize: "small"
71+ text: perRowRepeater.model[index]
72+ visible: root.expanded || rowIndex < maximumCollapsedRowCount
73+ color: root.scopeStyle ? root.scopeStyle.foreground : "grey"
74+ font.bold: index == 0
75+ }
76+ }
77+ }
78+ }
79+ }
80+}
qml/Dash/Previews/PreviewWidgetFactory.qml+1
@@ -58,6 +58,7 @@ Loader {
58 case "payments": return "PreviewPayments.qml";
58 case "payments": return "PreviewPayments.qml";
59 case "rating-input": return "PreviewRatingInput.qml";
59 case "rating-input": return "PreviewRatingInput.qml";
60 case "reviews": return "PreviewRatingDisplay.qml";
60 case "reviews": return "PreviewRatingDisplay.qml";
61+ case "table": return "PreviewTable.qml";
61 case "text": return "PreviewTextSummary.qml";
62 case "text": return "PreviewTextSummary.qml";
62 case "video": return "PreviewVideoPlayback.qml";
63 case "video": return "PreviewVideoPlayback.qml";
63 default: return "";
64 default: return "";
qml/Dash/ScopesOverview.qmlnew file+523
@@ -0,0 +1,523 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import Dash 0.1
19+import Ubuntu.Components 0.1
20+import "../Components"
21+
22+Item {
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+ Binding {
88+ target: scope
89+ property: "isActive"
90+ value: progress === 1
91+ }
92+
93+ function animateDashFromAll(scopeId) {
94+ var currentScopePos = allScopeCardPosition(scopeId);
95+ if (currentScopePos) {
96+ showDashFromPos(currentScopePos, allCardSize);
97+ } else {
98+ console.log("Warning: Could not find Dash OverView All card position for scope", dashContent.currentScopeId);
99+ }
100+ }
101+
102+ function showDashFromPos(itemPos, itemSize) {
103+ scopesOverviewXYScaler.scale = itemSize.width / scopesOverviewXYScaler.width;
104+ scopesOverviewXYScaler.x = itemPos.x -(scopesOverviewXYScaler.width - scopesOverviewXYScaler.width * scopesOverviewXYScaler.scale) / 2;
105+ scopesOverviewXYScaler.y = itemPos.y -(scopesOverviewXYScaler.height - scopesOverviewXYScaler.height * scopesOverviewXYScaler.scale) / 2;
106+ scopesOverviewXYScaler.opacity = 0;
107+ root.growingDashFromPos = true;
108+ scopesOverviewXYScaler.scale = 1;
109+ scopesOverviewXYScaler.x = 0;
110+ scopesOverviewXYScaler.y = 0;
111+ scopesOverviewXYScaler.opacity = 1;
112+ }
113+
114+ function allScopeCardPosition(scopeId) {
115+ if (middleItems.count > 1) {
116+ var loaderItem = middleItems.itemAt(1).item;
117+ if (loaderItem) {
118+ var pos = loaderItem.scopeCardPosition(scopeId);
119+ return loaderItem.mapToItem(null, pos.x, pos.y);
120+ }
121+ }
122+ }
123+
124+ function ensureAllScopeVisible(scopeId) {
125+ if (middleItems.count > 1) {
126+ var loaderItem = middleItems.itemAt(1).item;
127+ if (loaderItem) {
128+ var pos = loaderItem.scopeCardPosition(scopeId);
129+ loaderItem.contentY = Math.min(pos.y, loaderItem.contentHeight - loaderItem.height);
130+ }
131+ }
132+ }
133+
134+ onProgressChanged: {
135+ if (progress == 0) {
136+ pageHeader.resetSearch();
137+ pageHeader.unfocus(); // Shouldn't the previous call do this too?
138+ }
139+ }
140+
141+ ScopeStyle {
142+ id: overviewScopeStyle
143+ style: { "foreground-color" : "white", "background-color" : "transparent" }
144+ }
145+
146+ DashBackground {
147+ anchors.fill: parent
148+ source: "graphics/dark_background.jpg"
149+ }
150+
151+ Connections {
152+ target: pageHeader
153+ onSearchQueryChanged: {
154+ // Need this in order, otherwise something gets unhappy in rendering
155+ // of the overlay in carousels because the parent of the dash dies for
156+ // a moment, this way we make sure it's reparented first
157+ // by forceXYScalerEater making dashItemEater return scopesOverviewXYScaler
158+ // before we kill the previous parent by scope.searchQuery
159+ root.forceXYScalerEater = true;
160+ root.scope.searchQuery = pageHeader.searchQuery;
161+ root.forceXYScalerEater = false;
162+ }
163+ }
164+
165+ Binding {
166+ target: pageHeader
167+ property: "searchQuery"
168+ value: scope ? scope.searchQuery : ""
169+ }
170+
171+ Item {
172+ id: scopesOverviewContent
173+ x: previewListView.open ? -width : 0
174+ Behavior on x { UbuntuNumberAnimation { } }
175+ width: parent.width
176+ height: parent.height
177+
178+ PageHeader {
179+ id: pageHeader
180+ objectName: "scopesOverviewPageHeader"
181+
182+ readonly property real yDisplacement: pageHeader.height + tabBar.height + tabBar.anchors.margins
183+
184+ y: {
185+ if (root.progress < 0.5) {
186+ return -yDisplacement;
187+ } else {
188+ return -yDisplacement + (root.progress - 0.5) * yDisplacement * 2;
189+ }
190+ }
191+ width: parent.width
192+ clip: true
193+ title: i18n.tr("Manage Dash")
194+ scopeStyle: overviewScopeStyle
195+ showSignatureLine: false
196+ searchEntryEnabled: true
197+ }
198+
199+ ScopesOverviewTab {
200+ id: tabBar
201+ anchors {
202+ left: parent.left
203+ right: parent.right
204+ top: pageHeader.bottom
205+ margins: units.gu(2)
206+ }
207+ height: units.gu(4)
208+
209+ enabled: opacity == 1
210+ opacity: !scope || scope.searchQuery == "" ? 1 : 0
211+ Behavior on opacity { UbuntuNumberAnimation { } }
212+ }
213+
214+ Repeater {
215+ id: middleItems
216+ objectName: "scopesOverviewRepeater"
217+ property real overrideOpacity: -1
218+ model: scope && scope.searchQuery == "" ? scope.categories : null
219+ delegate: Loader {
220+ id: loader
221+ objectName: "scopesOverviewRepeaterChild" + index
222+
223+ height: {
224+ if (index == 0) {
225+ return root.height;
226+ } else {
227+ return root.height - pageHeader.height - tabBar.height - tabBar.anchors.margins - units.gu(2);
228+ }
229+ }
230+ width: {
231+ if (index == 0) {
232+ return root.width / scopeScale;
233+ } else {
234+ return root.width;
235+ }
236+ }
237+ x: {
238+ if (index == 0) {
239+ return (root.width - width) / 2;
240+ } else {
241+ return 0;
242+ }
243+ }
244+ anchors {
245+ bottom: scopesOverviewContent.bottom
246+ }
247+
248+ scale: index == 0 ? scopeScale : 1
249+
250+ opacity: {
251+ if (middleItems.overrideOpacity >= 0)
252+ return middleItems.overrideOpacity;
253+
254+ if (tabBar.currentTab != index)
255+ return 0;
256+
257+ return index == 0 ? 1 : root.progress;
258+ }
259+ Behavior on opacity {
260+ enabled: root.progress == 1
261+ UbuntuNumberAnimation { }
262+ }
263+ enabled: opacity == 1
264+
265+ clip: index == 1
266+
267+ CardTool {
268+ id: cardTool
269+ objectName: "cardTool"
270+ count: results.count
271+ template: model.renderer
272+ components: model.components
273+ viewWidth: parent.width
274+ }
275+
276+ source: {
277+ if (index == 0 && categoryId == "favorites") return "ScopesOverviewFavorites.qml";
278+ else if (index == 1 && categoryId == "all") return "ScopesOverviewAll.qml";
279+ else return "";
280+ }
281+
282+ onLoaded: {
283+ item.model = Qt.binding(function() { return results; });
284+ item.cardTool = cardTool;
285+ if (index == 0) {
286+ item.scopeWidth = Qt.binding(function() { return root.width; });
287+ item.scopeHeight = Qt.binding(function() { return root.height; });
288+ item.appliedScale = Qt.binding(function() { return loader.scale });
289+ item.currentIndex = Qt.binding(function() { return root.currentIndex });
290+ } else if (index == 1) {
291+ item.extraHeight = bottomBar.height;
292+ }
293+ }
294+
295+ Connections {
296+ target: loader.item
297+ onClicked: {
298+ if (tabBar.currentTab == 0) {
299+ root.favoriteSelected(itemModel.scopeId);
300+ } else {
301+ var favoriteScopesItem = middleItems.itemAt(0).item;
302+ var scopeIndex = favoriteScopesItem.model.scopeIndex(itemModel.scopeId);
303+ if (scopeIndex >= 0) {
304+ root.allFavoriteSelected(itemModel.scopeId);
305+ } else {
306+ // Will result in an openScope from root.scope
307+ scopesOverviewXYScaler.restorePosition = item.mapToItem(null, 0, 0);
308+ scopesOverviewXYScaler.restoreSize = allCardSize;
309+ root.scope.activate(result);
310+ }
311+ }
312+ }
313+ onPressAndHold: {
314+ // Preview can call openScope so make sure restorePosition and restoreSize are set
315+ scopesOverviewXYScaler.restorePosition = undefined;
316+ scopesOverviewXYScaler.restoreSize = allCardSize;
317+
318+ previewListView.model = target.model;
319+ previewListView.currentIndex = -1;
320+ previewListView.currentIndex = index;
321+ previewListView.open = true;
322+ }
323+ }
324+ }
325+ }
326+
327+ GenericScopeView {
328+ id: searchResultsViewer
329+ objectName: "searchResultsViewer"
330+ anchors {
331+ top: pageHeader.bottom
332+ right: parent.right
333+ left: parent.left
334+ bottom: parent.bottom
335+ }
336+ scope: root.scope && root.scope.searchQuery != "" ? root.scope : null
337+ scopeStyle: overviewScopeStyle
338+ enabled: opacity == 1
339+ showPageHeader: false
340+ clip: true
341+ opacity: searchResultsViewer.scope ? 1 : 0
342+ isCurrent: true
343+ Behavior on opacity { UbuntuNumberAnimation { } }
344+
345+ function itemClicked(index, result, item, itemModel, resultsModel, limitedCategoryItemCount) {
346+ pageHeader.closePopup();
347+ if (itemModel.scopeId) {
348+ // This can end up in openScope so save restorePosition and restoreSize
349+ scopesOverviewXYScaler.restorePosition = item.mapToItem(null, 0, 0);
350+ scopesOverviewXYScaler.restoreSize = Qt.size(item.width, item.height);
351+ root.searchSelected(itemModel.scopeId, result, item.mapToItem(null, 0, 0), Qt.size(item.width, item.height));
352+ } else {
353+ // Not a scope, just activate it
354+ searchResultsViewer.scope.activate(result);
355+ }
356+ }
357+
358+ function itemPressedAndHeld(index, itemModel, resultsModel, limitedCategoryItemCount) {
359+ // Do nothing
360+ }
361+ }
362+
363+ Rectangle {
364+ id: bottomBar
365+ color: "black"
366+ height: units.gu(8)
367+ width: parent.width
368+ enabled: opacity == 1
369+ opacity: scope && scope.searchQuery == "" ? 1 : 0
370+ Behavior on opacity { UbuntuNumberAnimation { } }
371+ y: {
372+ if (root.progress < 0.5) {
373+ return parent.height;
374+ } else {
375+ return parent.height - (root.progress - 0.5) * height * 2;
376+ }
377+ }
378+
379+ AbstractButton {
380+ objectName: "scopesOverviewDoneButton"
381+ width: Math.max(label.width + units.gu(2), units.gu(10))
382+ height: units.gu(4)
383+ anchors {
384+ left: parent.left
385+ leftMargin: units.gu(2)
386+ verticalCenter: parent.verticalCenter
387+ }
388+ Rectangle {
389+ anchors.fill: parent
390+ border.color: "white"
391+ border.width: units.dp(1)
392+ radius: units.dp(10)
393+ color: parent.pressed ? "gray" : "transparent"
394+ }
395+ Label {
396+ id: label
397+ anchors.centerIn: parent
398+ text: i18n.tr("Done")
399+ color: parent.pressed ? "black" : "white"
400+ }
401+ onClicked: root.done();
402+ }
403+
404+ AbstractButton {
405+ objectName: "scopesOverviewStoreButton"
406+ width: Math.max(storeLabel.width, units.gu(10))
407+ height: units.gu(4)
408+ anchors {
409+ right: parent.right
410+ verticalCenter: parent.verticalCenter
411+ }
412+ Image {
413+ id: storeImage
414+ source: "graphics/apps-scope.png"
415+ anchors.horizontalCenter: parent.horizontalCenter
416+ width: units.gu(2)
417+ height: units.gu(2)
418+ fillMode: Image.Stretch
419+ }
420+ Label {
421+ id: storeLabel
422+ anchors.horizontalCenter: parent.horizontalCenter
423+ anchors.top: storeImage.bottom
424+ text: i18n.tr("Store")
425+ color: "white"
426+ }
427+ onClicked: {
428+ // Just zoom from the middle
429+ scopesOverviewXYScaler.restorePosition = undefined;
430+ scopesOverviewXYScaler.restoreSize = allCardSize;
431+ scope.performQuery("scope://com.canonical.scopes.clickstore");
432+ }
433+ }
434+ }
435+ }
436+
437+ PreviewListView {
438+ id: previewListView
439+ objectName: "scopesOverviewPreviewListView"
440+ scope: root.scope
441+ scopeStyle: overviewScopeStyle
442+ visible: x != width
443+ width: parent.width
444+ height: parent.height
445+ anchors.left: scopesOverviewContent.right
446+ }
447+
448+
449+
450+ Item {
451+ id: scopesOverviewXYScaler
452+ width: parent.width
453+ height: parent.height
454+
455+ clip: scale != 1.0
456+ enabled: scale == 1
457+
458+ property bool animationsEnabled: root.showingNonFavoriteScope || root.growingDashFromPos
459+
460+ property var restorePosition
461+ property var restoreSize
462+
463+ Behavior on x {
464+ enabled: scopesOverviewXYScaler.animationsEnabled
465+ UbuntuNumberAnimation { }
466+ }
467+ Behavior on y {
468+ enabled: scopesOverviewXYScaler.animationsEnabled
469+ UbuntuNumberAnimation { }
470+ }
471+ Behavior on opacity {
472+ enabled: scopesOverviewXYScaler.animationsEnabled
473+ UbuntuNumberAnimation { }
474+ }
475+ Behavior on scale {
476+ enabled: scopesOverviewXYScaler.animationsEnabled
477+ UbuntuNumberAnimation {
478+ onRunningChanged: {
479+ if (!running) {
480+ if (root.showingNonFavoriteScope && scopesOverviewXYScaler.scale != 1) {
481+ root.scope.closeScope(tempScopeItem.scope);
482+ tempScopeItem.scope = null;
483+ } else if (root.growingDashFromPos) {
484+ root.growingDashFromPos = false;
485+ }
486+ }
487+ }
488+ }
489+ }
490+
491+ DashBackground {
492+ anchors.fill: tempScopeItem
493+ visible: tempScopeItem.visible
494+ parent: tempScopeItem.parent
495+ }
496+
497+ GenericScopeView {
498+ id: tempScopeItem
499+ objectName: "scopesOverviewTempScopeItem"
500+
501+ width: parent.width
502+ height: parent.height
503+ scale: dash.contentScale
504+ clip: scale != 1.0
505+ visible: scope != null
506+ hasBackAction: true
507+ isCurrent: visible
508+ onBackClicked: {
509+ var v = scopesOverviewXYScaler.restoreSize.width / tempScopeItem.width;
510+ scopesOverviewXYScaler.scale = v;
511+ if (scopesOverviewXYScaler.restorePosition) {
512+ scopesOverviewXYScaler.x = scopesOverviewXYScaler.restorePosition.x -(tempScopeItem.width - tempScopeItem.width * v) / 2;
513+ scopesOverviewXYScaler.y = scopesOverviewXYScaler.restorePosition.y -(tempScopeItem.height - tempScopeItem.height * v) / 2;
514+ } else {
515+ scopesOverviewXYScaler.x = 0;
516+ scopesOverviewXYScaler.y = 0;
517+ }
518+ scopesOverviewXYScaler.opacity = 0;
519+ middleItems.overrideOpacity = -1;
520+ }
521+ }
522+ }
523+}
qml/Dash/ScopesOverviewAll.qmlnew file+54
@@ -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+
17+import QtQuick 2.0
18+import Ubuntu.Components 0.1
19+
20+Flickable {
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+}
qml/Dash/ScopesOverviewFavorites.qmlnew file+73
@@ -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+
17+import QtQuick 2.0
18+
19+Flickable {
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: currentIndex < repeater.count ? repeater.itemAt(currentIndex) : null
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+}
qml/Dash/ScopesOverviewTab.qmlnew file+74
@@ -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+
17+import QtQuick 2.3
18+import Ubuntu.Components 0.1
19+
20+Item {
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+}
qml/Dash/graphics/apps-scope.pngnew file

Binary file not shown.

qml/Dash/graphics/dark_background.jpgnew file

Binary file not shown.

tests/autopilot/unity8/shell/tests/test_emulators.py+1−1
@@ -122,7 +122,7 @@ class DashEmulatorTestCase(tests.DashBaseTestCase):
122 self._assert_scope_is_opened(scope, scope_id)
122 self._assert_scope_is_opened(scope, scope_id)
123
123
124 def test_open_generic_scope(self):
124 def test_open_generic_scope(self):
125− scope_id = 'scopes'
125+ scope_id = 'musicaggregator'
126 scope = self.dash.open_scope(scope_id)
126 scope = self.dash.open_scope(scope_id)
127 self._assert_scope_is_opened(scope, scope_id)
127 self._assert_scope_is_opened(scope, scope_id)
128 self.assertIsInstance(scope, dash_emulators.GenericScopeView)
128 self.assertIsInstance(scope, dash_emulators.GenericScopeView)
tests/mocks/Unity/CMakeLists.txt+1
@@ -22,6 +22,7 @@ add_definitions(-DQT_NO_KEYWORDS)
22set(UnityQML_SOURCES
22set(UnityQML_SOURCES
23 fake_scope.cpp
23 fake_scope.cpp
24 fake_scopes.cpp
24 fake_scopes.cpp
25+ fake_scopesoverview.cpp
25 fake_categories.cpp
26 fake_categories.cpp
26 fake_navigation.cpp
27 fake_navigation.cpp
27 fake_resultsmodel.cpp
28 fake_resultsmodel.cpp
tests/mocks/Unity/fake_resultsmodel.cpp+2−1
@@ -58,8 +58,9 @@ ResultsModel::data(const QModelIndex& index, int role) const
58 case RoleUri:
58 case RoleUri:
59 case RoleCategoryId:
59 case RoleCategoryId:
60 case RoleDndUri:
60 case RoleDndUri:
61− case RoleResult:
62 return QString();
61 return QString();
62+ case RoleResult:
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:
tests/mocks/Unity/fake_scope.cpp+18−6
@@ -18,14 +18,16 @@
18#include <QUrl>
18#include <QUrl>
19
19
20#include "fake_scope.h"
20#include "fake_scope.h"
21+
21#include "fake_navigation.h"
22#include "fake_navigation.h"
22#include "fake_resultsmodel.h"
23#include "fake_resultsmodel.h"
24+#include "fake_scopes.h"
23
25
24−Scope::Scope(QObject* parent) : Scope(QString(), QString(), false, parent)
26+Scope::Scope(Scopes* parent) : Scope(QString(), QString(), false, parent)
25{
27{
26}
28}
27
29
28−Scope::Scope(QString const& id, QString const& name, bool favorite, QObject* parent, int categories)
30+Scope::Scope(QString const& id, QString const& name, bool favorite, Scopes* parent, int categories)
29 : unity::shell::scopes::ScopeInterface(parent)
31 : unity::shell::scopes::ScopeInterface(parent)
30 , m_id(id)
32 , m_id(id)
31 , m_name(name)
33 , m_name(name)
@@ -36,6 +38,7 @@ Scope::Scope(QString const& id, QString const& name, bool favorite, QObject* par
36 , m_currentAltNavigationId("altroot")
38 , m_currentAltNavigationId("altroot")
37 , m_previewRendererName("preview-generic")
39 , m_previewRendererName("preview-generic")
38 , m_categories(new Categories(categories, this))
40 , m_categories(new Categories(categories, this))
41+ , m_openScope(nullptr)
39{
42{
40}
43}
41
44
@@ -66,7 +69,7 @@ QString Scope::description() const
66
69
67QString Scope::searchHint() const
70QString Scope::searchHint() const
68{
71{
69− return QString("");
72+ return QString("Search %1").arg(m_name);
70}
73}
71
74
72QString Scope::shortcut() const
75QString Scope::shortcut() const
@@ -158,7 +161,12 @@ void Scope::setNoResultsHint(const QString& str)
158
161
159void Scope::activate(QVariant const& result)
162void Scope::activate(QVariant const& result)
160{
163{
161− Q_UNUSED(result);
164+ qDebug() << "Called activate on scope" << m_id << "with result" << result;
165+ if (result.toString() == "Result.2.2") {
166+ Scopes *scopes = dynamic_cast<Scopes*>(parent());
167+ m_openScope = scopes->getScopeFromAll("MockScope9");
168+ Q_EMIT openScope(m_openScope);
169+ }
162}
170}
163
171
164PreviewStack* Scope::preview(QVariant const& result)
172PreviewStack* Scope::preview(QVariant const& result)
@@ -174,9 +182,13 @@ void Scope::cancelActivation()
174{
182{
175}
183}
176
184
177−void Scope::closeScope(unity::shell::scopes::ScopeInterface* /*scope*/)
185+void Scope::closeScope(unity::shell::scopes::ScopeInterface* scope)
178{
186{
187+ if (scope != m_openScope) {
188+ qDebug() << scope << m_openScope;
179− qFatal("Scope::closeScope is not implemented");
189+ qFatal("Scope::closeScope got wrong scope in closeScope");
190+ }
191+ m_openScope = nullptr;
180}
192}
181
193
182QString Scope::currentNavigationId() const
194QString Scope::currentNavigationId() const
tests/mocks/Unity/fake_scope.h+6−3
@@ -24,13 +24,15 @@
24
24
25#include <QTimer>
25#include <QTimer>
26
26
27+class Scopes;
28+
27class Scope : public unity::shell::scopes::ScopeInterface
29class Scope : public unity::shell::scopes::ScopeInterface
28{
30{
29 Q_OBJECT
31 Q_OBJECT
30
32
31public:
33public:
32− Scope(QObject* parent = 0);
34+ Scope(Scopes* parent = 0);
33− Scope(QString const& id, QString const& name, bool favorite, QObject* parent = 0, int categories = 20);
35+ Scope(QString const& id, QString const& name, bool favorite, Scopes* parent = 0, int categories = 20);
34
36
35 /* getters */
37 /* getters */
36 QString id() const override;
38 QString id() const override;
@@ -92,7 +94,8 @@ protected:
92
94
93 QString m_previewRendererName;
95 QString m_previewRendererName;
94
96
95− Categories* m_categories;
97+ unity::shell::scopes::CategoriesInterface* m_categories;
98+ unity::shell::scopes::ScopeInterface* m_openScope;
96};
99};
97
100
98#endif // FAKE_SCOPE_H
101#endif // FAKE_SCOPE_H
tests/mocks/Unity/fake_scopes.cpp+45−6
@@ -18,6 +18,7 @@
18
18
19// Self
19// Self
20#include "fake_scopes.h"
20#include "fake_scopes.h"
21+#include "fake_scopesoverview.h"
21
22
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)
23
24
@@ -26,6 +27,7 @@
26
27
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{
@@ -52,10 +54,17 @@ void Scopes::updateScopes()
52 addScope(new Scope("clickscope", "Apps", true, this));
54 addScope(new Scope("clickscope", "Apps", true, this));
53 addScope(new Scope("MockScope5", "Videos", true, this));
55 addScope(new Scope("MockScope5", "Videos", true, this));
54 addScope(new Scope("SingleCategoryScope", "Single", true, this, 1));
56 addScope(new Scope("SingleCategoryScope", "Single", true, this, 1));
57+ addScope(new Scope("MockScope4", "MS4", true, this));
58+ addScope(new Scope("MockScope6", "MS6", true, this));
59+ addScope(new Scope("MockScope7", "MS7", false, this));
60+ addScope(new Scope("MockScope8", "MS8", false, this));
61+ addScope(new Scope("MockScope9", "MS9", false, this));
62+ m_scopesOverview = new ScopesOverview(this);
55
63
56 if (!m_loaded) {
64 if (!m_loaded) {
57 m_loaded = true;
65 m_loaded = true;
58 Q_EMIT loadedChanged();
66 Q_EMIT loadedChanged();
67+ Q_EMIT overviewScopeChanged();
59 }
68 }
60}
69}
61
70
@@ -64,10 +73,13 @@ void Scopes::clear()
64 timer.stop();
73 timer.stop();
65 if (m_scopes.size() > 0) {
74 if (m_scopes.size() > 0) {
66 beginRemoveRows(QModelIndex(), 0, m_scopes.count()-1);
75 beginRemoveRows(QModelIndex(), 0, m_scopes.count()-1);
67− qDeleteAll(m_scopes);
76+ qDeleteAll(m_allScopes);
77+ m_allScopes.clear();
68 m_scopes.clear();
78 m_scopes.clear();
69 endRemoveRows();
79 endRemoveRows();
70 }
80 }
81+ delete m_scopesOverview;
82+ m_scopesOverview = nullptr;
71
83
72 if (m_loaded) {
84 if (m_loaded) {
73 m_loaded = false;
85 m_loaded = false;
@@ -113,8 +125,22 @@ unity::shell::scopes::ScopeInterface* Scopes::getScope(int row) const
113 return m_scopes[row];
125 return m_scopes[row];
114}
126}
115
127
116−unity::shell::scopes::ScopeInterface* Scopes::getScope(QString const&) const
128+unity::shell::scopes::ScopeInterface* Scopes::getScope(QString const &scope_id) const
117{
129{
130+ // According to mh3 Scopes::getScope should only return favorite scopes (i.e the ones in the model)
131+ for (Scope *scope : m_scopes) {
132+ if (scope->id() == scope_id)
133+ return scope;
134+ }
135+ return nullptr;
136+}
137+
138+Scope* Scopes::getScopeFromAll(const QString& scope_id) const
139+{
140+ for (Scope *scope : m_allScopes) {
141+ if (scope->id() == scope_id)
142+ return scope;
143+ }
118 return nullptr;
144 return nullptr;
119}
145}
120
146
@@ -135,13 +161,26 @@ int Scopes::count() const
135
161
136unity::shell::scopes::ScopeInterface* Scopes::overviewScope() const
162unity::shell::scopes::ScopeInterface* Scopes::overviewScope() const
137{
163{
138− return nullptr;
164+ return m_scopesOverview;
165+}
166+
167+QList<Scope*> Scopes::scopes() const
168+{
169+ return m_scopes;
170+}
171+
172+QList<Scope*> Scopes::allScopes() const
173+{
174+ return m_allScopes;
139}
175}
140
176
141void Scopes::addScope(Scope* scope)
177void Scopes::addScope(Scope* scope)
142{
178{
143 int index = rowCount();
179 int index = rowCount();
180+ if (scope->favorite()) {
144− beginInsertRows(QModelIndex(), index, index);
181+ beginInsertRows(QModelIndex(), index, index);
145− m_scopes.append(scope);
182+ m_scopes.append(scope);
146− endInsertRows();
183+ endInsertRows();
184+ }
185+ m_allScopes.append(scope);
147}
186}
tests/mocks/Unity/fake_scopes.h+8−1
@@ -53,11 +53,18 @@ public:
53 int count() const override;
53 int count() const override;
54 unity::shell::scopes::ScopeInterface* overviewScope() const override;
54 unity::shell::scopes::ScopeInterface* overviewScope() const override;
55
55
56+ // This is used as part of implementation of the other C++ code, not API
57+ QList<Scope*> scopes() const;
58+ QList<Scope*> allScopes() const;
59+ Scope* getScopeFromAll(const QString& scope_id) const;
60+
56private Q_SLOTS:
61private Q_SLOTS:
57 void updateScopes();
62 void updateScopes();
58
63
59private:
64private:
60− QList<Scope*> m_scopes;
65+ QList<Scope*> m_scopes; // the favorite ones
66+ QList<Scope*> m_allScopes;
67+ Scope *m_scopesOverview;
61 bool m_loaded;
68 bool m_loaded;
62 QTimer timer;
69 QTimer timer;
63};
70};
tests/mocks/Unity/fake_scopesoverview.cppnew file+281
@@ -0,0 +1,281 @@
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+
23+ScopesOverview::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+
32+void 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+
44+Q_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+
51+ScopesOverviewCategories::ScopesOverviewCategories(Scopes *scopes, QObject* parent)
52+ : unity::shell::scopes::CategoriesInterface(parent)
53+ , m_scopes(scopes)
54+{
55+}
56+
57+int ScopesOverviewCategories::rowCount(const QModelIndex& /*parent*/) const
58+{
59+ return 2;
60+}
61+
62+void ScopesOverviewCategories::addSpecialCategory(QString const&, QString const&, QString const&, QString const&, QObject*)
63+{
64+ qFatal("Using un-implemented ScopesOverviewCategories::addSpecialCategory");
65+}
66+
67+bool ScopesOverviewCategories::overrideCategoryJson(QString const& /* categoryId */, QString const& /* json */)
68+{
69+ qFatal("Using un-implemented ScopesOverviewCategories::overrideCategoryJson");
70+}
71+
72+QVariant
73+ScopesOverviewCategories::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+ QList<Scope*> scopes = index.row() == 0 ? m_scopes->scopes() : m_scopes->allScopes();
85+ resultsModel = new ScopesOverviewResultsModel(scopes, categoryId, that);
86+ m_resultsModels[index.row()] = resultsModel;
87+ }
88+ switch (role) {
89+ case RoleCategoryId:
90+ return categoryId;
91+ case RoleName:
92+ return index.row() == 0 ? "Favorites" : "All";
93+ case RoleIcon:
94+ return QVariant();
95+ case RoleRawRendererTemplate:
96+ qFatal("Using un-implemented RoleRawRendererTemplate Categories role");
97+ return QVariant();
98+ case RoleRenderer:
99+ {
100+ QVariantMap map;
101+ map["category-layout"] = "grid";
102+ map["card-size"] = "small";
103+ map["overlay"] = true;
104+ return map;
105+ }
106+ case RoleComponents:
107+ {
108+ QVariantMap map, artMap;
109+ artMap["aspect-ratio"] = "0.5";
110+ artMap["field"] = "art";
111+ map["art"] = artMap;
112+ map["title"] = "HOLA";
113+ return map;
114+ }
115+ case RoleResults:
116+ return QVariant::fromValue(resultsModel);
117+ case RoleCount:
118+ return resultsModel->rowCount();
119+ case RoleHeaderLink:
120+ return QString();
121+ default:
122+ qFatal("Using un-implemented Categories role");
123+ return QVariant();
124+ }
125+}
126+
127+
128+
129+ScopesOverviewSearchCategories::ScopesOverviewSearchCategories(Scopes *scopes, QObject* parent)
130+ : unity::shell::scopes::CategoriesInterface(parent)
131+ , m_scopes(scopes)
132+{
133+}
134+
135+int ScopesOverviewSearchCategories::rowCount(const QModelIndex& /*parent*/) const
136+{
137+ return 2;
138+}
139+
140+void ScopesOverviewSearchCategories::addSpecialCategory(QString const&, QString const&, QString const&, QString const&, QObject*)
141+{
142+ qFatal("Using un-implemented ScopesOverviewSearchCategories::addSpecialCategory");
143+}
144+
145+bool ScopesOverviewSearchCategories::overrideCategoryJson(QString const& /* categoryId */, QString const& /* json */)
146+{
147+ qFatal("Using un-implemented ScopesOverviewSearchCategories::overrideCategoryJson");
148+}
149+
150+QVariant
151+ScopesOverviewSearchCategories::data(const QModelIndex& index, int role) const
152+{
153+ if (!index.isValid()) {
154+ return QVariant();
155+ }
156+
157+ const QString categoryId = index.row() == 0 ? "searchA" : "searchB";
158+
159+ unity::shell::scopes::ResultsModelInterface *resultsModel = m_resultsModels[index.row()];
160+ if (!resultsModel) {
161+ QObject *that = const_cast<ScopesOverviewSearchCategories*>(this);
162+ QList<Scope *> scopes;
163+ if (index.row() == 0) {
164+ scopes << m_scopes->getScopeFromAll("clickscope") << nullptr << m_scopes->getScopeFromAll("MockScope2");
165+ } else {
166+ scopes << nullptr << m_scopes->getScopeFromAll("MockScope7") << nullptr << m_scopes->getScopeFromAll("MockScope1");
167+ }
168+ resultsModel = new ScopesOverviewResultsModel(scopes, categoryId, that);
169+ m_resultsModels[index.row()] = resultsModel;
170+ }
171+ switch (role) {
172+ case RoleCategoryId:
173+ return categoryId;
174+ case RoleName:
175+ return index.row() == 0 ? "SearchA" : "SearchB";
176+ case RoleIcon:
177+ return QVariant();
178+ case RoleRawRendererTemplate:
179+ qFatal("Using un-implemented RoleRawRendererTemplate Categories role");
180+ return QVariant();
181+ case RoleRenderer:
182+ {
183+ QVariantMap map;
184+ map["category-layout"] = "grid";
185+ map["card-size"] = "small";
186+ map["overlay"] = true;
187+ return map;
188+ }
189+ case RoleComponents:
190+ {
191+ QVariantMap map, artMap;
192+ artMap["aspect-ratio"] = "1";
193+ artMap["field"] = "art";
194+ map["art"] = artMap;
195+ map["title"] = "HOLA";
196+ return map;
197+ }
198+ case RoleResults:
199+ return QVariant::fromValue(resultsModel);
200+ case RoleCount:
201+ return resultsModel->rowCount();
202+ case RoleHeaderLink:
203+ return QString();
204+ default:
205+ qFatal("Using un-implemented Categories role");
206+ return QVariant();
207+ }
208+}
209+
210+
211+ScopesOverviewResultsModel::ScopesOverviewResultsModel(const QList<Scope *> &scopes, const QString &categoryId, QObject* parent)
212+ : unity::shell::scopes::ResultsModelInterface(parent)
213+ , m_scopes(scopes)
214+ , m_categoryId(categoryId)
215+{
216+}
217+
218+QString ScopesOverviewResultsModel::categoryId() const
219+{
220+ return m_categoryId;
221+}
222+
223+void ScopesOverviewResultsModel::setCategoryId(QString const& /*id*/)
224+{
225+ qFatal("Calling un-implemented ScopesOverviewResultsModel::setCategoryId");
226+}
227+
228+int ScopesOverviewResultsModel::scopeIndex(QString const& id) const
229+{
230+ const int scopeCount = count();
231+ for (int i = 0; i < scopeCount; ++i) {
232+ if (m_scopes[i]->id() == id)
233+ return i;
234+ }
235+ return -1;
236+}
237+
238+QHash<int, QByteArray> ScopesOverviewResultsModel::roleNames() const
239+{
240+ QHash<int, QByteArray> roles = unity::shell::scopes::ResultsModelInterface::roleNames();
241+ roles[RoleBackground + 1] = "scopeId";
242+ return roles;
243+}
244+
245+int ScopesOverviewResultsModel::rowCount(const QModelIndex& parent) const
246+{
247+ Q_UNUSED(parent);
248+
249+ return m_scopes.count();
250+}
251+
252+int ScopesOverviewResultsModel::count() const
253+{
254+ return rowCount();
255+}
256+
257+QVariant
258+ScopesOverviewResultsModel::data(const QModelIndex& index, int role) const
259+{
260+ unity::shell::scopes::ScopeInterface *scope = m_scopes[index.row()];
261+ switch (role) {
262+ case RoleUri:
263+ case RoleCategoryId:
264+ case RoleDndUri:
265+ return QString();
266+ case RoleResult:
267+ return scope ? scope->id() : QString("Result.%1.%2").arg(categoryId()).arg(index.row());
268+ case RoleTitle:
269+ return scope ? scope->name() : QString("Title.%1.%2").arg(categoryId()).arg(index.row());
270+ case RoleArt:
271+ return qmlDirectory() + "graphics/applicationIcons/dash.png";
272+ case RoleMascot:
273+ case RoleEmblem:
274+ case RoleSummary:
275+ case RoleBackground + 1: // scopeId
276+ return scope ? scope->id() : nullptr;
277+ break;
278+ default:
279+ return QVariant();
280+ }
281+}
tests/mocks/Unity/fake_scopesoverview.hnew file+104
@@ -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+
23+class Scopes;
24+
25+class ScopesOverview : public Scope
26+{
27+ Q_OBJECT
28+
29+public:
30+ ScopesOverview(Scopes* parent = 0);
31+
32+ void setSearchQuery(const QString& search_query) override;
33+ Q_INVOKABLE void activate(QVariant const& result) override;
34+
35+private:
36+ unity::shell::scopes::CategoriesInterface *m_scopesOverviewCategories;
37+ unity::shell::scopes::CategoriesInterface *m_searchCategories;
38+};
39+
40+class ScopesOverviewCategories : public unity::shell::scopes::CategoriesInterface
41+{
42+ Q_OBJECT
43+
44+public:
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+
53+private:
54+ mutable QHash<int, unity::shell::scopes::ResultsModelInterface*> m_resultsModels;
55+
56+ Scopes *m_scopes;
57+};
58+
59+class ScopesOverviewSearchCategories : public unity::shell::scopes::CategoriesInterface
60+{
61+ Q_OBJECT
62+
63+public:
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+
72+private:
73+ mutable QHash<int, unity::shell::scopes::ResultsModelInterface*> m_resultsModels;
74+
75+ Scopes *m_scopes;
76+};
77+
78+class ScopesOverviewResultsModel : public unity::shell::scopes::ResultsModelInterface
79+{
80+ Q_OBJECT
81+
82+public:
83+ explicit ScopesOverviewResultsModel(const QList<Scope *> &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+
99+private:
100+ QList<Scope *> m_scopes;
101+ QString m_categoryId;
102+};
103+
104+#endif // FAKE_SCOPESOVERVIEW_H
tests/plugins/Dash/cardcreator/2.res+2−2
@@ -89,7 +89,7 @@ left: parent.left;
89 wrapMode: Text.Wrap;
89 wrapMode: Text.Wrap;
90 maximumLineCount: 2;
90 maximumLineCount: 2;
91 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
91 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
92− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
92+ color: 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");
93 visible: showHeader ;
93 visible: showHeader ;
94 text: root.title;
94 text: root.title;
95 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
95 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
@@ -104,7 +104,7 @@ left: parent.left;
104 elide: Text.ElideRight;
104 elide: Text.ElideRight;
105 fontSize: "small";
105 fontSize: "small";
106 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
106 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
107− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
107+ color: 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");
108 visible: titleLabel.visible && titleLabel.text;
108 visible: titleLabel.visible && titleLabel.text;
109 text: cardData && cardData["subtitle"] || "";
109 text: cardData && cardData["subtitle"] || "";
110 font.weight: Font.Light;
110 font.weight: Font.Light;
tests/plugins/Dash/cardcreator/5.res+8−6
@@ -68,8 +68,9 @@ Loader {
68 visible: showHeader && status == Loader.Ready;
68 visible: showHeader && status == Loader.Ready;
69 sourceComponent: ShaderEffect {
69 sourceComponent: ShaderEffect {
70 id: overlay;
70 id: overlay;
71− height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2);
71+ height: (fixedHeaderHeight > 0 ? fixedHeaderHeight : headerHeight) + units.gu(2);
72− opacity: 0.6;
72+ property real luminance: 0.2126 * overlayColor.r + 0.7152 * overlayColor.g + 0.0722 * overlayColor.b;
73+ property color overlayColor: cardData && cardData["overlayColor"] || "#99000000";
73 property var source: ShaderEffectSource {
74 property var source: ShaderEffectSource {
74 id: shaderSource;
75 id: shaderSource;
75 sourceItem: artShapeLoader.item;
76 sourceItem: artShapeLoader.item;
@@ -90,15 +91,16 @@ Loader {
90 varying highp vec2 coord;
91 varying highp vec2 coord;
91 uniform sampler2D source;
92 uniform sampler2D source;
92 uniform lowp float qt_Opacity;
93 uniform lowp float qt_Opacity;
94+ uniform highp vec4 overlayColor;
93 void main() {
95 void main() {
94 lowp vec4 tex = texture2D(source, coord);
96 lowp vec4 tex = texture2D(source, coord);
95− gl_FragColor = vec4(0, 0, 0, tex.a) * qt_Opacity;
97+ gl_FragColor = vec4(overlayColor.r, overlayColor.g, overlayColor.b, 1) * qt_Opacity * overlayColor.a * tex.a;
96 }";
98 }";
97 }
99 }
98 }
100 }
99readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;
101readonly property int headerHeight: titleLabel.height + subtitleLabel.height + subtitleLabel.anchors.topMargin;
100Label {
102Label {
101− id: titleLabel;
103+ id: titleLabel;
102 objectName: "titleLabel";
104 objectName: "titleLabel";
103 anchors { left: parent.left;
105 anchors { left: parent.left;
104 leftMargin: units.gu(1);
106 leftMargin: units.gu(1);
@@ -112,7 +114,7 @@ Label {
112 wrapMode: Text.Wrap;
114 wrapMode: Text.Wrap;
113 maximumLineCount: 2;
115 maximumLineCount: 2;
114 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
116 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
115− color: "white";
117+ color: overlayLoader.item.luminance < (root.scopeStyle ? root.scopeStyle.threshold : 0.7) ? (root.scopeStyle ? root.scopeStyle.light : "white") : (root.scopeStyle ? root.scopeStyle.dark : "grey");
116 visible: showHeader && overlayLoader.active;
118 visible: showHeader && overlayLoader.active;
117 text: root.title;
119 text: root.title;
118 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
120 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
@@ -131,7 +133,7 @@ Label {
131 elide: Text.ElideRight;
133 elide: Text.ElideRight;
132 fontSize: "small";
134 fontSize: "small";
133 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
135 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
134− color: "white";
136+ color: overlayLoader.item.luminance < (root.scopeStyle ? root.scopeStyle.threshold : 0.7) ? (root.scopeStyle ? root.scopeStyle.light : "white") : (root.scopeStyle ? root.scopeStyle.dark : "grey");
135 visible: titleLabel.visible && titleLabel.text;
137 visible: titleLabel.visible && titleLabel.text;
136 text: cardData && cardData["subtitle"] || "";
138 text: cardData && cardData["subtitle"] || "";
137 font.weight: Font.Light;
139 font.weight: Font.Light;
tests/plugins/Dash/cardcreator/7.res+4−4
@@ -90,7 +90,7 @@ left: parent.left;
90 wrapMode: Text.Wrap;
90 wrapMode: Text.Wrap;
91 maximumLineCount: 2;
91 maximumLineCount: 2;
92 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
92 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
93− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
93+ color: 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");
94 visible: showHeader ;
94 visible: showHeader ;
95 text: root.title;
95 text: root.title;
96 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
96 font.weight: components && components["subtitle"] ? Font.DemiBold : Font.Normal;
@@ -104,7 +104,7 @@ Label {
104 elide: Text.ElideRight;
104 elide: Text.ElideRight;
105 fontSize: "small";
105 fontSize: "small";
106 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
106 font.pixelSize: Math.round(FontUtils.sizeToPixels(fontSize) * fontScale);
107− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
107+ color: 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");
108 visible: titleLabel.visible && titleLabel.text;
108 visible: titleLabel.visible && titleLabel.text;
109 text: cardData && cardData["subtitle"] || "";
109 text: cardData && cardData["subtitle"] || "";
110 font.weight: Font.Light;
110 font.weight: Font.Light;
@@ -115,8 +115,8 @@ CardAttributes {
115 id: attributesRow;
115 id: attributesRow;
116 objectName: "attributesRow";
116 objectName: "attributesRow";
117 anchors { left: parent.left; right: parent.right }
117 anchors { left: parent.left; right: parent.right }
118− color: backgroundLoader.active && backgroundLoader.item && backgroundLoader.item.luminance < 0.7 ? "white" : (root.scopeStyle ? root.scopeStyle.foreground : "grey");
118+ color: 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");
119− model: cardData["attributes"];
119+ model: cardData["attributes"];
120 }
120 }
121
121
122 ]
122 ]
tests/plugins/Dash/tst_ScopeStyle.qml+1−1
@@ -101,7 +101,7 @@ Rectangle {
101
101
102 function test_threshold_data() {
102 function test_threshold_data() {
103 return [
103 return [
104− { tag: "default", index: 0, threshold: 0.5020 },
104+ { tag: "default", index: 0, threshold: 0.7510 },
105 { tag: "red on black", index: 1, threshold: 0.1063 },
105 { tag: "red on black", index: 1, threshold: 0.1063 },
106 { tag: "green on white", index: 2, threshold: 0.6795 },
106 { tag: "green on white", index: 2, threshold: 0.6795 },
107 { tag: "blue on darkgrey", index: 3, threshold: 0.3675 },
107 { tag: "blue on darkgrey", index: 3, threshold: 0.3675 },
tests/qmltests/CMakeLists.txt+1
@@ -49,6 +49,7 @@ add_qml_test(Dash/Previews PreviewPayments)
49add_qml_test(Dash/Previews PreviewProgress)
49add_qml_test(Dash/Previews PreviewProgress)
50add_qml_test(Dash/Previews PreviewRatingDisplay)
50add_qml_test(Dash/Previews PreviewRatingDisplay)
51add_qml_test(Dash/Previews PreviewRatingInput)
51add_qml_test(Dash/Previews PreviewRatingInput)
52+add_qml_test(Dash/Previews PreviewTable)
52add_qml_test(Dash/Previews PreviewTextSummary)
53add_qml_test(Dash/Previews PreviewTextSummary)
53add_qml_test(Dash/Previews PreviewVideoPlayback)
54add_qml_test(Dash/Previews PreviewVideoPlayback)
54add_qml_test(Dash/Previews PreviewWidgetFactory)
55add_qml_test(Dash/Previews PreviewWidgetFactory)
tests/qmltests/Dash/Previews/tst_PreviewExpandable.qml+5−1
@@ -30,12 +30,16 @@ Rectangle {
30 property string longText2: "This is a very very very long text. 1 This is a very very very long text. 2 This is a very very very long text. 3 This is a very very very long text. 4 This is a very very very long text. 5 This is a very very very long text. 6 This is a very very very long text. 7 This is a very very very long text. 8 This is a very very very long text. 9 This is a very very very long text. 10 This is a very very very long text. 11 This is a very very very long text."
30 property string longText2: "This is a very very very long text. 1 This is a very very very long text. 2 This is a very very very long text. 3 This is a very very very long text. 4 This is a very very very long text. 5 This is a very very very long text. 6 This is a very very very long text. 7 This is a very very very long text. 8 This is a very very very long text. 9 This is a very very very long text. 10 This is a very very very long text. 11 This is a very very very long text."
31 property string shortText: "This is a short text :)"
31 property string shortText: "This is a short text :)"
32
32
33+ property var tableData: {
34+ "values": [ [ "Long Label 1", "Value 1"], [ "Label 2", "Long Value 2"], [ "Label 3", "Value 3"], [ "Label 4", "Value 4"], [ "Label 5", "Value 5"] ]
35+ }
36+
33 property var widgetData: {
37 property var widgetData: {
34 "title": "Title here",
38 "title": "Title here",
35 "collapsed-widgets": 2,
39 "collapsed-widgets": 2,
36 "widgets": [
40 "widgets": [
37 { "type": "text", "widgetId" : "text1", "properties" : { "text": longText } },
41 { "type": "text", "widgetId" : "text1", "properties" : { "text": longText } },
38− { "type": "text", "widgetId" : "text2", "properties" : { "text": longText2 } },
42+ { "type": "table", "widgetId" : "table1", "properties" : tableData },
39 { "type": "text", "widgetId" : "text3", "properties" : { "text": shortText } },
43 { "type": "text", "widgetId" : "text3", "properties" : { "text": shortText } },
40 { "type": "text", "widgetId" : "text4", "properties" : { "text": longText } }
44 { "type": "text", "widgetId" : "text4", "properties" : { "text": longText } }
41 ]
45 ]
tests/qmltests/Dash/Previews/tst_PreviewTable.qmlnew file+114
@@ -0,0 +1,114 @@
1+/*
2+ * Copyright 2014 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+import QtQuick 2.0
18+import QtTest 1.0
19+import Ubuntu.Components 0.1
20+import "../../../../qml/Dash/Previews"
21+import Unity.Test 0.1 as UT
22+
23+Rectangle {
24+ id: root
25+ width: units.gu(40)
26+ height: units.gu(80)
27+ color: Theme.palette.selected.background
28+
29+ property var widgetDataComplete: {
30+ "title": "Title here",
31+ "values": [ [ "Long Label 1", "Value 1"], [ "Label 2", "Long Value 2"], [ "Label 3", "Value 3"], [ "Label 4", "Value 4"], [ "Label 5", "Value 5"] ]
32+ }
33+
34+ property var widgetDataNoTitle: {
35+ "values": [ [ "Long Label 1", "Value 1"], [ "Label 2", "Long Value 2"], [ "Label 3", "Value 3"], [ "Label 4", "Value 4"], [ "Label 5", "Value 5"] ]
36+ }
37+
38+ PreviewTable {
39+ id: previewTable
40+ anchors { left: parent.left; right: parent.right }
41+ widgetData: widgetDataComplete
42+
43+ Rectangle {
44+ color: "red"
45+ anchors.fill: parent
46+ opacity: 0.5
47+ }
48+ }
49+
50+ UT.UnityTestCase {
51+ name: "PreviewTableTest"
52+ when: windowShown
53+
54+ function init() {
55+ previewTable.widgetData = widgetDataComplete;
56+ }
57+
58+ function test_values() {
59+ compare(findChild(previewTable, "label00").text, "Long Label 1");
60+ compare(findChild(previewTable, "label01").text, "Value 1");
61+ compare(findChild(previewTable, "label10").text, "Label 2");
62+ compare(findChild(previewTable, "label11").text, "Long Value 2");
63+ compare(findChild(previewTable, "label20").text, "Label 3");
64+ compare(findChild(previewTable, "label21").text, "Value 3");
65+ compare(findChild(previewTable, "label30").text, "Label 4");
66+ compare(findChild(previewTable, "label31").text, "Value 4");
67+ compare(findChild(previewTable, "label40").text, "Label 5");
68+ compare(findChild(previewTable, "label41").text, "Value 5");
69+ }
70+
71+ function test_optional_title() {
72+ var titleLabel = findChild(previewTable, "titleLabel");
73+ compare(titleLabel.visible, true);
74+ var titleHeight = titleLabel.height;
75+ var prevHeight = previewTable.height;
76+
77+ previewTable.widgetData = widgetDataNoTitle;
78+ var column = findChild(previewTable, "column");
79+ tryCompare(previewTable, "height", prevHeight - titleHeight - column.spacing );
80+ }
81+
82+ function test_show_collapsed() {
83+ verify(findChild(previewTable, "label00").visible);
84+ verify(findChild(previewTable, "label01").visible);
85+ verify(findChild(previewTable, "label10").visible);
86+ verify(findChild(previewTable, "label11").visible);
87+ verify(findChild(previewTable, "label20").visible);
88+ verify(findChild(previewTable, "label21").visible);
89+ verify(findChild(previewTable, "label30").visible);
90+ verify(findChild(previewTable, "label31").visible);
91+ verify(findChild(previewTable, "label40").visible);
92+ verify(findChild(previewTable, "label41").visible);
93+
94+ waitForRendering(previewTable);
95+ var prevHeight = previewTable.height;
96+ previewTable.expanded = false;
97+
98+ verify(findChild(previewTable, "label00").visible);
99+ verify(findChild(previewTable, "label01").visible);
100+ verify(findChild(previewTable, "label10").visible);
101+ verify(findChild(previewTable, "label11").visible);
102+ verify(findChild(previewTable, "label20").visible);
103+ verify(findChild(previewTable, "label21").visible);
104+ verify(!findChild(previewTable, "label30").visible);
105+ verify(!findChild(previewTable, "label31").visible);
106+ verify(!findChild(previewTable, "label40").visible);
107+ verify(!findChild(previewTable, "label41").visible);
108+
109+ var labelHeight = findChild(previewTable, "label00").height;
110+ var gridLayout = findChild(previewTable, "gridLayout");
111+ tryCompare(previewTable, "height", prevHeight - labelHeight * 2 - gridLayout.rowSpacing * 2);
112+ }
113+ }
114+}
tests/qmltests/Dash/Previews/tst_PreviewWidgetFactory.qml+1
@@ -84,6 +84,7 @@ Rectangle {
84 { tag: "Progress", type: "progress", source: "PreviewProgress.qml" },
84 { tag: "Progress", type: "progress", source: "PreviewProgress.qml" },
85 { tag: "Rating Input", type: "rating-input", source: "PreviewRatingInput.qml" },
85 { tag: "Rating Input", type: "rating-input", source: "PreviewRatingInput.qml" },
86 { tag: "Rating Display", type: "reviews", source: "PreviewRatingDisplay.qml" },
86 { tag: "Rating Display", type: "reviews", source: "PreviewRatingDisplay.qml" },
87+ { tag: "Table", type: "table", source: "PreviewTable.qml" },
87 { tag: "Text", type: "text", source: "PreviewTextSummary.qml" },
88 { tag: "Text", type: "text", source: "PreviewTextSummary.qml" },
88 { tag: "Video", type: "video", source: "PreviewVideoPlayback.qml" },
89 { tag: "Video", type: "video", source: "PreviewVideoPlayback.qml" },
89 ];
90 ];
tests/qmltests/Dash/tst_Dash.qml+229−7
@@ -20,8 +20,6 @@ import "../../../qml/Dash"
20import Ubuntu.Components 0.1
20import Ubuntu.Components 0.1
21import Unity.Test 0.1 as UT
21import Unity.Test 0.1 as UT
22
22
23−// TODO We don't have any tests for the overlay scope functionality.
24−
25Item {
23Item {
26 id: shell
24 id: shell
27 width: units.gu(40)
25 width: units.gu(40)
@@ -61,9 +59,9 @@ Item {
61 function get_scope_data() {
59 function get_scope_data() {
62 return [
60 return [
63 { tag: "MockScope1", visualIndex: 0 },
61 { tag: "MockScope1", visualIndex: 0 },
64− { tag: "MockScope2", visualIndex: 1 },
62+ { tag: "MockScope2", visualIndex: -1 },
65− { tag: "clickscope", visualIndex: 2 },
63+ { tag: "clickscope", visualIndex: 1 },
66− { tag: "MockScope5", visualIndex: 3 },
64+ { tag: "MockScope5", visualIndex: 2 },
67 ]
65 ]
68 }
66 }
69
67
@@ -79,10 +77,234 @@ Item {
79 tryCompare(dashContentList, "count", 0);
77 tryCompare(dashContentList, "count", 0);
80 scopes.load();
78 scopes.load();
81 tryCompare(scopes, "loaded", true);
79 tryCompare(scopes, "loaded", true);
82− tryCompare(dashContentList, "count", 5);
80+ tryCompare(dashContentList, "count", 6);
83
81
84 verify(dashContentList != undefined);
82 verify(dashContentList != undefined);
83+ if (data.visualIndex == -1) {
84+ tryCompare(dashContentList, "currentIndex", 0);
85+ expectFail(data.tag, "non favorite scopes should not be visble in the scopes model");
86+ compare(dashContentList.currentItem.scopeId, data.tag); // this should fail
87+ } else {
85− tryCompare(dashContentList, "currentIndex", data.visualIndex);
88+ tryCompare(dashContentList, "currentIndex", data.visualIndex);
89+ compare(dashContentList.currentItem.scopeId, data.tag);
90+ }
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 categoryListView = findChild(dashContentList.currentItem, "categoryListView");
235+ var dashCategory2 = findChild(categoryListView, "dashCategory2");
236+ tryCompareFunction(function() {
237+ var d = findChild(dashCategory2, "delegate2");
238+ if (d) return true;
239+ categoryListView.contentY += 100;
240+ return false;
241+ }, true);
242+ var card2 = findChild(dashCategory2, "delegate2");
243+ waitForRendering(card2);
244+ mouseClick(card2, card2.width / 2, card2.height / 2);
245+
246+ // Wait for temp scope to be there
247+ var dashTempScopeItem = findChild(dash, "dashTempScopeItem");
248+ tryCompare(dashTempScopeItem, "x", 0);
249+
250+ // Show the overview
251+ touchFlick(dash, dash.width / 2, dash.height - 1, dash.width / 2, dash.height - units.gu(18));
252+ var overviewController = findInvisibleChild(dash, "overviewController");
253+ tryCompare(overviewController, "progress", 1);
254+
255+ // Make sure tab is where it should
256+ var scopesOverview = findChild(dash, "scopesOverview");
257+ compare(scopesOverview.currentTab, 1);
258+
259+ // Do a search
260+ var scopesOverviewPageHeader = findChild(scopesOverview, "scopesOverviewPageHeader");
261+ var searchButton = findChild(scopesOverviewPageHeader, "search_header_button");
262+ mouseClick(searchButton, 0, 0);
263+
264+ // Type something
265+ keyClick(Qt.Key_H);
266+
267+ // Check results grid is there and the other lists are not
268+ var searchResultsViewer = findChild(scopesOverview, "searchResultsViewer");
269+ var scopesOverviewRepeater = findChild(dash, "scopesOverviewRepeater");
270+ tryCompare(searchResultsViewer, "opacity", 1);
271+ tryCompare(scopesOverviewRepeater, "count", 0);
272+
273+ // Click on a temp scope in the search
274+ var dashCategorysearchA = findChild(searchResultsViewer, "dashCategorysearchA");
275+ var cardTempScope = findChild(dashCategorysearchA, "delegate2");
276+ waitForRendering(cardTempScope);
277+ mouseClick(cardTempScope, cardTempScope.width / 2, cardTempScope.height / 2);
278+
279+ // Check the bottom edge (overview) is disabled from temp scope
280+ var overviewDragHandle = findChild(dash, "overviewDragHandle");
281+ compare(overviewDragHandle.enabled, false);
282+
283+ // Check temp scope is there
284+ var scopesOverviewTempScopeItem = findChild(dash, "scopesOverviewTempScopeItem");
285+ tryCompareFunction( function() { return scopesOverviewTempScopeItem.scope != null; }, true);
286+ tryCompare(scopesOverviewTempScopeItem, "enabled", true);
287+
288+ // Go back
289+ var scopesOverviewTempScopeItemHeader = findChild(scopesOverviewTempScopeItem, "scopePageHeader");
290+ var backButton = findChild(findChild(scopesOverviewTempScopeItemHeader, "innerPageHeader"), "backButton");
291+ mouseClick(backButton, 0, 0);
292+
293+ // Check temp scope is gone
294+ var scopesOverviewTempScopeItem = findChild(dash, "scopesOverviewTempScopeItem");
295+ tryCompareFunction( function() { return scopesOverviewTempScopeItem.scope == null; }, true);
296+ tryCompare(scopesOverviewTempScopeItem, "enabled", false);
297+
298+ // Press on a favorite
299+ var dashCategorysearchB = findChild(searchResultsViewer, "dashCategorysearchB");
300+ var cardFavSearch = findChild(dashCategorysearchB, "delegate3");
301+ mouseClick(cardFavSearch, 0, 0);
302+
303+ // Check the dash overview is gone
304+ tryCompare(overviewController, "progress", 0);
305+
306+ // Original list went to the favorite
307+ compare(dashContentList.currentIndex, 0);
86 }
308 }
87
309
88 function test_setCurrentScope() {
310 function test_setCurrentScope() {
tests/qmltests/Dash/tst_DashContent.qml+19−6
@@ -70,7 +70,7 @@ Item {
70 function loadScopes() {
70 function loadScopes() {
71 scopeLoadedSpy.clear();
71 scopeLoadedSpy.clear();
72 scopesModel.load();
72 scopesModel.load();
73− tryCompare(scopeLoadedSpy, "count", 4);
73+ tryCompare(scopeLoadedSpy, "count", 6);
74 }
74 }
75
75
76 function init() {
76 function init() {
@@ -114,7 +114,8 @@ Item {
114
114
115 loadScopes();
115 loadScopes();
116
116
117+ compare(dashContentList.count, 6);
117− verify(dashContentList.currentIndex >= 0 && dashContentList.currentIndex < 5);
118+ verify(dashContentList.currentIndex >= 0 && dashContentList.currentIndex < dashContentList.count);
118 }
119 }
119
120
120 function test_show_header_on_list_movement() {
121 function test_show_header_on_list_movement() {
@@ -170,7 +171,7 @@ Item {
170
171
171 // test greater than scope count.
172 // test greater than scope count.
172 var currentScopeIndex = dashContent.currentIndex;
173 var currentScopeIndex = dashContent.currentIndex;
173− dashContent.setCurrentScopeAtIndex(8, true, false);
174+ dashContent.setCurrentScopeAtIndex(18, true, false);
174 compare(dashContent.currentIndex, currentScopeIndex, "Scope should not change if changing to greater index than count");
175 compare(dashContent.currentIndex, currentScopeIndex, "Scope should not change if changing to greater index than count");
175 }
176 }
176
177
@@ -189,9 +190,9 @@ Item {
189 function test_scope_mapping_data() {
190 function test_scope_mapping_data() {
190 return [
191 return [
191 {tag: "index0", index: 0, objectName: "MockScope1"},
192 {tag: "index0", index: 0, objectName: "MockScope1"},
192− {tag: "index1", index: 1, objectName: "MockScope2"},
193+ {tag: "index1", index: 1, objectName: "clickscope"},
193− {tag: "index2", index: 2, objectName: "clickscope"},
194+ {tag: "index2", index: 2, objectName: "MockScope5"},
194− {tag: "index3", index: 3, objectName: "MockScope5"}
195+ {tag: "index3", index: 3, objectName: "SingleCategoryScope"}
195 ]
196 ]
196 }
197 }
197
198
@@ -379,5 +380,17 @@ Item {
379 mouseClick(allButton, 0, 0);
380 mouseClick(allButton, 0, 0);
380 tryCompare(dashNavigation.currentNavigation, "navigationId", "middle2");
381 tryCompare(dashNavigation.currentNavigation, "navigationId", "middle2");
381 }
382 }
383+
384+ function test_searchHint() {
385+ var dashContentList = findChild(dashContent, "dashContentList");
386+ verify(dashContentList !== null);
387+ var scope = findChild(dashContent, "MockScope1 loader");
388+ waitForRendering(scope);
389+
390+ var categoryListView = findChild(scope, "categoryListView");
391+ waitForRendering(categoryListView);
392+
393+ compare(categoryListView.pageHeader.searchHint, "Search People");
394+ }
382 }
395 }
383}
396}
tests/qmltests/Dash/tst_GenericScopeView.qml+12−9
@@ -61,8 +61,8 @@ Item {
61 property Item header: findChild(genericScopeView, "scopePageHeader")
61 property Item header: findChild(genericScopeView, "scopePageHeader")
62
62
63 function init() {
63 function init() {
64− genericScopeView.scope = scopes.getScope(1)
64+ genericScopeView.scope = scopes.getScope(2);
65− shell.width = units.gu(120)
65+ shell.width = units.gu(120);
66 genericScopeView.categoryView.positionAtBeginning();
66 genericScopeView.categoryView.positionAtBeginning();
67 waitForRendering(genericScopeView.categoryView);
67 waitForRendering(genericScopeView.categoryView);
68 }
68 }
@@ -88,13 +88,13 @@ Item {
88
88
89 function test_showDash() {
89 function test_showDash() {
90 testCase.previewListView.open = true;
90 testCase.previewListView.open = true;
91− scopes.getScope(1).showDash();
91+ genericScopeView.scope.showDash();
92 tryCompare(testCase.previewListView, "open", false);
92 tryCompare(testCase.previewListView, "open", false);
93 }
93 }
94
94
95 function test_hideDash() {
95 function test_hideDash() {
96 testCase.previewListView.open = true;
96 testCase.previewListView.open = true;
97− scopes.getScope(1).hideDash();
97+ genericScopeView.scope.hideDash();
98 tryCompare(testCase.previewListView, "open", false);
98 tryCompare(testCase.previewListView, "open", false);
99 }
99 }
100
100
@@ -111,8 +111,9 @@ Item {
111
111
112 function test_changeScope() {
112 function test_changeScope() {
113 genericScopeView.scope.searchQuery = "test"
113 genericScopeView.scope.searchQuery = "test"
114− genericScopeView.scope = scopes.getScope(2)
114+ var originalScopeId = genericScopeView.scope.id;
115− genericScopeView.scope = scopes.getScope(1)
115+ genericScopeView.scope = scopes.getScope(originalScopeId + 1)
116+ genericScopeView.scope = scopes.getScope(originalScopeId)
116 tryCompare(genericScopeView.scope, "searchQuery", "test")
117 tryCompare(genericScopeView.scope, "searchQuery", "test")
117 }
118 }
118
119
@@ -198,6 +199,8 @@ Item {
198 openPreview(4, 0);
199 openPreview(4, 0);
199
200
200 compare(testCase.previewListView.count, 12, "There should only be 12 items in preview.");
201 compare(testCase.previewListView.count, 12, "There should only be 12 items in preview.");
202+
203+ closePreview();
201 }
204 }
202
205
203 function test_narrow_delegate_ranges_expand() {
206 function test_narrow_delegate_ranges_expand() {
@@ -233,7 +236,7 @@ Item {
233 }
236 }
234
237
235 function test_single_category_expansion() {
238 function test_single_category_expansion() {
236− genericScopeView.scope = scopes.getScope(4);
239+ genericScopeView.scope = scopes.getScope(3);
237
240
238 tryCompareFunction(function() { return findChild(genericScopeView, "dashCategory0") != undefined; }, true);
241 tryCompareFunction(function() { return findChild(genericScopeView, "dashCategory0") != undefined; }, true);
239 var category = findChild(genericScopeView, "dashCategory0")
242 var category = findChild(genericScopeView, "dashCategory0")
@@ -330,8 +333,8 @@ Item {
330 function test_header_style_data() {
333 function test_header_style_data() {
331 return [
334 return [
332 { tag: "Default", index: 0, foreground: "grey", background: "", logo: "" },
335 { tag: "Default", index: 0, foreground: "grey", background: "", logo: "" },
333− { tag: "Foreground", index: 2, foreground: "yellow", background: "", logo: "" },
336+ { tag: "Foreground", index: 1, foreground: "yellow", background: "", logo: "" },
334− { tag: "Logo+Background", index: 3, foreground: "grey", background: "gradient:///lightgrey/grey",
337+ { tag: "Logo+Background", index: 2, foreground: "grey", background: "gradient:///lightgrey/grey",
335 logo: Qt.resolvedUrl("../Components/tst_PageHeader/logo-ubuntu-orange.svg") },
338 logo: Qt.resolvedUrl("../Components/tst_PageHeader/logo-ubuntu-orange.svg") },
336 ];
339 ];
337 }
340 }