Merge lp:~azzar1/unity/gs-integration into lp:unity
- gs-integration
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Marco Trevisan (Treviño) |
Approved revision: | no longer in the source branch. |
Merged at revision: | 4079 |
Proposed branch: | lp:~azzar1/unity/gs-integration |
Merge into: | lp:unity |
Prerequisite: | lp:~robert-ancell/unity/gnome-software |
Diff against target: |
897 lines (+247/-295) 17 files modified
CMakeLists.txt (+1/-0) debian/control (+1/-0) launcher/LauncherController.cpp (+18/-57) launcher/LauncherControllerPrivate.h (+2/-3) launcher/LauncherIcon.cpp (+14/-0) launcher/LauncherIcon.h (+2/-0) launcher/SimpleLauncherIcon.cpp (+27/-8) launcher/SimpleLauncherIcon.h (+2/-0) launcher/SoftwareCenterLauncherIcon.cpp (+4/-108) launcher/SoftwareCenterLauncherIcon.h (+1/-7) tests/test_launcher_controller.cpp (+0/-32) tests/test_software_center_launcher_icon.cpp (+5/-79) unity-shared/AppStreamApplication.cpp (+104/-0) unity-shared/AppStreamApplication.h (+61/-0) unity-shared/ApplicationManager.h (+3/-0) unity-shared/CMakeLists.txt (+1/-0) unity-shared/DesktopApplicationManager.h (+1/-1) |
To merge this branch: | bzr merge lp:~azzar1/unity/gs-integration |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Marco Trevisan (Treviño) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Review via email: mp+286915@code.launchpad.net |
This proposal supersedes a proposal from 2016-02-19.
Commit message
Gnome-software launcher integration.
Description of the change
Gnome-software launcher integration.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
Marco Trevisan (Treviño) (3v1n0) wrote : Posted in a previous version of this proposal | # |
Add libappstream-
Also, please, ensure that this merges with lp:~robert-ancell/unity/gnome-software
See comments, there might be some room for future optimization.
Andrea Azzarone (azzar1) wrote : Posted in a previous version of this proposal | # |
Done. We can talk more about the icon stuff later on.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:4076
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Marco Trevisan (Treviño) (3v1n0) wrote : Posted in a previous version of this proposal | # |
Ok, looks good...
It would be nice if we might also get the application icon path instead of the pixbuf, so please keep looking at this for next improvements.
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
Ok, looks good...
It would be nice if we might also get the application icon path instead of the pixbuf, so please keep looking at this for next improvements.
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2016-02-09 01:57:51 +0000 |
3 | +++ CMakeLists.txt 2016-02-23 15:50:24 +0000 |
4 | @@ -228,6 +228,7 @@ |
5 | set(UNITY_PROTOCOL_PRIVATE_DEPS unity-protocol-private>=7.1.0) |
6 | set(UNITY_PLUGIN_SHARED_DEPS |
7 | ${UNITY_PROTOCOL_PRIVATE_DEPS} |
8 | + appstream-glib |
9 | atk |
10 | atk-bridge-2.0 |
11 | cairo>=1.13.1 |
12 | |
13 | === modified file 'debian/control' |
14 | --- debian/control 2016-02-09 12:20:47 +0000 |
15 | +++ debian/control 2016-02-23 15:50:24 +0000 |
16 | @@ -13,6 +13,7 @@ |
17 | gsettings-desktop-schemas-dev, |
18 | gsettings-ubuntu-schemas (>= 0.0.1+14.04.20140219), |
19 | intltool (>= 0.35.0), |
20 | + libappstream-glib-dev, |
21 | libatk1.0-dev, |
22 | libbamf3-dev (>= 0.5.2~bzr0), |
23 | libboost-dev, |
24 | |
25 | === modified file 'launcher/LauncherController.cpp' |
26 | --- launcher/LauncherController.cpp 2015-12-17 22:32:37 +0000 |
27 | +++ launcher/LauncherController.cpp 2016-02-23 15:50:24 +0000 |
28 | @@ -41,6 +41,7 @@ |
29 | #include "ExpoLauncherIcon.h" |
30 | #include "TrashLauncherIcon.h" |
31 | #include "BFBLauncherIcon.h" |
32 | +#include "unity-shared/AppStreamApplication.h" |
33 | #include "unity-shared/IconRenderer.h" |
34 | #include "unity-shared/UScreen.h" |
35 | #include "unity-shared/UBusMessages.h" |
36 | @@ -61,13 +62,8 @@ |
37 | "<node>" |
38 | " <interface name='com.canonical.Unity.Launcher'>" |
39 | "" |
40 | - " <method name='AddLauncherItemFromPosition'>" |
41 | - " <arg type='s' name='title' direction='in'/>" |
42 | - " <arg type='s' name='icon' direction='in'/>" |
43 | - " <arg type='i' name='icon_x' direction='in'/>" |
44 | - " <arg type='i' name='icon_y' direction='in'/>" |
45 | - " <arg type='i' name='icon_size' direction='in'/>" |
46 | - " <arg type='s' name='desktop_file' direction='in'/>" |
47 | + " <method name='AddLauncherItem'>" |
48 | + " <arg type='s' name='appstream_app_id' direction='in'/>" |
49 | " <arg type='s' name='aptdaemon_task' direction='in'/>" |
50 | " </method>" |
51 | "" |
52 | @@ -506,44 +502,25 @@ |
53 | } |
54 | |
55 | void |
56 | -Controller::Impl::OnLauncherAddRequestSpecial(std::string const& path, |
57 | - std::string const& aptdaemon_trans_id, |
58 | - std::string const& icon_path, |
59 | - int icon_x, |
60 | - int icon_y, |
61 | - int icon_size) |
62 | +Controller::Impl::OnLauncherAddRequestSpecial(std::string const& appstream_app_id, |
63 | + std::string const& aptdaemon_trans_id) |
64 | { |
65 | - // Check if desktop file was supplied, or if it's set to SC's agent |
66 | - // See https://bugs.launchpad.net/unity/+bug/1002440 |
67 | - if (path.empty() || path == local::SOFTWARE_CENTER_AGENT) |
68 | + // Check if desktop file was supplied |
69 | + if (appstream_app_id.empty()) |
70 | return; |
71 | |
72 | auto const& icon = std::find_if(model_->begin(), model_->end(), |
73 | - [&path](AbstractLauncherIcon::Ptr const& i) { return (i->DesktopFile() == path); }); |
74 | + [&appstream_app_id](AbstractLauncherIcon::Ptr const& i) { return (i->DesktopFile() == appstream_app_id); }); |
75 | |
76 | if (icon != model_->end()) |
77 | return; |
78 | |
79 | - auto const& result = CreateSCLauncherIcon(path, aptdaemon_trans_id, icon_path); |
80 | + auto const& result = CreateSCLauncherIcon(appstream_app_id, aptdaemon_trans_id); |
81 | |
82 | if (result) |
83 | { |
84 | - // Setting the icon position and adding it to the model, makes the launcher |
85 | - // to compute its center |
86 | RegisterIcon(result, GetLastIconPriority<ApplicationLauncherIcon>("", true)); |
87 | - |
88 | - if (icon_x > 0 || icon_y > 0) |
89 | - { |
90 | - // This will ensure that the center of the new icon is set, so that |
91 | - // the animation could be done properly. |
92 | - sources_.AddIdle([this, icon_x, icon_y, result] { |
93 | - return !result->Animate(CurrentLauncher(), icon_x, icon_y); |
94 | - }); |
95 | - } |
96 | - else |
97 | - { |
98 | - result->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, true); |
99 | - } |
100 | + result->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, true); |
101 | } |
102 | } |
103 | |
104 | @@ -944,22 +921,11 @@ |
105 | return AbstractLauncherIcon::Ptr(); |
106 | } |
107 | |
108 | -SoftwareCenterLauncherIcon::Ptr Controller::Impl::CreateSCLauncherIcon(std::string const& file_path, |
109 | - std::string const& aptdaemon_trans_id, |
110 | - std::string const& icon_path) |
111 | +SoftwareCenterLauncherIcon::Ptr Controller::Impl::CreateSCLauncherIcon(std::string const& appstream_app_id, |
112 | + std::string const& aptdaemon_trans_id) |
113 | { |
114 | - SoftwareCenterLauncherIcon::Ptr result; |
115 | - |
116 | - ApplicationPtr app = ApplicationManager::Default().GetApplicationForDesktopFile(file_path); |
117 | - if (!app) |
118 | - return result; |
119 | - |
120 | - if (app->seen) |
121 | - return result; |
122 | - |
123 | - result = new SoftwareCenterLauncherIcon(app, aptdaemon_trans_id, icon_path); |
124 | - |
125 | - return result; |
126 | + ApplicationPtr app = std::make_shared<appstream::Application>(appstream_app_id); |
127 | + return SoftwareCenterLauncherIcon::Ptr(new SoftwareCenterLauncherIcon(app, aptdaemon_trans_id)); |
128 | } |
129 | |
130 | void Controller::Impl::AddRunningApps() |
131 | @@ -1548,16 +1514,11 @@ |
132 | |
133 | GVariant* Controller::Impl::OnDBusMethodCall(std::string const& method, GVariant *parameters) |
134 | { |
135 | - if (method == "AddLauncherItemFromPosition") |
136 | + if (method == "AddLauncherItem") |
137 | { |
138 | - glib::String icon, icon_title, desktop_file, aptdaemon_task; |
139 | - gint icon_x, icon_y, icon_size; |
140 | - |
141 | - g_variant_get(parameters, "(ssiiiss)", &icon_title, &icon, &icon_x, &icon_y, |
142 | - &icon_size, &desktop_file, &aptdaemon_task); |
143 | - |
144 | - OnLauncherAddRequestSpecial(desktop_file.Str(), aptdaemon_task.Str(), |
145 | - icon.Str(), icon_x, icon_y, icon_size); |
146 | + glib::String appstream_app_id, aptdaemon_trans_id; |
147 | + g_variant_get(parameters, "(ss)", &appstream_app_id, &aptdaemon_trans_id); |
148 | + OnLauncherAddRequestSpecial(appstream_app_id.Str(), aptdaemon_trans_id.Str()); |
149 | } |
150 | else if (method == "UpdateLauncherIconFavoriteState") |
151 | { |
152 | |
153 | === modified file 'launcher/LauncherControllerPrivate.h' |
154 | --- launcher/LauncherControllerPrivate.h 2015-12-07 18:34:41 +0000 |
155 | +++ launcher/LauncherControllerPrivate.h 2016-02-23 15:50:24 +0000 |
156 | @@ -69,8 +69,7 @@ |
157 | void OnDeviceIconAdded(AbstractLauncherIcon::Ptr const& icon); |
158 | |
159 | void OnLauncherAddRequest(std::string const& icon_uri, AbstractLauncherIcon::Ptr const& before); |
160 | - void OnLauncherAddRequestSpecial(std::string const& path, std::string const& aptdaemon_trans_id, |
161 | - std::string const& icon_path, int icon_x, int icon_y, int icon_size); |
162 | + void OnLauncherAddRequestSpecial(std::string const& appstream_app_id, std::string const& aptdaemon_trans_id); |
163 | void OnLauncherUpdateIconStickyState(std::string const& desktop_file, bool sticky); |
164 | void OnLauncherRemoveRequest(AbstractLauncherIcon::Ptr const& icon); |
165 | |
166 | @@ -90,7 +89,7 @@ |
167 | ApplicationLauncherIcon* CreateAppLauncherIcon(ApplicationPtr const&); |
168 | AbstractLauncherIcon::Ptr CreateFavoriteIcon(std::string const& icon_uri, bool emit_signal = false); |
169 | AbstractLauncherIcon::Ptr GetIconByUri(std::string const& icon_uri); |
170 | - SoftwareCenterLauncherIcon::Ptr CreateSCLauncherIcon(std::string const& file_path, std::string const& aptdaemon_trans_id, std::string const& icon_path); |
171 | + SoftwareCenterLauncherIcon::Ptr CreateSCLauncherIcon(std::string const& appstream_app_id, std::string const& aptdaemon_trans_id); |
172 | |
173 | void SetupIcons(); |
174 | void MigrateFavorites(); |
175 | |
176 | === modified file 'launcher/LauncherIcon.cpp' |
177 | --- launcher/LauncherIcon.cpp 2015-11-25 23:16:11 +0000 |
178 | +++ launcher/LauncherIcon.cpp 2016-02-23 15:50:24 +0000 |
179 | @@ -365,6 +365,20 @@ |
180 | return _unity_theme; |
181 | } |
182 | |
183 | +BaseTexturePtr LauncherIcon::TextureFromPixbuf(GdkPixbuf* pixbuf, int size, bool update_glow_colors) |
184 | +{ |
185 | + g_return_val_if_fail(GDK_IS_PIXBUF(pixbuf), BaseTexturePtr()); |
186 | + |
187 | + glib::Object<GdkPixbuf> scaled_pixbuf(gdk_pixbuf_scale_simple(pixbuf, size, size, GDK_INTERP_BILINEAR)); |
188 | + |
189 | + if (update_glow_colors) |
190 | + ColorForIcon(scaled_pixbuf, _background_color, _glow_color); |
191 | + |
192 | + BaseTexturePtr result; |
193 | + result.Adopt(nux::CreateTexture2DFromPixbuf(scaled_pixbuf, true)); |
194 | + return result; |
195 | +} |
196 | + |
197 | BaseTexturePtr LauncherIcon::TextureFromGtkTheme(std::string icon_name, int size, bool update_glow_colors) |
198 | { |
199 | GtkIconTheme* default_theme; |
200 | |
201 | === modified file 'launcher/LauncherIcon.h' |
202 | --- launcher/LauncherIcon.h 2015-11-25 23:16:11 +0000 |
203 | +++ launcher/LauncherIcon.h 2016-02-23 15:50:24 +0000 |
204 | @@ -269,6 +269,8 @@ |
205 | |
206 | virtual bool HandlesSpread () { return false; } |
207 | |
208 | + BaseTexturePtr TextureFromPixbuf(GdkPixbuf *pixbuf, int size, bool update_glow_colors = true); |
209 | + |
210 | BaseTexturePtr TextureFromGtkTheme(std::string name, int size, bool update_glow_colors = true); |
211 | |
212 | BaseTexturePtr TextureFromSpecificGtkTheme(GtkIconTheme* theme, std::string const& name, int size, bool update_glow_colors = true, bool is_default_theme = false); |
213 | |
214 | === modified file 'launcher/SimpleLauncherIcon.cpp' |
215 | --- launcher/SimpleLauncherIcon.cpp 2014-07-30 00:49:35 +0000 |
216 | +++ launcher/SimpleLauncherIcon.cpp 2016-02-23 15:50:24 +0000 |
217 | @@ -34,6 +34,7 @@ |
218 | SimpleLauncherIcon::SimpleLauncherIcon(IconType type) |
219 | : LauncherIcon(type) |
220 | , icon_name("", sigc::mem_fun(this, &SimpleLauncherIcon::SetIconName)) |
221 | + , icon_pixbuf(glib::Object<GdkPixbuf>(), sigc::mem_fun(this, &SimpleLauncherIcon::SetIconPixbuf)) |
222 | { |
223 | auto* theme = gtk_icon_theme_get_default(); |
224 | theme_changed_signal_.Connect(theme, "changed", [this] (GtkIconTheme *) { |
225 | @@ -53,17 +54,24 @@ |
226 | if (it != texture_map_.end()) |
227 | return it->second.GetPointer(); |
228 | |
229 | - std::string const& icon_string = icon_name(); |
230 | - |
231 | - if (icon_string.empty()) |
232 | - return nullptr; |
233 | - |
234 | BaseTexturePtr texture; |
235 | |
236 | - if (icon_string[0] == '/') |
237 | - texture = TextureFromPath(icon_string, size); |
238 | + if (icon_pixbuf()) |
239 | + { |
240 | + texture = TextureFromPixbuf(icon_pixbuf(), size); |
241 | + } |
242 | else |
243 | - texture = TextureFromGtkTheme(icon_string, size); |
244 | + { |
245 | + std::string const& icon_string = icon_name(); |
246 | + |
247 | + if (icon_string.empty()) |
248 | + return nullptr; |
249 | + |
250 | + if (icon_string[0] == '/') |
251 | + texture = TextureFromPath(icon_string, size); |
252 | + else |
253 | + texture = TextureFromGtkTheme(icon_string, size); |
254 | + } |
255 | |
256 | if (!texture) |
257 | return nullptr; |
258 | @@ -83,6 +91,17 @@ |
259 | return true; |
260 | } |
261 | |
262 | +bool SimpleLauncherIcon::SetIconPixbuf(glib::Object<GdkPixbuf>& target, glib::Object<GdkPixbuf> const& value) |
263 | +{ |
264 | + if (target == value) |
265 | + return false; |
266 | + |
267 | + target = value; |
268 | + ReloadIcon(); |
269 | + |
270 | + return true; |
271 | +} |
272 | + |
273 | void SimpleLauncherIcon::ReloadIcon() |
274 | { |
275 | texture_map_.clear(); |
276 | |
277 | === modified file 'launcher/SimpleLauncherIcon.h' |
278 | --- launcher/SimpleLauncherIcon.h 2013-09-19 16:44:03 +0000 |
279 | +++ launcher/SimpleLauncherIcon.h 2016-02-23 15:50:24 +0000 |
280 | @@ -38,6 +38,7 @@ |
281 | |
282 | // Properties |
283 | nux::Property<std::string> icon_name; |
284 | + nux::Property<glib::Object<GdkPixbuf>> icon_pixbuf; |
285 | |
286 | protected: |
287 | std::string GetName() const; |
288 | @@ -49,6 +50,7 @@ |
289 | private: |
290 | void ReloadIcon(); |
291 | bool SetIconName(std::string& target, std::string const& value); |
292 | + bool SetIconPixbuf(glib::Object<GdkPixbuf>& target, glib::Object<GdkPixbuf> const& value); |
293 | |
294 | private: |
295 | std::unordered_map<int, BaseTexturePtr> texture_map_; |
296 | |
297 | === modified file 'launcher/SoftwareCenterLauncherIcon.cpp' |
298 | --- launcher/SoftwareCenterLauncherIcon.cpp 2015-12-07 16:13:42 +0000 |
299 | +++ launcher/SoftwareCenterLauncherIcon.cpp 2016-02-23 15:50:24 +0000 |
300 | @@ -44,8 +44,7 @@ |
301 | |
302 | NUX_IMPLEMENT_OBJECT_TYPE(SoftwareCenterLauncherIcon); |
303 | SoftwareCenterLauncherIcon::SoftwareCenterLauncherIcon(ApplicationPtr const& app, |
304 | - std::string const& aptdaemon_trans_id, |
305 | - std::string const& icon_path) |
306 | + std::string const& aptdaemon_trans_id) |
307 | : WindowedLauncherIcon(IconType::APPLICATION) |
308 | , ApplicationLauncherIcon(app) |
309 | , aptdaemon_trans_(std::make_shared<glib::DBusProxy>("org.debian.apt", |
310 | @@ -69,61 +68,13 @@ |
311 | SetQuirk(Quirk::PROGRESS, (progress > 0)); |
312 | }); |
313 | |
314 | - if (!icon_path.empty()) |
315 | - icon_name = icon_path; |
316 | + if (app->icon_pixbuf()) |
317 | + icon_pixbuf = app->icon_pixbuf(); |
318 | |
319 | if (!aptdaemon_trans_id_.empty()) // Application is being installed, or hasn't been installed yet |
320 | tooltip_text = _("Waiting to install"); |
321 | } |
322 | |
323 | -bool SoftwareCenterLauncherIcon::Animate(nux::ObjectPtr<Launcher> const& launcher, int start_x, int start_y) |
324 | -{ |
325 | - using namespace std::placeholders; |
326 | - |
327 | - if (start_x <= 0 && start_y <= 0) |
328 | - { |
329 | - SetQuirk(Quirk::VISIBLE, true); |
330 | - return true; |
331 | - } |
332 | - |
333 | - int monitor = launcher->monitor(); |
334 | - auto const& icon_center = GetCenter(monitor); |
335 | - |
336 | - if (icon_center.x == 0 && icon_center.y == 0) |
337 | - return false; |
338 | - |
339 | - auto* floating_icon = new SimpleLauncherIcon(GetIconType()); |
340 | - AbstractLauncherIcon::Ptr floating_icon_ptr(floating_icon); |
341 | - floating_icon->icon_name = icon_name(); |
342 | - |
343 | - // Transform this in a spacer-icon and make it visible only on launcher's monitor |
344 | - icon_name = ""; |
345 | - SetQuirk(Quirk::VISIBLE, true, monitor); |
346 | - |
347 | - auto rcb = std::bind(&Launcher::RenderIconToTexture, launcher.GetPointer(), _1, _2, floating_icon_ptr); |
348 | - drag_window_ = new LauncherDragWindow(launcher->GetWidth(), rcb); |
349 | - drag_window_->SetBaseXY(start_x, start_y); |
350 | - drag_window_->SetAnimationTarget(icon_center.x, icon_center.y + (launcher->GetIconSize() / 2)); |
351 | - |
352 | - launcher->ForceReveal(true); |
353 | - drag_window_->ShowWindow(true); |
354 | - |
355 | - auto cb = sigc::bind(sigc::mem_fun(this, &SoftwareCenterLauncherIcon::OnDragAnimationFinished), launcher, floating_icon->icon_name()); |
356 | - drag_window_->anim_completed.connect(cb); |
357 | - drag_window_->StartSlowAnimation(); |
358 | - |
359 | - return true; |
360 | -} |
361 | - |
362 | -void SoftwareCenterLauncherIcon::OnDragAnimationFinished(nux::ObjectPtr<Launcher> const& launcher, std::string const& final_icon) |
363 | -{ |
364 | - icon_name = final_icon; |
365 | - drag_window_->ShowWindow(false); |
366 | - drag_window_.Release(); |
367 | - launcher->ForceReveal(false); |
368 | - SetQuirk(Quirk::VISIBLE, true); |
369 | -} |
370 | - |
371 | void SoftwareCenterLauncherIcon::ActivateLauncherIcon(ActionArg arg) |
372 | { |
373 | if (finished_) |
374 | @@ -144,62 +95,7 @@ |
375 | |
376 | std::string SoftwareCenterLauncherIcon::GetActualDesktopFileAfterInstall() |
377 | { |
378 | - // Fixup the _desktop_file because the one we get from software-center |
379 | - // is not the final one, e.g. the s-c-agent does send a temp one and |
380 | - // app-install-data points to the "wrong" one in /usr/share/app-install |
381 | - // |
382 | - // So: |
383 | - // - if there is a desktop file already and it startswith |
384 | - // /usr/share/app-install/desktop, then transform to |
385 | - // /usr/share/application |
386 | - // - if there is a desktop file with prefix /tmp/software-center-agent: |
387 | - // transform to /usr/share/application |
388 | - // (its using "/tmp/software-center-agent:$random:$pkgname.desktop") |
389 | - // maybe: |
390 | - // - and search in /var/lib/apt/lists/$pkgname.list |
391 | - // for a desktop file that roughly matches what we want |
392 | - auto const& desktop_file = DesktopFile(); |
393 | - |
394 | - // take /usr/share/app-install/desktop/foo:subdir__bar.desktop |
395 | - // and tranform it |
396 | - if (desktop_file.find("/share/app-install/desktop/") != std::string::npos) |
397 | - { |
398 | - auto colon_pos = desktop_file.rfind(":"); |
399 | - auto filename = desktop_file.substr(colon_pos + 1, desktop_file.length() - colon_pos); |
400 | - // the app-install-data package encodes subdirs in a funny way, once |
401 | - // that is fixed, this code can be dropped |
402 | - if (filename.find("__") != std::string::npos) |
403 | - { |
404 | - int pos = filename.find("__"); |
405 | - filename = filename.replace(pos, 2, "-"); |
406 | - } |
407 | - filename = DesktopUtilities::GetDesktopPathById(filename); |
408 | - return filename; |
409 | - } |
410 | - else if (desktop_file.find("/tmp/software-center-agent:") == 0) |
411 | - { |
412 | - // by convention the software-center-agent uses |
413 | - // /usr/share/applications/$pkgname.desktop |
414 | - // or |
415 | - // /usr/share/applications/extras-$pkgname.desktop |
416 | - auto colon_pos = desktop_file.rfind(":"); |
417 | - auto desktopf = desktop_file.substr(colon_pos + 1, desktop_file.length() - colon_pos); |
418 | - |
419 | - auto filename = DesktopUtilities::GetDesktopPathById(desktopf); |
420 | - |
421 | - if (!filename.empty()) |
422 | - return filename; |
423 | - |
424 | - // now try extras-$pkgname.desktop |
425 | - filename = DesktopUtilities::GetDesktopPathById("extras-" + desktopf); |
426 | - if (!filename.empty()) |
427 | - return filename; |
428 | - |
429 | - // FIXME: test if there is a file now and if not, search |
430 | - // /var/lib/dpkg/info/$pkgname.list for a desktop file |
431 | - } |
432 | - |
433 | - return desktop_file; |
434 | + return DesktopUtilities::GetDesktopPathById(DesktopFile()); |
435 | } |
436 | |
437 | void SoftwareCenterLauncherIcon::OnFinished(GVariant *params) |
438 | |
439 | === modified file 'launcher/SoftwareCenterLauncherIcon.h' |
440 | --- launcher/SoftwareCenterLauncherIcon.h 2013-08-28 16:41:20 +0000 |
441 | +++ launcher/SoftwareCenterLauncherIcon.h 2016-02-23 15:50:24 +0000 |
442 | @@ -24,7 +24,6 @@ |
443 | #include <string> |
444 | #include <UnityCore/GLibDBusProxy.h> |
445 | #include "ApplicationLauncherIcon.h" |
446 | -#include "LauncherDragWindow.h" |
447 | |
448 | namespace unity |
449 | { |
450 | @@ -39,10 +38,7 @@ |
451 | typedef nux::ObjectPtr<SoftwareCenterLauncherIcon> Ptr; |
452 | |
453 | SoftwareCenterLauncherIcon(ApplicationPtr const& app, |
454 | - std::string const& aptdaemon_trans_id, |
455 | - std::string const& icon_path); |
456 | - |
457 | - bool Animate(nux::ObjectPtr<Launcher> const& launcher, int start_x, int start_y); |
458 | + std::string const& aptdaemon_trans_id); |
459 | |
460 | protected: |
461 | std::string GetName() const; |
462 | @@ -52,10 +48,8 @@ |
463 | std::string GetActualDesktopFileAfterInstall(); |
464 | void OnFinished(GVariant *params); |
465 | void OnPropertyChanged(GVariant* params); |
466 | - void OnDragAnimationFinished(nux::ObjectPtr<Launcher> const&, std::string const&); |
467 | |
468 | glib::DBusProxy::Ptr aptdaemon_trans_; |
469 | - LauncherDragWindow::Ptr drag_window_; |
470 | bool finished_; |
471 | bool needs_urgent_; |
472 | std::string aptdaemon_trans_id_; |
473 | |
474 | === modified file 'tests/test_launcher_controller.cpp' |
475 | --- tests/test_launcher_controller.cpp 2016-02-23 15:50:24 +0000 |
476 | +++ tests/test_launcher_controller.cpp 2016-02-23 15:50:24 +0000 |
477 | @@ -1321,38 +1321,6 @@ |
478 | lc.launcher().remove_request.emit(device_icon); |
479 | } |
480 | |
481 | -TEST_F(TestLauncherController, LauncherAddRequestSpecial) |
482 | -{ |
483 | - std::string desktop = app::BZR_HANDLE_PATCH; |
484 | - std::string icon_uri = FavoriteStore::URI_PREFIX_APP + desktop; |
485 | - ASSERT_FALSE(lc.Impl()->GetIconByUri(icon_uri).IsValid()); |
486 | - EXPECT_CALL(*unity_app_, LogEvent(_, _)).Times(0); |
487 | - |
488 | - lc.Impl()->OnLauncherAddRequestSpecial(desktop, "", "", 0, 0, 32); |
489 | - |
490 | - auto const& sw_center_icon = lc.Impl()->GetIconByUri(icon_uri); |
491 | - ASSERT_TRUE(sw_center_icon.IsValid()); |
492 | - EXPECT_TRUE(sw_center_icon->IsSticky()); |
493 | - EXPECT_NE(dynamic_cast<SoftwareCenterLauncherIcon*>(sw_center_icon.GetPointer()), nullptr); |
494 | -} |
495 | - |
496 | -TEST_F(TestLauncherController, LauncherAddRequestSpecialIgnored) |
497 | -{ |
498 | - std::string desktop = app::BZR_HANDLE_PATCH; |
499 | - std::string icon_uri = FavoriteStore::URI_PREFIX_APP + desktop; |
500 | - |
501 | - MockApplicationLauncherIcon::Ptr bamf_icon(new MockApplicationLauncherIcon::Nice(desktop)); |
502 | - lc.Impl()->RegisterIcon(bamf_icon, std::numeric_limits<int>::max()); |
503 | - ASSERT_TRUE(lc.Impl()->GetIconByUri(icon_uri).IsValid()); |
504 | - |
505 | - EXPECT_CALL(*bamf_icon, Stick(false)).Times(0); |
506 | - |
507 | - int previous_model_size = lc.Impl()->model_->Size(); |
508 | - lc.Impl()->OnLauncherAddRequestSpecial(desktop, "", "", 0, 0, 32); |
509 | - |
510 | - EXPECT_EQ(previous_model_size, lc.Impl()->model_->Size()); |
511 | -} |
512 | - |
513 | TEST_F(TestLauncherController, SaveIconsOrder) |
514 | { |
515 | favorite_store.ClearFavorites(); |
516 | |
517 | === modified file 'tests/test_software_center_launcher_icon.cpp' |
518 | --- tests/test_software_center_launcher_icon.cpp 2016-02-23 15:50:24 +0000 |
519 | +++ tests/test_software_center_launcher_icon.cpp 2016-02-23 15:50:24 +0000 |
520 | @@ -42,28 +42,26 @@ |
521 | { |
522 | namespace |
523 | { |
524 | -const std::string PRE_INSTALL_ICON = "software-launcher-icon"; |
525 | const std::string FINAL_ICON = "org.gnome.Software"; |
526 | const std::string APP_NAME = "Software"; |
527 | const std::string LOCAL_DATA_DIR = BUILDDIR"/tests/data"; |
528 | const std::string GS_DESKTOP = LOCAL_DATA_DIR+"/applications/org.gnome.Software.desktop"; |
529 | -const std::string GS_APP_INSTALL_DESKTOP = "/usr/share/app-install/desktop/software-center:org.gnome.Software.desktop"; |
530 | +const std::string GS_APP_INSTALL_DESKTOP = "org.gnome.Software.desktop"; |
531 | } |
532 | |
533 | struct TestSoftwareCenterLauncherIcon : testmocks::TestUnityAppBase |
534 | { |
535 | TestSoftwareCenterLauncherIcon() |
536 | : gs(std::make_shared<MockApplication::Nice>(GS_APP_INSTALL_DESKTOP, FINAL_ICON, APP_NAME)) |
537 | - , icon(gs, "/com/canonical/unity/test/object/path", PRE_INSTALL_ICON) |
538 | + , icon(gs, "/com/canonical/unity/test/object/path") |
539 | {} |
540 | |
541 | struct MockSoftwareCenterLauncherIcon : SoftwareCenterLauncherIcon |
542 | { |
543 | MockSoftwareCenterLauncherIcon(ApplicationPtr const& app, |
544 | - std::string const& aptdaemon_trans_id, |
545 | - std::string const& icon_path) |
546 | + std::string const& aptdaemon_trans_id) |
547 | : WindowedLauncherIcon(IconType::APPLICATION) |
548 | - , SoftwareCenterLauncherIcon(app, aptdaemon_trans_id, icon_path) |
549 | + , SoftwareCenterLauncherIcon(app, aptdaemon_trans_id) |
550 | {} |
551 | |
552 | void LauncherIconUnstick() { LauncherIcon::UnStick(); } |
553 | @@ -71,7 +69,6 @@ |
554 | using SoftwareCenterLauncherIcon::GetActualDesktopFileAfterInstall; |
555 | using SoftwareCenterLauncherIcon::OnFinished; |
556 | using SoftwareCenterLauncherIcon::OnPropertyChanged; |
557 | - using SoftwareCenterLauncherIcon::drag_window_; |
558 | using LauncherIcon::GetRemoteUri; |
559 | }; |
560 | |
561 | @@ -94,9 +91,7 @@ |
562 | { |
563 | EXPECT_FALSE(icon.IsVisible()); |
564 | EXPECT_TRUE(icon.IsSticky()); |
565 | - EXPECT_EQ(AbstractLauncherIcon::Position::FLOATING, icon.position()); |
566 | EXPECT_EQ("Waiting to install", icon.tooltip_text()); |
567 | - EXPECT_EQ(PRE_INSTALL_ICON, icon.icon_name()); |
568 | } |
569 | |
570 | TEST_F(TestSoftwareCenterLauncherIcon, DesktopFileTransformTrivial) |
571 | @@ -106,28 +101,9 @@ |
572 | EXPECT_EQ(icon.GetActualDesktopFileAfterInstall(), GS_DESKTOP); |
573 | } |
574 | |
575 | -TEST_F(TestSoftwareCenterLauncherIcon, DesktopFileTransformAppInstall) |
576 | -{ |
577 | - // ensure that tranformation from app-install data desktop files works |
578 | - gs->desktop_file_ = "/usr/share/app-install/desktop/pkgname:kde4__afile.desktop"; |
579 | - EXPECT_EQ(icon.GetActualDesktopFileAfterInstall(), |
580 | - LOCAL_DATA_DIR+"/applications/kde4/afile.desktop"); |
581 | -} |
582 | - |
583 | -TEST_F(TestSoftwareCenterLauncherIcon, DesktopFileTransformSCAgent) |
584 | -{ |
585 | - // now simualte data coming from the software-center-agent |
586 | - gs->desktop_file_ = "/tmp/software-center-agent:VP2W9M:org.gnome.Software.desktop"; |
587 | - EXPECT_EQ(icon.GetActualDesktopFileAfterInstall(), GS_DESKTOP); |
588 | -} |
589 | - |
590 | -// simulate a OnFinished signal from a /usr/share/app-install location |
591 | -// and ensure that the remote uri is updated from temp location to |
592 | -// the real location |
593 | TEST_F(TestSoftwareCenterLauncherIcon, OnFinishedReplacesDesktopFile) |
594 | { |
595 | icon.OnFinished(glib::Variant(g_variant_new("(s)", "exit-success"))); |
596 | - |
597 | EXPECT_EQ(GS_DESKTOP, icon.DesktopFile()); |
598 | } |
599 | |
600 | @@ -162,7 +138,7 @@ |
601 | { |
602 | // Using an icon ptr, to get the removed signal to be properly emitted |
603 | nux::ObjectPtr<MockSoftwareCenterLauncherIcon> icon_ptr( |
604 | - new MockSoftwareCenterLauncherIcon(gs, "/com/canonical/unity/test/object/path", PRE_INSTALL_ICON)); |
605 | + new MockSoftwareCenterLauncherIcon(gs, "/com/canonical/unity/test/object/path")); |
606 | |
607 | bool removed = false; |
608 | auto& app_manager = unity::ApplicationManager::Default(); |
609 | @@ -217,65 +193,15 @@ |
610 | EXPECT_EQ(icon.tooltip_text(), gs->title()); |
611 | } |
612 | |
613 | -TEST_F(TestSoftwareCenterLauncherIcon, OnFinishedUpdatesIcon) |
614 | -{ |
615 | - icon.icon_name = "foo-icon"; |
616 | - icon.OnFinished(glib::Variant(g_variant_new("(s)", "exit-success"))); |
617 | - EXPECT_EQ(icon.icon_name(), gs->icon()); |
618 | -} |
619 | - |
620 | TEST_F(TestSoftwareCenterLauncherIcon, OnFinishedLogsEvent) |
621 | { |
622 | EXPECT_CALL(*unity_app_, LogEvent(ApplicationEventType::ACCESS, _)); |
623 | icon.OnFinished(glib::Variant(g_variant_new("(s)", "exit-success"))); |
624 | } |
625 | |
626 | -TEST_F(TestSoftwareCenterLauncherIcon, AnimateToInvalidPosition) |
627 | -{ |
628 | - EXPECT_FALSE(icon.Animate(CreateLauncher(), 1, 2)); |
629 | - EXPECT_FALSE(icon.IsVisible()); |
630 | - EXPECT_EQ(PRE_INSTALL_ICON, icon.icon_name()); |
631 | -} |
632 | - |
633 | -TEST_F(TestSoftwareCenterLauncherIcon, AnimateFromInvalidPosition) |
634 | -{ |
635 | - EXPECT_TRUE(icon.Animate(CreateLauncher(), 0, 0)); |
636 | - EXPECT_TRUE(icon.IsVisible()); |
637 | - EXPECT_EQ(PRE_INSTALL_ICON, icon.icon_name()); |
638 | -} |
639 | - |
640 | #pragma GCC diagnostic push |
641 | #pragma GCC diagnostic ignored "-Wunused-variable" |
642 | |
643 | -struct MultiMonitor : TestSoftwareCenterLauncherIcon, WithParamInterface<unsigned> {}; |
644 | -INSTANTIATE_TEST_CASE_P(TestSoftwareCenterLauncherIcon, MultiMonitor, Range<unsigned>(0, monitors::MAX, 1)); |
645 | - |
646 | -TEST_P(/*TestSoftwareCenterLauncherIcon*/MultiMonitor, Animate) |
647 | -{ |
648 | - auto launcher = CreateLauncher(); |
649 | - launcher->monitor = GetParam(); |
650 | - icon.SetCenter({1, 1, 0}, launcher->monitor()); |
651 | - ASSERT_TRUE(icon.Animate(launcher, 2, 2)); |
652 | - EXPECT_FALSE(icon.IsVisible()); |
653 | - EXPECT_TRUE(icon.icon_name().empty()); |
654 | - |
655 | - for (unsigned i = 0; i < monitors::MAX; ++i) |
656 | - ASSERT_EQ(static_cast<int>(i) == launcher->monitor(), icon.IsVisibleOnMonitor(i)); |
657 | - |
658 | - bool animated = false; |
659 | - ASSERT_TRUE(icon.drag_window_); |
660 | - icon.drag_window_->anim_completed.connect([&animated] { animated = true; }); |
661 | - Utils::WaitUntilMSec(animated); |
662 | - ASSERT_TRUE(animated); |
663 | - |
664 | - EXPECT_EQ(PRE_INSTALL_ICON, icon.icon_name()); |
665 | - EXPECT_FALSE(icon.drag_window_); |
666 | - |
667 | - for (unsigned i = 0; i < monitors::MAX; ++i) |
668 | - ASSERT_TRUE(icon.IsVisibleOnMonitor(i)); |
669 | - |
670 | - EXPECT_TRUE(icon.IsVisible()); |
671 | -} |
672 | |
673 | struct InstallProgress : TestSoftwareCenterLauncherIcon, WithParamInterface<int> {}; |
674 | INSTANTIATE_TEST_CASE_P(TestSoftwareCenterLauncherIcon, InstallProgress, Range<int>(0, 99, 10)); |
675 | |
676 | === added file 'unity-shared/AppStreamApplication.cpp' |
677 | --- unity-shared/AppStreamApplication.cpp 1970-01-01 00:00:00 +0000 |
678 | +++ unity-shared/AppStreamApplication.cpp 2016-02-23 15:50:24 +0000 |
679 | @@ -0,0 +1,104 @@ |
680 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
681 | +/* |
682 | + * Copyright (C) 2016 Canonical Ltd |
683 | + * |
684 | + * This program is free software: you can redistribute it and/or modify |
685 | + * it under the terms of the GNU General Public License version 3 as |
686 | + * published by the Free Software Foundation. |
687 | + * |
688 | + * This program is distributed in the hope that it will be useful, |
689 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
690 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
691 | + * GNU General Public License for more details. |
692 | + * |
693 | + * You should have received a copy of the GNU General Public License |
694 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
695 | + * |
696 | + * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com> |
697 | + */ |
698 | + |
699 | +#include "AppStreamApplication.h" |
700 | + |
701 | +#include <appstream-glib.h> |
702 | + |
703 | +#include <iostream> |
704 | + |
705 | +namespace unity |
706 | +{ |
707 | +namespace appstream |
708 | +{ |
709 | + |
710 | +Application::Application(std::string const& appstream_id) |
711 | + : appstream_id_(appstream_id) |
712 | +{ |
713 | + desktop_file.SetGetterFunction([this](){ return appstream_id_; }); |
714 | + title.SetGetterFunction([this](){ return title_; }); |
715 | + icon_pixbuf.SetGetterFunction([this](){ return icon_pixbuf_; }); |
716 | + |
717 | + glib::Object<AsStore> as_store(as_store_new()); |
718 | + g_return_if_fail(as_store); |
719 | + |
720 | + as_store_load(as_store, AS_STORE_LOAD_FLAG_APP_INFO_SYSTEM, nullptr, nullptr); |
721 | + |
722 | + AsApp *as_app = as_store_get_app_by_id(as_store, appstream_id_.c_str()); |
723 | + g_return_if_fail(as_app); |
724 | + |
725 | + title_ = glib::gchar_to_string(as_app_get_name(as_app, nullptr)); |
726 | + |
727 | + AsIcon *as_icon = as_app_get_icon_default(as_app); |
728 | + g_return_if_fail(as_icon); |
729 | + |
730 | + as_icon_load(as_icon, AS_ICON_LOAD_FLAG_SEARCH_SIZE, nullptr); |
731 | + icon_pixbuf_ = glib::Object<GdkPixbuf>(as_icon_get_pixbuf(as_icon), glib::AddRef()); |
732 | +} |
733 | + |
734 | +AppType Application::type() const |
735 | +{ |
736 | + return AppType::NORMAL; |
737 | +} |
738 | + |
739 | +std::string Application::repr() const |
740 | +{ |
741 | + std::ostringstream sout; |
742 | + sout << "<AppStream::Application " << appstream_id_ << " >"; |
743 | + return sout.str(); |
744 | +} |
745 | + |
746 | +WindowList const& Application::GetWindows() const |
747 | +{ |
748 | + return window_list_; |
749 | +} |
750 | + |
751 | +bool Application::OwnsWindow(Window window_id) const |
752 | +{ |
753 | + return false; |
754 | +} |
755 | + |
756 | +std::vector<std::string> Application::GetSupportedMimeTypes() const |
757 | +{ |
758 | + return std::vector<std::string>(); |
759 | +} |
760 | + |
761 | +ApplicationWindowPtr Application::GetFocusableWindow() const |
762 | +{ |
763 | + return nullptr; |
764 | +} |
765 | + |
766 | +void Application::Focus(bool show_on_visible, int monitor) const |
767 | +{} |
768 | + |
769 | +void Application::Quit() const |
770 | +{} |
771 | + |
772 | +bool Application::CreateLocalDesktopFile() const |
773 | +{ |
774 | + return false; |
775 | +} |
776 | + |
777 | +std::string Application::desktop_id() const |
778 | +{ |
779 | + return ""; |
780 | +} |
781 | + |
782 | +} |
783 | +} |
784 | |
785 | === added file 'unity-shared/AppStreamApplication.h' |
786 | --- unity-shared/AppStreamApplication.h 1970-01-01 00:00:00 +0000 |
787 | +++ unity-shared/AppStreamApplication.h 2016-02-23 15:50:24 +0000 |
788 | @@ -0,0 +1,61 @@ |
789 | +// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*- |
790 | +/* |
791 | + * Copyright (C) 2016 Canonical Ltd |
792 | + * |
793 | + * This program is free software: you can redistribute it and/or modify |
794 | + * it under the terms of the GNU General Public License version 3 as |
795 | + * published by the Free Software Foundation. |
796 | + * |
797 | + * This program is distributed in the hope that it will be useful, |
798 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
799 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
800 | + * GNU General Public License for more details. |
801 | + * |
802 | + * You should have received a copy of the GNU General Public License |
803 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
804 | + * |
805 | + * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com> |
806 | + */ |
807 | + |
808 | +#ifndef UNITYSHARED_APPSTREAM_APPLICATION_H |
809 | +#define UNITYSHARED_APPSTREAM_APPLICATION_H |
810 | + |
811 | +#include "DesktopApplicationManager.h" |
812 | + |
813 | +namespace unity |
814 | +{ |
815 | +namespace appstream |
816 | +{ |
817 | + |
818 | +class Application : public desktop::Application |
819 | +{ |
820 | +public: |
821 | + Application(std::string const& appstream_id); |
822 | + |
823 | + AppType type() const override; |
824 | + std::string repr() const override; |
825 | + |
826 | + WindowList const& GetWindows() const override; |
827 | + bool OwnsWindow(Window window_id) const override; |
828 | + |
829 | + std::vector<std::string> GetSupportedMimeTypes() const override; |
830 | + |
831 | + ApplicationWindowPtr GetFocusableWindow() const override; |
832 | + void Focus(bool show_on_visible, int monitor) const override; |
833 | + void Quit() const override; |
834 | + |
835 | + bool CreateLocalDesktopFile() const override; |
836 | + |
837 | + std::string desktop_id() const override; |
838 | + |
839 | +private: |
840 | + std::string appstream_id_; |
841 | + std::string title_; |
842 | + glib::Object<_GdkPixbuf> icon_pixbuf_; |
843 | + WindowList window_list_; |
844 | +}; |
845 | + |
846 | +} |
847 | +} |
848 | + |
849 | +#endif |
850 | |
851 | === modified file 'unity-shared/ApplicationManager.h' |
852 | --- unity-shared/ApplicationManager.h 2015-11-26 00:20:23 +0000 |
853 | +++ unity-shared/ApplicationManager.h 2016-02-23 15:50:24 +0000 |
854 | @@ -25,8 +25,10 @@ |
855 | |
856 | #include <sigc++/signal.h> |
857 | #include <NuxCore/Property.h> |
858 | +#include <UnityCore/GLibWrapper.h> |
859 | #include <unity-shared/WindowManager.h> |
860 | |
861 | +struct _GdkPixbuf; |
862 | |
863 | namespace unity |
864 | { |
865 | @@ -153,6 +155,7 @@ |
866 | nux::ROProperty<std::string> desktop_file; |
867 | nux::ROProperty<std::string> title; |
868 | nux::ROProperty<std::string> icon; |
869 | + nux::ROProperty<glib::Object<_GdkPixbuf>> icon_pixbuf; |
870 | |
871 | // Considering using a property for the "unity-seen" quark |
872 | nux::RWProperty<bool> seen; |
873 | |
874 | === modified file 'unity-shared/CMakeLists.txt' |
875 | --- unity-shared/CMakeLists.txt 2015-11-06 18:05:38 +0000 |
876 | +++ unity-shared/CMakeLists.txt 2016-02-23 15:50:24 +0000 |
877 | @@ -18,6 +18,7 @@ |
878 | # |
879 | set (UNITY_SHARED_SOURCES |
880 | ApplicationManager.cpp |
881 | + AppStreamApplication.cpp |
882 | BGHash.cpp |
883 | CoverArt.cpp |
884 | BackgroundEffectHelper.cpp |
885 | |
886 | === modified file 'unity-shared/DesktopApplicationManager.h' |
887 | --- unity-shared/DesktopApplicationManager.h 2014-01-15 14:51:10 +0000 |
888 | +++ unity-shared/DesktopApplicationManager.h 2016-02-23 15:50:24 +0000 |
889 | @@ -24,7 +24,7 @@ |
890 | #include <UnityCore/GLibWrapper.h> |
891 | #include <UnityCore/GLibSignal.h> |
892 | |
893 | -#include "unity-shared/ApplicationManager.h" |
894 | +#include "ApplicationManager.h" |
895 | |
896 | namespace unity |
897 | { |
FAILED: Continuous integration, rev:4070 jenkins. qa.ubuntu. com/job/ unity-ci/ 1409/ jenkins. qa.ubuntu. com/job/ unity-xenial- amd64-ci/ 59/console jenkins. qa.ubuntu. com/job/ unity-xenial- armhf-ci/ 59/console jenkins. qa.ubuntu. com/job/ unity-xenial- i386-ci/ 59/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- ci/1409/ rebuild
http://