Merge lp:~3v1n0/unity/launcher-draggable-icons-6.0 into lp:unity/6.0

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Marco Trevisan (Treviño)
Approved revision: no longer in the source branch.
Merged at revision: 2692
Proposed branch: lp:~3v1n0/unity/launcher-draggable-icons-6.0
Merge into: lp:unity/6.0
Diff against target: 7558 lines (+3857/-1097)
72 files modified
UnityCore/DesktopUtilities.cpp (+29/-9)
UnityCore/DesktopUtilities.h (+1/-0)
UnityCore/GLibDBusProxy.cpp (+0/-4)
com.canonical.Unity.gschema.xml (+3/-3)
launcher/AbstractLauncherIcon.h (+16/-2)
launcher/BFBLauncherIcon.cpp (+1/-0)
launcher/BamfLauncherIcon.cpp (+31/-48)
launcher/BamfLauncherIcon.h (+0/-1)
launcher/CMakeLists.txt (+1/-0)
launcher/DesktopLauncherIcon.cpp (+19/-6)
launcher/DesktopLauncherIcon.h (+4/-12)
launcher/DeviceLauncherSection.cpp (+14/-7)
launcher/DeviceLauncherSection.h (+3/-5)
launcher/DndData.cpp (+5/-5)
launcher/DndData.h (+1/-1)
launcher/ExpoLauncherIcon.cpp (+64/-0)
launcher/ExpoLauncherIcon.h (+45/-0)
launcher/FavoriteStore.cpp (+93/-4)
launcher/FavoriteStore.h (+21/-8)
launcher/FavoriteStoreGSettings.cpp (+67/-68)
launcher/FavoriteStoreGSettings.h (+7/-4)
launcher/FavoriteStorePrivate.cpp (+14/-0)
launcher/FavoriteStorePrivate.h (+3/-1)
launcher/HudLauncherIcon.cpp (+2/-1)
launcher/Launcher.cpp (+83/-108)
launcher/Launcher.h (+5/-8)
launcher/LauncherController.cpp (+526/-341)
launcher/LauncherController.h (+1/-3)
launcher/LauncherControllerPrivate.h (+28/-41)
launcher/LauncherIcon.cpp (+31/-4)
launcher/LauncherIcon.h (+5/-9)
launcher/LauncherModel.cpp (+34/-32)
launcher/MockLauncherIcon.h (+11/-15)
launcher/SoftwareCenterLauncherIcon.cpp (+27/-38)
launcher/SoftwareCenterLauncherIcon.h (+1/-1)
launcher/SpacerLauncherIcon.cpp (+1/-1)
launcher/SpacerLauncherIcon.h (+0/-4)
launcher/StandaloneLauncher.cpp (+1/-1)
launcher/TrashLauncherIcon.cpp (+1/-0)
launcher/VolumeLauncherIcon.cpp (+34/-4)
launcher/VolumeLauncherIcon.h (+3/-0)
manual-tests/Launcher.txt (+15/-0)
panel/PanelMenuView.h (+0/-1)
plugins/unityshell/src/unityshell.cpp (+5/-7)
plugins/unityshell/unityshell.xml.in (+0/-6)
tests/CMakeLists.txt (+19/-11)
tests/gmockvolume.c (+4/-3)
tests/test_bamf_launcher_icon.cpp (+70/-2)
tests/test_bfb_launcher_icon.cpp (+11/-8)
tests/test_desktop_launcher_icon.cpp (+80/-0)
tests/test_desktop_utilities.cpp (+52/-22)
tests/test_device_launcher_section.cpp (+19/-54)
tests/test_expo_launcher_icon.cpp (+58/-0)
tests/test_favorite_store.cpp (+111/-0)
tests/test_favorite_store_gsettings.cpp (+52/-29)
tests/test_hud_launcher_icon.cpp (+53/-0)
tests/test_launcher.cpp (+226/-15)
tests/test_launcher_controller.cpp (+1246/-44)
tests/test_launcher_icon.cpp (+113/-0)
tests/test_launcher_model.cpp (+182/-40)
tests/test_main.cpp (+1/-0)
tests/test_main_xless.cpp (+1/-1)
tests/test_mock_devices.h (+93/-0)
tests/test_software_center_launcher_icon.cpp (+74/-0)
tests/test_trash_launcher_icon.cpp (+39/-0)
tests/test_volume_launcher_icon.cpp (+67/-46)
unity-shared/PluginAdapter.h (+2/-0)
unity-shared/PluginAdapterCompiz.cpp (+5/-0)
unity-shared/PluginAdapterStandalone.cpp (+15/-7)
unity-shared/WindowManager.cpp (+5/-0)
unity-shared/WindowManager.h (+1/-0)
unity-standalone/StandaloneUnity.cpp (+2/-2)
To merge this branch: bzr merge lp:~3v1n0/unity/launcher-draggable-icons-6.0
Reviewer Review Type Date Requested Status
Andrea Azzarone (community) Approve
Brandon Schaefer (community) Approve
Review via email: mp+124838@code.launchpad.net

Commit message

LauncherController, FavoriteStore, Launcher, Icons: always use sort priority based on favorites to get positioned on launcher

This is the continuum of the work started in lp:~3v1n0/unity/keep-priority-launcher-model, here we use the launcher icons priority to correctly order the icons in the launcher, based on the position that they have in the favorite store.

The unity launcher favorite store now handles not only desktop paths or id but also (mostly) icons uris (such as application://desktop-id or unity://desktop-icon or device://uuid); these values are used by LauncherController to dispose these icons in the launchers.

To do this, I had to change AbstractLauncherIcon to define a position property that now LauncherModel uses together with the icon priority (that is now set by default to the icon type but then can change during the usage, or based on favorites).

The icons ordering has changed a lot: now the favorites control everything (except BFB and trash) and we add the icons based on their defined position. Added two special places: "unity://running-apps" and "unity://devices" that optionally defines where these kind of icons should be placed. This is not strict by the way, because if these uris are not defined we add them by default at the bottom of the launcher main model.

When a new Device or Application icon is added to the launcher, we append it to the list of the non-sticky devices or applications.

Favorites reordering, removal or additions have been refactored to fit to our new system; when we save the favorites, the position of the "running-apps" or "attached-devices" is computed based on where the first icon of this type is placed.

The expo icon is handled differently, since it is not added if we have no workspaces available; it also updates its visibility based on the workspaces settings.

SoftwareCenterLauncher icons are now handled differently: we now fully consider them as sticky application icons, so we firstly add them to the model (setting their priority based on the last sticky icon we have), then we animate them. They already know where they should go, based on model calculations (also fixed a bug that caused them not to get the overlay shourtcut when added).

See other commit messages for more info, they should be quite comprehensive.

----

Testing: updated and added a lot of new unit tests to cover (hopefully) all the changes I've done (that's mostly why this diff is so big, since the real changes are less than the half of the changed code) and to test the areas that we never tested before, just few stats:

test-gtest: added 13 new test cases (+5%)
test-gtest-xless: added 94 new test cases (+56%)

Description of the change

To post a comment you must log in.
Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

Looks go to me. +1

review: Approve
Revision history for this message
Andrea Azzarone (azzar1) wrote :

Approve as discussed on IRC.

review: Approve
Revision history for this message
Unity Merger (unity-merger) wrote :

