on xenial help sign in
Add scope favoriting support
674ddacMichał Sawicz
po/unity8.pot+72−23
@@ -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-08-21 11:36+0200\n"
11+"POT-Creation-Date: 2014-08-26 14:04+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"
@@ -17,7 +17,7 @@ msgstr ""
17"Content-Type: text/plain; charset=UTF-8\n"
17"Content-Type: text/plain; charset=UTF-8\n"
18"Content-Transfer-Encoding: 8bit\n"
18"Content-Transfer-Encoding: 8bit\n"
19
19
20−#: plugins/LightDM/Greeter.cpp:129
20+#: plugins/LightDM/Greeter.cpp:130
21msgid "Password: "
21msgid "Password: "
22msgstr ""
22msgstr ""
23
23
@@ -30,19 +30,55 @@ msgstr ""
30msgid "Unpin shortcut"
30msgid "Unpin shortcut"
31msgstr ""
31msgstr ""
32
32
33−#: qml/Components/Dialogs.qml:142
33+#: qml/Components/Dialogs.qml:70
34−msgid "Are you sure you would like to turn power off?"
34+msgid "Log out"
35+msgstr ""
36+
37+#: qml/Components/Dialogs.qml:71
38+msgid "Are you sure you want to log out?"
39+msgstr ""
40+
41+#: qml/Components/Dialogs.qml:73 qml/Components/Dialogs.qml:97
42+#: qml/Components/Dialogs.qml:122
43+msgid "No"
44+msgstr ""
45+
46+#: qml/Components/Dialogs.qml:80 qml/Components/Dialogs.qml:104
47+#: qml/Components/Dialogs.qml:129
48+msgid "Yes"
49+msgstr ""
50+
51+#: qml/Components/Dialogs.qml:94
52+msgid "Shut down"
53+msgstr ""
54+
55+#: qml/Components/Dialogs.qml:95
56+msgid "Are you sure you want to shut down?"
57+msgstr ""
58+
59+#: qml/Components/Dialogs.qml:119
60+msgid "Reboot"
61+msgstr ""
62+
63+#: qml/Components/Dialogs.qml:120
64+msgid "Are you sure you want to reboot?"
35msgstr ""
65msgstr ""
36
66
37#: qml/Components/Dialogs.qml:144
67#: qml/Components/Dialogs.qml:144
38−msgid "Power off"
68+msgid "Power"
69+msgstr ""
70+
71+#: qml/Components/Dialogs.qml:145
72+msgid ""
73+"Are you sure you would like\n"
74+"to power off?"
39msgstr ""
75msgstr ""
40
76
41−#: qml/Components/Dialogs.qml:153
77+#: qml/Components/Dialogs.qml:147
42−msgid "Restart"
78+msgid "Power off"
43msgstr ""
79msgstr ""
44
80
45−#: qml/Components/Dialogs.qml:162
81+#: qml/Components/Dialogs.qml:157
46msgid "Cancel"
82msgid "Cancel"
47msgstr ""
83msgstr ""
48
84
@@ -125,10 +161,23 @@ msgstr ""
125msgid "See all"
161msgid "See all"
126msgstr ""
162msgstr ""
127
163
128−#: qml/Dash/GenericScopeView.qml:424 qml/Panel/SearchIndicator.qml:27
164+#: qml/Dash/GenericScopeView.qml:424 qml/Dash/PageHeader.qml:260
165+#: qml/Panel/SearchIndicator.qml:27
129msgid "Search"
166msgid "Search"
130msgstr ""
167msgstr ""
131
168
169+#: qml/Dash/PageHeader.qml:270
170+msgid "Settings"
171+msgstr ""
172+
173+#: qml/Dash/PageHeader.qml:279
174+msgid "Remove from Favorites"
175+msgstr ""
176+
177+#: qml/Dash/PageHeader.qml:279
178+msgid "Add to Favorites"
179+msgstr ""
180+
132#: qml/Dash/Previews/PreviewActionCombo.qml:34
181#: qml/Dash/Previews/PreviewActionCombo.qml:34
133msgid "More..."
182msgid "More..."
134msgstr ""
183msgstr ""
@@ -153,11 +202,11 @@ msgstr ""
153msgid "Manage Dash"
202msgid "Manage Dash"
154msgstr ""
203msgstr ""
155
204
156−#: qml/Dash/ScopesOverview.qml:408
205+#: qml/Dash/ScopesOverview.qml:417
157msgid "Done"
206msgid "Done"
158msgstr ""
207msgstr ""
159
208
160−#: qml/Dash/ScopesOverview.qml:434
209+#: qml/Dash/ScopesOverview.qml:443
161msgid "Store"
210msgid "Store"
162msgstr ""
211msgstr ""
163
212
@@ -173,7 +222,7 @@ msgstr ""
173msgid "Swipe to unlock"
222msgid "Swipe to unlock"
174msgstr ""
223msgstr ""
175
224
176−#: qml/Hud/HudParametrizedActionsPage.qml:132
225+#: qml/Hud/HudParametrizedActionsPage.qml:139
177msgid "Confirm"
226msgid "Confirm"
178msgstr ""
227msgstr ""
179
228
@@ -201,7 +250,7 @@ msgstr ""
201msgid "Enter SIM PIN"
250msgid "Enter SIM PIN"
202msgstr ""
251msgstr ""
203
252
204−#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:270
253+#: qml/Notifications/NotificationMenuItemFactory.qml:121 qml/Shell.qml:283
205msgid "Sorry, incorrect PIN"
254msgid "Sorry, incorrect PIN"
206msgstr ""
255msgstr ""
207
256
@@ -245,47 +294,47 @@ msgstr ""
245msgid "Roaming"
294msgid "Roaming"
246msgstr ""
295msgstr ""
247
296
248−#: qml/Shell.qml:266
297+#: qml/Shell.qml:279
249msgid "Enter your passphrase"
298msgid "Enter your passphrase"
250msgstr ""
299msgstr ""
251
300
252−#: qml/Shell.qml:267
301+#: qml/Shell.qml:280
253msgid "Sorry, incorrect passphrase"
302msgid "Sorry, incorrect passphrase"
254msgstr ""
303msgstr ""
255
304
256−#: qml/Shell.qml:269
305+#: qml/Shell.qml:282
257msgid "Enter your PIN"
306msgid "Enter your PIN"
258msgstr ""
307msgstr ""
259
308
260−#: qml/Shell.qml:273
309+#: qml/Shell.qml:286
261#, qt-format
310#, qt-format
262msgid "Enter your %1"
311msgid "Enter your %1"
263msgstr ""
312msgstr ""
264
313
265−#: qml/Shell.qml:274
314+#: qml/Shell.qml:287
266#, qt-format
315#, qt-format
267msgid "Sorry, incorrect %1"
316msgid "Sorry, incorrect %1"
268msgstr ""
317msgstr ""
269
318
270−#: qml/Shell.qml:310
319+#: qml/Shell.qml:323
271msgid "Sorry, incorrect passphrase."
320msgid "Sorry, incorrect passphrase."
272msgstr ""
321msgstr ""
273
322
274−#: qml/Shell.qml:311
323+#: qml/Shell.qml:324
275msgid "Sorry, incorrect passcode."
324msgid "Sorry, incorrect passcode."
276msgstr ""
325msgstr ""
277
326
278−#: qml/Shell.qml:312
327+#: qml/Shell.qml:325
279msgid "This will be your last attempt."
328msgid "This will be your last attempt."
280msgstr ""
329msgstr ""
281
330
282−#: qml/Shell.qml:314
331+#: qml/Shell.qml:327
283msgid ""
332msgid ""
284"If passphrase is entered incorrectly, your phone will conduct a factory "
333"If passphrase is entered incorrectly, your phone will conduct a factory "
285"reset and all personal data will be deleted."
334"reset and all personal data will be deleted."
286msgstr ""
335msgstr ""
287
336
288−#: qml/Shell.qml:315
337+#: qml/Shell.qml:328
289msgid ""
338msgid ""
290"If passcode is entered incorrectly, your phone will conduct a factory reset "
339"If passcode is entered incorrectly, your phone will conduct a factory reset "
291"and all personal data will be deleted."
340"and all personal data will be deleted."
qml/Dash/DashContent.qml+20
@@ -110,6 +110,26 @@ Item {
110 onMovementStarted: currentItem.item.showHeader();
110 onMovementStarted: currentItem.item.showHeader();
111 clip: parent.x != 0
111 clip: parent.x != 0
112
112
113+ // TODO QTBUG-40846 and QTBUG-40848
114+ // The remove transition doesn't happen when removing the last item
115+ // And can't work around it because index is reset to -1 regardless of
116+ // ListView.delayRemove
117+
118+ remove: Transition {
119+ SequentialAnimation {
120+ PropertyAction { property: "layer.enabled"; value: true }
121+ PropertyAction { property: "ListView.delayRemove"; value: true }
122+ ParallelAnimation {
123+ PropertyAnimation { properties: "scale"; to: 0.25; duration: UbuntuAnimation.SnapDuration }
124+ PropertyAnimation { properties: "y"; to: dashContent.height; duration: UbuntuAnimation.SnapDuration }
125+ }
126+ PropertyAction { property: "ListView.delayRemove"; value: false }
127+ }
128+ }
129+ removeDisplaced: Transition {
130+ PropertyAnimation { property: "x"; duration: UbuntuAnimation.SnapDecision }
131+ }
132+
113 // If the number of items is less than the current index, then need to reset to another item.
133 // If the number of items is less than the current index, then need to reset to another item.
114 onCountChanged: {
134 onCountChanged: {
115 if (count > 0) {
135 if (count > 0) {
qml/Dash/GenericScopeView.qml+3
@@ -429,6 +429,8 @@ FocusScope {
429 showBackButton: scopeView.hasBackAction
429 showBackButton: scopeView.hasBackAction
430 searchEntryEnabled: true
430 searchEntryEnabled: true
431 settingsEnabled: scopeView.scope && scopeView.scope.settings && scopeView.scope.settings.count > 0 || false
431 settingsEnabled: scopeView.scope && scopeView.scope.settings && scopeView.scope.settings.count > 0 || false
432+ favoriteEnabled: scopeView.scope && scopeView.scope.id !== "clickscope"
433+ favorite: scopeView.scope && scopeView.scope.favorite
432 scopeStyle: scopeView.scopeStyle
434 scopeStyle: scopeView.scopeStyle
433 paginationCount: scopeView.paginationCount
435 paginationCount: scopeView.paginationCount
434 paginationIndex: scopeView.paginationIndex
436 paginationIndex: scopeView.paginationIndex
@@ -443,6 +445,7 @@ FocusScope {
443
445
444 onBackClicked: scopeView.backClicked()
446 onBackClicked: scopeView.backClicked()
445 onSettingsClicked: subPageLoader.openSubPage("settings")
447 onSettingsClicked: subPageLoader.openSubPage("settings")
448+ onFavoriteClicked: scopeView.scope.favorite = !scopeView.scope.favorite
446 }
449 }
447 }
450 }
448 }
451 }
qml/Dash/PageHeader.qml+12
@@ -32,6 +32,8 @@ Item {
32
32
33 property bool searchEntryEnabled: false
33 property bool searchEntryEnabled: false
34 property bool settingsEnabled: false
34 property bool settingsEnabled: false
35+ property bool favoriteEnabled: false
36+ property bool favorite: false
35 property ListModel searchHistory: SearchHistoryModel
37 property ListModel searchHistory: SearchHistoryModel
36 property alias searchQuery: searchTextField.text
38 property alias searchQuery: searchTextField.text
37 property alias searchHint: searchTextField.placeholderText
39 property alias searchHint: searchTextField.placeholderText
@@ -45,6 +47,7 @@ Item {
45
47
46 signal backClicked()
48 signal backClicked()
47 signal settingsClicked()
49 signal settingsClicked()
50+ signal favoriteClicked()
48
51
49 onScopeStyleChanged: refreshLogo()
52 onScopeStyleChanged: refreshLogo()
50 onSearchQueryChanged: {
53 onSearchQueryChanged: {
@@ -253,6 +256,7 @@ Item {
253 actions: [
256 actions: [
254 Action {
257 Action {
255 objectName: "search"
258 objectName: "search"
259+ text: i18n.tr("Search")
256 iconName: "search"
260 iconName: "search"
257 visible: root.searchEntryEnabled
261 visible: root.searchEntryEnabled
258 onTriggered: {
262 onTriggered: {
@@ -262,9 +266,17 @@ Item {
262 },
266 },
263 Action {
267 Action {
264 objectName: "settings"
268 objectName: "settings"
269+ text: i18n.tr("Settings")
265 iconName: "settings"
270 iconName: "settings"
266 visible: root.settingsEnabled
271 visible: root.settingsEnabled
267 onTriggered: root.settingsClicked()
272 onTriggered: root.settingsClicked()
273+ },
274+ Action {
275+ objectName: "favorite"
276+ text: root.favorite ? i18n.tr("Remove from Favorites") : i18n.tr("Add to Favorites")
277+ iconName: root.favorite ? "starred" : "non-starred"
278+ visible: root.favoriteEnabled
279+ onTriggered: root.favoriteClicked()
268 }
280 }
269 ]
281 ]
270 }
282 }
tests/mocks/Unity/fake_scopes.h+1−1
@@ -56,7 +56,7 @@ public:
56 // This is used as part of implementation of the other C++ code, not API
56 // This is used as part of implementation of the other C++ code, not API
57 QList<Scope*> scopes() const;
57 QList<Scope*> scopes() const;
58 QList<Scope*> allScopes() const;
58 QList<Scope*> allScopes() const;
59− Scope* getScopeFromAll(const QString& scope_id) const;
59+ Q_INVOKABLE Scope* getScopeFromAll(const QString& scope_id) const;
60
60
61private Q_SLOTS:
61private Q_SLOTS:
62 void updateScopes();
62 void updateScopes();
tests/qmltests/Dash/tst_GenericScopeView.qml+28
@@ -425,6 +425,34 @@ Item {
425 verify(image, "Could not find the title image.");
425 verify(image, "Could not find the title image.");
426 compare(image.source, data.logo, "Title image has the wrong source");
426 compare(image.source, data.logo, "Title image has the wrong source");
427 }
427 }
428+
429+ function test_favorite_data() {
430+ return [
431+ { tag: "People", id: "MockScope1", favorite: true },
432+ { tag: "Music", id: "MockScope2", favorite: false },
433+ { tag: "Apps", id: "clickscope", favorite: true },
434+ ];
435+ }
436+
437+ function test_favorite(data) {
438+ genericScopeView.scope = scopes.getScopeFromAll(data.id);
439+ waitForRendering(genericScopeView);
440+ verify(header, "Could not find the header.");
441+
442+ compare(genericScopeView.scope.favorite, data.favorite, "Unexpected initial favorite value");
443+
444+ var innerHeader = findChild(header, "innerPageHeader");
445+ verify(innerHeader, "Could not find the inner header");
446+
447+ expectFail("Apps", "Click scope should not have a favorite button");
448+ var favoriteAction = findChild(innerHeader, "favorite_header_button");
449+ verify(favoriteAction, "Could not find the favorite action.");
450+ mouseClick(favoriteAction, favoriteAction.width / 2, favoriteAction.height / 2);
451+
452+ tryCompare(genericScopeView.scope, "favorite", !data.favorite);
453+
454+ genericScopeView.scope = !genericScopeView.scope;
455+ }
428 }
456 }
429 }
457 }
430}
458}