Merge lp:~3v1n0/unity/trash-volumes-illumination into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Brandon Schaefer
Approved revision: no longer in the source branch.
Merged at revision: 3256
Proposed branch: lp:~3v1n0/unity/trash-volumes-illumination
Merge into: lp:unity
Diff against target: 706 lines (+278/-58)
16 files modified
launcher/DeviceLauncherSection.cpp (+1/-1)
launcher/Launcher.cpp (+7/-0)
launcher/TrashLauncherIcon.cpp (+21/-6)
launcher/TrashLauncherIcon.h (+1/-0)
launcher/Volume.h (+2/-0)
launcher/VolumeImp.cpp (+33/-7)
launcher/VolumeImp.h (+1/-0)
launcher/VolumeLauncherIcon.cpp (+2/-2)
tests/test_mock_devices.h (+1/-0)
tests/test_mock_filemanager.h (+4/-1)
tests/test_trash_launcher_icon.cpp (+41/-3)
tests/test_volume_imp.cpp (+33/-9)
tests/test_volume_launcher_icon.cpp (+27/-28)
unity-shared/FileManager.h (+8/-1)
unity-shared/GnomeFileManager.cpp (+86/-0)
unity-shared/GnomeFileManager.h (+10/-0)
To merge this branch: bzr merge lp:~3v1n0/unity/trash-volumes-illumination
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Brandon Schaefer (community) Approve
Review via email: mp+155845@code.launchpad.net

Commit message

{Trash,Volume}Icon: enable running state if the location is opened in the filemanager

Description of the change

GnomeFileManager is now monitoring the nautilus' OpenLocations property and emitting changes when this value is updated.

TrashLauncherIcon and VolumeLauncherIcon checks if their location is opened in the filemanager to toggle the icon illumination.

The pips support is disabled for now since this needs some other nautilus changes (done and pending merge) and a major refactoring for windows handling.

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

Looks good, but what happens when you set the backlight to always on? Possibly make the indicator arrow 1 when its open? Also its no illuminated for me (like what happens when things are urgent), but im not sure if thats what you intended (I don't see it in the code).

review: Needs Information
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

> Looks good, but what happens when you set the backlight to always on? Possibly
> make the indicator arrow 1 when its open?

I thought about that, but it could be confusing since it wouldn't be aware of the window position (monitor or workspace side), so I'd prefer to keep it in this way for now (in the worst case, there's no regression).

However the pips support is something I've alredy been working on and I've opened the bug #1161323 to track it.

> Also its no illuminated for me (like what happens when things are urgent),
> but im not sure if thats what you intended (I don't see it in the code).

This is what I meant by illumination: http://ubuntuone.com/4WdBG8RSg0bbU4f1rHoZee
Per se the trash/device icons would have a white background and I don't think this is what we want to see when they're opened.

Revision history for this message
Brandon Schaefer (brandontschaefer) wrote :

LGTM.

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'launcher/DeviceLauncherSection.cpp'
2--- launcher/DeviceLauncherSection.cpp 2013-03-21 16:22:34 +0000
3+++ launcher/DeviceLauncherSection.cpp 2013-03-28 12:05:12 +0000
4@@ -32,7 +32,7 @@
5 DevicesSettings::Ptr devices_settings)
6 : monitor_(volume_monitor)
7 , devices_settings_(devices_settings)
8- , file_manager_(std::make_shared<GnomeFileManager>())
9+ , file_manager_(GnomeFileManager::Get())
10 , device_notification_display_(std::make_shared<DeviceNotificationDisplayImp>())
11 {
12 monitor_->volume_added.connect(sigc::mem_fun(this, &DeviceLauncherSection::OnVolumeAdded));
13
14=== modified file 'launcher/Launcher.cpp'
15--- launcher/Launcher.cpp 2013-03-19 18:47:01 +0000
16+++ launcher/Launcher.cpp 2013-03-28 12:05:12 +0000
17@@ -851,6 +851,13 @@
18 arg.window_indicators = std::max<int> (icon->WindowsOnViewport().size(), 1);
19 else
20 arg.window_indicators = std::max<int> (icon->WindowsForMonitor(monitor).size(), 1);
21+
22+ if (icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH ||
23+ icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE)
24+ {
25+ // TODO: also these icons should respect the actual windows they have
26+ arg.window_indicators = 0;
27+ }
28 }
29
30 arg.backlight_intensity = IconBackgroundIntensity(icon, current);
31
32=== modified file 'launcher/TrashLauncherIcon.cpp'
33--- launcher/TrashLauncherIcon.cpp 2013-03-21 20:39:55 +0000
34+++ launcher/TrashLauncherIcon.cpp 2013-03-28 12:05:12 +0000
35@@ -23,12 +23,10 @@
36
37 #include "config.h"
38 #include <glib/gi18n-lib.h>
39-#include <Nux/WindowCompositor.h>
40 #include <NuxCore/Logger.h>
41 #include <zeitgeist.h>
42+#include <UnityCore/DesktopUtilities.h>
43
44-#include "Launcher.h"
45-#include "QuicklistManager.h"
46 #include "QuicklistMenuItemLabel.h"
47 #include "unity-shared/GnomeFileManager.h"
48
49@@ -41,17 +39,18 @@
50 {
51 const std::string ZEITGEIST_UNITY_ACTOR = "application://compiz.desktop";
52 const std::string TRASH_URI = "trash:";
53+ const std::string TRASH_PATH = "file://" + DesktopUtilities::GetUserDataDirectory() + "/Trash/files";
54 }
55
56 TrashLauncherIcon::TrashLauncherIcon(FileManager::Ptr const& fmo)
57 : SimpleLauncherIcon(IconType::TRASH)
58- , file_manager_(fmo ? fmo : std::make_shared<GnomeFileManager>())
59+ , file_manager_(fmo ? fmo : GnomeFileManager::Get())
60 {
61 tooltip_text = _("Trash");
62 icon_name = "user-trash";
63 position = Position::END;
64 SetQuirk(Quirk::VISIBLE, true);
65- SetQuirk(Quirk::RUNNING, false);
66+ SetQuirk(Quirk::RUNNING, IsOpened());
67 SetShortcut('t');
68
69 glib::Object<GFile> location(g_file_new_for_uri(TRASH_URI.c_str()));
70@@ -72,6 +71,10 @@
71 });
72 }
73
74+ file_manager_->locations_changed.connect([this] {
75+ SetQuirk(Quirk::RUNNING, IsOpened());
76+ });
77+
78 UpdateTrashIcon();
79 }
80
81@@ -94,11 +97,23 @@
82 return result;
83 }
84
85+bool TrashLauncherIcon::IsOpened() const
86+{
87+ return (file_manager_->IsPrefixOpened(TRASH_URI) || file_manager_->IsPrefixOpened(TRASH_PATH));
88+}
89+
90 void TrashLauncherIcon::ActivateLauncherIcon(ActionArg arg)
91 {
92 SimpleLauncherIcon::ActivateLauncherIcon(arg);
93
94- file_manager_->Open(TRASH_URI.c_str(), arg.timestamp);
95+ if (file_manager_->IsPrefixOpened(TRASH_PATH))
96+ {
97+ file_manager_->OpenActiveChild(TRASH_PATH.c_str(), arg.timestamp);
98+ }
99+ else
100+ {
101+ file_manager_->OpenActiveChild(TRASH_URI.c_str(), arg.timestamp);
102+ }
103 }
104
105 void TrashLauncherIcon::UpdateTrashIcon()
106
107=== modified file 'launcher/TrashLauncherIcon.h'
108--- launcher/TrashLauncherIcon.h 2013-03-21 19:58:52 +0000
109+++ launcher/TrashLauncherIcon.h 2013-03-28 12:05:12 +0000
110@@ -49,6 +49,7 @@
111
112 private:
113 void ActivateLauncherIcon(ActionArg arg);
114+ bool IsOpened() const;
115 MenuItemsVector GetMenus();
116
117 static void UpdateTrashIconCb(GObject* source, GAsyncResult* res, gpointer data);
118
119=== modified file 'launcher/Volume.h'
120--- launcher/Volume.h 2013-03-13 20:54:45 +0000
121+++ launcher/Volume.h 2013-03-28 12:05:12 +0000
122@@ -46,6 +46,7 @@
123 virtual std::string GetIdentifier() const = 0;
124 virtual bool HasSiblings() const = 0;
125 virtual bool IsMounted() const = 0;
126+ virtual bool IsOpened() const = 0;
127
128 virtual void EjectAndShowNotification() = 0;
129 virtual void MountAndOpenInFileManager(unsigned long long timestamp = 0) = 0;
130@@ -54,6 +55,7 @@
131
132 sigc::signal<void> changed;
133 sigc::signal<void> removed;
134+ sigc::signal<void, bool> opened;
135
136 private:
137 Volume(Volume const&) = delete;
138
139=== modified file 'launcher/VolumeImp.cpp'
140--- launcher/VolumeImp.cpp 2013-03-21 19:58:52 +0000
141+++ launcher/VolumeImp.cpp 2013-03-28 12:05:12 +0000
142@@ -40,6 +40,7 @@
143 DeviceNotificationDisplay::Ptr const& device_notification_display,
144 VolumeImp* parent)
145 : parent_(parent)
146+ , opened_(false)
147 , open_timestamp_(0)
148 , volume_(volume)
149 , file_manager_(file_manager)
150@@ -50,7 +51,17 @@
151 });
152
153 signal_volume_removed_.Connect(volume_, "removed", [this] (GVolume*) {
154- parent_->removed.emit();
155+ parent_->removed.emit();
156+ });
157+
158+ file_manager_->locations_changed.connect([this] {
159+ bool opened = file_manager_->IsPrefixOpened(GetUri());
160+
161+ if (opened_ != opened)
162+ {
163+ opened_ = opened;
164+ parent_->opened.emit(opened_);
165+ }
166 });
167 }
168
169@@ -112,6 +123,11 @@
170 return static_cast<bool>(mount);
171 }
172
173+ bool IsOpened() const
174+ {
175+ return opened_;
176+ }
177+
178 void EjectAndShowNotification()
179 {
180 if (!CanBeEjected())
181@@ -167,18 +183,22 @@
182
183 void OpenInFileManager()
184 {
185- file_manager_->Open(GetUri(), open_timestamp_);
186+ file_manager_->OpenActiveChild(GetUri(), open_timestamp_);
187 }
188
189- std::string GetUri()
190+ std::string GetUri() const
191 {
192 glib::Object<GMount> mount(g_volume_get_mount(volume_));
193+
194+ if (!mount.IsType(G_TYPE_MOUNT))
195+ return std::string();
196+
197 glib::Object<GFile> root(g_mount_get_root(mount));
198
199- if (root.IsType(G_TYPE_FILE))
200- return glib::String(g_file_get_uri(root)).Str();
201- else
202- return std::string();
203+ if (!root.IsType(G_TYPE_FILE))
204+ return std::string();
205+
206+ return glib::String(g_file_get_uri(root)).Str();
207 }
208
209 void StopDrive()
210@@ -213,6 +233,7 @@
211 }
212
213 VolumeImp* parent_;
214+ bool opened_;
215 unsigned long long open_timestamp_;
216 glib::Cancellable cancellable_;
217 glib::Object<GVolume> volume_;
218@@ -276,6 +297,11 @@
219 return pimpl->IsMounted();
220 }
221
222+bool VolumeImp::IsOpened() const
223+{
224+ return pimpl->IsOpened();
225+}
226+
227 void VolumeImp::MountAndOpenInFileManager(unsigned long long timestamp)
228 {
229 pimpl->MountAndOpenInFileManager(timestamp);
230
231=== modified file 'launcher/VolumeImp.h'
232--- launcher/VolumeImp.h 2013-03-21 16:22:34 +0000
233+++ launcher/VolumeImp.h 2013-03-28 12:05:12 +0000
234@@ -51,6 +51,7 @@
235 virtual std::string GetIdentifier() const;
236 virtual bool HasSiblings() const;
237 virtual bool IsMounted() const;
238+ virtual bool IsOpened() const;
239
240 virtual void EjectAndShowNotification();
241 virtual void MountAndOpenInFileManager(unsigned long long timestamp);
242
243=== modified file 'launcher/VolumeLauncherIcon.cpp'
244--- launcher/VolumeLauncherIcon.cpp 2013-03-13 20:54:45 +0000
245+++ launcher/VolumeLauncherIcon.cpp 2013-03-28 12:05:12 +0000
246@@ -71,8 +71,7 @@
247 {
248 parent_->tooltip_text = volume_->GetName();
249 parent_->icon_name = volume_->GetIconName();
250-
251- parent_->SetQuirk(Quirk::RUNNING, false);
252+ parent_->SetQuirk(Quirk::RUNNING, volume_->IsOpened());
253 }
254
255 void UpdateVisibility()
256@@ -92,6 +91,7 @@
257 volume_changed_conn_ = volume_->changed.connect(sigc::mem_fun(this, &Impl::OnVolumeChanged));
258 volume_removed_conn_ = volume_->removed.connect(sigc::mem_fun(this, &Impl::OnVolumeRemoved));
259 settings_changed_conn_ = devices_settings_->changed.connect(sigc::mem_fun(this, &Impl::OnSettingsChanged));
260+ volume_->opened.connect(sigc::hide(sigc::mem_fun(this, &Impl::UpdateIcon)));
261 }
262
263 void OnVolumeChanged()
264
265=== modified file 'tests/test_mock_devices.h'
266--- tests/test_mock_devices.h 2013-03-13 20:54:45 +0000
267+++ tests/test_mock_devices.h 2013-03-28 12:05:12 +0000
268@@ -83,6 +83,7 @@
269 MOCK_CONST_METHOD0(HasSiblings, bool(void));
270 MOCK_CONST_METHOD0(CanBeEjected, bool(void));
271 MOCK_CONST_METHOD0(IsMounted, bool(void));
272+ MOCK_CONST_METHOD0(IsOpened, bool(void));
273
274 MOCK_METHOD0(EjectAndShowNotification, void(void));
275 MOCK_METHOD1(MountAndOpenInFileManager, void(unsigned long long));
276
277=== modified file 'tests/test_mock_filemanager.h'
278--- tests/test_mock_filemanager.h 2013-03-21 20:36:16 +0000
279+++ tests/test_mock_filemanager.h 2013-03-28 12:05:12 +0000
280@@ -30,9 +30,12 @@
281 typedef std::shared_ptr<MockFileManager> Ptr;
282
283 MOCK_METHOD2(Open, void(std::string const& uri, unsigned long long time));
284+ MOCK_METHOD2(OpenActiveChild, void(std::string const& uri, unsigned long long time));
285 MOCK_METHOD1(EmptyTrash, void(unsigned long long time));
286+ MOCK_CONST_METHOD0(OpenedLocations, std::vector<std::string>());
287+ MOCK_CONST_METHOD1(IsPrefixOpened, bool(std::string const& uri));
288 };
289
290 }
291
292-#endif
293\ No newline at end of file
294+#endif
295
296=== modified file 'tests/test_trash_launcher_icon.cpp'
297--- tests/test_trash_launcher_icon.cpp 2013-03-25 15:55:05 +0000
298+++ tests/test_trash_launcher_icon.cpp 2013-03-28 12:05:12 +0000
299@@ -18,20 +18,24 @@
300 */
301
302 #include <gmock/gmock.h>
303+#include <UnityCore/DesktopUtilities.h>
304
305 #include "TrashLauncherIcon.h"
306 #include "test_mock_filemanager.h"
307
308 using namespace unity;
309 using namespace unity::launcher;
310+using namespace testing;
311
312 namespace
313 {
314
315-struct TestTrashLauncherIcon : testing::Test
316+const std::string FALLBACK_TRASH_URI = "file://" + DesktopUtilities::GetUserDataDirectory() + "/Trash/files";
317+
318+struct TestTrashLauncherIcon : Test
319 {
320 TestTrashLauncherIcon()
321- : fm_(std::make_shared<MockFileManager>())
322+ : fm_(std::make_shared<NiceMock<MockFileManager>>())
323 , icon(fm_)
324 {}
325
326@@ -47,7 +51,15 @@
327 TEST_F(TestTrashLauncherIcon, Activate)
328 {
329 unsigned long long time = g_random_int();
330- EXPECT_CALL(*fm_, Open("trash:", time));
331+ EXPECT_CALL(*fm_, OpenActiveChild("trash:", time));
332+ icon.Activate(ActionArg(ActionArg::Source::LAUNCHER, 0, time));
333+}
334+
335+TEST_F(TestTrashLauncherIcon, ActivateFallback)
336+{
337+ ON_CALL(*fm_, IsPrefixOpened(FALLBACK_TRASH_URI)).WillByDefault(Return(true));
338+ unsigned long long time = g_random_int();
339+ EXPECT_CALL(*fm_, OpenActiveChild(FALLBACK_TRASH_URI, time));
340 icon.Activate(ActionArg(ActionArg::Source::LAUNCHER, 0, time));
341 }
342
343@@ -69,4 +81,30 @@
344 dbusmenu_menuitem_handle_event(empty_trash_menu, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, time);
345 }
346
347+TEST_F(TestTrashLauncherIcon, RunningState)
348+{
349+ EXPECT_CALL(*fm_, IsPrefixOpened("trash:")).WillRepeatedly(Return(true));
350+ EXPECT_CALL(*fm_, IsPrefixOpened(FALLBACK_TRASH_URI)).WillRepeatedly(Return(false));
351+ fm_->locations_changed.emit();
352+ EXPECT_TRUE(icon.GetQuirk(AbstractLauncherIcon::Quirk::RUNNING));
353+
354+ EXPECT_CALL(*fm_, IsPrefixOpened("trash:")).WillRepeatedly(Return(false));
355+ EXPECT_CALL(*fm_, IsPrefixOpened(FALLBACK_TRASH_URI)).WillRepeatedly(Return(false));
356+ fm_->locations_changed.emit();
357+ EXPECT_FALSE(icon.GetQuirk(AbstractLauncherIcon::Quirk::RUNNING));
358+}
359+
360+TEST_F(TestTrashLauncherIcon, RunningStateFallBack)
361+{
362+ EXPECT_CALL(*fm_, IsPrefixOpened("trash:")).WillRepeatedly(Return(false));
363+ EXPECT_CALL(*fm_, IsPrefixOpened(FALLBACK_TRASH_URI)).WillRepeatedly(Return(true));
364+ fm_->locations_changed.emit();
365+ EXPECT_TRUE(icon.GetQuirk(AbstractLauncherIcon::Quirk::RUNNING));
366+
367+ EXPECT_CALL(*fm_, IsPrefixOpened("trash:")).WillRepeatedly(Return(false));
368+ EXPECT_CALL(*fm_, IsPrefixOpened(FALLBACK_TRASH_URI)).WillRepeatedly(Return(false));
369+ fm_->locations_changed.emit();
370+ EXPECT_FALSE(icon.GetQuirk(AbstractLauncherIcon::Quirk::RUNNING));
371+}
372+
373 }
374
375=== modified file 'tests/test_volume_imp.cpp'
376--- tests/test_volume_imp.cpp 2013-03-21 20:36:16 +0000
377+++ tests/test_volume_imp.cpp 2013-03-28 12:05:12 +0000
378@@ -46,7 +46,7 @@
379 void SetUp()
380 {
381 gvolume_ = g_mock_volume_new();
382- file_manager_.reset(new MockFileManager);
383+ file_manager_.reset(new NiceMock<MockFileManager>);
384 device_notification_display_.reset(new MockDeviceNotificationDisplay);
385 volume_.reset(new launcher::VolumeImp(glib::Object<GVolume>(G_VOLUME(gvolume_.RawPtr()), glib::AddRef()),
386 file_manager_, device_notification_display_));
387@@ -61,6 +61,7 @@
388 TEST_F(TestVolumeImp, TestCtor)
389 {
390 EXPECT_FALSE(volume_->IsMounted());
391+ EXPECT_FALSE(volume_->IsOpened());
392 }
393
394 TEST_F(TestVolumeImp, TestCanBeEjected)
395@@ -109,6 +110,36 @@
396 EXPECT_TRUE(volume_->IsMounted());
397 }
398
399+TEST_F(TestVolumeImp, TestIsOpened)
400+{
401+ volume_->MountAndOpenInFileManager(0);
402+
403+ EXPECT_CALL(*file_manager_, IsPrefixOpened(ROOT_FILE_URI));
404+ ON_CALL(*file_manager_, IsPrefixOpened(_)).WillByDefault(Return(true));
405+ file_manager_->locations_changed.emit();
406+ EXPECT_TRUE(volume_->IsOpened());
407+
408+ EXPECT_CALL(*file_manager_, IsPrefixOpened(ROOT_FILE_URI));
409+ ON_CALL(*file_manager_, IsPrefixOpened(_)).WillByDefault(Return(false));
410+ file_manager_->locations_changed.emit();
411+ EXPECT_FALSE(volume_->IsOpened());
412+}
413+
414+TEST_F(TestVolumeImp, TestIsOpenedSignal)
415+{
416+ ON_CALL(*file_manager_, IsPrefixOpened(_)).WillByDefault(Return(false));
417+
418+ bool opened = false;
419+ volume_->opened.connect([&opened] (bool value) { opened = value; });
420+ file_manager_->locations_changed.emit();
421+
422+ ASSERT_FALSE(opened);
423+
424+ ON_CALL(*file_manager_, IsPrefixOpened(_)).WillByDefault(Return(true));
425+ file_manager_->locations_changed.emit();
426+ EXPECT_TRUE(opened);
427+}
428+
429 TEST_F(TestVolumeImp, TestEjectAndShowNotification)
430 {
431 g_mock_volume_set_can_eject(gvolume_, TRUE);
432@@ -122,14 +153,7 @@
433 TEST_F(TestVolumeImp, TestMountAndOpenInFileManager)
434 {
435 unsigned long long time = g_random_int();
436- EXPECT_CALL(*file_manager_, Open(ROOT_FILE_URI, time));
437-
438- volume_->MountAndOpenInFileManager(time);
439- EXPECT_EQ(g_mock_volume_last_mount_had_mount_operation(gvolume_), TRUE);
440- EXPECT_TRUE(volume_->IsMounted());
441-
442- time = g_random_int();
443- EXPECT_CALL(*file_manager_, Open(ROOT_FILE_URI, time));
444+ EXPECT_CALL(*file_manager_, OpenActiveChild(ROOT_FILE_URI, time));
445
446 volume_->MountAndOpenInFileManager(time);
447 EXPECT_EQ(g_mock_volume_last_mount_had_mount_operation(gvolume_), TRUE);
448
449=== modified file 'tests/test_volume_launcher_icon.cpp'
450--- tests/test_volume_launcher_icon.cpp 2013-03-14 00:18:36 +0000
451+++ tests/test_volume_launcher_icon.cpp 2013-03-28 12:05:12 +0000
452@@ -35,8 +35,8 @@
453 {
454 virtual void SetUp()
455 {
456- volume_.reset(new MockVolume);
457- settings_.reset(new MockDevicesSettings);
458+ volume_.reset(new NiceMock<MockVolume>);
459+ settings_.reset(new NiceMock<MockDevicesSettings>);
460
461 SetupVolumeDefaultBehavior();
462 SetupSettingsDefaultBehavior();
463@@ -44,40 +44,25 @@
464
465 void CreateIcon()
466 {
467- icon_ = new VolumeLauncherIcon(volume_, settings_);
468+ icon_ = new NiceMock<VolumeLauncherIcon>(volume_, settings_);
469 }
470
471 void SetupSettingsDefaultBehavior()
472 {
473- EXPECT_CALL(*settings_, IsABlacklistedDevice(_))
474- .WillRepeatedly(Return(false));
475+ ON_CALL(*settings_, IsABlacklistedDevice(_)).WillByDefault(Return(false));
476 }
477
478 void SetupVolumeDefaultBehavior()
479 {
480- EXPECT_CALL(*volume_, CanBeRemoved())
481- .WillRepeatedly(Return(false));
482-
483- EXPECT_CALL(*volume_, CanBeStopped())
484- .WillRepeatedly(Return(false));
485-
486- EXPECT_CALL(*volume_, GetName())
487- .WillRepeatedly(Return("Test Name"));
488-
489- EXPECT_CALL(*volume_, GetIconName())
490- .WillRepeatedly(Return("Test Icon Name"));
491-
492- EXPECT_CALL(*volume_, GetIdentifier())
493- .WillRepeatedly(Return("Test Identifier"));
494-
495- EXPECT_CALL(*volume_, HasSiblings())
496- .WillRepeatedly(Return(false));
497-
498- EXPECT_CALL(*volume_, CanBeEjected())
499- .WillRepeatedly(Return(false));
500-
501- EXPECT_CALL(*volume_, IsMounted())
502- .WillRepeatedly(Return(true));
503+ ON_CALL(*volume_, CanBeRemoved()).WillByDefault(Return(false));
504+ ON_CALL(*volume_, CanBeStopped()).WillByDefault(Return(false));
505+ ON_CALL(*volume_, GetName()).WillByDefault(Return("Test Name"));
506+ ON_CALL(*volume_, GetIconName()).WillByDefault(Return("Test Icon Name"));
507+ ON_CALL(*volume_, GetIdentifier()).WillByDefault(Return("Test Identifier"));
508+ ON_CALL(*volume_, HasSiblings()).WillByDefault(Return(false));
509+ ON_CALL(*volume_, CanBeEjected()).WillByDefault(Return(false));
510+ ON_CALL(*volume_, IsMounted()).WillByDefault(Return(true));
511+ ON_CALL(*volume_, IsOpened()) .WillByDefault(Return(true));
512 }
513
514 glib::Object<DbusmenuMenuitem> GetMenuItemAtIndex(int index)
515@@ -105,9 +90,23 @@
516 {
517 CreateIcon();
518
519+ EXPECT_EQ(icon_->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING), volume_->IsOpened());
520+}
521+
522+TEST_F(TestVolumeLauncherIcon, TestRunningStateUpdatesOnOpenedState)
523+{
524+ CreateIcon();
525+
526+ ON_CALL(*volume_, IsOpened()).WillByDefault(Return(false));
527+ volume_->opened.emit(volume_->IsOpened());
528 EXPECT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING));
529+
530+ ON_CALL(*volume_, IsOpened()).WillByDefault(Return(true));
531+ volume_->opened.emit(volume_->IsOpened());
532+ EXPECT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING));
533 }
534
535+
536 TEST_F(TestVolumeLauncherIcon, TestPosition)
537 {
538 CreateIcon();
539
540=== modified file 'unity-shared/FileManager.h'
541--- unity-shared/FileManager.h 2013-03-21 20:09:02 +0000
542+++ unity-shared/FileManager.h 2013-03-28 12:05:12 +0000
543@@ -23,20 +23,27 @@
544
545 #include <memory>
546 #include <string>
547+#include <sigc++/sigc++.h>
548
549 namespace unity
550 {
551
552-class FileManager
553+class FileManager : public sigc::trackable
554 {
555 public:
556 typedef std::shared_ptr<FileManager> Ptr;
557
558 FileManager() = default;
559 virtual ~FileManager() {}
560+
561 virtual void Open(std::string const& uri, unsigned long long timestamp = 0) = 0;
562+ virtual void OpenActiveChild(std::string const& uri, unsigned long long timestamp = 0) = 0;
563+ virtual std::vector<std::string> OpenedLocations() const = 0;
564+ virtual bool IsPrefixOpened(std::string const& uri) const = 0;
565 virtual void EmptyTrash(unsigned long long timestamp = 0) = 0;
566
567+ sigc::signal<void> locations_changed;
568+
569 private:
570 FileManager(FileManager const&) = delete;
571 FileManager& operator=(FileManager const&) = delete;
572
573=== modified file 'unity-shared/GnomeFileManager.cpp'
574--- unity-shared/GnomeFileManager.cpp 2013-03-21 20:37:04 +0000
575+++ unity-shared/GnomeFileManager.cpp 2013-03-28 12:05:12 +0000
576@@ -35,6 +35,75 @@
577 const std::string TRASH_URI = "trash:";
578 }
579
580+struct GnomeFileManager::Impl
581+{
582+ Impl(GnomeFileManager* parent)
583+ : parent_(parent)
584+ , filemanager_proxy_("org.freedesktop.FileManager1", "/org/freedesktop/FileManager1", "org.freedesktop.FileManager1")
585+ {
586+ auto callback = sigc::mem_fun(this, &Impl::OnOpenLocationsUpdated);
587+ filemanager_proxy_.GetProperty("OpenLocations", callback);
588+ filemanager_proxy_.ConnectProperty("OpenLocations", callback);
589+ }
590+
591+ void OnOpenLocationsUpdated(GVariant* value)
592+ {
593+ if (!g_variant_is_of_type(value, G_VARIANT_TYPE_STRING_ARRAY))
594+ {
595+ LOG_ERROR(logger) << "Locations value type is not matching the expected one!";
596+ return;
597+ }
598+
599+ opened_locations_.clear();
600+
601+ GVariantIter iter;
602+ const char *str;
603+
604+ g_variant_iter_init(&iter, value);
605+
606+ while (g_variant_iter_loop(&iter, "s", &str))
607+ {
608+ LOG_DEBUG(logger) << "Opened location " << str;
609+ opened_locations_.push_back(str);
610+ }
611+
612+ parent_->locations_changed.emit();
613+ }
614+
615+ std::string GetOpenedPrefix(std::string const& uri)
616+ {
617+ glib::Object<GFile> uri_file(g_file_new_for_uri(uri.c_str()));
618+
619+ for (auto const& loc : opened_locations_)
620+ {
621+ glib::Object<GFile> loc_file(g_file_new_for_uri(loc.c_str()));
622+
623+ if (g_file_equal(loc_file, uri_file) || g_file_has_prefix(loc_file, uri_file))
624+ return loc;
625+ }
626+
627+ return "";
628+ }
629+
630+ GnomeFileManager* parent_;
631+ glib::DBusProxy filemanager_proxy_;
632+ std::vector<std::string> opened_locations_;
633+};
634+
635+
636+FileManager::Ptr GnomeFileManager::Get()
637+{
638+ static FileManager::Ptr instance(new GnomeFileManager());
639+ return instance;
640+}
641+
642+GnomeFileManager::GnomeFileManager()
643+ : impl_(new Impl(this))
644+{}
645+
646+GnomeFileManager::~GnomeFileManager()
647+{}
648+
649 void GnomeFileManager::Open(std::string const& uri, unsigned long long timestamp)
650 {
651 if (uri.empty())
652@@ -59,6 +128,13 @@
653 }
654 }
655
656+void GnomeFileManager::OpenActiveChild(std::string const& uri, unsigned long long timestamp)
657+{
658+ auto const& opened = impl_->GetOpenedPrefix(uri);
659+
660+ Open(opened.empty() ? uri : opened, timestamp);
661+}
662+
663 void GnomeFileManager::Activate(unsigned long long timestamp)
664 {
665 glib::Cancellable cancellable;
666@@ -104,4 +180,14 @@
667 proxy->CallBegin("EmptyTrash", nullptr, [proxy] (GVariant*, glib::Error const&) {});
668 }
669
670+std::vector<std::string> GnomeFileManager::OpenedLocations() const
671+{
672+ return impl_->opened_locations_;
673+}
674+
675+bool GnomeFileManager::IsPrefixOpened(std::string const& uri) const
676+{
677+ return !impl_->GetOpenedPrefix(uri).empty();
678+}
679+
680 }
681
682=== modified file 'unity-shared/GnomeFileManager.h'
683--- unity-shared/GnomeFileManager.h 2013-03-21 20:37:04 +0000
684+++ unity-shared/GnomeFileManager.h 2013-03-28 12:05:12 +0000
685@@ -29,11 +29,21 @@
686 class GnomeFileManager : public FileManager
687 {
688 public:
689+ static FileManager::Ptr Get();
690+ ~GnomeFileManager();
691+
692 void Open(std::string const& uri, unsigned long long timestamp);
693+ void OpenActiveChild(std::string const& uri, unsigned long long timestamp);
694 void EmptyTrash(unsigned long long timestamp);
695+ std::vector<std::string> OpenedLocations() const;
696+ bool IsPrefixOpened(std::string const& uri) const;
697
698 private:
699+ GnomeFileManager();
700 void Activate(unsigned long long timestamp);
701+
702+ struct Impl;
703+ std::unique_ptr<Impl> impl_;
704 };
705
706 }