The Jenkins job https://jenkins.qa.ubuntu.com/job/automerge-unity/1337/console reported an error when processing this lp:~3v1n0/unity/launcher-draggable-icons-6.0 branch.
Not merging it.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'UnityCore/DesktopUtilities.cpp'
2--- UnityCore/DesktopUtilities.cpp 2012-06-01 09:33:15 +0000
3+++ UnityCore/DesktopUtilities.cpp 2012-09-18 15:52:46 +0000
4@@ -19,8 +19,10 @@
5 */
6
7 #include <algorithm>
8+#include <memory>
9
10 #include <glib.h>
11+#include <gio/gdesktopappinfo.h>
12
13 #include "DesktopUtilities.h"
14 #include "GLibWrapper.h"
15@@ -119,23 +121,41 @@
16 return GetDesktopID(data_dirs, desktop_path);
17 }
18
19+std::string DesktopUtilities::GetDesktopPathById(std::string const& desktop_id)
20+{
21+ if (desktop_id.empty())
22+ return "";
23+
24+ glib::Object<GDesktopAppInfo> info;
25+
26+ if (desktop_id.find(G_DIR_SEPARATOR_S) != std::string::npos)
27+ info = g_desktop_app_info_new_from_filename(desktop_id.c_str());
28+ else
29+ info = g_desktop_app_info_new(desktop_id.c_str());
30+
31+ if (info)
32+ {
33+ const char* filename = g_desktop_app_info_get_filename(info);
34+
35+ if (filename)
36+ return filename;
37+ }
38+
39+ return "";
40+}
41
42 std::string DesktopUtilities::GetBackgroundColor(std::string const& desktop_path)
43 {
44- GKeyFile* key_file = g_key_file_new();
45+ std::shared_ptr<GKeyFile> key_file(g_key_file_new(), g_key_file_free);
46
47 glib::Error error;
48- g_key_file_load_from_file(key_file, desktop_path.c_str(), static_cast<GKeyFileFlags>(0), &error);
49+ g_key_file_load_from_file(key_file.get(), desktop_path.c_str(), static_cast<GKeyFileFlags>(0), &error);
50
51 if (error)
52- {
53- g_key_file_free(key_file);
54 return "";
55- }
56-
57- glib::String value(g_key_file_get_string(key_file, "Desktop Entry", "X-Unity-IconBackgroundColor", &error));
58-
59- g_key_file_free(key_file);
60+
61+ glib::String value(g_key_file_get_string(key_file.get(), "Desktop Entry", "X-Unity-IconBackgroundColor", &error));
62+
63 return value.Str();
64 }
65
66
67=== modified file 'UnityCore/DesktopUtilities.h'
68--- UnityCore/DesktopUtilities.h 2012-05-25 07:37:21 +0000
69+++ UnityCore/DesktopUtilities.h 2012-09-18 15:52:46 +0000
70@@ -36,6 +36,7 @@
71 static std::string GetDesktopID(std::string const& desktop_path);
72 static std::string GetDesktopID(std::vector<std::string> const& default_paths,
73 std::string const& desktop_path);
74+ static std::string GetDesktopPathById(std::string const& desktop_id);
75
76 static std::string GetBackgroundColor(std::string const& desktop_path);
77 };
78
79=== modified file 'UnityCore/GLibDBusProxy.cpp'
80--- UnityCore/GLibDBusProxy.cpp 2012-07-17 13:42:48 +0000
81+++ UnityCore/GLibDBusProxy.cpp 2012-09-18 15:52:46 +0000
82@@ -90,7 +90,6 @@
83
84 glib::Object<GDBusProxy> proxy_;
85 glib::Object<GCancellable> cancellable_;
86- guint watcher_id_;
87 bool connected_;
88
89 glib::Signal<void, GDBusProxy*, char*, char*, GVariant*> g_signal_connection_;
90@@ -113,7 +112,6 @@
91 , bus_type_(bus_type)
92 , flags_(flags)
93 , cancellable_(g_cancellable_new())
94- , watcher_id_(0)
95 , connected_(false)
96 {
97 StartReconnectionTimeout();
98@@ -122,8 +120,6 @@
99 DBusProxy::Impl::~Impl()
100 {
101 g_cancellable_cancel(cancellable_);
102- if (watcher_id_)
103- g_bus_unwatch_name(watcher_id_);
104 }
105
106 void DBusProxy::Impl::StartReconnectionTimeout()
107
108=== modified file 'com.canonical.Unity.gschema.xml'
109--- com.canonical.Unity.gschema.xml 2012-08-31 09:15:33 +0000
110+++ com.canonical.Unity.gschema.xml 2012-09-18 15:52:46 +0000
111@@ -44,9 +44,9 @@
112 </schema>
113 <schema path="/com/canonical/unity/launcher/" id="com.canonical.Unity.Launcher" gettext-domain="unity">
114 <key type="as" name="favorites">
115- <default>[ 'ubiquity-gtkui.desktop', 'nautilus-home.desktop', 'firefox.desktop', 'libreoffice-writer.desktop', 'libreoffice-calc.desktop', 'libreoffice-impress.desktop', 'ubuntu-software-center.desktop', 'ubuntuone-installer.desktop', 'gnome-control-center.desktop' ]</default>
116- <summary>List of desktop file ids for favorites on the launcher.</summary>
117- <description>These applications are shown in the Launcher by default.</description>
118+ <default>[ 'application://ubiquity-gtkui.desktop', 'application://nautilus-home.desktop', 'application://firefox.desktop', 'application://libreoffice-writer.desktop', 'application://libreoffice-calc.desktop', 'application://libreoffice-impress.desktop', 'application://ubuntu-software-center.desktop', 'application://ubuntuone-installer.desktop', 'application://gnome-control-center.desktop', 'unity://running-apps', 'unity://expo-icon', 'unity://devices' ]</default>
119+ <summary>List of items that should be shown by default in the launcher</summary>
120+ <description>These items can be application://desktop-id.desktop, device://uiid and unity://special-id (including unity://running-apps that specifies the position of the ran applications, unity://devices the position of the attached devices, unity://expo-icon the position of the workspace switcher and unity://show-desktop-icon the position of the show-desktop icon); the order of this list determines the launcher items position.</description>
121 </key>
122 <key type="s" name="favorite-migration">
123 <default>''</default>
124
125=== modified file 'launcher/AbstractLauncherIcon.h'
126--- launcher/AbstractLauncherIcon.h 2012-08-15 02:51:33 +0000
127+++ launcher/AbstractLauncherIcon.h 2012-09-18 15:52:46 +0000
128@@ -93,6 +93,7 @@
129 DESKTOP,
130 PLACE,
131 DEVICE,
132+ SPACER,
133 TRASH,
134 END
135 };
136@@ -117,10 +118,18 @@
137 LAST
138 };
139
140+ enum class Position
141+ {
142+ BEGIN,
143+ FLOATING,
144+ END
145+ };
146+
147 virtual ~AbstractLauncherIcon() {}
148
149 nux::Property<std::string> tooltip_text;
150 nux::Property<bool> tooltip_enabled;
151+ nux::Property<Position> position;
152
153 virtual void HideTooltip() = 0;
154
155@@ -158,8 +167,6 @@
156
157 virtual const bool WindowVisibleOnViewport() = 0;
158
159- virtual bool IsSpacer() = 0;
160-
161 virtual float PresentUrgency() = 0;
162
163 virtual float GetProgress() = 0;
164@@ -211,6 +218,11 @@
165
166 virtual void UnStick() = 0;
167
168+ static int DefaultPriority(IconType type)
169+ {
170+ return static_cast<int>(type) * 1000;
171+ }
172+
173 sigc::signal<void, int, int, unsigned long> mouse_down;
174 sigc::signal<void, int, int, unsigned long> mouse_up;
175 sigc::signal<void, int, int, unsigned long> mouse_click;
176@@ -221,6 +233,8 @@
177 sigc::signal<void, AbstractLauncherIcon::Ptr> remove;
178 sigc::signal<void, nux::ObjectPtr<nux::View>> tooltip_visible;
179 sigc::signal<void> visibility_changed;
180+ sigc::signal<void> position_saved;
181+ sigc::signal<void> position_forgot;
182
183 sigc::connection needs_redraw_connection;
184 sigc::connection on_icon_added_connection;
185
186=== modified file 'launcher/BFBLauncherIcon.cpp'
187--- launcher/BFBLauncherIcon.cpp 2012-08-15 02:51:33 +0000
188+++ launcher/BFBLauncherIcon.cpp 2012-09-18 15:52:46 +0000
189@@ -36,6 +36,7 @@
190 {
191 tooltip_text = _("Dash Home");
192 icon_name = PKGDATADIR"/launcher_bfb.png";
193+ position = Position::BEGIN;
194 SetQuirk(Quirk::VISIBLE, true);
195 SetQuirk(Quirk::RUNNING, false);
196
197
198=== modified file 'launcher/BamfLauncherIcon.cpp'
199--- launcher/BamfLauncherIcon.cpp 2012-08-21 21:46:54 +0000
200+++ launcher/BamfLauncherIcon.cpp 2012-09-18 15:52:46 +0000
201@@ -74,11 +74,7 @@
202 tooltip_text = BamfName();
203 icon_name = (icon ? icon.Str() : DEFAULT_ICON);
204
205- if (IsSticky())
206- SetQuirk(Quirk::VISIBLE, true);
207- else
208- SetQuirk(Quirk::VISIBLE, bamf_view_user_visible(bamf_view));
209-
210+ SetQuirk(Quirk::VISIBLE, bamf_view_user_visible(bamf_view));
211 SetQuirk(Quirk::ACTIVE, bamf_view_is_active(bamf_view));
212 SetQuirk(Quirk::RUNNING, bamf_view_is_running(bamf_view));
213
214@@ -95,7 +91,7 @@
215 sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-removed",
216 [&] (BamfView*, BamfView*) { EnsureWindowState(); });
217 _gsignals.Add(sig);
218-
219+
220 sig = new glib::Signal<void, BamfView*, BamfView*>(bamf_view, "child-moved",
221 [&] (BamfView *, BamfView *) {
222 EnsureWindowState();
223@@ -173,9 +169,12 @@
224
225 BamfLauncherIcon::~BamfLauncherIcon()
226 {
227- if (_bamf_app)
228+ if (_bamf_app.IsType(BAMF_TYPE_APPLICATION))
229+ {
230+ bamf_view_set_sticky(BAMF_VIEW(_bamf_app.RawPtr()), FALSE);
231 g_object_set_qdata(G_OBJECT(_bamf_app.RawPtr()),
232 g_quark_from_static_string("unity-seen"), nullptr);
233+ }
234 }
235
236 void BamfLauncherIcon::Remove()
237@@ -201,11 +200,6 @@
238 return bamf_view_is_sticky(BAMF_VIEW(_bamf_app.RawPtr()));
239 }
240
241-bool BamfLauncherIcon::IsVisible() const
242-{
243- return GetQuirk(Quirk::VISIBLE);
244-}
245-
246 bool BamfLauncherIcon::IsActive() const
247 {
248 return GetQuirk(Quirk::ACTIVE);
249@@ -235,7 +229,6 @@
250 wm->Activate(arg.target);
251 return;
252 }
253-
254
255 /* We should check each child to see if there is
256 * an unmapped (!= minimized) window around and
257@@ -638,22 +631,22 @@
258 GList* children;
259
260 BamfView *focusable_child = BAMF_VIEW (bamf_application_get_focusable_child (_bamf_app.RawPtr()));
261-
262+
263 if (focusable_child != NULL)
264 {
265 Window xid;
266-
267+
268 if (BAMF_IS_WINDOW (focusable_child))
269 xid = bamf_window_get_xid (BAMF_WINDOW(focusable_child));
270 else if (BAMF_IS_TAB (focusable_child))
271 {
272 BamfTab *focusable_tab = BAMF_TAB (focusable_child);
273-
274+
275 xid = bamf_tab_get_xid (focusable_tab);
276-
277+
278 bamf_tab_raise (focusable_tab);
279 }
280-
281+
282 windows.push_back(xid);
283 return windows;
284 }
285@@ -662,7 +655,7 @@
286 if (g_strcmp0 (bamf_application_get_application_type (_bamf_app.RawPtr()), "webapp") == 0)
287 {
288 OpenInstanceLauncherIcon(arg);
289-
290+
291 return windows;
292 }
293 }
294@@ -762,13 +755,13 @@
295 {
296 /* BamfTab does not support the monitor interface...so a bit of a nasty hack here. */
297 xid = bamf_tab_get_xid (static_cast<BamfTab*>(l->data));
298-
299+
300 if (WindowManager::Default()->IsWindowOnCurrentDesktop(xid) == false)
301 continue;
302-
303+
304 for (int j = 0; j < max_num_monitors; j++)
305 monitors[j] = true;
306-
307+
308 continue;
309 }
310
311@@ -939,30 +932,28 @@
312
313 void BamfLauncherIcon::Stick(bool save)
314 {
315+ SimpleLauncherIcon::Stick(save);
316+
317 if (IsSticky())
318 return;
319
320- std::string const& desktop_file = DesktopFile();
321 bamf_view_set_sticky(BAMF_VIEW(_bamf_app.RawPtr()), true);
322-
323- if (save && !desktop_file.empty())
324- FavoriteStore::Instance().AddFavorite(desktop_file, -1);
325 }
326
327 void BamfLauncherIcon::UnStick()
328 {
329+ SimpleLauncherIcon::UnStick();
330+
331 if (!IsSticky())
332 return;
333
334- std::string const& desktop_file = DesktopFile();
335 BamfView* view = BAMF_VIEW(_bamf_app.RawPtr());
336 bamf_view_set_sticky(view, false);
337
338- if (bamf_view_is_closed(view) || !bamf_view_user_visible(view))
339+ SetQuirk(Quirk::VISIBLE, bamf_view_user_visible(view));
340+
341+ if (bamf_view_is_closed(view))
342 Remove();
343-
344- if (!desktop_file.empty())
345- FavoriteStore::Instance().RemoveFavorite(desktop_file);
346 }
347
348 void BamfLauncherIcon::ToggleSticky()
349@@ -1227,12 +1218,11 @@
350 {
351 if (_remote_uri.empty())
352 {
353- const std::string prefix = "application://";
354 std::string const& desktop_id = GetDesktopID();
355
356 if (!desktop_id.empty())
357 {
358- _remote_uri = prefix + desktop_id;
359+ _remote_uri = FavoriteStore::URI_PREFIX_APP + desktop_id;
360 }
361 }
362
363@@ -1384,32 +1374,25 @@
364 if (desktop_file.empty())
365 return;
366
367- GKeyFile* key_file = g_key_file_new();
368+ std::shared_ptr<GKeyFile> key_file(g_key_file_new(), g_key_file_free);
369 glib::Error error;
370
371- g_key_file_load_from_file(key_file, desktop_file.c_str(), (GKeyFileFlags) 0, &error);
372+ g_key_file_load_from_file(key_file.get(), desktop_file.c_str(), (GKeyFileFlags) 0, &error);
373
374 if (error)
375- {
376- g_key_file_free(key_file);
377 return;
378- }
379-
380- char** mimes = g_key_file_get_string_list(key_file, "Desktop Entry", "MimeType", nullptr, nullptr);
381+
382+ std::shared_ptr<char*> mimes(g_key_file_get_string_list(key_file.get(), "Desktop Entry", "MimeType", nullptr, nullptr),
383+ g_strfreev);
384+
385 if (!mimes)
386- {
387- g_key_file_free(key_file);
388 return;
389- }
390
391- for (int i = 0; mimes[i]; i++)
392+ for (int i = 0; mimes.get()[i]; i++)
393 {
394- unity::glib::String super_type(g_content_type_from_mime_type(mimes[i]));
395+ unity::glib::String super_type(g_content_type_from_mime_type(mimes.get()[i]));
396 _supported_types.insert(super_type.Str());
397 }
398-
399- g_key_file_free(key_file);
400- g_strfreev(mimes);
401 }
402 }
403
404
405=== modified file 'launcher/BamfLauncherIcon.h'
406--- launcher/BamfLauncherIcon.h 2012-08-20 06:37:21 +0000
407+++ launcher/BamfLauncherIcon.h 2012-09-18 15:52:46 +0000
408@@ -48,7 +48,6 @@
409 std::string DesktopFile();
410
411 bool IsSticky() const;
412- bool IsVisible() const;
413 bool IsActive() const;
414 bool IsRunning() const;
415 bool IsUrgent() const;
416
417=== modified file 'launcher/CMakeLists.txt'
418--- launcher/CMakeLists.txt 2012-08-25 15:54:29 +0000
419+++ launcher/CMakeLists.txt 2012-09-18 15:52:46 +0000
420@@ -42,6 +42,7 @@
421 DevicesSettingsImp.cpp
422 DndData.cpp
423 EdgeBarrierController.cpp
424+ ExpoLauncherIcon.cpp
425 FavoriteStore.cpp
426 FavoriteStoreGSettings.cpp
427 FavoriteStorePrivate.cpp
428
429=== modified file 'launcher/DesktopLauncherIcon.cpp'
430--- launcher/DesktopLauncherIcon.cpp 2012-08-02 13:16:06 +0000
431+++ launcher/DesktopLauncherIcon.cpp 2012-09-18 15:52:46 +0000
432@@ -19,6 +19,7 @@
433
434 #include "DesktopLauncherIcon.h"
435 #include "unity-shared/WindowManager.h"
436+#include "FavoriteStore.h"
437
438 #include <glib/gi18n-lib.h>
439
440@@ -28,17 +29,14 @@
441 {
442
443 DesktopLauncherIcon::DesktopLauncherIcon()
444- : SimpleLauncherIcon(IconType::DESKTOP)
445- , show_in_switcher_(true)
446+ : SimpleLauncherIcon(IconType::DESKTOP)
447+ , show_in_switcher_(true)
448 {
449 tooltip_text = _("Show Desktop");
450 icon_name = "desktop";
451 SetQuirk(Quirk::VISIBLE, true);
452 SetQuirk(Quirk::RUNNING, false);
453-}
454-
455-DesktopLauncherIcon::~DesktopLauncherIcon()
456-{
457+ SetShortcut('d');
458 }
459
460 void
461@@ -53,5 +51,20 @@
462 return "DesktopLauncherIcon";
463 }
464
465+std::string DesktopLauncherIcon::GetRemoteUri()
466+{
467+ return FavoriteStore::URI_PREFIX_UNITY + "desktop-icon";
468+}
469+
470+void DesktopLauncherIcon::SetShowInSwitcher(bool show_in_switcher)
471+{
472+ show_in_switcher_ = show_in_switcher;
473+}
474+
475+bool DesktopLauncherIcon::ShowInSwitcher(bool current)
476+{
477+ return show_in_switcher_;
478+}
479+
480 } // namespace launcher
481 } // namespace unity
482
483=== modified file 'launcher/DesktopLauncherIcon.h'
484--- launcher/DesktopLauncherIcon.h 2012-05-07 19:52:54 +0000
485+++ launcher/DesktopLauncherIcon.h 2012-09-18 15:52:46 +0000
486@@ -29,24 +29,16 @@
487
488 class DesktopLauncherIcon : public SimpleLauncherIcon
489 {
490-
491 public:
492 DesktopLauncherIcon();
493- ~DesktopLauncherIcon();
494-
495- void SetShowInSwitcher(bool show_in_switcher)
496- {
497- show_in_switcher_ = show_in_switcher;
498- }
499-
500- bool ShowInSwitcher(bool current)
501- {
502- return show_in_switcher_;
503- }
504+
505+ void SetShowInSwitcher(bool show_in_switcher);
506+ bool ShowInSwitcher(bool current);
507
508 protected:
509 void ActivateLauncherIcon(ActionArg arg);
510 std::string GetName() const;
511+ std::string GetRemoteUri();
512
513 private:
514 bool show_in_switcher_;
515
516=== modified file 'launcher/DeviceLauncherSection.cpp'
517--- launcher/DeviceLauncherSection.cpp 2012-08-28 17:28:02 +0000
518+++ launcher/DeviceLauncherSection.cpp 2012-09-18 15:52:46 +0000
519@@ -38,10 +38,7 @@
520 monitor_->volume_added.connect(sigc::mem_fun(this, &DeviceLauncherSection::OnVolumeAdded));
521 monitor_->volume_removed.connect(sigc::mem_fun(this, &DeviceLauncherSection::OnVolumeRemoved));
522
523- device_populate_idle_.Run([this] () {
524- PopulateEntries();
525- return false;
526- });
527+ PopulateEntries();
528 }
529
530 void DeviceLauncherSection::PopulateEntries()
531@@ -60,11 +57,11 @@
532 if (map_.find(volume) != map_.end())
533 return;
534
535- VolumeLauncherIcon::Ptr icon(new VolumeLauncherIcon(std::make_shared<VolumeImp>(volume, file_manager_opener_, device_notification_display_),
536- devices_settings_));
537+ auto vol = std::make_shared<VolumeImp>(volume, file_manager_opener_, device_notification_display_);
538+ VolumeLauncherIcon::Ptr icon(new VolumeLauncherIcon(vol, devices_settings_));
539
540 map_[volume] = icon;
541- IconAdded.emit(icon);
542+ icon_added.emit(icon);
543 }
544
545 void DeviceLauncherSection::OnVolumeRemoved(glib::Object<GVolume> const& volume)
546@@ -76,5 +73,15 @@
547 map_.erase(volume_it);
548 }
549
550+std::vector<VolumeLauncherIcon::Ptr> DeviceLauncherSection::GetIcons() const
551+{
552+ std::vector<VolumeLauncherIcon::Ptr> icons;
553+
554+ for (auto const& it : map_)
555+ icons.push_back(it.second);
556+
557+ return icons;
558+}
559+
560 }
561 }
562
563=== modified file 'launcher/DeviceLauncherSection.h'
564--- launcher/DeviceLauncherSection.h 2012-08-22 09:03:25 +0000
565+++ launcher/DeviceLauncherSection.h 2012-09-18 15:52:46 +0000
566@@ -23,8 +23,6 @@
567 #include <map>
568 #include <memory>
569
570-#include <UnityCore/GLibSource.h>
571-
572 #include "AbstractVolumeMonitorWrapper.h"
573 #include "DevicesSettings.h"
574 #include "DeviceNotificationDisplay.h"
575@@ -42,7 +40,9 @@
576 DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr volume_monitor,
577 DevicesSettings::Ptr devices_settings);
578
579- sigc::signal<void, AbstractLauncherIcon::Ptr> IconAdded;
580+ std::vector<VolumeLauncherIcon::Ptr> GetIcons() const;
581+
582+ sigc::signal<void, AbstractLauncherIcon::Ptr> icon_added;
583
584 private:
585 void PopulateEntries();
586@@ -55,8 +55,6 @@
587 DevicesSettings::Ptr devices_settings_;
588 FileManagerOpener::Ptr file_manager_opener_;
589 DeviceNotificationDisplay::Ptr device_notification_display_;
590-
591- glib::Idle device_populate_idle_;
592 };
593
594 }
595
596=== modified file 'launcher/DndData.cpp'
597--- launcher/DndData.cpp 2012-07-09 14:11:06 +0000
598+++ launcher/DndData.cpp 2012-09-18 15:52:46 +0000
599@@ -27,12 +27,12 @@
600 #include <UnityCore/GLibWrapper.h>
601
602 namespace unity {
603-
604-void DndData::Fill(char* uris)
605-{
606+
607+void DndData::Fill(const char* uris)
608+{
609 Reset();
610-
611- char* pch = strtok (uris, "\r\n");
612+
613+ const char* pch = strtok (const_cast<char*>(uris), "\r\n");
614 while (pch)
615 {
616 glib::String content_type(g_content_type_guess(pch,
617
618=== modified file 'launcher/DndData.h'
619--- launcher/DndData.h 2012-05-07 19:52:54 +0000
620+++ launcher/DndData.h 2012-09-18 15:52:46 +0000
621@@ -32,7 +32,7 @@
622 /**
623 * Fills the object given a list of uris.
624 **/
625- void Fill(char* uris);
626+ void Fill(const char* uris);
627
628 /**
629 * Resets the object. Call this function when no longer need data
630
631=== added file 'launcher/ExpoLauncherIcon.cpp'
632--- launcher/ExpoLauncherIcon.cpp 1970-01-01 00:00:00 +0000
633+++ launcher/ExpoLauncherIcon.cpp 2012-09-18 15:52:46 +0000
634@@ -0,0 +1,64 @@
635+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
636+/*
637+ * Copyright (C) 2012 Canonical Ltd
638+ *
639+ * This program is free software: you can redistribute it and/or modify
640+ * it under the terms of the GNU General Public License version 3 as
641+ * published by the Free Software Foundation.
642+ *
643+ * This program is distributed in the hope that it will be useful,
644+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
645+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
646+ * GNU General Public License for more details.
647+ *
648+ * You should have received a copy of the GNU General Public License
649+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
650+ *
651+ * Authored by: Marco Trevisan <marco.trevisan@canonical.com>
652+ */
653+
654+#include "ExpoLauncherIcon.h"
655+#include "unity-shared/WindowManager.h"
656+#include "FavoriteStore.h"
657+
658+#include <glib/gi18n-lib.h>
659+
660+namespace unity
661+{
662+namespace launcher
663+{
664+
665+ExpoLauncherIcon::ExpoLauncherIcon()
666+ : SimpleLauncherIcon(IconType::EXPO)
667+{
668+ tooltip_text = _("Workspace Switcher");
669+ icon_name = "workspace-switcher";
670+ SetQuirk(Quirk::VISIBLE, false);
671+ SetQuirk(Quirk::RUNNING, false);
672+ SetShortcut('s');
673+}
674+
675+void ExpoLauncherIcon::ActivateLauncherIcon(ActionArg arg)
676+{
677+ SimpleLauncherIcon::ActivateLauncherIcon(arg);
678+ WindowManager::Default()->InitiateExpo();
679+}
680+
681+void ExpoLauncherIcon::Stick(bool save)
682+{
683+ SimpleLauncherIcon::Stick(save);
684+ SetQuirk(Quirk::VISIBLE, (WindowManager::Default()->WorkspaceCount() > 1));
685+}
686+
687+std::string ExpoLauncherIcon::GetName() const
688+{
689+ return "ExpoLauncherIcon";
690+}
691+
692+std::string ExpoLauncherIcon::GetRemoteUri()
693+{
694+ return FavoriteStore::URI_PREFIX_UNITY + "expo-icon";
695+}
696+
697+} // namespace launcher
698+} // namespace unity
699
700=== added file 'launcher/ExpoLauncherIcon.h'
701--- launcher/ExpoLauncherIcon.h 1970-01-01 00:00:00 +0000
702+++ launcher/ExpoLauncherIcon.h 2012-09-18 15:52:46 +0000
703@@ -0,0 +1,45 @@
704+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
705+/*
706+ * Copyright (C) 2012 Canonical Ltd
707+ *
708+ * This program is free software: you can redistribute it and/or modify
709+ * it under the terms of the GNU General Public License version 3 as
710+ * published by the Free Software Foundation.
711+ *
712+ * This program is distributed in the hope that it will be useful,
713+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
714+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
715+ * GNU General Public License for more details.
716+ *
717+ * You should have received a copy of the GNU General Public License
718+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
719+ *
720+ * Authored by: Marco Trevisan <marco.trevisan@canonical.com>
721+ */
722+
723+#ifndef EXPO_LAUNCHER_ICON_H
724+#define EXPO_LAUNCHER_ICON_H
725+
726+#include "SimpleLauncherIcon.h"
727+
728+namespace unity
729+{
730+namespace launcher
731+{
732+
733+class ExpoLauncherIcon : public SimpleLauncherIcon
734+{
735+public:
736+ ExpoLauncherIcon();
737+ void Stick(bool save);
738+
739+protected:
740+ void ActivateLauncherIcon(ActionArg arg);
741+ std::string GetName() const;
742+ std::string GetRemoteUri();
743+};
744+
745+}
746+}
747+
748+#endif // EXPO_LAUNCHER_ICON_H
749
750=== modified file 'launcher/FavoriteStore.cpp'
751--- launcher/FavoriteStore.cpp 2012-05-07 19:52:54 +0000
752+++ launcher/FavoriteStore.cpp 2012-09-18 15:52:46 +0000
753@@ -1,6 +1,6 @@
754 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
755 /*
756-* Copyright (C) 2010 Canonical Ltd
757+* Copyright (C) 2010-2012 Canonical Ltd
758 *
759 * This program is free software: you can redistribute it and/or modify
760 * it under the terms of the GNU General Public License version 3 as
761@@ -15,19 +15,29 @@
762 * along with this program. If not, see <http://www.gnu.org/licenses/>.
763 *
764 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
765+* Marco Trevisan <marco.trevisan@canonical.com>
766 */
767
768 #include <NuxCore/Logger.h>
769-#include "FavoriteStoreGSettings.h"
770+#include <glib.h>
771+
772+#include "FavoriteStore.h"
773+#include "FavoriteStorePrivate.h"
774
775 namespace unity
776 {
777 namespace
778 {
779- nux::logging::Logger logger("unity.favouritestore");
780- FavoriteStore* favoritestore_instance = nullptr;
781+nux::logging::Logger logger("unity.favorite.store");
782+FavoriteStore* favoritestore_instance = nullptr;
783+const std::string PREFIX_SEPARATOR = "://";
784 }
785
786+const std::string FavoriteStore::URI_PREFIX_APP = "application://";
787+const std::string FavoriteStore::URI_PREFIX_FILE = "file://";
788+const std::string FavoriteStore::URI_PREFIX_DEVICE = "device://";
789+const std::string FavoriteStore::URI_PREFIX_UNITY = "unity://";
790+
791 FavoriteStore::FavoriteStore()
792 {
793 if (favoritestore_instance)
794@@ -56,4 +66,83 @@
795 return *favoritestore_instance;
796 }
797
798+bool FavoriteStore::IsValidFavoriteUri(std::string const& uri)
799+{
800+ if (uri.empty())
801+ return false;
802+
803+ if (uri.find(URI_PREFIX_APP) == 0 || uri.find(URI_PREFIX_FILE) == 0)
804+ {
805+ return internal::impl::IsDesktopFilePath(uri);
806+ }
807+ else if (uri.find(URI_PREFIX_DEVICE) == 0)
808+ {
809+ return uri.length() > URI_PREFIX_DEVICE.length();
810+ }
811+ else if (uri.find(URI_PREFIX_UNITY) == 0)
812+ {
813+ return uri.length() > URI_PREFIX_UNITY.length();
814+ }
815+
816+ return false;
817+}
818+
819+std::string FavoriteStore::ParseFavoriteFromUri(std::string const& uri) const
820+{
821+ if (uri.empty())
822+ return "";
823+
824+ std::string fav = uri;
825+ auto prefix_pos = fav.find(PREFIX_SEPARATOR);
826+
827+ if (prefix_pos == std::string::npos)
828+ {
829+ // We assume that favorites with no prefix, but with a .desktop suffix are applications
830+ if (internal::impl::IsDesktopFilePath(uri))
831+ {
832+ fav = URI_PREFIX_APP + fav;
833+ prefix_pos = URI_PREFIX_APP.length();
834+ }
835+ }
836+ else
837+ {
838+ prefix_pos += PREFIX_SEPARATOR.length();
839+ }
840+
841+ // Matches application://desktop-id.desktop or application:///path/to/file.desktop
842+ if (fav.find(URI_PREFIX_APP) == 0 || fav.find(URI_PREFIX_FILE) == 0)
843+ {
844+ std::string const& fav_value = fav.substr(prefix_pos);
845+
846+ if (fav_value.empty())
847+ {
848+ LOG_WARNING(logger) << "Unable to load Favorite for uri '" << fav << "'";
849+ return "";
850+ }
851+
852+ if (fav_value[0] == '/' || fav.find(URI_PREFIX_FILE) == 0)
853+ {
854+ if (g_file_test(fav_value.c_str(), G_FILE_TEST_EXISTS))
855+ {
856+ return fav;
857+ }
858+ else
859+ {
860+ LOG_WARNING(logger) << "Unable to load desktop file: " << fav_value;
861+ }
862+ }
863+ else
864+ {
865+ return URI_PREFIX_APP + fav_value;
866+ }
867+ }
868+ else if (IsValidFavoriteUri(fav))
869+ {
870+ return fav;
871+ }
872+
873+ LOG_WARNING(logger) << "Unable to load Favorite for uri '" << fav << "'";
874+ return "";
875+}
876+
877 }
878
879=== modified file 'launcher/FavoriteStore.h'
880--- launcher/FavoriteStore.h 2012-05-07 19:52:54 +0000
881+++ launcher/FavoriteStore.h 2012-09-18 15:52:46 +0000
882@@ -1,6 +1,6 @@
883 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
884 /*
885-* Copyright (C) 2010 Canonical Ltd
886+* Copyright (C) 2010-2012 Canonical Ltd
887 *
888 * This program is free software: you can redistribute it and/or modify
889 * it under the terms of the GNU General Public License version 3 as
890@@ -15,6 +15,7 @@
891 * along with this program. If not, see <http://www.gnu.org/licenses/>.
892 *
893 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
894+* Marco Trevisan <marco.trevisan@canonical.com>
895 */
896
897 #ifndef UNITY_FAVORITE_STORE_H
898@@ -42,26 +43,38 @@
899
900 static FavoriteStore& Instance();
901
902- virtual FavoriteList const& GetFavorites() = 0;
903+ virtual FavoriteList const& GetFavorites() const = 0;
904
905 // These will NOT emit the relevant signals, so bare that in mind
906 // i.e. don't hope that you can add stuff and hook the view up to
907 // favorite_added events to update the view. The signals only emit if
908 // there has been a change on the GSettings object from an external
909 // source
910- virtual void AddFavorite(std::string const& desktop_path, int position) = 0;
911- virtual void RemoveFavorite(std::string const& desktop_path) = 0;
912- virtual void MoveFavorite(std::string const& desktop_path, int position) = 0;
913- virtual void SetFavorites(FavoriteList const& desktop_paths) = 0;
914+ virtual void AddFavorite(std::string const& icon_uri, int position) = 0;
915+ virtual void RemoveFavorite(std::string const& icon_uri) = 0;
916+ virtual void MoveFavorite(std::string const& icon_uri, int position) = 0;
917+ virtual bool IsFavorite(std::string const& icon_uri) const = 0;
918+ virtual int FavoritePosition(std::string const& icon_uri) const = 0;
919+ virtual void SetFavorites(FavoriteList const& icon_uris) = 0;
920
921 // Signals
922 // These only emit if something has changed the GSettings object externally
923
924- //desktop_path, position, before/after
925+ //icon_uri, position, before/after
926 sigc::signal<void, std::string const&, std::string const&, bool> favorite_added;
927- //desktop_path
928+ //icon_uri
929 sigc::signal<void, std::string const&> favorite_removed;
930 sigc::signal<void> reordered;
931+
932+ static const std::string URI_PREFIX_APP;
933+ static const std::string URI_PREFIX_FILE;
934+ static const std::string URI_PREFIX_DEVICE;
935+ static const std::string URI_PREFIX_UNITY;
936+
937+ static bool IsValidFavoriteUri(std::string const& uri);
938+
939+protected:
940+ std::string ParseFavoriteFromUri(std::string const& uri) const;
941 };
942
943 }
944
945=== modified file 'launcher/FavoriteStoreGSettings.cpp'
946--- launcher/FavoriteStoreGSettings.cpp 2012-08-15 17:22:33 +0000
947+++ launcher/FavoriteStoreGSettings.cpp 2012-09-18 15:52:46 +0000
948@@ -1,6 +1,6 @@
949 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
950 /*
951-* Copyright (C) 2010 Canonical Ltd
952+* Copyright (C) 2010-2012 Canonical Ltd
953 *
954 * This program is free software: you can redistribute it and/or modify
955 * it under the terms of the GNU General Public License version 3 as
956@@ -15,9 +15,9 @@
957 * along with this program. If not, see <http://www.gnu.org/licenses/>.
958 *
959 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
960+* Marco Trevisan <marco.trevisan@canonical.com>
961 */
962
963-#include <gio/gdesktopappinfo.h>
964 #include <NuxCore/Logger.h>
965 #include <UnityCore/DesktopUtilities.h>
966
967@@ -40,7 +40,7 @@
968
969 namespace
970 {
971-nux::logging::Logger logger("unity.favorites");
972+nux::logging::Logger logger("unity.favorite.store.gsettings");
973 const std::string SETTINGS_NAME = "com.canonical.Unity.Launcher";
974 const std::string SETTINGS_KEY = "favorites";
975 }
976@@ -59,117 +59,89 @@
977
978 void FavoriteStoreGSettings::Refresh()
979 {
980- FillList(favorites_);
981+ FillList();
982 }
983
984-void FavoriteStoreGSettings::FillList(FavoriteList& list)
985+void FavoriteStoreGSettings::FillList()
986 {
987- list.clear();
988-
989- gchar** favs = g_settings_get_strv(settings_, SETTINGS_KEY.c_str());
990-
991- for (int i = 0; favs[i] != NULL; ++i)
992+ favorites_.clear();
993+ std::shared_ptr<gchar*> favs(g_settings_get_strv(settings_, SETTINGS_KEY.c_str()));
994+
995+ for (int i = 0; favs.get()[i]; ++i)
996 {
997- // We will be storing either full /path/to/desktop/files or foo.desktop id's
998- if (favs[i][0] == '/')
999- {
1000- if (g_file_test(favs[i], G_FILE_TEST_EXISTS))
1001- {
1002- list.push_back(favs[i]);
1003- }
1004- else
1005- {
1006- LOG_WARNING(logger) << "Unable to load desktop file: "
1007- << favs[i];
1008- }
1009- }
1010- else
1011- {
1012- glib::Object<GDesktopAppInfo> info(g_desktop_app_info_new(favs[i]));
1013- const char* filename = 0;
1014- if (info)
1015- filename = g_desktop_app_info_get_filename(info);
1016+ std::string const& fav = ParseFavoriteFromUri(favs.get()[i]);
1017
1018- if (filename)
1019- {
1020- list.push_back(filename);
1021- }
1022- else
1023- {
1024- LOG_WARNING(logger) << "Unable to load GDesktopAppInfo for '" << favs[i] << "'";
1025- }
1026- }
1027+ if (!fav.empty())
1028+ favorites_.push_back(fav);
1029 }
1030-
1031- g_strfreev(favs);
1032 }
1033
1034-FavoriteList const& FavoriteStoreGSettings::GetFavorites()
1035+FavoriteList const& FavoriteStoreGSettings::GetFavorites() const
1036 {
1037 return favorites_;
1038 }
1039
1040-void FavoriteStoreGSettings::AddFavorite(std::string const& desktop_path, int position)
1041+void FavoriteStoreGSettings::AddFavorite(std::string const& icon_uri, int position)
1042 {
1043- int size = favorites_.size();
1044- if (desktop_path.empty() || position > size)
1045+ std::string const& fav = ParseFavoriteFromUri(icon_uri);
1046+
1047+ if (fav.empty() || position > static_cast<int>(favorites_.size()))
1048 return;
1049
1050 if (position < 0)
1051 {
1052 // It goes on the end.
1053- favorites_.push_back(desktop_path);
1054+ favorites_.push_back(fav);
1055 }
1056 else
1057 {
1058 FavoriteList::iterator pos = favorites_.begin();
1059 std::advance(pos, position);
1060- favorites_.insert(pos, desktop_path);
1061+ favorites_.insert(pos, fav);
1062 }
1063
1064 SaveFavorites(favorites_);
1065 Refresh();
1066 }
1067
1068-void FavoriteStoreGSettings::RemoveFavorite(std::string const& desktop_path)
1069+void FavoriteStoreGSettings::RemoveFavorite(std::string const& icon_uri)
1070 {
1071- if (desktop_path.empty() || desktop_path[0] != '/')
1072+ std::string const& fav = ParseFavoriteFromUri(icon_uri);
1073+
1074+ if (fav.empty())
1075 return;
1076
1077- FavoriteList::iterator pos = std::find(favorites_.begin(), favorites_.end(), desktop_path);
1078+ FavoriteList::iterator pos = std::find(favorites_.begin(), favorites_.end(), fav);
1079 if (pos == favorites_.end())
1080- {
1081 return;
1082- }
1083
1084 favorites_.erase(pos);
1085 SaveFavorites(favorites_);
1086 Refresh();
1087 }
1088
1089-void FavoriteStoreGSettings::MoveFavorite(std::string const& desktop_path, int position)
1090+void FavoriteStoreGSettings::MoveFavorite(std::string const& icon_uri, int position)
1091 {
1092- int size = favorites_.size();
1093- if (desktop_path.empty() || position > size)
1094+ std::string const& fav = ParseFavoriteFromUri(icon_uri);
1095+
1096+ if (fav.empty() || position > static_cast<int>(favorites_.size()))
1097 return;
1098
1099- FavoriteList::iterator pos = std::find(favorites_.begin(), favorites_.end(), desktop_path);
1100+ FavoriteList::iterator pos = std::find(favorites_.begin(), favorites_.end(), fav);
1101 if (pos == favorites_.end())
1102- {
1103 return;
1104- }
1105
1106 favorites_.erase(pos);
1107 if (position < 0)
1108 {
1109 // It goes on the end.
1110- favorites_.push_back(desktop_path);
1111+ favorites_.push_back(fav);
1112 }
1113 else
1114 {
1115 FavoriteList::iterator insert_pos = favorites_.begin();
1116 std::advance(insert_pos, position);
1117- favorites_.insert(insert_pos, desktop_path);
1118+ favorites_.insert(insert_pos, fav);
1119 }
1120
1121 SaveFavorites(favorites_);
1122@@ -186,26 +158,34 @@
1123 {
1124 const int size = favorites.size();
1125 const char* favs[size + 1];
1126- favs[size] = NULL;
1127
1128- int index = 0;
1129 // Since we don't always save the full path, we store the values we are
1130 // actually going to save in a different list.
1131- auto system_dirs = DesktopUtilities::GetDataDirectories();
1132 FavoriteList values;
1133- for (FavoriteList::const_iterator i = favorites.begin(), end = favorites.end();
1134- i != end; ++i, ++index)
1135+ int index = 0;
1136+
1137+ for (auto const& fav_uri : favorites)
1138 {
1139+ std::string const& fav = ParseFavoriteFromUri(fav_uri);
1140+ if (fav.empty())
1141+ {
1142+ LOG_WARNING(logger) << "Impossible to add favorite '" << fav_uri << "' to store";
1143+ continue;
1144+ }
1145+
1146 // By using insert we get the iterator to the newly inserted string value.
1147 // That way we can use the c_str() method to access the const char* for
1148 // the string that we are going to save. This way we know that the pointer
1149 // is valid for the lifetime of the favs array usage in the method call to
1150 // set the settings, and that we aren't referencing a temporary.
1151- std::string const& desktop_id = DesktopUtilities::GetDesktopID(system_dirs, *i);
1152- FavoriteList::iterator iter = values.insert(values.end(), desktop_id);
1153+ FavoriteList::iterator iter = values.insert(values.end(), fav);
1154 favs[index] = iter->c_str();
1155+ ++index;
1156 }
1157
1158+ for (int i = index; i <= size; ++i)
1159+ favs[i] = nullptr;
1160+
1161 ignore_signals_ = ignore;
1162 if (!g_settings_set_strv(settings_, SETTINGS_KEY.c_str(), favs))
1163 {
1164@@ -220,7 +200,7 @@
1165 return;
1166
1167 FavoriteList old(favorites_);
1168- FillList(favorites_);
1169+ FillList();
1170
1171 auto newbies = impl::GetNewbies(old, favorites_);
1172
1173@@ -243,7 +223,26 @@
1174
1175 if (impl::NeedToBeReordered(old, favorites_))
1176 reordered.emit();
1177-
1178+}
1179+
1180+bool FavoriteStoreGSettings::IsFavorite(std::string const& icon_uri) const
1181+{
1182+ return std::find(favorites_.begin(), favorites_.end(), icon_uri) != favorites_.end();
1183+}
1184+
1185+int FavoriteStoreGSettings::FavoritePosition(std::string const& icon_uri) const
1186+{
1187+ int index = 0;
1188+
1189+ for (auto const& fav : favorites_)
1190+ {
1191+ if (fav == icon_uri)
1192+ return index;
1193+
1194+ ++index;
1195+ }
1196+
1197+ return -1;
1198 }
1199
1200 } // namespace internal
1201
1202=== modified file 'launcher/FavoriteStoreGSettings.h'
1203--- launcher/FavoriteStoreGSettings.h 2012-08-01 18:12:10 +0000
1204+++ launcher/FavoriteStoreGSettings.h 2012-09-18 15:52:46 +0000
1205@@ -1,6 +1,6 @@
1206 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
1207 /*
1208-* Copyright (C) 2010 Canonical Ltd
1209+* Copyright (C) 2010-2012 Canonical Ltd
1210 *
1211 * This program is free software: you can redistribute it and/or modify
1212 * it under the terms of the GNU General Public License version 3 as
1213@@ -15,6 +15,7 @@
1214 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1215 *
1216 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
1217+* Marco Trevisan <marco.trevisan@canonical.com>
1218 */
1219
1220 #ifndef FAVORITE_STORE_GSETTINGS_H
1221@@ -38,17 +39,19 @@
1222 public:
1223 FavoriteStoreGSettings();
1224
1225- virtual FavoriteList const& GetFavorites();
1226+ virtual FavoriteList const& GetFavorites() const;
1227 virtual void AddFavorite(std::string const& desktop_path, int position);
1228 virtual void RemoveFavorite(std::string const& desktop_path);
1229 virtual void MoveFavorite(std::string const& desktop_path, int position);
1230+ virtual bool IsFavorite(std::string const& icon_uri) const;
1231+ virtual int FavoritePosition(std::string const& icon_uri) const;
1232+ virtual void SetFavorites(FavoriteList const& desktop_paths);
1233 void SaveFavorites(FavoriteList const& favorites, bool ignore = true);
1234- virtual void SetFavorites(FavoriteList const& desktop_paths);
1235
1236 private:
1237 void Refresh();
1238 void Changed();
1239- void FillList(FavoriteList& list);
1240+ void FillList();
1241
1242 FavoriteList favorites_;
1243 bool ignore_signals_;
1244
1245=== modified file 'launcher/FavoriteStorePrivate.cpp'
1246--- launcher/FavoriteStorePrivate.cpp 2012-05-07 19:52:54 +0000
1247+++ launcher/FavoriteStorePrivate.cpp 2012-09-18 15:52:46 +0000
1248@@ -124,6 +124,20 @@
1249 return false;
1250 }
1251
1252+bool IsDesktopFilePath(std::string const& path)
1253+{
1254+ static const std::string desktop_ext = ".desktop";
1255+ auto path_len = path.length();
1256+ auto desktop_length = desktop_ext.length();
1257+
1258+ if (path_len > desktop_length)
1259+ {
1260+ return path.compare(path_len - desktop_length, desktop_length, desktop_ext) == 0;
1261+ }
1262+
1263+ return false;
1264+}
1265+
1266
1267 } // namespace impl
1268 } // namespace internal
1269
1270=== modified file 'launcher/FavoriteStorePrivate.h'
1271--- launcher/FavoriteStorePrivate.h 2012-05-07 19:52:54 +0000
1272+++ launcher/FavoriteStorePrivate.h 2012-09-18 15:52:46 +0000
1273@@ -32,13 +32,15 @@
1274
1275 std::vector<std::string> GetNewbies(std::list<std::string> const& old, std::list<std::string> const& fresh);
1276
1277-void GetSignalAddedInfo(std::list<std::string> const& favs, std::vector<std::string> const& newbies,
1278+void GetSignalAddedInfo(std::list<std::string> const& favs, std::vector<std::string> const& newbies,
1279 std::string const& path, std::string& position, bool& before);
1280
1281 std::vector<std::string> GetRemoved(std::list<std::string> const& old, std::list<std::string> const& fresh);
1282
1283 bool NeedToBeReordered(std::list<std::string> const& old, std::list<std::string> const& fresh);
1284
1285+bool IsDesktopFilePath(std::string const& path);
1286+
1287
1288 } // namespace impl
1289 } // namespace internal
1290
1291=== modified file 'launcher/HudLauncherIcon.cpp'
1292--- launcher/HudLauncherIcon.cpp 2012-08-22 08:17:33 +0000
1293+++ launcher/HudLauncherIcon.cpp 2012-09-18 15:52:46 +0000
1294@@ -45,6 +45,7 @@
1295 {
1296 tooltip_text = _("HUD");
1297 icon_name = PKGDATADIR"/launcher_bfb.png";
1298+ position = Position::BEGIN;
1299 SetQuirk(Quirk::VISIBLE, false);
1300 SetQuirk(Quirk::RUNNING, false);
1301 SetQuirk(Quirk::ACTIVE, true);
1302@@ -121,7 +122,7 @@
1303
1304 void HudLauncherIcon::ActivateLauncherIcon(ActionArg arg)
1305 {
1306- if (GetQuirk(Quirk::VISIBLE))
1307+ if (IsVisible())
1308 {
1309 ubus_manager_.SendMessage(UBUS_HUD_CLOSE_REQUEST);
1310 }
1311
1312=== modified file 'launcher/Launcher.cpp'
1313--- launcher/Launcher.cpp 2012-09-04 15:56:50 +0000
1314+++ launcher/Launcher.cpp 2012-09-18 15:52:46 +0000
1315@@ -54,6 +54,7 @@
1316 #include <UnityCore/GLibWrapper.h>
1317 #include <UnityCore/Variant.h>
1318
1319+#include <boost/algorithm/string.hpp>
1320 #include <sigc++/sigc++.h>
1321
1322 namespace unity
1323@@ -106,6 +107,7 @@
1324 nux::ObjectPtr<DNDCollectionWindow> const& collection_window,
1325 NUX_FILE_LINE_DECL)
1326 : View(NUX_FILE_LINE_PARAM)
1327+ , display(nux::GetGraphicsDisplay()->GetX11Display())
1328 , monitor(0)
1329 , _parent(parent)
1330 , _active_quicklist(nullptr)
1331@@ -116,6 +118,7 @@
1332 , _data_checked(false)
1333 , _steal_drag(false)
1334 , _drag_edge_touching(false)
1335+ , _initial_drag_animation(false)
1336 , _dash_is_open(false)
1337 , _hud_is_open(false)
1338 , _folded_angle(1.0f)
1339@@ -462,9 +465,8 @@
1340 return true;
1341
1342 // animations happening on specific icons
1343- LauncherModel::iterator it;
1344- for (it = _model->begin(); it != _model->end(); ++it)
1345- if (IconNeedsAnimation(*it, current))
1346+ for (auto const &icon : *_model)
1347+ if (IconNeedsAnimation(icon, current))
1348 return true;
1349
1350 return false;
1351@@ -495,10 +497,10 @@
1352
1353 if (icon->GetIconType() == AbstractLauncherIcon::IconType::HUD)
1354 {
1355- return (icon->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE)) ? 1.0f : 0.0f;
1356+ return icon->IsVisible() ? 1.0f : 0.0f;
1357 }
1358
1359- if (icon->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE))
1360+ if (icon->IsVisible())
1361 {
1362 struct timespec icon_visible_time = icon->GetQuirkTime(AbstractLauncherIcon::Quirk::VISIBLE);
1363 int enter_ms = unity::TimeUtil::TimeDelta(&current, &icon_visible_time);
1364@@ -891,8 +893,11 @@
1365
1366 if (GetActionState() == ACTION_DRAG_ICON ||
1367 (_drag_window && _drag_window->Animating()) ||
1368- icon->IsSpacer())
1369+ icon->GetIconType() == AbstractLauncherIcon::IconType::SPACER)
1370+ {
1371 arg.skip = true;
1372+ }
1373+
1374 size_modifier *= DragThresholdProgress(current);
1375 }
1376
1377@@ -932,11 +937,12 @@
1378
1379 icon->SetCenter(nux::Point3(roundf(center.x), roundf(center.y), roundf(center.z)), monitor, parent_abs_geo);
1380
1381- // FIXME: this is a hack, we should have a look why SetAnimationTarget is necessary in SetAnimationTarget
1382- // we should ideally just need it at start to set the target
1383+ // FIXME: this is a hack, to avoid that we set the target to the end of the icon
1384 if (!_initial_drag_animation && icon == _drag_icon && _drag_window && _drag_window->Animating())
1385- _drag_window->SetAnimationTarget(static_cast<int>(_drag_icon->GetCenter(monitor).x),
1386- static_cast<int>(_drag_icon->GetCenter(monitor).y));
1387+ {
1388+ auto const& icon_center = _drag_icon->GetCenter(monitor);
1389+ _drag_window->SetAnimationTarget(icon_center.x, icon_center.y);
1390+ }
1391
1392 center.y += (half_size * size_modifier) + spacing; // move to end
1393 }
1394@@ -953,10 +959,10 @@
1395 nux::Color FullySaturateColor (nux::Color color)
1396 {
1397 float max = std::max<float>(color.red, std::max<float>(color.green, color.blue));
1398+
1399 if (max > 0.0f)
1400- {
1401 color = color * (1.0f / max);
1402- }
1403+
1404 return color;
1405 }
1406
1407@@ -1396,8 +1402,8 @@
1408
1409 void Launcher::OnPluginStateChanged()
1410 {
1411- _hide_machine.SetQuirk (LauncherHideMachine::EXPO_ACTIVE, WindowManager::Default ()->IsExpoActive ());
1412- _hide_machine.SetQuirk (LauncherHideMachine::SCALE_ACTIVE, WindowManager::Default ()->IsScaleActive ());
1413+ _hide_machine.SetQuirk(LauncherHideMachine::EXPO_ACTIVE, WindowManager::Default()->IsExpoActive());
1414+ _hide_machine.SetQuirk(LauncherHideMachine::SCALE_ACTIVE, WindowManager::Default()->IsScaleActive());
1415 }
1416
1417 LauncherHideMode Launcher::GetHideMode() const
1418@@ -1669,11 +1675,6 @@
1419 return _model;
1420 }
1421
1422-void Launcher::SetDevicesSettings(DevicesSettings::Ptr devices_settings)
1423-{
1424- devices_settings_ = devices_settings;
1425-}
1426-
1427 void Launcher::EnsureIconOnScreen(AbstractLauncherIcon::Ptr selection)
1428 {
1429 nux::Geometry const& geo = GetGeometry();
1430@@ -1681,7 +1682,7 @@
1431 int natural_y = 0;
1432 for (auto icon : *_model)
1433 {
1434- if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE) || !icon->IsVisibleOnMonitor(monitor))
1435+ if (!icon->IsVisible() || !icon->IsVisibleOnMonitor(monitor))
1436 continue;
1437
1438 if (icon == selection)
1439@@ -1953,7 +1954,7 @@
1440 EnsureAnimation();
1441 }
1442
1443-bool Launcher::StartIconDragTimeout()
1444+bool Launcher::StartIconDragTimeout(int x, int y)
1445 {
1446 // if we are still waiting…
1447 if (GetActionState() == ACTION_NONE)
1448@@ -1964,7 +1965,7 @@
1449 _icon_under_mouse = nullptr;
1450 }
1451 _initial_drag_animation = true;
1452- StartIconDragRequest(GetMouseX(), GetMouseY());
1453+ StartIconDragRequest(x, y);
1454 }
1455
1456 return false;
1457@@ -1972,26 +1973,27 @@
1458
1459 void Launcher::StartIconDragRequest(int x, int y)
1460 {
1461- nux::Geometry geo = GetAbsoluteGeometry();
1462- AbstractLauncherIcon::Ptr drag_icon = MouseIconIntersection((int)(GetGeometry().width / 2.0f), y);
1463-
1464- x += geo.x;
1465- y += geo.y;
1466-
1467+ nux::Geometry const& abs_geo = GetAbsoluteGeometry();
1468+ AbstractLauncherIcon::Ptr drag_icon = MouseIconIntersection(abs_geo.width / 2.0f, y);
1469
1470 // FIXME: nux doesn't give nux::GetEventButton (button_flags) there, relying
1471 // on an internal Launcher property then
1472- bool can_drag = (_model->IconHasSister(drag_icon) || drag_icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE);
1473- if (drag_icon && _last_button_press == 1 && can_drag)
1474+ if (drag_icon && _last_button_press == 1 && drag_icon->position() == AbstractLauncherIcon::Position::FLOATING)
1475 {
1476+ auto const& icon_center = drag_icon->GetCenter(monitor);
1477+ x += abs_geo.x;
1478+ y += abs_geo.y;
1479+
1480 SetActionState(ACTION_DRAG_ICON);
1481 StartIconDrag(drag_icon);
1482- UpdateDragWindowPosition(drag_icon->GetCenter(monitor).x, drag_icon->GetCenter(monitor).y);
1483+ UpdateDragWindowPosition(icon_center.x, icon_center.y);
1484+
1485 if (_initial_drag_animation)
1486 {
1487 _drag_window->SetAnimationTarget(x, y);
1488 _drag_window->StartAnimation();
1489 }
1490+
1491 EnsureAnimation();
1492 }
1493 else
1494@@ -2008,6 +2010,7 @@
1495
1496 _hide_machine.SetQuirk(LauncherHideMachine::INTERNAL_DND_ACTIVE, true);
1497 _drag_icon = icon;
1498+ _drag_icon_position = _model->IconIndex(icon);
1499
1500 HideDragWindow();
1501 _offscreen_drag_texture = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture(_icon_size, _icon_size, 1, nux::BITFMT_R8G8B8A8);
1502@@ -2031,15 +2034,20 @@
1503 {
1504 hovered_icon->SetQuirk(AbstractLauncherIcon::Quirk::PULSE_ONCE, true);
1505
1506- launcher_removerequest.emit(_drag_icon);
1507+ remove_request.emit(_drag_icon);
1508
1509 HideDragWindow();
1510 EnsureAnimation();
1511 }
1512 else
1513 {
1514- if (!_drag_window->Cancelled())
1515+ if (!_drag_window->Cancelled() && _model->IconIndex(_drag_icon) != _drag_icon_position)
1516+ {
1517+ if (_drag_icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE)
1518+ _drag_icon->Stick(false);
1519+
1520 _model->Save();
1521+ }
1522
1523 if (_drag_window->on_anim_completed.connected())
1524 _drag_window->on_anim_completed.disconnect();
1525@@ -2103,15 +2111,11 @@
1526 return;
1527
1528 auto const& launcher_geo = GetGeometry();
1529- auto hovered_icon = MouseIconIntersection((launcher_geo.x + launcher_geo.width) / 2.0, y - GetAbsoluteY());
1530+ auto const& hovered_icon = MouseIconIntersection((launcher_geo.x + launcher_geo.width) / 2.0, y - GetAbsoluteY());
1531 struct timespec current;
1532 clock_gettime(CLOCK_MONOTONIC, &current);
1533 float progress = DragThresholdProgress(current);
1534
1535- // Icons of different types can't be mixed, so let's avoid this.
1536- if (hovered_icon && hovered_icon->GetIconType() != _drag_icon->GetIconType())
1537- hovered_icon = nullptr;
1538-
1539 if (hovered_icon && _drag_icon != hovered_icon)
1540 {
1541 if (progress >= 1.0f)
1542@@ -2130,12 +2134,8 @@
1543 {
1544 auto const& icon = *it;
1545
1546- if (!icon->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE) ||
1547- !icon->IsVisibleOnMonitor(monitor) ||
1548- icon->GetIconType() != _drag_icon->GetIconType())
1549- {
1550+ if (!icon->IsVisible() || !icon->IsVisibleOnMonitor(monitor))
1551 continue;
1552- }
1553
1554 if (y >= icon->GetCenter(monitor).y)
1555 {
1556@@ -2216,7 +2216,9 @@
1557 }
1558 else
1559 {
1560- StartIconDragRequest(x, y);
1561+ // We we can safely start the icon drag, from the original mouse-down position
1562+ sources_.Remove(START_DRAGICON_DURATION);
1563+ StartIconDragRequest(x - _dnd_delta_x, y - _dnd_delta_y);
1564 }
1565 }
1566 else if (GetActionState() == ACTION_DRAG_LAUNCHER)
1567@@ -2226,7 +2228,7 @@
1568 }
1569 else if (GetActionState() == ACTION_DRAG_ICON)
1570 {
1571- nux::Geometry geo = GetAbsoluteGeometry();
1572+ nux::Geometry const& geo = GetAbsoluteGeometry();
1573 UpdateDragWindowPosition(geo.x + x, geo.y + y);
1574 }
1575
1576@@ -2405,7 +2407,7 @@
1577 {
1578 _icon_mouse_down = launcher_icon;
1579 // if MouseUp after the time ended -> it's an icon drag, otherwise, it's starting an app
1580- auto cb_func = sigc::mem_fun(this, &Launcher::StartIconDragTimeout);
1581+ auto cb_func = sigc::bind(sigc::mem_fun(this, &Launcher::StartIconDragTimeout), x, y);
1582 sources_.AddTimeout(START_DRAGICON_DURATION, cb_func, START_DRAGICON_TIMEOUT);
1583
1584 launcher_icon->mouse_down.emit(nux::GetEventButton(button_flags), monitor, key_flags);
1585@@ -2452,7 +2454,7 @@
1586
1587 for (it = _model->begin(); it != _model->end(); ++it)
1588 {
1589- if (!(*it)->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE) || !(*it)->IsVisibleOnMonitor(monitor))
1590+ if (!(*it)->IsVisible() || !(*it)->IsVisibleOnMonitor(monitor))
1591 continue;
1592
1593 nux::Point2 screen_coord [4];
1594@@ -2537,35 +2539,41 @@
1595 nux::GetWindowCompositor().RestoreRenderingSurface();
1596 }
1597
1598+bool Launcher::DndIsSpecialRequest(std::string const& uri) const
1599+{
1600+ return (boost::algorithm::ends_with(uri, ".desktop") || uri.find("device://") == 0);
1601+}
1602+
1603 void Launcher::OnDNDDataCollected(const std::list<char*>& mimes)
1604 {
1605 _dnd_data.Reset();
1606
1607- unity::glib::String uri_list_const(g_strdup("text/uri-list"));
1608+ const std::string uri_list = "text/uri-list";
1609+ auto& display = nux::GetWindowThread()->GetGraphicsDisplay();
1610
1611- for (auto it : mimes)
1612+ for (auto const& mime : mimes)
1613 {
1614- if (!g_str_equal(it, uri_list_const.Value()))
1615+ if (mime != uri_list)
1616 continue;
1617
1618- _dnd_data.Fill(nux::GetWindowThread()->GetGraphicsDisplay().GetDndData(uri_list_const.Value()));
1619+ _dnd_data.Fill(display.GetDndData(const_cast<char*>(uri_list.c_str())));
1620 break;
1621 }
1622
1623 _hide_machine.SetQuirk(LauncherHideMachine::EXTERNAL_DND_ACTIVE, true);
1624
1625- for (auto it : _dnd_data.Uris())
1626+ auto const& uris = _dnd_data.Uris();
1627+ if (std::find_if(uris.begin(), uris.end(), [this] (std::string const& uri)
1628+ {return DndIsSpecialRequest(uri);}) != uris.end())
1629 {
1630- if (g_str_has_suffix(it.c_str(), ".desktop") || g_str_has_prefix(it.c_str(), "device://"))
1631- {
1632- _steal_drag = true;
1633- break;
1634- }
1635+ _steal_drag = true;
1636+
1637+ if (IsOverlayOpen())
1638+ SaturateIcons();
1639 }
1640-
1641- if (!_steal_drag)
1642+ else
1643 {
1644- for (auto it : *_model)
1645+ for (auto const& it : *_model)
1646 {
1647 if (it->ShouldHighlightOnDrag(_dnd_data))
1648 {
1649@@ -2579,11 +2587,6 @@
1650 }
1651 }
1652 }
1653- else
1654- {
1655- if (IsOverlayOpen())
1656- SaturateIcons();
1657- }
1658 }
1659
1660 void Launcher::ProcessDndEnter()
1661@@ -2651,32 +2654,29 @@
1662
1663 void Launcher::ProcessDndMove(int x, int y, std::list<char*> mimes)
1664 {
1665- nux::Area* parent = GetToplevel();
1666- unity::glib::String uri_list_const(g_strdup("text/uri-list"));
1667-
1668 if (!_data_checked)
1669 {
1670+ const std::string uri_list = "text/uri-list";
1671 _data_checked = true;
1672 _dnd_data.Reset();
1673+ auto& display = nux::GetWindowThread()->GetGraphicsDisplay();
1674
1675 // get the data
1676- for (auto it : mimes)
1677+ for (auto const& mime : mimes)
1678 {
1679- if (!g_str_equal(it, uri_list_const.Value()))
1680+ if (mime != uri_list)
1681 continue;
1682
1683- _dnd_data.Fill(nux::GetWindowThread()->GetGraphicsDisplay().GetDndData(uri_list_const.Value()));
1684+ _dnd_data.Fill(display.GetDndData(const_cast<char*>(uri_list.c_str())));
1685 break;
1686 }
1687
1688 // see if the launcher wants this one
1689- for (auto it : _dnd_data.Uris())
1690+ auto const& uris = _dnd_data.Uris();
1691+ if (std::find_if(uris.begin(), uris.end(), [this] (std::string const& uri)
1692+ {return DndIsSpecialRequest(uri);}) != uris.end())
1693 {
1694- if (g_str_has_suffix(it.c_str(), ".desktop") || g_str_has_prefix(it.c_str(), "device://"))
1695- {
1696- _steal_drag = true;
1697- break;
1698- }
1699+ _steal_drag = true;
1700 }
1701
1702 // only set hover once we know our first x/y
1703@@ -2685,7 +2685,7 @@
1704
1705 if (!_steal_drag)
1706 {
1707- for (auto it : *_model)
1708+ for (auto const& it : *_model)
1709 {
1710 if (it->ShouldHighlightOnDrag(_dnd_data))
1711 it->SetQuirk(AbstractLauncherIcon::Quirk::DESAT, false);
1712@@ -2695,7 +2695,7 @@
1713 }
1714 }
1715
1716- SetMousePosition(x - parent->GetGeometry().x, y - parent->GetGeometry().y);
1717+ SetMousePosition(x - _parent->GetGeometry().x, y - _parent->GetGeometry().y);
1718
1719 if (!IsOverlayOpen() && _mouse_position.x == 0 && _mouse_position.y <= (_parent->GetGeometry().height - _icon_size - 2 * _space_between_icons) && !_drag_edge_touching)
1720 {
1721@@ -2722,7 +2722,7 @@
1722 if (hovered_icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH)
1723 _steal_drag = false;
1724
1725- if (hovered_icon->GetIconType() == AbstractLauncherIcon::IconType::APPLICATION || hovered_icon->GetIconType() == AbstractLauncherIcon::IconType::EXPO)
1726+ if (hovered_icon->position() == AbstractLauncherIcon::Position::FLOATING)
1727 hovered_icon_is_appropriate = true;
1728 }
1729
1730@@ -2732,7 +2732,6 @@
1731 if (!_dnd_hovered_icon && hovered_icon_is_appropriate)
1732 {
1733 _dnd_hovered_icon = new SpacerLauncherIcon(monitor());
1734- _dnd_hovered_icon->SetSortPriority(G_MAXINT);
1735 _model->AddIcon(_dnd_hovered_icon);
1736 _model->ReorderBefore(_dnd_hovered_icon, hovered_icon, true);
1737 }
1738@@ -2787,34 +2786,10 @@
1739 {
1740 if (_steal_drag)
1741 {
1742- for (auto it : _dnd_data.Uris())
1743+ for (auto const& uri : _dnd_data.Uris())
1744 {
1745- if (g_str_has_suffix(it.c_str(), ".desktop"))
1746- {
1747- char* path = nullptr;
1748-
1749- if (g_str_has_prefix(it.c_str(), "application://"))
1750- {
1751- const char* tmp = it.c_str() + strlen("application://");
1752- unity::glib::String tmp2(g_strdup_printf("file:///usr/share/applications/%s", tmp));
1753- path = g_filename_from_uri(tmp2.Value(), NULL, NULL);
1754- }
1755- else if (g_str_has_prefix(it.c_str(), "file://"))
1756- {
1757- path = g_filename_from_uri(it.c_str(), NULL, NULL);
1758- }
1759-
1760- if (path)
1761- {
1762- launcher_addrequest.emit(path, _dnd_hovered_icon);
1763- g_free(path);
1764- }
1765- }
1766- else if (devices_settings_ && g_str_has_prefix(it.c_str(), "device://"))
1767- {
1768- const gchar* uuid = it.c_str() + 9;
1769- devices_settings_->TryToUnblacklist(uuid);
1770- }
1771+ if (DndIsSpecialRequest(uri))
1772+ add_request.emit(uri, _dnd_hovered_icon);
1773 }
1774 }
1775 else if (_dnd_hovered_icon && _drag_action != nux::DNDACTION_NONE)
1776
1777=== modified file 'launcher/Launcher.h'
1778--- launcher/Launcher.h 2012-09-01 14:00:19 +0000
1779+++ launcher/Launcher.h 2012-09-18 15:52:46 +0000
1780@@ -83,8 +83,6 @@
1781 void SetModel(LauncherModel::Ptr model);
1782 LauncherModel::Ptr GetModel() const;
1783
1784- void SetDevicesSettings(DevicesSettings::Ptr devices_settings);
1785-
1786 void StartKeyShowLauncher();
1787 void EndKeyShowLauncher();
1788
1789@@ -121,9 +119,8 @@
1790 int GetDragDelta() const;
1791 void SetHover(bool hovered);
1792
1793- sigc::signal<void, char*, AbstractLauncherIcon::Ptr> launcher_addrequest;
1794- sigc::signal<void, AbstractLauncherIcon::Ptr> launcher_removerequest;
1795- sigc::signal<void, AbstractLauncherIcon::Ptr> icon_animation_complete;
1796+ sigc::signal<void, std::string const&, AbstractLauncherIcon::Ptr> add_request;
1797+ sigc::signal<void, AbstractLauncherIcon::Ptr> remove_request;
1798 sigc::signal<void> selection_change;
1799 sigc::signal<void> hidden_changed;
1800 sigc::signal<void> sc_launcher_icon_animation;
1801@@ -199,7 +196,7 @@
1802 void OnSelectionChanged(AbstractLauncherIcon::Ptr selection);
1803
1804 bool StrutHack();
1805- bool StartIconDragTimeout();
1806+ bool StartIconDragTimeout(int x, int y);
1807 bool OnScrollTimeout();
1808 bool OnUpdateDragManagerTimeout();
1809
1810@@ -319,6 +316,7 @@
1811 void DndReset();
1812 void DndHoveredIconReset();
1813 void DndTimeoutSetup();
1814+ bool DndIsSpecialRequest(std::string const& uri) const;
1815
1816 LauncherModel::Ptr _model;
1817 nux::BaseWindow* _parent;
1818@@ -371,6 +369,7 @@
1819 int _launcher_drag_delta_min;
1820 int _enter_y;
1821 int _last_button_press;
1822+ int _drag_icon_position;
1823 float _drag_out_delta_x;
1824 bool _drag_gesture_ongoing;
1825 float _last_reveal_progress;
1826@@ -395,8 +394,6 @@
1827 ui::AbstractIconRenderer::Ptr icon_renderer;
1828 BackgroundEffectHelper bg_effect_helper_;
1829
1830- DevicesSettings::Ptr devices_settings_;
1831-
1832 UBusManager ubus_;
1833 glib::SourceManager sources_;
1834
1835
1836=== modified file 'launcher/LauncherController.cpp'
1837--- launcher/LauncherController.cpp 2012-09-11 09:59:25 +0000
1838+++ launcher/LauncherController.cpp 2012-09-18 15:52:46 +0000
1839@@ -1,6 +1,6 @@
1840 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
1841 /*
1842- * Copyright (C) 2010, 2011 Canonical Ltd
1843+ * Copyright (C) 2010-2012 Canonical Ltd
1844 *
1845 * This program is free software: you can redistribute it and/or modify
1846 * it under the terms of the GNU General Public License version 3 as
1847@@ -16,6 +16,7 @@
1848 *
1849 * Authored by: Jason Smith <jason.smith@canonical.com>
1850 * Tim Penhey <tim.penhey@canonical.com>
1851+ * Marco Trevisan <marco.trevisan@canonical.com>
1852 */
1853
1854 #include <glib/gi18n-lib.h>
1855@@ -25,6 +26,7 @@
1856 #include <Nux/HLayout.h>
1857 #include <Nux/BaseWindow.h>
1858 #include <NuxCore/Logger.h>
1859+#include <UnityCore/DesktopUtilities.h>
1860
1861 #include "LauncherOptions.h"
1862 #include "BamfLauncherIcon.h"
1863@@ -35,6 +37,7 @@
1864 #include "LauncherController.h"
1865 #include "LauncherControllerPrivate.h"
1866 #include "SoftwareCenterLauncherIcon.h"
1867+#include "ExpoLauncherIcon.h"
1868 #include "unity-shared/WindowManager.h"
1869 #include "TrashLauncherIcon.h"
1870 #include "BFBLauncherIcon.h"
1871@@ -82,63 +85,45 @@
1872 const std::string KEYPRESS_TIMEOUT = "keypress-timeout";
1873 const std::string LABELS_TIMEOUT = "label-show-timeout";
1874 const std::string HIDE_TIMEOUT = "hide-timeout";
1875-}
1876-}
1877-
1878-
1879+
1880+ const std::string SOFTWARE_CENTER_AGENT = "software-center-agent";
1881+
1882+ const std::string RUNNING_APPS_URI = FavoriteStore::URI_PREFIX_UNITY + "running-apps";
1883+ const std::string DEVICES_URI = FavoriteStore::URI_PREFIX_UNITY + "devices";
1884+}
1885+}
1886
1887 GDBusInterfaceVTable Controller::Impl::interface_vtable =
1888 { Controller::Impl::OnDBusMethodCall, NULL, NULL};
1889
1890-Controller::Impl::Impl(Display* display, Controller* parent)
1891+
1892+Controller::Impl::Impl(Controller* parent)
1893 : parent_(parent)
1894- , model_(new LauncherModel())
1895- , sort_priority_(0)
1896- , volume_monitor_(new VolumeMonitorWrapper)
1897- , devices_settings_(new DevicesSettingsImp)
1898- , device_section_(volume_monitor_, devices_settings_)
1899- , show_desktop_icon_(false)
1900- , display_(display)
1901+ , model_(std::make_shared<LauncherModel>())
1902 , matcher_(bamf_matcher_get_default())
1903+ , device_section_(std::make_shared<VolumeMonitorWrapper>(), std::make_shared<DevicesSettingsImp>())
1904+ , expo_icon_(new ExpoLauncherIcon())
1905+ , desktop_icon_(new DesktopLauncherIcon())
1906+ , sort_priority_(AbstractLauncherIcon::DefaultPriority(AbstractLauncherIcon::IconType::APPLICATION))
1907+ , launcher_open(false)
1908+ , launcher_keynav(false)
1909+ , launcher_grabbed(false)
1910+ , reactivate_keynav(false)
1911+ , keynav_restore_window_(true)
1912+ , launcher_key_press_time_(0)
1913+ , dbus_owner_(g_bus_own_name(G_BUS_TYPE_SESSION, DBUS_NAME.c_str(), G_BUS_NAME_OWNER_FLAGS_NONE,
1914+ OnBusAcquired, nullptr, nullptr, this, nullptr))
1915 {
1916 edge_barriers_.options = parent_->options();
1917
1918 UScreen* uscreen = UScreen::GetDefault();
1919- auto monitors = uscreen->GetMonitors();
1920- int primary = uscreen->GetPrimaryMonitor();
1921-
1922- launcher_open = false;
1923- launcher_keynav = false;
1924- launcher_grabbed = false;
1925- reactivate_keynav = false;
1926- keynav_restore_window_ = true;
1927-
1928- EnsureLaunchers(primary, monitors);
1929-
1930- launcher_ = launchers[0];
1931- device_section_.IconAdded.connect(sigc::mem_fun(this, &Impl::OnIconAdded));
1932-
1933- num_workspaces_ = WindowManager::Default()->WorkspaceCount();
1934- if (num_workspaces_ > 1)
1935- {
1936- InsertExpoAction();
1937- }
1938-
1939- // Insert the "Show Desktop" launcher icon in the launcher...
1940- if (show_desktop_icon_)
1941- InsertDesktopIcon();
1942-
1943- InsertTrash();
1944-
1945- sources_.AddTimeout(500, [&] { SetupBamf(); return false; });
1946+ EnsureLaunchers(uscreen->GetPrimaryMonitor(), uscreen->GetMonitors());
1947+
1948+ SetupIcons();
1949
1950 remote_model_.entry_added.connect(sigc::mem_fun(this, &Impl::OnLauncherEntryRemoteAdded));
1951 remote_model_.entry_removed.connect(sigc::mem_fun(this, &Impl::OnLauncherEntryRemoteRemoved));
1952
1953- FavoriteStore::Instance().favorite_added.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreFavoriteAdded));
1954- FavoriteStore::Instance().favorite_removed.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreFavoriteRemoved));
1955- FavoriteStore::Instance().reordered.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreReordered));
1956-
1957 LauncherHideMode hide_mode = parent_->options()->hide_mode;
1958 BFBLauncherIcon* bfb = new BFBLauncherIcon(hide_mode);
1959 RegisterIcon(AbstractLauncherIcon::Ptr(bfb));
1960@@ -146,35 +131,27 @@
1961 HudLauncherIcon* hud = new HudLauncherIcon(hide_mode);
1962 RegisterIcon(AbstractLauncherIcon::Ptr(hud));
1963
1964- parent_->options()->hide_mode.changed.connect([bfb,hud](LauncherHideMode mode) {
1965+ TrashLauncherIcon* trash = new TrashLauncherIcon();
1966+ RegisterIcon(AbstractLauncherIcon::Ptr(trash));
1967+
1968+ parent_->options()->hide_mode.changed.connect([bfb, hud](LauncherHideMode mode) {
1969 bfb->SetHideMode(mode);
1970 hud->SetHideMode(mode);
1971 });
1972
1973- desktop_icon_ = AbstractLauncherIcon::Ptr(new DesktopLauncherIcon());
1974-
1975 uscreen->changed.connect(sigc::mem_fun(this, &Controller::Impl::OnScreenChanged));
1976
1977 WindowManager& plugin_adapter = *(WindowManager::Default());
1978- plugin_adapter.window_focus_changed.connect (sigc::mem_fun (this, &Controller::Impl::OnWindowFocusChanged));
1979-
1980- launcher_key_press_time_ = 0;
1981+ plugin_adapter.window_focus_changed.connect(sigc::mem_fun(this, &Controller::Impl::OnWindowFocusChanged));
1982
1983 ubus.RegisterInterest(UBUS_QUICKLIST_END_KEY_NAV, [&](GVariant * args) {
1984 if (reactivate_keynav)
1985 parent_->KeyNavGrab();
1986- model_->SetSelection(reactivate_index);
1987+
1988+ model_->SetSelection(reactivate_index);
1989 });
1990
1991 parent_->AddChild(model_.get());
1992-
1993- uscreen->resuming.connect([&]() -> void {
1994- for (auto launcher : launchers)
1995- launcher->QueueDraw();
1996- });
1997-
1998- dbus_owner_ = g_bus_own_name(G_BUS_TYPE_SESSION, DBUS_NAME.c_str(), G_BUS_NAME_OWNER_FLAGS_NONE,
1999- OnBusAcquired, nullptr, nullptr, this, nullptr);
2000 }
2001
2002 Controller::Impl::~Impl()
2003@@ -182,9 +159,9 @@
2004 // Since the launchers are in a window which adds a reference to the
2005 // launcher, we need to make sure the base windows are unreferenced
2006 // otherwise the launchers never die.
2007- for (auto launcher_ptr : launchers)
2008+ for (auto const& launcher_ptr : launchers)
2009 {
2010- if (launcher_ptr.IsValid())
2011+ if (launcher_ptr)
2012 launcher_ptr->GetParent()->UnReference();
2013 }
2014
2015@@ -198,7 +175,7 @@
2016 unsigned int launchers_size = launchers.size();
2017 unsigned int last_launcher = 0;
2018
2019- for (unsigned int i = 0; i < num_launchers; i++, last_launcher++)
2020+ for (unsigned int i = 0; i < num_launchers; ++i, ++last_launcher)
2021 {
2022 if (i >= launchers_size)
2023 {
2024@@ -232,6 +209,7 @@
2025 }
2026 }
2027
2028+ launcher_ = launchers[0];
2029 launchers.resize(num_launchers);
2030 }
2031
2032@@ -240,7 +218,7 @@
2033 EnsureLaunchers(primary_monitor, monitors);
2034 }
2035
2036-void Controller::Impl::OnWindowFocusChanged (guint32 xid)
2037+void Controller::Impl::OnWindowFocusChanged(guint32 xid)
2038 {
2039 static bool keynav_first_focus = false;
2040
2041@@ -264,11 +242,9 @@
2042 nux::BaseWindow* launcher_window = new nux::BaseWindow(TEXT("LauncherWindow"));
2043
2044 Launcher* launcher = new Launcher(launcher_window, nux::ObjectPtr<DNDCollectionWindow>(new DNDCollectionWindow));
2045- launcher->display = display_;
2046 launcher->monitor = monitor;
2047 launcher->options = parent_->options();
2048 launcher->SetModel(model_);
2049- launcher->SetDevicesSettings(devices_settings_);
2050
2051 nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
2052 layout->AddView(launcher, 1);
2053@@ -283,58 +259,103 @@
2054 launcher_window->InputWindowEnableStruts(parent_->options()->hide_mode == LAUNCHER_HIDE_NEVER);
2055 launcher_window->SetEnterFocusInputArea(launcher);
2056
2057- launcher->launcher_addrequest.connect(sigc::mem_fun(this, &Impl::OnLauncherAddRequest));
2058- launcher->launcher_removerequest.connect(sigc::mem_fun(this, &Impl::OnLauncherRemoveRequest));
2059-
2060- launcher->icon_animation_complete.connect(sigc::mem_fun(this, &Impl::OnSCIconAnimationComplete));
2061+ launcher->add_request.connect(sigc::mem_fun(this, &Impl::OnLauncherAddRequest));
2062+ launcher->remove_request.connect(sigc::mem_fun(this, &Impl::OnLauncherRemoveRequest));
2063
2064 parent_->AddChild(launcher);
2065
2066 return launcher;
2067 }
2068
2069-void Controller::Impl::OnLauncherAddRequest(char* path, AbstractLauncherIcon::Ptr before)
2070-{
2071- for (auto it : model_->GetSublist<BamfLauncherIcon> ())
2072- {
2073- if (path && path == it->DesktopFile())
2074- {
2075- it->Stick();
2076- model_->ReorderBefore(it, before, false);
2077- Save();
2078- return;
2079- }
2080- }
2081-
2082- AbstractLauncherIcon::Ptr result = CreateFavorite(path);
2083- if (result)
2084- {
2085- RegisterIcon(result);
2086- if (before)
2087- model_->ReorderBefore(result, before, false);
2088- }
2089-
2090- Save();
2091-}
2092-
2093-void Controller::Impl::Save()
2094-{
2095- unity::FavoriteList desktop_paths;
2096-
2097- // Updates gsettings favorites.
2098- auto launchers = model_->GetSublist<BamfLauncherIcon> ();
2099- for (auto icon : launchers)
2100+void Controller::Impl::OnLauncherAddRequest(std::string const& icon_uri, AbstractLauncherIcon::Ptr icon_before)
2101+{
2102+ std::string app_uri;
2103+
2104+ if (icon_uri.find(FavoriteStore::URI_PREFIX_FILE) == 0)
2105+ {
2106+ auto const& desktop_path = icon_uri.substr(FavoriteStore::URI_PREFIX_FILE.length());
2107+ app_uri = FavoriteStore::URI_PREFIX_APP + DesktopUtilities::GetDesktopID(desktop_path);
2108+ }
2109+
2110+ auto const& icon = GetIconByUri(app_uri.empty() ? icon_uri : app_uri);
2111+
2112+ if (icon)
2113+ {
2114+ icon->Stick(false);
2115+ model_->ReorderAfter(icon, icon_before);
2116+ }
2117+ else
2118+ {
2119+ if (icon_before)
2120+ RegisterIcon(CreateFavoriteIcon(icon_uri), icon_before->SortPriority());
2121+ else
2122+ RegisterIcon(CreateFavoriteIcon(icon_uri));
2123+ }
2124+
2125+ SaveIconsOrder();
2126+}
2127+
2128+void Controller::Impl::AddFavoriteKeepingOldPosition(FavoriteList& icons, std::string const& icon_uri) const
2129+{
2130+ auto const& favorites = FavoriteStore::Instance().GetFavorites();
2131+ auto it = std::find(favorites.rbegin(), favorites.rend(), icon_uri);
2132+
2133+ FavoriteList::reverse_iterator icons_it = icons.rbegin();
2134+
2135+ while (it != favorites.rend())
2136+ {
2137+ icons_it = std::find(icons.rbegin(), icons.rend(), *it);
2138+
2139+ if (icons_it != icons.rend())
2140+ break;
2141+
2142+ ++it;
2143+ }
2144+
2145+ icons.insert(icons_it.base(), icon_uri);
2146+}
2147+
2148+void Controller::Impl::SaveIconsOrder()
2149+{
2150+ FavoriteList icons;
2151+ bool found_first_running_app = false;
2152+ bool found_first_device = false;
2153+
2154+ for (auto const& icon : *model_)
2155 {
2156 if (!icon->IsSticky())
2157+ {
2158+ if (!icon->IsVisible())
2159+ continue;
2160+
2161+ if (!found_first_running_app && icon->GetIconType() == AbstractLauncherIcon::IconType::APPLICATION)
2162+ {
2163+ found_first_running_app = true;
2164+ icons.push_back(local::RUNNING_APPS_URI);
2165+ }
2166+
2167+ if (!found_first_device && icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE)
2168+ {
2169+ found_first_device = true;
2170+ icons.push_back(local::DEVICES_URI);
2171+ }
2172+
2173 continue;
2174-
2175- std::string const& desktop_file = icon->DesktopFile();
2176-
2177- if (!desktop_file.empty())
2178- desktop_paths.push_back(desktop_file);
2179+ }
2180+
2181+ std::string const& remote_uri = icon->RemoteUri();
2182+
2183+ if (!remote_uri.empty())
2184+ icons.push_back(remote_uri);
2185 }
2186
2187- unity::FavoriteStore::Instance().SetFavorites(desktop_paths);
2188+ if (!found_first_running_app)
2189+ AddFavoriteKeepingOldPosition(icons, local::RUNNING_APPS_URI);
2190+
2191+ if (!found_first_device)
2192+ AddFavoriteKeepingOldPosition(icons, local::DEVICES_URI);
2193+
2194+ FavoriteStore::Instance().SetFavorites(icons);
2195 }
2196
2197 void
2198@@ -345,64 +366,53 @@
2199 int icon_y,
2200 int icon_size)
2201 {
2202- auto bamf_icons = model_->GetSublist<BamfLauncherIcon>();
2203- for (auto icon : bamf_icons)
2204- {
2205- if (icon->DesktopFile() == path)
2206- return;
2207- }
2208-
2209 // Check if desktop file was supplied, or if it's set to SC's agent
2210 // See https://bugs.launchpad.net/unity/+bug/1002440
2211- if (path.empty() || path == "software-center-agent")
2212- return;
2213-
2214- SoftwareCenterLauncherIcon::Ptr result = CreateSCLauncherIcon(path, aptdaemon_trans_id, icon_path);
2215-
2216- CurrentLauncher()->ForceReveal(true);
2217+ if (path.empty() || path == local::SOFTWARE_CENTER_AGENT)
2218+ return;
2219+
2220+ auto const& icon = std::find_if(model_->begin(), model_->end(),
2221+ [&path](AbstractLauncherIcon::Ptr const& i) { return (i->DesktopFile() == path); });
2222+
2223+ if (icon != model_->end())
2224+ return;
2225+
2226+ auto const& result = CreateSCLauncherIcon(path, aptdaemon_trans_id, icon_path);
2227
2228 if (result)
2229 {
2230- result->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false);
2231- result->Animate(CurrentLauncher(), icon_x, icon_y, icon_size);
2232- RegisterIcon(result);
2233- Save();
2234+ // Setting the icon position and adding it to the model, makes the launcher
2235+ // to compute its center
2236+ RegisterIcon(result, GetLastIconPriority<BamfLauncherIcon>("", true));
2237+
2238+ // This will ensure that the center of the new icon is set, so that
2239+ // the animation could be done properly.
2240+ sources_.AddIdle([this, icon_x, icon_y, result] {
2241+ result->Animate(CurrentLauncher(), icon_x, icon_y);
2242+ return false;
2243+ });
2244 }
2245 }
2246
2247-void Controller::Impl::OnSCIconAnimationComplete(AbstractLauncherIcon::Ptr icon)
2248-{
2249- icon->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, true);
2250- launcher_->ForceReveal(false);
2251-}
2252-
2253 void Controller::Impl::SortAndUpdate()
2254 {
2255- gint shortcut = 1;
2256+ unsigned shortcut = 1;
2257
2258- auto launchers = model_->GetSublist<BamfLauncherIcon> ();
2259- for (auto icon : launchers)
2260+ for (auto const& icon : model_->GetSublist<BamfLauncherIcon>())
2261 {
2262 if (shortcut <= 10 && icon->IsVisible())
2263 {
2264- std::stringstream shortcut_string;
2265- shortcut_string << (shortcut % 10);
2266- icon->SetShortcut(shortcut_string.str()[0]);
2267+ icon->SetShortcut(std::to_string(shortcut % 10)[0]);
2268 ++shortcut;
2269 }
2270- // reset shortcut
2271 else
2272 {
2273+ // reset shortcut
2274 icon->SetShortcut(0);
2275 }
2276 }
2277 }
2278
2279-void Controller::Impl::OnIconAdded(AbstractLauncherIcon::Ptr icon)
2280-{
2281- this->RegisterIcon(icon);
2282-}
2283-
2284 void Controller::Impl::OnIconRemoved(AbstractLauncherIcon::Ptr icon)
2285 {
2286 SortAndUpdate();
2287@@ -428,10 +438,13 @@
2288 {
2289 auto device_icon = dynamic_cast<VolumeLauncherIcon*>(icon.GetPointer());
2290
2291- if (device_icon && device_icon->CanEject())
2292- device_icon->EjectAndShowNotification();
2293- else if (device_icon && device_icon->CanStop())
2294- device_icon->StopDrive();
2295+ if (device_icon)
2296+ {
2297+ if (device_icon->CanEject())
2298+ device_icon->EjectAndShowNotification();
2299+ else if (device_icon->CanStop())
2300+ device_icon->StopDrive();
2301+ }
2302
2303 break;
2304 }
2305@@ -442,63 +455,63 @@
2306
2307 void Controller::Impl::OnLauncherEntryRemoteAdded(LauncherEntryRemote::Ptr const& entry)
2308 {
2309- for (auto icon : *model_)
2310- {
2311- if (!icon || icon->RemoteUri().empty())
2312- continue;
2313-
2314- if (entry->AppUri() == icon->RemoteUri())
2315- {
2316- icon->InsertEntryRemote(entry);
2317- }
2318- }
2319+ if (entry->AppUri().empty())
2320+ return;
2321+
2322+ auto const& apps_icons = model_->GetSublist<BamfLauncherIcon>();
2323+ auto const& icon = std::find_if(apps_icons.begin(), apps_icons.end(),
2324+ [&entry](AbstractLauncherIcon::Ptr const& i) { return (i->RemoteUri() == entry->AppUri()); });
2325+
2326+ if (icon != apps_icons.end())
2327+ (*icon)->InsertEntryRemote(entry);
2328 }
2329
2330 void Controller::Impl::OnLauncherEntryRemoteRemoved(LauncherEntryRemote::Ptr const& entry)
2331 {
2332- for (auto icon : *model_)
2333- {
2334+ for (auto const& icon : *model_)
2335 icon->RemoveEntryRemote(entry);
2336- }
2337 }
2338
2339 void Controller::Impl::OnFavoriteStoreFavoriteAdded(std::string const& entry, std::string const& pos, bool before)
2340 {
2341- auto bamf_list = model_->GetSublist<BamfLauncherIcon>();
2342- AbstractLauncherIcon::Ptr other;
2343- if (bamf_list.size() > 0)
2344- other = *(bamf_list.begin());
2345+ if (entry == local::RUNNING_APPS_URI || entry == local::DEVICES_URI)
2346+ {
2347+ // Since the running apps and the devices are always shown, when added to
2348+ // the model, we only have to re-order them
2349+ ResetIconPriorities();
2350+ return;
2351+ }
2352+
2353+ AbstractLauncherIcon::Ptr other = *(model_->begin());
2354
2355 if (!pos.empty())
2356 {
2357- for (auto it : bamf_list)
2358+ for (auto const& it : *model_)
2359 {
2360- if (it->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE) && pos == it->DesktopFile())
2361+ if (it->IsVisible() && pos == it->RemoteUri())
2362 other = it;
2363 }
2364 }
2365
2366- for (auto it : bamf_list)
2367+ AbstractLauncherIcon::Ptr const& fav = GetIconByUri(entry);
2368+ if (fav)
2369 {
2370- if (entry == it->DesktopFile())
2371- {
2372- it->Stick(false);
2373- if (!before)
2374- model_->ReorderAfter(it, other);
2375- else
2376- model_->ReorderBefore(it, other, false);
2377- return;
2378- }
2379+ fav->Stick(false);
2380+
2381+ if (before)
2382+ model_->ReorderBefore(fav, other, false);
2383+ else
2384+ model_->ReorderAfter(fav, other);
2385 }
2386-
2387- AbstractLauncherIcon::Ptr result = CreateFavorite(entry.c_str());
2388- if (result)
2389+ else
2390 {
2391+ AbstractLauncherIcon::Ptr const& result = CreateFavoriteIcon(entry);
2392 RegisterIcon(result);
2393- if (!before)
2394+
2395+ if (before)
2396+ model_->ReorderBefore(result, other, false);
2397+ else
2398 model_->ReorderAfter(result, other);
2399- else
2400- model_->ReorderBefore(result, other, false);
2401 }
2402
2403 SortAndUpdate();
2404@@ -506,104 +519,132 @@
2405
2406 void Controller::Impl::OnFavoriteStoreFavoriteRemoved(std::string const& entry)
2407 {
2408- for (auto icon : model_->GetSublist<BamfLauncherIcon> ())
2409- {
2410- if (icon->DesktopFile() == entry)
2411- {
2412- icon->UnStick();
2413- break;
2414- }
2415+ if (entry == local::RUNNING_APPS_URI || entry == local::DEVICES_URI)
2416+ {
2417+ // Since the running apps and the devices are always shown, when added to
2418+ // the model, we only have to re-order them
2419+ ResetIconPriorities();
2420+ return;
2421+ }
2422+
2423+ auto const& icon = GetIconByUri(entry);
2424+ if (icon)
2425+ {
2426+ icon->UnStick();
2427+
2428+ // When devices are removed from favorites, they should be re-ordered (not removed)
2429+ if (icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE)
2430+ ResetIconPriorities();
2431 }
2432 }
2433
2434-void Controller::Impl::OnFavoriteStoreReordered()
2435+void Controller::Impl::ResetIconPriorities()
2436 {
2437 FavoriteList const& favs = FavoriteStore::Instance().GetFavorites();
2438- auto bamf_list = model_->GetSublist<BamfLauncherIcon>();
2439-
2440- int i = 0;
2441- for (auto it : favs)
2442- {
2443- auto icon = std::find_if(bamf_list.begin(), bamf_list.end(),
2444- [&it](AbstractLauncherIcon::Ptr x) { return (x->DesktopFile() == it); });
2445-
2446- if (icon != bamf_list.end())
2447- {
2448- (*icon)->SetSortPriority(i++);
2449- }
2450- }
2451-
2452- for (auto it : bamf_list)
2453- {
2454- if (!it->IsSticky())
2455- it->SetSortPriority(i++);
2456+ auto const& apps_icons = model_->GetSublist<BamfLauncherIcon>();
2457+ auto const& volumes_icons = model_->GetSublist<VolumeLauncherIcon>();
2458+ bool running_apps_found = false;
2459+ bool volumes_found = false;
2460+
2461+ for (auto const& fav : favs)
2462+ {
2463+ if (fav == local::RUNNING_APPS_URI)
2464+ {
2465+ for (auto const& ico : apps_icons)
2466+ {
2467+ if (!ico->IsSticky())
2468+ ico->SetSortPriority(++sort_priority_);
2469+ }
2470+
2471+ running_apps_found = true;
2472+ continue;
2473+ }
2474+ else if (fav == local::DEVICES_URI)
2475+ {
2476+ for (auto const& ico : volumes_icons)
2477+ {
2478+ if (!ico->IsSticky())
2479+ ico->SetSortPriority(++sort_priority_);
2480+ }
2481+
2482+ volumes_found = true;
2483+ continue;
2484+ }
2485+
2486+ auto const& icon = GetIconByUri(fav);
2487+
2488+ if (icon)
2489+ icon->SetSortPriority(++sort_priority_);
2490+ }
2491+
2492+ if (!running_apps_found)
2493+ {
2494+ for (auto const& ico : apps_icons)
2495+ {
2496+ if (!ico->IsSticky())
2497+ ico->SetSortPriority(++sort_priority_);
2498+ }
2499+ }
2500+
2501+ if (!volumes_found)
2502+ {
2503+ for (auto const& ico : volumes_icons)
2504+ {
2505+ if (!ico->IsSticky())
2506+ ico->SetSortPriority(++sort_priority_);
2507+ }
2508 }
2509
2510 model_->Sort();
2511 }
2512
2513-void Controller::Impl::OnExpoActivated()
2514-{
2515- WindowManager::Default()->InitiateExpo();
2516-}
2517-
2518-void Controller::Impl::InsertTrash()
2519-{
2520- AbstractLauncherIcon::Ptr icon(new TrashLauncherIcon());
2521- RegisterIcon(icon);
2522-}
2523-
2524 void Controller::Impl::UpdateNumWorkspaces(int workspaces)
2525 {
2526- if ((num_workspaces_ == 0) && (workspaces > 0))
2527- {
2528- InsertExpoAction();
2529- }
2530- else if ((num_workspaces_ > 0) && (workspaces == 0))
2531- {
2532- RemoveExpoAction();
2533- }
2534-
2535- num_workspaces_ = workspaces;
2536-}
2537-
2538-void Controller::Impl::InsertExpoAction()
2539-{
2540- expo_icon_ = AbstractLauncherIcon::Ptr(new SimpleLauncherIcon(AbstractLauncherIcon::IconType::EXPO));
2541-
2542- SimpleLauncherIcon* icon = static_cast<SimpleLauncherIcon*>(expo_icon_.GetPointer());
2543- icon->tooltip_text = _("Workspace Switcher");
2544- icon->icon_name = "workspace-switcher";
2545- icon->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, true);
2546- icon->SetQuirk(AbstractLauncherIcon::Quirk::RUNNING, false);
2547- icon->SetShortcut('s');
2548-
2549- on_expoicon_activate_connection_ = icon->activate.connect(sigc::mem_fun(this, &Impl::OnExpoActivated));
2550-
2551-
2552- RegisterIcon(expo_icon_);
2553-}
2554-
2555-void Controller::Impl::RemoveExpoAction()
2556-{
2557- if (on_expoicon_activate_connection_)
2558- on_expoicon_activate_connection_.disconnect();
2559- model_->RemoveIcon(expo_icon_);
2560-}
2561-
2562-void Controller::Impl::InsertDesktopIcon()
2563-{
2564- RegisterIcon(desktop_icon_);
2565-}
2566-
2567-void Controller::Impl::RemoveDesktopIcon()
2568-{
2569- model_->RemoveIcon(desktop_icon_);
2570-}
2571-
2572-void Controller::Impl::RegisterIcon(AbstractLauncherIcon::Ptr icon)
2573-{
2574+ bool visible = expo_icon_->IsVisible();
2575+ bool wp_enabled = (workspaces > 1);
2576+
2577+ if (wp_enabled && !visible)
2578+ {
2579+ if (FavoriteStore::Instance().IsFavorite(expo_icon_->RemoteUri()))
2580+ {
2581+ expo_icon_->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, true);
2582+ }
2583+ }
2584+ else if (!wp_enabled && visible)
2585+ {
2586+ expo_icon_->SetQuirk(AbstractLauncherIcon::Quirk::VISIBLE, false);
2587+ }
2588+}
2589+
2590+void Controller::Impl::RegisterIcon(AbstractLauncherIcon::Ptr icon, int priority)
2591+{
2592+ if (!icon || model_->IconIndex(icon) >= 0)
2593+ return;
2594+
2595+ if (priority != std::numeric_limits<int>::min())
2596+ icon->SetSortPriority(priority);
2597+
2598+ icon->position_saved.connect([this] {
2599+ // These calls must be done in order: first we save the new sticky icons
2600+ // then we re-order the model so that there won't be two icons with the same
2601+ // priority
2602+ SaveIconsOrder();
2603+ ResetIconPriorities();
2604+ });
2605+
2606+ std::string const& icon_uri = icon->RemoteUri();
2607+ icon->position_forgot.connect([this, icon_uri] {
2608+ FavoriteStore::Instance().RemoveFavorite(icon_uri);
2609+ });
2610+
2611+ if (icon->GetIconType() == AbstractLauncherIcon::IconType::APPLICATION)
2612+ {
2613+ icon->visibility_changed.connect(sigc::mem_fun(this, &Impl::SortAndUpdate));
2614+ SortAndUpdate();
2615+ }
2616+
2617 model_->AddIcon(icon);
2618+
2619 std::string const& path = icon->DesktopFile();
2620
2621 if (!path.empty())
2622@@ -615,7 +656,59 @@
2623 }
2624 }
2625
2626-/* static private */
2627+template<typename IconType>
2628+int Controller::Impl::GetLastIconPriority(std::string const& favorite_uri, bool sticky)
2629+{
2630+ auto const& icons = model_->GetSublist<IconType>();
2631+ int icon_prio = std::numeric_limits<int>::min();
2632+
2633+ AbstractLauncherIcon::Ptr last_icon;
2634+
2635+ // Get the last (non)-sticky icon position (if available)
2636+ for (auto it = icons.rbegin(); it != icons.rend(); ++it)
2637+ {
2638+ auto const& icon = *it;
2639+ bool update_last_icon = ((!last_icon && !sticky) || sticky);
2640+
2641+ if (update_last_icon || icon->IsSticky() == sticky)
2642+ {
2643+ last_icon = icon;
2644+
2645+ if (icon->IsSticky() == sticky)
2646+ break;
2647+ }
2648+ }
2649+
2650+ if (last_icon)
2651+ {
2652+ icon_prio = last_icon->SortPriority();
2653+
2654+ if (sticky && last_icon->IsSticky() != sticky)
2655+ icon_prio -= 1;
2656+ }
2657+ else if (!favorite_uri.empty())
2658+ {
2659+ // If we have no applications opened, we must guess it position by favorites
2660+ for (auto const& fav : FavoriteStore::Instance().GetFavorites())
2661+ {
2662+ if (fav == favorite_uri)
2663+ {
2664+ if (icon_prio == std::numeric_limits<int>::min())
2665+ icon_prio = (*model_->begin())->SortPriority() - 1;
2666+
2667+ break;
2668+ }
2669+
2670+ auto const& icon = GetIconByUri(fav);
2671+
2672+ if (icon)
2673+ icon_prio = icon->SortPriority();
2674+ }
2675+ }
2676+
2677+ return icon_prio;
2678+}
2679+
2680 void Controller::Impl::OnViewOpened(BamfMatcher* matcher, BamfView* view)
2681 {
2682 if (!BAMF_IS_APPLICATION(view))
2683@@ -630,35 +723,111 @@
2684 }
2685
2686 AbstractLauncherIcon::Ptr icon(new BamfLauncherIcon(app));
2687- icon->visibility_changed.connect(sigc::mem_fun(this, &Impl::SortAndUpdate));
2688- icon->SetSortPriority(sort_priority_++);
2689- RegisterIcon(icon);
2690- SortAndUpdate();
2691-}
2692-
2693-AbstractLauncherIcon::Ptr Controller::Impl::CreateFavorite(const char* file_path)
2694-{
2695- BamfApplication* app;
2696+ RegisterIcon(icon, GetLastIconPriority<BamfLauncherIcon>(local::RUNNING_APPS_URI));
2697+}
2698+
2699+void Controller::Impl::OnDeviceIconAdded(AbstractLauncherIcon::Ptr icon)
2700+{
2701+ RegisterIcon(icon, GetLastIconPriority<VolumeLauncherIcon>(local::DEVICES_URI));
2702+}
2703+
2704+AbstractLauncherIcon::Ptr Controller::Impl::CreateFavoriteIcon(std::string const& icon_uri)
2705+{
2706 AbstractLauncherIcon::Ptr result;
2707
2708- app = bamf_matcher_get_application_for_desktop_file(matcher_, file_path, true);
2709- if (!app)
2710- return result;
2711-
2712- if (g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen")))
2713- {
2714- bamf_view_set_sticky(BAMF_VIEW(app), true);
2715- return result;
2716- }
2717-
2718- bamf_view_set_sticky(BAMF_VIEW(app), true);
2719- AbstractLauncherIcon::Ptr icon (new BamfLauncherIcon(app));
2720- icon->SetSortPriority(sort_priority_++);
2721- result = icon;
2722+ if (!FavoriteStore::IsValidFavoriteUri(icon_uri))
2723+ {
2724+ LOG_WARNING(logger) << "Ignoring favorite '" << icon_uri << "'.";
2725+ return result;
2726+ }
2727+
2728+ std::string desktop_id;
2729+
2730+ if (icon_uri.find(FavoriteStore::URI_PREFIX_APP) == 0)
2731+ {
2732+ desktop_id = icon_uri.substr(FavoriteStore::URI_PREFIX_APP.size());
2733+ }
2734+ else if (icon_uri.find(FavoriteStore::URI_PREFIX_FILE) == 0)
2735+ {
2736+ desktop_id = icon_uri.substr(FavoriteStore::URI_PREFIX_FILE.size());
2737+ }
2738+
2739+ if (!desktop_id.empty())
2740+ {
2741+ BamfApplication* app;
2742+ std::string const& desktop_path = DesktopUtilities::GetDesktopPathById(desktop_id);
2743+
2744+ app = bamf_matcher_get_application_for_desktop_file(matcher_, desktop_path.c_str(), true);
2745+
2746+ if (!app)
2747+ return result;
2748+
2749+ if (g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen")))
2750+ {
2751+ bamf_view_set_sticky(BAMF_VIEW(app), true);
2752+ return result;
2753+ }
2754+
2755+ result = AbstractLauncherIcon::Ptr(new BamfLauncherIcon(app));
2756+ }
2757+ else if (icon_uri.find(FavoriteStore::URI_PREFIX_DEVICE) == 0)
2758+ {
2759+ auto const& devices = device_section_.GetIcons();
2760+ auto const& icon = std::find_if(devices.begin(), devices.end(),
2761+ [&icon_uri](AbstractLauncherIcon::Ptr const& i) { return (i->RemoteUri() == icon_uri); });
2762+
2763+ if (icon == devices.end())
2764+ {
2765+ // Using an idle to remove the favorite, not to erase while iterating
2766+ sources_.AddIdle([this, icon_uri] {
2767+ FavoriteStore::Instance().RemoveFavorite(icon_uri);
2768+ return false;
2769+ });
2770+
2771+ return result;
2772+ }
2773+
2774+ result = *icon;
2775+ }
2776+ else if (desktop_icon_->RemoteUri() == icon_uri)
2777+ {
2778+ result = desktop_icon_;
2779+ }
2780+ else if (expo_icon_->RemoteUri() == icon_uri)
2781+ {
2782+ result = expo_icon_;
2783+ }
2784+
2785+ if (result)
2786+ {
2787+ if (!result->IsSticky())
2788+ result->Stick(false);
2789+ else
2790+ {
2791+ LOG_ERROR(logger) << "Ignoring favorite '" << icon_uri << "': it's already on the launcher!";
2792+ result = nullptr;
2793+ }
2794+ }
2795
2796 return result;
2797 }
2798
2799+AbstractLauncherIcon::Ptr Controller::Impl::GetIconByUri(std::string const& icon_uri)
2800+{
2801+ if (icon_uri.empty())
2802+ return AbstractLauncherIcon::Ptr();
2803+
2804+ auto const& icon = std::find_if(model_->begin(), model_->end(),
2805+ [&icon_uri](AbstractLauncherIcon::Ptr const& i) { return (i->RemoteUri() == icon_uri); });
2806+
2807+ if (icon != model_->end())
2808+ {
2809+ return *icon;
2810+ }
2811+
2812+ return AbstractLauncherIcon::Ptr();
2813+}
2814+
2815 SoftwareCenterLauncherIcon::Ptr Controller::Impl::CreateSCLauncherIcon(std::string const& file_path,
2816 std::string const& aptdaemon_trans_id,
2817 std::string const& icon_path)
2818@@ -678,50 +847,79 @@
2819
2820 bamf_view_set_sticky(BAMF_VIEW(app), true);
2821 result = new SoftwareCenterLauncherIcon(app, aptdaemon_trans_id, icon_path);
2822- result->SetSortPriority(sort_priority_++);
2823
2824 return result;
2825 }
2826
2827-void Controller::Impl::SetupBamf()
2828-{
2829- GList* apps, *l;
2830- BamfApplication* app;
2831-
2832- FavoriteList const& favs = FavoriteStore::Instance().GetFavorites();
2833-
2834- for (FavoriteList::const_iterator i = favs.begin(), end = favs.end();
2835- i != end; ++i)
2836- {
2837- AbstractLauncherIcon::Ptr fav = CreateFavorite(i->c_str());
2838-
2839- if (fav)
2840- {
2841- fav->SetSortPriority(sort_priority_++);
2842- RegisterIcon(fav);
2843- }
2844- }
2845-
2846- apps = bamf_matcher_get_applications(matcher_);
2847+void Controller::Impl::AddRunningApps()
2848+{
2849+ std::shared_ptr<GList> apps(bamf_matcher_get_applications(matcher_), g_list_free);
2850+
2851+ for (GList *l = apps.get(); l; l = l->next)
2852+ {
2853+ if (!BAMF_IS_APPLICATION(l->data))
2854+ continue;
2855+
2856+ BamfApplication* app = BAMF_APPLICATION(l->data);
2857+
2858+ if (g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen")))
2859+ continue;
2860+
2861+ AbstractLauncherIcon::Ptr icon(new BamfLauncherIcon(app));
2862+ RegisterIcon(icon, ++sort_priority_);
2863+ }
2864+}
2865+
2866+void Controller::Impl::AddDevices()
2867+{
2868+ auto& fav_store = FavoriteStore::Instance();
2869+ for (auto const& icon : device_section_.GetIcons())
2870+ {
2871+ if (!icon->IsSticky() && !fav_store.IsFavorite(icon->RemoteUri()))
2872+ RegisterIcon(icon, ++sort_priority_);
2873+ }
2874+}
2875+
2876+void Controller::Impl::SetupIcons()
2877+{
2878+ auto& favorite_store = FavoriteStore::Instance();
2879+ FavoriteList const& favs = favorite_store.GetFavorites();
2880+ bool running_apps_added = false;
2881+ bool devices_added = false;
2882+
2883+ for (auto const& fav_uri : favs)
2884+ {
2885+ if (fav_uri == local::RUNNING_APPS_URI)
2886+ {
2887+ AddRunningApps();
2888+ running_apps_added = true;
2889+ continue;
2890+ }
2891+ else if (fav_uri == local::DEVICES_URI)
2892+ {
2893+ AddDevices();
2894+ devices_added = true;
2895+ continue;
2896+ }
2897+
2898+ RegisterIcon(CreateFavoriteIcon(fav_uri), ++sort_priority_);
2899+ }
2900+
2901+ if (!running_apps_added)
2902+ AddRunningApps();
2903+
2904+ if (!devices_added)
2905+ AddDevices();
2906+
2907 view_opened_signal_.Connect(matcher_, "view-opened", sigc::mem_fun(this, &Impl::OnViewOpened));
2908-
2909- for (l = apps; l; l = l->next)
2910- {
2911- app = BAMF_APPLICATION(l->data);
2912-
2913- if (g_object_get_qdata(G_OBJECT(app), g_quark_from_static_string("unity-seen")))
2914- continue;
2915-
2916- AbstractLauncherIcon::Ptr icon(new BamfLauncherIcon(app));
2917- icon->SetSortPriority(sort_priority_++);
2918- RegisterIcon(icon);
2919- }
2920- g_list_free(apps);
2921- SortAndUpdate();
2922+ device_section_.icon_added.connect(sigc::mem_fun(this, &Impl::OnDeviceIconAdded));
2923+ favorite_store.favorite_added.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreFavoriteAdded));
2924+ favorite_store.favorite_removed.connect(sigc::mem_fun(this, &Impl::OnFavoriteStoreFavoriteRemoved));
2925+ favorite_store.reordered.connect(sigc::mem_fun(this, &Impl::ResetIconPriorities));
2926
2927 model_->order_changed.connect(sigc::mem_fun(this, &Impl::SortAndUpdate));
2928 model_->icon_removed.connect(sigc::mem_fun(this, &Impl::OnIconRemoved));
2929- model_->saved.connect(sigc::mem_fun(this, &Impl::Save));
2930+ model_->saved.connect(sigc::mem_fun(this, &Impl::SaveIconsOrder));
2931 }
2932
2933 void Controller::Impl::SendHomeActivationRequest()
2934@@ -729,10 +927,10 @@
2935 ubus.SendMessage(UBUS_PLACE_ENTRY_ACTIVATE_REQUEST, g_variant_new("(sus)", "home.lens", dash::NOT_HANDLED, ""));
2936 }
2937
2938-Controller::Controller(Display* display)
2939+Controller::Controller()
2940 : options(Options::Ptr(new Options()))
2941 , multiple_launchers(true)
2942- , pimpl(new Impl(display, this))
2943+ , pimpl(new Impl(this))
2944 {
2945 multiple_launchers.changed.connect([&](bool value) -> void {
2946 UScreen* uscreen = UScreen::GetDefault();
2947@@ -814,19 +1012,6 @@
2948 pimpl->launcher_->GetParent()->PushToFront();
2949 }
2950
2951-void Controller::SetShowDesktopIcon(bool show_desktop_icon)
2952-{
2953- if (pimpl->show_desktop_icon_ == show_desktop_icon)
2954- return;
2955-
2956- pimpl->show_desktop_icon_ = show_desktop_icon;
2957-
2958- if (pimpl->show_desktop_icon_)
2959- pimpl->InsertDesktopIcon();
2960- else
2961- pimpl->RemoveDesktopIcon();
2962-}
2963-
2964 int Controller::Impl::MonitorWithMouse()
2965 {
2966 UScreen* uscreen = UScreen::GetDefault();
2967@@ -1110,7 +1295,7 @@
2968 timespec current;
2969 clock_gettime(CLOCK_MONOTONIC, &current);
2970
2971- unity::variant::BuilderWrapper(builder)
2972+ variant::BuilderWrapper(builder)
2973 .add("key_nav_is_active", KeyNavIsActive())
2974 .add("key_nav_launcher_monitor", pimpl->keyboard_launcher_.IsValid() ? pimpl->keyboard_launcher_->monitor : -1)
2975 .add("key_nav_selection", pimpl->model_->SelectionIndex())
2976
2977=== modified file 'launcher/LauncherController.h'
2978--- launcher/LauncherController.h 2012-08-11 09:16:21 +0000
2979+++ launcher/LauncherController.h 2012-09-18 15:52:46 +0000
2980@@ -47,7 +47,7 @@
2981 nux::Property<Options::Ptr> options;
2982 nux::Property<bool> multiple_launchers;
2983
2984- Controller(Display* display);
2985+ Controller();
2986 ~Controller();
2987
2988 Launcher& launcher() const;
2989@@ -61,8 +61,6 @@
2990
2991 void PushToFront();
2992
2993- void SetShowDesktopIcon(bool show_desktop_icon);
2994-
2995 bool AboutToShowDash(int was_tap, int when) const;
2996
2997 void HandleLauncherKeyPress(int when);
2998
2999=== modified file 'launcher/LauncherControllerPrivate.h'
3000--- launcher/LauncherControllerPrivate.h 2012-08-17 13:07:53 +0000
3001+++ launcher/LauncherControllerPrivate.h 2012-09-18 15:52:46 +0000
3002@@ -46,59 +46,53 @@
3003 class Controller::Impl
3004 {
3005 public:
3006- Impl(Display* display, Controller* parent);
3007+ Impl(Controller* parent);
3008 ~Impl();
3009
3010 void UpdateNumWorkspaces(int workspaces);
3011
3012 Launcher* CreateLauncher(int monitor);
3013
3014- void Save();
3015+ void SaveIconsOrder();
3016 void SortAndUpdate();
3017
3018 nux::ObjectPtr<Launcher> CurrentLauncher();
3019
3020- void OnIconAdded(AbstractLauncherIcon::Ptr icon);
3021+ template<typename IconType>
3022+ int GetLastIconPriority(std::string const& favorite_uri = "", bool sticky = false);
3023+ void AddFavoriteKeepingOldPosition(FavoriteList& icons, std::string const& icon_uri) const;
3024+
3025 void OnIconRemoved(AbstractLauncherIcon::Ptr icon);
3026+ void OnDeviceIconAdded(AbstractLauncherIcon::Ptr icon);
3027
3028- void OnLauncherAddRequest(char* path, AbstractLauncherIcon::Ptr before);
3029+ void OnLauncherAddRequest(std::string const& icon_uri, AbstractLauncherIcon::Ptr before);
3030 void OnLauncherAddRequestSpecial(std::string const& path, std::string const& aptdaemon_trans_id,
3031 std::string const& icon_path, int icon_x, int icon_y, int icon_size);
3032 void OnLauncherRemoveRequest(AbstractLauncherIcon::Ptr icon);
3033- void OnSCIconAnimationComplete(AbstractLauncherIcon::Ptr icon);
3034
3035 void OnLauncherEntryRemoteAdded(LauncherEntryRemote::Ptr const& entry);
3036 void OnLauncherEntryRemoteRemoved(LauncherEntryRemote::Ptr const& entry);
3037
3038 void OnFavoriteStoreFavoriteAdded(std::string const& entry, std::string const& pos, bool before);
3039 void OnFavoriteStoreFavoriteRemoved(std::string const& entry);
3040- void OnFavoriteStoreReordered();
3041-
3042-
3043- void InsertExpoAction();
3044- void RemoveExpoAction();
3045-
3046- void InsertDesktopIcon();
3047- void RemoveDesktopIcon();
3048+ void ResetIconPriorities();
3049
3050 void SendHomeActivationRequest();
3051
3052 int MonitorWithMouse();
3053
3054- void InsertTrash();
3055-
3056- void RegisterIcon(AbstractLauncherIcon::Ptr icon);
3057-
3058- AbstractLauncherIcon::Ptr CreateFavorite(const char* file_path);
3059-
3060+ void RegisterIcon(AbstractLauncherIcon::Ptr icon, int priority = std::numeric_limits<int>::min());
3061+
3062+ AbstractLauncherIcon::Ptr CreateFavoriteIcon(std::string const& icon_uri);
3063+ AbstractLauncherIcon::Ptr GetIconByUri(std::string const& icon_uri);
3064 SoftwareCenterLauncherIcon::Ptr CreateSCLauncherIcon(std::string const& file_path, std::string const& aptdaemon_trans_id, std::string const& icon_path);
3065
3066- void SetupBamf();
3067+ void SetupIcons();
3068+ void AddRunningApps();
3069+ void AddDevices();
3070
3071 void EnsureLaunchers(int primary, std::vector<nux::Geometry> const& monitors);
3072
3073- void OnExpoActivated();
3074-
3075 void OnScreenChanged(int primary_monitor, std::vector<nux::Geometry>& monitors);
3076
3077 void OnWindowFocusChanged (guint32 xid);
3078@@ -123,38 +117,31 @@
3079
3080 Controller* parent_;
3081 LauncherModel::Ptr model_;
3082+ glib::Object<BamfMatcher> matcher_;
3083 nux::ObjectPtr<Launcher> launcher_;
3084 nux::ObjectPtr<Launcher> keyboard_launcher_;
3085- int sort_priority_;
3086- AbstractVolumeMonitorWrapper::Ptr volume_monitor_;
3087- DevicesSettingsImp::Ptr devices_settings_;
3088 DeviceLauncherSection device_section_;
3089 LauncherEntryRemoteModel remote_model_;
3090 AbstractLauncherIcon::Ptr expo_icon_;
3091 AbstractLauncherIcon::Ptr desktop_icon_;
3092- int num_workspaces_;
3093- bool show_desktop_icon_;
3094- Display* display_;
3095-
3096- bool launcher_open;
3097- bool launcher_keynav;
3098- bool launcher_grabbed;
3099- bool reactivate_keynav;
3100- int reactivate_index;
3101- bool keynav_restore_window_;
3102- int launcher_key_press_time_;
3103- unsigned int dbus_owner_;
3104-
3105 ui::EdgeBarrierController edge_barriers_;
3106-
3107 LauncherList launchers;
3108
3109- glib::Object<BamfMatcher> matcher_;
3110+ unsigned sort_priority_;
3111+ bool launcher_open;
3112+ bool launcher_keynav;
3113+ bool launcher_grabbed;
3114+ bool reactivate_keynav;
3115+ int reactivate_index;
3116+ bool keynav_restore_window_;
3117+ int launcher_key_press_time_;
3118+ unsigned dbus_owner_;
3119+
3120+
3121 glib::Signal<void, BamfMatcher*, BamfView*> view_opened_signal_;
3122 glib::SourceManager sources_;
3123 UBusManager ubus;
3124
3125- sigc::connection on_expoicon_activate_connection_;
3126 sigc::connection launcher_key_press_connection_;
3127 sigc::connection launcher_event_outside_connection_;
3128 };
3129
3130=== modified file 'launcher/LauncherIcon.cpp'
3131--- launcher/LauncherIcon.cpp 2012-08-15 02:51:33 +0000
3132+++ launcher/LauncherIcon.cpp 2012-09-18 15:52:46 +0000
3133@@ -74,10 +74,11 @@
3134
3135 LauncherIcon::LauncherIcon(IconType type)
3136 : _icon_type(type)
3137+ , _sticky(false)
3138 , _remote_urgent(false)
3139 , _present_urgency(0)
3140 , _progress(0)
3141- , _sort_priority(0)
3142+ , _sort_priority(DefaultPriority(type))
3143 , _last_monitor(0)
3144 , _background_color(nux::color::White)
3145 , _glow_color(nux::color::White)
3146@@ -89,7 +90,7 @@
3147 , _saved_center(max_num_monitors)
3148 , _allow_quicklist_to_show(true)
3149 {
3150- for (unsigned i = 0; i < unsigned(Quirk::LAST); i++)
3151+ for (unsigned i = 0; i < unsigned(Quirk::LAST); ++i)
3152 {
3153 _quirks[i] = false;
3154 _quirk_times[i].tv_sec = 0;
3155@@ -107,10 +108,10 @@
3156 tooltip_text.SetSetterFunction(sigc::mem_fun(this, &LauncherIcon::SetTooltipText));
3157 tooltip_text = "blank";
3158
3159+ position = Position::FLOATING;
3160+
3161 // FIXME: the abstraction is already broken, should be fixed for O
3162 // right now, hooking the dynamic quicklist the less ugly possible way
3163-
3164-
3165 mouse_enter.connect(sigc::mem_fun(this, &LauncherIcon::RecvMouseEnter));
3166 mouse_leave.connect(sigc::mem_fun(this, &LauncherIcon::RecvMouseLeave));
3167 mouse_down.connect(sigc::mem_fun(this, &LauncherIcon::RecvMouseDown));
3168@@ -517,6 +518,7 @@
3169
3170 if (!_tooltip)
3171 LoadTooltip();
3172+ _tooltip->SetText(tooltip_text());
3173 _tooltip->ShowTooltipWithTipAt(tip_x, tip_y);
3174 _tooltip->ShowWindow(!tooltip_text().empty());
3175 tooltip_visible.emit(_tooltip);
3176@@ -1179,6 +1181,31 @@
3177 remove.emit(AbstractLauncherIcon::Ptr(this));
3178 }
3179
3180+void LauncherIcon::Stick(bool save)
3181+{
3182+ if (_sticky)
3183+ return;
3184+
3185+ _sticky = true;
3186+
3187+ if (save)
3188+ position_saved.emit();
3189+
3190+ SetQuirk(Quirk::VISIBLE, true);
3191+}
3192+
3193+void LauncherIcon::UnStick()
3194+{
3195+ if (!_sticky)
3196+ return;
3197+
3198+ _sticky = false;
3199+
3200+ position_forgot.emit();
3201+
3202+ SetQuirk(Quirk::VISIBLE, false);
3203+}
3204+
3205
3206 } // namespace launcher
3207 } // namespace unity
3208
3209=== modified file 'launcher/LauncherIcon.h'
3210--- launcher/LauncherIcon.h 2012-08-15 02:51:33 +0000
3211+++ launcher/LauncherIcon.h 2012-09-18 15:52:46 +0000
3212@@ -108,11 +108,6 @@
3213
3214 const bool WindowVisibleOnViewport();
3215
3216- virtual bool IsSpacer()
3217- {
3218- return false;
3219- };
3220-
3221 float PresentUrgency();
3222
3223 float GetProgress();
3224@@ -188,9 +183,9 @@
3225
3226 virtual std::string DesktopFile() { return std::string(""); }
3227
3228- virtual bool IsSticky() const { return false; }
3229+ virtual bool IsSticky() const { return _sticky; }
3230
3231- virtual bool IsVisible() const { return false; }
3232+ virtual bool IsVisible() const { return GetQuirk(Quirk::VISIBLE); }
3233
3234 virtual bool IsVisibleOnMonitor(int monitor) const;
3235
3236@@ -198,9 +193,9 @@
3237
3238 virtual void AboutToRemove() {}
3239
3240- virtual void Stick(bool save = true) {}
3241+ virtual void Stick(bool save = true);
3242
3243- virtual void UnStick() {}
3244+ virtual void UnStick();
3245
3246 protected:
3247 std::vector<nux::Point3> GetCenters();
3248@@ -313,6 +308,7 @@
3249
3250 void OnTooltipEnabledChanged(bool value);
3251
3252+ bool _sticky;
3253 bool _remote_urgent;
3254 float _present_urgency;
3255 float _progress;
3256
3257=== modified file 'launcher/LauncherModel.cpp'
3258--- launcher/LauncherModel.cpp 2012-09-04 15:51:31 +0000
3259+++ launcher/LauncherModel.cpp 2012-09-18 15:52:46 +0000
3260@@ -56,14 +56,14 @@
3261
3262 bool LauncherModel::IconShouldShelf(AbstractLauncherIcon::Ptr const& icon) const
3263 {
3264- return icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH;
3265+ return icon->position() == AbstractLauncherIcon::Position::END;
3266 }
3267
3268 bool LauncherModel::CompareIcons(AbstractLauncherIcon::Ptr const& first, AbstractLauncherIcon::Ptr const& second)
3269 {
3270- if (first->GetIconType() < second->GetIconType())
3271+ if (first->position() < second->position())
3272 return true;
3273- else if (first->GetIconType() > second->GetIconType())
3274+ else if (first->position() > second->position())
3275 return false;
3276
3277 return first->SortPriority() < second->SortPriority();
3278@@ -163,25 +163,11 @@
3279 if (!icon)
3280 return false;
3281
3282- const_iterator it;
3283- const_iterator end;
3284-
3285- if (IconShouldShelf(icon))
3286- {
3287- it = _inner_shelf.begin();
3288- end = _inner_shelf.end();
3289- }
3290- else
3291- {
3292- it = _inner_main.begin();
3293- end = _inner_main.end();
3294- }
3295-
3296- for (; it != end; ++it)
3297- {
3298- AbstractLauncherIcon::Ptr const& iter_icon = *it;
3299-
3300- if (iter_icon != icon && iter_icon->GetIconType() == icon->GetIconType())
3301+ auto const& container = IconShouldShelf(icon) ? _inner_shelf : _inner_main;
3302+
3303+ for (auto const& icon_it : container)
3304+ {
3305+ if (icon_it != icon && icon_it->GetIconType() == icon->GetIconType())
3306 return true;
3307 }
3308
3309@@ -193,16 +179,20 @@
3310 if (icon == other || icon.IsNull() || other.IsNull())
3311 return;
3312
3313- if (icon->GetIconType() != other->GetIconType())
3314+ if (icon->position() != other->position())
3315 return;
3316
3317 icon->SetSortPriority(other->SortPriority() + 1);
3318
3319 for (auto it = std::next(std::find(begin(), end(), other)); it != end(); ++it)
3320 {
3321+ auto const& icon_it = *it;
3322+
3323+ if (icon_it == icon)
3324+ continue;
3325+
3326 // Increasing the priority of the icons next to the other one
3327- auto const& icon_it = *it;
3328- int new_priority = icon_it->SortPriority() + 1;
3329+ int new_priority = icon_it->SortPriority() + 2;
3330 icon_it->SetSortPriority(new_priority);
3331 }
3332
3333@@ -214,7 +204,7 @@
3334 if (icon == other || icon.IsNull() || other.IsNull())
3335 return;
3336
3337- if (icon->GetIconType() != other->GetIconType())
3338+ if (icon->position() != other->position())
3339 return;
3340
3341 bool found_target = false;
3342@@ -228,7 +218,13 @@
3343 continue;
3344 }
3345
3346- int new_priority = icon_it->SortPriority() + (found_target ? 1 : -1);
3347+ int old_priority = icon_it->SortPriority();
3348+ int new_priority = old_priority + (found_target ? 1 : -1);
3349+
3350+ // We need to reduce the priority of all the icons previous to 'other'
3351+ if (icon_it != other && !found_target && other->SortPriority() == old_priority)
3352+ new_priority -= 1;
3353+
3354 icon_it->SetSortPriority(new_priority);
3355
3356 if (icon_it == other)
3357@@ -237,7 +233,7 @@
3358 icon_it->SaveCenter();
3359
3360 center = !center;
3361- new_priority = new_priority - 1;
3362+ new_priority += -1;
3363 icon->SetSortPriority(new_priority);
3364
3365 if (animate && center)
3366@@ -260,7 +256,7 @@
3367 if (icon == other || icon.IsNull() || other.IsNull())
3368 return;
3369
3370- if (icon->GetIconType() != other->GetIconType())
3371+ if (icon->position() != other->position())
3372 return;
3373
3374 bool found_icon = false;
3375@@ -276,7 +272,13 @@
3376 continue;
3377 }
3378
3379- int new_priority = icon_it->SortPriority() + (found_target ? 1 : -1);
3380+ int old_priority = icon_it->SortPriority();
3381+ int new_priority = old_priority + (found_target ? 1 : -1);
3382+
3383+ // We need to reduce the priority of all the icons previous to 'other'
3384+ if (icon_it != other && !found_target && other->SortPriority() == old_priority)
3385+ new_priority -= 1;
3386+
3387 icon_it->SetSortPriority(new_priority);
3388
3389 if (icon_it == other)
3390@@ -285,7 +287,7 @@
3391 icon_it->SaveCenter();
3392
3393 center = !center;
3394- new_priority = new_priority + (found_icon ? 1 : -1);
3395+ new_priority += found_icon ? 1 : -1;
3396 icon->SetSortPriority(new_priority);
3397
3398 if (animate && center)
3399@@ -377,7 +379,7 @@
3400
3401 for (auto const& current : _inner)
3402 {
3403- if (current->GetIconType() != icon->GetIconType())
3404+ if (current->position() != icon->position())
3405 continue;
3406
3407 if (!found_target)
3408
3409=== modified file 'launcher/MockLauncherIcon.h'
3410--- launcher/MockLauncherIcon.h 2012-09-04 14:13:16 +0000
3411+++ launcher/MockLauncherIcon.h 2012-09-18 15:52:46 +0000
3412@@ -45,20 +45,20 @@
3413 NUX_DECLARE_OBJECT_TYPE(MockLauncherIcon, AbstractLauncherIcon);
3414 public:
3415 MockLauncherIcon(IconType type = IconType::APPLICATION)
3416- : type_(type)
3417- , sort_priority_(0)
3418- , icon_(0)
3419+ : icon_(0)
3420+ , type_(type)
3421+ , sort_priority_(DefaultPriority(type))
3422+ , remote_uri_("fake")
3423 {
3424 tooltip_text = "Mock Icon";
3425+ position = Position::FLOATING;
3426
3427 for (unsigned i = 0; i < unsigned(Quirk::LAST); ++i)
3428- {
3429 quirks_[i] = false;
3430- }
3431 }
3432
3433 std::string GetName() const { return "MockLauncherIcon"; }
3434-
3435+
3436 void AddProperties(GVariantBuilder* builder) {}
3437
3438 void HideTooltip() {}
3439@@ -180,11 +180,6 @@
3440 return true;
3441 }
3442
3443- bool IsSpacer()
3444- {
3445- return false;
3446- }
3447-
3448 float PresentUrgency()
3449 {
3450 return 0.0f;
3451@@ -244,7 +239,7 @@
3452
3453 std::string RemoteUri()
3454 {
3455- return "fake";
3456+ return remote_uri_;
3457 }
3458
3459 nux::BaseTexture* TextureForSize(int size)
3460@@ -293,9 +288,9 @@
3461 bool IsVisible() const { return false; }
3462
3463 void AboutToRemove() {}
3464-
3465+
3466 void Stick(bool save = true) {}
3467-
3468+
3469 void UnStick() {}
3470
3471 private:
3472@@ -346,12 +341,13 @@
3473 return result;
3474 }
3475
3476+ nux::BaseTexture* icon_;
3477 IconType type_;
3478 int sort_priority_;
3479- nux::BaseTexture* icon_;
3480 bool quirks_[unsigned(Quirk::LAST)];
3481 timespec quirk_times_[unsigned(Quirk::LAST)];
3482 std::map<int, nux::Point3> center_;
3483+ std::string remote_uri_;
3484 };
3485
3486 }
3487
3488=== modified file 'launcher/SoftwareCenterLauncherIcon.cpp'
3489--- launcher/SoftwareCenterLauncherIcon.cpp 2012-08-02 13:16:06 +0000
3490+++ launcher/SoftwareCenterLauncherIcon.cpp 2012-09-18 15:52:46 +0000
3491@@ -45,23 +45,19 @@
3492 , needs_urgent_(false)
3493 , aptdaemon_trans_id_(aptdaemon_trans_id)
3494 {
3495-
3496+ SetQuirk(Quirk::VISIBLE, false);
3497 aptdaemon_trans_.Connect("PropertyChanged", sigc::mem_fun(this, &SoftwareCenterLauncherIcon::OnPropertyChanged));
3498 aptdaemon_trans_.Connect("Finished", sigc::mem_fun(this, &SoftwareCenterLauncherIcon::OnFinished));
3499
3500- icon_name = icon_path;
3501+ if (!icon_path.empty())
3502+ icon_name = icon_path;
3503+
3504 if (!aptdaemon_trans_id_.empty()) // Application is being installed, or hasn't been installed yet
3505 tooltip_text = _("Waiting to install");
3506 }
3507
3508-void SoftwareCenterLauncherIcon::Animate(nux::ObjectPtr<Launcher> launcher,
3509- int icon_x,
3510- int icon_y,
3511- int icon_size)
3512+void SoftwareCenterLauncherIcon::Animate(nux::ObjectPtr<Launcher> const& launcher, int start_x, int start_y)
3513 {
3514- int target_x = 0;
3515- int target_y = 0;
3516-
3517 launcher_ = launcher;
3518
3519 icon_texture_ = nux::GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableDeviceTexture(
3520@@ -72,30 +68,15 @@
3521
3522 drag_window_ = new LauncherDragWindow(icon_texture_);
3523
3524+ launcher->ForceReveal(true);
3525 launcher->RenderIconToTexture(nux::GetWindowThread()->GetGraphicsEngine(),
3526 AbstractLauncherIcon::Ptr(this),
3527 icon_texture_);
3528
3529- drag_window_->SetBaseXY(icon_x, icon_y);
3530+ auto const& icon_center = GetCenter(launcher->monitor());
3531+ drag_window_->SetBaseXY(start_x, start_y);
3532 drag_window_->ShowWindow(true);
3533-
3534- // Find out the center of last BamfLauncherIcon with non-zero co-ordinates
3535- auto bamf_icons = launcher->GetModel()->GetSublist<BamfLauncherIcon>();
3536- //TODO: don't iterate through them and pick the last one, just use back() to get the last one.
3537- for (auto current_bamf_icon : bamf_icons)
3538- {
3539- auto icon_center = current_bamf_icon->GetCenter(launcher->monitor);
3540-
3541- if (icon_center.x != 0 && icon_center.y != 0)
3542- {
3543- target_x = icon_center.x;
3544- target_y = icon_center.y;
3545- }
3546- }
3547-
3548- target_y = target_y + (launcher->GetIconSize() / 2);
3549- drag_window_->SetAnimationTarget(target_x, target_y);
3550-
3551+ drag_window_->SetAnimationTarget(icon_center.x, icon_center.y + (launcher->GetIconSize() / 2));
3552 drag_window_->on_anim_completed = drag_window_->anim_completed.connect(sigc::mem_fun(this, &SoftwareCenterLauncherIcon::OnDragAnimationFinished));
3553 drag_window_->StartAnimation();
3554 }
3555@@ -103,23 +84,29 @@
3556 void SoftwareCenterLauncherIcon::OnDragAnimationFinished()
3557 {
3558 drag_window_->ShowWindow(false);
3559- launcher_->icon_animation_complete.emit(AbstractLauncherIcon::Ptr(this));
3560 drag_window_ = nullptr;
3561+ launcher_->ForceReveal(false);
3562+ launcher_ = nullptr;
3563+ icon_texture_ = nullptr;
3564+ SetQuirk(Quirk::VISIBLE, true);
3565 }
3566
3567 void SoftwareCenterLauncherIcon::ActivateLauncherIcon(ActionArg arg)
3568 {
3569 if (finished_)
3570 {
3571- if (needs_urgent_)
3572- {
3573- SetQuirk(Quirk::URGENT, false);
3574- needs_urgent_ = false;
3575- }
3576- BamfLauncherIcon::ActivateLauncherIcon(arg);
3577+ if (needs_urgent_)
3578+ {
3579+ SetQuirk(Quirk::URGENT, false);
3580+ needs_urgent_ = false;
3581+ }
3582+
3583+ BamfLauncherIcon::ActivateLauncherIcon(arg);
3584 }
3585 else
3586- SetQuirk(Quirk::STARTING, false);
3587+ {
3588+ SetQuirk(Quirk::STARTING, false);
3589+ }
3590 }
3591
3592 void SoftwareCenterLauncherIcon::OnFinished(GVariant *params)
3593@@ -135,7 +122,9 @@
3594 SetProgress(0.0f);
3595 finished_ = true;
3596 needs_urgent_ = true;
3597- } else {
3598+ }
3599+ else
3600+ {
3601 // failure condition, remove icon again
3602 UnStick();
3603 }
3604@@ -167,7 +156,7 @@
3605
3606 std::string SoftwareCenterLauncherIcon::GetName() const
3607 {
3608- return "SoftwareCenterLauncherIcon";
3609+ return "SoftwareCenterLauncherIcon";
3610 }
3611
3612 }
3613
3614=== modified file 'launcher/SoftwareCenterLauncherIcon.h'
3615--- launcher/SoftwareCenterLauncherIcon.h 2012-07-25 03:11:05 +0000
3616+++ launcher/SoftwareCenterLauncherIcon.h 2012-09-18 15:52:46 +0000
3617@@ -42,7 +42,7 @@
3618 std::string const& aptdaemon_trans_id,
3619 std::string const& icon_path);
3620
3621- void Animate(nux::ObjectPtr<Launcher> launcher, int icon_x, int icon_y, int icon_size);
3622+ void Animate(nux::ObjectPtr<Launcher> const& launcher, int start_x, int start_y);
3623
3624 std::string GetName() const;
3625
3626
3627=== modified file 'launcher/SpacerLauncherIcon.cpp'
3628--- launcher/SpacerLauncherIcon.cpp 2012-08-02 13:16:06 +0000
3629+++ launcher/SpacerLauncherIcon.cpp 2012-09-18 15:52:46 +0000
3630@@ -28,7 +28,7 @@
3631 {
3632
3633 SpacerLauncherIcon::SpacerLauncherIcon(int monitor)
3634- : SingleMonitorLauncherIcon(IconType::APPLICATION, monitor)
3635+ : SingleMonitorLauncherIcon(IconType::SPACER, monitor)
3636 {
3637 SetQuirk(Quirk::VISIBLE, true);
3638 SetQuirk(Quirk::RUNNING, false);
3639
3640=== modified file 'launcher/SpacerLauncherIcon.h'
3641--- launcher/SpacerLauncherIcon.h 2012-05-07 19:52:54 +0000
3642+++ launcher/SpacerLauncherIcon.h 2012-09-18 15:52:46 +0000
3643@@ -32,10 +32,6 @@
3644 public:
3645 SpacerLauncherIcon(int monitor);
3646
3647- bool IsSpacer()
3648- {
3649- return true;
3650- }
3651 protected:
3652 std::string GetName() const;
3653 };
3654
3655=== modified file 'launcher/StandaloneLauncher.cpp'
3656--- launcher/StandaloneLauncher.cpp 2012-08-15 02:51:33 +0000
3657+++ launcher/StandaloneLauncher.cpp 2012-09-18 15:52:46 +0000
3658@@ -45,7 +45,7 @@
3659 void ThreadWidgetInit(nux::NThread* thread, void* InitData)
3660 {
3661 // launcherWindow->SetGeometry (nux::Geometry(0, 0, 300, 800));
3662- controller.reset(new launcher::Controller(0));
3663+ controller.reset(new launcher::Controller());
3664 }
3665
3666 int main(int argc, char** argv)
3667
3668=== modified file 'launcher/TrashLauncherIcon.cpp'
3669--- launcher/TrashLauncherIcon.cpp 2012-09-07 09:19:33 +0000
3670+++ launcher/TrashLauncherIcon.cpp 2012-09-18 15:52:46 +0000
3671@@ -48,6 +48,7 @@
3672 {
3673 tooltip_text = _("Trash");
3674 icon_name = "user-trash";
3675+ position = Position::END;
3676 SetQuirk(Quirk::VISIBLE, true);
3677 SetQuirk(Quirk::RUNNING, false);
3678 SetShortcut('t');
3679
3680=== modified file 'launcher/VolumeLauncherIcon.cpp'
3681--- launcher/VolumeLauncherIcon.cpp 2012-08-28 17:42:25 +0000
3682+++ launcher/VolumeLauncherIcon.cpp 2012-09-18 15:52:46 +0000
3683@@ -26,6 +26,7 @@
3684 #include "DevicesSettings.h"
3685 #include "Volume.h"
3686 #include "VolumeLauncherIcon.h"
3687+#include "FavoriteStore.h"
3688
3689 namespace unity
3690 {
3691@@ -36,7 +37,7 @@
3692
3693 nux::logging::Logger logger("unity.launcher");
3694
3695-const unsigned int volume_changed_timeout = 500;
3696+const unsigned int volume_changed_timeout = 500;
3697
3698 }
3699
3700@@ -61,7 +62,7 @@
3701 }
3702
3703 ~Impl()
3704- {
3705+ {
3706 volume_changed_conn_.disconnect();
3707 volume_removed_conn_.disconnect();
3708 settings_changed_conn_.disconnect();
3709@@ -83,7 +84,7 @@
3710
3711 void UpdateKeepInLauncher()
3712 {
3713- auto identifier = volume_->GetIdentifier();
3714+ auto const& identifier = volume_->GetIdentifier();
3715 keep_in_launcher_ = !devices_settings_->IsABlacklistedDevice(identifier);
3716 }
3717
3718@@ -104,6 +105,7 @@
3719 if (devices_settings_->IsABlacklistedDevice(volume_->GetIdentifier()))
3720 devices_settings_->TryToUnblacklist(volume_->GetIdentifier());
3721
3722+ parent_->UnStick();
3723 parent_->Remove();
3724 }
3725
3726@@ -163,7 +165,8 @@
3727 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
3728
3729 gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
3730- auto identifier = volume_->GetIdentifier();
3731+ auto const& identifier = volume_->GetIdentifier();
3732+ parent_->UnStick();
3733 devices_settings_->TryToBlacklist(identifier);
3734 }));
3735
3736@@ -239,6 +242,16 @@
3737 menu.push_back(menu_item);
3738 }
3739
3740+ std::string GetRemoteUri()
3741+ {
3742+ auto const& identifier = volume_->GetIdentifier();
3743+
3744+ if (identifier.empty())
3745+ return "";
3746+
3747+ return FavoriteStore::URI_PREFIX_DEVICE + identifier;
3748+ }
3749+
3750 VolumeLauncherIcon* parent_;
3751 bool keep_in_launcher_;
3752 Volume::Ptr volume_;
3753@@ -293,6 +306,23 @@
3754 return pimpl_->GetMenus();
3755 }
3756
3757+std::string VolumeLauncherIcon::GetRemoteUri()
3758+{
3759+ return pimpl_->GetRemoteUri();
3760+}
3761+
3762+void VolumeLauncherIcon::Stick(bool save)
3763+{
3764+ SimpleLauncherIcon::Stick(save);
3765+ pimpl_->devices_settings_->TryToUnblacklist(pimpl_->volume_->GetIdentifier());
3766+}
3767+
3768+void VolumeLauncherIcon::UnStick()
3769+{
3770+ SimpleLauncherIcon::UnStick();
3771+ SetQuirk(Quirk::VISIBLE, true);
3772+}
3773+
3774 //
3775 // Introspection
3776 //
3777
3778=== modified file 'launcher/VolumeLauncherIcon.h'
3779--- launcher/VolumeLauncherIcon.h 2012-08-28 17:28:02 +0000
3780+++ launcher/VolumeLauncherIcon.h 2012-09-18 15:52:46 +0000
3781@@ -43,7 +43,10 @@
3782 void EjectAndShowNotification(); // TODO: rename to private virtual void DoDropToTrash();
3783 bool CanStop() const;
3784 void StopDrive();
3785+ void Stick(bool save = true);
3786+ void UnStick();
3787 MenuItemsVector GetMenus();
3788+ std::string GetRemoteUri();
3789
3790 protected:
3791 virtual void ActivateLauncherIcon(ActionArg arg);
3792
3793=== modified file 'manual-tests/Launcher.txt'
3794--- manual-tests/Launcher.txt 2012-09-17 12:16:31 +0000
3795+++ manual-tests/Launcher.txt 2012-09-18 15:52:46 +0000
3796@@ -191,6 +191,21 @@
3797 it, and the any pips for running apps show again.
3798
3799
3800+Dragging fixed icons does not reorder an icon above or below
3801+------------------------------------------------------------
3802+This test is about not reordering when dragging fixed icons.
3803+
3804+#. Move the mouse so it is over the BFB launcher icon
3805+#. Press and hold the mouse button
3806+#. Try to drag the icon to the right of the launcher.
3807+#. Move the mouse down at least to the height of the second launcher icon
3808+ keeping the mouse pressed.
3809+#. Release
3810+
3811+Outcome:
3812+ * No icon should be dragged.
3813+
3814+
3815 Dragged launcher icons out of the launcher are properly drawn
3816 -------------------------------------------------------------
3817 This test ensures that the launcher icons out of the launcher are properly drawn
3818
3819=== modified file 'panel/PanelMenuView.h'
3820--- panel/PanelMenuView.h 2012-08-22 04:30:28 +0000
3821+++ panel/PanelMenuView.h 2012-09-18 15:52:46 +0000
3822@@ -136,7 +136,6 @@
3823 glib::Object<BamfMatcher> _matcher;
3824
3825 nux::TextureLayer* _title_layer;
3826- nux::HLayout* _menu_layout;
3827 nux::ObjectPtr<WindowButtons> _window_buttons;
3828 nux::ObjectPtr<PanelTitlebarGrabArea> _titlebar_grab_area;
3829 nux::ObjectPtr<nux::BaseTexture> _title_texture;
3830
3831=== modified file 'plugins/unityshell/src/unityshell.cpp'
3832--- plugins/unityshell/src/unityshell.cpp 2012-09-17 10:20:33 +0000
3833+++ plugins/unityshell/src/unityshell.cpp 2012-09-18 15:52:46 +0000
3834@@ -266,7 +266,6 @@
3835 optionSetAutohideAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
3836 optionSetDashBlurExperimentalNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
3837 optionSetShortcutOverlayNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
3838- optionSetShowDesktopIconNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
3839 optionSetShowLauncherInitiate(boost::bind(&UnityScreen::showLauncherKeyInitiate, this, _1, _2, _3));
3840 optionSetShowLauncherTerminate(boost::bind(&UnityScreen::showLauncherKeyTerminate, this, _1, _2, _3));
3841 optionSetKeyboardFocusInitiate(boost::bind(&UnityScreen::setKeyboardFocusKeyInitiate, this, _1, _2, _3));
3842@@ -2842,9 +2841,6 @@
3843 enable_shortcut_overlay_ = optionGetShortcutOverlay();
3844 shortcut_controller_->SetEnabled(enable_shortcut_overlay_);
3845 break;
3846- case UnityshellOptions::ShowDesktopIcon:
3847- launcher_controller_->SetShowDesktopIcon(optionGetShowDesktopIcon());
3848- break;
3849 case UnityshellOptions::DecayRate:
3850 launcher_options->edge_decay_rate = optionGetDecayRate() * 100;
3851 break;
3852@@ -2917,11 +2913,13 @@
3853 CompOption::Value& v)
3854 {
3855 bool status = screen->setOptionForPlugin(plugin, name, v);
3856+
3857 if (status)
3858 {
3859- if (strcmp(plugin, "core") == 0 && strcmp(name, "hsize") == 0)
3860+ if (strcmp(plugin, "core") == 0)
3861 {
3862- launcher_controller_->UpdateNumWorkspaces(screen->vpSize().width() * screen->vpSize().height());
3863+ if (strcmp(name, "hsize") == 0 || strcmp(name, "vsize") == 0)
3864+ launcher_controller_->UpdateNumWorkspaces(screen->vpSize().width() * screen->vpSize().height());
3865 }
3866 }
3867 return status;
3868@@ -2952,7 +2950,7 @@
3869 void UnityScreen::initLauncher()
3870 {
3871 Timer timer;
3872- launcher_controller_ = std::make_shared<launcher::Controller>(screen->dpy());
3873+ launcher_controller_ = std::make_shared<launcher::Controller>();
3874 AddChild(launcher_controller_.get());
3875
3876 switcher_controller_ = std::make_shared<switcher::Controller>();
3877
3878=== modified file 'plugins/unityshell/unityshell.xml.in'
3879--- plugins/unityshell/unityshell.xml.in 2012-08-17 14:44:05 +0000
3880+++ plugins/unityshell/unityshell.xml.in 2012-09-18 15:52:46 +0000
3881@@ -400,12 +400,6 @@
3882 <default>true</default>
3883 </option>
3884
3885- <option name="show_desktop_icon" type="bool">
3886- <_short>Show "Desktop Icon" in the launcher</_short>
3887- <_long>Enable/Disable "Show Desktop Icon" in the launcher.</_long>
3888- <default>false</default>
3889- </option>
3890-
3891 <option name="menus_fadein" type="int">
3892 <_short>Menus Fade-in duration</_short>
3893 <_long>Duration (in milliseconds) of the menus fade-in animation, used when the mouse goes over the top-panel.</_long>
3894
3895=== modified file 'tests/CMakeLists.txt'
3896--- tests/CMakeLists.txt 2012-09-13 14:41:57 +0000
3897+++ tests/CMakeLists.txt 2012-09-18 15:52:46 +0000
3898@@ -3,16 +3,16 @@
3899 #
3900 # Data
3901 #
3902-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/ubuntuone-installer.desktop
3903- ${CMAKE_BINARY_DIR}/tests/data/ubuntuone-installer.desktop)
3904-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/ubuntu-software-center.desktop
3905- ${CMAKE_BINARY_DIR}/tests/data/ubuntu-software-center.desktop)
3906-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/update-manager.desktop
3907- ${CMAKE_BINARY_DIR}/tests/data/update-manager.desktop)
3908-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/bzr-handle-patch.desktop
3909- ${CMAKE_BINARY_DIR}/tests/data/bzr-handle-patch.desktop)
3910-configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/no-icon.desktop
3911- ${CMAKE_BINARY_DIR}/tests/data/no-icon.desktop)
3912+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/applications/ubuntuone-installer.desktop
3913+ ${CMAKE_BINARY_DIR}/tests/data/applications/ubuntuone-installer.desktop)
3914+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/applications/ubuntu-software-center.desktop
3915+ ${CMAKE_BINARY_DIR}/tests/data/applications/ubuntu-software-center.desktop)
3916+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/applications/update-manager.desktop
3917+ ${CMAKE_BINARY_DIR}/tests/data/applications/update-manager.desktop)
3918+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/applications/bzr-handle-patch.desktop
3919+ ${CMAKE_BINARY_DIR}/tests/data/applications/bzr-handle-patch.desktop)
3920+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/data/applications/no-icon.desktop
3921+ ${CMAKE_BINARY_DIR}/tests/data/applications/no-icon.desktop)
3922 #
3923 # Unit tests
3924 #
3925@@ -136,6 +136,7 @@
3926 test_indicator_entry.cpp
3927 test_indicators.cpp
3928 test_introspection.cpp
3929+ test_favorite_store.cpp
3930 test_favorite_store_gsettings.cpp
3931 test_favorite_store_private.cpp
3932 test_home_lens.cpp
3933@@ -200,20 +201,23 @@
3934 # Tests that require X
3935 add_executable(test-gtest
3936 test_main.cpp
3937- test_bamflaunchericon.cpp
3938+ test_bamf_launcher_icon.cpp
3939 test_bfb_launcher_icon.cpp
3940 test_dashview_impl.cpp
3941+ test_desktop_launcher_icon.cpp
3942 test_edge_barrier_controller.cpp
3943 test_launcher.cpp
3944 test_device_launcher_section.cpp
3945 test_lensview_impl.cpp
3946 test_hud_button.cpp
3947 test_hud_controller.cpp
3948+ test_hud_launcher_icon.cpp
3949 test_hud_view.cpp
3950 test_icon_loader.cpp
3951 test_im_text_entry.cpp
3952 test_launcher_controller.cpp
3953 test_launcher_drag_window.cpp
3954+ test_launcher_icon.cpp
3955 test_keyboard_util.cpp
3956 test_panel_style.cpp
3957 test_previews_application.cpp
3958@@ -225,10 +229,13 @@
3959 test_quicklist_view.cpp
3960 test_resultviewgrid.cpp
3961 test_single_monitor_launcher_icon.cpp
3962+ test_software_center_launcher_icon.cpp
3963+ test_expo_launcher_icon.cpp
3964 test_switcher_controller.cpp
3965 test_switcher_model.cpp
3966 test_texture_cache.cpp
3967 test_thumbnail_generator.cpp
3968+ test_trash_launcher_icon.cpp
3969 test_launcher_minimize_speed.cpp
3970 test_volume_imp.cpp
3971 test_volume_launcher_icon.cpp
3972@@ -272,6 +279,7 @@
3973 ${CMAKE_SOURCE_DIR}/launcher/DevicesSettingsImp.cpp
3974 ${CMAKE_SOURCE_DIR}/launcher/DndData.cpp
3975 ${CMAKE_SOURCE_DIR}/launcher/EdgeBarrierController.cpp
3976+ ${CMAKE_SOURCE_DIR}/launcher/ExpoLauncherIcon.cpp
3977 ${CMAKE_SOURCE_DIR}/launcher/FavoriteStore.cpp
3978 ${CMAKE_SOURCE_DIR}/launcher/FavoriteStoreGSettings.cpp
3979 ${CMAKE_SOURCE_DIR}/launcher/FavoriteStorePrivate.cpp
3980
3981=== added directory 'tests/data/applications'
3982=== renamed file 'tests/data/bzr-handle-patch.desktop' => 'tests/data/applications/bzr-handle-patch.desktop'
3983=== renamed file 'tests/data/no-icon.desktop' => 'tests/data/applications/no-icon.desktop'
3984=== renamed file 'tests/data/ubuntu-software-center.desktop' => 'tests/data/applications/ubuntu-software-center.desktop'
3985=== renamed file 'tests/data/ubuntuone-installer.desktop' => 'tests/data/applications/ubuntuone-installer.desktop'
3986=== renamed file 'tests/data/update-manager.desktop' => 'tests/data/applications/update-manager.desktop'
3987=== modified file 'tests/gmockvolume.c'
3988--- tests/gmockvolume.c 2012-09-18 11:09:48 +0000
3989+++ tests/gmockvolume.c 2012-09-18 15:52:46 +0000
3990@@ -89,10 +89,11 @@
3991 static void
3992 g_mock_volume_init (GMockVolume *mock_volume)
3993 {
3994- mock_volume->name = g_strdup("");
3995+ guint32 uuid = g_random_int();
3996+ mock_volume->name = g_strdup_printf("MockVolume %u", uuid);
3997 mock_volume->icon = g_icon_new_for_string("", NULL);
3998- mock_volume->uuid = g_strdup("");
3999- mock_volume->label = g_strdup("");
4000+ mock_volume->uuid = g_strdup_printf("%u", uuid);
4001+ mock_volume->label = g_strdup_printf("MockVolumeLabel");
4002 mock_volume->mount = NULL;
4003 }
4004
4005
4006=== renamed file 'tests/test_bamflaunchericon.cpp' => 'tests/test_bamf_launcher_icon.cpp'
4007--- tests/test_bamflaunchericon.cpp 2012-07-16 20:05:59 +0000
4008+++ tests/test_bamf_launcher_icon.cpp 2012-09-18 15:52:46 +0000
4009@@ -23,16 +23,19 @@
4010 #include <gmock/gmock.h>
4011
4012 #include <UnityCore/GLibWrapper.h>
4013+#include <UnityCore/DesktopUtilities.h>
4014
4015 #include "BamfLauncherIcon.h"
4016+#include "FavoriteStore.h"
4017
4018 using namespace unity;
4019+using namespace unity::launcher;
4020
4021 namespace
4022 {
4023
4024-const std::string USC_DESKTOP = BUILDDIR"/tests/data/ubuntu-software-center.desktop";
4025-const std::string NO_ICON_DESKTOP = BUILDDIR"/tests/data/no-icon.desktop";
4026+const std::string USC_DESKTOP = BUILDDIR"/tests/data/applications/ubuntu-software-center.desktop";
4027+const std::string NO_ICON_DESKTOP = BUILDDIR"/tests/data/applications/no-icon.desktop";
4028
4029 class TestBamfLauncherIcon : public testing::Test
4030 {
4031@@ -61,6 +64,11 @@
4032 nux::ObjectPtr<launcher::BamfLauncherIcon> empty_app;
4033 };
4034
4035+TEST_F(TestBamfLauncherIcon, Position)
4036+{
4037+ EXPECT_EQ(usc_icon->position(), AbstractLauncherIcon::Position::FLOATING);
4038+}
4039+
4040 TEST_F(TestBamfLauncherIcon, TestCustomBackgroundColor)
4041 {
4042 nux::Color const& color = usc_icon->BackgroundColor();
4043@@ -78,4 +86,64 @@
4044 EXPECT_EQ(empty_app->icon_name.Get(), "application-default-icon");
4045 }
4046
4047+TEST_F(TestBamfLauncherIcon, Stick)
4048+{
4049+ BamfView* bamf_app = BAMF_VIEW(bamf_matcher_get_application_for_desktop_file(bamf_matcher, USC_DESKTOP.c_str(), FALSE));
4050+ ASSERT_FALSE(bamf_view_is_sticky(bamf_app));
4051+
4052+ bool saved = false;
4053+ usc_icon->position_saved.connect([&saved] {saved = true;});
4054+
4055+ usc_icon->Stick(false);
4056+ EXPECT_TRUE(bamf_view_is_sticky(bamf_app));
4057+ EXPECT_TRUE(usc_icon->IsSticky());
4058+ EXPECT_TRUE(usc_icon->IsVisible());
4059+ EXPECT_FALSE(saved);
4060+
4061+ usc_icon->Stick(true);
4062+ EXPECT_FALSE(saved);
4063+ bamf_view_set_sticky(bamf_app, FALSE);
4064+}
4065+
4066+TEST_F(TestBamfLauncherIcon, StickAndSave)
4067+{
4068+ BamfView* bamf_app = BAMF_VIEW(bamf_matcher_get_application_for_desktop_file(bamf_matcher, USC_DESKTOP.c_str(), FALSE));
4069+ ASSERT_FALSE(bamf_view_is_sticky(bamf_app));
4070+
4071+ bool saved = false;
4072+ usc_icon->position_saved.connect([&saved] {saved = true;});
4073+
4074+ usc_icon->Stick(true);
4075+ EXPECT_TRUE(bamf_view_is_sticky(bamf_app));
4076+ EXPECT_TRUE(usc_icon->IsSticky());
4077+ EXPECT_TRUE(usc_icon->IsVisible());
4078+ EXPECT_TRUE(saved);
4079+ bamf_view_set_sticky(bamf_app, FALSE);
4080+}
4081+
4082+TEST_F(TestBamfLauncherIcon, Unstick)
4083+{
4084+ BamfView* bamf_app = BAMF_VIEW(bamf_matcher_get_application_for_desktop_file(bamf_matcher, USC_DESKTOP.c_str(), FALSE));
4085+ ASSERT_FALSE(bamf_view_is_sticky(bamf_app));
4086+
4087+ bool forgot = false;
4088+ usc_icon->position_forgot.connect([&forgot] {forgot = true;});
4089+
4090+ usc_icon->Stick(false);
4091+ ASSERT_TRUE(bamf_view_is_sticky(bamf_app));
4092+ ASSERT_TRUE(usc_icon->IsSticky());
4093+
4094+ usc_icon->UnStick();
4095+ EXPECT_FALSE(bamf_view_is_sticky(bamf_app));
4096+ EXPECT_FALSE(usc_icon->IsSticky());
4097+ EXPECT_FALSE(usc_icon->IsVisible());
4098+ EXPECT_TRUE(forgot);
4099+}
4100+
4101+TEST_F(TestBamfLauncherIcon, RemoteUri)
4102+{
4103+ EXPECT_EQ(usc_icon->RemoteUri(), FavoriteStore::URI_PREFIX_APP + DesktopUtilities::GetDesktopID(USC_DESKTOP));
4104+ EXPECT_TRUE(empty_app->RemoteUri().empty());
4105+}
4106+
4107 }
4108
4109=== modified file 'tests/test_bfb_launcher_icon.cpp'
4110--- tests/test_bfb_launcher_icon.cpp 2012-08-14 15:13:19 +0000
4111+++ tests/test_bfb_launcher_icon.cpp 2012-09-18 15:52:46 +0000
4112@@ -33,18 +33,21 @@
4113 MockBFBLauncherIcon()
4114 : BFBLauncherIcon(LauncherHideMode::LAUNCHER_HIDE_NEVER)
4115 {}
4116-
4117- AbstractLauncherIcon::MenuItemsVector GetMenus()
4118- {
4119- return BFBLauncherIcon::GetMenus();
4120- }
4121 };
4122
4123-TEST(TestBFBLauncherIcon, OverlayMenus)
4124+struct TestBFBLauncherIcon : testing::Test
4125 {
4126 MockBFBLauncherIcon bfb;
4127-
4128- for (auto menu_item : bfb.GetMenus())
4129+};
4130+
4131+TEST_F(TestBFBLauncherIcon, Position)
4132+{
4133+ EXPECT_EQ(bfb.position, AbstractLauncherIcon::Position::BEGIN);
4134+}
4135+
4136+TEST_F(TestBFBLauncherIcon, OverlayMenus)
4137+{
4138+ for (auto menu_item : bfb.Menus())
4139 {
4140 bool overlay_item = dbusmenu_menuitem_property_get_bool(menu_item, QuicklistMenuItem::OVERLAY_MENU_ITEM_PROPERTY);
4141 ASSERT_TRUE(overlay_item);
4142
4143=== added file 'tests/test_desktop_launcher_icon.cpp'
4144--- tests/test_desktop_launcher_icon.cpp 1970-01-01 00:00:00 +0000
4145+++ tests/test_desktop_launcher_icon.cpp 2012-09-18 15:52:46 +0000
4146@@ -0,0 +1,80 @@
4147+/*
4148+ * Copyright 2012 Canonical Ltd.
4149+ *
4150+ * This program is free software: you can redistribute it and/or modify it
4151+ * under the terms of the GNU General Public License version 3, as published
4152+ * by the Free Software Foundation.
4153+ *
4154+ * This program is distributed in the hope that it will be useful, but
4155+ * WITHOUT ANY WARRANTY; without even the implied warranties of
4156+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
4157+ * PURPOSE. See the GNU General Public License for more details.
4158+ *
4159+ * You should have received a copy of the GNU General Public License
4160+ * version 3 along with this program. If not, see
4161+ * <http://www.gnu.org/licenses/>
4162+ *
4163+ * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
4164+ */
4165+
4166+#include <gmock/gmock.h>
4167+
4168+#include "PluginAdapter.h"
4169+#include "DesktopLauncherIcon.h"
4170+
4171+using namespace unity;
4172+using namespace unity::launcher;
4173+
4174+namespace
4175+{
4176+
4177+struct TestDesktopLauncherIcon : testing::Test
4178+{
4179+ DesktopLauncherIcon icon;
4180+};
4181+
4182+TEST_F(TestDesktopLauncherIcon, Type)
4183+{
4184+ EXPECT_EQ(icon.GetIconType(), AbstractLauncherIcon::IconType::DESKTOP);
4185+}
4186+
4187+TEST_F(TestDesktopLauncherIcon, Shortcut)
4188+{
4189+ EXPECT_EQ(icon.GetShortcut(), 'd');
4190+}
4191+
4192+TEST_F(TestDesktopLauncherIcon, Position)
4193+{
4194+ EXPECT_EQ(icon.position(), AbstractLauncherIcon::Position::FLOATING);
4195+}
4196+
4197+TEST_F(TestDesktopLauncherIcon, ActivateToggleShowDesktop)
4198+{
4199+ auto plugin_adapter = PluginAdapter::Default();
4200+
4201+ ASSERT_FALSE(plugin_adapter->InShowDesktop());
4202+
4203+ icon.Activate(ActionArg());
4204+ ASSERT_TRUE(plugin_adapter->InShowDesktop());
4205+
4206+ icon.Activate(ActionArg());
4207+ EXPECT_FALSE(plugin_adapter->InShowDesktop());
4208+}
4209+
4210+TEST_F(TestDesktopLauncherIcon, ShowInSwitcher)
4211+{
4212+ EXPECT_TRUE(icon.ShowInSwitcher(false));
4213+ EXPECT_TRUE(icon.ShowInSwitcher(true));
4214+
4215+ icon.SetShowInSwitcher(false);
4216+
4217+ EXPECT_FALSE(icon.ShowInSwitcher(false));
4218+ EXPECT_FALSE(icon.ShowInSwitcher(true));
4219+}
4220+
4221+TEST_F(TestDesktopLauncherIcon, RemoteUri)
4222+{
4223+ EXPECT_EQ(icon.RemoteUri(), "unity://desktop-icon");
4224+}
4225+
4226+}
4227
4228=== modified file 'tests/test_desktop_utilities.cpp'
4229--- tests/test_desktop_utilities.cpp 2012-06-01 09:33:15 +0000
4230+++ tests/test_desktop_utilities.cpp 2012-09-18 15:52:46 +0000
4231@@ -30,7 +30,9 @@
4232 using testing::Eq;
4233
4234 namespace {
4235-
4236+
4237+const std::string LOCAL_DATA_DIR = BUILDDIR"/tests/data";
4238+
4239 TEST(TestDesktopUtilitiesDesktopID, TestEmptyValues)
4240 {
4241 std::vector<std::string> empty_list;
4242@@ -88,71 +90,99 @@
4243 Eq("subdir-to.desktop"));
4244 EXPECT_THAT(DesktopUtilities::GetDesktopID(dirs, "/this/path/applications/subdir1/subdir2/to.desktop"),
4245 Eq("subdir1-subdir2-to.desktop"));
4246+ EXPECT_THAT(DesktopUtilities::GetDesktopID(dirs, "/this/path/applications/subdir1/subdir2-to.desktop"),
4247+ Eq("subdir1-subdir2-to.desktop"));
4248 }
4249
4250 TEST(TestDesktopUtilitiesDataDirectories, TestGetUserDataDirectory)
4251 {
4252- const gchar* old_home = g_getenv("XDG_DATA_HOME");
4253+ const gchar* env = g_getenv("XDG_DATA_HOME");
4254+ std::string old_home = env ? env : "";
4255+
4256 g_setenv("XDG_DATA_HOME", "UnityUserConfig", TRUE);
4257
4258 std::string const& user_data_dir = DesktopUtilities::GetUserDataDirectory();
4259
4260- g_setenv("XDG_DATA_HOME", old_home, TRUE);
4261+ g_setenv("XDG_DATA_HOME", old_home.c_str(), TRUE);
4262
4263 EXPECT_THAT(user_data_dir, Eq("UnityUserConfig"));
4264 }
4265
4266 TEST(TestDesktopUtilitiesDataDirectories, TestGetSystemDataDirectory)
4267 {
4268- const gchar* old_dirs = g_getenv("XDG_DATA_DIRS");
4269- g_setenv("XDG_DATA_DIRS", "dir1:dir2::dir3:dir4", TRUE);
4270+ const gchar* env = g_getenv("XDG_DATA_DIRS");
4271+ std::string old_dirs = env ? env : "";
4272+ g_setenv("XDG_DATA_DIRS", ("dir1:dir2::dir3:dir4:"+LOCAL_DATA_DIR).c_str(), TRUE);
4273
4274 std::vector<std::string> const& system_dirs = DesktopUtilities::GetSystemDataDirectories();
4275
4276- g_setenv("XDG_DATA_DIRS", old_dirs, TRUE);
4277+ g_setenv("XDG_DATA_DIRS", old_dirs.c_str(), TRUE);
4278
4279- ASSERT_THAT(system_dirs.size(), Eq(4));
4280+ ASSERT_THAT(system_dirs.size(), Eq(5));
4281 EXPECT_THAT(system_dirs[0], Eq("dir1"));
4282 EXPECT_THAT(system_dirs[1], Eq("dir2"));
4283 EXPECT_THAT(system_dirs[2], Eq("dir3"));
4284 EXPECT_THAT(system_dirs[3], Eq("dir4"));
4285+ EXPECT_THAT(system_dirs[4], Eq(LOCAL_DATA_DIR));
4286 }
4287
4288 TEST(TestDesktopUtilitiesDataDirectories, TestGetDataDirectory)
4289 {
4290- const gchar* old_dirs = g_getenv("XDG_DATA_DIRS");
4291- g_setenv("XDG_DATA_DIRS", "dir1:dir2::dir3:dir4", TRUE);
4292- const gchar* old_home = g_getenv("XDG_DATA_HOME");
4293+ const gchar* env = g_getenv("XDG_DATA_DIRS");
4294+ std::string old_dirs = env ? env : "";
4295+ env = g_getenv("XDG_DATA_HOME");
4296+ std::string old_home = env ? env : "";
4297+
4298+ g_setenv("XDG_DATA_DIRS", ("dir1:dir2::dir3:dir4:"+LOCAL_DATA_DIR).c_str(), TRUE);
4299 g_setenv("XDG_DATA_HOME", "UnityUserConfig", TRUE);
4300
4301 std::vector<std::string> const& data_dirs = DesktopUtilities::GetDataDirectories();
4302
4303- g_setenv("XDG_DATA_DIRS", old_dirs, TRUE);
4304- g_setenv("XDG_DATA_HOME", old_home, TRUE);
4305+ g_setenv("XDG_DATA_DIRS", old_dirs.c_str(), TRUE);
4306+ g_setenv("XDG_DATA_HOME", old_home.c_str(), TRUE);
4307
4308- ASSERT_THAT(data_dirs.size(), Eq(5));
4309+ ASSERT_THAT(data_dirs.size(), Eq(6));
4310 EXPECT_THAT(data_dirs[0], Eq("dir1"));
4311 EXPECT_THAT(data_dirs[1], Eq("dir2"));
4312 EXPECT_THAT(data_dirs[2], Eq("dir3"));
4313 EXPECT_THAT(data_dirs[3], Eq("dir4"));
4314- EXPECT_THAT(data_dirs[4], Eq("UnityUserConfig"));
4315-}
4316-
4317-TEST(TestDesktopUtilitiesDataDirectories, TestGetBackgroundColor)
4318-{
4319- std::string const& color = DesktopUtilities::GetBackgroundColor(BUILDDIR"/tests/data/ubuntu-software-center.desktop");
4320+ EXPECT_THAT(data_dirs[4], Eq(LOCAL_DATA_DIR));
4321+ EXPECT_THAT(data_dirs[5], Eq("UnityUserConfig"));
4322+}
4323+
4324+TEST(TestDesktopUtilities, TestGetDesktopPathById)
4325+{
4326+ const gchar* env = g_getenv("XDG_DATA_DIRS");
4327+ std::string old_dirs = env ? env : "";
4328+ env = g_getenv("XDG_DATA_HOME");
4329+ std::string old_home = env ? env : "";
4330+
4331+ g_setenv("XDG_DATA_DIRS", LOCAL_DATA_DIR.c_str(), TRUE);
4332+ g_setenv("XDG_DATA_HOME", "UnityUserConfig", TRUE);
4333+
4334+ std::string const& file = DesktopUtilities::GetDesktopPathById("ubuntu-software-center.desktop");
4335+
4336+ g_setenv("XDG_DATA_DIRS", old_dirs.c_str(), TRUE);
4337+ g_setenv("XDG_DATA_HOME", old_dirs.c_str(), TRUE);
4338+
4339+ EXPECT_EQ(file, LOCAL_DATA_DIR + "/applications/ubuntu-software-center.desktop");
4340+}
4341+
4342+TEST(TestDesktopUtilities, TestGetBackgroundColor)
4343+{
4344+ std::string const& color = DesktopUtilities::GetBackgroundColor(LOCAL_DATA_DIR+"/applications/ubuntu-software-center.desktop");
4345
4346 EXPECT_EQ(color, "#aabbcc");
4347 }
4348
4349-TEST(TestDesktopUtilitiesDataDirectories, TestGetBackgroundColorNoKey)
4350+TEST(TestDesktopUtilities, TestGetBackgroundColorNoKey)
4351 {
4352- std::string const& color = DesktopUtilities::GetBackgroundColor(BUILDDIR"/tests/data/update-manager.desktop");
4353+ std::string const& color = DesktopUtilities::GetBackgroundColor(LOCAL_DATA_DIR+"/applications/update-manager.desktop");
4354
4355 EXPECT_TRUE(color.empty());
4356 }
4357
4358-TEST(TestDesktopUtilitiesDataDirectories, TestGetBackgroundColorNoFile)
4359+TEST(TestDesktopUtilities, TestGetBackgroundColorNoFile)
4360 {
4361 std::string const& color = DesktopUtilities::GetBackgroundColor("hello-world.desktop");
4362
4363
4364=== modified file 'tests/test_device_launcher_section.cpp'
4365--- tests/test_device_launcher_section.cpp 2012-08-17 15:53:06 +0000
4366+++ tests/test_device_launcher_section.cpp 2012-09-18 15:52:46 +0000
4367@@ -21,17 +21,16 @@
4368 */
4369
4370 #include <gmock/gmock.h>
4371+
4372+#include "DevicesSettings.h"
4373+#include "test_mock_devices.h"
4374+#include "test_utils.h"
4375+
4376 using namespace testing;
4377-
4378-#include "DeviceLauncherSection.h"
4379-#include "DevicesSettings.h"
4380-#include "AbstractVolumeMonitorWrapper.h"
4381-using namespace unity;
4382 using namespace unity::launcher;
4383
4384-#include "gmockvolume.h"
4385-#include "test_utils.h"
4386-
4387+namespace unity
4388+{
4389 namespace
4390 {
4391
4392@@ -50,72 +49,38 @@
4393 bool icon_added;
4394 };
4395
4396-class MockVolumeMonitorWrapper : public AbstractVolumeMonitorWrapper
4397-{
4398-public:
4399- typedef std::shared_ptr<MockVolumeMonitorWrapper> Ptr;
4400-
4401- MockVolumeMonitorWrapper()
4402- : volume1(G_VOLUME(g_mock_volume_new()))
4403- , volume2(G_VOLUME(g_mock_volume_new()))
4404- {
4405- }
4406-
4407- VolumeList GetVolumes()
4408- {
4409- VolumeList ret;
4410-
4411- ret.push_back(volume1);
4412- ret.push_back(volume2);
4413-
4414- return ret;
4415- }
4416-
4417- glib::Object<GVolume> volume1;
4418- glib::Object<GVolume> volume2;
4419-};
4420-
4421-class MockDevicesSettings : public DevicesSettings
4422-{
4423- MOCK_CONST_METHOD1(IsABlacklistedDevice, bool(std::string const& uuid));
4424- MOCK_METHOD1(TryToBlacklist, void(std::string const& uuid));
4425- MOCK_METHOD1(TryToUnblacklist, void(std::string const& uuid));
4426-};
4427-
4428-class TestDeviceLauncherSection : public Test
4429-{
4430-public:
4431+struct TestDeviceLauncherSection : Test
4432+{
4433 TestDeviceLauncherSection()
4434 : monitor_(new MockVolumeMonitorWrapper)
4435 , devices_settings_(new MockDevicesSettings)
4436 , section_(monitor_, devices_settings_)
4437 {}
4438
4439- void SetUp()
4440- {
4441- // Make sure PopulateEntries is called.
4442- Utils::WaitForTimeoutMSec(1500);
4443- }
4444-
4445 MockVolumeMonitorWrapper::Ptr monitor_;
4446 DevicesSettings::Ptr devices_settings_;
4447 DeviceLauncherSection section_;
4448 };
4449
4450-
4451-TEST_F(TestDeviceLauncherSection, TestNoDuplicates)
4452+TEST_F(TestDeviceLauncherSection, NoDuplicates)
4453 {
4454 std::shared_ptr<EventListener> listener(new EventListener);
4455- section_.IconAdded.connect(sigc::mem_fun(*listener, &EventListener::OnIconAdded));
4456+ section_.icon_added.connect(sigc::mem_fun(*listener, &EventListener::OnIconAdded));
4457
4458 // Emit the signal volume_added for each volume.
4459- monitor_->volume_added.emit(monitor_->volume1);
4460- monitor_->volume_added.emit(monitor_->volume2);
4461+ monitor_->volume_added.emit(*(std::next(monitor_->volumes_.begin(), 0)));
4462+ monitor_->volume_added.emit(*(std::next(monitor_->volumes_.begin(), 1)));
4463
4464 Utils::WaitForTimeoutMSec(500);
4465
4466 EXPECT_EQ(listener->icon_added, false);
4467 }
4468
4469+TEST_F(TestDeviceLauncherSection, GetIcons)
4470+{
4471+ EXPECT_EQ(section_.GetIcons().size(), 2);
4472+}
4473+
4474+}
4475 }
4476
4477
4478=== added file 'tests/test_expo_launcher_icon.cpp'
4479--- tests/test_expo_launcher_icon.cpp 1970-01-01 00:00:00 +0000
4480+++ tests/test_expo_launcher_icon.cpp 2012-09-18 15:52:46 +0000
4481@@ -0,0 +1,58 @@
4482+/*
4483+ * Copyright 2012 Canonical Ltd.
4484+ *
4485+ * This program is free software: you can redistribute it and/or modify it
4486+ * under the terms of the GNU General Public License version 3, as published
4487+ * by the Free Software Foundation.
4488+ *
4489+ * This program is distributed in the hope that it will be useful, but
4490+ * WITHOUT ANY WARRANTY; without even the implied warranties of
4491+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
4492+ * PURPOSE. See the GNU General Public License for more details.
4493+ *
4494+ * You should have received a copy of the GNU General Public License
4495+ * version 3 along with this program. If not, see
4496+ * <http://www.gnu.org/licenses/>
4497+ *
4498+ * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
4499+ */
4500+
4501+#include <gmock/gmock.h>
4502+
4503+#include "ExpoLauncherIcon.h"
4504+#include "PluginAdapter.h"
4505+
4506+using namespace unity;
4507+using namespace unity::launcher;
4508+
4509+namespace
4510+{
4511+struct TestExpoLauncherIcon : testing::Test
4512+{
4513+ ExpoLauncherIcon icon;
4514+};
4515+
4516+TEST_F(TestExpoLauncherIcon, ActivateToggleExpo)
4517+{
4518+ auto plugin_adapter = PluginAdapter::Default();
4519+
4520+ ASSERT_FALSE(plugin_adapter->IsExpoActive());
4521+
4522+ icon.Activate(ActionArg());
4523+ ASSERT_TRUE(plugin_adapter->IsExpoActive());
4524+
4525+ icon.Activate(ActionArg());
4526+ EXPECT_FALSE(plugin_adapter->IsExpoActive());
4527+}
4528+
4529+TEST_F(TestExpoLauncherIcon, Position)
4530+{
4531+ EXPECT_EQ(icon.position(), AbstractLauncherIcon::Position::FLOATING);
4532+}
4533+
4534+TEST_F(TestExpoLauncherIcon, RemoteUri)
4535+{
4536+ EXPECT_EQ(icon.RemoteUri(), "unity://expo-icon");
4537+}
4538+
4539+}
4540
4541=== added file 'tests/test_favorite_store.cpp'
4542--- tests/test_favorite_store.cpp 1970-01-01 00:00:00 +0000
4543+++ tests/test_favorite_store.cpp 2012-09-18 15:52:46 +0000
4544@@ -0,0 +1,111 @@
4545+/*
4546+ * Copyright 2012 Canonical Ltd.
4547+ *
4548+ * This program is free software: you can redistribute it and/or modify it
4549+ * under the terms of the GNU General Public License version 3, as published
4550+ * by the Free Software Foundation.
4551+ *
4552+ * This program is distributed in the hope that it will be useful, but
4553+ * WITHOUT ANY WARRANTY; without even the implied warranties of
4554+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
4555+ * PURPOSE. See the GNU General Public License for more details.
4556+ *
4557+ * You should have received a copy of the GNU General Public License
4558+ * version 3 along with this program. If not, see
4559+ * <http://www.gnu.org/licenses/>
4560+ *
4561+ * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
4562+ */
4563+
4564+#include <gmock/gmock.h>
4565+#include <config.h>
4566+
4567+#include "FavoriteStore.h"
4568+
4569+using namespace unity;
4570+
4571+namespace
4572+{
4573+class MockFavoriteStore : public FavoriteStore
4574+{
4575+public:
4576+ FavoriteList const& GetFavorites() const { return fav_list_; }
4577+ void AddFavorite(std::string const& icon_uri, int position) {}
4578+ void RemoveFavorite(std::string const& icon_uri) {}
4579+ void MoveFavorite(std::string const& icon_uri, int position) {}
4580+ bool IsFavorite(std::string const& icon_uri) const { return false; }
4581+ int FavoritePosition(std::string const& icon_uri) const { return -1; }
4582+ void SetFavorites(FavoriteList const& icon_uris) {}
4583+
4584+ std::string ParseFavoriteFromUri(std::string const& uri) const
4585+ {
4586+ return FavoriteStore::ParseFavoriteFromUri(uri);
4587+ }
4588+
4589+private:
4590+ FavoriteList fav_list_;
4591+};
4592+
4593+struct TestFavoriteStore : public testing::Test
4594+{
4595+ MockFavoriteStore favorite_store;
4596+};
4597+
4598+TEST_F(TestFavoriteStore, Construction)
4599+{
4600+ FavoriteStore& instance = FavoriteStore::Instance();
4601+ EXPECT_EQ(&instance, &favorite_store);
4602+}
4603+
4604+TEST_F(TestFavoriteStore, UriPrefixes)
4605+{
4606+ EXPECT_EQ(FavoriteStore::URI_PREFIX_APP, "application://");
4607+ EXPECT_EQ(FavoriteStore::URI_PREFIX_FILE, "file://");
4608+ EXPECT_EQ(FavoriteStore::URI_PREFIX_DEVICE, "device://");
4609+ EXPECT_EQ(FavoriteStore::URI_PREFIX_UNITY, "unity://");
4610+}
4611+
4612+TEST_F(TestFavoriteStore, IsValidFavoriteUri)
4613+{
4614+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri(""));
4615+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri("invalid-favorite"));
4616+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri("/path/to/desktop_file"));
4617+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri("desktop_file"));
4618+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri("file:///path/to/desktop_file"));
4619+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri("application://desktop_file"));
4620+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri("application://"));
4621+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri("device://"));
4622+ EXPECT_FALSE(FavoriteStore::IsValidFavoriteUri("unity://"));
4623+
4624+ EXPECT_TRUE(FavoriteStore::IsValidFavoriteUri("device://uuid"));
4625+ EXPECT_TRUE(FavoriteStore::IsValidFavoriteUri("file:///path/to/desktop_file.desktop"));
4626+ EXPECT_TRUE(FavoriteStore::IsValidFavoriteUri("application://desktop_file.desktop"));
4627+ EXPECT_TRUE(FavoriteStore::IsValidFavoriteUri("device://a"));
4628+ EXPECT_TRUE(FavoriteStore::IsValidFavoriteUri("unity://b"));
4629+ EXPECT_TRUE(FavoriteStore::IsValidFavoriteUri("application://c.desktop"));
4630+}
4631+
4632+TEST_F(TestFavoriteStore, ParseFavoriteFromUri)
4633+{
4634+ const std::string VALID_DESKTOP_PATH = BUILDDIR"/tests/data/applications/ubuntu-software-center.desktop";
4635+ EXPECT_EQ(favorite_store.ParseFavoriteFromUri("file.desktop"), "application://file.desktop");
4636+ EXPECT_EQ(favorite_store.ParseFavoriteFromUri(VALID_DESKTOP_PATH), "application://"+VALID_DESKTOP_PATH);
4637+
4638+ EXPECT_EQ(favorite_store.ParseFavoriteFromUri("application://file.desktop"), "application://file.desktop");
4639+ EXPECT_EQ(favorite_store.ParseFavoriteFromUri("application://"+VALID_DESKTOP_PATH), "application://"+VALID_DESKTOP_PATH);
4640+ EXPECT_EQ(favorite_store.ParseFavoriteFromUri("file://"+VALID_DESKTOP_PATH), "file://"+VALID_DESKTOP_PATH);
4641+
4642+ EXPECT_EQ(favorite_store.ParseFavoriteFromUri("unity://uri"), "unity://uri");
4643+ EXPECT_EQ(favorite_store.ParseFavoriteFromUri("device://uuid"), "device://uuid");
4644+
4645+ EXPECT_TRUE(favorite_store.ParseFavoriteFromUri("file").empty());
4646+ EXPECT_TRUE(favorite_store.ParseFavoriteFromUri("/path/to/file").empty());
4647+ EXPECT_TRUE(favorite_store.ParseFavoriteFromUri("/path/to/file.desktop").empty());
4648+ EXPECT_TRUE(favorite_store.ParseFavoriteFromUri("application:///path/to/file.desktop").empty());
4649+ EXPECT_TRUE(favorite_store.ParseFavoriteFromUri("file:///path/to/file.desktop").empty());
4650+ EXPECT_TRUE(favorite_store.ParseFavoriteFromUri("file://file.desktop").empty());
4651+ EXPECT_TRUE(favorite_store.ParseFavoriteFromUri("unity://").empty());
4652+ EXPECT_TRUE(favorite_store.ParseFavoriteFromUri("device://").empty());
4653+}
4654+
4655+}
4656
4657=== modified file 'tests/test_favorite_store_gsettings.cpp'
4658--- tests/test_favorite_store_gsettings.cpp 2012-08-02 12:13:38 +0000
4659+++ tests/test_favorite_store_gsettings.cpp 2012-09-18 15:52:46 +0000
4660@@ -21,18 +21,12 @@
4661
4662 #include <config.h>
4663
4664-#include <algorithm>
4665-#include <memory>
4666-#include <string>
4667-
4668-#define G_SETTINGS_ENABLE_BACKEND
4669-#include <gio/gsettingsbackend.h>
4670 #include <gmock/gmock.h>
4671 #include <glib.h>
4672
4673 #include "FavoriteStore.h"
4674 #include "FavoriteStoreGSettings.h"
4675-#include "FavoriteStorePrivate.h"
4676+
4677 #include <UnityCore/GLibWrapper.h>
4678
4679 using namespace unity;
4680@@ -45,14 +39,16 @@
4681 const gchar* SETTINGS_KEY = "favorites";
4682 const gchar* SCHEMA_DIRECTORY = BUILDDIR"/settings";
4683
4684-const char* base_store_favs[] = { BUILDDIR"/tests/data/ubuntuone-installer.desktop",
4685- BUILDDIR"/tests/data/ubuntu-software-center.desktop",
4686- BUILDDIR"/tests/data/update-manager.desktop",
4687+const char* base_store_favs[] = { BUILDDIR"/tests/data/applications/ubuntuone-installer.desktop",
4688+ "file://" BUILDDIR "/tests/data/applications/ubuntu-software-center.desktop",
4689+ "application://" BUILDDIR "/tests/data/applications/update-manager.desktop",
4690+ "unity://test-icon",
4691+ "device://uuid",
4692 NULL
4693 };
4694 const int n_base_store_favs = G_N_ELEMENTS(base_store_favs) - 1; /* NULL */
4695
4696-const std::string other_desktop = BUILDDIR"/tests/data/bzr-handle-patch.desktop";
4697+const std::string other_desktop = "application://" BUILDDIR "/tests/data/applications/bzr-handle-patch.desktop";
4698
4699 // Utilities
4700 std::string const& at(FavoriteList const& favs, int index)
4701@@ -110,9 +106,9 @@
4702 FavoriteList const& favs = settings.GetFavorites();
4703
4704 ASSERT_EQ(favs.size(), n_base_store_favs);
4705- EXPECT_TRUE(ends_with(at(favs, 0), base_store_favs[0]));
4706+ EXPECT_TRUE(ends_with(at(favs, 0), FavoriteStore::URI_PREFIX_APP+base_store_favs[0]));
4707 EXPECT_TRUE(ends_with(at(favs, 1), base_store_favs[1]));
4708- EXPECT_TRUE(at(favs, 2) == base_store_favs[2]);
4709+ EXPECT_EQ(at(favs, 2), base_store_favs[2]);
4710 }
4711
4712 TEST_F(TestFavoriteStoreGSettings, TestAddFavorite)
4713@@ -122,7 +118,7 @@
4714 settings.AddFavorite(other_desktop, 0);
4715 FavoriteList const& favs = settings.GetFavorites();
4716 ASSERT_EQ(favs.size(), n_base_store_favs + 1);
4717- EXPECT_TRUE(other_desktop == at(favs, 0));
4718+ EXPECT_EQ(other_desktop, at(favs, 0));
4719 }
4720
4721 TEST_F(TestFavoriteStoreGSettings, TestAddFavoritePosition)
4722@@ -132,7 +128,7 @@
4723 settings.AddFavorite(other_desktop, 2);
4724 FavoriteList const& favs = settings.GetFavorites();
4725 ASSERT_EQ(favs.size(), n_base_store_favs + 1);
4726- EXPECT_TRUE(other_desktop == at(favs, 2));
4727+ EXPECT_EQ(other_desktop, at(favs, 2));
4728 }
4729
4730 TEST_F(TestFavoriteStoreGSettings,TestAddFavoriteLast)
4731@@ -142,7 +138,7 @@
4732 settings.AddFavorite(other_desktop, -1);
4733 FavoriteList const& favs = settings.GetFavorites();
4734 ASSERT_EQ(favs.size(), n_base_store_favs + 1);
4735- EXPECT_TRUE(other_desktop == favs.back());
4736+ EXPECT_EQ(other_desktop, favs.back());
4737 }
4738
4739 TEST_F(TestFavoriteStoreGSettings,TestAddFavoriteOutOfRange)
4740@@ -178,13 +174,13 @@
4741 FavoriteStore &settings = FavoriteStore::Instance();
4742
4743 FavoriteList const& favs = settings.GetFavorites();
4744- settings.RemoveFavorite("");
4745- EXPECT_EQ(favs.size(), n_base_store_favs);
4746-
4747- settings.RemoveFavorite("foo.desktop");
4748- EXPECT_EQ(favs.size(), n_base_store_favs);
4749-
4750- settings.RemoveFavorite("/this/desktop/doesnt/exist/hopefully.desktop");
4751+ settings.RemoveFavorite(" ");
4752+ EXPECT_EQ(favs.size(), n_base_store_favs);
4753+
4754+ settings.RemoveFavorite("application://foo.desktop");
4755+ EXPECT_EQ(favs.size(), n_base_store_favs);
4756+
4757+ settings.RemoveFavorite("application:///this/desktop/doesnt/exist/hopefully.desktop");
4758 EXPECT_EQ(favs.size(), n_base_store_favs);
4759 }
4760
4761@@ -198,7 +194,7 @@
4762
4763 ASSERT_EQ(favs.size(), n_base_store_favs);
4764 EXPECT_EQ(at(favs, 0), base_store_favs[2]);
4765- EXPECT_TRUE(ends_with(at(favs, 1), base_store_favs[0]));
4766+ EXPECT_TRUE(ends_with(at(favs, 1), FavoriteStore::URI_PREFIX_APP+base_store_favs[0]));
4767 EXPECT_TRUE(ends_with(at(favs, 2), base_store_favs[1]));
4768 }
4769
4770@@ -212,7 +208,7 @@
4771 settings.MoveFavorite(at(favs, 0), 100);
4772
4773 ASSERT_EQ(favs.size(), n_base_store_favs);
4774- EXPECT_TRUE(ends_with(at(favs, 0), base_store_favs[0]));
4775+ EXPECT_TRUE(ends_with(at(favs, 0), FavoriteStore::URI_PREFIX_APP+base_store_favs[0]));
4776 EXPECT_TRUE(ends_with(at(favs, 1), base_store_favs[1]));
4777 EXPECT_EQ(at(favs, 2), base_store_favs[2]);
4778 }
4779@@ -239,7 +235,7 @@
4780 favorite_store->SaveFavorites(favs, false);
4781
4782 ASSERT_TRUE(signal_received);
4783- EXPECT_EQ(position, base_store_favs[0]);
4784+ EXPECT_EQ(position, FavoriteStore::URI_PREFIX_APP+base_store_favs[0]);
4785 EXPECT_TRUE(before);
4786 }
4787
4788@@ -322,12 +318,12 @@
4789 {
4790 FavoriteStore &settings = FavoriteStore::Instance();
4791 bool signal_received = false;
4792- std::string path_removed;
4793+ std::vector<std::string> paths_removed;
4794
4795 settings.favorite_removed.connect([&](std::string const& path)
4796 {
4797 signal_received = true;
4798- path_removed = path;
4799+ paths_removed.push_back(path);
4800 });
4801
4802 FavoriteList favs;
4803@@ -336,7 +332,10 @@
4804 favorite_store->SaveFavorites(favs, false);
4805
4806 ASSERT_TRUE(signal_received);
4807- EXPECT_EQ(path_removed, base_store_favs[1]);
4808+ ASSERT_EQ(paths_removed.size(), 3);
4809+ EXPECT_EQ(paths_removed[0], base_store_favs[4]);
4810+ EXPECT_EQ(paths_removed[1], base_store_favs[1]);
4811+ EXPECT_EQ(paths_removed[2], base_store_favs[3]);
4812 }
4813
4814 TEST_F(TestFavoriteStoreGSettings, TestFavoriteReordered)
4815@@ -464,4 +463,28 @@
4816 EXPECT_TRUE(reordered_received);
4817 }
4818
4819+TEST_F(TestFavoriteStoreGSettings, TestIsFavorite)
4820+{
4821+ EXPECT_TRUE(favorite_store->IsFavorite(FavoriteStore::URI_PREFIX_APP+base_store_favs[0]));
4822+
4823+ for (int i = 1; i < n_base_store_favs; i++)
4824+ {
4825+ ASSERT_TRUE(favorite_store->IsFavorite(base_store_favs[i]));
4826+ }
4827+
4828+ EXPECT_FALSE(favorite_store->IsFavorite("unity://invalid-favorite"));
4829+}
4830+
4831+TEST_F(TestFavoriteStoreGSettings, TestFavoritePosition)
4832+{
4833+ EXPECT_EQ(favorite_store->FavoritePosition(FavoriteStore::URI_PREFIX_APP+base_store_favs[0]), 0);
4834+
4835+ for (int i = 1; i < n_base_store_favs; i++)
4836+ {
4837+ ASSERT_EQ(favorite_store->FavoritePosition(base_store_favs[i]), i);
4838+ }
4839+
4840+ EXPECT_EQ(favorite_store->FavoritePosition("unity://invalid-favorite"), -1);
4841+}
4842+
4843 } // anonymous namespace
4844
4845=== added file 'tests/test_hud_launcher_icon.cpp'
4846--- tests/test_hud_launcher_icon.cpp 1970-01-01 00:00:00 +0000
4847+++ tests/test_hud_launcher_icon.cpp 2012-09-18 15:52:46 +0000
4848@@ -0,0 +1,53 @@
4849+/*
4850+ * Copyright 2012 Canonical Ltd.
4851+ *
4852+ * This program is free software: you can redistribute it and/or modify it
4853+ * under the terms of the GNU General Public License version 3, as published
4854+ * by the Free Software Foundation.
4855+ *
4856+ * This program is distributed in the hope that it will be useful, but
4857+ * WITHOUT ANY WARRANTY; without even the implied warranties of
4858+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
4859+ * PURPOSE. See the GNU General Public License for more details.
4860+ *
4861+ * You should have received a copy of the GNU General Public License
4862+ * version 3 along with this program. If not, see
4863+ * <http://www.gnu.org/licenses/>
4864+ *
4865+ * Authored by: Marco Trevisan (Treviño) <marco.trevisan@canonical.com>
4866+ */
4867+
4868+#include <gmock/gmock.h>
4869+
4870+#include "HudLauncherIcon.h"
4871+
4872+using namespace unity;
4873+using namespace unity::launcher;
4874+
4875+namespace
4876+{
4877+
4878+class MockHudLauncherIcon : public HudLauncherIcon
4879+{
4880+public:
4881+ MockHudLauncherIcon()
4882+ : HudLauncherIcon(LauncherHideMode::LAUNCHER_HIDE_NEVER)
4883+ {}
4884+};
4885+
4886+struct TestHudLauncherIcon : testing::Test
4887+{
4888+ MockHudLauncherIcon hud;
4889+};
4890+
4891+TEST_F(TestHudLauncherIcon, Type)
4892+{
4893+ EXPECT_EQ(hud.GetIconType(), AbstractLauncherIcon::IconType::HUD);
4894+}
4895+
4896+TEST_F(TestHudLauncherIcon, Position)
4897+{
4898+ EXPECT_EQ(hud.position(), AbstractLauncherIcon::Position::BEGIN);
4899+}
4900+
4901+}
4902
4903=== modified file 'tests/test_launcher.cpp'
4904--- tests/test_launcher.cpp 2012-09-04 14:26:23 +0000
4905+++ tests/test_launcher.cpp 2012-09-18 15:52:46 +0000
4906@@ -48,8 +48,12 @@
4907 {
4908 public:
4909 typedef nux::ObjectPtr<MockMockLauncherIcon> Ptr;
4910+ MockMockLauncherIcon(IconType type = IconType::APPLICATION)
4911+ : MockLauncherIcon(type)
4912+ {}
4913
4914 MOCK_METHOD1(ShouldHighlightOnDrag, bool(DndData const&));
4915+ MOCK_METHOD1(Stick, void(bool));
4916 };
4917
4918 }
4919@@ -57,7 +61,7 @@
4920 class TestLauncher : public Test
4921 {
4922 public:
4923- class MockLauncher : public launcher::Launcher
4924+ class MockLauncher : public Launcher
4925 {
4926 public:
4927 MockLauncher(nux::BaseWindow* parent, nux::ObjectPtr<DNDCollectionWindow> const& collection_window)
4928@@ -92,6 +96,11 @@
4929 Launcher::ShowDragWindow();
4930 }
4931
4932+ void EndIconDrag()
4933+ {
4934+ Launcher::EndIconDrag();
4935+ }
4936+
4937 void UpdateDragWindowPosition(int x, int y)
4938 {
4939 Launcher::UpdateDragWindowPosition(x, y);
4940@@ -106,6 +115,55 @@
4941 {
4942 Launcher::ResetMouseDragState();
4943 }
4944+
4945+ bool DndIsSpecialRequest(std::string const& uri) const
4946+ {
4947+ return Launcher::DndIsSpecialRequest(uri);
4948+ }
4949+
4950+ int GetDragIconPosition() const
4951+ {
4952+ return _drag_icon_position;
4953+ }
4954+
4955+ void ProcessDndEnter()
4956+ {
4957+ Launcher::ProcessDndEnter();
4958+ }
4959+
4960+ void ProcessDndLeave()
4961+ {
4962+ Launcher::ProcessDndLeave();
4963+ }
4964+
4965+ void ProcessDndMove(int x, int y, std::list<char*> mimes)
4966+ {
4967+ Launcher::ProcessDndMove(x, y, mimes);
4968+ }
4969+
4970+ void FakeProcessDndMove(int x, int y, std::list<std::string> uris)
4971+ {
4972+ _dnd_data.Reset();
4973+
4974+ std::string data_uri;
4975+ for (std::string const& uri : uris)
4976+ data_uri += uri+"\r\n";
4977+
4978+ _dnd_data.Fill(data_uri.c_str());
4979+
4980+ if (std::find_if(_dnd_data.Uris().begin(), _dnd_data.Uris().end(), [this] (std::string const& uri)
4981+ {return DndIsSpecialRequest(uri);}) != _dnd_data.Uris().end())
4982+ {
4983+ _steal_drag = true;
4984+ }
4985+
4986+ _dnd_hovered_icon = MouseIconIntersection(x, y);
4987+ }
4988+
4989+ void ProcessDndDrop(int x, int y)
4990+ {
4991+ Launcher::ProcessDndDrop(x, y);
4992+ }
4993 };
4994
4995 TestLauncher()
4996@@ -119,6 +177,29 @@
4997 launcher_->SetModel(model_);
4998 }
4999
5000+ std::vector<MockMockLauncherIcon::Ptr> AddMockIcons(unsigned number)
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches