Merge lp:~laney/ubuntu-system-settings/show-more-icons into lp:ubuntu-system-settings
- show-more-icons
- Merge into trunk
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 |
Related bugs: |
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_
Sebastien Bacher (seb128) wrote : | # |
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> ]
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:721
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:722
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:725
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Sebastien Bacher (seb128) wrote : | # |
looks good, thanks
Preview Diff
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 |
Looks fine but I didn't review in details, one review comment though