Merge lp:~laney/ubuntu-system-settings/show-more-icons into lp:ubuntu-system-settings

Proposed by Iain Lane
Status: Merged
Approved by: Sebastien Bacher
Approved revision: 725
Merged at revision: 763
Proposed branch: lp:~laney/ubuntu-system-settings/show-more-icons
Merge into: lp:ubuntu-system-settings
Diff against target: 264 lines (+138/-82)
2 files modified
plugins/about/click.cpp (+131/-81)
plugins/about/click.h (+7/-1)
To merge this branch: bzr merge lp:~laney/ubuntu-system-settings/show-more-icons
Reviewer Review Type Date Requested Status
Sebastien Bacher (community) Approve
PS Jenkins bot continuous-integration Needs Fixing
Review via email: mp+224871@code.launchpad.net

Commit message

[about] Look harder for the desktop file so we can display more icons in the list of apps

Description of the change

Try harder to get at the desktop file in order to pull its icon.

Still doesn't get 100% coverage, need to look at why g_desktop_app_info_new_from_filename() doesn't parse some files.

To post a comment you must log in.
Revision history for this message
Sebastien Bacher (seb128) wrote :

Looks fine but I didn't review in details, one review comment though

Revision history for this message
Iain Lane (laney) wrote :

On Fri, Jun 27, 2014 at 05:22:20PM -0000, Sebastien Bacher wrote:
> Looks fine but I didn't review in details, one review comment though
>
> Diff comments:
> […]
> > + if (!appinfo) {
> > + g_warning ("Couldn't parse desktop file %s",
> > + desktopFileName);
> > + return;
>
> "desktopFileName" is leaked in that case

Oh yes, well done. I fixed that now.

Note that the code is mostly moved from one giant function which we had
before to slightly smaller ones. Not the easiest diff to review,
granted.

--
Iain Lane [ <email address hidden> ]
Debian Developer [ <email address hidden> ]
Ubuntu Developer [ <email address hidden> ]

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:721
http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-ci/905/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-utopic-touch/1311
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic/1146
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-amd64-ci/97
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/97
        deb: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/97/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-i386-ci/97
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-mako/1626
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/2214
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/2214/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/8965
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic/947
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/1289
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/1289/artifact/work/output/*zip*/output.zip

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/ubuntu-system-settings-ci/905/rebuild

review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:722
http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-ci/906/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-utopic-touch/1325/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic/1155
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-amd64-ci/98
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/98
        deb: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/98/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-i386-ci/98
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-mako/1638/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/2232
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/2232/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/8980
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic/954
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/1298
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/1298/artifact/work/output/*zip*/output.zip

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/ubuntu-system-settings-ci/906/rebuild

review: Needs Fixing (continuous-integration)
722. By Iain Lane

Reindent, check theme icon

723. By Iain Lane

Merge trunk, goto out instead

724. By Iain Lane

Read the desktop file as a keyfile instead of with GDesktopAppInfo

Some click packages ship spec-violating desktop files which GDesktopAppInfo
won't load.

725. By Iain Lane

comments

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:725
http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-ci/912/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-utopic-touch/1405/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic/1215
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-amd64-ci/104
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/104
        deb: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-armhf-ci/104/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/ubuntu-system-settings-utopic-i386-ci/104
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-mako/1704/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/2355
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/2355/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/9093
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic/1001
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/1361
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/1361/artifact/work/output/*zip*/output.zip

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/ubuntu-system-settings-ci/912/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Sebastien Bacher (seb128) wrote :

looks good, thanks

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/about/click.cpp'
2--- plugins/about/click.cpp 2013-10-30 01:22:51 +0000
3+++ plugins/about/click.cpp 2014-07-01 12:20:23 +0000
4@@ -25,7 +25,6 @@
5 #include <libintl.h>
6
7 #include <QDebug>
8-#include <QDir>
9 #include <QIcon>
10 #include <QJsonArray>
11 #include <QJsonDocument>
12@@ -38,6 +37,135 @@
13 m_clickPackages = buildClickList();
14 }
15
16+/* Look through `hooks' for a desktop file in `directory'
17+ * and set the display name and icon from this.
18+ *
19+ * Will set with information from the first desktop file found and parsed.
20+ */
21+void ClickModel::populateFromDesktopFile (Click *newClick,
22+ QVariantMap hooks,
23+ QDir directory)
24+{
25+ QVariantMap appHooks;
26+ GKeyFile *appinfo = g_key_file_new();
27+ gchar *desktopFileName = NULL;
28+
29+ QVariantMap::ConstIterator begin(hooks.constBegin());
30+ QVariantMap::ConstIterator end(hooks.constEnd());
31+
32+ // Look through the hooks for a 'desktop' key which points to a desktop
33+ // file referring to this app.
34+ while (begin != end) {
35+ appHooks = (*begin++).toMap();
36+ if (!appHooks.isEmpty() &&
37+ appHooks.contains("desktop") &&
38+ directory.exists()) {
39+ QFile desktopFile(directory.absoluteFilePath(
40+ appHooks.value("desktop", "undefined").toString()));
41+
42+ desktopFileName =
43+ g_strdup(desktopFile.fileName().toLocal8Bit().constData());
44+
45+ g_debug ("Desktop file: %s", desktopFileName);
46+
47+ if (!desktopFile.exists())
48+ goto out;
49+
50+ gboolean loaded = g_key_file_load_from_file(appinfo,
51+ desktopFileName,
52+ G_KEY_FILE_NONE,
53+ NULL);
54+
55+ if (!loaded) {
56+ g_warning ("Couldn't parse desktop file %s", desktopFileName);
57+ goto out;
58+ }
59+
60+ gchar * name = g_key_file_get_string (appinfo,
61+ G_KEY_FILE_DESKTOP_GROUP,
62+ G_KEY_FILE_DESKTOP_KEY_NAME,
63+ NULL);
64+
65+ if (name) {
66+ g_debug ("Name is %s", name);
67+ newClick->displayName = name;
68+ g_free (name);
69+ name = NULL;
70+ }
71+
72+ // Overwrite the icon with the .desktop file's one if we have it.
73+ // This is the one that the app scope displays so use that if we
74+ // can.
75+ gchar * icon = g_key_file_get_string (appinfo,
76+ G_KEY_FILE_DESKTOP_GROUP,
77+ G_KEY_FILE_DESKTOP_KEY_ICON,
78+ NULL);
79+
80+ if (icon) {
81+ g_debug ("Icon is %s", icon);
82+ QFile iconFile(icon);
83+ if (iconFile.exists()) {
84+ newClick->icon = icon;
85+ } else {
86+ QString qIcon(QString::fromLocal8Bit(icon));
87+ iconFile.setFileName(directory.absoluteFilePath(
88+ QDir::cleanPath(qIcon)));
89+ if (iconFile.exists())
90+ newClick->icon = iconFile.fileName();
91+ else if (QIcon::hasThemeIcon(qIcon)) // try the icon theme
92+ newClick->icon = qIcon;
93+ }
94+ }
95+ }
96+out:
97+ g_free (desktopFileName);
98+ g_key_file_free (appinfo);
99+ return;
100+ }
101+}
102+
103+ClickModel::Click ClickModel::buildClick(QVariantMap manifest)
104+{
105+ Click newClick;
106+ QDir directory;
107+
108+ newClick.name = manifest.value("title",
109+ gettext("Unknown title")).toString();
110+
111+ // This key is the base directory where the click package is installed to.
112+ // We'll look for files relative to this.
113+ if (manifest.contains("_directory")) {
114+ directory = manifest.value("_directory", "/undefined").toString();
115+ // Set the icon from the click package. Might be a path or a reference to a themed icon.
116+ QString iconFile(manifest.value("icon", "undefined").toString());
117+
118+ if (directory.exists()) {
119+ QFile icon(directory.absoluteFilePath(iconFile.simplified()));
120+ if (!icon.exists() && QIcon::hasThemeIcon(iconFile)) // try the icon theme
121+ newClick.icon = iconFile;
122+ else
123+ newClick.icon = icon.fileName();
124+ }
125+
126+ }
127+
128+ // "hooks" → title → "desktop" / "icon"
129+ QVariant hooks(manifest.value("hooks"));
130+
131+ if (hooks.isValid()) {
132+ QVariantMap allHooks(hooks.toMap());
133+ // The desktop file contains an icon and the display name
134+ populateFromDesktopFile(&newClick, allHooks, directory);
135+ }
136+
137+ newClick.installSize = manifest.value("installed-size",
138+ "0").toString().toUInt()*1024;
139+
140+ m_totalClickSize += newClick.installSize;
141+
142+ return newClick;
143+}
144+
145 QList<ClickModel::Click> ClickModel::buildClickList()
146 {
147 QFile clickBinary("/usr/bin/click");
148@@ -80,86 +208,8 @@
149
150 while (begin != end) {
151 QVariantMap val = (*begin++).toObject().toVariantMap();
152- Click newClick;
153- QDir directory;
154-
155- newClick.name = val.value("title",
156- gettext("Unknown title")).toString();
157-
158- if (val.contains("_directory")) {
159- directory = val.value("_directory", "/undefined").toString();
160- // Set the icon from the click package
161- QString iconFile(val.value("icon", "undefined").toString());
162- if (directory.exists()) {
163- QString icon(directory.filePath(iconFile.simplified()));
164- newClick.icon = icon;
165- }
166- }
167-
168- // "hooks" → title → "desktop" / "icon"
169- QVariant hooks(val.value("hooks"));
170-
171- if (hooks.isValid()) {
172- QVariantMap allHooks(hooks.toMap());
173-
174- if (allHooks.contains(newClick.name)) {
175- QVariantMap appHooks(allHooks.value(newClick.name).toMap());
176- if (!appHooks.isEmpty() &&
177- appHooks.contains("desktop") &&
178- directory.exists()) {
179- QFile desktopFile(
180- directory.absoluteFilePath(
181- appHooks.value("desktop",
182- "undefined").toString()));
183- const char * desktopFileName =
184- desktopFile.fileName().toLocal8Bit().constData();
185- g_debug ("Desktop file: %s", desktopFileName);
186- if (desktopFile.exists()) {
187- GDesktopAppInfo *appinfo =
188- g_desktop_app_info_new_from_filename (
189- desktopFileName);
190-
191- if (!appinfo) {
192- g_warning ("Couldn't parse desktop file %s",
193- desktopFileName);
194- } else {
195- const char * name = g_app_info_get_name (
196- (GAppInfo *) appinfo);
197-
198- if (name) {
199- g_debug ("Name is %s", name);
200- newClick.displayName = name;
201- }
202-
203- // Overwrite the icon with the .desktop file's one
204- // if we have it. This one is more reliable.
205- const char * icon = g_desktop_app_info_get_string (
206- appinfo, "Icon");
207- if (icon) {
208- g_debug ("Icon is %s", icon);
209- QFile iconFile(icon);
210- if (iconFile.exists()) {
211- newClick.icon = icon;
212- } else {
213- iconFile.setFileName(
214- directory.absoluteFilePath(
215- QString::fromLocal8Bit(icon)));
216- if (iconFile.exists())
217- newClick.icon = iconFile.fileName();
218- }
219- }
220- }
221- }
222- }
223- }
224- }
225-
226- newClick.installSize = val.value("installed-size",
227- "0").toString().toUInt()*1024;
228-
229- m_totalClickSize += newClick.installSize;
230-
231- clickPackages.append(newClick);
232+
233+ clickPackages.append(buildClick(val));
234 }
235
236 return clickPackages;
237
238=== modified file 'plugins/about/click.h'
239--- plugins/about/click.h 2013-10-29 22:43:40 +0000
240+++ plugins/about/click.h 2014-07-01 12:20:23 +0000
241@@ -21,9 +21,10 @@
242 #define CLICK_H
243
244 #include <QAbstractTableModel>
245-#include <QSortFilterProxyModel>
246+#include <QDir>
247 #include <QObject>
248 #include <QProcess>
249+#include <QSortFilterProxyModel>
250
251 class ClickModel : public QAbstractTableModel
252 {
253@@ -56,7 +57,12 @@
254 quint64 getClickSize() const;
255
256 private:
257+ void populateFromDesktopFile(Click *newClick,
258+ QVariantMap hooks,
259+ QDir directory);
260+ Click buildClick(QVariantMap manifest);
261 QList<Click> buildClickList();
262+
263 QList<Click> m_clickPackages;
264 int m_totalClickSize;
265

Subscribers

People subscribed via source and target branches