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
=== modified file 'plugins/about/click.cpp'
--- plugins/about/click.cpp 2013-10-30 01:22:51 +0000
+++ plugins/about/click.cpp 2014-07-01 12:20:23 +0000
@@ -25,7 +25,6 @@
25#include <libintl.h>25#include <libintl.h>
2626
27#include <QDebug>27#include <QDebug>
28#include <QDir>
29#include <QIcon>28#include <QIcon>
30#include <QJsonArray>29#include <QJsonArray>
31#include <QJsonDocument>30#include <QJsonDocument>
@@ -38,6 +37,135 @@
38 m_clickPackages = buildClickList();37 m_clickPackages = buildClickList();
39}38}
4039
40/* Look through `hooks' for a desktop file in `directory'
41 * and set the display name and icon from this.
42 *
43 * Will set with information from the first desktop file found and parsed.
44 */
45void ClickModel::populateFromDesktopFile (Click *newClick,
46 QVariantMap hooks,
47 QDir directory)
48{
49 QVariantMap appHooks;
50 GKeyFile *appinfo = g_key_file_new();
51 gchar *desktopFileName = NULL;
52
53 QVariantMap::ConstIterator begin(hooks.constBegin());
54 QVariantMap::ConstIterator end(hooks.constEnd());
55
56 // Look through the hooks for a 'desktop' key which points to a desktop
57 // file referring to this app.
58 while (begin != end) {
59 appHooks = (*begin++).toMap();
60 if (!appHooks.isEmpty() &&
61 appHooks.contains("desktop") &&
62 directory.exists()) {
63 QFile desktopFile(directory.absoluteFilePath(
64 appHooks.value("desktop", "undefined").toString()));
65
66 desktopFileName =
67 g_strdup(desktopFile.fileName().toLocal8Bit().constData());
68
69 g_debug ("Desktop file: %s", desktopFileName);
70
71 if (!desktopFile.exists())
72 goto out;
73
74 gboolean loaded = g_key_file_load_from_file(appinfo,
75 desktopFileName,
76 G_KEY_FILE_NONE,
77 NULL);
78
79 if (!loaded) {
80 g_warning ("Couldn't parse desktop file %s", desktopFileName);
81 goto out;
82 }
83
84 gchar * name = g_key_file_get_string (appinfo,
85 G_KEY_FILE_DESKTOP_GROUP,
86 G_KEY_FILE_DESKTOP_KEY_NAME,
87 NULL);
88
89 if (name) {
90 g_debug ("Name is %s", name);
91 newClick->displayName = name;
92 g_free (name);
93 name = NULL;
94 }
95
96 // Overwrite the icon with the .desktop file's one if we have it.
97 // This is the one that the app scope displays so use that if we
98 // can.
99 gchar * icon = g_key_file_get_string (appinfo,
100 G_KEY_FILE_DESKTOP_GROUP,
101 G_KEY_FILE_DESKTOP_KEY_ICON,
102 NULL);
103
104 if (icon) {
105 g_debug ("Icon is %s", icon);
106 QFile iconFile(icon);
107 if (iconFile.exists()) {
108 newClick->icon = icon;
109 } else {
110 QString qIcon(QString::fromLocal8Bit(icon));
111 iconFile.setFileName(directory.absoluteFilePath(
112 QDir::cleanPath(qIcon)));
113 if (iconFile.exists())
114 newClick->icon = iconFile.fileName();
115 else if (QIcon::hasThemeIcon(qIcon)) // try the icon theme
116 newClick->icon = qIcon;
117 }
118 }
119 }
120out:
121 g_free (desktopFileName);
122 g_key_file_free (appinfo);
123 return;
124 }
125}
126
127ClickModel::Click ClickModel::buildClick(QVariantMap manifest)
128{
129 Click newClick;
130 QDir directory;
131
132 newClick.name = manifest.value("title",
133 gettext("Unknown title")).toString();
134
135 // This key is the base directory where the click package is installed to.
136 // We'll look for files relative to this.
137 if (manifest.contains("_directory")) {
138 directory = manifest.value("_directory", "/undefined").toString();
139 // Set the icon from the click package. Might be a path or a reference to a themed icon.
140 QString iconFile(manifest.value("icon", "undefined").toString());
141
142 if (directory.exists()) {
143 QFile icon(directory.absoluteFilePath(iconFile.simplified()));
144 if (!icon.exists() && QIcon::hasThemeIcon(iconFile)) // try the icon theme
145 newClick.icon = iconFile;
146 else
147 newClick.icon = icon.fileName();
148 }
149
150 }
151
152 // "hooks" → title → "desktop" / "icon"
153 QVariant hooks(manifest.value("hooks"));
154
155 if (hooks.isValid()) {
156 QVariantMap allHooks(hooks.toMap());
157 // The desktop file contains an icon and the display name
158 populateFromDesktopFile(&newClick, allHooks, directory);
159 }
160
161 newClick.installSize = manifest.value("installed-size",
162 "0").toString().toUInt()*1024;
163
164 m_totalClickSize += newClick.installSize;
165
166 return newClick;
167}
168
41QList<ClickModel::Click> ClickModel::buildClickList()169QList<ClickModel::Click> ClickModel::buildClickList()
42{170{
43 QFile clickBinary("/usr/bin/click");171 QFile clickBinary("/usr/bin/click");
@@ -80,86 +208,8 @@
80208
81 while (begin != end) {209 while (begin != end) {
82 QVariantMap val = (*begin++).toObject().toVariantMap();210 QVariantMap val = (*begin++).toObject().toVariantMap();
83 Click newClick;211
84 QDir directory;212 clickPackages.append(buildClick(val));
85
86 newClick.name = val.value("title",
87 gettext("Unknown title")).toString();
88
89 if (val.contains("_directory")) {
90 directory = val.value("_directory", "/undefined").toString();
91 // Set the icon from the click package
92 QString iconFile(val.value("icon", "undefined").toString());
93 if (directory.exists()) {
94 QString icon(directory.filePath(iconFile.simplified()));
95 newClick.icon = icon;
96 }
97 }
98
99 // "hooks" → title → "desktop" / "icon"
100 QVariant hooks(val.value("hooks"));
101
102 if (hooks.isValid()) {
103 QVariantMap allHooks(hooks.toMap());
104
105 if (allHooks.contains(newClick.name)) {
106 QVariantMap appHooks(allHooks.value(newClick.name).toMap());
107 if (!appHooks.isEmpty() &&
108 appHooks.contains("desktop") &&
109 directory.exists()) {
110 QFile desktopFile(
111 directory.absoluteFilePath(
112 appHooks.value("desktop",
113 "undefined").toString()));
114 const char * desktopFileName =
115 desktopFile.fileName().toLocal8Bit().constData();
116 g_debug ("Desktop file: %s", desktopFileName);
117 if (desktopFile.exists()) {
118 GDesktopAppInfo *appinfo =
119 g_desktop_app_info_new_from_filename (
120 desktopFileName);
121
122 if (!appinfo) {
123 g_warning ("Couldn't parse desktop file %s",
124 desktopFileName);
125 } else {
126 const char * name = g_app_info_get_name (
127 (GAppInfo *) appinfo);
128
129 if (name) {
130 g_debug ("Name is %s", name);
131 newClick.displayName = name;
132 }
133
134 // Overwrite the icon with the .desktop file's one
135 // if we have it. This one is more reliable.
136 const char * icon = g_desktop_app_info_get_string (
137 appinfo, "Icon");
138 if (icon) {
139 g_debug ("Icon is %s", icon);
140 QFile iconFile(icon);
141 if (iconFile.exists()) {
142 newClick.icon = icon;
143 } else {
144 iconFile.setFileName(
145 directory.absoluteFilePath(
146 QString::fromLocal8Bit(icon)));
147 if (iconFile.exists())
148 newClick.icon = iconFile.fileName();
149 }
150 }
151 }
152 }
153 }
154 }
155 }
156
157 newClick.installSize = val.value("installed-size",
158 "0").toString().toUInt()*1024;
159
160 m_totalClickSize += newClick.installSize;
161
162 clickPackages.append(newClick);
163 }213 }
164214
165 return clickPackages;215 return clickPackages;
166216
=== modified file 'plugins/about/click.h'
--- plugins/about/click.h 2013-10-29 22:43:40 +0000
+++ plugins/about/click.h 2014-07-01 12:20:23 +0000
@@ -21,9 +21,10 @@
21#define CLICK_H21#define CLICK_H
2222
23#include <QAbstractTableModel>23#include <QAbstractTableModel>
24#include <QSortFilterProxyModel>24#include <QDir>
25#include <QObject>25#include <QObject>
26#include <QProcess>26#include <QProcess>
27#include <QSortFilterProxyModel>
2728
28class ClickModel : public QAbstractTableModel29class ClickModel : public QAbstractTableModel
29{30{
@@ -56,7 +57,12 @@
56 quint64 getClickSize() const;57 quint64 getClickSize() const;
5758
58private:59private:
60 void populateFromDesktopFile(Click *newClick,
61 QVariantMap hooks,
62 QDir directory);
63 Click buildClick(QVariantMap manifest);
59 QList<Click> buildClickList();64 QList<Click> buildClickList();
65
60 QList<Click> m_clickPackages;66 QList<Click> m_clickPackages;
61 int m_totalClickSize;67 int m_totalClickSize;
6268

Subscribers

People subscribed via source and target branches