Merge lp:~lukas-kde/unity8/desktopFileActions into lp:unity8

Proposed by Lukáš Tinkl on 2015-11-02
Status: Work in progress
Proposed branch: lp:~lukas-kde/unity8/desktopFileActions
Merge into: lp:unity8
Diff against target: 1174 lines (+689/-83)
16 files modified
plugins/Unity/Launcher/CMakeLists.txt (+2/-0)
plugins/Unity/Launcher/dbusinterface.h (+1/-2)
plugins/Unity/Launcher/desktopfilehandler.cpp (+91/-40)
plugins/Unity/Launcher/desktopfilehandler.h (+17/-4)
plugins/Unity/Launcher/launcheritem.cpp (+7/-5)
plugins/Unity/Launcher/launcheritem.h (+3/-1)
plugins/Unity/Launcher/launchermodel.cpp (+26/-4)
plugins/Unity/Launcher/quicklistentry.cpp (+12/-4)
plugins/Unity/Launcher/quicklistentry.h (+4/-3)
plugins/Unity/Launcher/quicklistmodel.cpp (+0/-9)
plugins/Unity/Launcher/quicklistmodel.h (+1/-3)
tests/mocks/Unity/Launcher/MockLauncherModel.cpp (+3/-2)
tests/plugins/Unity/Launcher/CMakeLists.txt (+3/-1)
tests/plugins/Unity/Launcher/google-chrome.desktop (+222/-0)
tests/plugins/Unity/Launcher/launchermodeltest.cpp (+50/-5)
tests/plugins/Unity/Launcher/thunderbird.desktop (+247/-0)
To merge this branch: bzr merge lp:~lukas-kde/unity8/desktopFileActions
Reviewer Review Type Date Requested Status
Unity8 CI Bot continuous-integration Needs Fixing on 2016-06-20
Michael Zanetti (community) Needs Information on 2016-04-05
Albert Astals Cid (community) merges fine Abstain on 2016-03-15
PS Jenkins bot continuous-integration Needs Fixing on 2016-01-04
Michael Terry 2015-11-02 Needs Fixing on 2015-11-10
Review via email: mp+276408@code.launchpad.net

Commit Message

Extend launcher quick list items with extra actions from the .desktop file

Description of the Change

Extend launcher quick list items with extra actions coming from the respective .desktop file

DesktopFileHandler now parses extra action in the Actions or X-Ayatana-Desktop-Shortcuts groups, and adds them to the launcher item's quicklist.

For example, Google Chrome gets these extra actions: "New Window" or "New Anonymous Window", Libreoffice Calc: "New spreadsheet".

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

No

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

Yes

* Did you make sure that your branch does not contain spurious tags?

Yes

* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?

N/A

* If you changed the UI, has there been a design review?

N/A

To post a comment you must log in.
2013. By Lukáš Tinkl on 2015-11-05

merge trunk

PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2013
http://jenkins.qa.ubuntu.com/job/unity8-ci/6651/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5026
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/66/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1363
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/66
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1258
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1259
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/65
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/65
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-mako/4035
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5023
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5023/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/24929
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-mako/40/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/66
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/66/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/24928

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6651/rebuild

review: Needs Fixing (continuous-integration)
Michael Terry (mterry) wrote :

Comments inline. Haven't tested yet, this was just looking over the code.

review: Needs Fixing
2014. By Lukáš Tinkl on 2015-11-10

merge trunk

PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2014
http://jenkins.qa.ubuntu.com/job/unity8-ci/6693/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5105
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/108/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1405
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/108
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1300
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1301
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/107
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/107
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4087
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5114
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5114/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25065
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/12/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/108
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/108/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25066

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6693/rebuild

review: Needs Fixing (continuous-integration)
2015. By Lukáš Tinkl on 2015-11-10

fix issues pointed out in review

Lukáš Tinkl (lukas-kde) wrote :

> Comments inline. Haven't tested yet, this was just looking over the code.

Issues should be fixed, tests still passing

Michael Terry (mterry) wrote :

Thanks for addressing my nits! One further inline note and then bringing some bigger issues out to the comment thread.

First, startApplication is a no-op if the application is already running. We support desktop actions on already-running apps on the desktop. I assume the spec for this feature on Touch also supports desktop actions on already-running apps.

This will seemingly require plumbing changes to allow running an app twice with different arguments. Changes in qtmir at least, which should be coordinated with Gerry.

Second, I'd like to see a test that runs through the code that launches an app. Makes sure we do launch the app, with the right arguments, and ignore the first token (instead preferring the appId).

And it should cover the "app not running" case as well as the "app already running" case.

If you had such a test, you'd run into the first issue above.

review: Needs Fixing
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2015
http://jenkins.qa.ubuntu.com/job/unity8-ci/6695/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5107
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/110/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1407
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/110
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1302
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1303
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/109
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/109
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4089
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5116
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5116/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25070
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/13/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/110
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/110/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25068

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6695/rebuild

review: Needs Fixing (continuous-integration)
2016. By Lukáš Tinkl on 2015-11-10

parse and split the args using g_shell_parse_argv()

PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2016
http://jenkins.qa.ubuntu.com/job/unity8-ci/6697/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5112
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/112/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1409
    FAILURE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/112/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1304
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1305
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/111
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/111
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4092
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5121
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5121/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25078
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/15/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/112
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/112/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25077

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6697/rebuild

review: Needs Fixing (continuous-integration)
Albert Astals Cid (aacid) wrote :

Text conflict in tests/plugins/Unity/Launcher/launchermodeltest.cpp
1 conflicts encountered.

review: Needs Fixing
2017. By Lukáš Tinkl on 2015-11-20

merge trunk

Lukáš Tinkl (lukas-kde) wrote :

> Text conflict in tests/plugins/Unity/Launcher/launchermodeltest.cpp
> 1 conflicts encountered.

Fixed

Albert Astals Cid (aacid) :
review: Abstain (merges fine)
2018. By Lukáš Tinkl on 2015-11-30

merge trunk

2019. By Lukáš Tinkl on 2015-12-02

merge trunk

2020. By Lukáš Tinkl on 2016-01-04

merge trunk

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2020
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/32/
Executed test runs:

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-1-ci/32/rebuild

review: Needs Fixing (continuous-integration)
Albert Astals Cid (aacid) wrote :

Text conflict in plugins/Unity/Launcher/launcheritem.cpp
Text conflict in plugins/Unity/Launcher/launcheritem.h
Text conflict in plugins/Unity/Launcher/launchermodel.cpp
3 conflicts encountered.

review: Needs Fixing
2021. By Lukáš Tinkl on 2016-03-14

merge trunk, resolve conflicts

Albert Astals Cid (aacid) :
review: Abstain (merges fine)
Michael Zanetti (mzanetti) :
review: Needs Information
2022. By Lukáš Tinkl on 2016-05-12

merge trunk

2023. By Lukáš Tinkl on 2016-06-06

merge trunk

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2023
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1417/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/1883/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/1909
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1845
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1845
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/1845
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1836/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1836/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1836/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1836/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1836/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1836/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1836/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1836/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1836/console

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1417/rebuild

review: Needs Fixing (continuous-integration)
Albert Astals Cid (aacid) wrote :

Text conflict in plugins/Unity/Launcher/CMakeLists.txt
Text conflict in tests/plugins/Unity/Launcher/CMakeLists.txt
2 conflicts encountered.

2024. By Lukáš Tinkl on 2016-06-20

merge trunk, resolve conflicts

Lukáš Tinkl (lukas-kde) wrote :

Conflicts resolved

Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:2024
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1553/
Executed test runs:
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build/2065/console
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/2093
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2004
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2004
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2004
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1995/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1995/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1995/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1995/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1995/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1995/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1995/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1995/console
    FAILURE: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1995/console

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-unity8-ci/1553/rebuild

review: Needs Fixing (continuous-integration)
Albert Astals Cid (aacid) wrote :

No changes since more than 2 months, i'll put it as WiP

Unmerged revisions

2024. By Lukáš Tinkl on 2016-06-20

merge trunk, resolve conflicts

2023. By Lukáš Tinkl on 2016-06-06

merge trunk

2022. By Lukáš Tinkl on 2016-05-12

