on xenial help sign in
Merge from wallpaper branch
1000459Michael Terry
Components/EdgeDemo.qml+2−1
@@ -218,8 +218,9 @@ Item {
218 d.finalEdgeDemo = d.overlay.createObject(demo.underlay, {
218 d.finalEdgeDemo = d.overlay.createObject(demo.underlay, {
219 "edge": "none",
219 "edge": "none",
220 "title": i18n.tr("Well done"),
220 "title": i18n.tr("Well done"),
221− "text": i18n.tr("You have now mastered the edge gestures and can start using the phone"),
221+ "text": i18n.tr("You have now mastered the edge gestures and can start using the phone<br><br>Tap anywhere to start"),
222 "anchors.fill": demo.dash,
222 "anchors.fill": demo.dash,
223+ "showSkip": false,
223 });
224 });
224 }
225 }
225 if (d.finalEdgeDemo) {
226 if (d.finalEdgeDemo) {
Components/EdgeDemoOverlay.qml+5
@@ -43,6 +43,11 @@ Showable {
43 */
43 */
44 property alias skipText: skipLabel.text
44 property alias skipText: skipLabel.text
45
45
46+ /*
47+ * This is the visible status of the skip button.
48+ */
49+ property alias showSkip: skipLabel.visible
50+
46 /*
51 /*
47 * Whether this demo is running currently.
52 * Whether this demo is running currently.
48 */
53 */
Dash/DashBar.qml+2−3
@@ -83,9 +83,8 @@ Item {
83 }
83 }
84
84
85 delegate:
85 delegate:
86− Item {
86+ // FIXME: Use Panel's integrated trigger() once that works again.
87− signal clicked()
87+ MouseArea {
88−
89 width: itemSize
88 width: itemSize
90 height: dashBar.height
89 height: dashBar.height
91 anchors.top: parent.top
90 anchors.top: parent.top
Greeter/Infographics.qml+1−2
@@ -293,9 +293,8 @@ Item {
293 objectName: "backgroundCircle"
293 objectName: "backgroundCircle"
294
294
295 anchors.fill: parent
295 anchors.fill: parent
296− opacity: 0.9
297
296
298− source: "graphics/infographic_circle.png"
297+ source: "graphics/infographic_circle_back.png"
299 }
298 }
300
299
301 Timer {
300 Timer {
Greeter/graphics/infographic_circle.pngdeleted

Binary file not shown.

Greeter/graphics/infographic_circle_back.pngnew file

Binary file not shown.

Launcher/LauncherDelegate.qml+20−9
@@ -24,6 +24,7 @@ Item {
24 property int count: -1
24 property int count: -1
25 property int progress: -1
25 property int progress: -1
26 property bool highlighted: false
26 property bool highlighted: false
27+ property bool itemFocused: false
27 property real maxAngle: 0
28 property real maxAngle: 0
28 property bool inverted: false
29 property bool inverted: false
29
30
@@ -43,17 +44,18 @@ Item {
43 onCountChanged: shaderEffectSource.scheduleUpdate();
44 onCountChanged: shaderEffectSource.scheduleUpdate();
44 onProgressChanged: shaderEffectSource.scheduleUpdate();
45 onProgressChanged: shaderEffectSource.scheduleUpdate();
45 onHighlightedChanged: shaderEffectSource.scheduleUpdate();
46 onHighlightedChanged: shaderEffectSource.scheduleUpdate();
47+ onItemFocusedChanged: shaderEffectSource.scheduleUpdate();
46
48
47 Item {
49 Item {
48 id: iconItem
50 id: iconItem
49− width: parent.itemWidth
51+ width: parent.itemWidth + units.gu(1)
50− height: parent.itemHeight
52+ height: parent.itemHeight + units.gu(1)
51 anchors.centerIn: parent
53 anchors.centerIn: parent
52
54
53 UbuntuShape {
55 UbuntuShape {
54 id: iconShape
56 id: iconShape
55 anchors.fill: parent
57 anchors.fill: parent
56− anchors.margins: units.gu(0.5)
58+ anchors.margins: units.gu(1)
57 radius: "medium"
59 radius: "medium"
58
60
59 image: Image {
61 image: Image {
@@ -78,7 +80,7 @@ Item {
78 anchors {
80 anchors {
79 right: parent.right
81 right: parent.right
80 top: parent.top
82 top: parent.top
81− margins: -units.dp(1)
83+ margins: units.dp(3)
82 }
84 }
83 width: Math.min(root.itemWidth, Math.max(units.gu(3), countLabel.implicitWidth + units.gu(2.5)))
85 width: Math.min(root.itemWidth, Math.max(units.gu(3), countLabel.implicitWidth + units.gu(2.5)))
84 height: units.gu(3)
86 height: units.gu(3)
@@ -105,9 +107,9 @@ Item {
105 left: iconItem.left
107 left: iconItem.left
106 right: iconItem.right
108 right: iconItem.right
107 bottom: iconItem.bottom
109 bottom: iconItem.bottom
108− leftMargin: units.gu(0.5)
110+ leftMargin: units.gu(1)
109− rightMargin: units.gu(0.5)
111+ rightMargin: units.gu(1)
110− bottomMargin: units.gu(0.5)
112+ bottomMargin: units.gu(1)
111 }
113 }
112 height: units.gu(1.5)
114 height: units.gu(1.5)
113 visible: root.progress > -1
115 visible: root.progress > -1
@@ -136,14 +138,23 @@ Item {
136 }
138 }
137 }
139 }
138 }
140 }
141+ Image {
142+ objectName: "focusedHighlight"
143+ anchors {
144+ right: parent.right
145+ verticalCenter: parent.verticalCenter
146+ }
147+ visible: root.itemFocused
148+ source: "graphics/focused_app_arrow.png"
149+ }
139 }
150 }
140
151
141 ShaderEffect {
152 ShaderEffect {
142 id: transformEffect
153 id: transformEffect
143 anchors.centerIn: parent
154 anchors.centerIn: parent
144 anchors.verticalCenterOffset: root.offset
155 anchors.verticalCenterOffset: root.offset
145− width: parent.itemWidth
156+ width: iconItem.width
146− height: parent.itemHeight
157+ height: iconItem.height
147 property real itemOpacity: root.itemOpacity
158 property real itemOpacity: root.itemOpacity
148 property real brightness: Math.max(-1, root.brightness)
159 property real brightness: Math.max(-1, root.brightness)
149 property real angle: root.angle
160 property real angle: root.angle
Launcher/LauncherPanel.qml+9−2
@@ -50,8 +50,6 @@ Item {
50 id: mainColumn
50 id: mainColumn
51 anchors {
51 anchors {
52 fill: parent
52 fill: parent
53− leftMargin: units.gu(0.5)
54− rightMargin: units.gu(0.5)
55 }
53 }
56
54
57 MouseArea {
55 MouseArea {
@@ -94,6 +92,8 @@ Item {
94 fill: parent
92 fill: parent
95 topMargin: -extensionSize + units.gu(0.5)
93 topMargin: -extensionSize + units.gu(0.5)
96 bottomMargin: -extensionSize + units.gu(1)
94 bottomMargin: -extensionSize + units.gu(1)
95+ leftMargin: units.gu(0.5)
96+ rightMargin: units.gu(0.5)
97 }
97 }
98 topMargin: extensionSize
98 topMargin: extensionSize
99 bottomMargin: extensionSize
99 bottomMargin: extensionSize
@@ -156,6 +156,7 @@ Item {
156 iconName: model.icon
156 iconName: model.icon
157 count: model.count
157 count: model.count
158 progress: model.progress
158 progress: model.progress
159+ itemFocused: model.focused
159 inverted: root.inverted
160 inverted: root.inverted
160 z: -Math.abs(offset)
161 z: -Math.abs(offset)
161 maxAngle: 55
162 maxAngle: 55
@@ -512,6 +513,12 @@ Item {
512 objectName: "quickListEntry" + index
513 objectName: "quickListEntry" + index
513 text: (model.clickable ? "" : "<b>") + model.label + (model.clickable ? "" : "</b>")
514 text: (model.clickable ? "" : "<b>") + model.label + (model.clickable ? "" : "</b>")
514 highlightWhenPressed: model.clickable
515 highlightWhenPressed: model.clickable
516+
517+ // FIXME: This is a workaround for the theme not being context sensitive. I.e. the
518+ // ListItems don't know that they are sitting in a themed Popover where the color
519+ // needs to be inverted.
520+ __foregroundColor: Theme.palette.selected.backgroundText
521+
515 onClicked: {
522 onClicked: {
516 if (!model.clickable) {
523 if (!model.clickable) {
517 return;
524 return;
Launcher/graphics/focused_app_arrow@30.pngnew file

Binary file not shown.

Panel/Indicators/DefaultIndicatorWidget.qml+1−1
@@ -24,7 +24,7 @@ import Unity.IndicatorsLegacy 0.1 as Indicators
24Indicators.IndicatorWidget {
24Indicators.IndicatorWidget {
25 id: indicatorWidget
25 id: indicatorWidget
26
26
27− width: itemRow.width + units.gu(1)
27+ width: itemRow.width + units.gu(0.5)
28
28
29 property alias label: itemLabel.text
29 property alias label: itemLabel.text
30 property alias iconSource: itemImage.source
30 property alias iconSource: itemImage.source
Panel/Indicators/DefaultIndicatorWidget2.qml+43−16
@@ -24,10 +24,11 @@ import Unity.Indicators 0.1 as Indicators
24Indicators.IndicatorWidget {
24Indicators.IndicatorWidget {
25 id: indicatorWidget
25 id: indicatorWidget
26
26
27− width: itemRow.width + units.gu(1)
27+ width: itemRow.width + units.gu(0.5)
28
28
29− property alias label: itemLabel.text
29+ property alias leftLabel: itemLeftLabel.text
30− property alias iconSource: itemImage.source
30+ property alias rightLabel: itemRightLabel.text
31+ property var icons: undefined
31
32
32 Row {
33 Row {
33 id: itemRow
34 id: itemRow
@@ -39,19 +40,43 @@ Indicators.IndicatorWidget {
39 }
40 }
40 spacing: units.gu(0.5)
41 spacing: units.gu(0.5)
41
42
42− // FIXME : Should us Ubuntu.Icon . results in low res images
43+ Label {
43− Image {
44+ id: itemLeftLabel
44− id: itemImage
45− objectName: "itemImage"
45+ objectName: "leftLabel"
46− visible: source != ""
46+ color: Theme.palette.selected.backgroundText
47− height: indicatorWidget.iconSize
47+ opacity: 0.8
48− width: indicatorWidget.iconSize
48+ font.family: "Ubuntu"
49+ fontSize: "medium"
49 anchors.verticalCenter: parent.verticalCenter
50 anchors.verticalCenter: parent.verticalCenter
51+ visible: text != ""
52+ }
53+
54+ Row {
55+ width: childrenRect.width
56+ anchors {
57+ top: parent.top
58+ bottom: parent.bottom
59+ }
60+ spacing: units.gu(0.5)
61+
62+ Repeater {
63+ model: indicatorWidget.icons
64+
65+ Image {
66+ id: itemImage
67+ objectName: "itemImage"
68+ visible: source != ""
69+ source: modelData
70+ height: indicatorWidget.iconSize
71+ width: indicatorWidget.iconSize
72+ anchors.verticalCenter: parent.verticalCenter
73+ }
74+ }
50 }
75 }
51
76
52 Label {
77 Label {
53− id: itemLabel
78+ id: itemRightLabel
54− objectName: "itemLabel"
79+ objectName: "rightLabel"
55 color: Theme.palette.selected.backgroundText
80 color: Theme.palette.selected.backgroundText
56 opacity: 0.8
81 opacity: 0.8
57 font.family: "Ubuntu"
82 font.family: "Ubuntu"
@@ -63,14 +88,16 @@ Indicators.IndicatorWidget {
63
88
64 onActionStateChanged: {
89 onActionStateChanged: {
65 if (actionState == undefined) {
90 if (actionState == undefined) {
66− label = "";
91+ leftLabel = "";
67− iconSource = "";
92+ rightLabel = "";
93+ icons = undefined;
68 enabled = false;
94 enabled = false;
69 return;
95 return;
70 }
96 }
71
97
72− label = actionState.label;
98+ leftLabel = actionState.leftLabel ? actionState.leftLabel : "";
99+ rightLabel = actionState.rightLabel ? actionState.rightLabel : "";
73− iconSource = actionState.icon;
100+ icons = actionState.icons;
74 enabled = actionState.visible;
101 enabled = actionState.visible;
75 }
102 }
76}
103}
Panel/Indicators/NetworkIndicatorWidget.qml+1−1
@@ -24,7 +24,7 @@ import Unity.IndicatorsLegacy 0.1 as Indicators
24Indicators.IndicatorWidget {
24Indicators.IndicatorWidget {
25 id: indicatorWidget
25 id: indicatorWidget
26
26
27− width: networkIcon.width + units.gu(1)
27+ width: networkIcon.width + units.gu(0.5)
28
28
29 property int signalStrength: 0
29 property int signalStrength: 0
30 property int connectionState: Indicators.NetworkConnection.Initial
30 property int connectionState: Indicators.NetworkConnection.Initial
Shell.qml+10−1
@@ -96,6 +96,15 @@ FocusScope {
96 greeter.hide();
96 greeter.hide();
97 shell.activateApplication(desktopFile);
97 shell.activateApplication(desktopFile);
98 }
98 }
99+
100+ onMainStageFocusedApplicationChanged: {
101+ var app = applicationManager.mainStageFocusedApplication
102+ if (app != null) {
103+ LauncherModel.applicationFocused(app.desktopFile);
104+ } else {
105+ LauncherModel.applicationFocused("");
106+ }
107+ }
99 }
108 }
100
109
101 function activateApplication(desktopFile, argument) {
110 function activateApplication(desktopFile, argument) {
@@ -470,7 +479,7 @@ FocusScope {
470 onSelected: {
479 onSelected: {
471 // Update launcher items for new user
480 // Update launcher items for new user
472 var user = LightDM.Users.data(uid, LightDM.UserRoles.NameRole);
481 var user = LightDM.Users.data(uid, LightDM.UserRoles.NameRole);
473− AccountsService.setUser(user);
482+ AccountsService.user = user;
474 LauncherModel.setUser(user);
483 LauncherModel.setUser(user);
475 }
484 }
476
485
build+9
@@ -57,6 +57,15 @@ mk_build_deps() {
57 [ ! -f unity8-build-deps*deb -o $CODE_DIR/debian/control -nt unity8-build-deps*deb ] && mk-build-deps --install --root-cmd sudo $CODE_DIR/debian/control
57 [ ! -f unity8-build-deps*deb -o $CODE_DIR/debian/control -nt unity8-build-deps*deb ] && mk-build-deps --install --root-cmd sudo $CODE_DIR/debian/control
58}
58}
59
59
60+if [ -f "/usr/bin/ccache" ] ; then
61+ if [ "x$CC" = "x" ]; then
62+ export CC='ccache gcc'
63+ fi
64+ if [ "x$CXX" = "x" ] ; then
65+ export CXX='ccache g++'
66+ fi
67+fi
68+
60if [ -f "/usr/bin/ninja" ] ; then
69if [ -f "/usr/bin/ninja" ] ; then
61 GENERATOR="-G Ninja"
70 GENERATOR="-G Ninja"
62 # Ninja does not need -j, it parallelizes automatically.
71 # Ninja does not need -j, it parallelizes automatically.
debian/changelog+71
@@ -1,3 +1,74 @@
1+unity8 (7.81.3+13.10.20130905.2-0ubuntu1) saucy; urgency=low
2+
3+ [ Michael Zanetti ]
4+ * Integrate Launcher with AppManager.
5+
6+ [ Nick Dedekind ]
7+ * Removed FIXME from slider int->double conversion.
8+
9+ [ Ubuntu daily release ]
10+ * Automatic snapshot from revision 291
11+
12+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 05 Sep 2013 10:48:02 +0000
13+
14+unity8 (7.81.3+13.10.20130904.1-0ubuntu1) saucy; urgency=low
15+
16+ [ Nicolas d'Offay ]
17+ * Switched infographic background at design's request.
18+
19+ [ Ubuntu daily release ]
20+ * Automatic snapshot from revision 287
21+
22+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 04 Sep 2013 07:34:57 +0000
23+
24+unity8 (7.81.3+13.10.20130904-0ubuntu1) saucy; urgency=low
25+
26+ [ mhall119 ]
27+ * Add a little bit of text to the last step of the tour telling the
28+ user how to end it and get to their phone.
29+
30+ [ Jussi Pakkanen ]
31+ * Use CCache if it is installed.
32+
33+ [ Nick Dedekind ]
34+ * Multiple icon/label support for indicators.
35+
36+ [ Albert Astals ]
37+ * Remove unneeded role.
38+
39+ [ Lars Uebernickel ]
40+ * Fall back to "ubuntu-mobile" icon theme if $UBUNTU_ICON_THEME is
41+ unset.
42+
43+ [ Michael Zanetti ]
44+ * Use MouseAreas in DashBar to enable clicking again.
45+ * load launcher default config from existing dconf key.
46+
47+ [ Ubuntu daily release ]
48+ * Automatic snapshot from revision 285
49+
50+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 04 Sep 2013 03:02:57 +0000
51+
52+unity8 (7.81.3+13.10.20130903.1-0ubuntu1) saucy; urgency=low
53+
54+ [ Michael Zanetti ]
55+ * workaround quicklist text color.
56+
57+ [ Ubuntu daily release ]
58+ * Automatic snapshot from revision 277
59+
60+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 03 Sep 2013 06:09:36 +0000
61+
62+unity8 (7.81.3+13.10.20130830-0ubuntu1) saucy; urgency=low
63+
64+ [ Pawel Stolowski ]
65+ * Implement a virtual 'All' filter option.
66+
67+ [ Ubuntu daily release ]
68+ * Automatic snapshot from revision 275
69+
70+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Fri, 30 Aug 2013 12:44:40 +0000
71+
1unity8 (7.81.3+13.10.20130829.2-0ubuntu1) saucy; urgency=low
72unity8 (7.81.3+13.10.20130829.2-0ubuntu1) saucy; urgency=low
2
73
3 [ Michael Terry ]
74 [ Michael Terry ]
debian/control+1
@@ -9,6 +9,7 @@ Build-Depends: cmake,
9 libgl1-mesa-dev[!armhf] | libgl-dev[!armhf],
9 libgl1-mesa-dev[!armhf] | libgl-dev[!armhf],
10 libgl1-mesa-dri,
10 libgl1-mesa-dri,
11 libgles2-mesa-dev[armhf],
11 libgles2-mesa-dev[armhf],
12+ libgsettings-qt-dev,
12 libhud-client2-dev,
13 libhud-client2-dev,
13 libjson-perl,
14 libjson-perl,
14 libnih-dbus-dev,
15 libnih-dbus-dev,
main.cpp+3−2
@@ -65,9 +65,10 @@ void appendImportPaths(QQmlEngine *engine, const QStringList &paths)
65
65
66void resolveIconTheme() {
66void resolveIconTheme() {
67 const char *ubuntuIconTheme = getenv("UBUNTU_ICON_THEME");
67 const char *ubuntuIconTheme = getenv("UBUNTU_ICON_THEME");
68− if (ubuntuIconTheme != NULL) {
68+ if (ubuntuIconTheme == NULL) {
69− QIcon::setThemeName(ubuntuIconTheme);
69+ ubuntuIconTheme = "ubuntu-mobile";
70 }
70 }
71+ QIcon::setThemeName(ubuntuIconTheme);
71}
72}
72} // namespace {
73} // namespace {
73
74
plugins/AccountsService/AccountsBindings.cppdeleted−116
@@ -1,116 +0,0 @@
1−/*
2− * Copyright (C) 2013 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− * Author: Michael Terry <michael.terry@canonical.com>
17− */
18−
19−#include "AccountsBindings.h"
20−#include "AccountsService.h"
21−
22−#include <QStringList>
23−
24−AccountsBindings::AccountsBindings(QObject* parent)
25− : QObject(parent),
26− m_service(new AccountsService(this)),
27− m_user(qgetenv("USER"))
28−{
29− connect(m_service, SIGNAL(propertiesChanged(const QString &, const QString &, const QStringList &)),
30− this, SLOT(propertiesChanged(const QString &, const QString &, const QStringList &)));
31− connect(m_service, SIGNAL(maybeChanged(const QString &)),
32− this, SLOT(maybeChanged(const QString &)));
33−}
34−
35−void AccountsBindings::setUser(const QString &user)
36−{
37− m_user = user;
38− updateDemoEdges();
39− updateBackgroundFile();
40− updateStatsWelcomeScreen();
41−}
42−
43−bool AccountsBindings::getDemoEdges()
44−{
45− return m_demoEdges;
46−}
47−
48−void AccountsBindings::setDemoEdges(bool demoEdges)
49−{
50− m_demoEdges = demoEdges;
51− m_service->setUserProperty(m_user, "com.canonical.unity.AccountsService", "demo-edges", demoEdges);
52−}
53−
54−QString AccountsBindings::getBackgroundFile()
55−{
56− return m_backgroundFile;
57−}
58−
59−bool AccountsBindings::getStatsWelcomeScreen()
60−{
61− return m_statsWelcomeScreen;
62−}
63−
64−void AccountsBindings::updateDemoEdges()
65−{
66− auto demoEdges = m_service->getUserProperty(m_user, "com.canonical.unity.AccountsService", "demo-edges").toBool();
67− if (m_demoEdges != demoEdges) {
68− m_demoEdges = demoEdges;
69− Q_EMIT demoEdgesChanged();
70− }
71−}
72−
73−void AccountsBindings::updateBackgroundFile()
74−{
75− auto backgroundFile = m_service->getUserProperty(m_user, "org.freedesktop.Accounts.User", "BackgroundFile").toString();
76− if (m_backgroundFile != backgroundFile) {
77− m_backgroundFile = backgroundFile;
78− Q_EMIT backgroundFileChanged();
79− }
80−}
81−
82−void AccountsBindings::updateStatsWelcomeScreen()
83−{
84− auto statsWelcomeScreen = m_service->getUserProperty(m_user, "com.ubuntu.touch.AccountsService.SecurityPrivacy", "StatsWelcomeScreen").toBool();
85− if (m_statsWelcomeScreen != statsWelcomeScreen) {
86− m_statsWelcomeScreen = statsWelcomeScreen;
87− Q_EMIT statsWelcomeScreenChanged();
88− }
89−}
90−
91−void AccountsBindings::propertiesChanged(const QString &user, const QString &interface, const QStringList &changed)
92−{
93− if (m_user != user) {
94− return;
95− }
96−
97− if (interface == "com.canonical.unity.AccountsService") {
98− if (changed.contains("demo-edges")) {
99− updateDemoEdges();
100− }
101− } else if (interface == "com.ubuntu.touch.AccountsService.SecurityPrivacy") {
102− if (changed.contains("StatsWelcomeScreen")) {
103− updateStatsWelcomeScreen();
104− }
105− }
106−}
107−
108−void AccountsBindings::maybeChanged(const QString &user)
109−{
110− if (m_user != user) {
111− return;
112− }
113−
114− // Standard properties might have changed
115− updateBackgroundFile();
116−}
plugins/AccountsService/AccountsBindings.hdeleted−72
@@ -1,72 +0,0 @@
1−/*
2− * Copyright (C) 2012,2013 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− * Authors: Michael Terry <michael.terry@canonical.com>
17− */
18−
19−#ifndef UNITY_ACCOUNTSBINDINGS_H
20−#define UNITY_ACCOUNTSBINDINGS_H
21−
22−#include <QObject>
23−#include <QString>
24−
25−class AccountsService;
26−
27−class AccountsBindings: public QObject
28−{
29− Q_OBJECT
30− Q_PROPERTY (bool demoEdges
31− READ getDemoEdges
32− WRITE setDemoEdges
33− NOTIFY demoEdgesChanged)
34− Q_PROPERTY (QString backgroundFile
35− READ getBackgroundFile
36− NOTIFY backgroundFileChanged)
37− Q_PROPERTY (bool statsWelcomeScreen
38− READ getStatsWelcomeScreen
39− NOTIFY statsWelcomeScreenChanged)
40−
41−public:
42− explicit AccountsBindings(QObject *parent = 0);
43−
44− Q_INVOKABLE void setUser(const QString &user);
45−
46− bool getDemoEdges();
47− void setDemoEdges(bool demoEdges);
48− QString getBackgroundFile();
49− bool getStatsWelcomeScreen();
50−
51−Q_SIGNALS:
52− void demoEdgesChanged();
53− void backgroundFileChanged();
54− void statsWelcomeScreenChanged();
55−
56−private Q_SLOTS:
57− void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
58− void maybeChanged(const QString &user);
59−
60−private:
61− void updateDemoEdges();
62− void updateBackgroundFile();
63− void updateStatsWelcomeScreen();
64−
65− AccountsService *m_service;
66− QString m_user;
67− bool m_demoEdges;
68− QString m_backgroundFile;
69− bool m_statsWelcomeScreen;
70−};
71−
72−#endif
plugins/AccountsService/AccountsService.cpp+77−80
@@ -17,110 +17,107 @@
17 */
17 */
18
18
19#include "AccountsService.h"
19#include "AccountsService.h"
20−#include <QDBusConnection>
20+#include "AccountsServiceDBusAdaptor.h"
21−#include <QDBusConnectionInterface>
21+
22−#include <QDBusMessage>
22+#include <QStringList>
23−#include <QDBusVariant>
24
23
25AccountsService::AccountsService(QObject* parent)
24AccountsService::AccountsService(QObject* parent)
26 : QObject(parent),
25 : QObject(parent),
27− accounts_manager(NULL),
26+ m_service(new AccountsServiceDBusAdaptor(this)),
28− users()
27+ m_user(qgetenv("USER"))
29{
28{
30− auto connection = QDBusConnection::SM_BUSNAME();
29+ connect(m_service, SIGNAL(propertiesChanged(const QString &, const QString &, const QStringList &)),
31− auto interface = connection.interface();
30+ this, SLOT(propertiesChanged(const QString &, const QString &, const QStringList &)));
32− interface->startService("org.freedesktop.Accounts");
31+ connect(m_service, SIGNAL(maybeChanged(const QString &)),
33− accounts_manager = new QDBusInterface("org.freedesktop.Accounts",
32+ this, SLOT(maybeChanged(const QString &)));
34− "/org/freedesktop/Accounts",
35− "org.freedesktop.Accounts",
36− connection, this);
37}
33}
38
34
39−QVariant AccountsService::getUserProperty(const QString &user, const QString &interface, const QString &property)
35+QString AccountsService::getUser()
40{
36{
41− auto iface = getUserInterface(user);
37+ return m_user;
42− if (iface != nullptr && iface->isValid()) {
43− auto answer = iface->call("Get", interface, property);
44− if (answer.type() == QDBusMessage::ReplyMessage) {
45− return answer.arguments()[0].value<QDBusVariant>().variant();
46− }
47− }
48− return QVariant();
49}
38}
50
39
51−void AccountsService::setUserProperty(const QString &user, const QString &interface, const QString &property, const QVariant &value)
40+void AccountsService::setUser(const QString &user)
52{
41{
53− auto iface = getUserInterface(user);
42+ m_user = user;
54− if (iface != nullptr && iface->isValid()) {
43+ Q_EMIT userChanged();
55− // The value needs to be carefully wrapped
44+
56− iface->call("Set", interface, property, QVariant::fromValue(QDBusVariant(value)));
45+ updateDemoEdges();
57− }
46+ updateBackgroundFile();
47+ updateStatsWelcomeScreen();
48+}
49+
50+bool AccountsService::getDemoEdges()
51+{
52+ return m_demoEdges;
58}
53}
59
54
60−void AccountsService::propertiesChangedSlot(const QString &interface, const QVariantMap &changed, const QStringList &invalid)
55+void AccountsService::setDemoEdges(bool demoEdges)
61{
56{
62− // Merge changed and invalidated together
57+ m_demoEdges = demoEdges;
63− QStringList combined;
58+ m_service->setUserProperty(m_user, "com.canonical.unity.AccountsService", "demo-edges", demoEdges);
64− combined << invalid;
59+}
65− combined << changed.keys();
66− combined.removeDuplicates();
67
60
68− Q_EMIT propertiesChanged(getUserForPath(message().path()), interface, combined);
61+QString AccountsService::getBackgroundFile()
62+{
63+ return m_backgroundFile;
69}
64}
70
65
71−void AccountsService::maybeChangedSlot()
66+bool AccountsService::getStatsWelcomeScreen()
72{
67{
73− Q_EMIT maybeChanged(getUserForPath(message().path()));
68+ return m_statsWelcomeScreen;
74}
69}
75
70
76−QString AccountsService::getUserForPath(const QString &path)
71+void AccountsService::updateDemoEdges()
77{
72{
78− QMap<QString, QDBusInterface *>::const_iterator i;
73+ auto demoEdges = m_service->getUserProperty(m_user, "com.canonical.unity.AccountsService", "demo-edges").toBool();
79− for (i = users.constBegin(); i != users.constEnd(); ++i) {
74+ if (m_demoEdges != demoEdges) {
80− if (i.value()->path() == path) {
75+ m_demoEdges = demoEdges;
81− return i.key();
76+ Q_EMIT demoEdgesChanged();
82− }
83 }
77 }
84− return QString();
85}
78}
86
79
87−QDBusInterface *AccountsService::getUserInterface(const QString &user)
80+void AccountsService::updateBackgroundFile()
88{
81{
89− auto iface = users.value(user);
90− if (iface == nullptr && accounts_manager->isValid()) {
91− auto answer = accounts_manager->call("FindUserByName", user);
92− if (answer.type() == QDBusMessage::ReplyMessage) {
93− auto path = answer.arguments()[0].value<QDBusObjectPath>().path();
94−
95− iface = new QDBusInterface("org.freedesktop.Accounts",
96− path,
97− "org.freedesktop.DBus.Properties",
98− accounts_manager->connection(), this);
99−
100− // With its own pre-defined properties, AccountsService is oddly
101− // close-lipped. It won't send out proper DBus.Properties notices,
102− // but it does have one catch-all Changed() signal. So let's
103− // listen to that.
104− iface->connection().connect(
105− iface->service(),
106− path,
107− "org.freedesktop.Accounts.User",
82+ auto backgroundFile = m_service->getUserProperty(m_user, "org.freedesktop.Accounts.User", "BackgroundFile").toString();
108− "Changed",
83+ if (m_backgroundFile != backgroundFile) {
109− this,
84+ m_backgroundFile = backgroundFile;
110− SLOT(maybeChangedSlot()));
85+ Q_EMIT backgroundFileChanged();
111−
86+ }
112− // But custom properties do send out the right notifications, so
87+}
113− // let's still listen there.
88+
114− iface->connection().connect(
89+void AccountsService::updateStatsWelcomeScreen()
115− iface->service(),
90+{
116− path,
91+ auto statsWelcomeScreen = m_service->getUserProperty(m_user, "com.ubuntu.touch.AccountsService.SecurityPrivacy", "StatsWelcomeScreen").toBool();
117− "org.freedesktop.DBus.Properties",
92+ if (m_statsWelcomeScreen != statsWelcomeScreen) {
118− "PropertiesChanged",
93+ m_statsWelcomeScreen = statsWelcomeScreen;
119− this,
94+ Q_EMIT statsWelcomeScreenChanged();
120− SLOT(propertiesChangedSlot(QString, QVariantMap, QStringList)));
95+ }
121−
96+}
122− users.insert(user, iface);
97+
98+void AccountsService::propertiesChanged(const QString &user, const QString &interface, const QStringList &changed)
99+{
100+ if (m_user != user) {
101+ return;
102+ }
103+
104+ if (interface == "com.canonical.unity.AccountsService") {
105+ if (changed.contains("demo-edges")) {
106+ updateDemoEdges();
123 }
107 }
108+ } else if (interface == "com.ubuntu.touch.AccountsService.SecurityPrivacy") {
109+ if (changed.contains("StatsWelcomeScreen")) {
110+ updateStatsWelcomeScreen();
111+ }
112+ }
113+}
114+
115+void AccountsService::maybeChanged(const QString &user)
116+{
117+ if (m_user != user) {
118+ return;
124 }
119 }
125− return iface;
120+
121+ // Standard properties might have changed
122+ updateBackgroundFile();
126}
123}
plugins/AccountsService/AccountsService.h+38−15
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2012,2013 Canonical, Ltd.
2+ * Copyright (C) 2013 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -19,36 +19,59 @@
19#ifndef UNITY_ACCOUNTSSERVICE_H
19#ifndef UNITY_ACCOUNTSSERVICE_H
20#define UNITY_ACCOUNTSSERVICE_H
20#define UNITY_ACCOUNTSSERVICE_H
21
21
22−#include <QDBusContext>
23−#include <QDBusInterface>
24−#include <QMap>
25#include <QObject>
22#include <QObject>
26#include <QString>
23#include <QString>
27
24
25+class AccountsServiceDBusAdaptor;
26+
28−class AccountsService: public QObject, public QDBusContext
27+class AccountsService: public QObject
29{
28{
30 Q_OBJECT
29 Q_OBJECT
30+ Q_PROPERTY (QString user
31+ READ getUser
32+ WRITE setUser
33+ NOTIFY userChanged)
34+ Q_PROPERTY (bool demoEdges
35+ READ getDemoEdges
36+ WRITE setDemoEdges
37+ NOTIFY demoEdgesChanged)
38+ Q_PROPERTY (QString backgroundFile
39+ READ getBackgroundFile
40+ NOTIFY backgroundFileChanged)
41+ Q_PROPERTY (bool statsWelcomeScreen
42+ READ getStatsWelcomeScreen
43+ NOTIFY statsWelcomeScreenChanged)
31
44
32public:
45public:
33 explicit AccountsService(QObject *parent = 0);
46 explicit AccountsService(QObject *parent = 0);
34
47
35− Q_INVOKABLE QVariant getUserProperty(const QString &user, const QString &interface, const QString &property);
48+ QString getUser();
36− Q_INVOKABLE void setUserProperty(const QString &user, const QString &interface, const QString &property, const QVariant &value);
49+ void setUser(const QString &user);
50+ bool getDemoEdges();
51+ void setDemoEdges(bool demoEdges);
52+ QString getBackgroundFile();
53+ bool getStatsWelcomeScreen();
37
54
38Q_SIGNALS:
55Q_SIGNALS:
39− void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
56+ void userChanged();
40− void maybeChanged(const QString &user); // Standard properties might have changed
57+ void demoEdgesChanged();
58+ void backgroundFileChanged();
59+ void statsWelcomeScreenChanged();
41
60
42private Q_SLOTS:
61private Q_SLOTS:
43− void propertiesChangedSlot(const QString &interface, const QVariantMap &changed, const QStringList &invalid);
62+ void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
44− void maybeChangedSlot();
63+ void maybeChanged(const QString &user);
45
64
46private:
65private:
47− QDBusInterface *getUserInterface(const QString &user);
66+ void updateDemoEdges();
48− QString getUserForPath(const QString &path);
67+ void updateBackgroundFile();
68+ void updateStatsWelcomeScreen();
49
69
50− QDBusInterface *accounts_manager;
70+ AccountsServiceDBusAdaptor *m_service;
51− QMap<QString, QDBusInterface *> users;
71+ QString m_user;
72+ bool m_demoEdges;
73+ QString m_backgroundFile;
74+ bool m_statsWelcomeScreen;
52};
75};
53
76
54#endif
77#endif
plugins/AccountsService/AccountsServiceDBusAdaptor.cppnew file+126
@@ -0,0 +1,126 @@
1+/*
2+ * Copyright (C) 2013 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+ * Author: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#include "AccountsServiceDBusAdaptor.h"
20+#include <QDBusConnection>
21+#include <QDBusConnectionInterface>
22+#include <QDBusMessage>
23+#include <QDBusVariant>
24+
25+AccountsServiceDBusAdaptor::AccountsServiceDBusAdaptor(QObject* parent)
26+ : QObject(parent),
27+ accounts_manager(NULL),
28+ users()
29+{
30+ auto connection = QDBusConnection::SM_BUSNAME();
31+ auto interface = connection.interface();
32+ interface->startService("org.freedesktop.Accounts");
33+ accounts_manager = new QDBusInterface("org.freedesktop.Accounts",
34+ "/org/freedesktop/Accounts",
35+ "org.freedesktop.Accounts",
36+ connection, this);
37+}
38+
39+QVariant AccountsServiceDBusAdaptor::getUserProperty(const QString &user, const QString &interface, const QString &property)
40+{
41+ auto iface = getUserInterface(user);
42+ if (iface != nullptr && iface->isValid()) {
43+ auto answer = iface->call("Get", interface, property);
44+ if (answer.type() == QDBusMessage::ReplyMessage) {
45+ return answer.arguments()[0].value<QDBusVariant>().variant();
46+ }
47+ }
48+ return QVariant();
49+}
50+
51+void AccountsServiceDBusAdaptor::setUserProperty(const QString &user, const QString &interface, const QString &property, const QVariant &value)
52+{
53+ auto iface = getUserInterface(user);
54+ if (iface != nullptr && iface->isValid()) {
55+ // The value needs to be carefully wrapped
56+ iface->call("Set", interface, property, QVariant::fromValue(QDBusVariant(value)));
57+ }
58+}
59+
60+void AccountsServiceDBusAdaptor::propertiesChangedSlot(const QString &interface, const QVariantMap &changed, const QStringList &invalid)
61+{
62+ // Merge changed and invalidated together
63+ QStringList combined;
64+ combined << invalid;
65+ combined << changed.keys();
66+ combined.removeDuplicates();
67+
68+ Q_EMIT propertiesChanged(getUserForPath(message().path()), interface, combined);
69+}
70+
71+void AccountsServiceDBusAdaptor::maybeChangedSlot()
72+{
73+ Q_EMIT maybeChanged(getUserForPath(message().path()));
74+}
75+
76+QString AccountsServiceDBusAdaptor::getUserForPath(const QString &path)
77+{
78+ QMap<QString, QDBusInterface *>::const_iterator i;
79+ for (i = users.constBegin(); i != users.constEnd(); ++i) {
80+ if (i.value()->path() == path) {
81+ return i.key();
82+ }
83+ }
84+ return QString();
85+}
86+
87+QDBusInterface *AccountsServiceDBusAdaptor::getUserInterface(const QString &user)
88+{
89+ auto iface = users.value(user);
90+ if (iface == nullptr && accounts_manager->isValid()) {
91+ auto answer = accounts_manager->call("FindUserByName", user);
92+ if (answer.type() == QDBusMessage::ReplyMessage) {
93+ auto path = answer.arguments()[0].value<QDBusObjectPath>().path();
94+
95+ iface = new QDBusInterface("org.freedesktop.Accounts",
96+ path,
97+ "org.freedesktop.DBus.Properties",
98+ accounts_manager->connection(), this);
99+
100+ // With its own pre-defined properties, AccountsService is oddly
101+ // close-lipped. It won't send out proper DBus.Properties notices,
102+ // but it does have one catch-all Changed() signal. So let's
103+ // listen to that.
104+ iface->connection().connect(
105+ iface->service(),
106+ path,
107+ "org.freedesktop.Accounts.User",
108+ "Changed",
109+ this,
110+ SLOT(maybeChangedSlot()));
111+
112+ // But custom properties do send out the right notifications, so
113+ // let's still listen there.
114+ iface->connection().connect(
115+ iface->service(),
116+ path,
117+ "org.freedesktop.DBus.Properties",
118+ "PropertiesChanged",
119+ this,
120+ SLOT(propertiesChangedSlot(QString, QVariantMap, QStringList)));
121+
122+ users.insert(user, iface);
123+ }
124+ }
125+ return iface;
126+}
plugins/AccountsService/AccountsServiceDBusAdaptor.hnew file+54
@@ -0,0 +1,54 @@
1+/*
2+ * Copyright (C) 2013 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+ * Authors: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#ifndef UNITY_ACCOUNTSSERVICEDBUSADAPTOR_H
20+#define UNITY_ACCOUNTSSERVICEDBUSADAPTOR_H
21+
22+#include <QDBusContext>
23+#include <QDBusInterface>
24+#include <QMap>
25+#include <QObject>
26+#include <QString>
27+
28+class AccountsServiceDBusAdaptor: public QObject, public QDBusContext
29+{
30+ Q_OBJECT
31+
32+public:
33+ explicit AccountsServiceDBusAdaptor(QObject *parent = 0);
34+
35+ Q_INVOKABLE QVariant getUserProperty(const QString &user, const QString &interface, const QString &property);
36+ Q_INVOKABLE void setUserProperty(const QString &user, const QString &interface, const QString &property, const QVariant &value);
37+
38+Q_SIGNALS:
39+ void propertiesChanged(const QString &user, const QString &interface, const QStringList &changed);
40+ void maybeChanged(const QString &user); // Standard properties might have changed
41+
42+private Q_SLOTS:
43+ void propertiesChangedSlot(const QString &interface, const QVariantMap &changed, const QStringList &invalid);
44+ void maybeChangedSlot();
45+
46+private:
47+ QDBusInterface *getUserInterface(const QString &user);
48+ QString getUserForPath(const QString &path);
49+
50+ QDBusInterface *accounts_manager;
51+ QMap<QString, QDBusInterface *> users;
52+};
53+
54+#endif
plugins/AccountsService/CMakeLists.txt+1−1
@@ -3,8 +3,8 @@ include(Plugins)
3add_definitions(-DSM_BUSNAME=systemBus)
3add_definitions(-DSM_BUSNAME=systemBus)
4
4
5add_library(AccountsService-qml MODULE
5add_library(AccountsService-qml MODULE
6− AccountsBindings.cpp
7 AccountsService.cpp
6 AccountsService.cpp
7+ AccountsServiceDBusAdaptor.cpp
8 plugin.cpp
8 plugin.cpp
9 )
9 )
10
10
plugins/AccountsService/plugin.cpp+3−3
@@ -17,7 +17,7 @@
17 */
17 */
18
18
19#include "plugin.h"
19#include "plugin.h"
20−#include "AccountsBindings.h"
20+#include "AccountsService.h"
21
21
22#include <QDBusMetaType>
22#include <QDBusMetaType>
23#include <QtQml>
23#include <QtQml>
@@ -26,12 +26,12 @@ static QObject *service_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
26{
26{
27 Q_UNUSED(engine)
27 Q_UNUSED(engine)
28 Q_UNUSED(scriptEngine)
28 Q_UNUSED(scriptEngine)
29− return new AccountsBindings();
29+ return new AccountsService();
30}
30}
31
31
32void AccountsServicePlugin::registerTypes(const char *uri)
32void AccountsServicePlugin::registerTypes(const char *uri)
33{
33{
34 Q_ASSERT(uri == QLatin1String("AccountsService"));
34 Q_ASSERT(uri == QLatin1String("AccountsService"));
35 qDBusRegisterMetaType<QList<QVariantMap>>();
35 qDBusRegisterMetaType<QList<QVariantMap>>();
36− qmlRegisterSingletonType<AccountsBindings>(uri, 0, 1, "AccountsService", service_provider);
36+ qmlRegisterSingletonType<AccountsService>(uri, 0, 1, "AccountsService", service_provider);
37}
37}
plugins/Unity/CMakeLists.txt+1
@@ -43,6 +43,7 @@ set(QMLPLUGIN_SRC
43 preview.cpp
43 preview.cpp
44 previewaction.cpp
44 previewaction.cpp
45 previewinfohint.cpp
45 previewinfohint.cpp
46+ showallfilteroption.cpp
46 signalslist.cpp
47 signalslist.cpp
47 socialpreview.cpp
48 socialpreview.cpp
48 socialpreviewcomment.cpp
49 socialpreviewcomment.cpp
plugins/Unity/Indicators/qml/MenuItemFactory.qml+1−16
@@ -73,23 +73,8 @@ Item {
73 'max-icon': 'icon'});
73 'max-icon': 'icon'});
74 }
74 }
75
75
76− // FIXME: The interval should be [0.0 - 1.0]. Unfortunately, when
77− // reaching the boundaries (0.0 or 1.0), the value is converted
78− // to an integer when automatically wrapped in a variant when
79− // passed to QStateAction::updateState(…). The server chokes on
80− // those values, complaining that they’re not of the right type…
81 onChangeState: {
76 onChangeState: {
82− if (value == Math.round(value)) {
83− if (value >= maximumValue) {
84− model.changeState(modelIndex, maximumValue - 0.000001);
85− } else if (value <= minimumValue) {
86− model.changeState(modelIndex, minimumValue + 0.000001);
77+ model.changeState(modelIndex, value);
87− } else {
88− model.changeState(modelIndex, value * 1.000001);
89− }
90− } else {
91− model.changeState(modelIndex, value);
92− }
93 }
78 }
94 }
79 }
95 }
80 }
plugins/Unity/Indicators/rootactionstate.cpp+44−14
@@ -108,25 +108,32 @@ bool RootActionState::isValid() const
108 return m_menu && m_menu->rowCount() > 0;
108 return m_menu && m_menu->rowCount() > 0;
109}
109}
110
110
111−QString RootActionState::label() const
111+QString RootActionState::leftLabel() const
112{
112{
113 if (!isValid()) return QString();
113 if (!isValid()) return QString();
114
114
115− return m_cachedState.value("label", QVariant::fromValue(QString())).toString();
115+ return m_cachedState.value("pre-label", QVariant::fromValue(QString())).toString();
116}
116}
117
117
118−QString RootActionState::icon() const
118+QString RootActionState::rightLabel() const
119{
119{
120 if (!isValid()) return QString();
120 if (!isValid()) return QString();
121
121
122− return m_cachedState.value("icon", QVariant::fromValue(QString())).toString();
122+ return m_cachedState.value("label", QVariant::fromValue(QString())).toString();
123+}
124+
125+QStringList RootActionState::icons() const
126+{
127+ if (!isValid()) return QStringList();
128+
129+ return m_cachedState.value("icons", QVariant::fromValue(QStringList())).toStringList();
123}
130}
124
131
125QString RootActionState::accessibleName() const
132QString RootActionState::accessibleName() const
126{
133{
127 if (!isValid()) return QString();
134 if (!isValid()) return QString();
128
135
129− return m_cachedState.value("accessible-name", QVariant::fromValue(QString())).toString();
136+ return m_cachedState.value("accessible-desc", QVariant::fromValue(QString())).toString();
130}
137}
131
138
132bool RootActionState::isVisible() const
139bool RootActionState::isVisible() const
@@ -198,16 +205,39 @@ QVariant RootActionState::toQVariant(GVariant* state) const
198 while (g_variant_iter_loop (&iter, "{sv}", &key, &vvalue))
205 while (g_variant_iter_loop (&iter, "{sv}", &key, &vvalue))
199 {
206 {
200 QString str = QString::fromUtf8(key);
207 QString str = QString::fromUtf8(key);
201− if (str == "icon") {
208+ if (str == "icon" && !qmap.contains("icons")) {
209+ QStringList icons;
210+
202 // FIXME - should be sending a url.
211 // FIXME - should be sending a url.
203− GIcon *icon = g_icon_deserialize (vvalue);
212+ GIcon *gicon = g_icon_deserialize (vvalue);
204− if (icon) {
213+ if (gicon) {
205− qmap.insert(str, iconUri(icon));
214+ icons << iconUri(gicon);
206− g_object_unref (icon);
215+ g_object_unref (gicon);
207 }
216 }
208− else {
209− qmap.insert(str, QVariant(""));
217+ qmap.insert("icons", icons);
218+
219+ } else if (str == "icons") {
220+
221+ QStringList icons;
222+
223+ if (g_variant_type_is_array(g_variant_get_type(vvalue))) {
224+
225+
226+ for (int i = 0, iMax = g_variant_n_children(vvalue); i < iMax; i++) {
227+ GVariant *child = g_variant_get_child_value(vvalue, i);
228+
229+ // FIXME - should be sending a url.
230+ GIcon *gicon = g_icon_deserialize (child);
231+ if (gicon) {
232+ icons << iconUri(gicon);
233+ g_object_unref (gicon);
234+ }
235+ g_variant_unref(child);
236+ }
210 }
237 }
238+ // will overwrite icon.
239+ qmap.insert("icons", icons);
240+
211 } else {
241 } else {
212 qmap.insert(str, ActionStateParser::toQVariant(vvalue));
242 qmap.insert(str, ActionStateParser::toQVariant(vvalue));
213 }
243 }
@@ -230,12 +260,12 @@ QVariant RootActionState::toQVariant(GVariant* state) const
230 &visible);
260 &visible);
231
261
232 qmap["label"] = label ? QString::fromUtf8(label) : "";
262 qmap["label"] = label ? QString::fromUtf8(label) : "";
233− qmap["accessible-name"] = accessible_name ? QString::fromUtf8(accessible_name) : "";
263+ qmap["accessible-desc"] = accessible_name ? QString::fromUtf8(accessible_name) : "";
234 qmap["visible"] = visible;
264 qmap["visible"] = visible;
235
265
236 gicon = g_icon_new_for_string (icon, NULL);
266 gicon = g_icon_new_for_string (icon, NULL);
237 if (gicon) {
267 if (gicon) {
238− qmap["icon"] = iconUri(gicon);
268+ qmap["icons"] = QStringList() << iconUri(gicon);
239 g_object_unref (gicon);
269 g_object_unref (gicon);
240 }
270 }
241
271
plugins/Unity/Indicators/rootactionstate.h+9−6
@@ -32,8 +32,9 @@ class UNITYINDICATORS_EXPORT RootActionState : public ActionStateParser
32 Q_PROPERTY(UnityMenuModel* menu READ menu WRITE setMenu NOTIFY menuChanged)
32 Q_PROPERTY(UnityMenuModel* menu READ menu WRITE setMenu NOTIFY menuChanged)
33
33
34 Q_PROPERTY(bool valid READ isValid NOTIFY validChanged)
34 Q_PROPERTY(bool valid READ isValid NOTIFY validChanged)
35− Q_PROPERTY(QString label READ label NOTIFY labelChanged)
35+ Q_PROPERTY(QString leftLabel READ leftLabel NOTIFY leftLabelChanged)
36− Q_PROPERTY(QString icon READ icon NOTIFY iconChanged)
36+ Q_PROPERTY(QString rightLabel READ rightLabel NOTIFY rightLabelChanged)
37+ Q_PROPERTY(QStringList icons READ icons NOTIFY iconsChanged)
37 Q_PROPERTY(QString accessibleName READ accessibleName NOTIFY accessibleNameChanged)
38 Q_PROPERTY(QString accessibleName READ accessibleName NOTIFY accessibleNameChanged)
38 Q_PROPERTY(bool visible READ isVisible NOTIFY visibleChanged)
39 Q_PROPERTY(bool visible READ isVisible NOTIFY visibleChanged)
39public:
40public:
@@ -47,8 +48,9 @@ public:
47 void setIndex(int index);
48 void setIndex(int index);
48
49
49 bool isValid() const;
50 bool isValid() const;
50− QString label() const;
51+ QString leftLabel() const;
51− QString icon() const;
52+ QString rightLabel() const;
53+ QStringList icons() const;
52 QString accessibleName() const;
54 QString accessibleName() const;
53 bool isVisible() const;
55 bool isVisible() const;
54
56
@@ -62,8 +64,9 @@ Q_SIGNALS:
62 void indexChanged();
64 void indexChanged();
63
65
64 void validChanged();
66 void validChanged();
65− void labelChanged();
67+ void leftLabelChanged();
66− void iconChanged();
68+ void rightLabelChanged();
69+ void iconsChanged();
67 void accessibleNameChanged();
70 void accessibleNameChanged();
68 void visibleChanged();
71 void visibleChanged();
69
72
plugins/Unity/Launcher/CMakeLists.txt+5−1
@@ -1,11 +1,13 @@
1include(FindPkgConfig)
1include(FindPkgConfig)
2pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=2)
2pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=2)
3+pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
3
4
4add_definitions(-DSM_BUSNAME=systemBus)
5add_definitions(-DSM_BUSNAME=systemBus)
5
6
6include_directories(
7include_directories(
7 ${CMAKE_CURRENT_SOURCE_DIR}
8 ${CMAKE_CURRENT_SOURCE_DIR}
8 ${CMAKE_SOURCE_DIR}/plugins/AccountsService
9 ${CMAKE_SOURCE_DIR}/plugins/AccountsService
10+ ${GSETTINGS_QT_INCLUDE_DIRS}
9)
11)
10
12
11set(QMLLAUNCHERPLUGIN_SRC
13set(QMLLAUNCHERPLUGIN_SRC
@@ -15,7 +17,7 @@ set(QMLLAUNCHERPLUGIN_SRC
15 quicklistmodel.cpp
17 quicklistmodel.cpp
16 common/quicklistentry.cpp
18 common/quicklistentry.cpp
17 backend/launcherbackend.cpp
19 backend/launcherbackend.cpp
18− ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsService.cpp
20+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
19 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
21 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
20 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
22 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
21 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/QuickListModelInterface.h
23 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/QuickListModelInterface.h
@@ -25,6 +27,8 @@ add_library(UnityLauncher-qml MODULE
25 ${QMLLAUNCHERPLUGIN_SRC}
27 ${QMLLAUNCHERPLUGIN_SRC}
26 )
28 )
27
29
30+target_link_libraries(UnityLauncher-qml ${GSETTINGS_QT_LDFLAGS})
31+
28qt5_use_modules(UnityLauncher-qml DBus Qml)
32qt5_use_modules(UnityLauncher-qml DBus Qml)
29
33
30# export the qmldir and qmltypes files
34# export the qmldir and qmltypes files
plugins/Unity/Launcher/backend/launcherbackend.cpp+188−100
@@ -18,109 +18,149 @@
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
19 */
20
20
21−#include "AccountsService.h"
21+#include "AccountsServiceDBusAdaptor.h"
22#include "launcherbackend.h"
22#include "launcherbackend.h"
23
23
24#include <QDir>
24#include <QDir>
25#include <QDBusArgument>
25#include <QDBusArgument>
26#include <QFileInfo>
26#include <QFileInfo>
27+#include <QGSettings>
28+#include <QDebug>
29+
30+class LauncherBackendItem
31+{
32+public:
33+ LauncherBackendItem(): pinned(false) {}
34+
35+ QString desktopFile;
36+ QString displayName;
37+ QString icon;
38+ bool pinned;
39+};
27
40
28LauncherBackend::LauncherBackend(bool useStorage, QObject *parent):
41LauncherBackend::LauncherBackend(bool useStorage, QObject *parent):
29 QObject(parent),
42 QObject(parent),
30 m_accounts(nullptr)
43 m_accounts(nullptr)
31{
44{
32 if (useStorage) {
45 if (useStorage) {
33− m_accounts = new AccountsService(this);
46+ m_accounts = new AccountsServiceDBusAdaptor(this);
34 }
47 }
35− setUser(qgetenv("USER"));
48+ m_user = qgetenv("USER");
49+ syncFromAccounts();
36}
50}
37
51
38LauncherBackend::~LauncherBackend()
52LauncherBackend::~LauncherBackend()
39{
53{
40− clearItems();
54+ m_storedApps.clear();
41−}
42
55
43−void LauncherBackend::clearItems()
44−{
45− for (LauncherBackendItem &app: m_storedApps) {
56+ Q_FOREACH(LauncherBackendItem *item, m_itemCache) {
46− delete app.settings;
57+ delete item;
47 }
58 }
48− m_storedApps.clear();
59+ m_itemCache.clear();
49}
60}
50
61
51QStringList LauncherBackend::storedApplications() const
62QStringList LauncherBackend::storedApplications() const
52{
63{
53− auto files = QStringList();
54− for (const LauncherBackendItem &app: m_storedApps) {
55− files << app.settings->fileName();
56− }
57− return files;
64+ return m_storedApps;
58}
65}
59
66
60void LauncherBackend::setStoredApplications(const QStringList &appIds)
67void LauncherBackend::setStoredApplications(const QStringList &appIds)
61{
68{
62− // Record all existing pinned apps, so we can notice them in new list
69+ if (appIds.count() < m_storedApps.count()) {
63− auto pinnedItems = QStringList();
70+ Q_FOREACH(const QString &appId, m_storedApps) {
64− for (LauncherBackendItem &app: m_storedApps) {
71+ if (!appIds.contains(appId)) {
65− if (app.pinned) {
72+ delete m_itemCache.take(appId);
66− pinnedItems.append(app.settings->fileName());
73+ }
67 }
74 }
68 }
75 }
69−
76+ m_storedApps = appIds;
70− clearItems();
71−
72− for (const QString &appId: appIds) {
77+ Q_FOREACH(const QString &appId, appIds) {
73− loadApp(makeAppDetails(appId, pinnedItems.contains(desktopFile(appId))));
78+ if (!m_itemCache.contains(appId)) {
79+ QString df = findDesktopFile(appId);
80+ if (!df.isEmpty()) {
81+ LauncherBackendItem *item = parseDesktopFile(df);
82+ m_itemCache.insert(appId, item);
83+ } else {
84+ // Cannot find any data for that app... ignoring it.
85+ qWarning() << "cannot find desktop file for" << appId << ". discarding app.";
86+ m_storedApps.removeAll(appId);
87+ }
88+ }
74 }
89 }
75−
76 syncToAccounts();
90 syncToAccounts();
77}
91}
78
92
79QString LauncherBackend::desktopFile(const QString &appId) const
93QString LauncherBackend::desktopFile(const QString &appId) const
80{
94{
81− QFileInfo fileInfo(QDir("/usr/share/applications"), appId);
95+ LauncherBackendItem *item = m_itemCache.value(appId);
82− return fileInfo.absoluteFilePath();
96+ if (item) {
97+ return item->desktopFile;
98+ }
99+
100+ return findDesktopFile(appId);
83}
101}
84
102
85QString LauncherBackend::displayName(const QString &appId) const
103QString LauncherBackend::displayName(const QString &appId) const
86{
104{
87− auto desktopFile = parseDesktopFile(appId);
105+ LauncherBackendItem *item = m_itemCache.value(appId);
88− auto displayName = desktopFile->value("Desktop Entry/Name").toString();
106+ if (item) {
89− delete desktopFile;
107+ return item->displayName;
108+ }
109+
110+ QString df = findDesktopFile(appId);
111+ if (!df.isEmpty()) {
112+ LauncherBackendItem *item = parseDesktopFile(df);
113+ m_itemCache.insert(appId, item);
114+ return item->displayName;
115+ }
116+
90− return displayName;
117+ return QString();
91}
118}
92
119
93QString LauncherBackend::icon(const QString &appId) const
120QString LauncherBackend::icon(const QString &appId) const
94{
121{
95− auto desktopFile = parseDesktopFile(appId);
122+ QString iconName;
96− auto iconName = desktopFile->value("Desktop Entry/Icon").toString();
123+ LauncherBackendItem *item = m_itemCache.value(appId);
97− delete desktopFile;
124+ if (item) {
98−
125+ iconName = item->icon;
126+ } else {
127+ QString df = findDesktopFile(appId);
99− if (!iconName.isEmpty()) {
128+ if (!df.isEmpty()) {
100− QFileInfo iconFileInfo(iconName);
129+ LauncherBackendItem *item = parseDesktopFile(df);
101− if (iconFileInfo.isRelative()) {
130+ m_itemCache.insert(appId, item);
102− iconName = "image://gicon/" + iconName;
131+ iconName = item->icon;
103 }
132 }
104 }
133 }
105
134
135+ QFileInfo info(iconName);
136+ if (info.exists()) {
137+ return info.absoluteFilePath();
138+ }
106− return iconName;
139+ return "image://theme/" + iconName;
107}
140}
108
141
109bool LauncherBackend::isPinned(const QString &appId) const
142bool LauncherBackend::isPinned(const QString &appId) const
110{
143{
111− auto index = findItem(appId);
144+ LauncherBackendItem *item = m_itemCache.value(appId);
112− if (index < 0) {
145+ if (item) {
113− return false;
146+ return item->pinned;
114− } else {
115− return m_storedApps[index].pinned;
116 }
147 }
148+ return false;
117}
149}
118
150
119void LauncherBackend::setPinned(const QString &appId, bool pinned)
151void LauncherBackend::setPinned(const QString &appId, bool pinned)
120{
152{
121− auto index = findItem(appId);
153+ if (!m_storedApps.contains(appId)) {
122− if (index >= 0 && !m_storedApps[index].pinned) {
154+ return;
155+ }
156+
157+ LauncherBackendItem *item = m_itemCache.value(appId);
158+ if (!item) {
159+ item = new LauncherBackendItem();
160+ m_itemCache.insert(appId, item);
161+ }
162+ if (item->pinned != pinned) {
123− m_storedApps[index].pinned = pinned;
163+ item->pinned = pinned;
124 syncToAccounts();
164 syncToAccounts();
125 }
165 }
126}
166}
@@ -153,8 +193,10 @@ int LauncherBackend::count(const QString &appId) const
153
193
154void LauncherBackend::setUser(const QString &username)
194void LauncherBackend::setUser(const QString &username)
155{
195{
196+ if (qgetenv("USER") == "lightdm" && m_user != username) {
156− m_user = username;
197+ m_user = username;
157− syncFromAccounts();
198+ syncFromAccounts();
199+ }
158}
200}
159
201
160void LauncherBackend::triggerQuickListAction(const QString &appId, const QString &quickListId)
202void LauncherBackend::triggerQuickListAction(const QString &appId, const QString &quickListId)
@@ -169,75 +211,132 @@ void LauncherBackend::syncFromAccounts()
169 QList<QVariantMap> apps;
211 QList<QVariantMap> apps;
170 bool defaults = true;
212 bool defaults = true;
171
213
172− clearItems();
214+ m_storedApps.clear();
173
215
174− if (m_user != "" && m_accounts != nullptr) {
216+ if (m_accounts && !m_user.isEmpty()) {
175− auto variant = m_accounts->getUserProperty(m_user, "com.canonical.unity.AccountsService", "launcher-items");
217+ QVariant variant = m_accounts->getUserProperty(m_user, "com.canonical.unity.AccountsService", "launcher-items");
176 apps = qdbus_cast<QList<QVariantMap>>(variant.value<QDBusArgument>());
218 apps = qdbus_cast<QList<QVariantMap>>(variant.value<QDBusArgument>());
177 defaults = isDefaultsItem(apps);
219 defaults = isDefaultsItem(apps);
178 }
220 }
179
221
180− // TODO: load default pinned ones from default config, instead of hardcoding here...
222+ if (m_accounts && defaults) { // Checking accounts as it'll be null when !useStorage
181− if (defaults) {
223+ QGSettings gSettings("com.canonical.Unity.Launcher", "/com/canonical/unity/launcher/");
182− apps <<
224+ Q_FOREACH(const QString &entry, gSettings.get("favorites").toStringList()) {
183− makeAppDetails("dialer-app.desktop", true) <<
225+ if (entry.startsWith("application://")) {
184− makeAppDetails("messaging-app.desktop", true) <<
226+ QString appId = entry;
185− makeAppDetails("address-book-app.desktop", true) <<
227+ // Transform "application://foobar.desktop" to "foobar"
186− makeAppDetails("camera-app.desktop", true) <<
228+ appId.remove("application://");
187− makeAppDetails("gallery-app.desktop", true) <<
229+ if (appId.endsWith(".desktop")) {
188− makeAppDetails("facebook-webapp.desktop", true) <<
230+ appId.chop(8);
189− makeAppDetails("webbrowser-app.desktop", true) <<
231+ }
190− makeAppDetails("twitter-webapp.desktop", true) <<
232+ QString df = findDesktopFile(appId);
191− makeAppDetails("gmail-webapp.desktop", true) <<
233+
192− makeAppDetails("ubuntu-weather-app.desktop", true) <<
234+ if (!df.isEmpty()) {
193− makeAppDetails("notes-app.desktop", true) <<
235+ m_storedApps << appId;
194− makeAppDetails("calendar-app.desktop", true);
236+
195− }
237+ if (!m_itemCache.contains(appId)) {
196−
238+ m_itemCache.insert(appId, parseDesktopFile(df));
239+ }
240+ m_itemCache.value(appId)->pinned = true;
241+ }
242+ }
243+ }
244+ } else {
197− for (const QVariant &app: apps) {
245+ for (const QVariant &app: apps) {
198− loadApp(app.toMap());
246+ loadFromVariant(app.toMap());
247+ }
199 }
248 }
200}
249}
201
250
202void LauncherBackend::syncToAccounts()
251void LauncherBackend::syncToAccounts()
203{
252{
204− if (m_user != "" && m_accounts != nullptr) {
253+ if (m_accounts && !m_user.isEmpty()) {
205 QList<QVariantMap> items;
254 QList<QVariantMap> items;
206
255
207− for (LauncherBackendItem &app: m_storedApps) {
256+ Q_FOREACH(const QString &appId, m_storedApps) {
208− items << makeAppDetails(app.settings->fileName(), app.pinned);
257+ items << itemToVariant(appId);
209 }
258 }
210
259
211 m_accounts->setUserProperty(m_user, "com.canonical.unity.AccountsService", "launcher-items", QVariant::fromValue(items));
260 m_accounts->setUserProperty(m_user, "com.canonical.unity.AccountsService", "launcher-items", QVariant::fromValue(items));
212 }
261 }
213}
262}
214
263
215−QSettings *LauncherBackend::parseDesktopFile(const QString &appId) const
264+QString LauncherBackend::findDesktopFile(const QString &appId) const
216{
265{
217− auto fullAppId = desktopFile(appId);
266+ int dashPos = -1;
218− return new QSettings(fullAppId, QSettings::IniFormat);
267+ QString helper = appId;
268+
269+ QStringList searchDirs;
270+ searchDirs << QDir::homePath() + "/.local/share/applications";
271+ searchDirs << "/usr/share/applications";
272+
273+#ifdef LAUNCHER_TESTING
274+ searchDirs << "";
275+#endif
276+
277+ do {
278+ if (dashPos != -1) {
279+ helper = helper.replace(dashPos, 1, '/');
280+ }
281+
282+ Q_FOREACH(const QString &searchDir, searchDirs) {
283+ QFileInfo fileInfo(QDir(searchDir), helper + ".desktop");
284+ if (fileInfo.exists()) {
285+ return fileInfo.absoluteFilePath();
286+ }
287+ }
288+
289+ dashPos = helper.indexOf("-");
290+ } while (dashPos != -1);
291+
292+ return QString();
219}
293}
220
294
221−void LauncherBackend::loadApp(const QVariantMap &details)
295+LauncherBackendItem* LauncherBackend::parseDesktopFile(const QString &desktopFile) const
222{
296{
223− auto appId = details.value("id").toString();
297+ QSettings settings(desktopFile, QSettings::IniFormat);
224− auto isPinned = details.value("is-pinned").toBool();
225
298
226− if (appId.isEmpty()) {
299+
300+ LauncherBackendItem* item = new LauncherBackendItem();
301+ item->desktopFile = desktopFile;
302+ item->displayName = settings.value("Desktop Entry/Name").toString();
303+ item->icon = settings.value("Desktop Entry/Icon").toString();
304+ item->pinned = false;
305+ return item;
306+}
307+
308+void LauncherBackend::loadFromVariant(const QVariantMap &details)
309+{
310+ if (!details.contains("id")) {
227 return;
311 return;
228 }
312 }
313+ QString appId = details.value("id").toString();
314+
315+ LauncherBackendItem *item = m_itemCache.value(appId);
316+ if (item) {
317+ delete item;
318+ }
319+
320+ item = new LauncherBackendItem();
229
321
230− LauncherBackendItem item;
322+ item->desktopFile = details.value("desktopFile").toString();
231− item.settings = parseDesktopFile(appId);
323+ item->displayName = details.value("name").toString();
232− item.pinned = isPinned;
324+ item->icon = details.value("icon").toString();
325+ item->pinned = details.value("is-pinned").toBool();
326+
327+ m_itemCache.insert(appId, item);
233− m_storedApps.append(item);
328+ m_storedApps.append(appId);
234}
329}
235
330
236−QVariantMap LauncherBackend::makeAppDetails(const QString &appId, bool pinned) const
331+QVariantMap LauncherBackend::itemToVariant(const QString &appId) const
237{
332{
333+ LauncherBackendItem *item = m_itemCache.value(appId);
238 QVariantMap details;
334 QVariantMap details;
239 details.insert("id", appId);
335 details.insert("id", appId);
336+ details.insert("name", item->displayName);
337+ details.insert("icon", item->icon);
338+ details.insert("desktopFile", item->desktopFile);
240− details.insert("is-pinned", pinned);
339+ details.insert("is-pinned", item->pinned);
241 return details;
340 return details;
242}
341}
243
342
@@ -248,14 +347,3 @@ bool LauncherBackend::isDefaultsItem(const QList<QVariantMap> &apps) const
248 // list of one item with the 'defaults' field set to true.
347 // list of one item with the 'defaults' field set to true.
249 return (apps.size() == 1 && apps[0].value("defaults").toBool());
348 return (apps.size() == 1 && apps[0].value("defaults").toBool());
250}
349}
251−
252−int LauncherBackend::findItem(const QString &appId) const
253−{
254− auto fullAppId = desktopFile(appId);
255− for (int i = 0; i < m_storedApps.size(); ++i) {
256− if (m_storedApps[i].settings->fileName() == fullAppId) {
257− return i;
258− }
259− }
260− return -1;
261−}
plugins/Unity/Launcher/backend/launcherbackend.h+12−14
@@ -25,12 +25,14 @@
25#include <QSettings>
25#include <QSettings>
26#include <QStringList>
26#include <QStringList>
27
27
28−class AccountsService;
28+class AccountsServiceDBusAdaptor;
29
29
30/**
30/**
31 * @brief An interface that provides all the data needed by the launcher.
31 * @brief An interface that provides all the data needed by the launcher.
32 */
32 */
33
33
34+class LauncherBackendItem;
35+
34class LauncherBackend : public QObject
36class LauncherBackend : public QObject
35{
37{
36 Q_OBJECT
38 Q_OBJECT
@@ -141,24 +143,20 @@ Q_SIGNALS:
141 void countChanged(const QString &appId, int count);
143 void countChanged(const QString &appId, int count);
142
144
143private:
145private:
146+ QString findDesktopFile(const QString &appId) const;
144− QSettings *parseDesktopFile(const QString &appId) const;
147+ LauncherBackendItem* parseDesktopFile(const QString &desktopFile) const;
148+
145− QVariantMap makeAppDetails(const QString &appId, bool pinned) const;
149+ QVariantMap itemToVariant(const QString &appId) const;
146− void loadApp(const QVariantMap &details);
150+ void loadFromVariant(const QVariantMap &details);
147− int findItem(const QString &appId) const;
151+
148 bool isDefaultsItem(const QList<QVariantMap> &apps) const;
152 bool isDefaultsItem(const QList<QVariantMap> &apps) const;
149 void syncFromAccounts();
153 void syncFromAccounts();
150 void syncToAccounts();
154 void syncToAccounts();
151− void clearItems();
152
155
156+ QList<QString> m_storedApps;
153− class LauncherBackendItem
157+ mutable QHash<QString, LauncherBackendItem*> m_itemCache;
154− {
155− public:
156− QSettings *settings;
157− bool pinned;
158− };
159
158
160− QList<LauncherBackendItem> m_storedApps;
159+ AccountsServiceDBusAdaptor *m_accounts;
161− AccountsService *m_accounts;
162 QString m_user;
160 QString m_user;
163};
161};
164
162
plugins/Unity/Launcher/launcheritem.cpp+14
@@ -31,6 +31,7 @@ LauncherItem::LauncherItem(const QString &appId, const QString &desktopFile, con
31 m_recent(false),
31 m_recent(false),
32 m_progress(-1),
32 m_progress(-1),
33 m_count(0),
33 m_count(0),
34+ m_focused(false),
34 m_quickList(new QuickListModel(this))
35 m_quickList(new QuickListModel(this))
35{
36{
36 QuickListEntry nameAction;
37 QuickListEntry nameAction;
@@ -131,6 +132,19 @@ void LauncherItem::setCount(int count)
131 }
132 }
132}
133}
133
134
135+bool LauncherItem::focused() const
136+{
137+ return m_focused;
138+}
139+
140+void LauncherItem::setFocused(bool focused)
141+{
142+ if (m_focused != focused) {
143+ m_focused = focused;
144+ Q_EMIT focusedChanged(focused);
145+ }
146+}
147+
134unity::shell::launcher::QuickListModelInterface *LauncherItem::quickList() const
148unity::shell::launcher::QuickListModelInterface *LauncherItem::quickList() const
135{
149{
136 return m_quickList;
150 return m_quickList;
plugins/Unity/Launcher/launcheritem.h+4
@@ -54,6 +54,9 @@ public:
54 int count() const;
54 int count() const;
55 void setCount(int count);
55 void setCount(int count);
56
56
57+ bool focused() const;
58+ void setFocused(bool focused);
59+
57 unity::shell::launcher::QuickListModelInterface *quickList() const;
60 unity::shell::launcher::QuickListModelInterface *quickList() const;
58
61
59Q_SIGNALS:
62Q_SIGNALS:
@@ -70,6 +73,7 @@ private:
70 bool m_recent;
73 bool m_recent;
71 int m_progress;
74 int m_progress;
72 int m_count;
75 int m_count;
76+ bool m_focused;
73 QuickListModel *m_quickList;
77 QuickListModel *m_quickList;
74};
78};
75
79
plugins/Unity/Launcher/launchermodel.cpp+59
@@ -74,6 +74,8 @@ QVariant LauncherModel::data(const QModelIndex &index, int role) const
74 return item->count();
74 return item->count();
75 case RoleProgress:
75 case RoleProgress:
76 return item->progress();
76 return item->progress();
77+ case RoleFocused:
78+ return item->focused();
77 }
79 }
78
80
79 return QVariant();
81 return QVariant();
@@ -191,6 +193,63 @@ void LauncherModel::setUser(const QString &username)
191 m_backend->setUser(username);
193 m_backend->setUser(username);
192}
194}
193
195
196+void LauncherModel::applicationFocused(const QString &appId)
197+{
198+ // Unfocus all apps
199+ for(int i = 0; i < m_list.count(); ++i) {
200+ LauncherItem *item = m_list.at(i);
201+ if (item->focused()) {
202+ item->setFocused(false);
203+ Q_EMIT dataChanged(this->index(i), this->index(i), QVector<int>() << RoleFocused);
204+ }
205+ }
206+
207+ if (appId.isEmpty()) {
208+ return;
209+ }
210+
211+ // FIXME: drop this once we get real appIds from the AppManager
212+ QString helper = appId.split('/').last();
213+ if (helper.endsWith(".desktop")) {
214+ helper.chop(8);
215+ }
216+
217+ int index = findApplication(helper);
218+ if (index >= 0) {
219+ m_list.at(index)->setFocused(true);
220+ Q_EMIT dataChanged(this->index(index), this->index(index), QVector<int>() << RoleFocused);
221+ } else {
222+ // Add app to recent apps
223+ QString desktopFile = m_backend->desktopFile(helper);
224+ QString appName = m_backend->displayName(helper);
225+ QString icon = m_backend->icon(helper);
226+
227+ LauncherItem *item = new LauncherItem(helper, desktopFile, appName, icon);
228+ item->setRecent(true);
229+ item->setFocused(true);
230+ beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
231+ m_list.append(item);
232+ endInsertRows();
233+
234+ // Clean up old recent apps
235+ QList<int> recentAppIndices;
236+ for (int i = 0; i < m_list.count(); ++i) {
237+ if (m_list.at(i)->recent()) {
238+ recentAppIndices << i;
239+ }
240+ }
241+ int run = 0;
242+ while (recentAppIndices.count() > 5) {
243+ beginRemoveRows(QModelIndex(), recentAppIndices.first() - run, recentAppIndices.first() - run);
244+ m_list.takeAt(recentAppIndices.first() - run)->deleteLater();
245+ endRemoveRows();
246+ recentAppIndices.takeFirst();
247+ ++run;
248+ }
249+ storeAppList();
250+ }
251+}
252+
194void LauncherModel::storeAppList()
253void LauncherModel::storeAppList()
195{
254{
196 QStringList appIds;
255 QStringList appIds;
plugins/Unity/Launcher/launchermodel.h+1
@@ -49,6 +49,7 @@ public:
49 Q_INVOKABLE void requestRemove(const QString &appId);
49 Q_INVOKABLE void requestRemove(const QString &appId);
50 Q_INVOKABLE void quickListActionInvoked(const QString &appId, int actionIndex);
50 Q_INVOKABLE void quickListActionInvoked(const QString &appId, int actionIndex);
51 Q_INVOKABLE void setUser(const QString &username);
51 Q_INVOKABLE void setUser(const QString &username);
52+ Q_INVOKABLE void applicationFocused(const QString &appId);
52
53
53private:
54private:
54 void storeAppList();
55 void storeAppList();
plugins/Unity/categories.cpp−3
@@ -43,7 +43,6 @@ Categories::Categories(QObject* parent)
43 m_roles[Categories::RoleHints] = "hints";
43 m_roles[Categories::RoleHints] = "hints";
44 m_roles[Categories::RoleResults] = "results";
44 m_roles[Categories::RoleResults] = "results";
45 m_roles[Categories::RoleCount] = "count";
45 m_roles[Categories::RoleCount] = "count";
46− m_roles[Categories::RoleCategoryIndex] = "categoryIndex";
47
46
48 // TODO This should not be needed but accumulatting the count changes
47 // TODO This should not be needed but accumulatting the count changes
49 // makes the visualization more stable and also makes crashes on fast
48 // makes the visualization more stable and also makes crashes on fast
@@ -222,8 +221,6 @@ Categories::data(const QModelIndex& index, int role) const
222 return QVariant::fromValue(m_overriddenCategories[id]->rowCount());
221 return QVariant::fromValue(m_overriddenCategories[id]->rowCount());
223 }
222 }
224 return QVariant::fromValue(getResults(index.row())->rowCount());
223 return QVariant::fromValue(getResults(index.row())->rowCount());
225− case RoleCategoryIndex:
226− return QVariant::fromValue(index.row());
227 default:
224 default:
228 return QVariant();
225 return QVariant();
229 }
226 }
plugins/Unity/categories.h+1−2
@@ -50,8 +50,7 @@ public:
50 RoleProgressSource,
50 RoleProgressSource,
51 RoleHints,
51 RoleHints,
52 RoleResults,
52 RoleResults,
53− RoleCount,
53+ RoleCount
54− RoleCategoryIndex
55 };
54 };
56
55
57 Q_INVOKABLE void overrideResults(const QString& categoryId, QAbstractItemModel* model);
56 Q_INVOKABLE void overrideResults(const QString& categoryId, QAbstractItemModel* model);
plugins/Unity/checkoptionfilter.cpp+3−1
@@ -52,9 +52,11 @@ void CheckOptionFilter::onOptionsChanged(unity::dash::CheckOptionFilter::CheckOp
52
52
53 m_options = new UnityOptionsModel(this, options,
53 m_options = new UnityOptionsModel(this, options,
54 m_unityCheckOptionFilter->option_added,
54 m_unityCheckOptionFilter->option_added,
55− m_unityCheckOptionFilter->option_removed);
55+ m_unityCheckOptionFilter->option_removed,
56+ m_unityCheckOptionFilter->show_all_button);
56
57
57 connect(m_options, SIGNAL(activeChanged(AbstractFilterOption *)), m_options, SLOT(ensureTheOnlyActive(AbstractFilterOption *)));
58 connect(m_options, SIGNAL(activeChanged(AbstractFilterOption *)), m_options, SLOT(ensureTheOnlyActive(AbstractFilterOption *)));
59+ connect(m_options, SIGNAL(showAllActivated()), this, SLOT(clear()));
58
60
59 /* Property change signals */
61 /* Property change signals */
60 m_signals << m_unityCheckOptionFilter->options.changed.connect(sigc::mem_fun(this, &CheckOptionFilter::onOptionsChanged));
62 m_signals << m_unityCheckOptionFilter->options.changed.connect(sigc::mem_fun(this, &CheckOptionFilter::onOptionsChanged));
plugins/Unity/filter.h+3−2
@@ -56,11 +56,12 @@ public:
56 bool filtering() const;
56 bool filtering() const;
57 virtual GenericOptionsModel* options() const = 0;
57 virtual GenericOptionsModel* options() const = 0;
58
58
59− Q_INVOKABLE void clear();
60−
61 static Filter* newFromUnityFilter(unity::dash::Filter::Ptr unityFilter);
59 static Filter* newFromUnityFilter(unity::dash::Filter::Ptr unityFilter);
62 bool hasUnityFilter(unity::dash::Filter::Ptr unityFilter) const;
60 bool hasUnityFilter(unity::dash::Filter::Ptr unityFilter) const;
63
61
62+public Q_SLOTS:
63+ void clear();
64+
64Q_SIGNALS:
65Q_SIGNALS:
65 void optionsChanged();
66 void optionsChanged();
66
67
plugins/Unity/genericoptionsmodel.cpp+20−3
@@ -22,10 +22,18 @@
22
22
23// local
23// local
24#include "abstractfilteroption.h"
24#include "abstractfilteroption.h"
25+#include "showallfilteroption.h"
25
26
26−GenericOptionsModel::GenericOptionsModel(QObject *parent)
27+GenericOptionsModel::GenericOptionsModel(bool showAllOption, QObject *parent)
27 : QAbstractListModel(parent)
28 : QAbstractListModel(parent)
28{
29{
30+ if (showAllOption)
31+ {
32+ auto showAll = new ShowAllFilterOption(this);
33+ connect(showAll, SIGNAL(activeChanged(bool)), this, SLOT(onOptionChanged()));
34+ connect(showAll, SIGNAL(activeChanged(bool)), this, SLOT(onShowAllClicked(bool)));
35+ addOption(showAll);
36+ }
29}
37}
30
38
31GenericOptionsModel::~GenericOptionsModel()
39GenericOptionsModel::~GenericOptionsModel()
@@ -73,7 +81,7 @@ QVariant GenericOptionsModel::data(const QModelIndex& index, int role) const
73
81
74int GenericOptionsModel::rowCount(const QModelIndex& /* parent */) const
82int GenericOptionsModel::rowCount(const QModelIndex& /* parent */) const
75{
83{
76− return m_options.size ();
84+ return m_options.size();
77}
85}
78
86
79void GenericOptionsModel::setActive(int idx, bool value)
87void GenericOptionsModel::setActive(int idx, bool value)
@@ -117,7 +125,10 @@ void GenericOptionsModel::ensureTheOnlyActive(AbstractFilterOption *activeOption
117
125
118void GenericOptionsModel::addOption(AbstractFilterOption *option, int index)
126void GenericOptionsModel::addOption(AbstractFilterOption *option, int index)
119{
127{
128+ if (index >= 0)
120− m_options.insert(index, option);
129+ m_options.insert(index, option);
130+ else
131+ m_options.append(option);
121
132
122 connect(option, SIGNAL(idChanged(const QString &)), this, SLOT(onOptionChanged()));
133 connect(option, SIGNAL(idChanged(const QString &)), this, SLOT(onOptionChanged()));
123 connect(option, SIGNAL(nameChanged(const QString &)), this, SLOT(onOptionChanged()));
134 connect(option, SIGNAL(nameChanged(const QString &)), this, SLOT(onOptionChanged()));
@@ -168,3 +179,9 @@ void GenericOptionsModel::onActiveChanged()
168 Q_EMIT activeChanged(option);
179 Q_EMIT activeChanged(option);
169 }
180 }
170}
181}
182+
183+void GenericOptionsModel::onShowAllClicked(bool active)
184+{
185+ if (active)
186+ Q_EMIT showAllActivated();
187+}
plugins/Unity/genericoptionsmodel.h+4−2
@@ -35,7 +35,7 @@ class Q_DECL_EXPORT GenericOptionsModel : public QAbstractListModel
35 Q_ENUMS(Roles)
35 Q_ENUMS(Roles)
36
36
37public:
37public:
38− GenericOptionsModel(QObject *parent = nullptr);
38+ GenericOptionsModel(bool showAllOption = false, QObject *parent = nullptr);
39 ~GenericOptionsModel();
39 ~GenericOptionsModel();
40
40
41 enum Roles {
41 enum Roles {
@@ -59,13 +59,15 @@ public Q_SLOTS:
59
59
60Q_SIGNALS:
60Q_SIGNALS:
61 void activeChanged(AbstractFilterOption *option);
61 void activeChanged(AbstractFilterOption *option);
62+ void showAllActivated();
62
63
63protected Q_SLOTS:
64protected Q_SLOTS:
64 void onOptionChanged();
65 void onOptionChanged();
65 void onActiveChanged();
66 void onActiveChanged();
67+ void onShowAllClicked(bool active);
66
68
67protected:
69protected:
68− void addOption(AbstractFilterOption *option, int index);
70+ void addOption(AbstractFilterOption *option, int index = -1);
69 void removeOption(int index);
71 void removeOption(int index);
70 int indexOf(const QString &option_id);
72 int indexOf(const QString &option_id);
71
73
plugins/Unity/multirangefilter.cpp+3−1
@@ -52,9 +52,11 @@ void MultiRangeFilter::onOptionsChanged(unity::dash::MultiRangeFilter::Options o
52
52
53 m_options = new UnityOptionsModel(this, options,
53 m_options = new UnityOptionsModel(this, options,
54 m_unityMultiRangeFilter->option_added,
54 m_unityMultiRangeFilter->option_added,
55− m_unityMultiRangeFilter->option_removed);
55+ m_unityMultiRangeFilter->option_removed,
56+ m_unityMultiRangeFilter->show_all_button);
56
57
57 connect(m_options, SIGNAL(activeChanged(AbstractFilterOption *)), m_options, SLOT(ensureTheOnlyActive(AbstractFilterOption *)));
58 connect(m_options, SIGNAL(activeChanged(AbstractFilterOption *)), m_options, SLOT(ensureTheOnlyActive(AbstractFilterOption *)));
59+ connect(m_options, SIGNAL(showAllActivated()), this, SLOT(clear()));
58
60
59 /* Property change signals */
61 /* Property change signals */
60 m_signals << m_unityMultiRangeFilter->options.changed.connect(sigc::mem_fun(this, &MultiRangeFilter::onOptionsChanged));
62 m_signals << m_unityMultiRangeFilter->options.changed.connect(sigc::mem_fun(this, &MultiRangeFilter::onOptionsChanged));
plugins/Unity/radiooptionfilter.cpp+3−1
@@ -51,7 +51,9 @@ void RadioOptionFilter::onOptionsChanged(unity::dash::RadioOptionFilter::RadioOp
51 }
51 }
52 m_options = new UnityOptionsModel(this, m_unityRadioOptionFilter->options,
52 m_options = new UnityOptionsModel(this, m_unityRadioOptionFilter->options,
53 m_unityRadioOptionFilter->option_added,
53 m_unityRadioOptionFilter->option_added,
54− m_unityRadioOptionFilter->option_removed);
54+ m_unityRadioOptionFilter->option_removed,
55+ m_unityRadioOptionFilter->show_all_button);
56+ connect(m_options, SIGNAL(showAllActivated()), this, SLOT(clear()));
55
57
56 m_signals << m_unityRadioOptionFilter->options.changed.connect(sigc::mem_fun(this, &RadioOptionFilter::onOptionsChanged));
58 m_signals << m_unityRadioOptionFilter->options.changed.connect(sigc::mem_fun(this, &RadioOptionFilter::onOptionsChanged));
57
59
plugins/Unity/ratingoptionsmodel.cpp+3−3
@@ -23,11 +23,11 @@
23// local
23// local
24#include "ratingfilteroption.h"
24#include "ratingfilteroption.h"
25
25
26−RatingOptionsModel::RatingOptionsModel(QObject *parent) :
26+RatingOptionsModel::RatingOptionsModel(bool showAllOption, QObject *parent) :
27− GenericOptionsModel(parent)
27+ GenericOptionsModel(showAllOption, parent)
28{
28{
29 for (int i=1; i<=5; i++) {
29 for (int i=1; i<=5; i++) {
30 auto opt = new RatingFilterOption(QString::number(i), i*0.2f, this);
30 auto opt = new RatingFilterOption(QString::number(i), i*0.2f, this);
31− addOption(opt, i-1);
31+ addOption(opt);
32 }
32 }
33}
33}
plugins/Unity/ratingoptionsmodel.h+1−1
@@ -27,7 +27,7 @@ class RatingOptionsModel : public GenericOptionsModel
27 Q_OBJECT
27 Q_OBJECT
28
28
29public:
29public:
30− RatingOptionsModel(QObject *parent);
30+ RatingOptionsModel(bool showAllOption, QObject *parent);
31};
31};
32
32
33#endif // RATINGOPTIONSMODEL_H
33#endif // RATINGOPTIONSMODEL_H
plugins/Unity/ratingsfilter.cpp+2−1
@@ -53,9 +53,10 @@ void RatingsFilter::setUnityFilter(unity::dash::Filter::Ptr filter)
53
53
54 delete m_options;
54 delete m_options;
55
55
56− m_options = new RatingOptionsModel(this);
56+ m_options = new RatingOptionsModel(m_unityRatingsFilter->show_all_button, this);
57 connect(m_options, SIGNAL(activeChanged(AbstractFilterOption *)), m_options, SLOT(ensureTheOnlyActive(AbstractFilterOption *)));
57 connect(m_options, SIGNAL(activeChanged(AbstractFilterOption *)), m_options, SLOT(ensureTheOnlyActive(AbstractFilterOption *)));
58 connect(m_options, SIGNAL(activeChanged(AbstractFilterOption *)), this, SLOT(onActiveChanged(AbstractFilterOption *)));
58 connect(m_options, SIGNAL(activeChanged(AbstractFilterOption *)), this, SLOT(onActiveChanged(AbstractFilterOption *)));
59+ connect(m_options, SIGNAL(showAllActivated()), this, SLOT(clear()));
59
60
60 Q_EMIT optionsChanged();
61 Q_EMIT optionsChanged();
61}
62}
plugins/Unity/showallfilteroption.cppnew file+60
@@ -0,0 +1,60 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+// self
21+#include "showallfilteroption.h"
22+
23+#include <libintl.h>
24+
25+unsigned int ShowAllFilterOption::m_showAllCount = 0;
26+
27+ShowAllFilterOption::ShowAllFilterOption(QObject *parent) :
28+ AbstractFilterOption(parent),
29+ m_active(false)
30+{
31+ m_id = QString("show_all::%1").arg(m_showAllCount++);
32+}
33+
34+QString ShowAllFilterOption::id() const
35+{
36+ return m_id;
37+}
38+
39+QString ShowAllFilterOption::name() const
40+{
41+ return QString::fromUtf8(dgettext("unity", "All"));
42+}
43+
44+QString ShowAllFilterOption::iconHint() const
45+{
46+ return QString::Null();
47+}
48+
49+bool ShowAllFilterOption::active() const
50+{
51+ return m_active;
52+}
53+
54+void ShowAllFilterOption::setActive(bool active)
55+{
56+ if (active != m_active) {
57+ m_active = active;
58+ Q_EMIT activeChanged(m_active);
59+ }
60+}
plugins/Unity/showallfilteroption.hnew file+51
@@ -0,0 +1,51 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * Authors:
5+ * Pawel Stolowski <pawel.stolowski@canonical.com>
6+ *
7+ * This program is free software; you can redistribute it and/or modify
8+ * it under the terms of the GNU General Public License as published by
9+ * the Free Software Foundation; version 3.
10+ *
11+ * This program is distributed in the hope that it will be useful,
12+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+ * GNU General Public License for more details.
15+ *
16+ * You should have received a copy of the GNU General Public License
17+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
18+ */
19+
20+#ifndef SHOWALLFILTEROPTION_H
21+#define SHOWALLFILTEROPTION_H
22+
23+// local
24+#include "abstractfilteroption.h"
25+
26+class Q_DECL_EXPORT ShowAllFilterOption : public AbstractFilterOption
27+{
28+ Q_OBJECT
29+
30+public:
31+ explicit ShowAllFilterOption(QObject *parent = nullptr);
32+
33+ /* getters */
34+ QString id() const override;
35+ QString name() const override;
36+ QString iconHint() const override;
37+ bool active() const override;
38+
39+ /* setters */
40+ void setActive(bool active) override;
41+
42+private:
43+ bool m_active;
44+ QString m_id;
45+
46+ static unsigned int m_showAllCount;
47+};
48+
49+Q_DECLARE_METATYPE(ShowAllFilterOption*)
50+
51+#endif // SHOWALLFILTEROPTION_H
plugins/Unity/unityoptionsmodel.cpp+5−4
@@ -26,8 +26,9 @@
26UnityOptionsModel::UnityOptionsModel(QObject *parent,
26UnityOptionsModel::UnityOptionsModel(QObject *parent,
27 const std::vector<unity::dash::FilterOption::Ptr> options,
27 const std::vector<unity::dash::FilterOption::Ptr> options,
28 sigc::signal<void, unity::dash::FilterOption::Ptr> optionAdded,
28 sigc::signal<void, unity::dash::FilterOption::Ptr> optionAdded,
29− sigc::signal<void, unity::dash::FilterOption::Ptr> optionRemoved) :
29+ sigc::signal<void, unity::dash::FilterOption::Ptr> optionRemoved,
30+ bool showAllOption) :
30− GenericOptionsModel(parent)
31+ GenericOptionsModel(showAllOption, parent)
31{
32{
32 setOptions(options, optionAdded, optionRemoved);
33 setOptions(options, optionAdded, optionRemoved);
33}
34}
@@ -38,7 +39,7 @@ void UnityOptionsModel::setOptions(const std::vector<unity::dash::FilterOption::
38{
39{
39 for (unsigned int i=0; i<options.size(); i++)
40 for (unsigned int i=0; i<options.size(); i++)
40 {
41 {
41− addOption(new FilterOption(options[i], this), i);
42+ addOption(new FilterOption(options[i], this));
42 }
43 }
43 optionAdded.connect(sigc::mem_fun(this, &UnityOptionsModel::onOptionAdded));
44 optionAdded.connect(sigc::mem_fun(this, &UnityOptionsModel::onOptionAdded));
44 optionRemoved.connect(sigc::mem_fun(this, &UnityOptionsModel::onOptionRemoved));
45 optionRemoved.connect(sigc::mem_fun(this, &UnityOptionsModel::onOptionRemoved));
@@ -50,7 +51,7 @@ void UnityOptionsModel::onOptionAdded(unity::dash::FilterOption::Ptr option)
50 if (index >= 0)
51 if (index >= 0)
51 {
52 {
52 beginInsertRows(QModelIndex(), index, index);
53 beginInsertRows(QModelIndex(), index, index);
53− addOption(new FilterOption(option, this), index);
54+ addOption(new FilterOption(option, this));
54 endInsertRows();
55 endInsertRows();
55 }
56 }
56}
57}
plugins/Unity/unityoptionsmodel.h+2−1
@@ -35,7 +35,8 @@ public:
35 UnityOptionsModel(QObject *parent,
35 UnityOptionsModel(QObject *parent,
36 const std::vector<unity::dash::FilterOption::Ptr> options,
36 const std::vector<unity::dash::FilterOption::Ptr> options,
37 sigc::signal<void, unity::dash::FilterOption::Ptr> optionAdded,
37 sigc::signal<void, unity::dash::FilterOption::Ptr> optionAdded,
38− sigc::signal<void, unity::dash::FilterOption::Ptr> optionRemoved);
38+ sigc::signal<void, unity::dash::FilterOption::Ptr> optionRemoved,
39+ bool showAllOption);
39
40
40private:
41private:
41 void setOptions(const std::vector<unity::dash::FilterOption::Ptr> options,
42 void setOptions(const std::vector<unity::dash::FilterOption::Ptr> options,
po/ar.po+2−29
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n % 100 >= "
17"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n % 100 >= "
18"3 && n % 100 <= 10 ? 3 : n % 100 >= 11 && n % 100 <= 99 ? 4 : 5;\n"
18"3 && n % 100 <= 10 ? 3 : n % 100 >= 11 && n % 100 <= 99 ? 4 : 5;\n"
19−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
19+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
20−"X-Generator: Launchpad (build 16738)\n"
20+"X-Generator: Launchpad (build 16750)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -254,30 +254,3 @@ msgstr "عذراً، لا يوجد ما يطابق بحثك."
254#, qt-format
254#, qt-format
255msgid "Please enter %1"
255msgid "Please enter %1"
256msgstr ""
256msgstr ""
257−
258−#~ msgid "Running apps"
259−#~ msgstr "البرامج المُشغّلة"
260−
261−#~ msgid "Frequently used"
262−#~ msgstr "مُستخدمة بكثرة"
263−
264−#~ msgid "Installed"
265−#~ msgstr "مُثبّتة"
266−
267−#~ msgid "Available for download"
268−#~ msgstr "متوفرة للتنزيل"
269−
270−#~ msgid "Apps"
271−#~ msgstr "تطبيقات"
272−
273−#~ msgid "Frequent Apps"
274−#~ msgstr "تطبيقات مألوفة"
275−
276−#~ msgid "Recent Music"
277−#~ msgstr "آخر الصوتيات المشغلة"
278−
279−#~ msgid "Videos Popular Online"
280−#~ msgstr "فيديوهات رائجة على الإنترنت"
281−
282−#~ msgid "Home"
283−#~ msgstr "الرئيسية"
po/az.po+2−8
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,9 +253,3 @@ msgstr "Bağışlayın, amma axtarışınıza heç bir nəticə uyğun gəlmir."
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Apps"
258−#~ msgstr "Tətbiqlər"
259−
260−#~ msgid "Home"
261−#~ msgstr "Ev"
po/bg.po+2−11
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Type: text/plain; charset=UTF-8\n"
17"Content-Transfer-Encoding: 8bit\n"
17"Content-Transfer-Encoding: 8bit\n"
18"Plural-Forms: nplurals=2; plural=n != 1;\n"
18"Plural-Forms: nplurals=2; plural=n != 1;\n"
19−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
19+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
20−"X-Generator: Launchpad (build 16738)\n"
20+"X-Generator: Launchpad (build 16750)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -254,12 +254,3 @@ msgstr "Съжаляваме, няма нищо, което да отговар
254#, qt-format
254#, qt-format
255msgid "Please enter %1"
255msgid "Please enter %1"
256msgstr ""
256msgstr ""
257−
258−#~ msgid "Installed"
259−#~ msgstr "Инсталирани"
260−
261−#~ msgid "Apps"
262−#~ msgstr "Приложения"
263−
264−#~ msgid "Home"
265−#~ msgstr "Начало"
po/ca.po+2−29
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,30 +253,3 @@ msgstr "No hi ha res que coincideixi amb la cerca"
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Running apps"
258−#~ msgstr "Aplications actives"
259−
260−#~ msgid "Frequently used"
261−#~ msgstr "Les més freqüents"
262−
263−#~ msgid "Installed"
264−#~ msgstr "Instal·lades"
265−
266−#~ msgid "Available for download"
267−#~ msgstr "Disponibles per baixar"
268−
269−#~ msgid "Apps"
270−#~ msgstr "Aplicacions"
271−
272−#~ msgid "Frequent Apps"
273−#~ msgstr "Aplicacions freqüents"
274−
275−#~ msgid "Recent Music"
276−#~ msgstr "Música recent"
277−
278−#~ msgid "Videos Popular Online"
279−#~ msgstr "Vídeos populars en línia"
280−
281−#~ msgid "Home"
282−#~ msgstr "Inici"
po/de.po+2−29
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,30 +253,3 @@ msgstr "Entschuldigung, es wurden keine Treffer erzielt."
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Running apps"
258−#~ msgstr "Aktive Anwendungen"
259−
260−#~ msgid "Frequently used"
261−#~ msgstr "Häufig verwendet"
262−
263−#~ msgid "Installed"
264−#~ msgstr "Installiert"
265−
266−#~ msgid "Available for download"
267−#~ msgstr "Zum Herunterladen verfügbar"
268−
269−#~ msgid "Apps"
270−#~ msgstr "Anwendungen"
271−
272−#~ msgid "Frequent Apps"
273−#~ msgstr "Häufig genutzte Anwendungen"
274−
275−#~ msgid "Recent Music"
276−#~ msgstr "Zuletzt gehörte Musik"
277−
278−#~ msgid "Videos Popular Online"
279−#~ msgstr "Beliebte Online-Videos"
280−
281−#~ msgid "Home"
282−#~ msgstr "Start"
po/el.po+2−8
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,9 +253,3 @@ msgstr "Λυπούμαστε, δεν υπάρχει τίποτα που να τ
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Apps"
258−#~ msgstr "Εφαρμογές"
259−
260−#~ msgid "Home"
261−#~ msgstr "Αρχή"
po/en_AU.po+2−29
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,30 +253,3 @@ msgstr "Sorry, there is nothing that matches your search."
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Running apps"
258−#~ msgstr "Running apps"
259−
260−#~ msgid "Frequently used"
261−#~ msgstr "Frequently used"
262−
263−#~ msgid "Installed"
264−#~ msgstr "Installed"
265−
266−#~ msgid "Available for download"
267−#~ msgstr "Available for download"
268−
269−#~ msgid "Apps"
270−#~ msgstr "Apps"
271−
272−#~ msgid "Frequent Apps"
273−#~ msgstr "Frequent Apps"
274−
275−#~ msgid "Recent Music"
276−#~ msgstr "Recent Music"
277−
278−#~ msgid "Videos Popular Online"
279−#~ msgstr "Videos Popular Online"
280−
281−#~ msgid "Home"
282−#~ msgstr "Home"
po/en_GB.po+2−29
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,30 +253,3 @@ msgstr "Sorry, there is nothing that matches your search."
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr "Please enter %1"
255msgstr "Please enter %1"
256−
257−#~ msgid "Running apps"
258−#~ msgstr "Running apps"
259−
260−#~ msgid "Frequently used"
261−#~ msgstr "Frequently used"
262−
263−#~ msgid "Installed"
264−#~ msgstr "Installed"
265−
266−#~ msgid "Available for download"
267−#~ msgstr "Available for download"
268−
269−#~ msgid "Apps"
270−#~ msgstr "Apps"
271−
272−#~ msgid "Frequent Apps"
273−#~ msgstr "Frequent Apps"
274−
275−#~ msgid "Recent Music"
276−#~ msgstr "Recent Music"
277−
278−#~ msgid "Videos Popular Online"
279−#~ msgstr "Videos Popular Online"
280−
281−#~ msgid "Home"
282−#~ msgstr "Home"
po/eo.po+2−2
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
po/es.po+24−49
@@ -8,15 +8,15 @@ msgstr ""
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: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2013-08-27 13:36-0400\n"
10"POT-Creation-Date: 2013-08-27 13:36-0400\n"
11−"PO-Revision-Date: 2013-07-08 07:25+0000\n"
11+"PO-Revision-Date: 2013-09-04 22:12+0000\n"
12"Last-Translator: Adolfo Jayme Barrientos <fitoschido@gmail.com>\n"
12"Last-Translator: Adolfo Jayme Barrientos <fitoschido@gmail.com>\n"
13"Language-Team: Spanish <es@li.org>\n"
13"Language-Team: Spanish <es@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-09-05 05:35+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16758)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -88,47 +88,49 @@ msgstr "YouTube"
88
88
89#: Components/EdgeDemoOverlay.qml:145
89#: Components/EdgeDemoOverlay.qml:145
90msgid "Skip intro"
90msgid "Skip intro"
91−msgstr ""
91+msgstr "Omitir la introducción"
92
92
93#: Components/EdgeDemo.qml:98
93#: Components/EdgeDemo.qml:98
94msgid "Right edge"
94msgid "Right edge"
95−msgstr ""
95+msgstr "Borde derecho"
96
96
97#: Components/EdgeDemo.qml:99
97#: Components/EdgeDemo.qml:99
98msgid "Try swiping from the right edge to unlock the phone"
98msgid "Try swiping from the right edge to unlock the phone"
99−msgstr ""
99+msgstr "Deslice el dedo desde el borde derecho para desbloquear el teléfono"
100
100
101#: Components/EdgeDemo.qml:135
101#: Components/EdgeDemo.qml:135
102msgid "Top edge"
102msgid "Top edge"
103−msgstr ""
103+msgstr "Borde superior"
104
104
105#: Components/EdgeDemo.qml:136
105#: Components/EdgeDemo.qml:136
106msgid "Try swiping from the top edge to access the indicators"
106msgid "Try swiping from the top edge to access the indicators"
107−msgstr ""
107+msgstr "Deslice el dedo desde el borde superior para acceder a los menús"
108
108
109#: Components/EdgeDemo.qml:161
109#: Components/EdgeDemo.qml:161
110msgid "Close"
110msgid "Close"
111−msgstr ""
111+msgstr "Cerrar"
112
112
113#: Components/EdgeDemo.qml:162
113#: Components/EdgeDemo.qml:162
114msgid "Swipe up again to close the settings screen"
114msgid "Swipe up again to close the settings screen"
115−msgstr ""
115+msgstr "Deslice hacia arriba para cerrar la pantalla de configuración"
116
116
117#: Components/EdgeDemo.qml:189
117#: Components/EdgeDemo.qml:189
118msgid "Left edge"
118msgid "Left edge"
119−msgstr ""
119+msgstr "Borde izquierdo"
120
120
121#: Components/EdgeDemo.qml:190
121#: Components/EdgeDemo.qml:190
122msgid "Swipe from the left to reveal the launcher for quick access to apps"
122msgid "Swipe from the left to reveal the launcher for quick access to apps"
123msgstr ""
123msgstr ""
124+"Deslice el dedo desde la izquierda para mostrar el lanzador y acceder "
125+"rápidamente a las aplicaciones"
124
126
125#: Components/EdgeDemo.qml:217
127#: Components/EdgeDemo.qml:217
126msgid "Well done"
128msgid "Well done"
127−msgstr ""
129+msgstr "Bien hecho"
128
130
129#: Components/EdgeDemo.qml:218
131#: Components/EdgeDemo.qml:218
130msgid "You have now mastered the edge gestures and can start using the phone"
132msgid "You have now mastered the edge gestures and can start using the phone"
131−msgstr ""
133+msgstr "Ahora domina el uso de gestos de los bordes. Puede usar el teléfono"
132
134
133#: Components/PageHeader.qml:298
135#: Components/PageHeader.qml:298
134msgid "Recent searches"
136msgid "Recent searches"
@@ -138,35 +140,35 @@ msgstr "Búsquedas recientes"
138#: Dash/Apps/AppInfo.qml:73
140#: Dash/Apps/AppInfo.qml:73
139#, qt-format
141#, qt-format
140msgid "(%1)"
142msgid "(%1)"
141−msgstr ""
143+msgstr "(%1)"
142
144
143#. TRANSLATORS: Number of persons who wrote reviews for this app
145#. TRANSLATORS: Number of persons who wrote reviews for this app
144#: Dash/Apps/AppInfo.qml:85
146#: Dash/Apps/AppInfo.qml:85
145#, qt-format
147#, qt-format
146msgid "%1 review"
148msgid "%1 review"
147msgid_plural "%1 reviews"
149msgid_plural "%1 reviews"
148−msgstr[0] ""
150+msgstr[0] "%1 reseña"
149−msgstr[1] ""
151+msgstr[1] "%1 reseñas"
150
152
151#: Dash/Apps/AppPreview.qml:175
153#: Dash/Apps/AppPreview.qml:175
152msgid "Rate this"
154msgid "Rate this"
153−msgstr ""
155+msgstr "Valorar esto"
154
156
155#: Dash/Apps/AppReviews.qml:72
157#: Dash/Apps/AppReviews.qml:72
156msgid "Add a review"
158msgid "Add a review"
157−msgstr ""
159+msgstr "Añadir una reseña"
158
160
159#: Dash/Apps/AppReviews.qml:84
161#: Dash/Apps/AppReviews.qml:84
160msgid "Review"
162msgid "Review"
161−msgstr ""
163+msgstr "Reseñar"
162
164
163#: Dash/Apps/AppReviews.qml:118
165#: Dash/Apps/AppReviews.qml:118
164msgid "Send"
166msgid "Send"
165−msgstr ""
167+msgstr "Enviar"
166
168
167#: Dash/Apps/AppReviews.qml:136
169#: Dash/Apps/AppReviews.qml:136
168msgid "Comments:"
170msgid "Comments:"
169−msgstr ""
171+msgstr "Comentarios:"
170
172
171#: Dash/DashMusic.qml:27 Dash/DashVideos.qml:28
173#: Dash/DashMusic.qml:27 Dash/DashVideos.qml:28
172msgid "Featured"
174msgid "Featured"
@@ -210,7 +212,7 @@ msgstr "Autor:"
210
212
211#: Greeter/Lockscreen.qml:134
213#: Greeter/Lockscreen.qml:134
212msgid "Emergency Call"
214msgid "Emergency Call"
213−msgstr ""
215+msgstr "Llamada de emergencia"
214
216
215#: Greeter/PassphraseLockscreen.qml:59
217#: Greeter/PassphraseLockscreen.qml:59
216#, qt-format
218#, qt-format
@@ -253,30 +255,3 @@ msgstr "No hay nada que coincida con su búsqueda."
253#, qt-format
255#, qt-format
254msgid "Please enter %1"
256msgid "Please enter %1"
255msgstr "Introduzca %1"
257msgstr "Introduzca %1"
256−
257−#~ msgid "Running apps"
258−#~ msgstr "Aplicaciones en ejecución"
259−
260−#~ msgid "Frequently used"
261−#~ msgstr "Usadas frecuentemente"
262−
263−#~ msgid "Installed"
264−#~ msgstr "Instaladas"
265−
266−#~ msgid "Available for download"
267−#~ msgstr "Disponibles para descargar"
268−
269−#~ msgid "Apps"
270−#~ msgstr "Aplicaciones"
271−
272−#~ msgid "Frequent Apps"
273−#~ msgstr "Aplicaciones frecuentes"
274−
275−#~ msgid "Recent Music"
276−#~ msgstr "Música reciente"
277−
278−#~ msgid "Videos Popular Online"
279−#~ msgstr "Vídeos populares en línea"
280−
281−#~ msgid "Home"
282−#~ msgstr "Inicio"
po/fi.po+2−29
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,30 +253,3 @@ msgstr "Hakuun täsmääviä tuloksia ei löydy."
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr "Kirjoita %1"
255msgstr "Kirjoita %1"
256−
257−#~ msgid "Running apps"
258−#~ msgstr "Käynnissä olevat sovellukset"
259−
260−#~ msgid "Frequently used"
261−#~ msgstr "Usein käytetyt"
262−
263−#~ msgid "Installed"
264−#~ msgstr "Asennetut"
265−
266−#~ msgid "Available for download"
267−#~ msgstr "Ladattavissa"
268−
269−#~ msgid "Apps"
270−#~ msgstr "Sovellukset"
271−
272−#~ msgid "Frequent Apps"
273−#~ msgstr "Yleisimmät sovellukset"
274−
275−#~ msgid "Recent Music"
276−#~ msgstr "Viimeisin musiikki"
277−
278−#~ msgid "Videos Popular Online"
279−#~ msgstr "Suositut verkkovideot"
280−
281−#~ msgid "Home"
282−#~ msgstr "Kotinäyttö"
po/fo.po+2−8
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,9 +253,3 @@ msgstr "Tíanverri er tað einki sum hóskar til tína leiting."
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Apps"
258−#~ msgstr "Nýtsluskipanir"
259−
260−#~ msgid "Home"
261−#~ msgstr "Heim"
po/fr.po+2−5
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,6 +253,3 @@ msgstr ""
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Apps"
258−#~ msgstr "Applications"
po/gl.po+2−29
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,30 +253,3 @@ msgstr "Sentímolo, non hai nada que coincida con esta busca."
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Running apps"
258−#~ msgstr "Aplicativos en execución"
259−
260−#~ msgid "Frequently used"
261−#~ msgstr "Usadas frecuentemente"
262−
263−#~ msgid "Installed"
264−#~ msgstr "Instalado"
265−
266−#~ msgid "Available for download"
267−#~ msgstr "Dispoñíbel para descargar"
268−
269−#~ msgid "Apps"
270−#~ msgstr "Aplicativos"
271−
272−#~ msgid "Frequent Apps"
273−#~ msgstr "Aplicativos frecuentes"
274−
275−#~ msgid "Recent Music"
276−#~ msgstr "Música recente"
277−
278−#~ msgid "Videos Popular Online"
279−#~ msgstr "Vídeos populares en liña"
280−
281−#~ msgid "Home"
282−#~ msgstr "Cartafol persoal"
po/he.po+2−8
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,9 +253,3 @@ msgstr "שום דבר אינו תואם לחיפוש שלך, עמך הסליחה
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Apps"
258−#~ msgstr "יישומים"
259−
260−#~ msgid "Home"
261−#~ msgstr "בית"
po/hr.po+2−8
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
19+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
20−"X-Generator: Launchpad (build 16738)\n"
20+"X-Generator: Launchpad (build 16750)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -254,9 +254,3 @@ msgstr "Nažalost, ne postoji ništa što odgovara vašoj pretrazi."
254#, qt-format
254#, qt-format
255msgid "Please enter %1"
255msgid "Please enter %1"
256msgstr ""
256msgstr ""
257−
258−#~ msgid "Apps"
259−#~ msgstr "Aplikacije"
260−
261−#~ msgid "Home"
262−#~ msgstr "Početna"
po/hu.po+2−17
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,18 +253,3 @@ msgstr "Elnézést, nincs találat a keresésre."
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Running apps"
258−#~ msgstr "Futó alkalmazások"
259−
260−#~ msgid "Frequently used"
261−#~ msgstr "Gyakran használt"
262−
263−#~ msgid "Installed"
264−#~ msgstr "Telepített"
265−
266−#~ msgid "Apps"
267−#~ msgstr "Alkalmazások"
268−
269−#~ msgid "Home"
270−#~ msgstr "Kezdőoldal"
po/hy.po+2−29
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,30 +253,3 @@ msgstr "Կներերք, բայց Ձեր հարցումով ոչինչ չկար"
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Running apps"
258−#~ msgstr "Բացած ծրագրեր"
259−
260−#~ msgid "Frequently used"
261−#~ msgstr "Վերջին բացածները"
262−
263−#~ msgid "Installed"
264−#~ msgstr "Տեղադրված"
265−
266−#~ msgid "Available for download"
267−#~ msgstr "Հասանելի ծրագրեր"
268−
269−#~ msgid "Apps"
270−#~ msgstr "Ծրագրեր"
271−
272−#~ msgid "Frequent Apps"
273−#~ msgstr "Հաճախակի ծրագրերը"
274−
275−#~ msgid "Recent Music"
276−#~ msgstr "Վերջին երգերը"
277−
278−#~ msgid "Videos Popular Online"
279−#~ msgstr "Հայտնի օնլայն վիդեոներ"
280−
281−#~ msgid "Home"
282−#~ msgstr "Տուն"
po/id.po+2−2
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
po/it.po+2−8
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,9 +253,3 @@ msgstr "Nessun risultato corrispondente alla ricerca."
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Apps"
258−#~ msgstr "Applicazioni"
259−
260−#~ msgid "Home"
261−#~ msgstr "Home"
po/ja.po+2−2
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
po/kn.po+2−8
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,9 +253,3 @@ msgstr "ಕ್ಷಮಿಸಿ ನಿಮ್ಮ ಶೋಧನೆಗೆ ಸರಿಯ
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Apps"
258−#~ msgstr "ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"
259−
260−#~ msgid "Home"
261−#~ msgstr "ಮನೆ (Home)"
po/ko.po+2−23
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,24 +253,3 @@ msgstr ""
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Running apps"
258−#~ msgstr "돌아가고 있는 앱"
259−
260−#~ msgid "Frequently used"
261−#~ msgstr "자주 쓰는 것들"
262−
263−#~ msgid "Installed"
264−#~ msgstr "깔림"
265−
266−#~ msgid "Available for download"
267−#~ msgstr "내려받을 수 있음"
268−
269−#~ msgid "Apps"
270−#~ msgstr "앱"
271−
272−#~ msgid "Frequent Apps"
273−#~ msgstr "자주 쓰는 앱"
274−
275−#~ msgid "Recent Music"
276−#~ msgstr "요즈음 찾는 음악"
po/ky.po+2−8
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,9 +253,3 @@ msgstr "Тилекке каршы, сиздин издөөңүзгө эч нер
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Apps"
258−#~ msgstr "Тиркемелер"
259−
260−#~ msgid "Home"
261−#~ msgstr "Үй папкасы"
po/lv.po+2−8
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,9 +253,3 @@ msgstr "Diemžēl nekas neatbilst jūsu meklētajam."
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Apps"
258−#~ msgstr "Lietotnes"
259−
260−#~ msgid "Home"
261−#~ msgstr "Mājas"
po/my.po+2−8
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,9 +253,3 @@ msgstr "ဆောရီး၊ သင်၏ရှာဖွေမူနှင့
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Apps"
258−#~ msgstr "Apps"
259−
260−#~ msgid "Home"
261−#~ msgstr "ပင်မ"
po/nb.po+2−17
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,18 +253,3 @@ msgstr "Søket ga ingen treff."
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Frequently used"
258−#~ msgstr "Ofte brukt"
259−
260−#~ msgid "Installed"
261−#~ msgstr "Installert"
262−
263−#~ msgid "Available for download"
264−#~ msgstr "Tilgjengelig for nedlasting"
265−
266−#~ msgid "Apps"
267−#~ msgstr "Programmer"
268−
269−#~ msgid "Home"
270−#~ msgstr "Hjem"
po/nl.po+2−8
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,9 +253,3 @@ msgstr "Er is helaas niets dat met uw zoekopdracht overeenkomt."
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Apps"
258−#~ msgstr "Apps"
259−
260−#~ msgid "Home"
261−#~ msgstr "Hoofdvenster"
po/pl.po+2−29
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
17"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
18"|| n%100>=20) ? 1 : 2;\n"
18"|| n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
19+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
20−"X-Generator: Launchpad (build 16738)\n"
20+"X-Generator: Launchpad (build 16750)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -254,30 +254,3 @@ msgstr "Nie znaleziono pasujących wyników."
254#, qt-format
254#, qt-format
255msgid "Please enter %1"
255msgid "Please enter %1"
256msgstr "Wprowadź %1"
256msgstr "Wprowadź %1"
257−
258−#~ msgid "Running apps"
259−#~ msgstr "Uruchomione aplikacje"
260−
261−#~ msgid "Frequently used"
262−#~ msgstr "Najczęściej używane"
263−
264−#~ msgid "Installed"
265−#~ msgstr "Zainstalowane"
266−
267−#~ msgid "Available for download"
268−#~ msgstr "Dostępne do pobrania"
269−
270−#~ msgid "Apps"
271−#~ msgstr "Aplikacje"
272−
273−#~ msgid "Frequent Apps"
274−#~ msgstr "Często używane aplikacje"
275−
276−#~ msgid "Recent Music"
277−#~ msgstr "Najnowsza muzyka"
278−
279−#~ msgid "Videos Popular Online"
280−#~ msgstr "Wideo popularne online"
281−
282−#~ msgid "Home"
283−#~ msgstr "Dom"
po/pt_BR.po+2−8
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
17"Plural-Forms: nplurals=2; plural=n > 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,9 +253,3 @@ msgstr "Desculpe, não há nada que corresponda à sua pesquisa."
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Apps"
258−#~ msgstr "Aplicativos"
259−
260−#~ msgid "Home"
261−#~ msgstr "Início"
po/ro.po+2−8
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=(n == 1 ? 0: (((n % 100 > 19) || ((n % 100 "
17"Plural-Forms: nplurals=3; plural=(n == 1 ? 0: (((n % 100 > 19) || ((n % 100 "
18"== 0) && (n != 0))) ? 2: 1));\n"
18"== 0) && (n != 0))) ? 2: 1));\n"
19−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
19+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
20−"X-Generator: Launchpad (build 16738)\n"
20+"X-Generator: Launchpad (build 16750)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -255,9 +255,3 @@ msgstr ""
255#, qt-format
255#, qt-format
256msgid "Please enter %1"
256msgid "Please enter %1"
257msgstr ""
257msgstr ""
258−
259−#~ msgid "Apps"
260−#~ msgstr "Aplicații"
261−
262−#~ msgid "Home"
263−#~ msgstr "Acasă"
po/ru.po+2−29
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
19+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
20−"X-Generator: Launchpad (build 16738)\n"
20+"X-Generator: Launchpad (build 16750)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -254,30 +254,3 @@ msgstr "Извините, поиск не дал результатов."
254#, qt-format
254#, qt-format
255msgid "Please enter %1"
255msgid "Please enter %1"
256msgstr "Пожалуйста, введите %1"
256msgstr "Пожалуйста, введите %1"
257−
258−#~ msgid "Running apps"
259−#~ msgstr "Запущенные приложения"
260−
261−#~ msgid "Frequently used"
262−#~ msgstr "Часто используемые"
263−
264−#~ msgid "Installed"
265−#~ msgstr "Установленные"
266−
267−#~ msgid "Available for download"
268−#~ msgstr "Доступно для загрузки"
269−
270−#~ msgid "Apps"
271−#~ msgstr "Приложения"
272−
273−#~ msgid "Frequent Apps"
274−#~ msgstr "Часто используемые приложения"
275−
276−#~ msgid "Recent Music"
277−#~ msgstr "Недавно прослушанная музыка"
278−
279−#~ msgid "Videos Popular Online"
280−#~ msgstr "Популярные видео из сети"
281−
282−#~ msgid "Home"
283−#~ msgstr "Главная"
po/si.po+2−2
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
po/sl.po+2−23
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || "
17"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || "
18"n%100==4 ? 3 : 0);\n"
18"n%100==4 ? 3 : 0);\n"
19−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
19+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
20−"X-Generator: Launchpad (build 16738)\n"
20+"X-Generator: Launchpad (build 16750)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -254,24 +254,3 @@ msgstr "Nič se ne ujema z vašim iskalnim nizom."
254#, qt-format
254#, qt-format
255msgid "Please enter %1"
255msgid "Please enter %1"
256msgstr ""
256msgstr ""
257−
258−#~ msgid "Frequently used"
259−#~ msgstr "Pogosto uporabljano"
260−
261−#~ msgid "Installed"
262−#~ msgstr "Nameščeno"
263−
264−#~ msgid "Available for download"
265−#~ msgstr "Na voljo za prejem"
266−
267−#~ msgid "Apps"
268−#~ msgstr "Programi"
269−
270−#~ msgid "Recent Music"
271−#~ msgstr "Nedavna glasba"
272−
273−#~ msgid "Home"
274−#~ msgstr "Domov"
275−
276−#~ msgid "Frequent Apps"
277−#~ msgstr "Pogosto uporabljani programi"
po/sr.po+2−8
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
19+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
20−"X-Generator: Launchpad (build 16738)\n"
20+"X-Generator: Launchpad (build 16750)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -254,9 +254,3 @@ msgstr "Нажалост, претрага није наишла на икакв
254#, qt-format
254#, qt-format
255msgid "Please enter %1"
255msgid "Please enter %1"
256msgstr ""
256msgstr ""
257−
258−#~ msgid "Apps"
259−#~ msgstr "Програми"
260−
261−#~ msgid "Home"
262−#~ msgstr "Почетна"
po/sv.po+2−2
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
po/te.po+2−5
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,6 +253,3 @@ msgstr ""
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Home"
258−#~ msgstr "నివాసం"
po/tr.po+2−29
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,30 +253,3 @@ msgstr "Üzgünüz, aramanızla eşleşen hiçbir şey yok."
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Running apps"
258−#~ msgstr "Çalışan uygulamalar"
259−
260−#~ msgid "Frequently used"
261−#~ msgstr "Sıkça kullanılanlar"
262−
263−#~ msgid "Installed"
264−#~ msgstr "Yüklenenler"
265−
266−#~ msgid "Available for download"
267−#~ msgstr "İndirilebilir durumda"
268−
269−#~ msgid "Apps"
270−#~ msgstr "Uygulamalar"
271−
272−#~ msgid "Frequent Apps"
273−#~ msgstr "Sıkça Kullanılan Uygulamalar"
274−
275−#~ msgid "Recent Music"
276−#~ msgstr "En Son Müzik"
277−
278−#~ msgid "Videos Popular Online"
279−#~ msgstr "Çevrimiçi Yaygın Videolar"
280−
281−#~ msgid "Home"
282−#~ msgstr "Ana Sayfa"
po/ug.po+2−29
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,30 +253,3 @@ msgstr "كەچۈرۈڭ، ئىزدىگىنىڭىزگە ماس نەتىجە تېپ
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Running apps"
258−#~ msgstr "ئىجرا بولۇۋاتقان ئەپلەر"
259−
260−#~ msgid "Frequently used"
261−#~ msgstr "كوپ ئىشلىتىلگەنلىرى"
262−
263−#~ msgid "Installed"
264−#~ msgstr "ئورنىتىلغانلىرى"
265−
266−#~ msgid "Available for download"
267−#~ msgstr "چۈشۈرگىلى بولىدىغانلىرى"
268−
269−#~ msgid "Apps"
270−#~ msgstr "ئەپلەر"
271−
272−#~ msgid "Frequent Apps"
273−#~ msgstr "دائىم ئىشلىتىلىدىغان ئەپلەر"
274−
275−#~ msgid "Recent Music"
276−#~ msgstr "يېقىندا ئاڭلىغان مۇزىكىلار"
277−
278−#~ msgid "Videos Popular Online"
279−#~ msgstr "توردىكى ئالقىشقا ئېرىشكەن سىنلار"
280−
281−#~ msgid "Home"
282−#~ msgstr "ماكان"
po/uk.po+2−29
@@ -16,8 +16,8 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
17"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
18"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
19−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
19+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
20−"X-Generator: Launchpad (build 16738)\n"
20+"X-Generator: Launchpad (build 16750)\n"
21
21
22#: Applications/applications.js:23
22#: Applications/applications.js:23
23msgid "Phone"
23msgid "Phone"
@@ -254,30 +254,3 @@ msgstr "Вибачте, для вказаних вами ключових слі
254#, qt-format
254#, qt-format
255msgid "Please enter %1"
255msgid "Please enter %1"
256msgstr "Будь ласка, введіть %1"
256msgstr "Будь ласка, введіть %1"
257−
258−#~ msgid "Running apps"
259−#~ msgstr "Запущені програми"
260−
261−#~ msgid "Frequently used"
262−#~ msgstr "Найчастіше використовувані"
263−
264−#~ msgid "Installed"
265−#~ msgstr "Встановлені"
266−
267−#~ msgid "Available for download"
268−#~ msgstr "Доступно до завантаження"
269−
270−#~ msgid "Apps"
271−#~ msgstr "Програми"
272−
273−#~ msgid "Frequent Apps"
274−#~ msgstr "Часто використовувані програми"
275−
276−#~ msgid "Recent Music"
277−#~ msgstr "Нещодавно прослухана музика"
278−
279−#~ msgid "Videos Popular Online"
280−#~ msgstr "Популярні в мережі відео"
281−
282−#~ msgid "Home"
283−#~ msgstr "Домівка"
po/zh_CN.po+2−29
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,30 +253,3 @@ msgstr "对不起,没有找到您想要的结果。"
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Running apps"
258−#~ msgstr "正在运行的应用程序"
259−
260−#~ msgid "Frequently used"
261−#~ msgstr "常用"
262−
263−#~ msgid "Installed"
264−#~ msgstr "已安装"
265−
266−#~ msgid "Available for download"
267−#~ msgstr "可供下载"
268−
269−#~ msgid "Apps"
270−#~ msgstr "应用程序"
271−
272−#~ msgid "Frequent Apps"
273−#~ msgstr "常用软件"
274−
275−#~ msgid "Recent Music"
276−#~ msgstr "近期听过的音乐"
277−
278−#~ msgid "Videos Popular Online"
279−#~ msgstr "热门在线视频"
280−
281−#~ msgid "Home"
282−#~ msgstr "主页"
po/zh_TW.po+2−29
@@ -15,8 +15,8 @@ msgstr ""
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2013-08-29 05:41+0000\n"
18+"X-Launchpad-Export-Date: 2013-08-30 05:37+0000\n"
19−"X-Generator: Launchpad (build 16738)\n"
19+"X-Generator: Launchpad (build 16750)\n"
20
20
21#: Applications/applications.js:23
21#: Applications/applications.js:23
22msgid "Phone"
22msgid "Phone"
@@ -253,30 +253,3 @@ msgstr "很抱歉,找不到符合您想搜尋的結果。"
253#, qt-format
253#, qt-format
254msgid "Please enter %1"
254msgid "Please enter %1"
255msgstr ""
255msgstr ""
256−
257−#~ msgid "Running apps"
258−#~ msgstr "執行中的程式"
259−
260−#~ msgid "Frequently used"
261−#~ msgstr "最常使用"
262−
263−#~ msgid "Installed"
264−#~ msgstr "已安裝"
265−
266−#~ msgid "Available for download"
267−#~ msgstr "可供下載"
268−
269−#~ msgid "Apps"
270−#~ msgstr "程式"
271−
272−#~ msgid "Frequent Apps"
273−#~ msgstr "常用的程式"
274−
275−#~ msgid "Recent Music"
276−#~ msgstr "最近聽過的音樂"
277−
278−#~ msgid "Videos Popular Online"
279−#~ msgstr "線上熱門的影片"
280−
281−#~ msgid "Home"
282−#~ msgstr "家屋"
tests/mocks/AccountsService/AccountsBindings.cpp → tests/mocks/AccountsService/AccountsService.cpprenamed+15−8
@@ -16,38 +16,45 @@
16 * Author: Michael Terry <michael.terry@canonical.com>
16 * Author: Michael Terry <michael.terry@canonical.com>
17 */
17 */
18
18
19−#include "AccountsBindings.h"
19+#include "AccountsService.h"
20
20
21−AccountsBindings::AccountsBindings(QObject* parent)
21+AccountsService::AccountsService(QObject* parent)
22 : QObject(parent),
22 : QObject(parent),
23 m_statsWelcomeScreen(true)
23 m_statsWelcomeScreen(true)
24{
24{
25}
25}
26
26
27−void AccountsBindings::setUser(const QString &)
27+QString AccountsService::getUser()
28{
28{
29+ return "testuser";
29}
30}
30
31
32+void AccountsService::setUser(const QString &user)
33+{
34+ Q_UNUSED(user)
35+}
36+
31−bool AccountsBindings::getDemoEdges()
37+bool AccountsService::getDemoEdges()
32{
38{
33 return false;
39 return false;
34}
40}
35
41
36−void AccountsBindings::setDemoEdges(bool)
42+void AccountsService::setDemoEdges(bool demoEdges)
37{
43{
44+ Q_UNUSED(demoEdges)
38}
45}
39
46
40−QString AccountsBindings::getBackgroundFile()
47+QString AccountsService::getBackgroundFile()
41{
48{
42 return TOP_SRCDIR "/graphics/phone_background.jpg";
49 return TOP_SRCDIR "/graphics/phone_background.jpg";
43}
50}
44
51
45−bool AccountsBindings::getStatsWelcomeScreen()
52+bool AccountsService::getStatsWelcomeScreen()
46{
53{
47 return m_statsWelcomeScreen;
54 return m_statsWelcomeScreen;
48}
55}
49
56
50−void AccountsBindings::setStatsWelcomeScreen(bool statsWelcomeScreen)
57+void AccountsService::setStatsWelcomeScreen(bool statsWelcomeScreen)
51{
58{
52 m_statsWelcomeScreen = statsWelcomeScreen;
59 m_statsWelcomeScreen = statsWelcomeScreen;
53 statsWelcomeScreenChanged();
60 statsWelcomeScreenChanged();
tests/mocks/AccountsService/AccountsBindings.h → tests/mocks/AccountsService/AccountsService.hrenamed+12−7
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2012,2013 Canonical, Ltd.
2+ * Copyright (C) 2013 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -17,16 +17,20 @@
17 * Michael Terry <michael.terry@canonical.com>
17 * Michael Terry <michael.terry@canonical.com>
18 */
18 */
19
19
20−#ifndef UNITY_MOCK_ACCOUNTSBINDINGS_H
20+#ifndef UNITY_MOCK_ACCOUNTSSERVICE_H
21−#define UNITY_MOCK_ACCOUNTSBINDINGS_H
21+#define UNITY_MOCK_ACCOUNTSSERVICE_H
22
22
23#include <QObject>
23#include <QObject>
24#include <QString>
24#include <QString>
25#include <QVariant>
25#include <QVariant>
26
26
27−class AccountsBindings: public QObject
27+class AccountsService: public QObject
28{
28{
29 Q_OBJECT
29 Q_OBJECT
30+ Q_PROPERTY (QString user
31+ READ getUser
32+ WRITE setUser
33+ NOTIFY userChanged)
30 Q_PROPERTY (bool demoEdges
34 Q_PROPERTY (bool demoEdges
31 READ getDemoEdges
35 READ getDemoEdges
32 WRITE setDemoEdges
36 WRITE setDemoEdges
@@ -40,10 +44,10 @@ class AccountsBindings: public QObject
40 NOTIFY statsWelcomeScreenChanged)
44 NOTIFY statsWelcomeScreenChanged)
41
45
42public:
46public:
43− explicit AccountsBindings(QObject *parent = 0);
47+ explicit AccountsService(QObject *parent = 0);
44−
45− Q_INVOKABLE void setUser(const QString &user);
46
48
49+ QString getUser();
50+ void setUser(const QString &user);
47 bool getDemoEdges();
51 bool getDemoEdges();
48 void setDemoEdges(bool demoEdges);
52 void setDemoEdges(bool demoEdges);
49 QString getBackgroundFile();
53 QString getBackgroundFile();
@@ -51,6 +55,7 @@ public:
51 void setStatsWelcomeScreen(bool statsWelcomeScreen);
55 void setStatsWelcomeScreen(bool statsWelcomeScreen);
52
56
53Q_SIGNALS:
57Q_SIGNALS:
58+ void userChanged();
54 void demoEdgesChanged();
59 void demoEdgesChanged();
55 void backgroundFileChanged();
60 void backgroundFileChanged();
56 void statsWelcomeScreenChanged();
61 void statsWelcomeScreenChanged();
tests/mocks/AccountsService/CMakeLists.txt+1−1
@@ -1,7 +1,7 @@
1add_definitions(-DTOP_SRCDIR="${CMAKE_SOURCE_DIR}")
1add_definitions(-DTOP_SRCDIR="${CMAKE_SOURCE_DIR}")
2
2
3add_library(MockAccountsService-qml MODULE
3add_library(MockAccountsService-qml MODULE
4− AccountsBindings.cpp
4+ AccountsService.cpp
5 plugin.cpp
5 plugin.cpp
6 )
6 )
7
7
tests/mocks/AccountsService/plugin.cpp+3−3
@@ -18,7 +18,7 @@
18 */
18 */
19
19
20#include "plugin.h"
20#include "plugin.h"
21−#include "AccountsBindings.h"
21+#include "AccountsService.h"
22
22
23#include <QtQml>
23#include <QtQml>
24
24
@@ -26,11 +26,11 @@ static QObject *service_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
26{
26{
27 Q_UNUSED(engine)
27 Q_UNUSED(engine)
28 Q_UNUSED(scriptEngine)
28 Q_UNUSED(scriptEngine)
29− return new AccountsBindings();
29+ return new AccountsService();
30}
30}
31
31
32void AccountsServicePlugin::registerTypes(const char *uri)
32void AccountsServicePlugin::registerTypes(const char *uri)
33{
33{
34 Q_ASSERT(uri == QLatin1String("AccountsService"));
34 Q_ASSERT(uri == QLatin1String("AccountsService"));
35− qmlRegisterSingletonType<AccountsBindings>(uri, 0, 1, "AccountsService", service_provider);
35+ qmlRegisterSingletonType<AccountsService>(uri, 0, 1, "AccountsService", service_provider);
36}
36}
tests/mocks/LightDM/demo/GreeterPrivate.cpp+4−2
@@ -55,11 +55,13 @@ void GreeterPrivate::handleRespond(const QString &response)
55 QSettings settings(QDir::homePath() + "/.unity8-greeter-demo", QSettings::NativeFormat);
55 QSettings settings(QDir::homePath() + "/.unity8-greeter-demo", QSettings::NativeFormat);
56 QVariant password = settings.value("password", "none");
56 QVariant password = settings.value("password", "none");
57
57
58+ QString passwordValue;
58 if (password == "pin") {
59 if (password == "pin") {
59− authenticated = (response == "1234");
60+ passwordValue = settings.value("passwordValue", "1234").toString();
60 } else {
61 } else {
61− authenticated = (response == "password");
62+ passwordValue = settings.value("passwordValue", "password").toString();
62 }
63 }
64+ authenticated = (response == passwordValue);
63 Q_EMIT q->authenticationComplete();
65 Q_EMIT q->authenticationComplete();
64}
66}
65
67
tests/mocks/Unity/CMakeLists.txt+2
@@ -17,6 +17,8 @@ add_definitions(-DQT_NO_KEYWORDS)
17
17
18set(UnityQML_SOURCES
18set(UnityQML_SOURCES
19 ${CMAKE_SOURCE_DIR}/plugins/Unity/categoryresults.cpp
19 ${CMAKE_SOURCE_DIR}/plugins/Unity/categoryresults.cpp
20+ fake_applications_scope.cpp
21+ fake_preview.cpp
20 fake_scope.cpp
22 fake_scope.cpp
21 fake_scopes.cpp
23 fake_scopes.cpp
22 fake_categories.cpp
24 fake_categories.cpp
tests/mocks/Unity/Launcher/MockLauncherItem.cpp+16
@@ -33,6 +33,7 @@ MockLauncherItem::MockLauncherItem(const QString &appId, const QString& desktopF
33 m_recent(false),
33 m_recent(false),
34 m_progress(-1),
34 m_progress(-1),
35 m_count(0),
35 m_count(0),
36+ m_focused(false),
36 m_quickList(new MockQuickListModel(this))
37 m_quickList(new MockQuickListModel(this))
37{
38{
38
39
@@ -128,6 +129,21 @@ void MockLauncherItem::setCount(int count)
128 }
129 }
129}
130}
130
131
132+bool MockLauncherItem::focused() const
133+{
134+ return m_focused;
135+}
136+
137+void MockLauncherItem::setFocused(bool focused)
138+{
139+ if (m_focused != focused)
140+ {
141+ m_focused = focused;
142+ Q_EMIT focusedChanged(focused);
143+ }
144+}
145+
146+
131unity::shell::launcher::QuickListModelInterface *MockLauncherItem::quickList() const
147unity::shell::launcher::QuickListModelInterface *MockLauncherItem::quickList() const
132{
148{
133 return m_quickList;
149 return m_quickList;
tests/mocks/Unity/Launcher/MockLauncherItem.h+4
@@ -52,6 +52,9 @@ public:
52 int count() const;
52 int count() const;
53 void setCount(int count);
53 void setCount(int count);
54
54
55+ bool focused() const;
56+ void setFocused(bool focused);
57+
55 unity::shell::launcher::QuickListModelInterface *quickList() const;
58 unity::shell::launcher::QuickListModelInterface *quickList() const;
56
59
57private:
60private:
@@ -64,6 +67,7 @@ private:
64 bool m_recent;
67 bool m_recent;
65 int m_progress;
68 int m_progress;
66 int m_count;
69 int m_count;
70+ bool m_focused;
67 MockQuickListModel *m_quickList;
71 MockQuickListModel *m_quickList;
68};
72};
69
73
tests/mocks/Unity/Launcher/MockLauncherModel.cpp+9
@@ -25,6 +25,7 @@ MockLauncherModel::MockLauncherModel(QObject* parent): LauncherModelInterface(pa
25 MockLauncherItem *item = new MockLauncherItem("phone-app", "/usr/share/applications/phone-app.desktop", "Phone", "phone-app", this);
25 MockLauncherItem *item = new MockLauncherItem("phone-app", "/usr/share/applications/phone-app.desktop", "Phone", "phone-app", this);
26 item->setProgress(0);
26 item->setProgress(0);
27 m_list.append(item);
27 m_list.append(item);
28+ item->setFocused(true);
28 item = new MockLauncherItem("camera-app", "/usr/share/applications/camera-app.desktop", "Camera", "camera", this);
29 item = new MockLauncherItem("camera-app", "/usr/share/applications/camera-app.desktop", "Camera", "camera", this);
29 item->setProgress(10);
30 item->setProgress(10);
30 m_list.append(item);
31 m_list.append(item);
@@ -49,6 +50,7 @@ MockLauncherModel::MockLauncherModel(QObject* parent): LauncherModelInterface(pa
49 item = new MockLauncherItem("notes-app", "/usr/share/applications/notes-app.desktop", "Notepad", "notepad", this);
50 item = new MockLauncherItem("notes-app", "/usr/share/applications/notes-app.desktop", "Notepad", "notepad", this);
50 item->setProgress(50);
51 item->setProgress(50);
51 item->setCount(5);
52 item->setCount(5);
53+ item->setFocused(true);
52 m_list.append(item);
54 m_list.append(item);
53 item = new MockLauncherItem("calendar-app", "/usr/share/applications/calendar-app.desktop","Calendar", "calendar", this);
55 item = new MockLauncherItem("calendar-app", "/usr/share/applications/calendar-app.desktop","Calendar", "calendar", this);
54 m_list.append(item);
56 m_list.append(item);
@@ -85,6 +87,8 @@ QVariant MockLauncherModel::data(const QModelIndex& index, int role) const
85 return item->progress();
87 return item->progress();
86 case RoleCount:
88 case RoleCount:
87 return item->count();
89 return item->count();
90+ case RoleFocused:
91+ return item->focused();
88 }
92 }
89
93
90 return QVariant();
94 return QVariant();
@@ -180,3 +184,8 @@ void MockLauncherModel::setUser(const QString &username)
180 Q_UNUSED(username)
184 Q_UNUSED(username)
181 // TODO: implement this...
185 // TODO: implement this...
182}
186}
187+
188+void MockLauncherModel::applicationFocused(const QString &appId)
189+{
190+ Q_UNUSED(appId)
191+}
tests/mocks/Unity/Launcher/MockLauncherModel.h+1
@@ -44,6 +44,7 @@ public:
44 Q_INVOKABLE void requestRemove(const QString &appId);
44 Q_INVOKABLE void requestRemove(const QString &appId);
45 Q_INVOKABLE void quickListActionInvoked(const QString &appId, int actionIndex);
45 Q_INVOKABLE void quickListActionInvoked(const QString &appId, int actionIndex);
46 Q_INVOKABLE void setUser(const QString &username);
46 Q_INVOKABLE void setUser(const QString &username);
47+ Q_INVOKABLE void applicationFocused(const QString &appId);
47
48
48Q_SIGNALS:
49Q_SIGNALS:
49 void quickListTriggered(const QString &appId, int index);
50 void quickListTriggered(const QString &appId, int index);
tests/mocks/Unity/fake_applications_scope.cppnew file+68
@@ -0,0 +1,68 @@
1+/*
2+ * Copyright (C) 2013 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_applications_scope.h"
18+
19+static const gchar * categories_model_schema[] = {
20+ "s", //ID
21+ "s", // DISPLAY_NAME
22+ "s", // ICON_HINT
23+ "s", // RENDERER_NAME
24+ "a{sv}" // HINTS
25+};
26+
27+ApplicationsScope::ApplicationsScope(bool visible, QObject* parent)
28+ : Scope(parent)
29+{
30+ m_id = "applications.scope";
31+ m_name = "Applications";
32+ m_visible = visible;
33+ m_categories->setModel(createCategoriesModel());
34+}
35+
36+DeeModel* ApplicationsScope::createCategoriesModel()
37+{
38+ DeeModel* category_model = dee_sequence_model_new();
39+ dee_model_set_schema_full(category_model, categories_model_schema, G_N_ELEMENTS(categories_model_schema));
40+ GVariant* hints = g_variant_new_array(g_variant_type_element(G_VARIANT_TYPE_VARDICT), NULL, 0);
41+
42+ GVariant* children[1];
43+ children[0] = g_variant_new_dict_entry(g_variant_new_string("content-type"),
44+ g_variant_new_variant(g_variant_new_string("apps")));
45+ GVariant* recentHints = g_variant_new_array(g_variant_type_element(G_VARIANT_TYPE_VARDICT), children, 1);
46+ dee_model_append(category_model,
47+ "recent",
48+ "Recent",
49+ "gtk-apply",
50+ "special",
51+ recentHints);
52+
53+ dee_model_append(category_model,
54+ "installed",
55+ "Installed",
56+ "gtk-apply",
57+ "grid",
58+ hints);
59+
60+ dee_model_append(category_model,
61+ "suggested",
62+ "Suggested",
63+ "gtk-apply",
64+ "grid",
65+ hints);
66+
67+ return category_model;
68+}
tests/mocks/Unity/fake_applications_scope.hnew file+33
@@ -0,0 +1,33 @@
1+/*
2+ * Copyright (C) 2013 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_APPLICATIONS_SCOPE_H
18+#define FAKE_APPLICATIONS_SCOPE_H
19+
20+#include "fake_scope.h"
21+
22+class ApplicationsScope : public Scope
23+{
24+ Q_OBJECT
25+
26+public:
27+ ApplicationsScope(bool visible, QObject* parent = 0);
28+
29+private:
30+ DeeModel* createCategoriesModel();
31+};
32+
33+#endif // FAKE_APPLICATIONS_SCOPE_H
tests/mocks/Unity/fake_categories.cpp+84−12
@@ -24,11 +24,20 @@
24
24
25#define CATEGORY_COLUMN 2
25#define CATEGORY_COLUMN 2
26
26
27+// TODO: use something from libunity once it's public
28+enum CategoryColumn {
29+ ID,
30+ DISPLAY_NAME,
31+ ICON_HINT,
32+ RENDERER_NAME,
33+ HINTS
34+};
35+
27Categories::Categories(QObject* parent)
36Categories::Categories(QObject* parent)
28 : DeeListModel(parent)
37 : DeeListModel(parent)
29{
38{
30 // FIXME: need to clean up unused filters on countChanged
39 // FIXME: need to clean up unused filters on countChanged
31− m_roles[Categories::RoleId] = "id";
40+ m_roles[Categories::RoleCategoryId] = "categoryId";
32 m_roles[Categories::RoleName] = "name";
41 m_roles[Categories::RoleName] = "name";
33 m_roles[Categories::RoleIcon] = "icon";
42 m_roles[Categories::RoleIcon] = "icon";
34 m_roles[Categories::RoleRenderer] = "renderer";
43 m_roles[Categories::RoleRenderer] = "renderer";
@@ -36,7 +45,6 @@ Categories::Categories(QObject* parent)
36 m_roles[Categories::RoleHints] = "hints";
45 m_roles[Categories::RoleHints] = "hints";
37 m_roles[Categories::RoleResults] = "results";
46 m_roles[Categories::RoleResults] = "results";
38 m_roles[Categories::RoleCount] = "count";
47 m_roles[Categories::RoleCount] = "count";
39− m_roles[Categories::RoleCategoryIndex] = "categoryIndex";
40
48
41 // TODO This should not be needed but accumulatting the count changes
49 // TODO This should not be needed but accumulatting the count changes
42 // makes the visualization more stable and also makes crashes on fast
50 // makes the visualization more stable and also makes crashes on fast
@@ -74,6 +82,25 @@ Categories::onCountChanged()
74 }
82 }
75}
83}
76
84
85+void Categories::onRowCountChanged()
86+{
87+ QAbstractItemModel* model = qobject_cast<QAbstractItemModel*>(sender());
88+ // find the corresponding category index
89+ for (auto iter = m_overriddenCategories.begin(); iter != m_overriddenCategories.end(); ++iter) {
90+ if (iter.value() == model) {
91+ for (int i = 0; i < rowCount(); i++) {
92+ auto id = data(index(i), RoleCategoryId).toString();
93+ if (id != iter.key()) continue;
94+ QVector<int> roles;
95+ roles.append(RoleCount);
96+ QModelIndex changedIndex = index(i);
97+ Q_EMIT dataChanged(changedIndex, changedIndex, roles);
98+ break;
99+ }
100+ }
101+ }
102+}
103+
77void
104void
78Categories::onEmitCountChanged()
105Categories::onEmitCountChanged()
79{
106{
@@ -93,6 +120,41 @@ Categories::roleNames() const
93 return m_roles;
120 return m_roles;
94}
121}
95
122
123+void Categories::onOverrideModelDestroyed()
124+{
125+ QObject* model = sender();
126+ auto iter = m_overriddenCategories.begin();
127+ while (iter != m_overriddenCategories.end()) {
128+ if (iter.value() == model) {
129+ iter = m_overriddenCategories.erase(iter);
130+ continue;
131+ }
132+ ++iter;
133+ }
134+}
135+
136+void Categories::overrideResults(const QString& categoryId, QAbstractItemModel* model)
137+{
138+ m_overriddenCategories[categoryId] = model;
139+ // watch the model
140+ connect(model, &QObject::destroyed, this, &Categories::onOverrideModelDestroyed);
141+ connect(model, &QAbstractItemModel::rowsInserted, this, &Categories::onRowCountChanged);
142+ connect(model, &QAbstractItemModel::rowsRemoved, this, &Categories::onRowCountChanged);
143+ connect(model, &QAbstractItemModel::modelReset, this, &Categories::onRowCountChanged);
144+
145+ // emit the dataChanged signal if the category is already in the model
146+ for (int i = 0; i < rowCount(); i++) {
147+ auto id = data(index(i), RoleCategoryId).toString();
148+ if (id != categoryId) continue;
149+ QVector<int> roles;
150+ roles.append(RoleCount);
151+ roles.append(RoleResults);
152+ QModelIndex changedIndex = index(i);
153+ Q_EMIT dataChanged(changedIndex, changedIndex, roles);
154+ break;
155+ }
156+}
157+
96void Categories::setResultModel(DeeModel* model)
158void Categories::setResultModel(DeeModel* model)
97{
159{
98 // FIXME: should ref it
160 // FIXME: should ref it
@@ -154,27 +216,37 @@ Categories::data(const QModelIndex& index, int role) const
154 }
216 }
155
217
156 switch (role) {
218 switch (role) {
157− case RoleId:
219+ case RoleCategoryId:
158− return DeeListModel::data(index, 0); //ID
220+ return DeeListModel::data(index, CategoryColumn::ID);
159 case RoleName:
221 case RoleName:
160− return DeeListModel::data(index, 1); //DISPLAY_NAME
222+ return DeeListModel::data(index, CategoryColumn::DISPLAY_NAME);
161 case RoleIcon:
223 case RoleIcon:
162− return DeeListModel::data(index, 2); //ICON_HINT
224+ return DeeListModel::data(index, CategoryColumn::ICON_HINT);
163 case RoleRenderer:
225 case RoleRenderer:
164− return DeeListModel::data(index, 3); //RENDERER_NAME
226+ return DeeListModel::data(index, CategoryColumn::RENDERER_NAME);
165 case RoleContentType:
227 case RoleContentType:
166 {
228 {
167− auto hints = DeeListModel::data(index, 4).toHash();
229+ auto hints = DeeListModel::data(index, CategoryColumn::HINTS).toHash();
168− return hints.contains("content-type") ? hints["content-type"] : QVariant(QString("default"));
230+ return hints.contains("content-type") ? hints["content-type"] : QVariant(QString("default"));
169 }
231 }
170 case RoleHints:
232 case RoleHints:
171− return DeeListModel::data(index, 4); //HINTS
233+ return DeeListModel::data(index, CategoryColumn::HINTS);
172 case RoleResults:
234 case RoleResults:
235+ if (m_overriddenCategories.size() > 0)
236+ {
237+ auto id = DeeListModel::data(index, CategoryColumn::ID).toString();
238+ if (m_overriddenCategories.find(id) != m_overriddenCategories.end())
239+ return QVariant::fromValue(m_overriddenCategories[id]);
240+ }
173 return QVariant::fromValue(getFilter(index.row()));
241 return QVariant::fromValue(getFilter(index.row()));
174 case RoleCount:
242 case RoleCount:
243+ if (m_overriddenCategories.size() > 0)
244+ {
245+ auto id = DeeListModel::data(index, CategoryColumn::ID).toString();
246+ if (m_overriddenCategories.find(id) != m_overriddenCategories.end())
247+ return QVariant::fromValue(m_overriddenCategories[id]->rowCount());
248+ }
175 return QVariant::fromValue(getFilter(index.row())->rowCount());
249 return QVariant::fromValue(getFilter(index.row())->rowCount());
176− case RoleCategoryIndex:
177− return QVariant::fromValue(index.row());
178 default:
250 default:
179 return QVariant();
251 return QVariant();
180 }
252 }
tests/mocks/Unity/fake_categories.h+7−3
@@ -34,17 +34,18 @@ class Categories : public DeeListModel
34public:
34public:
35 Categories(QObject* parent = 0);
35 Categories(QObject* parent = 0);
36 enum Roles {
36 enum Roles {
37− RoleId,
37+ RoleCategoryId,
38 RoleName,
38 RoleName,
39 RoleIcon,
39 RoleIcon,
40 RoleRenderer,
40 RoleRenderer,
41 RoleContentType,
41 RoleContentType,
42 RoleHints,
42 RoleHints,
43 RoleResults,
43 RoleResults,
44− RoleCount,
44+ RoleCount
45− RoleCategoryIndex
46 };
45 };
47
46
47+ Q_INVOKABLE void overrideResults(const QString& categoryId, QAbstractItemModel* model);
48+
48 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
49 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
49
50
50 QHash<int, QByteArray> roleNames() const;
51 QHash<int, QByteArray> roleNames() const;
@@ -54,7 +55,9 @@ public:
54
55
55private Q_SLOTS:
56private Q_SLOTS:
56 void onCountChanged();
57 void onCountChanged();
58+ void onRowCountChanged();
57 void onEmitCountChanged();
59 void onEmitCountChanged();
60+ void onOverrideModelDestroyed();
58
61
59private:
62private:
60 DeeModel* getResultsForCategory(unsigned index) const;
63 DeeModel* getResultsForCategory(unsigned index) const;
@@ -64,6 +67,7 @@ private:
64 QTimer m_timer;
67 QTimer m_timer;
65 QSet<DeeListModel*> m_timerFilters;
68 QSet<DeeListModel*> m_timerFilters;
66 QHash<int, QByteArray> m_roles;
69 QHash<int, QByteArray> m_roles;
70+ QMap<QString, QAbstractItemModel*> m_overriddenCategories;
67 mutable QMap<int, DeeListModel*> m_filters;
71 mutable QMap<int, DeeListModel*> m_filters;
68};
72};
69
73
tests/mocks/Unity/fake_preview.cppnew file+66
@@ -0,0 +1,66 @@
1+/*
2+ * Copyright (C) 2013 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_preview.h"
18+
19+QString Preview::rendererName() const
20+{
21+ return "foo";
22+}
23+
24+QString Preview::title() const
25+{
26+ return "Title";
27+}
28+
29+QString Preview::subtitle() const
30+{
31+ return "Subtitle";
32+}
33+
34+QString Preview::description() const
35+{
36+ return "Description";
37+}
38+
39+QVariant Preview::actions()
40+{
41+ return QVariant();
42+}
43+
44+QVariant Preview::infoHints()
45+{
46+ return QVariant();
47+}
48+
49+QVariantMap Preview::infoHintsHash() const
50+{
51+ return QVariantMap();
52+}
53+
54+QString Preview::image() const
55+{
56+ return "";
57+}
58+
59+QString Preview::imageSourceUri() const
60+{
61+ return "";
62+}
63+
64+void Preview::execute(const QString& actionId, const QHash<QString, QVariant>& hints)
65+{
66+}
tests/mocks/Unity/fake_preview.hnew file+62
@@ -0,0 +1,62 @@
1+/*
2+ * Copyright (C) 2013 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_PREVIEW_H
18+#define FAKE_PREVIEW_H
19+
20+// Qt
21+#include <QObject>
22+#include <QString>
23+#include <QMetaType>
24+#include <QList>
25+#include <QVariantMap>
26+
27+class Q_DECL_EXPORT Preview : public QObject
28+{
29+ Q_OBJECT
30+
31+ Q_PROPERTY(QString rendererName READ rendererName NOTIFY previewChanged)
32+ Q_PROPERTY(QString title READ title NOTIFY previewChanged)
33+ Q_PROPERTY(QString subtitle READ subtitle NOTIFY previewChanged)
34+ Q_PROPERTY(QString description READ description NOTIFY previewChanged)
35+ Q_PROPERTY(QVariant actions READ actions NOTIFY previewChanged)
36+ Q_PROPERTY(QVariant infoHints READ infoHints NOTIFY previewChanged)
37+ Q_PROPERTY(QVariantMap infoMap READ infoHintsHash NOTIFY previewChanged)
38+ Q_PROPERTY(QString image READ image NOTIFY previewChanged)
39+ Q_PROPERTY(QString imageSourceUri READ imageSourceUri NOTIFY previewChanged)
40+
41+public:
42+ explicit Preview(QObject *parent = 0);
43+
44+ QString rendererName() const;
45+ QString title() const;
46+ QString subtitle() const;
47+ QString description() const;
48+ QVariant actions();
49+ QVariant infoHints();
50+ QVariantMap infoHintsHash() const;
51+ QString image() const;
52+ QString imageSourceUri() const;
53+
54+ Q_INVOKABLE void execute(const QString& actionId, const QHash<QString, QVariant>& hints);
55+
56+Q_SIGNALS:
57+ void previewChanged();
58+};
59+
60+Q_DECLARE_METATYPE(Preview *)
61+
62+#endif // FAKE_PREVIEW_H
tests/mocks/Unity/fake_scope.cpp+33−9
@@ -20,6 +20,8 @@
20#include <dee.h>
20#include <dee.h>
21#include "paths.h"
21#include "paths.h"
22
22
23+#include "fake_preview.h"
24+
23static DeeModel* create_categories_model(unsigned category_count);
25static DeeModel* create_categories_model(unsigned category_count);
24static DeeModel* create_results_model(unsigned category_count, unsigned result_count);
26static DeeModel* create_results_model(unsigned category_count, unsigned result_count);
25
27
@@ -127,6 +129,36 @@ void Scope::setNoResultsHint(const QString& str) {
127 }
129 }
128}
130}
129
131
132+void Scope::activate(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
133+ const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
134+ const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata)
135+{
136+ Q_UNUSED(uri);
137+ Q_UNUSED(icon_hint);
138+ Q_UNUSED(category);
139+ Q_UNUSED(result_type);
140+ Q_UNUSED(mimetype);
141+ Q_UNUSED(title);
142+ Q_UNUSED(comment);
143+ Q_UNUSED(dnd_uri);
144+ Q_UNUSED(metadata);
145+}
146+
147+void Scope::preview(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
148+ const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
149+ const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata)
150+{
151+ Q_UNUSED(uri);
152+ Q_UNUSED(icon_hint);
153+ Q_UNUSED(category);
154+ Q_UNUSED(result_type);
155+ Q_UNUSED(mimetype);
156+ Q_UNUSED(title);
157+ Q_UNUSED(comment);
158+ Q_UNUSED(dnd_uri);
159+ Q_UNUSED(metadata);
160+}
161+
130static const gchar * categories_model_schema[] = {
162static const gchar * categories_model_schema[] = {
131 "s", //ID
163 "s", //ID
132 "s", // DISPLAY_NAME
164 "s", // DISPLAY_NAME
@@ -168,14 +200,6 @@ static const gchar * results_model_schema[] = {
168 "a{sv}" // METADATA
200 "a{sv}" // METADATA
169};
201};
170
202
171−static const gchar * icons[] = {
172− "Applications.png",
173− "Home.png",
174− "Music.png",
175− "People.png",
176− "Videos.png",
177−};
178−
179DeeModel* create_results_model(unsigned category_count, unsigned result_count) {
203DeeModel* create_results_model(unsigned category_count, unsigned result_count) {
180 DeeModel* results_model = dee_sequence_model_new();
204 DeeModel* results_model = dee_sequence_model_new();
181 dee_model_set_schema_full(results_model, results_model_schema, G_N_ELEMENTS(results_model_schema));
205 dee_model_set_schema_full(results_model, results_model_schema, G_N_ELEMENTS(results_model_schema));
@@ -187,7 +211,7 @@ DeeModel* create_results_model(unsigned category_count, unsigned result_count) {
187
211
188 dee_model_append(results_model,
212 dee_model_append(results_model,
189 ("uri://result."+std::to_string(i)).c_str(),
213 ("uri://result."+std::to_string(i)).c_str(),
190− (shellAppDirectory() + "Dash/graphics/scopeIcons/" + (icons[i%G_N_ELEMENTS(icons)])).toLatin1().data(),
214+ (shellAppDirectory() + "graphics/applicationIcons/dash.png").toLatin1().data(),
191 category,
215 category,
192 0,
216 0,
193 "application/x-desktop",
217 "application/x-desktop",
tests/mocks/Unity/fake_scope.h+15−1
@@ -21,6 +21,8 @@
21#include <QObject>
21#include <QObject>
22#include "fake_categories.h"
22#include "fake_categories.h"
23
23
24+class Preview;
25+
24class Scope : public QObject
26class Scope : public QObject
25{
27{
26 Q_OBJECT
28 Q_OBJECT
@@ -63,6 +65,13 @@ public:
63 void setNoResultsHint(const QString& hint);
65 void setNoResultsHint(const QString& hint);
64 void setFormFactor(const QString& form_factor);
66 void setFormFactor(const QString& form_factor);
65
67
68+ Q_INVOKABLE void activate(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
69+ const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
70+ const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata);
71+ Q_INVOKABLE void preview(const QVariant &uri, const QVariant &icon_hint, const QVariant &category,
72+ const QVariant &result_type, const QVariant &mimetype, const QVariant &title,
73+ const QVariant &comment, const QVariant &dnd_uri, const QVariant &metadata);
74+
66Q_SIGNALS:
75Q_SIGNALS:
67 void idChanged(const QString&);
76 void idChanged(const QString&);
68 void nameChanged(const QString&);
77 void nameChanged(const QString&);
@@ -78,7 +87,12 @@ Q_SIGNALS:
78 void noResultsHintChanged();
87 void noResultsHintChanged();
79 void formFactorChanged();
88 void formFactorChanged();
80
89
81−private:
90+ // signals triggered by activate(..) or preview(..) requests.
91+ void previewReady(Preview *preview);
92+ void activateApplication(const QString &desktop);
93+
94+protected:
95+
82 QString m_id;
96 QString m_id;
83 QString m_iconHint;
97 QString m_iconHint;
84 QString m_description;
98 QString m_description;
tests/mocks/Unity/fake_scopes.cpp+4−1
@@ -19,6 +19,9 @@
19// Self
19// Self
20#include "fake_scopes.h"
20#include "fake_scopes.h"
21
21
22+// Local
23+#include "fake_applications_scope.h"
24+
22// TODO: Implement remaining pieces, like Categories (i.e. LensView now gives warnings)
25// TODO: Implement remaining pieces, like Categories (i.e. LensView now gives warnings)
23
26
24// Qt
27// Qt
@@ -53,7 +56,7 @@ void Scopes::updateScopes()
53 addScope(new Scope("MockScope1", "People", true, this));
56 addScope(new Scope("MockScope1", "People", true, this));
54 addScope(new Scope("MockScope2", "Music", false, this));
57 addScope(new Scope("MockScope2", "Music", false, this));
55 addScope(new Scope("home.scope", "Home", true, this));
58 addScope(new Scope("home.scope", "Home", true, this));
56− addScope(new Scope("applications.scope", "Applications", true, this));
59+ addScope(new ApplicationsScope(true, this));
57 addScope(new Scope("MockScope5", "Videos", true, this));
60 addScope(new Scope("MockScope5", "Videos", true, this));
58
61
59 if (!m_loaded) {
62 if (!m_loaded) {
tests/plugins/AccountsService/CMakeLists.txt+1−1
@@ -25,7 +25,7 @@ qt5_use_modules(mock-server Core DBus)
25
25
26add_executable(test-accountsservice
26add_executable(test-accountsservice
27 ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsService.cpp
27 ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsService.cpp
28− ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsBindings.cpp
28+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
29 client.cpp
29 client.cpp
30 )
30 )
31qt5_use_modules(test-accountsservice Core DBus Test)
31qt5_use_modules(test-accountsservice Core DBus Test)
tests/plugins/AccountsService/client.cpp+11−11
@@ -17,8 +17,8 @@
17 * Authored by: Michael Terry <michael.terry@canonical.com>
17 * Authored by: Michael Terry <michael.terry@canonical.com>
18 */
18 */
19
19
20−#include "AccountsBindings.h"
21#include "AccountsService.h"
20#include "AccountsService.h"
21+#include "AccountsServiceDBusAdaptor.h"
22#include <QSignalSpy>
22#include <QSignalSpy>
23#include <QTest>
23#include <QTest>
24
24
@@ -31,28 +31,28 @@ private Q_SLOTS:
31 void testInvalids()
31 void testInvalids()
32 {
32 {
33 // Test various invalid calls
33 // Test various invalid calls
34− AccountsService session;
34+ AccountsServiceDBusAdaptor session;
35 QCOMPARE(session.getUserProperty("NOPE", "com.canonical.unity.AccountsService", "demo-edges"), QVariant());
35 QCOMPARE(session.getUserProperty("NOPE", "com.canonical.unity.AccountsService", "demo-edges"), QVariant());
36 QCOMPARE(session.getUserProperty("testuser", "com.canonical.unity.AccountsService", "NOPE"), QVariant());
36 QCOMPARE(session.getUserProperty("testuser", "com.canonical.unity.AccountsService", "NOPE"), QVariant());
37 }
37 }
38
38
39− void testGetSetService()
39+ void testGetSetServiceDBusAdaptor()
40 {
40 {
41− AccountsService session;
41+ AccountsServiceDBusAdaptor session;
42 session.setUserProperty("testuser", "com.canonical.unity.AccountsService", "demo-edges", QVariant(true));
42 session.setUserProperty("testuser", "com.canonical.unity.AccountsService", "demo-edges", QVariant(true));
43 QCOMPARE(session.getUserProperty("testuser", "com.canonical.unity.AccountsService", "demo-edges"), QVariant(true));
43 QCOMPARE(session.getUserProperty("testuser", "com.canonical.unity.AccountsService", "demo-edges"), QVariant(true));
44 session.setUserProperty("testuser", "com.canonical.unity.AccountsService", "demo-edges", QVariant(false));
44 session.setUserProperty("testuser", "com.canonical.unity.AccountsService", "demo-edges", QVariant(false));
45 QCOMPARE(session.getUserProperty("testuser", "com.canonical.unity.AccountsService", "demo-edges"), QVariant(false));
45 QCOMPARE(session.getUserProperty("testuser", "com.canonical.unity.AccountsService", "demo-edges"), QVariant(false));
46 }
46 }
47
47
48− void testGetSetBindings()
48+ void testGetSetService()
49 {
49 {
50− AccountsBindings bindings;
50+ AccountsService session;
51− bindings.setUser("testuser");
51+ session.setUser("testuser");
52− bindings.setDemoEdges(true);
52+ session.setDemoEdges(true);
53− QCOMPARE(bindings.getDemoEdges(), true);
53+ QCOMPARE(session.getDemoEdges(), true);
54− bindings.setDemoEdges(false);
54+ session.setDemoEdges(false);
55− QCOMPARE(bindings.getDemoEdges(), false);
55+ QCOMPARE(session.getDemoEdges(), false);
56 }
56 }
57};
57};
58
58
tests/plugins/Unity/Launcher/CMakeLists.txt+41−4
@@ -1,22 +1,59 @@
1+pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
2+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=2)
3+
1include_directories(
4include_directories(
2 ${CMAKE_CURRENT_BINARY_DIR}
5 ${CMAKE_CURRENT_BINARY_DIR}
3 ${CMAKE_SOURCE_DIR}/plugins/AccountsService
6 ${CMAKE_SOURCE_DIR}/plugins/AccountsService
4 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher
7 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher
5 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/backend
8 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/backend
9+ ${GSETTINGS_QT_INCLUDE_DIRS}
6 )
10 )
7
11
8add_definitions(-DSM_BUSNAME=sessionBus)
12add_definitions(-DSM_BUSNAME=sessionBus)
9add_definitions(-DSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}")
13add_definitions(-DSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}")
14+add_definitions(-DLAUNCHER_TESTING)
10
15
16+### LauncherBackendTest
11−set(testCommand ${CMAKE_CURRENT_BINARY_DIR}/launcherbackendtestExec
17+set(testBackendCommand ${CMAKE_CURRENT_BINARY_DIR}/launcherbackendtestExec
12 -o ${CMAKE_BINARY_DIR}/launcherbackendtest.xml,xunitxml
18 -o ${CMAKE_BINARY_DIR}/launcherbackendtest.xml,xunitxml
13 -o -,txt)
19 -o -,txt)
14−add_test(NAME launcherbackendtest COMMAND ${testCommand})
20+add_test(NAME launcherbackendtest COMMAND ${testBackendCommand})
15−add_custom_target(launcherbackendtest ${testCommand})
21+add_custom_target(launcherbackendtest ${testBackendCommand})
16add_executable(launcherbackendtestExec
22add_executable(launcherbackendtestExec
17 launcherbackendtest.cpp
23 launcherbackendtest.cpp
18− ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsService.cpp
24+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
19 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/backend/launcherbackend.cpp
25 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/backend/launcherbackend.cpp
20 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/common/quicklistentry.cpp
26 ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/common/quicklistentry.cpp
21 )
27 )
28+target_link_libraries(launcherbackendtestExec ${GSETTINGS_QT_LDFLAGS})
22qt5_use_modules(launcherbackendtestExec Test Core DBus)
29qt5_use_modules(launcherbackendtestExec Test Core DBus)
30+
31+### LauncherModelTest
32+set(testModelCommand ${CMAKE_CURRENT_BINARY_DIR}/launchermodeltestExec
33+ -o ${CMAKE_BINARY_DIR}/launchermodeltest.xml,xunitxml
34+ -o -,txt)
35+add_test(NAME launchermodeltest COMMAND ${testModelCommand})
36+add_custom_target(launchermodeltest ${testModelCommand})
37+add_executable(launchermodeltestExec
38+ launchermodeltest.cpp
39+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/launchermodel.cpp
40+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/launcheritem.cpp
41+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/quicklistmodel.cpp
42+ ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
43+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/backend/launcherbackend.cpp
44+ ${CMAKE_SOURCE_DIR}/plugins/Unity/Launcher/common/quicklistentry.cpp
45+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
46+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
47+ ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/QuickListModelInterface.h
48+ )
49+target_link_libraries(launchermodeltestExec ${GSETTINGS_QT_LDFLAGS} )
50+qt5_use_modules(launchermodeltestExec Test Core DBus)
51+
52+# copy .desktop files into build directory for shadow builds
53+file(GLOB DESKTOP_FILES *.desktop)
54+
55+foreach(DESKTOP_FILE ${DESKTOP_FILES})
56+ file(COPY "${DESKTOP_FILE}"
57+ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
58+ )
59+endforeach()
tests/plugins/Unity/Launcher/launcherbackendtest.cpp+14−48
@@ -20,7 +20,6 @@
20#include "launcherbackend.h"
20#include "launcherbackend.h"
21
21
22#include <QtTest>
22#include <QtTest>
23−#include <QDebug>
24
23
25class LauncherBackendTest : public QObject
24class LauncherBackendTest : public QObject
26{
25{
@@ -31,62 +30,29 @@ private Q_SLOTS:
31 {
30 {
32 LauncherBackend backend(false);
31 LauncherBackend backend(false);
33
32
34− backend.setStoredApplications(QStringList() << "relative.path" << "/full/path");
33+ backend.setStoredApplications(QStringList() << "rel-icon" << "abs-icon" << "invalid");
35− QCOMPARE(backend.storedApplications(), QStringList() << "/usr/share/applications/relative.path" << "/full/path");
34+ QCOMPARE(backend.storedApplications(), QStringList() << "rel-icon" << "abs-icon");
36−
37− QCOMPARE(backend.desktopFile("one.desktop"), QString("/usr/share/applications/one.desktop"));
38− QCOMPARE(backend.desktopFile("two"), QString("/usr/share/applications/two"));
39− QCOMPARE(backend.desktopFile("/full"), QString("/full"));
40−
41− QCOMPARE(backend.desktopFile("/usr/share/applications/one.desktop"), QString("/usr/share/applications/one.desktop"));
42− }
43−
44− void testDesktopReading()
45− {
46− LauncherBackend backend(false);
47−
48− QCOMPARE(backend.displayName(SRCDIR "/rel-icon.desktop"), QString("Relative Icon"));
49− QCOMPARE(backend.icon(SRCDIR "/rel-icon.desktop"), QString("image://gicon/rel-icon"));
50−
51− QCOMPARE(backend.displayName(SRCDIR "/abs-icon.desktop"), QString("Absolute Icon"));
52− QCOMPARE(backend.icon(SRCDIR "/abs-icon.desktop"), QString("/path/to/icon.png"));
53−
54− QCOMPARE(backend.displayName(SRCDIR "/no-icon.desktop"), QString("No Icon"));
55− QCOMPARE(backend.icon(SRCDIR "/no-icon.desktop"), QString(""));
56−
57− QCOMPARE(backend.displayName(SRCDIR "/no-name.desktop"), QString(""));
58− QCOMPARE(backend.icon(SRCDIR "/no-name.desktop"), QString("image://gicon/no-name"));
59−
60− QCOMPARE(backend.displayName(SRCDIR "/no-exist.desktop"), QString(""));
61− QCOMPARE(backend.icon(SRCDIR "/no-exist.desktop"), QString(""));
62 }
35 }
63
36
64 void testPinning()
37 void testPinning()
65 {
38 {
66 LauncherBackend backend(false);
39 LauncherBackend backend(false);
67
40
68− // Confirm that default entries are all pinned
69− auto defaultApps = backend.storedApplications();
70− QVERIFY(defaultApps.size() > 0);
71− for (auto app: defaultApps) {
72− QCOMPARE(backend.isPinned(app), true);
73− }
74−
75− backend.setStoredApplications(QStringList() << "one" << "two");
41+ backend.setStoredApplications(QStringList() << "rel-icon" << "abs-icon");
76− QCOMPARE(backend.isPinned("one"), false);
42+ QCOMPARE(backend.isPinned("rel-icon"), false);
77− QCOMPARE(backend.isPinned("two"), false);
43+ QCOMPARE(backend.isPinned("abs-icon"), false);
78
44
79− backend.setPinned("two", true);
45+ backend.setPinned("rel-icon", true);
80− QCOMPARE(backend.isPinned("two"), true);
46+ QCOMPARE(backend.isPinned("rel-icon"), true);
81
47
82− backend.setStoredApplications(QStringList() << "one" << "two" << "three");
48+ backend.setStoredApplications(QStringList() << "rel-icon" << "abs-icon" << "no-name");
83− QCOMPARE(backend.isPinned("two"), true);
49+ QCOMPARE(backend.isPinned("rel-icon"), true);
84− QCOMPARE(backend.isPinned("three"), false);
50+ QCOMPARE(backend.isPinned("no-name"), false);
85
51
86− backend.setPinned("three", true);
52+ backend.setPinned("no-name", true);
87− backend.setStoredApplications(QStringList() << "one" << "two");
53+ backend.setStoredApplications(QStringList() << "rel-icon" << "abs-icon");
88− QCOMPARE(backend.isPinned("two"), true);
54+ QCOMPARE(backend.isPinned("rel-icon"), true);
89− QCOMPARE(backend.isPinned("three"), false); // doesn't exist anymore!
55+ QCOMPARE(backend.isPinned("no-name"), false); // doesn't exist anymore!
90 }
56 }
91};
57};
92
58
tests/plugins/Unity/Launcher/launchermodeltest.cppnew file+146
@@ -0,0 +1,146 @@
1+/*
2+ * Copyright 2013 Canonical Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU Lesser General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors:
17+ * Michael Zanetti <michael.zanetti@canonical.com>
18+ */
19+
20+// unity-api
21+#include <unity/shell/launcher/LauncherModelInterface.h>
22+
23+#include "launcheritem.h"
24+#include "launchermodel.h"
25+
26+#include <QtTest>
27+
28+class LauncherModelTest : public QObject
29+{
30+ Q_OBJECT
31+
32+private:
33+ LauncherModel *launcherModel;
34+
35+private Q_SLOTS:
36+
37+ void initTestCase() {
38+ launcherModel = new LauncherModel(this);
39+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 0);
40+ }
41+
42+ void init() {
43+ qDebug() << "init";
44+ launcherModel->applicationFocused("abs-icon");
45+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
46+
47+ launcherModel->applicationFocused("no-icon.desktop");
48+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
49+
50+ launcherModel->applicationFocused(QString());
51+ }
52+
53+ void cleanup() {
54+ while (launcherModel->rowCount(QModelIndex()) > 0) {
55+ launcherModel->requestRemove(launcherModel->get(0)->appId());
56+ }
57+ }
58+
59+ void testMove() {
60+ QCOMPARE(launcherModel->get(0)->pinned(), false);
61+ QCOMPARE(launcherModel->get(1)->pinned(), false);
62+
63+ LauncherItemInterface *item0BeforeMove = launcherModel->get(0);
64+ LauncherItemInterface *item1BeforeMove = launcherModel->get(1);
65+ launcherModel->move(1, 0);
66+
67+ QCOMPARE(item0BeforeMove, launcherModel->get(1));
68+ QCOMPARE(item1BeforeMove, launcherModel->get(0));
69+
70+ // moved item must be pinned now
71+ QCOMPARE(item0BeforeMove->pinned(), false);
72+ QCOMPARE(item1BeforeMove->pinned(), true);
73+ }
74+
75+ void testPinning() {
76+ QCOMPARE(launcherModel->get(0)->pinned(), false);
77+ QCOMPARE(launcherModel->get(1)->pinned(), false);
78+ launcherModel->pin(launcherModel->get(0)->appId());
79+ QCOMPARE(launcherModel->get(0)->pinned(), true);
80+ QCOMPARE(launcherModel->get(1)->pinned(), false);
81+ }
82+
83+ void testRemove() {
84+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
85+ launcherModel->requestRemove(launcherModel->get(0)->appId());
86+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
87+ }
88+
89+ void testQuickListPinningRemoving() {
90+ // we start with 2 unpinned items
91+ QCOMPARE(launcherModel->get(0)->pinned(), false);
92+ QCOMPARE(launcherModel->get(1)->pinned(), false);
93+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
94+
95+ // find the Pin item in the quicklist
96+ QuickListModel *model = qobject_cast<QuickListModel*>(launcherModel->get(0)->quickList());
97+ int pinActionIndex = -1;
98+ for (int i = 0; i < model->rowCount(QModelIndex()); ++i) {
99+ if (model->get(i).actionId() == "pin_item") {
100+ pinActionIndex = i;
101+ break;
102+ }
103+ }
104+ QVERIFY(pinActionIndex >= 0);
105+
106+ // trigger pin item quicklist action => Item must be pinned now.
107+ launcherModel->quickListActionInvoked(launcherModel->get(0)->appId(), pinActionIndex);
108+ QCOMPARE(launcherModel->get(0)->pinned(), true);
109+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
110+
111+ // quicklist needs to transform to remove item. trigger it and check it item goes away
112+ launcherModel->quickListActionInvoked(launcherModel->get(0)->appId(), pinActionIndex);
113+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
114+ }
115+
116+ void testApplicationFocused() {
117+ // all apps unfocused at beginning...
118+ QCOMPARE(launcherModel->get(0)->focused(), false);
119+ QCOMPARE(launcherModel->get(1)->focused(), false);
120+
121+ launcherModel->applicationFocused("abs-icon");
122+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
123+ QCOMPARE(launcherModel->get(0)->focused(), true);
124+ QCOMPARE(launcherModel->get(1)->focused(), false);
125+
126+ launcherModel->applicationFocused("no-icon");
127+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
128+ QCOMPARE(launcherModel->get(0)->focused(), false);
129+ QCOMPARE(launcherModel->get(1)->focused(), true);
130+
131+ launcherModel->applicationFocused("rel-icon");
132+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 3);
133+ QCOMPARE(launcherModel->get(0)->focused(), false);
134+ QCOMPARE(launcherModel->get(1)->focused(), false);
135+ QCOMPARE(launcherModel->get(2)->focused(), true);
136+
137+ launcherModel->applicationFocused(QString());
138+ QCOMPARE(launcherModel->rowCount(QModelIndex()), 3);
139+ QCOMPARE(launcherModel->get(0)->focused(), false);
140+ QCOMPARE(launcherModel->get(1)->focused(), false);
141+ QCOMPARE(launcherModel->get(2)->focused(), false);
142+ }
143+};
144+
145+QTEST_GUILESS_MAIN(LauncherModelTest)
146+#include "launchermodeltest.moc"
tests/plugins/Unity/filtersbindingstest.cpp+61−30
@@ -65,17 +65,17 @@ DeeModel* FiltersBindingsTest::createFilterModel()
65
65
66void FiltersBindingsTest::createMultiRangeFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount)
66void FiltersBindingsTest::createMultiRangeFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount)
67{
67{
68− createFilter(model, "filter-multirange", id, name, optionCount);
68+ createFilter(model, "filter-multirange", id, name, optionCount, true);
69}
69}
70
70
71void FiltersBindingsTest::createRadioOptionFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount)
71void FiltersBindingsTest::createRadioOptionFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount)
72{
72{
73− createFilter(model, "filter-radiooption", id, name, optionCount);
73+ createFilter(model, "filter-radiooption", id, name, optionCount, true);
74}
74}
75
75
76void FiltersBindingsTest::createCheckOptionFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount)
76void FiltersBindingsTest::createCheckOptionFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount)
77{
77{
78− createFilter(model, "filter-checkoption", id, name, optionCount);
78+ createFilter(model, "filter-checkoption", id, name, optionCount, true);
79}
79}
80
80
81void FiltersBindingsTest::createRatingsFilter(DeeModel *model, const std::string &id, const std::string &name)
81void FiltersBindingsTest::createRatingsFilter(DeeModel *model, const std::string &id, const std::string &name)
@@ -90,7 +90,7 @@ void FiltersBindingsTest::createRatingsFilter(DeeModel *model, const std::string
90 GVariant *children[2];
90 GVariant *children[2];
91 GVariant *key1 = g_variant_new_string("show-all-button");
91 GVariant *key1 = g_variant_new_string("show-all-button");
92 GVariant *key2 = g_variant_new_string("rating");
92 GVariant *key2 = g_variant_new_string("rating");
93− children[0] = g_variant_new_dict_entry(key1, g_variant_new_variant(g_variant_new_boolean(false)));
93+ children[0] = g_variant_new_dict_entry(key1, g_variant_new_variant(g_variant_new_boolean(true)));
94 children[1] = g_variant_new_dict_entry(key2, g_variant_new_variant(g_variant_new_double(0.0f)));
94 children[1] = g_variant_new_dict_entry(key2, g_variant_new_variant(g_variant_new_double(0.0f)));
95 auto fhints = g_variant_new_array(G_VARIANT_TYPE("{sv}"), children, 2);
95 auto fhints = g_variant_new_array(G_VARIANT_TYPE("{sv}"), children, 2);
96
96
@@ -102,7 +102,7 @@ void FiltersBindingsTest::createRatingsFilter(DeeModel *model, const std::string
102 dee_model_append_row(model, row);
102 dee_model_append_row(model, row);
103}
103}
104
104
105−void FiltersBindingsTest::createFilter(DeeModel *model, const std::string &renderer, const std::string &id, const std::string &name, int optionCount)
105+void FiltersBindingsTest::createFilter(DeeModel *model, const std::string &renderer, const std::string &id, const std::string &name, int optionCount, bool showAll)
106{
106{
107 GVariant* row[8];
107 GVariant* row[8];
108
108
@@ -114,7 +114,7 @@ void FiltersBindingsTest::createFilter(DeeModel *model, const std::string &rende
114 GVariant *children[2];
114 GVariant *children[2];
115 GVariant *key1 = g_variant_new_string("show-all-button");
115 GVariant *key1 = g_variant_new_string("show-all-button");
116 GVariant *key2 = g_variant_new_string("options");
116 GVariant *key2 = g_variant_new_string("options");
117− children[0] = g_variant_new_dict_entry(key1, g_variant_new_variant(g_variant_new_boolean(false)));
117+ children[0] = g_variant_new_dict_entry(key1, g_variant_new_variant(g_variant_new_boolean(showAll)));
118 children[1] = g_variant_new_dict_entry(key2, g_variant_new_variant(createOptions(optionCount)));
118 children[1] = g_variant_new_dict_entry(key2, g_variant_new_variant(createOptions(optionCount)));
119 auto fhints = g_variant_new_array(G_VARIANT_TYPE("{sv}"), children, 2);
119 auto fhints = g_variant_new_array(G_VARIANT_TYPE("{sv}"), children, 2);
120
120
@@ -143,9 +143,9 @@ void FiltersBindingsTest::testMultiRangeFilter()
143 auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
143 auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
144 QVERIFY(multi_filter != nullptr);
144 QVERIFY(multi_filter != nullptr);
145 auto options = multi_filter->options();
145 auto options = multi_filter->options();
146− QCOMPARE(options->rowCount(), 1);
146+ QCOMPARE(options->rowCount(), 2);
147
147
148− auto idx = options->index(0);
148+ auto idx = options->index(1);
149 QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
149 QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
150 QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
150 QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
151 QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
151 QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
@@ -168,9 +168,9 @@ void FiltersBindingsTest::testMultiRangeFilter()
168 auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
168 auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
169 QVERIFY(multi_filter != nullptr);
169 QVERIFY(multi_filter != nullptr);
170 auto options = multi_filter->options();
170 auto options = multi_filter->options();
171− QCOMPARE(options->rowCount(), 2);
171+ QCOMPARE(options->rowCount(), 3);
172
172
173− auto idx = options->index(0);
173+ auto idx = options->index(1);
174 QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
174 QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
175 QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
175 QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
176 QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
176 QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
@@ -181,10 +181,10 @@ void FiltersBindingsTest::testMultiRangeFilter()
181 QCOMPARE(icon_var.toString(), QString(""));
181 QCOMPARE(icon_var.toString(), QString(""));
182 QCOMPARE(active_var.toBool(), false);
182 QCOMPARE(active_var.toBool(), false);
183
183
184− AbstractFilterOption* opt1 = options->getRawOption(0);
184+ AbstractFilterOption* opt1 = options->getRawOption(1);
185 QCOMPARE(opt1->id(), QString("opt0"));
185 QCOMPARE(opt1->id(), QString("opt0"));
186
186
187− AbstractFilterOption* opt2 = options->getRawOption(1);
187+ AbstractFilterOption* opt2 = options->getRawOption(2);
188 QCOMPARE(opt2->id(), QString("opt1"));
188 QCOMPARE(opt2->id(), QString("opt1"));
189
189
190 delete multi_filter;
190 delete multi_filter;
@@ -199,18 +199,21 @@ void FiltersBindingsTest::testMultiRangeFilter()
199 auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
199 auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
200 QVERIFY(multi_filter != nullptr);
200 QVERIFY(multi_filter != nullptr);
201 auto options = multi_filter->options();
201 auto options = multi_filter->options();
202− QCOMPARE(options->rowCount(), 3);
202+ QCOMPARE(options->rowCount(), 4);
203+
204+ AbstractFilterOption* showAll = options->getRawOption(0);
205+ QVERIFY(showAll->id().startsWith("show_all::"));
203
206
204− AbstractFilterOption* opt0 = options->getRawOption(0);
207+ AbstractFilterOption* opt0 = options->getRawOption(1);
205 QCOMPARE(opt0->id(), QString("opt0"));
208 QCOMPARE(opt0->id(), QString("opt0"));
206
209
207− AbstractFilterOption* opt1 = options->getRawOption(1);
210+ AbstractFilterOption* opt1 = options->getRawOption(2);
208 QCOMPARE(opt1->id(), QString("opt1"));
211 QCOMPARE(opt1->id(), QString("opt1"));
209
212
210− AbstractFilterOption* opt2 = options->getRawOption(2);
213+ AbstractFilterOption* opt2 = options->getRawOption(3);
211 QCOMPARE(opt2->id(), QString("opt2"));
214 QCOMPARE(opt2->id(), QString("opt2"));
212
215
213− // verify combined filter options are bound to correct underlying unity options
216+ // verify filter options are bound to correct underlying unity options
214 auto core_multi_filter = std::dynamic_pointer_cast<unity::dash::MultiRangeFilter>(core_filter);
217 auto core_multi_filter = std::dynamic_pointer_cast<unity::dash::MultiRangeFilter>(core_filter);
215 QCOMPARE(QString::fromStdString(core_multi_filter->options()[0]->id()), QString("opt0"));
218 QCOMPARE(QString::fromStdString(core_multi_filter->options()[0]->id()), QString("opt0"));
216 QCOMPARE(QString::fromStdString(core_multi_filter->options()[1]->id()), QString("opt1"));
219 QCOMPARE(QString::fromStdString(core_multi_filter->options()[1]->id()), QString("opt1"));
@@ -274,7 +277,7 @@ void FiltersBindingsTest::testCheckOptionFilter()
274 auto check_filter = dynamic_cast<CheckOptionFilter*>(bind_filter);
277 auto check_filter = dynamic_cast<CheckOptionFilter*>(bind_filter);
275 QVERIFY(check_filter != nullptr);
278 QVERIFY(check_filter != nullptr);
276 auto options = check_filter->options();
279 auto options = check_filter->options();
277− QCOMPARE(options->rowCount(), 3);
280+ QCOMPARE(options->rowCount(), 4);
278
281
279 QCOMPARE(check_filter->id(), QString("f1"));
282 QCOMPARE(check_filter->id(), QString("f1"));
280 QCOMPARE(check_filter->name(), QString("Filter1"));
283 QCOMPARE(check_filter->name(), QString("Filter1"));
@@ -284,7 +287,7 @@ void FiltersBindingsTest::testCheckOptionFilter()
284 QCOMPARE(check_filter->collapsed(), false);
287 QCOMPARE(check_filter->collapsed(), false);
285 QCOMPARE(check_filter->filtering(), false);
288 QCOMPARE(check_filter->filtering(), false);
286
289
287− auto idx = options->index(0);
290+ auto idx = options->index(1);
288 QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
291 QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
289 QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
292 QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
290 QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
293 QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
@@ -295,7 +298,7 @@ void FiltersBindingsTest::testCheckOptionFilter()
295 QCOMPARE(icon_var.toString(), QString(""));
298 QCOMPARE(icon_var.toString(), QString(""));
296 QCOMPARE(active_var.toBool(), false);
299 QCOMPARE(active_var.toBool(), false);
297
300
298− idx = options->index(1);
301+ idx = options->index(2);
299 id_var = options->data(idx, GenericOptionsModel::RoleId);
302 id_var = options->data(idx, GenericOptionsModel::RoleId);
300 name_var = options->data(idx, GenericOptionsModel::RoleName);
303 name_var = options->data(idx, GenericOptionsModel::RoleName);
301 icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
304 icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
@@ -306,38 +309,55 @@ void FiltersBindingsTest::testCheckOptionFilter()
306 QCOMPARE(icon_var.toString(), QString(""));
309 QCOMPARE(icon_var.toString(), QString(""));
307 QCOMPARE(active_var.toBool(), false);
310 QCOMPARE(active_var.toBool(), false);
308
311
312+ AbstractFilterOption* showAll = options->getRawOption(0);
309− AbstractFilterOption* opt0 = options->getRawOption(0);
313+ AbstractFilterOption* opt0 = options->getRawOption(1);
310− AbstractFilterOption* opt1 = options->getRawOption(1);
314+ AbstractFilterOption* opt1 = options->getRawOption(2);
311− AbstractFilterOption* opt2 = options->getRawOption(2);
315+ AbstractFilterOption* opt2 = options->getRawOption(3);
312
316
317+ QSignalSpy showAllSpy(showAll, SIGNAL(activeChanged(bool)));
313 QSignalSpy opt0spy(opt0, SIGNAL(activeChanged(bool)));
318 QSignalSpy opt0spy(opt0, SIGNAL(activeChanged(bool)));
314 QSignalSpy opt1spy(opt1, SIGNAL(activeChanged(bool)));
319 QSignalSpy opt1spy(opt1, SIGNAL(activeChanged(bool)));
315 QSignalSpy opt2spy(opt2, SIGNAL(activeChanged(bool)));
320 QSignalSpy opt2spy(opt2, SIGNAL(activeChanged(bool)));
316 QSignalSpy dataChangedSpy(options, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
321 QSignalSpy dataChangedSpy(options, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
317
322
318 // test active property changes
323 // test active property changes
324+ QCOMPARE(showAll->active(), false);
319 QCOMPARE(opt0->active(), false);
325 QCOMPARE(opt0->active(), false);
320 QCOMPARE(opt1->active(), false);
326 QCOMPARE(opt1->active(), false);
321 QCOMPARE(opt2->active(), false);
327 QCOMPARE(opt2->active(), false);
322
328
323 opt0->setActive(true);
329 opt0->setActive(true);
330+ QCOMPARE(showAllSpy.count(), 0);
324 QCOMPARE(opt0spy.count(), 1);
331 QCOMPARE(opt0spy.count(), 1);
325 QCOMPARE(opt1spy.count(), 0);
332 QCOMPARE(opt1spy.count(), 0);
326 QCOMPARE(opt2spy.count(), 0);
333 QCOMPARE(opt2spy.count(), 0);
334+ QCOMPARE(showAll->active(), false);
327 QCOMPARE(opt0->active(), true);
335 QCOMPARE(opt0->active(), true);
328 QCOMPARE(opt1->active(), false);
336 QCOMPARE(opt1->active(), false);
329 QCOMPARE(opt2->active(), false);
337 QCOMPARE(opt2->active(), false);
330
338
331 opt1->setActive(true);
339 opt1->setActive(true);
340+ QCOMPARE(showAllSpy.count(), 0);
332 QCOMPARE(opt0spy.count(), 2);
341 QCOMPARE(opt0spy.count(), 2);
333 QCOMPARE(opt1spy.count(), 1);
342 QCOMPARE(opt1spy.count(), 1);
334 QCOMPARE(opt2spy.count(), 0);
343 QCOMPARE(opt2spy.count(), 0);
344+ QCOMPARE(showAll->active(), false);
335 QCOMPARE(opt0->active(), false);
345 QCOMPARE(opt0->active(), false);
336 QCOMPARE(opt1->active(), true);
346 QCOMPARE(opt1->active(), true);
337 QCOMPARE(opt2->active(), false);
347 QCOMPARE(opt2->active(), false);
338
348
339 QCOMPARE(dataChangedSpy.count(), 3);
349 QCOMPARE(dataChangedSpy.count(), 3);
340
350
351+ showAll->setActive(true);
352+ QCOMPARE(showAllSpy.count(), 1);
353+ QCOMPARE(opt0spy.count(), 2);
354+ QCOMPARE(opt1spy.count(), 2);
355+ QCOMPARE(opt2spy.count(), 0);
356+ QCOMPARE(showAll->active(), true);
357+ QCOMPARE(opt0->active(), false);
358+ QCOMPARE(opt1->active(), false);
359+ QCOMPARE(opt2->active(), false);
360+
341 delete check_filter;
361 delete check_filter;
342 }
362 }
343}
363}
@@ -357,7 +377,7 @@ void FiltersBindingsTest::testRadioOptionFilter()
357 auto radio_filter = dynamic_cast<RadioOptionFilter*>(bind_filter);
377 auto radio_filter = dynamic_cast<RadioOptionFilter*>(bind_filter);
358 QVERIFY(radio_filter != nullptr);
378 QVERIFY(radio_filter != nullptr);
359 auto options = radio_filter->options();
379 auto options = radio_filter->options();
360− QCOMPARE(options->rowCount(), 3);
380+ QCOMPARE(options->rowCount(), 4);
361
381
362 auto idx = options->index(0);
382 auto idx = options->index(0);
363 QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
383 QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
@@ -365,12 +385,23 @@ void FiltersBindingsTest::testRadioOptionFilter()
365 QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
385 QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
366 QVariant active_var = options->data(idx, GenericOptionsModel::RoleActive);
386 QVariant active_var = options->data(idx, GenericOptionsModel::RoleActive);
367
387
388+ QVERIFY(id_var.toString().startsWith("show_all::"));
389+ QVERIFY(name_var.toString().size() > 0);
390+ QCOMPARE(icon_var.toString(), QString(""));
391+ QCOMPARE(active_var.toBool(), false);
392+
393+ idx = options->index(1);
394+ id_var = options->data(idx, GenericOptionsModel::RoleId);
395+ name_var = options->data(idx, GenericOptionsModel::RoleName);
396+ icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
397+ active_var = options->data(idx, GenericOptionsModel::RoleActive);
398+
368 QCOMPARE(id_var.toString(), QString("opt0"));
399 QCOMPARE(id_var.toString(), QString("opt0"));
369 QCOMPARE(name_var.toString(), QString("Option 0"));
400 QCOMPARE(name_var.toString(), QString("Option 0"));
370 QCOMPARE(icon_var.toString(), QString(""));
401 QCOMPARE(icon_var.toString(), QString(""));
371 QCOMPARE(active_var.toBool(), false);
402 QCOMPARE(active_var.toBool(), false);
372
403
373− idx = options->index(1);
404+ idx = options->index(2);
374 id_var = options->data(idx, GenericOptionsModel::RoleId);
405 id_var = options->data(idx, GenericOptionsModel::RoleId);
375 name_var = options->data(idx, GenericOptionsModel::RoleName);
406 name_var = options->data(idx, GenericOptionsModel::RoleName);
376 icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
407 icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
@@ -381,9 +412,9 @@ void FiltersBindingsTest::testRadioOptionFilter()
381 QCOMPARE(icon_var.toString(), QString(""));
412 QCOMPARE(icon_var.toString(), QString(""));
382 QCOMPARE(active_var.toBool(), false);
413 QCOMPARE(active_var.toBool(), false);
383
414
384− AbstractFilterOption* opt0 = options->getRawOption(0);
415+ AbstractFilterOption* opt0 = options->getRawOption(1);
385− AbstractFilterOption* opt1 = options->getRawOption(1);
416+ AbstractFilterOption* opt1 = options->getRawOption(2);
386− AbstractFilterOption* opt2 = options->getRawOption(2);
417+ AbstractFilterOption* opt2 = options->getRawOption(3);
387
418
388 QSignalSpy opt0spy(opt0, SIGNAL(activeChanged(bool)));
419 QSignalSpy opt0spy(opt0, SIGNAL(activeChanged(bool)));
389 QSignalSpy opt1spy(opt1, SIGNAL(activeChanged(bool)));
420 QSignalSpy opt1spy(opt1, SIGNAL(activeChanged(bool)));
@@ -432,11 +463,11 @@ void FiltersBindingsTest::testRatingsFilter()
432 auto rating_filter = dynamic_cast<RatingsFilter*>(bind_filter);
463 auto rating_filter = dynamic_cast<RatingsFilter*>(bind_filter);
433 QVERIFY(rating_filter != nullptr);
464 QVERIFY(rating_filter != nullptr);
434 auto options = rating_filter->options();
465 auto options = rating_filter->options();
435− QCOMPARE(options->rowCount(), 5);
466+ QCOMPARE(options->rowCount(), 6);
436
467
437 RatingFilterOption* opt[5];
468 RatingFilterOption* opt[5];
438 for (int i = 0; i<5; i++) {
469 for (int i = 0; i<5; i++) {
439− opt[i] = dynamic_cast<RatingFilterOption *>(options->getRawOption(i));
470+ opt[i] = dynamic_cast<RatingFilterOption *>(options->getRawOption(i+1));
440 }
471 }
441
472
442 QSignalSpy opt0spy(opt[0], SIGNAL(activeChanged(bool)));
473 QSignalSpy opt0spy(opt[0], SIGNAL(activeChanged(bool)));
tests/plugins/Unity/filtersbindingstest.h+1−1
@@ -41,7 +41,7 @@ class FiltersBindingsTest : public QObject
41 void createCheckOptionFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount);
41 void createCheckOptionFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount);
42 void createRadioOptionFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount);
42 void createRadioOptionFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount);
43 void createRatingsFilter(DeeModel *model, const std::string &id, const std::string &name);
43 void createRatingsFilter(DeeModel *model, const std::string &id, const std::string &name);
44− void createFilter(DeeModel *model, const std::string &renderer, const std::string &id, const std::string &name, int optionCount);
44+ void createFilter(DeeModel *model, const std::string &renderer, const std::string &id, const std::string &name, int optionCount, bool showAll);
45};
45};
46
46
47#endif // FILTERSBINDINGSTEST_H
47#endif // FILTERSBINDINGSTEST_H
tests/qmltests/Launcher/tst_Launcher.qml+8
@@ -198,6 +198,14 @@ Item {
198 compare(findChild(delegate, "progressOverlay").visible, LauncherModel.get(i).progress >= 0)
198 compare(findChild(delegate, "progressOverlay").visible, LauncherModel.get(i).progress >= 0)
199 }
199 }
200 }
200 }
201+
202+ function test_focusedHighlight() {
203+ var launcherListView = findChild(launcher, "launcherListView");
204+ for (var i = 0; i < launcherListView.count; ++i) {
205+ var delegate = findChild(launcherListView, "launcherDelegate" + i)
206+ compare(findChild(delegate, "focusedHighlight").visible, LauncherModel.get(i).focused)
207+ }
208+ }
201 }
209 }
202
210
203 UT.UnityTestCase {
211 UT.UnityTestCase {