merge trunk

2021. By Lukáš Tinkl on 2016-03-14

merge trunk, resolve conflicts

2020. By Lukáš Tinkl on 2016-01-04

merge trunk

2019. By Lukáš Tinkl on 2015-12-02

merge trunk

2018. By Lukáš Tinkl on 2015-11-30

merge trunk

2017. By Lukáš Tinkl on 2015-11-20

merge trunk

2016. By Lukáš Tinkl on 2015-11-10

parse and split the args using g_shell_parse_argv()

2015. By Lukáš Tinkl on 2015-11-10

fix issues pointed out in review

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/Unity/Launcher/CMakeLists.txt'
2--- plugins/Unity/Launcher/CMakeLists.txt 2016-05-13 11:14:15 +0000
3+++ plugins/Unity/Launcher/CMakeLists.txt 2016-06-20 10:00:44 +0000
4@@ -1,4 +1,5 @@
5 pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=9)
6+pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)
7 pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
8
9 add_definitions(-DSM_BUSNAME=systemBus)
10@@ -36,6 +37,7 @@
11
12 target_link_libraries(UnityLauncher-qml
13 unity8-private
14+ ${GLIB_LDFLAGS}
15 ${GSETTINGS_QT_LDFLAGS}
16 ${GLIB_LIBRARIES}
17 )
18
19=== modified file 'plugins/Unity/Launcher/dbusinterface.h'
20--- plugins/Unity/Launcher/dbusinterface.h 2015-07-23 14:13:57 +0000
21+++ plugins/Unity/Launcher/dbusinterface.h 2016-06-20 10:00:44 +0000
22@@ -29,7 +29,7 @@
23 DBusInterface(LauncherModel *parent);
24 ~DBusInterface() = default;
25
26- // QDBusVirtualObject implementaition
27+ // QDBusVirtualObject implementation
28 QString introspect (const QString &path) const override;
29 bool handleMessage(const QDBusMessage& message, const QDBusConnection& connection) override;
30
31@@ -45,5 +45,4 @@
32 static QString encodeAppId(const QString& appId);
33
34 LauncherModel *m_launcherModel;
35-
36 };
37
38=== modified file 'plugins/Unity/Launcher/desktopfilehandler.cpp'
39--- plugins/Unity/Launcher/desktopfilehandler.cpp 2016-02-19 08:44:42 +0000
40+++ plugins/Unity/Launcher/desktopfilehandler.cpp 2016-06-20 10:00:44 +0000
41@@ -1,5 +1,5 @@
42 /*
43- * Copyright 2014 Canonical Ltd.
44+ * Copyright 2014-2015 Canonical Ltd.
45 *
46 * This program is free software; you can redistribute it and/or modify
47 * it under the terms of the GNU Lesser General Public License as published by
48@@ -13,8 +13,6 @@
49 * You should have received a copy of the GNU Lesser General Public License
50 * along with this program. If not, see <http://www.gnu.org/licenses/>.
51 *
52- * Authors:
53- * Michael Zanetti <michael.zanetti@canonical.com>
54 */
55
56 #include "desktopfilehandler.h"
57@@ -22,8 +20,8 @@
58 #include <QStringList>
59 #include <QStandardPaths>
60 #include <QDir>
61-#include <QSettings>
62 #include <QLocale>
63+#include <QDebug>
64
65 #include <libintl.h>
66
67@@ -31,9 +29,15 @@
68 QObject(parent),
69 m_appId(appId)
70 {
71+ m_keyFile = g_key_file_new();
72 load();
73 }
74
75+DesktopFileHandler::~DesktopFileHandler()
76+{
77+ g_key_file_free(m_keyFile);
78+}
79+
80 QString DesktopFileHandler::appId() const
81 {
82 return m_appId;
83@@ -60,6 +64,11 @@
84 void DesktopFileHandler::load()
85 {
86 m_filename.clear();
87+ if (!m_keyFile) {
88+ g_key_file_free(m_keyFile);
89+ m_keyFile = nullptr;
90+ }
91+ m_actions.clear();
92
93 if (m_appId.isEmpty()) {
94 return;
95@@ -70,7 +79,7 @@
96
97 QStringList searchDirs = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation);
98 #ifdef LAUNCHER_TESTING
99- searchDirs << QStringLiteral(".");
100+ searchDirs.prepend(QStringLiteral("."));
101 #endif
102
103 QString path;
104@@ -91,6 +100,8 @@
105 if (desktopFile.startsWith(helper)) {
106 QFileInfo fileInfo(searchDir, desktopFile);
107 m_filename = fileInfo.absoluteFilePath();
108+ g_key_file_load_from_file(m_keyFile, QFile::encodeName(m_filename), G_KEY_FILE_NONE, nullptr);
109+ readActionList();
110 return;
111 }
112 }
113@@ -100,38 +111,81 @@
114 } while (dashPos != -1);
115 }
116
117+void DesktopFileHandler::readActionList()
118+{
119+ m_actions.clear();
120+ if (!isValid()) {
121+ return;
122+ }
123+
124+ QString tmp;
125+ if (hasKey(G_KEY_FILE_DESKTOP_KEY_ACTIONS)) {
126+ tmp = readString(G_KEY_FILE_DESKTOP_KEY_ACTIONS);
127+ } else if (hasKey("X-Ayatana-Desktop-Shortcuts")) { // fallback for an old standard
128+ m_usingFallbackActions = true;
129+ tmp = readString("X-Ayatana-Desktop-Shortcuts");
130+ }
131+ if (!tmp.isEmpty()) {
132+ m_actions = tmp.split(';', QString::SkipEmptyParts);
133+ }
134+}
135+
136+QList<QuickListEntry> DesktopFileHandler::actions() const
137+{
138+ if (!isValid() || m_actions.isEmpty()) {
139+ return {};
140+ }
141+
142+ const QString groupTemplate = m_usingFallbackActions ? QStringLiteral("%1 Shortcut Group") : QStringLiteral("Desktop Action %1");
143+
144+ QList<QuickListEntry> result;
145+
146+ Q_FOREACH(const QString &action, m_actions) {
147+ QuickListEntry entry;
148+ const char * groupName = qstrdup(groupTemplate.arg(action).toUtf8().constData());
149+
150+ entry.setActionId(QStringLiteral("exec_%1").arg(action));
151+ entry.setText(readTranslatedString(G_KEY_FILE_DESKTOP_KEY_NAME, groupName));
152+ entry.setIcon(readString(G_KEY_FILE_DESKTOP_KEY_ICON, groupName));
153+ entry.setExec(readString(G_KEY_FILE_DESKTOP_KEY_EXEC, groupName));
154+ result.append(entry);
155+ delete [] groupName;
156+ }
157+
158+ return result;
159+}
160+
161+QString DesktopFileHandler::readTranslatedString(const char * key, const char * groupname) const
162+{
163+ Q_ASSERT(m_keyFile);
164+ const QString original = readString(key, groupname);
165+ const QString translated = g_key_file_get_locale_string(m_keyFile, groupname, key, nullptr, nullptr);
166+
167+ if (!translated.isEmpty() && original != translated) {
168+ return translated;
169+ } else if (hasKey("X-Ubuntu-Gettext-Domain")) {
170+ // No translation found in desktop file. Get the untranslated one and have a go with gettext.
171+ return QString::fromUtf8(dgettext(qPrintable(readString("X-Ubuntu-Gettext-Domain")), qPrintable(original)));
172+ }
173+
174+ return original;
175+}
176+
177+QString DesktopFileHandler::readString(const char *key, const char *groupname) const
178+{
179+ Q_ASSERT(m_keyFile);
180+ return QString::fromUtf8(g_key_file_get_string(m_keyFile, groupname, key, nullptr));
181+}
182+
183+bool DesktopFileHandler::hasKey(const char *key, const char *groupname) const
184+{
185+ Q_ASSERT(m_keyFile);
186+ return g_key_file_has_key(m_keyFile, groupname, key, nullptr);
187+}
188+
189 QString DesktopFileHandler::displayName() const
190 {
191- if (!isValid()) {
192- return QString();
193- }
194-
195- QSettings settings(m_filename, QSettings::IniFormat);
196- settings.setIniCodec("UTF-8");
197- settings.beginGroup(QStringLiteral("Desktop Entry"));
198-
199- // First try to find Name[xx_YY] and Name[xx] in .desktop file
200- const QString locale = QLocale().name();
201- const QStringList splitLocale = locale.split(QLatin1Char('_'));
202- const QString shortLocale = splitLocale.first();
203-
204- if (locale != shortLocale && settings.contains(QStringLiteral("Name[%1]").arg(locale))) {
205- return settings.value(QStringLiteral("Name[%1]").arg(locale)).toString();
206- }
207-
208- if (settings.contains(QStringLiteral("Name[%1]").arg(shortLocale))) {
209- return settings.value(QStringLiteral("Name[%1]").arg(shortLocale)).toString();
210- }
211-
212- // No translation found in desktop file. Get the untranslated one and have a go with gettext.
213- QString displayName = settings.value(QStringLiteral("Name")).toString();
214-
215- if (settings.contains(QStringLiteral("X-Ubuntu-Gettext-Domain"))) {
216- const QString domain = settings.value(QStringLiteral("X-Ubuntu-Gettext-Domain")).toString();
217- return dgettext(domain.toUtf8().constData(), displayName.toUtf8().constData());
218- }
219-
220- return displayName;
221+ return readTranslatedString(G_KEY_FILE_DESKTOP_KEY_NAME);
222 }
223
224 QString DesktopFileHandler::icon() const
225@@ -140,11 +194,8 @@
226 return QString();
227 }
228
229- QSettings settings(m_filename, QSettings::IniFormat);
230- settings.setIniCodec("UTF-8");
231- settings.beginGroup(QStringLiteral("Desktop Entry"));
232- QString iconString = settings.value(QStringLiteral("Icon")).toString();
233- QString pathString = settings.value(QStringLiteral("Path")).toString();
234+ const QString iconString = readString(G_KEY_FILE_DESKTOP_KEY_ICON);
235+ const QString pathString = readString(G_KEY_FILE_DESKTOP_KEY_PATH);
236
237 if (QFileInfo::exists(iconString)) {
238 return QFileInfo(iconString).absoluteFilePath();
239
240=== modified file 'plugins/Unity/Launcher/desktopfilehandler.h'
241--- plugins/Unity/Launcher/desktopfilehandler.h 2014-09-02 17:45:50 +0000
242+++ plugins/Unity/Launcher/desktopfilehandler.h 2016-06-20 10:00:44 +0000
243@@ -1,5 +1,5 @@
244 /*
245- * Copyright 2014 Canonical Ltd.
246+ * Copyright 2014-2015 Canonical Ltd.
247 *
248 * This program is free software; you can redistribute it and/or modify
249 * it under the terms of the GNU Lesser General Public License as published by
250@@ -13,18 +13,21 @@
251 * You should have received a copy of the GNU Lesser General Public License
252 * along with this program. If not, see <http://www.gnu.org/licenses/>.
253 *
254- * Authors:
255- * Michael Zanetti <michael.zanetti@canonical.com>
256 */
257
258 #ifndef DESKTOPFILEHANDLER_H
259 #define DESKTOPFILEHANDLER_H
260
261 #include <QObject>
262+#include <QStringList>
263+
264+#include <glib.h>
265+
266+#include "quicklistentry.h"
267
268 /**
269 * When an object of this class is created or whenever setAppId(appId) is called,
270- * this will search for a .desktop file matching the give appId. If a file is
271+ * this will search for a .desktop file matching the given appId. If a file is
272 * found, isValid() will return true and the other methods return the contents
273 * of the .desktop file.
274 *
275@@ -35,8 +38,10 @@
276 class DesktopFileHandler: public QObject
277 {
278 Q_OBJECT
279+
280 public:
281 DesktopFileHandler(const QString &appId = QString(), QObject *parent = nullptr);
282+ ~DesktopFileHandler();
283
284 QString appId() const;
285 void setAppId(const QString &appId);
286@@ -45,12 +50,20 @@
287 QString filename() const;
288 QString displayName() const;
289 QString icon() const;
290+ QList<QuickListEntry> actions() const;
291
292 private:
293 void load();
294+ void readActionList();
295+ QString readTranslatedString(const char * key, const char * groupname = G_KEY_FILE_DESKTOP_GROUP) const;
296+ QString readString(const char * key, const char * groupname = G_KEY_FILE_DESKTOP_GROUP) const;
297+ bool hasKey(const char * key, const char * groupname = G_KEY_FILE_DESKTOP_GROUP) const;
298
299 QString m_appId;
300 QString m_filename;
301+ QStringList m_actions;
302+ bool m_usingFallbackActions = false;
303+ GKeyFile * m_keyFile = nullptr;
304 };
305
306 #endif
307
308=== modified file 'plugins/Unity/Launcher/launcheritem.cpp'
309--- plugins/Unity/Launcher/launcheritem.cpp 2016-05-13 11:14:15 +0000
310+++ plugins/Unity/Launcher/launcheritem.cpp 2016-06-20 10:00:44 +0000
311@@ -1,5 +1,5 @@
312 /*
313- * Copyright 2013 Canonical Ltd.
314+ * Copyright 2013-2015 Canonical Ltd.
315 *
316 * This program is free software; you can redistribute it and/or modify
317 * it under the terms of the GNU Lesser General Public License as published by
318@@ -13,8 +13,6 @@
319 * You should have received a copy of the GNU Lesser General Public License
320 * along with this program. If not, see <http://www.gnu.org/licenses/>.
321 *
322- * Authors:
323- * Michael Zanetti <michael.zanetti@canonical.com>
324 */
325
326 #include "launcheritem.h"
327@@ -22,7 +20,8 @@
328
329 #include <libintl.h>
330
331-LauncherItem::LauncherItem(const QString &appId, const QString &name, const QString &icon, QObject *parent) :
332+LauncherItem::LauncherItem(const QString &appId, const QString &name, const QString &icon,
333+ const QList<QuickListEntry> &actions, QObject *parent) :
334 LauncherItemInterface(parent),
335 m_appId(appId),
336 m_name(name),
337@@ -38,7 +37,10 @@
338 m_surfaceCount(0),
339 m_quickList(new QuickListModel(this))
340 {
341- Q_ASSERT(parent != nullptr);
342+ Q_ASSERT(parent != nullptr)
343+ Q_FOREACH(const QuickListEntry &action, actions) {
344+ m_quickList->appendAction(action);
345+ }
346 QuickListEntry nameAction;
347 nameAction.setActionId(QStringLiteral("launch_item"));
348 nameAction.setText(m_name);
349
350=== modified file 'plugins/Unity/Launcher/launcheritem.h'
351--- plugins/Unity/Launcher/launcheritem.h 2016-05-10 15:51:00 +0000
352+++ plugins/Unity/Launcher/launcheritem.h 2016-06-20 10:00:44 +0000
353@@ -32,7 +32,9 @@
354 {
355 Q_OBJECT
356 public:
357- LauncherItem(const QString &appId, const QString &name, const QString &icon, QObject *parent);
358+ LauncherItem(const QString &appId, const QString &name, const QString &icon,
359+ const QList<QuickListEntry> &actions = QList<QuickListEntry>(),
360+ QObject *parent);
361
362 QString appId() const override;
363 QString name() const override;
364
365=== modified file 'plugins/Unity/Launcher/launchermodel.cpp'
366--- plugins/Unity/Launcher/launchermodel.cpp 2016-05-19 16:11:10 +0000
367+++ plugins/Unity/Launcher/launchermodel.cpp 2016-06-20 10:00:44 +0000
368@@ -29,6 +29,7 @@
369
370 #include <QDesktopServices>
371 #include <QDebug>
372+#include <QFile>
373
374 using namespace unity::shell::application;
375
376@@ -167,6 +168,7 @@
377 LauncherItem *item = new LauncherItem(appId,
378 desktopFile.displayName(),
379 desktopFile.icon(),
380+ desktopFile.actions(),
381 this);
382 item->setPinned(true);
383 m_list.insert(index, item);
384@@ -207,6 +209,23 @@
385 if (m_appManager) {
386 m_appManager->stopApplication(appId);
387 }
388+ } else if (actionId.startsWith(QLatin1String("exec_"))) { // extra .desktop actions
389+ const QString exec = model->get(actionIndex).exec().trimmed();
390+ if (!exec.isEmpty() && m_appManager) {
391+ gint argc;
392+ gchar **argv = NULL;
393+ if (g_shell_parse_argv(QFile::encodeName(exec).constData(), &argc, &argv, nullptr)) {
394+ QStringList arguments;
395+ for (gint i = 1; i < argc; ++i) { // split the args from the exec name
396+ gchar * arg = g_strdup(argv[i]);
397+ arguments << QString::fromUtf8(arg);
398+ g_free(arg);
399+ }
400+ // because of our security model, we just forward the args to our own binary
401+ m_appManager->startApplication(appId, arguments);
402+ }
403+ g_strfreev(argv);
404+ }
405 // Nope, we don't know this action, let the backend forward it to the application
406 } else {
407 // TODO: forward quicklist action to app, possibly via m_dbusIface
408@@ -231,9 +250,9 @@
409 return "application:///" + appId + ".desktop";
410 }
411
412- QStringList parts = appId.split('_');
413- QString package = parts.value(0);
414- QString app = parts.value(1, QStringLiteral("first-listed-app"));
415+ const QStringList parts = appId.split('_');
416+ const QString package = parts.value(0);
417+ const QString app = parts.value(1, QStringLiteral("first-listed-app"));
418 return "appid://" + package + "/" + app + "/current-user-version";
419 }
420
421@@ -385,6 +404,7 @@
422 LauncherItem *item = new LauncherItem(appId,
423 desktopFile.displayName(),
424 desktopFile.icon(),
425+ desktopFile.actions(),
426 this);
427 item->setCountVisible(true);
428 beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
429@@ -461,6 +481,7 @@
430 LauncherItem *item = new LauncherItem(entry,
431 desktopFile.displayName(),
432 desktopFile.icon(),
433+ desktopFile.actions(),
434 this);
435 item->setPinned(true);
436 beginInsertRows(QModelIndex(), addedIndex, addedIndex);
437@@ -529,7 +550,8 @@
438
439 item->setRunning(true);
440 } else {
441- LauncherItem *item = new LauncherItem(app->appId(), app->name(), app->icon().toString(), this);
442+ DesktopFileHandler handler(app->appId(), this);
443+ LauncherItem *item = new LauncherItem(handler.appId(), handler.displayName(), handler.icon(), handler.actions(), this);
444 item->setRecent(true);
445 item->setRunning(true);
446 item->setFocused(app->focused());
447
448=== modified file 'plugins/Unity/Launcher/quicklistentry.cpp'
449--- plugins/Unity/Launcher/quicklistentry.cpp 2015-06-09 18:37:16 +0000
450+++ plugins/Unity/Launcher/quicklistentry.cpp 2016-06-20 10:00:44 +0000
451@@ -1,7 +1,5 @@
452-/* Copyright (C) 2013, 2015 Canonical, Ltd.
453- *
454- * Authors:
455- * Michael Zanetti <michael.zanetti@canonical.com>
456+/*
457+ * Copyright (C) 2013, 2015 Canonical, Ltd.
458 *
459 * This program is free software; you can redistribute it and/or modify
460 * it under the terms of the GNU General Public License as published by
461@@ -57,6 +55,16 @@
462 return !m_actionId.isEmpty();
463 }
464
465+QString QuickListEntry::exec() const
466+{
467+ return m_exec;
468+}
469+
470+void QuickListEntry::setExec(const QString &exec)
471+{
472+ m_exec = exec;
473+}
474+
475 bool QuickListEntry::operator==(const QuickListEntry &other)
476 {
477 return !other.actionId().isEmpty() && other.actionId() == m_actionId;
478
479=== modified file 'plugins/Unity/Launcher/quicklistentry.h'
480--- plugins/Unity/Launcher/quicklistentry.h 2015-06-09 18:37:16 +0000
481+++ plugins/Unity/Launcher/quicklistentry.h 2016-06-20 10:00:44 +0000
482@@ -1,8 +1,5 @@
483 /* Copyright (C) 2013, 2015 Canonical, Ltd.
484 *
485- * Authors:
486- * Michael Zanetti <michael.zanetti@canonical.com>
487- *
488 * This program is free software; you can redistribute it and/or modify
489 * it under the terms of the GNU General Public License as published by
490 * the Free Software Foundation; version 3.
491@@ -37,12 +34,16 @@
492
493 bool clickable() const;
494
495+ QString exec() const;
496+ void setExec(const QString &exec);
497+
498 bool operator==(const QuickListEntry & other);
499
500 private:
501 QString m_actionId;
502 QString m_text;
503 QString m_icon;
504+ QString m_exec;
505 };
506
507 #endif // QUICKLISTENTRY
508
509=== modified file 'plugins/Unity/Launcher/quicklistmodel.cpp'
510--- plugins/Unity/Launcher/quicklistmodel.cpp 2015-06-09 18:37:16 +0000
511+++ plugins/Unity/Launcher/quicklistmodel.cpp 2016-06-20 10:00:44 +0000
512@@ -12,9 +12,6 @@
513 *
514 * You should have received a copy of the GNU Lesser General Public License
515 * along with this program. If not, see <http://www.gnu.org/licenses/>.
516- *
517- * Authors:
518- * Michael Zanetti <michael.zanetti@canonical.com>
519 */
520
521 #include "quicklistmodel.h"
522@@ -22,12 +19,6 @@
523 QuickListModel::QuickListModel(QObject *parent) :
524 QuickListModelInterface(parent)
525 {
526-
527-}
528-
529-QuickListModel::~QuickListModel()
530-{
531-
532 }
533
534 void QuickListModel::appendAction(const QuickListEntry &entry)
535
536=== modified file 'plugins/Unity/Launcher/quicklistmodel.h'
537--- plugins/Unity/Launcher/quicklistmodel.h 2015-06-09 18:37:16 +0000
538+++ plugins/Unity/Launcher/quicklistmodel.h 2016-06-20 10:00:44 +0000
539@@ -13,8 +13,6 @@
540 * You should have received a copy of the GNU Lesser General Public License
541 * along with this program. If not, see <http://www.gnu.org/licenses/>.
542 *
543- * Authors:
544- * Michael Zanetti <michael.zanetti@canonical.com>
545 */
546
547 #ifndef QUICKLISTMODEL_H
548@@ -33,7 +31,7 @@
549 public:
550 explicit QuickListModel(QObject *parent = 0);
551
552- ~QuickListModel();
553+ ~QuickListModel() = default;
554
555 void appendAction(const QuickListEntry &entry);
556
557
558=== modified file 'tests/mocks/Unity/Launcher/MockLauncherModel.cpp'
559--- tests/mocks/Unity/Launcher/MockLauncherModel.cpp 2016-06-17 01:13:55 +0000
560+++ tests/mocks/Unity/Launcher/MockLauncherModel.cpp 2016-06-20 10:00:44 +0000
561@@ -80,7 +80,7 @@
562 item->setFocused(true);
563 item->setPinned(true);
564 m_list.append(item);
565- item = new MockLauncherItem("calendar-app", "/usr/share/applications/calendar-app.desktop","Calendar", "calendar", this);
566+ item = new MockLauncherItem("calendar-app", "/usr/share/applications/calendar-app.desktop", "Calendar", "calendar", this);
567 item->setPinned(true);
568 m_list.append(item);
569 item = new MockLauncherItem("libreoffice", "/usr/share/applications/libreoffice.desktop","Libre Office", "libreoffice", this);
570@@ -197,7 +197,8 @@
571 m_list.insert(index, new MockLauncherItem(appId,
572 appId + ".desktop",
573 appId,
574- appId + ".png"));
575+ appId + ".png",
576+ this));
577 m_list.at(index)->setPinned(true);
578 endInsertRows();
579 }
580
581=== modified file 'tests/plugins/Unity/Launcher/CMakeLists.txt'
582--- tests/plugins/Unity/Launcher/CMakeLists.txt 2016-05-10 15:51:00 +0000
583+++ tests/plugins/Unity/Launcher/CMakeLists.txt 2016-06-20 10:00:44 +0000
584@@ -1,5 +1,6 @@
585 pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
586-pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=8)
587+pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)
588+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=9)
589
590 include_directories(
591 ${CMAKE_CURRENT_SOURCE_DIR}
592@@ -35,6 +36,7 @@
593 )
594 target_link_libraries(launchermodeltestExec
595 unity8-private
596+ ${GLIB_LDFLAGS}
597 ${GSETTINGS_QT_LDFLAGS}
598 ${GLIB_LIBRARIES}
599 )
600
601=== added file 'tests/plugins/Unity/Launcher/google-chrome.desktop'
602--- tests/plugins/Unity/Launcher/google-chrome.desktop 1970-01-01 00:00:00 +0000
603+++ tests/plugins/Unity/Launcher/google-chrome.desktop 2016-06-20 10:00:44 +0000
604@@ -0,0 +1,222 @@
605+[Desktop Entry]
606+Version=1.0
607+Name=Google Chrome
608+# Only KDE 4 seems to use GenericName, so we reuse the KDE strings.
609+# From Ubuntu's language-pack-kde-XX-base packages, version 9.04-20090413.
610+GenericName=Web Browser
611+GenericName[ar]=متصفح الشبكة
612+GenericName[bg]=Уеб браузър
613+GenericName[ca]=Navegador web
614+GenericName[cs]=WWW prohlížeč
615+GenericName[da]=Browser
616+GenericName[de]=Web-Browser
617+GenericName[el]=Περιηγητής ιστού
618+GenericName[en_GB]=Web Browser
619+GenericName[es]=Navegador web
620+GenericName[et]=Veebibrauser
621+GenericName[fi]=WWW-selain
622+GenericName[fr]=Navigateur Web
623+GenericName[gu]=વેબ બ્રાઉઝર
624+GenericName[he]=דפדפן אינטרנט
625+GenericName[hi]=वेब ब्राउज़र
626+GenericName[hu]=Webböngésző
627+GenericName[it]=Browser Web
628+GenericName[ja]=ウェブブラウザ
629+GenericName[kn]=ಜಾಲ ವೀಕ್ಷಕ
630+GenericName[ko]=웹 브라우저
631+GenericName[lt]=Žiniatinklio naršyklė
632+GenericName[lv]=Tīmekļa pārlūks
633+GenericName[ml]=വെബ് ബ്രൌസര്‍
634+GenericName[mr]=वेब ब्राऊजर
635+GenericName[nb]=Nettleser
636+GenericName[nl]=Webbrowser
637+GenericName[pl]=Przeglądarka WWW
638+GenericName[pt]=Navegador Web
639+GenericName[pt_BR]=Navegador da Internet
640+GenericName[ro]=Navigator de Internet
641+GenericName[ru]=Веб-браузер
642+GenericName[sl]=Spletni brskalnik
643+GenericName[sv]=Webbläsare
644+GenericName[ta]=இணைய உலாவி
645+GenericName[th]=เว็บเบราว์เซอร์
646+GenericName[tr]=Web Tarayıcı
647+GenericName[uk]=Навігатор Тенет
648+GenericName[zh_CN]=网页浏览器
649+GenericName[zh_HK]=網頁瀏覽器
650+GenericName[zh_TW]=網頁瀏覽器
651+# Not translated in KDE, from Epiphany 2.26.1-0ubuntu1.
652+GenericName[bn]=ওয়েব ব্রাউজার
653+GenericName[fil]=Web Browser
654+GenericName[hr]=Web preglednik
655+GenericName[id]=Browser Web
656+GenericName[or]=ଓ୍ବେବ ବ୍ରାଉଜର
657+GenericName[sk]=WWW prehliadač
658+GenericName[sr]=Интернет прегледник
659+GenericName[te]=మహాతల అన్వేషి
660+GenericName[vi]=Bộ duyệt Web
661+# Gnome and KDE 3 uses Comment.
662+Comment=Access the Internet
663+Comment[ar]=الدخول إلى الإنترنت
664+Comment[bg]=Достъп до интернет
665+Comment[bn]=ইন্টারনেটটি অ্যাক্সেস করুন
666+Comment[ca]=Accedeix a Internet
667+Comment[cs]=Přístup k internetu
668+Comment[da]=Få adgang til internettet
669+Comment[de]=Internetzugriff
670+Comment[el]=Πρόσβαση στο Διαδίκτυο
671+Comment[en_GB]=Access the Internet
672+Comment[es]=Accede a Internet.
673+Comment[et]=Pääs Internetti
674+Comment[fi]=Käytä internetiä
675+Comment[fil]=I-access ang Internet
676+Comment[fr]=Accéder à Internet
677+Comment[gu]=ઇંટરનેટ ઍક્સેસ કરો
678+Comment[he]=גישה אל האינטרנט
679+Comment[hi]=इंटरनेट तक पहुंच स्थापित करें
680+Comment[hr]=Pristup Internetu
681+Comment[hu]=Internetelérés
682+Comment[id]=Akses Internet
683+Comment[it]=Accesso a Internet
684+Comment[ja]=インターネットにアクセス
685+Comment[kn]=ಇಂಟರ್ನೆಟ್ ಅನ್ನು ಪ್ರವೇಶಿಸಿ
686+Comment[ko]=인터넷 연결
687+Comment[lt]=Interneto prieiga
688+Comment[lv]=Piekļūt internetam
689+Comment[ml]=ഇന്റര്‍‌നെറ്റ് ആക്‌സസ് ചെയ്യുക
690+Comment[mr]=इंटरनेटमध्ये प्रवेश करा
691+Comment[nb]=Gå til Internett
692+Comment[nl]=Verbinding maken met internet
693+Comment[or]=ଇଣ୍ଟର୍ନେଟ୍ ପ୍ରବେଶ କରନ୍ତୁ
694+Comment[pl]=Skorzystaj z internetu
695+Comment[pt]=Aceder à Internet
696+Comment[pt_BR]=Acessar a internet
697+Comment[ro]=Accesaţi Internetul
698+Comment[ru]=Доступ в Интернет
699+Comment[sk]=Prístup do siete Internet
700+Comment[sl]=Dostop do interneta
701+Comment[sr]=Приступите Интернету
702+Comment[sv]=Gå ut på Internet
703+Comment[ta]=இணையத்தை அணுகுதல்
704+Comment[te]=ఇంటర్నెట్‌ను ఆక్సెస్ చెయ్యండి
705+Comment[th]=เข้าถึงอินเทอร์เน็ต
706+Comment[tr]=İnternet'e erişin
707+Comment[uk]=Доступ до Інтернету
708+Comment[vi]=Truy cập Internet
709+Comment[zh_CN]=访问互联网
710+Comment[zh_HK]=連線到網際網路
711+Comment[zh_TW]=連線到網際網路
712+Exec=/usr/bin/google-chrome-stable %U
713+Terminal=false
714+Icon=google-chrome
715+Type=Application
716+Categories=Network;WebBrowser;
717+MimeType=text/html;text/xml;application/xhtml_xml;image/webp;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;
718+X-Ayatana-Desktop-Shortcuts=NewWindow;NewIncognito
719+
720+[NewWindow Shortcut Group]
721+Name=New Window
722+Name[am]=አዲስ መስኮት
723+Name[ar]=نافذة جديدة
724+Name[bg]=Нов прозорец
725+Name[bn]=নতুন উইন্ডো
726+Name[ca]=Finestra nova
727+Name[cs]=Nové okno
728+Name[da]=Nyt vindue
729+Name[de]=Neues Fenster
730+Name[el]=Νέο Παράθυρο
731+Name[en_GB]=New Window
732+Name[es]=Nueva ventana
733+Name[et]=Uus aken
734+Name[fa]=پنجره جدید
735+Name[fi]=Uusi ikkuna
736+Name[fil]=New Window
737+Name[fr]=Nouvelle fenêtre
738+Name[gu]=નવી વિંડો
739+Name[hi]=नई विंडो
740+Name[hr]=Novi prozor
741+Name[hu]=Új ablak
742+Name[id]=Jendela Baru
743+Name[it]=Nuova finestra
744+Name[iw]=חלון חדש
745+Name[ja]=新規ウインドウ
746+Name[kn]=ಹೊಸ ವಿಂಡೊ
747+Name[ko]=새 창
748+Name[lt]=Naujas langas
749+Name[lv]=Jauns logs
750+Name[ml]=പുതിയ വിന്‍ഡോ
751+Name[mr]=नवीन विंडो
752+Name[nl]=Nieuw venster
753+Name[no]=Nytt vindu
754+Name[pl]=Nowe okno
755+Name[pt]=Nova janela
756+Name[pt_BR]=Nova janela
757+Name[ro]=Fereastră nouă
758+Name[ru]=Новое окно
759+Name[sk]=Nové okno
760+Name[sl]=Novo okno
761+Name[sr]=Нови прозор
762+Name[sv]=Nytt fönster
763+Name[sw]=Dirisha Jipya
764+Name[ta]=புதிய சாளரம்
765+Name[te]=క్రొత్త విండో
766+Name[th]=หน้าต่างใหม่
767+Name[tr]=Yeni Pencere
768+Name[uk]=Нове вікно
769+Name[vi]=Cửa sổ Mới
770+Name[zh_CN]=新建窗口
771+Name[zh_TW]=開新視窗
772+Exec=/usr/bin/google-chrome-stable
773+TargetEnvironment=Unity
774+
775+[NewIncognito Shortcut Group]
776+Name=New Incognito Window
777+Name[ar]=نافذة جديدة للتصفح المتخفي
778+Name[bg]=Нов прозорец „инкогнито“
779+Name[bn]=নতুন ছদ্মবেশী উইন্ডো
780+Name[ca]=Finestra d'incògnit nova
781+Name[cs]=Nové anonymní okno
782+Name[da]=Nyt inkognitovindue
783+Name[de]=Neues Inkognito-Fenster
784+Name[el]=Νέο παράθυρο για ανώνυμη περιήγηση
785+Name[en_GB]=New Incognito window
786+Name[es]=Nueva ventana de incógnito
787+Name[et]=Uus inkognito aken
788+Name[fa]=پنجره جدید حالت ناشناس
789+Name[fi]=Uusi incognito-ikkuna
790+Name[fil]=Bagong Incognito window
791+Name[fr]=Nouvelle fenêtre de navigation privée
792+Name[gu]=નવી છુપી વિંડો
793+Name[hi]=नई गुप्त विंडो
794+Name[hr]=Novi anoniman prozor
795+Name[hu]=Új Inkognitóablak
796+Name[id]=Jendela Penyamaran baru
797+Name[it]=Nuova finestra di navigazione in incognito
798+Name[iw]=חלון חדש לגלישה בסתר
799+Name[ja]=新しいシークレット ウィンドウ
800+Name[kn]=ಹೊಸ ಅಜ್ಞಾತ ವಿಂಡೋ
801+Name[ko]=새 시크릿 창
802+Name[lt]=Naujas inkognito langas
803+Name[lv]=Jauns inkognito režīma logs
804+Name[ml]=പുതിയ വേഷ പ്രച്ഛന്ന വിന്‍ഡോ
805+Name[mr]=नवीन गुप्त विंडो
806+Name[nl]=Nieuw incognitovenster
807+Name[no]=Nytt inkognitovindu
808+Name[pl]=Nowe okno incognito
809+Name[pt]=Nova janela de navegação anónima
810+Name[pt_BR]=Nova janela anônima
811+Name[ro]=Fereastră nouă incognito
812+Name[ru]=Новое окно в режиме инкогнито
813+Name[sk]=Nové okno inkognito
814+Name[sl]=Novo okno brez beleženja zgodovine
815+Name[sr]=Нови прозор за прегледање без архивирања
816+Name[sv]=Nytt inkognitofönster
817+Name[ta]=புதிய மறைநிலைச் சாளரம்
818+Name[te]=క్రొత్త అజ్ఞాత విండో
819+Name[th]=หน้าต่างใหม่ที่ไม่ระบุตัวตน
820+Name[tr]=Yeni Gizli pencere
821+Name[uk]=Нове вікно в режимі анонімного перегляду
822+Name[vi]=Cửa sổ ẩn danh mới
823+Name[zh_CN]=新建隐身窗口
824+Name[zh_TW]=新增無痕式視窗
825+Exec=/usr/bin/google-chrome-stable --incognito
826+TargetEnvironment=Unity
827
828=== modified file 'tests/plugins/Unity/Launcher/launchermodeltest.cpp'
829--- tests/plugins/Unity/Launcher/launchermodeltest.cpp 2016-05-19 16:11:10 +0000
830+++ tests/plugins/Unity/Launcher/launchermodeltest.cpp 2016-06-20 10:00:44 +0000
831@@ -176,10 +176,10 @@
832 QVERIFY(addReply.isValid());
833 QCOMPARE(addReply.value(), true);
834
835- appManager->addApplication(new MockApp("abs-icon"));
836+ appManager->addApplication(new MockApp("abs-icon"), this);
837 QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
838
839- appManager->addApplication(new MockApp("no-icon"));
840+ appManager->addApplication(new MockApp("no-icon", this));
841 QCOMPARE(launcherModel->rowCount(QModelIndex()), 2);
842
843 launcherModel->m_settings->setStoredApplications(QStringList());
844@@ -297,6 +297,51 @@
845 QCOMPARE(launcherModel->rowCount(QModelIndex()), 1);
846 }
847
848+ void testDesktopFileHandler_data() {
849+ QTest::addColumn<QString>("desktop_file");
850+ QTest::addColumn<QString>("display_name");
851+ QTest::addColumn<QString>("icon_name");
852+ QTest::newRow("Thunderbird") << "thunderbird" // uses the current Actions= list
853+ << "Thunderbird Mail"
854+ << "image://theme/thunderbird";
855+ QTest::newRow("Google Chrome") << "google-chrome" // uses the obsolete X-Ayatana-Desktop-Shortcuts= list
856+ << "Google Chrome"
857+ << "image://theme/google-chrome";
858+ }
859+
860+ void testDesktopFileHandler() {
861+ QFETCH(QString, desktop_file);
862+ QFETCH(QString, display_name);
863+ QFETCH(QString, icon_name);
864+
865+ // clear the model
866+ cleanup();
867+ QCOMPARE(launcherModel->rowCount(), 0);
868+
869+ const uint builtinEntries = 3; // launch, pin, stop
870+ const QString execPrefix = QStringLiteral("exec_");
871+
872+ // add our test app .desktop file
873+ appManager->addApplication(new MockApp(desktop_file, this));
874+ QVERIFY(launcherModel->rowCount() == 1);
875+ LauncherItem * item = static_cast<LauncherItem *>(launcherModel->get(0));
876+ QVERIFY(item);
877+ QCOMPARE(item->name(), display_name);
878+ QCOMPARE(item->icon(), icon_name);
879+
880+ QuickListModel *quickList = qobject_cast<QuickListModel*>(item->quickList());
881+ QVERIFY(quickList);
882+ const uint extraEntries = quickList->rowCount() - builtinEntries;
883+ QVERIFY(extraEntries > 0); // each tested app has some extra actions
884+
885+ for (uint i = 0; i < extraEntries; ++i) { // verify each extra action (ID, Text, and Exec)
886+ QuickListEntry entry = quickList->get(i);
887+ QVERIFY(entry.actionId().startsWith(execPrefix) && entry.actionId().length() > execPrefix.length());
888+ QVERIFY(!entry.text().isEmpty());
889+ QVERIFY(!entry.exec().isEmpty());
890+ }
891+ }
892+
893 void testQuickListPinningRemoving() {
894 // we start with 2 unpinned items
895 QCOMPARE(launcherModel->get(0)->pinned(), false);
896@@ -429,7 +474,7 @@
897 QStringList nodes = extractNodes(reply.value());
898 QCOMPARE(nodes.count(), launcherModel->rowCount());
899
900- appManager->addApplication(new MockApp("foobar"));
901+ appManager->addApplication(new MockApp("foobar", this));
902 reply = interface.call("Introspect");
903 nodes = extractNodes(reply.value());
904 QCOMPARE(nodes.contains("foobar"), true);
905@@ -543,7 +588,7 @@
906 QCOMPARE(launcherModel->get(index)->countVisible(), true);
907
908 if (!isRunning && startWhenVisible) {
909- appManager->addApplication(new MockApp("abs-icon"));
910+ appManager->addApplication(new MockApp("abs-icon", this));
911 }
912
913 // Hide count emblem again
914@@ -652,7 +697,7 @@
915 QCOMPARE(launcherModel->rowCount(), getASConfig().count());
916
917 int oldCount = launcherModel->rowCount();
918- appManager->addApplication(new MockApp("rel-icon"));
919+ appManager->addApplication(new MockApp("rel-icon", this));
920 QCOMPARE(launcherModel->rowCount(), oldCount + 1);
921 QCOMPARE(launcherModel->rowCount(), getASConfig().count());
922 }
923
924=== added file 'tests/plugins/Unity/Launcher/thunderbird.desktop'
925--- tests/plugins/Unity/Launcher/thunderbird.desktop 1970-01-01 00:00:00 +0000
926+++ tests/plugins/Unity/Launcher/thunderbird.desktop 2016-06-20 10:00:44 +0000
927@@ -0,0 +1,247 @@
928+[Desktop Entry]
929+Encoding=UTF-8
930+Name=Thunderbird Mail
931+Name[ast]=Veceru de corréu Thunderbird
932+Name[ca]=Client de correu Thunderbird
933+Name[cs]=Poštovní klient Thunderbird
934+Name[da]=Mozilla Thunderbird - e-post/nyhedsgruppe
935+Name[de]=Thunderbird-E-Mail und -Nachrichten
936+Name[el]=Ηλεκτρονική αλληλογραφία Thunderbird
937+Name[es]=Cliente de correo Thunderbird
938+Name[fi]=Thunderbird-sähköposti
939+Name[fr]=Messagerie Thunderbird
940+Name[gl]=Cliente de correo Thunderbird
941+Name[he]=Mozilla Thunderbird דוא״ל/חדשות
942+Name[hr]=Mozilla Thunderbird e-pošta/novosti
943+Name[hu]=Thunderbird levelezőkliens
944+Name[it]=Email Mozilla Thunderbird
945+Name[ja]=Thunderbird電子メールクライアント
946+Name[ko]=Mozilla Thunderbird
947+Name[nl]=Mozilla Thunderbird e-mail/nieuws
948+Name[pl]=Klient poczty Thunderbird
949+Name[pt_BR]=Cliente de E-mail Thunderbird
950+Name[ru]=Почтовый клиент Thunderbird
951+Name[sk]=Thunderbird - poštový klient
952+Name[sv]=E-postklienten Thunderbird
953+Name[ug]=Mozilla Thunderbird ئېلخەت/خەۋەر
954+Name[uk]=Поштова програма Thunderbird
955+Name[vi]=Trình điện thư Mozilla Thunderbird
956+Name[zh_CN]=Thunderbird 邮件/新闻
957+Name[zh_TW]=Thunderbird 郵件
958+Comment=Send and receive mail with Thunderbird
959+Comment[ast]=Lleer y escribir corréu electrónicu
960+Comment[ca]=Llegiu i escriviu correu
961+Comment[cs]=Čtení a psaní pošty
962+Comment[da]=Skriv/læs e-post/nyhedsgruppe med Mozilla Thunderbird
963+Comment[de]=E-Mails und Nachrichten mit Thunderbird lesen und schreiben
964+Comment[el]=Διαβάστε και γράψτε γράμματα με το Mozilla Thunderbird
965+Comment[es]=Lea y escriba correos y noticias con Thunderbird
966+Comment[fi]=Lue ja kirjoita sähköposteja
967+Comment[fr]=Lire et écrire des courriels
968+Comment[gl]=Lea e escriba correo electrónico
969+Comment[he]=קריאה/כתיבה של דוא״ל/חדשות באמצעות Mozilla Thunderbird
970+Comment[hr]=Čitajte/šaljite e-poštu s Thunderbird
971+Comment[hu]=Levelek írása és olvasása a Thunderbirddel
972+Comment[it]=Per leggere e scrivere email
973+Comment[ja]=メールの読み書き
974+Comment[ko]=Mozilla Thunderbird 메일/뉴스 읽기 및 쓰기 클라이언트
975+Comment[nl]=E-mail/nieuws lezen en schrijven met Mozilla Thunderbird
976+Comment[pl]=Czytanie i wysyłanie e-maili
977+Comment[pt_BR]=Leia e escreva suas mensagens
978+Comment[ru]=Читайте и пишите письма
979+Comment[sk]=Čítajte a píšte poštu pomocou programu Thunderbird
980+Comment[sv]=Läs och skriv e-post
981+Comment[ug]=ئېلخەت ۋە خەۋەرلەرنى Mozilla Thunderbird دا كۆرۈش ۋە يېزىش
982+Comment[uk]=Читання та написання листів
983+Comment[vi]=Đọc và soạn thư điện tử
984+Comment[zh_CN]=阅读邮件或新闻
985+Comment[zh_TW]=以 Mozilla Thunderbird 讀寫郵件或新聞
986+GenericName=Mail Client
987+GenericName[ast]=Client de correu
988+GenericName[ca]=Client de correu
989+GenericName[cs]=Poštovní klient
990+GenericName[da]=E-postklient
991+GenericName[de]=E-Mail-Anwendung
992+GenericName[el]=Λογισμικό αλληλογραφίας
993+GenericName[es]=Cliente de correo
994+GenericName[fi]=Sähköpostiohjelma
995+GenericName[fr]=Client de messagerie
996+GenericName[gl]=Cliente de correo electrónico
997+GenericName[he]=לקוח דוא״ל
998+GenericName[hr]=Klijent e-pošte
999+GenericName[hu]=Levelezőkliens
1000+GenericName[it]=Client email
1001+GenericName[ja]=電子メールクライアント
1002+GenericName[ko]=메일 클라이언트
1003+GenericName[nl]=E-mailprogramma
1004+GenericName[pt_BR]=Cliente de E-mail
1005+GenericName[ru]=Почтовый клиент
1006+GenericName[sk]=Poštový klient
1007+GenericName[ug]=ئېلخەت دېتالى
1008+GenericName[uk]=Поштова програма
1009+GenericName[vi]=Phần mềm khách quản lý thư điện tử
1010+GenericName[zh_CN]=邮件新闻客户端
1011+GenericName[zh_TW]=郵件用戶端
1012+Keywords=Email;E-mail;Newsgroup;Feed;RSS
1013+Keywords[ast]=Corréu;Corréu-e;Noticies;Discusiones;Mensaxes;Canales;RSS
1014+Keywords[ca]=Correu;Email;E-mail;Mailing;Llistes;Notícies;RSS
1015+Keywords[cs]=Email;E-mail;Pošta;Elektronická pošta;Diskusní skupiny;Čtečka;RSS
1016+Keywords[da]=Email;E-mail;Epost;E-post;E-brev;Newsgroup;Nyhedsgruppe;Nyhedskilde;Usenet;Feed;RSS
1017+Keywords[de]=Mail;E-Mail;Newsgroup;Nachrichten;Feed;RSS;Post;News;Usenet;online;lesen;schreiben
1018+Keywords[el]=Email;E-mail;Newsgroup;Feed;RSS;ημαιλ;Αλληλογραφία;Ροή;ΡΣΣ;Συζητήσεις;Γράμματα
1019+Keywords[es]=Email;Correo electrónico;Noticias;Discusiones;Mensajes;Canales;RSS
1020+Keywords[fi]=Mail;E-Mail;Email;Newsgroup;Feed;RSS;posti;sähköposti;maili;meili;Usenet;uutisryhmät;syöte
1021+Keywords[fr]=Mails;Mels;E-Mails;Emails;Courriels;Courriers;Newsgroup;Feed;RSS;Poster;Thunderbird;Lire;Écrire
1022+Keywords[he]=דוא"ל;דוא״ל;מייל;אי-מייל;אימייל;הודעות;מוזילה;תאנדרבירד;ת׳אנדרבירד;ת'אנדרבירד;ת׳אנדרברד;ת'אנדרברד;דואל;
1023+Keywords[hr]=email;e-mail;e-pošta;pošta;RSS
1024+Keywords[hu]=Email;E-mail;Levél;Levelezés;Hírcsoport;Feed;Hírforrás;RSS
1025+Keywords[it]=Email;Mail;Posta;Newsgroup;Feed;RSS
1026+Keywords[is]=tölvupóstur;rafpóstur;fréttir;fréttahópar;samtöl;skilaboð;fréttastraumar;RSS
1027+Keywords[ja]=Eメール;イーメール;mail;e-mail;email;メール;電子メール;ニュースグループ;ネットニュース;RSS;フィードリーダー;書く;読む;Mozilla
1028+Keywords[nl]=Email;E-mail;Newsgroup;Feed;RSS;Nieuwsgroep;Post
1029+Keywords[ru]=Email;E-mail;Newsgroup;Feed;RSS;почта;письма;новости;фиды
1030+Keywords[sk]=Email;E-mail;Elektronická pošta;Diskusné skupiny;Čítačka kanálov;RSS
1031+Keywords[uk]=Email;E-mail;Newsgroup;Feed;RSS;пошта;новини;подачі;стрічка
1032+Keywords[vi]=Mail;E-Mail;Email;Newsgroup;Feed;RSS;Thư điện tử;Gửi thư
1033+Keywords[zh_CN]=Mail;E-Mail;Email;Newsgroup;Feed;RSS;电子;邮件;新闻;Thunderbird;tb;雷鸟;电邮;邮箱;阅读器;
1034+Exec=thunderbird %u
1035+Terminal=false
1036+X-MultipleArgs=false
1037+Type=Application
1038+Icon=thunderbird
1039+Categories=Application;Network;Email;
1040+MimeType=x-scheme-handler/mailto;application/x-xpinstall;
1041+StartupNotify=true
1042+Actions=Compose;Contacts
1043+
1044+[Desktop Action Compose]
1045+Name=Compose New Message
1046+Name[af]=Skryf 'n nuwe boodskap
1047+Name[ar]=حرر رسالة جديدة
1048+Name[ast]=Redactar un mensaxe nuevu
1049+Name[be]=Напісаць ліст
1050+Name[bg]=Ново писмо
1051+Name[bn]=নতুন বার্তা লিখুন
1052+Name[br]=Sevel ur gemennadenn nevez
1053+Name[bs]=Napiši novu poruku
1054+Name[ca]=Redacta un missatge nou
1055+Name[cs]=Napsat novou zprávu
1056+Name[cy]=Cyfansoddi Neges Newydd
1057+Name[da]=Skriv en ny besked
1058+Name[de]=Neue Nachricht erstellen
1059+Name[el]=Σύνταξη νέου μηνύματος
1060+Name[eo]=Redakti novan mesaĝon
1061+Name[es]=Redactar un mensaje nuevo
1062+Name[et]=Koosta uus sõnum
1063+Name[eu]=Mezu Berria Idatzi
1064+Name[fi]=Luo uusi viesti
1065+Name[fr]=Rédiger un nouveau courriel
1066+Name[gd]=Co-chuir Teachdaireachd Ùr
1067+Name[gl]=Redactar unha nova mensaxe
1068+Name[he]=חיבור הודעה חדשה
1069+Name[hi]=नया संदेश लिखें
1070+Name[hr]=Nova poruka
1071+Name[hu]=Új üzenet írása
1072+Name[hy]=Նամակ գրել
1073+Name[id]=Buat Pesan Baru
1074+Name[is]=Skrifa nýtt bréf
1075+Name[it]=Componi nuovo messaggio
1076+Name[ja]=新しいメッセージの作成
1077+Name[kk]=Жаңа хат жазу
1078+Name[kn]=ಹೊಸ ಸಂದೇಶವನ್ನು ಸಂಯೋಜಿಸು
1079+Name[ko]=새 메시지 쓰기
1080+Name[ku]=Peyameke nû biafirînê
1081+Name[lt]=Rašyti naują laišką
1082+Name[lv]=Sacerēt jaunu vēstuli
1083+Name[mk]=Состави нова порака
1084+Name[ml]=പുതിയ സന്ദേശം രചിക്കുക
1085+Name[mr]=नवीन संदेश लिहा.
1086+Name[nb]=Skriv en ny melding
1087+Name[nl]=Nieuw bericht opstellen
1088+Name[nn]=Skriv ei ny melding
1089+Name[pl]=Utwórz nową wiadomość
1090+Name[pt]=Criar nova mensagem
1091+Name[pt_BR]=Compor nova mensagem
1092+Name[ro]=Compune un mesaj nou
1093+Name[ru]=Написать письмо
1094+Name[si]=නව පණිවිඩයක් අරඹන්න
1095+Name[sk]=Napísať novú správu
1096+Name[sl]=Sestavi novo sporočilo
1097+Name[sq]=Krijo Mesazh të Ri
1098+Name[sr]=Састави нову поруку
1099+Name[sv]=Skriv nytt meddelande
1100+Name[ta]=புதிய செய்தியை உருவாக்கு
1101+Name[te]=కొత్త సందేశాన్ని రచించు
1102+Name[th]=สร้างข้อความใหม่
1103+Name[tr]=Yeni İleti Oluştur
1104+Name[uk]=Написати нове повідомлення
1105+Name[zh_CN]=撰写新消息
1106+Name[zh_TW]=撰寫新郵件
1107+Exec=thunderbird -compose
1108+OnlyShowIn=Messaging Menu;Unity;
1109+
1110+[Desktop Action Contacts]
1111+Name=Contacts
1112+Name[af]=Kontakte
1113+Name[ar]=المتراسلين
1114+Name[ast]=Contautos
1115+Name[be]=Кантакты
1116+Name[bg]=Контакти
1117+Name[bn]=পরিচিতি সমূহ
1118+Name[br]=Darempredoù
1119+Name[bs]=Kontakti
1120+Name[ca]=Contactes
1121+Name[cs]=Kontakty
1122+Name[cy]=Cysylltiadau
1123+Name[da]=Kontakter
1124+Name[de]=Kontakte
1125+Name[el]=Επαφές
1126+Name[eo]=Kontaktoj
1127+Name[es]=Contactos
1128+Name[et]=Kontaktid
1129+Name[eu]=Kontaktuak
1130+Name[fi]=Yhteystiedot
1131+Name[fr]=Carnet d'adresses
1132+Name[gd]=Buntanasan
1133+Name[gl]=Contactos
1134+Name[he]=אנשי קשר
1135+Name[hi]=संपर्क
1136+Name[hr]=Kontakti
1137+Name[hu]=Névjegyek
1138+Name[hy]=Կապորդներ
1139+Name[id]=Kontak
1140+Name[is]=Tengiliðir
1141+Name[it]=Contatti
1142+Name[ja]=連絡先
1143+Name[kk]=Байланыс жазулары
1144+Name[kn]=ಸಂಪರ್ಕಗಳು
1145+Name[ko]=연락처
1146+Name[ku]=Tekilî
1147+Name[lt]=Kontaktai
1148+Name[lv]=Kontakti
1149+Name[mk]=Контакти
1150+Name[ml]=വിലാസങ്ങള്‍
1151+Name[mr]=संपर्क
1152+Name[nb]=Kontakter
1153+Name[nl]=Contacten
1154+Name[nn]=Kontaktar
1155+Name[pl]=Kontakty
1156+Name[pt]=Contactos
1157+Name[pt_BR]=Contatos
1158+Name[ro]=Contacte
1159+Name[ru]=Контакты
1160+Name[si]=සබඳතා
1161+Name[sk]=Kontakty
1162+Name[sl]=Stiki
1163+Name[sq]=Kontaktet
1164+Name[sr]=Контакти
1165+Name[sv]=Kontakter
1166+Name[ta]=தொடர்புகள்
1167+Name[te]=పరిచయాలు
1168+Name[th]=รายชื่อติดต่อ
1169+Name[tr]=Kişiler
1170+Name[uk]=Контакти
1171+Name[zh_CN]=联系人
1172+Name[zh_TW]=連絡人
1173+Exec=thunderbird -addressbook
1174+OnlyShowIn=Messaging Menu;Unity;

Subscribers

People subscribed via source and target branches