Merge lp:~azzar1/unity/devices-cleanup-and-test into lp:unity

Proposed by Andrea Azzarone
Status: Merged
Approved by: Andrea Azzarone
Approved revision: no longer in the source branch.
Merged at revision: 2641
Proposed branch: lp:~azzar1/unity/devices-cleanup-and-test
Merge into: lp:unity
Diff against target: 3673 lines (+2330/-692)
35 files modified
com.canonical.Unity.gschema.xml (+3/-3)
launcher/AbstractVolumeMonitorWrapper.h (+3/-4)
launcher/CMakeLists.txt (+6/-3)
launcher/DeviceLauncherSection.cpp (+23/-27)
launcher/DeviceLauncherSection.h (+17/-7)
launcher/DeviceNotificationDisplay.h (+45/-0)
launcher/DeviceNotificationDisplayImp.cpp (+82/-0)
launcher/DeviceNotificationDisplayImp.h (+46/-0)
launcher/DevicesSettings.h (+26/-48)
launcher/DevicesSettingsImp.cpp (+133/-125)
launcher/DevicesSettingsImp.h (+50/-0)
launcher/FileManagerOpener.h (+45/-0)
launcher/FileManagerOpenerImp.cpp (+35/-0)
launcher/FileManagerOpenerImp.h (+39/-0)
launcher/Launcher.cpp (+12/-2)
launcher/Launcher.h (+5/-0)
launcher/LauncherController.cpp (+6/-4)
launcher/LauncherController.h (+1/-0)
launcher/LauncherControllerPrivate.h (+2/-0)
launcher/Volume.h (+62/-0)
launcher/VolumeImp.cpp (+294/-0)
launcher/VolumeImp.h (+68/-0)
launcher/VolumeLauncherIcon.cpp (+262/-382)
launcher/VolumeLauncherIcon.h (+27/-43)
plugins/unityshell/src/unityshell.cpp (+0/-5)
plugins/unityshell/unityshell.xml.in (+0/-20)
po/POTFILES.in (+2/-1)
tests/CMakeLists.txt (+8/-2)
tests/gmockmount.c (+167/-0)
tests/gmockmount.h (+55/-0)
tests/gmockvolume.c (+120/-13)
tests/gmockvolume.h (+14/-2)
tests/test_device_launcher_section.cpp (+11/-1)
tests/test_volume_imp.cpp (+163/-0)
tests/test_volume_launcher_icon.cpp (+498/-0)
To merge this branch: bzr merge lp:~azzar1/unity/devices-cleanup-and-test
Reviewer Review Type Date Requested Status
Marco Trevisan (Treviño) Approve
Review via email: mp+119265@code.launchpad.net

Commit message

Refactor device launcher icons.

Description of the change

== Problems ==
#. Unity launcher gets cluttered when having multiple partitions and/or external volumes attached.
#. Devices launcher icons needs test.

== Fix ==
#. DeviceNotificationShower and FileManagerOpener are written rely on SRP and DI.
#. Volume/VolumeImp is a wrapper for GVolume. It makes the VolumeLauncherIcon testable and readable.

== Test ==
#. Unit tests added for VolumeLauncherIcon and VolumeImpl. DeviceLauncherSection already has unit test.
#. I've not added tests for DevicesSettingsImp because Trevinho will remove DevicesSettingsImp in his next branch.

---

Forgive me for the long diff. Refactoring code to make it testable is hard without breaking legacy code.

To post a comment you must log in.
Revision history for this message
Sam Spilsbury (smspillaz) wrote :

> Forgive me for the long diff. Refactoring code to make it testable is hard without breaking legacy code.

There is no need to apologize for this - a large diff that gets code under test and makes it cleaner is better than a short diff that does not include test cases.

235 +class DeviceNotificationShower : private boost::noncopyable
236 +{
237 +public:
238 + typedef std::shared_ptr<DeviceNotificationShower> Ptr;
239 +

This class can probably be renamed to DeviceNotificationDisplay - the word "Shower" has two meanings in the english langauge and although it was silly of me to confuse one for the other, I did so anyways.

235 +class DeviceNotificationShower : private boost::noncopyable
236 +{
237 +public:
238 + typedef std::shared_ptr<DeviceNotificationShower> Ptr;
239 +

I'm also not entirely certain about making the interface noncopyable. Generally speaking the object should be noncopyable.

> IconLoader::GetDefault().

Can we remove that singleton?

3019 + g_mock_volume_set_can_eject(gvolume_, TRUE);
3020 + EXPECT_TRUE(volume_->CanBeEjected());

Generally speaking I prefer to operate mocked objects through their interfaces, eg

g_volume_set_can_eject (...); (I assume that you're testing the effect of external GIO code calling set_can_eject through the interface ...).

Also it might be useful for you to hook up your mock implementation of GDrive to a Google Mock directly. That way you can expect that your VolumeLauncherImp is calling the correct function and also determine what the return value is directly within the test code without having to add new api to GMockDrive to set them.

3068 + EXPECT_CALL(*file_manager_opener_, Open("file:///some/directory/testfile"))
3069 + .Times(1);
3070 +
3071 + volume_->MountAndOpenInFileManager();
3072 + EXPECT_TRUE(volume_->IsMounted());

It was a bit confusing as to where: "file:///some/directory/testfile" came from - better make it a constant.

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

> > Forgive me for the long diff. Refactoring code to make it testable is hard
> without breaking legacy code.
>
> There is no need to apologize for this - a large diff that gets code under
> test and makes it cleaner is better than a short diff that does not include
> test cases.
>
> 235 +class DeviceNotificationShower : private boost::noncopyable
> 236 +{
> 237 +public:
> 238 + typedef std::shared_ptr<DeviceNotificationShower> Ptr;
> 239 +
>
> This class can probably be renamed to DeviceNotificationDisplay - the word
> "Shower" has two meanings in the english langauge and although it was silly of
> me to confuse one for the other, I did so anyways.

Will do!

>
> 235 +class DeviceNotificationShower : private boost::noncopyable
> 236 +{
> 237 +public:
> 238 + typedef std::shared_ptr<DeviceNotificationShower> Ptr;
> 239 +
>
> I'm also not entirely certain about making the interface noncopyable.
> Generally speaking the object should be noncopyable.
>

We really don't need to make that object copyable. Also making in un-copyable force us to use it through a pointer.

> > IconLoader::GetDefault().
>

IconLoader is used in dash/hud/launcher/switcher code. I think it's not a good idea to do it in this branch.

> Can we remove that singleton?
>
> 3019 + g_mock_volume_set_can_eject(gvolume_, TRUE);
> 3020 + EXPECT_TRUE(volume_->CanBeEjected());
>
> Generally speaking I prefer to operate mocked objects through their
> interfaces, eg
>
> g_volume_set_can_eject (...); (I assume that you're testing the effect of
> external GIO code calling set_can_eject through the interface ...).

Here I'm testing the VolumeImp mocking GVolumeIface.

>
> Also it might be useful for you to hook up your mock implementation of GDrive
> to a Google Mock directly. That way you can expect that your VolumeLauncherImp
> is calling the correct function and also determine what the return value is
> directly within the test code without having to add new api to GMockDrive to
> set them.
>

Can we mock a GObject using Google Mock?

> 3068 + EXPECT_CALL(*file_manager_opener_,
> Open("file:///some/directory/testfile"))
> 3069 + .Times(1);
> 3070 +
> 3071 + volume_->MountAndOpenInFileManager();
> 3072 + EXPECT_TRUE(volume_->IsMounted());
>
> It was a bit confusing as to where: "file:///some/directory/testfile" came
> from - better make it a constant.

Will fix it.

Revision history for this message
Sam Spilsbury (smspillaz) wrote :
Download full text (3.5 KiB)

> > > Forgive me for the long diff. Refactoring code to make it testable is hard
> > without breaking legacy code.
> >
> > There is no need to apologize for this - a large diff that gets code under
> > test and makes it cleaner is better than a short diff that does not include
> > test cases.
> >
> > 235 +class DeviceNotificationShower : private boost::noncopyable
> > 236 +{
> > 237 +public:
> > 238 + typedef std::shared_ptr<DeviceNotificationShower> Ptr;
> > 239 +
> >
> > This class can probably be renamed to DeviceNotificationDisplay - the word
> > "Shower" has two meanings in the english langauge and although it was silly
> of
> > me to confuse one for the other, I did so anyways.
>
> Will do!
>
> >
> > 235 +class DeviceNotificationShower : private boost::noncopyable
> > 236 +{
> > 237 +public:
> > 238 + typedef std::shared_ptr<DeviceNotificationShower> Ptr;
> > 239 +
> >
> > I'm also not entirely certain about making the interface noncopyable.
> > Generally speaking the object should be noncopyable.
> >
>
> We really don't need to make that object copyable. Also making in un-copyable
> force us to use it through a pointer.

Right, my point was that you've made the interface itself noncopyable. However there probably isn't much
of a way to prevent copyablility except if we were to do it like that, so that seems okay.

>
> > > IconLoader::GetDefault().
> >
>
> IconLoader is used in dash/hud/launcher/switcher code. I think it's not a good
> idea to do it in this branch.

Sure, just food for thought.

>
> > Can we remove that singleton?
> >
> > 3019 + g_mock_volume_set_can_eject(gvolume_, TRUE);
> > 3020 + EXPECT_TRUE(volume_->CanBeEjected());
> >
> > Generally speaking I prefer to operate mocked objects through their
> > interfaces, eg
> >
> > g_volume_set_can_eject (...); (I assume that you're testing the effect of
> > external GIO code calling set_can_eject through the interface ...).
>
> Here I'm testing the VolumeImp mocking GVolumeIface.

Is VolumeImp providing a C++ wrapper around GVolumeIface ?

I feel like its a bit strange then, if the contents of the underlying GVolume can never be altered except by VolumeImp, that they are being altered in the tests to check the behaviour of VolumeImp.

Wouldn't it be better to alter GVolume through VolumeImp ?

Unless it is that it wraps an /existing/ GVolume, which has can_eject () already set. In this case, it probably makes more ense to implement GMockVolume in terms of google mock.

>
> >
> > Also it might be useful for you to hook up your mock implementation of
> GDrive
> > to a Google Mock directly. That way you can expect that your
> VolumeLauncherImp
> > is calling the correct function and also determine what the return value is
> > directly within the test code without having to add new api to GMockDrive to
> > set them.
> >
>
> Can we mock a GObject using Google Mock?

Yes you can, by making the interface delegate to a google mock.

Have a look at this:

http://bazaar.launchpad.net/~compiz-team/compiz/compiz.gtk-window-decorator-gsettings/view/head:/gtk/window-decorator/tests/compiz_gwd_mock_settings_writable.cpp
>
> > 3068 + EX...

Read more...

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

> Is VolumeImp providing a C++ wrapper around GVolumeIface ?

Volume is the interface, VolumeImp is the implementation. Volume doesn't know nothing about GVolume, VolumeImp is a kind of a wrapper. I added unit-test for VolumeImp because it's not a simple wrapper.

> I feel like its a bit strange then, if the contents of the underlying GVolume can never be altered except by VolumeImp, that they are being altered in the tests to check the behaviour of VolumeImp.

> Wouldn't it be better to alter GVolume through VolumeImp ?

We do it in VolumeLauncherIcon, mocking Volume. VolumeLauncherIcon doesn't use VolumeImp...

> Unless it is that it wraps an /existing/ GVolume, which has can_eject () already set. In this case, it probably makes more ense to implement GMockVolume in terms of google mock.

I will study this opportunity. Thank you :)

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

There are conflicts with trunk now...

50 - DeviceLauncherIcon.cpp
51 + VolumeLauncherIcon.cpp

Please, keep these in alphabetic order.

2252 void OnRemoved();

Please, make this protected in case you need this for testing.

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

> There are conflicts with trunk now...
>
> 50 - DeviceLauncherIcon.cpp
> 51 + VolumeLauncherIcon.cpp
>
> Please, keep these in alphabetic order.

Sure, will do?

>
> 2252 void OnRemoved();
>
> Please, make this protected in case you need this for testing.

It needs to be public. Maybe you meant "virtual"?

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

Nice, this work good for me... What about renaming IsABlacklistedDevice to IsBlackListedDevice?

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

> Nice, this work good for me... What about renaming IsABlacklistedDevice to
> IsBlackListedDevice?

Ok, but I think there is no need to change it if you're going to remove DevicesSettings ;)

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

Probably I will keep it, since we still need a blacklist for these devices, so for now I'll keep as you wrote it.
Also maybe it's better if you get rid of the "TryTo..." prefix.

Also is this idle still needed:
113 + device_populate_idle_.Run([this] () {
114 PopulateEntries();
115 return false;
116 });

I think it was added to make the launcher controller properly populate the devices, right?
If you confirm this, I'll handle it in another way into my branch.

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

> Probably I will keep it, since we still need a blacklist for these devices, so
> for now I'll keep as you wrote it.
> Also maybe it's better if you get rid of the "TryTo..." prefix.

I'd prefer too keep the prefix because adding/removing can fail. When you call TryTo... you're sure that adding/removing are completed successfully when you got the changed signal.

>
> Also is this idle still needed:
> 113 + device_populate_idle_.Run([this] () {
> 114 PopulateEntries();
> 115 return false;
> 116 });
>
> I think it was added to make the launcher controller properly populate the
> devices, right?
> If you confirm this, I'll handle it in another way into my branch.

Yeah you can remove it if it's a problem for you ;)

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

I removed the OnRemoved function ;)

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

I like the way you removed OnRemoved, I think this is fine for trunk now.

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

The Jenkins job https://jenkins.qa.ubuntu.com/job/automerge-unity/1155/console reported an error when processing this lp:~andyrock/unity/devices-cleanup-and-test branch.
Not merging it.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'com.canonical.Unity.gschema.xml'
--- com.canonical.Unity.gschema.xml 2012-07-19 10:13:55 +0000
+++ com.canonical.Unity.gschema.xml 2012-08-29 08:24:20 +0000
@@ -42,10 +42,10 @@
42 </key>42 </key>
43 </schema>43 </schema>
44 <schema path="/com/canonical/unity/devices/" id="com.canonical.Unity.Devices" gettext-domain="unity">44 <schema path="/com/canonical/unity/devices/" id="com.canonical.Unity.Devices" gettext-domain="unity">
45 <key type="as" name="favorites">45 <key type="as" name="blacklist">
46 <default>[]</default>46 <default>[]</default>
47 <summary>List of device uuid for favorites on the launcher.</summary>47 <summary>List of device uuid blacklist from the launcher.</summary>
48 <description>These devices are shown in the Launcher by default.</description>48 <description>These devices are not shown in the launcher by default.</description>
49 </key>49 </key>
50 </schema>50 </schema>
51 <schema path="/com/canonical/unity/dash/" id="com.canonical.Unity.Dash" gettext-domain="unity">51 <schema path="/com/canonical/unity/dash/" id="com.canonical.Unity.Dash" gettext-domain="unity">
5252
=== modified file 'launcher/AbstractVolumeMonitorWrapper.h'
--- launcher/AbstractVolumeMonitorWrapper.h 2012-07-18 22:54:22 +0000
+++ launcher/AbstractVolumeMonitorWrapper.h 2012-08-29 08:24:20 +0000
@@ -27,7 +27,6 @@
27#include <sigc++/trackable.h>27#include <sigc++/trackable.h>
2828
29#include <UnityCore/GLibWrapper.h>29#include <UnityCore/GLibWrapper.h>
30#include <UnityCore/GLibSignal.h>
3130
32namespace unity31namespace unity
33{32{
@@ -54,8 +53,8 @@
54 sigc::signal<void, glib::Object<GVolume> const&> volume_removed;53 sigc::signal<void, glib::Object<GVolume> const&> volume_removed;
55};54};
5655
57} // namespace launcher56}
58} // namespace unity57}
5958
60#endif // UNITYSHELL_ABSTRACT_VOLUME_MONITOR_WRAPPER_H59#endif
6160
6261
=== modified file 'launcher/CMakeLists.txt'
--- launcher/CMakeLists.txt 2012-07-27 20:20:29 +0000
+++ launcher/CMakeLists.txt 2012-08-29 08:24:20 +0000
@@ -37,14 +37,15 @@
37 DNDCollectionWindow.cpp37 DNDCollectionWindow.cpp
38 Decaymulator.cpp38 Decaymulator.cpp
39 DesktopLauncherIcon.cpp39 DesktopLauncherIcon.cpp
40 DeviceLauncherIcon.cpp
41 DeviceLauncherSection.cpp40 DeviceLauncherSection.cpp
42 DevicesSettings.cpp41 DeviceNotificationDisplayImp.cpp
42 DevicesSettingsImp.cpp
43 DndData.cpp43 DndData.cpp
44 EdgeBarrierController.cpp44 EdgeBarrierController.cpp
45 FavoriteStore.cpp45 FavoriteStore.cpp
46 FavoriteStoreGSettings.cpp46 FavoriteStoreGSettings.cpp
47 FavoriteStorePrivate.cpp47 FavoriteStorePrivate.cpp
48 FileManagerOpenerImp.cpp
48 HudLauncherIcon.cpp49 HudLauncherIcon.cpp
49 Launcher.cpp50 Launcher.cpp
50 LauncherController.cpp51 LauncherController.cpp
@@ -71,6 +72,8 @@
71 SpacerLauncherIcon.cpp72 SpacerLauncherIcon.cpp
72 Tooltip.cpp73 Tooltip.cpp
73 TrashLauncherIcon.cpp74 TrashLauncherIcon.cpp
75 VolumeImp.cpp
76 VolumeLauncherIcon.cpp
74 VolumeMonitorWrapper.cpp77 VolumeMonitorWrapper.cpp
75 )78 )
7679
@@ -87,7 +90,7 @@
87add_library (switcher-lib STATIC ${SWITCHER_SOURCES})90add_library (switcher-lib STATIC ${SWITCHER_SOURCES})
88add_dependencies (switcher-lib unity-core-${UNITY_API_VERSION} unity-shared)91add_dependencies (switcher-lib unity-core-${UNITY_API_VERSION} unity-shared)
8992
90# 93#
91# Standalone variant94# Standalone variant
92#95#
93add_executable (launcher StandaloneLauncher.cpp)96add_executable (launcher StandaloneLauncher.cpp)
9497
=== modified file 'launcher/DeviceLauncherSection.cpp'
--- launcher/DeviceLauncherSection.cpp 2012-07-18 17:51:56 +0000
+++ launcher/DeviceLauncherSection.cpp 2012-08-29 08:24:20 +0000
@@ -18,19 +18,27 @@
18 */18 */
1919
20#include "DeviceLauncherSection.h"20#include "DeviceLauncherSection.h"
21#include "DeviceNotificationDisplayImp.h"
22#include "DevicesSettings.h"
23#include "FileManagerOpenerImp.h"
24#include "VolumeImp.h"
2125
22namespace unity26namespace unity
23{27{
24namespace launcher28namespace launcher
25{29{
2630
27DeviceLauncherSection::DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr volume_monitor)31DeviceLauncherSection::DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr volume_monitor,
32 DevicesSettings::Ptr devices_settings)
28 : monitor_(volume_monitor)33 : monitor_(volume_monitor)
34 , devices_settings_(devices_settings)
35 , file_manager_opener_(new FileManagerOpenerImp)
36 , device_notification_display_(new DeviceNotificationDisplayImp)
29{37{
30 monitor_->volume_added.connect(sigc::mem_fun(this, &DeviceLauncherSection::OnVolumeAdded));38 monitor_->volume_added.connect(sigc::mem_fun(this, &DeviceLauncherSection::OnVolumeAdded));
31 monitor_->volume_removed.connect(sigc::mem_fun(this, &DeviceLauncherSection::OnVolumeRemoved));39 monitor_->volume_removed.connect(sigc::mem_fun(this, &DeviceLauncherSection::OnVolumeRemoved));
32 40
33 device_populate_idle_.Run([&] () {41 device_populate_idle_.Run([this] () {
34 PopulateEntries();42 PopulateEntries();
35 return false;43 return false;
36 });44 });
@@ -39,29 +47,21 @@
39void DeviceLauncherSection::PopulateEntries()47void DeviceLauncherSection::PopulateEntries()
40{48{
41 for (auto volume : monitor_->GetVolumes())49 for (auto volume : monitor_->GetVolumes())
42 {50 TryToCreateAndAddIcon(volume);
43 // Sanity check. Avoid duplicates.
44 if (map_.find(volume) != map_.end())
45 continue;
46
47 DeviceLauncherIcon::Ptr icon(new DeviceLauncherIcon(volume));
48
49 map_[volume] = icon;
50 IconAdded.emit(icon);
51 }
52}51}
5352
54/* Uses a std::map to track all the volume icons shown and not shown.
55 * Keep in mind: when "volume-removed" is recevied we should erase
56 * the pair (GVolume - DeviceLauncherIcon) from the std::map to avoid leaks
57 */
58void DeviceLauncherSection::OnVolumeAdded(glib::Object<GVolume> const& volume)53void DeviceLauncherSection::OnVolumeAdded(glib::Object<GVolume> const& volume)
59{54{
60 // Sanity check. Avoid duplicates.55 TryToCreateAndAddIcon(volume);
56}
57
58void DeviceLauncherSection::TryToCreateAndAddIcon(glib::Object<GVolume> volume)
59{
61 if (map_.find(volume) != map_.end())60 if (map_.find(volume) != map_.end())
62 return;61 return;
6362
64 DeviceLauncherIcon::Ptr icon(new DeviceLauncherIcon(volume));63 VolumeLauncherIcon::Ptr icon(new VolumeLauncherIcon(std::make_shared<VolumeImp>(volume, file_manager_opener_, device_notification_display_),
64 devices_settings_));
6565
66 map_[volume] = icon;66 map_[volume] = icon;
67 IconAdded.emit(icon);67 IconAdded.emit(icon);
@@ -73,12 +73,8 @@
7373
74 // Sanity check74 // Sanity check
75 if (volume_it != map_.end())75 if (volume_it != map_.end())
76 {
77 volume_it->second->OnRemoved();
78 map_.erase(volume_it);76 map_.erase(volume_it);
79 }77}
80}78
8179}
82} // namespace launcher80}
83} // namespace unity
84
8581
=== modified file 'launcher/DeviceLauncherSection.h'
--- launcher/DeviceLauncherSection.h 2012-07-18 17:51:56 +0000
+++ launcher/DeviceLauncherSection.h 2012-08-29 08:24:20 +0000
@@ -17,15 +17,19 @@
17 * Andrea Azzarone <andrea.azzarone@canonical.com>17 * Andrea Azzarone <andrea.azzarone@canonical.com>
18 */18 */
1919
20#ifndef _DEVICE_LAUNCHER_SECTION_H_20#ifndef UNITYSHELL_DEVICE_LAUNCHER_SECTION_H
21#define _DEVICE_LAUNCHER_SECTION_H_21#define UNITYSHELL_DEVICE_LAUNCHER_SECTION_H
2222
23#include <map>23#include <map>
24#include <memory>
2425
25#include <UnityCore/GLibSource.h>26#include <UnityCore/GLibSource.h>
2627
27#include "DeviceLauncherIcon.h"
28#include "AbstractVolumeMonitorWrapper.h"28#include "AbstractVolumeMonitorWrapper.h"
29#include "DevicesSettings.h"
30#include "DeviceNotificationDisplay.h"
31#include "FileManagerOpener.h"
32#include "VolumeLauncherIcon.h"
2933
30namespace unity34namespace unity
31{35{
@@ -35,7 +39,8 @@
35class DeviceLauncherSection : public sigc::trackable39class DeviceLauncherSection : public sigc::trackable
36{40{
37public:41public:
38 DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr volume_monitor);42 DeviceLauncherSection(AbstractVolumeMonitorWrapper::Ptr volume_monitor,
43 DevicesSettings::Ptr devices_settings);
3944
40 sigc::signal<void, AbstractLauncherIcon::Ptr> IconAdded;45 sigc::signal<void, AbstractLauncherIcon::Ptr> IconAdded;
4146
@@ -43,13 +48,18 @@
43 void PopulateEntries();48 void PopulateEntries();
44 void OnVolumeAdded(glib::Object<GVolume> const& volume);49 void OnVolumeAdded(glib::Object<GVolume> const& volume);
45 void OnVolumeRemoved(glib::Object<GVolume> const& volume);50 void OnVolumeRemoved(glib::Object<GVolume> const& volume);
51 void TryToCreateAndAddIcon(glib::Object<GVolume> volume);
4652
47 std::map<GVolume*, DeviceLauncherIcon::Ptr> map_;53 std::map<GVolume*, VolumeLauncherIcon::Ptr> map_;
48 AbstractVolumeMonitorWrapper::Ptr monitor_;54 AbstractVolumeMonitorWrapper::Ptr monitor_;
55 DevicesSettings::Ptr devices_settings_;
56 FileManagerOpener::Ptr file_manager_opener_;
57 DeviceNotificationDisplay::Ptr device_notification_display_;
58
49 glib::Idle device_populate_idle_;59 glib::Idle device_populate_idle_;
50};60};
5161
52}62}
53} // namespace unity63}
5464
55#endif // _DEVICE_LAUNCHER_SECTION_H_65#endif
5666
=== added file 'launcher/DeviceNotificationDisplay.h'
--- launcher/DeviceNotificationDisplay.h 1970-01-01 00:00:00 +0000
+++ launcher/DeviceNotificationDisplay.h 2012-08-29 08:24:20 +0000
@@ -0,0 +1,45 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright (C) 2012 Canonical Ltd
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18 */
19
20#ifndef UNITYSHELL_DEVICE_NOTIFICATION_DISPLAY_H
21#define UNITYSHELL_DEVICE_NOTIFICATION_DISPLAY_H
22
23#include <boost/noncopyable.hpp>
24#include <memory>
25#include <string>
26
27namespace unity
28{
29namespace launcher
30{
31
32class DeviceNotificationDisplay : private boost::noncopyable
33{
34public:
35 typedef std::shared_ptr<DeviceNotificationDisplay> Ptr;
36
37 virtual ~DeviceNotificationDisplay() {}
38
39 virtual void Display(std::string const& icon_name, std::string const& volume_name) = 0;
40};
41
42}
43}
44
45#endif
046
=== added file 'launcher/DeviceNotificationDisplayImp.cpp'
--- launcher/DeviceNotificationDisplayImp.cpp 1970-01-01 00:00:00 +0000
+++ launcher/DeviceNotificationDisplayImp.cpp 2012-08-29 08:24:20 +0000
@@ -0,0 +1,82 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright (C) 2012 Canonical Ltd
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18 */
19
20#include <gdk/gdk.h>
21#include <glib/gi18n-lib.h>
22#include <libnotify/notify.h>
23#include <sigc++/sigc++.h>
24#include <UnityCore/GLibWrapper.h>
25
26#include "DeviceNotificationDisplayImp.h"
27#include "unity-shared/IconLoader.h"
28
29namespace unity
30{
31namespace launcher
32{
33
34//
35// Start private implementation
36//
37class DeviceNotificationDisplayImp::Impl
38{
39public:
40 void Show(std::string const& icon_name, std::string const& volume_name)
41 {
42 int icon_size = 48;
43 IconLoader::GetDefault().LoadFromGIconString(icon_name, icon_size,
44 sigc::bind(sigc::mem_fun(this, &Impl::ShowNotificationWhenIconIsReady), volume_name));
45 }
46
47 void ShowNotificationWhenIconIsReady(std::string const& icon_name,
48 unsigned size,
49 glib::Object<GdkPixbuf> const& pixbuf,
50 std::string const& volume_name)
51 {
52 glib::Object<NotifyNotification> notification(notify_notification_new(volume_name.c_str(),
53 _("The drive has been successfully ejected"),
54 nullptr));
55
56 notify_notification_set_hint(notification, "x-canonical-private-synchronous", g_variant_new_boolean(TRUE));
57
58 if (GDK_IS_PIXBUF(pixbuf.RawPtr()))
59 notify_notification_set_image_from_pixbuf(notification, pixbuf);
60
61 notify_notification_show(notification, nullptr);
62 }
63};
64
65//
66// End private implementation
67//
68
69DeviceNotificationDisplayImp::DeviceNotificationDisplayImp()
70 : pimpl(new Impl)
71{}
72
73DeviceNotificationDisplayImp::~DeviceNotificationDisplayImp()
74{}
75
76void DeviceNotificationDisplayImp::Display(std::string const& icon_name, std::string const& volume_name)
77{
78 pimpl->Show(icon_name, volume_name);
79}
80
81}
82}
083
=== added file 'launcher/DeviceNotificationDisplayImp.h'
--- launcher/DeviceNotificationDisplayImp.h 1970-01-01 00:00:00 +0000
+++ launcher/DeviceNotificationDisplayImp.h 2012-08-29 08:24:20 +0000
@@ -0,0 +1,46 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright (C) 2012 Canonical Ltd
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18 */
19
20#ifndef UNITYSHELL_DEVICE_NOTIFICATION_DISPLAY_IMP_H
21#define UNITYSHELL_DEVICE_NOTIFICATION_DISPLAY_IMP_H
22
23#include "DeviceNotificationDisplay.h"
24
25namespace unity
26{
27namespace launcher
28{
29
30class DeviceNotificationDisplayImp : public DeviceNotificationDisplay
31{
32public:
33 DeviceNotificationDisplayImp();
34 virtual ~DeviceNotificationDisplayImp();
35
36 virtual void Display(std::string const& icon_name, std::string const& volume_name);
37
38private:
39 class Impl;
40 std::unique_ptr<Impl> pimpl;
41};
42
43}
44}
45
46#endif
047
=== modified file 'launcher/DevicesSettings.h'
--- launcher/DevicesSettings.h 2012-05-07 19:52:54 +0000
+++ launcher/DevicesSettings.h 2012-08-29 08:24:20 +0000
@@ -1,6 +1,6 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*2/*
3 * Copyright (C) 2010 Canonical Ltd3 * Copyright (C) 2010-12 Canonical Ltd
4 *4 *
5 * This program is free software: you can redistribute it and/or modify5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as6 * it under the terms of the GNU General Public License version 3 as
@@ -14,61 +14,39 @@
14 * You should have received a copy of the GNU General Public License14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *16 *
17 * Authored by: Andrea Azzarone <aazzarone@hotmail.it>17 * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18 */18 */
1919
20#ifndef DEVICES_SETTINGS_H20#ifndef UNITYSHELL_DEVICES_SETTINGS_H
21#define DEVICES_SETTINGS_H21#define UNITYSHELL_DEVICES_SETTINGS_H
2222
23#include <list>23#include <boost/noncopyable.hpp>
24#include <memory>
24#include <string>25#include <string>
2526
26#include <gio/gio.h>27#include <sigc++/signal.h>
27#include <boost/utility.hpp>28#include <sigc++/trackable.h>
28#include <sigc++/sigc++.h>29
29#include <UnityCore/GLibWrapper.h>30namespace unity
3031{
31namespace unity {32namespace launcher
3233{
33typedef std::list<std::string> DeviceList;34
3435class DevicesSettings : boost::noncopyable, public sigc::trackable
35class DevicesSettings : boost::noncopyable
36{36{
37public:37public:
38 typedef enum38 typedef std::shared_ptr<DevicesSettings> Ptr;
39 {39
40 NEVER = 0,40 virtual ~DevicesSettings() {};
41 ONLY_MOUNTED,41
42 ALWAYS42 virtual bool IsABlacklistedDevice(std::string const& uuid) const = 0;
4343 virtual void TryToBlacklist(std::string const& uuid) = 0;
44 } DevicesOption;44 virtual void TryToUnblacklist(std::string const& uuid) = 0;
4545
46 DevicesSettings();
47
48 static DevicesSettings& GetDefault();
49
50 void SetDevicesOption(DevicesOption devices_option);
51 DevicesOption GetDevicesOption() { return devices_option_; };
52
53 DeviceList const& GetFavorites() { return favorites_; };
54 void AddFavorite(std::string const& uuid);
55 void RemoveFavorite(std::string const& uuid);
56
57 void Changed(std::string const& key);
58
59 // Signals
60 sigc::signal<void> changed;46 sigc::signal<void> changed;
61
62private:
63 void Refresh();
64 void SaveFavorites(DeviceList const& favorites);
65
66 glib::Object<GSettings> settings_;
67 DeviceList favorites_;
68 bool ignore_signals_;
69 DevicesOption devices_option_;
70};47};
7148
72} // namespace unity49}
50}
7351
74#endif // DEVICES_SETTINGS_H52#endif
7553
=== renamed file 'launcher/DevicesSettings.cpp' => 'launcher/DevicesSettingsImp.cpp'
--- launcher/DevicesSettings.cpp 2012-05-07 19:52:54 +0000
+++ launcher/DevicesSettingsImp.cpp 2012-08-29 08:24:20 +0000
@@ -1,6 +1,6 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*2/*
3 * Copyright (C) 2010 Canonical Ltd3 * Copyright (C) 2010-12 Canonical Ltd
4 *4 *
5 * This program is free software: you can redistribute it and/or modify5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as6 * it under the terms of the GNU General Public License version 3 as
@@ -14,130 +14,138 @@
14 * You should have received a copy of the GNU General Public License14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *16 *
17 * Authored by: Andrea Azzarone <aazzarone@hotmail.it>17 * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18 */18 */
1919
20#include "DevicesSettings.h"20#include <list>
2121
22#include <algorithm>22#include <gio/gio.h>
2323#include <NuxCore/Logger.h>
24namespace unity {24
2525#include "DevicesSettingsImp.h"
26namespace {26#include <UnityCore/GLibSignal.h>
2727#include <UnityCore/GLibWrapper.h>
28const char* SETTINGS_NAME = "com.canonical.Unity.Devices";28
2929namespace unity
30void on_settings_updated(GSettings* settings,30{
31 const gchar* key,31namespace launcher
32 DevicesSettings* self);32{
3333namespace
34} // anonymous namespace34{
3535
36DevicesSettings& DevicesSettings::GetDefault()36nux::logging::Logger logger("unity.device.settings");
37{37
38 static DevicesSettings instance;38const std::string SETTINGS_NAME = "com.canonical.Unity.Devices";
39 return instance;39const std::string KEY_NAME = "blacklist";
40}40
4141}
42DevicesSettings::DevicesSettings()42
43 : settings_(g_settings_new(SETTINGS_NAME))43//
44 , ignore_signals_(false)44// Start private implementation
45 , devices_option_(ONLY_MOUNTED)45//
46{46class DevicesSettingsImp::Impl
4747{
48 g_signal_connect(settings_, "changed", G_CALLBACK(on_settings_updated), this);48public:
4949 Impl(DevicesSettingsImp* parent)
50 Refresh();50 : parent_(parent)
51}51 , settings_(g_settings_new(SETTINGS_NAME.c_str()))
5252 {
53void DevicesSettings::Refresh()53 DownloadBlacklist();
54{54 ConnectSignals();
55 gchar** favs = g_settings_get_strv(settings_, "favorites");55 }
5656
57 favorites_.clear();57 void ConnectSignals()
5858 {
59 for (int i = 0; favs[i] != NULL; i++)59 settings_changed_signal_.Connect(settings_, "changed::" + KEY_NAME, [this] (GSettings*, gchar*) {
60 favorites_.push_back(favs[i]);60 DownloadBlacklist();
6161 parent_->changed.emit();
62 g_strfreev(favs);62 });
63}63 }
6464
65void DevicesSettings::AddFavorite(std::string const& uuid)65 void DownloadBlacklist()
66{66 {
67 if (uuid.empty())67 std::shared_ptr<gchar*> downloaded_blacklist(g_settings_get_strv(settings_, KEY_NAME.c_str()), g_strfreev);
68 return;68
69 69 blacklist_.clear();
70 favorites_.push_back(uuid);70
7171 auto downloaded_blacklist_raw = downloaded_blacklist.get();
72 SaveFavorites(favorites_);72 for (int i = 0; downloaded_blacklist_raw[i]; ++i)
73 Refresh();73 blacklist_.push_back(downloaded_blacklist_raw[i]);
74}74 }
7575
76void DevicesSettings::RemoveFavorite(std::string const& uuid)76 void UploadBlacklist()
77{77 {
78 if (uuid.empty())78 const int size = blacklist_.size();
79 return;79 const char* blacklist_to_be_uploaded[size+1];
8080
81 DeviceList::iterator pos = std::find(favorites_.begin(), favorites_.end(), uuid);81 int index = 0;
82 if (pos == favorites_.end())82 for (auto item : blacklist_)
83 return;83 blacklist_to_be_uploaded[index++] = item.c_str();
8484 blacklist_to_be_uploaded[index] = nullptr;
85 favorites_.erase(pos);85
86 SaveFavorites(favorites_);86 if (!g_settings_set_strv(settings_, KEY_NAME.c_str(), blacklist_to_be_uploaded))
87 Refresh();87 {
88}88 LOG_WARNING(logger) << "Saving blacklist failed.";
8989 }
90void DevicesSettings::SaveFavorites(DeviceList const& favorites)90 }
91{91
92 const int size = favorites.size();92 bool IsABlacklistedDevice(std::string const& uuid) const
93 const char* favs[size + 1];93 {
94 favs[size] = NULL;94 auto begin = std::begin(blacklist_);
9595 auto end = std::end(blacklist_);
96 int index = 0;96 return std::find(begin, end, uuid) != end;
97 for (DeviceList::const_iterator i = favorites.begin(), end = favorites.end();97 }
98 i != end; ++i, ++index)98
99 {99 void TryToBlacklist(std::string const& uuid)
100 favs[index] = i->c_str();100 {
101 }101 if (uuid.empty() || IsABlacklistedDevice(uuid))
102102 return;
103 ignore_signals_ = true;103
104 if (!g_settings_set_strv(settings_, "favorites", favs))104 blacklist_.push_back(uuid);
105 g_warning("Saving favorites failed.");105 UploadBlacklist();
106 ignore_signals_ = false;106 }
107}107
108108 void TryToUnblacklist(std::string const& uuid)
109109 {
110void DevicesSettings::Changed(std::string const& key)110 if (uuid.empty() || !IsABlacklistedDevice(uuid))
111{111 return;
112 if (ignore_signals_)112
113 return;113 blacklist_.remove(uuid);
114 114 UploadBlacklist();
115 Refresh();115 }
116 116
117 changed.emit();117 DevicesSettingsImp* parent_;
118}118 glib::Object<GSettings> settings_;
119119 std::list<std::string> blacklist_;
120void DevicesSettings::SetDevicesOption(DevicesOption devices_option)120 glib::Signal<void, GSettings*, gchar*> settings_changed_signal_;
121{121
122 if (devices_option == devices_option_)122};
123 return;123
124124//
125 devices_option_ = devices_option;125// End private implementation
126126//
127 changed.emit();127
128}128DevicesSettingsImp::DevicesSettingsImp()
129129 : pimpl(new Impl(this))
130namespace {130{}
131131
132void on_settings_updated(GSettings* settings,132DevicesSettingsImp::~DevicesSettingsImp()
133 const gchar* key,133{}
134 DevicesSettings* self)134
135{135bool DevicesSettingsImp::IsABlacklistedDevice(std::string const& uuid) const
136 if (settings and key) {136{
137 self->Changed(key);137 return pimpl->IsABlacklistedDevice(uuid);
138 }138}
139}139
140140void DevicesSettingsImp::TryToBlacklist(std::string const& uuid)
141} // anonymous namespace141{
142142 pimpl->TryToBlacklist(uuid);
143}
144
145void DevicesSettingsImp::TryToUnblacklist(std::string const& uuid)
146{
147 pimpl->TryToUnblacklist(uuid);
148}
149
150} // namespace launcher
143} // namespace unity151} // namespace unity
144152
=== added file 'launcher/DevicesSettingsImp.h'
--- launcher/DevicesSettingsImp.h 1970-01-01 00:00:00 +0000
+++ launcher/DevicesSettingsImp.h 2012-08-29 08:24:20 +0000
@@ -0,0 +1,50 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright (C) 2012 Canonical Ltd
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18 */
19
20#ifndef UNITYSHELL_DEVICES_SETTINGS_IMP_H
21#define UNITYSHELL_DEVICES_SETTINGS_IMP_H
22
23#include "DevicesSettings.h"
24
25namespace unity
26{
27namespace launcher
28{
29
30class DevicesSettingsImp : public DevicesSettings
31{
32public:
33 typedef std::shared_ptr<DevicesSettingsImp> Ptr;
34
35 DevicesSettingsImp();
36 virtual ~DevicesSettingsImp();
37
38 virtual bool IsABlacklistedDevice(std::string const& uuid) const;
39 virtual void TryToBlacklist(std::string const& uuid);
40 virtual void TryToUnblacklist(std::string const& uuid);
41
42private:
43 class Impl;
44 std::unique_ptr<Impl> pimpl;
45};
46
47}
48}
49
50#endif
051
=== added file 'launcher/FileManagerOpener.h'
--- launcher/FileManagerOpener.h 1970-01-01 00:00:00 +0000
+++ launcher/FileManagerOpener.h 2012-08-29 08:24:20 +0000
@@ -0,0 +1,45 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright (C) 2012 Canonical Ltd
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18 */
19
20#ifndef UNITYSHELL_FILEMANAGER_OPENER_H
21#define UNITYSHELL_FILEMANAGER_OPENER_H
22
23#include <boost/noncopyable.hpp>
24#include <memory>
25#include <string>
26
27namespace unity
28{
29namespace launcher
30{
31
32class FileManagerOpener : private boost::noncopyable
33{
34public:
35 typedef std::shared_ptr<FileManagerOpener> Ptr;
36
37 virtual ~FileManagerOpener() {}
38
39 virtual void Open(std::string const& uri) = 0;
40};
41
42}
43}
44
45#endif
046
=== added file 'launcher/FileManagerOpenerImp.cpp'
--- launcher/FileManagerOpenerImp.cpp 1970-01-01 00:00:00 +0000
+++ launcher/FileManagerOpenerImp.cpp 2012-08-29 08:24:20 +0000
@@ -0,0 +1,35 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright (C) 2012 Canonical Ltd
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18 */
19
20#include <gio/gio.h>
21
22#include "FileManagerOpenerImp.h"
23
24namespace unity
25{
26namespace launcher
27{
28
29void FileManagerOpenerImp::Open(std::string const& uri)
30{
31 g_app_info_launch_default_for_uri(uri. c_str(), nullptr, nullptr);
32}
33
34}
35}
036
=== added file 'launcher/FileManagerOpenerImp.h'
--- launcher/FileManagerOpenerImp.h 1970-01-01 00:00:00 +0000
+++ launcher/FileManagerOpenerImp.h 2012-08-29 08:24:20 +0000
@@ -0,0 +1,39 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright (C) 2012 Canonical Ltd
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18 */
19
20#ifndef UNITYSHELL_FILEMANAGER_OPENER_IMP_H
21#define UNITYSHELL_FILEMANAGER_OPENER_IMP_H
22
23#include "FileManagerOpener.h"
24
25namespace unity
26{
27namespace launcher
28{
29
30class FileManagerOpenerImp : public FileManagerOpener
31{
32public:
33 virtual void Open(std::string const& uri);
34};
35
36}
37}
38
39#endif
040
=== modified file 'launcher/Launcher.cpp'
--- launcher/Launcher.cpp 2012-08-21 17:45:42 +0000
+++ launcher/Launcher.cpp 2012-08-29 08:24:20 +0000
@@ -1719,6 +1719,11 @@
1719 return _model;1719 return _model;
1720}1720}
17211721
1722void Launcher::SetDevicesSettings(DevicesSettings::Ptr devices_settings)
1723{
1724 devices_settings_ = devices_settings;
1725}
1726
1722void Launcher::EnsureIconOnScreen(AbstractLauncherIcon::Ptr selection)1727void Launcher::EnsureIconOnScreen(AbstractLauncherIcon::Ptr selection)
1723{1728{
1724 nux::Geometry const& geo = GetGeometry();1729 nux::Geometry const& geo = GetGeometry();
@@ -2581,7 +2586,7 @@
25812586
2582 for (auto it : _dnd_data.Uris())2587 for (auto it : _dnd_data.Uris())
2583 {2588 {
2584 if (g_str_has_suffix(it.c_str(), ".desktop"))2589 if (g_str_has_suffix(it.c_str(), ".desktop") || g_str_has_prefix(it.c_str(), "device://"))
2585 {2590 {
2586 _steal_drag = true;2591 _steal_drag = true;
2587 break;2592 break;
@@ -2686,7 +2691,7 @@
2686 // see if the launcher wants this one2691 // see if the launcher wants this one
2687 for (auto it : _dnd_data.Uris())2692 for (auto it : _dnd_data.Uris())
2688 {2693 {
2689 if (g_str_has_suffix(it.c_str(), ".desktop"))2694 if (g_str_has_suffix(it.c_str(), ".desktop") || g_str_has_prefix(it.c_str(), "device://"))
2690 {2695 {
2691 _steal_drag = true;2696 _steal_drag = true;
2692 break;2697 break;
@@ -2824,6 +2829,11 @@
2824 g_free(path);2829 g_free(path);
2825 }2830 }
2826 }2831 }
2832 else if (devices_settings_ && g_str_has_prefix(it.c_str(), "device://"))
2833 {
2834 const gchar* uuid = it.c_str() + 9;
2835 devices_settings_->TryToUnblacklist(uuid);
2836 }
2827 }2837 }
2828 }2838 }
2829 else if (_dnd_hovered_icon && _drag_action != nux::DNDACTION_NONE)2839 else if (_dnd_hovered_icon && _drag_action != nux::DNDACTION_NONE)
28302840
=== modified file 'launcher/Launcher.h'
--- launcher/Launcher.h 2012-08-21 17:45:42 +0000
+++ launcher/Launcher.h 2012-08-29 08:24:20 +0000
@@ -30,6 +30,7 @@
30#include "PointerBarrier.h"30#include "PointerBarrier.h"
31#include "unity-shared/AbstractIconRenderer.h"31#include "unity-shared/AbstractIconRenderer.h"
32#include "unity-shared/BackgroundEffectHelper.h"32#include "unity-shared/BackgroundEffectHelper.h"
33#include "DevicesSettings.h"
33#include "DNDCollectionWindow.h"34#include "DNDCollectionWindow.h"
34#include "DndData.h"35#include "DndData.h"
35#include "EdgeBarrierController.h"36#include "EdgeBarrierController.h"
@@ -82,6 +83,8 @@
82 void SetModel(LauncherModel::Ptr model);83 void SetModel(LauncherModel::Ptr model);
83 LauncherModel::Ptr GetModel() const;84 LauncherModel::Ptr GetModel() const;
8485
86 void SetDevicesSettings(DevicesSettings::Ptr devices_settings);
87
85 void StartKeyShowLauncher();88 void StartKeyShowLauncher();
86 void EndKeyShowLauncher();89 void EndKeyShowLauncher();
8790
@@ -393,6 +396,8 @@
393 ui::AbstractIconRenderer::Ptr icon_renderer;396 ui::AbstractIconRenderer::Ptr icon_renderer;
394 BackgroundEffectHelper bg_effect_helper_;397 BackgroundEffectHelper bg_effect_helper_;
395398
399 DevicesSettings::Ptr devices_settings_;
400
396 UBusManager ubus_;401 UBusManager ubus_;
397 glib::SourceManager sources_;402 glib::SourceManager sources_;
398403
399404
=== modified file 'launcher/LauncherController.cpp'
--- launcher/LauncherController.cpp 2012-08-27 03:00:42 +0000
+++ launcher/LauncherController.cpp 2012-08-29 08:24:20 +0000
@@ -29,7 +29,7 @@
29#include "LauncherOptions.h"29#include "LauncherOptions.h"
30#include "BamfLauncherIcon.h"30#include "BamfLauncherIcon.h"
31#include "DesktopLauncherIcon.h"31#include "DesktopLauncherIcon.h"
32#include "DeviceLauncherIcon.h"32#include "VolumeLauncherIcon.h"
33#include "FavoriteStore.h"33#include "FavoriteStore.h"
34#include "HudLauncherIcon.h"34#include "HudLauncherIcon.h"
35#include "LauncherController.h"35#include "LauncherController.h"
@@ -95,7 +95,8 @@
95 , model_(new LauncherModel())95 , model_(new LauncherModel())
96 , sort_priority_(0)96 , sort_priority_(0)
97 , volume_monitor_(new VolumeMonitorWrapper)97 , volume_monitor_(new VolumeMonitorWrapper)
98 , device_section_(volume_monitor_)98 , devices_settings_(new DevicesSettingsImp)
99 , device_section_(volume_monitor_, devices_settings_)
99 , show_desktop_icon_(false)100 , show_desktop_icon_(false)
100 , display_(display)101 , display_(display)
101 , matcher_(bamf_matcher_get_default())102 , matcher_(bamf_matcher_get_default())
@@ -267,6 +268,7 @@
267 launcher->monitor = monitor;268 launcher->monitor = monitor;
268 launcher->options = parent_->options();269 launcher->options = parent_->options();
269 launcher->SetModel(model_);270 launcher->SetModel(model_);
271 launcher->SetDevicesSettings(devices_settings_);
270272
271 nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);273 nux::HLayout* layout = new nux::HLayout(NUX_TRACKER_LOCATION);
272 layout->AddView(launcher, 1);274 layout->AddView(launcher, 1);
@@ -424,10 +426,10 @@
424 }426 }
425 case AbstractLauncherIcon::IconType::DEVICE:427 case AbstractLauncherIcon::IconType::DEVICE:
426 {428 {
427 DeviceLauncherIcon* device_icon = dynamic_cast<DeviceLauncherIcon*>(icon.GetPointer());429 auto device_icon = dynamic_cast<VolumeLauncherIcon*>(icon.GetPointer());
428430
429 if (device_icon && device_icon->CanEject())431 if (device_icon && device_icon->CanEject())
430 device_icon->Eject();432 device_icon->EjectAndShowNotification();
431 else if (device_icon && device_icon->CanStop())433 else if (device_icon && device_icon->CanStop())
432 device_icon->StopDrive();434 device_icon->StopDrive();
433435
434436
=== modified file 'launcher/LauncherController.h'
--- launcher/LauncherController.h 2012-07-27 19:32:41 +0000
+++ launcher/LauncherController.h 2012-08-29 08:24:20 +0000
@@ -32,6 +32,7 @@
32{32{
33namespace launcher33namespace launcher
34{34{
35
35class AbstractLauncherIcon;36class AbstractLauncherIcon;
36class Launcher;37class Launcher;
37class LauncherModel;38class LauncherModel;
3839
=== modified file 'launcher/LauncherControllerPrivate.h'
--- launcher/LauncherControllerPrivate.h 2012-07-25 13:42:41 +0000
+++ launcher/LauncherControllerPrivate.h 2012-08-29 08:24:20 +0000
@@ -27,6 +27,7 @@
2727
28#include "AbstractLauncherIcon.h"28#include "AbstractLauncherIcon.h"
29#include "DeviceLauncherSection.h"29#include "DeviceLauncherSection.h"
30#include "DevicesSettingsImp.h"
30#include "EdgeBarrierController.h"31#include "EdgeBarrierController.h"
31#include "LauncherController.h"32#include "LauncherController.h"
32#include "Launcher.h"33#include "Launcher.h"
@@ -126,6 +127,7 @@
126 nux::ObjectPtr<Launcher> keyboard_launcher_;127 nux::ObjectPtr<Launcher> keyboard_launcher_;
127 int sort_priority_;128 int sort_priority_;
128 AbstractVolumeMonitorWrapper::Ptr volume_monitor_;129 AbstractVolumeMonitorWrapper::Ptr volume_monitor_;
130 DevicesSettingsImp::Ptr devices_settings_;
129 DeviceLauncherSection device_section_;131 DeviceLauncherSection device_section_;
130 LauncherEntryRemoteModel remote_model_;132 LauncherEntryRemoteModel remote_model_;
131 AbstractLauncherIcon::Ptr expo_icon_;133 AbstractLauncherIcon::Ptr expo_icon_;
132134
=== added file 'launcher/Volume.h'
--- launcher/Volume.h 1970-01-01 00:00:00 +0000
+++ launcher/Volume.h 2012-08-29 08:24:20 +0000
@@ -0,0 +1,62 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright (C) 2012 Canonical Ltd
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18 */
19
20#ifndef UNITYSHELL_VOLUME_H
21#define UNITYSHELL_VOLUME_H
22
23#include <boost/noncopyable.hpp>
24#include <memory>
25#include <sigc++/signal.h>
26#include <sigc++/trackable.h>
27#include <string>
28
29namespace unity
30{
31namespace launcher
32{
33
34class Volume : private boost::noncopyable, public sigc::trackable
35{
36public:
37 typedef std::shared_ptr<Volume> Ptr;
38
39 virtual ~Volume() {}
40
41 virtual bool CanBeEjected() const = 0;
42 virtual bool CanBeRemoved() const = 0;
43 virtual bool CanBeStopped() const = 0;
44 virtual std::string GetName() const = 0;
45 virtual std::string GetIconName() const = 0;
46 virtual std::string GetIdentifier() const = 0;
47 virtual bool HasSiblings() const = 0;
48 virtual bool IsMounted() const = 0;
49
50 virtual void EjectAndShowNotification() = 0;
51 virtual void MountAndOpenInFileManager() = 0;
52 virtual void StopDrive() = 0;
53 virtual void Unmount() = 0;
54
55 sigc::signal<void> changed;
56 sigc::signal<void> removed;
57};
58
59}
60}
61
62#endif
063
=== added file 'launcher/VolumeImp.cpp'
--- launcher/VolumeImp.cpp 1970-01-01 00:00:00 +0000
+++ launcher/VolumeImp.cpp 2012-08-29 08:24:20 +0000
@@ -0,0 +1,294 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright (C) 2012 Canonical Ltd
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18 */
19
20#include <gio/gio.h>
21#include <gtk/gtk.h>
22#include <UnityCore/GLibSignal.h>
23
24#include "VolumeImp.h"
25
26namespace unity
27{
28namespace launcher
29{
30
31//
32// Start private implementation
33//
34
35class VolumeImp::Impl
36{
37public:
38 Impl(glib::Object<GVolume> const& volume,
39 FileManagerOpener::Ptr const& file_manager_opener,
40 DeviceNotificationDisplay::Ptr const& device_notification_display,
41 VolumeImp* parent)
42 : parent_(parent)
43 , cancellable_(g_cancellable_new())
44 , volume_(volume)
45 , file_manager_opener_(file_manager_opener)
46 , device_notification_display_(device_notification_display)
47 {
48 signal_volume_changed_.Connect(volume_, "changed", [this] (GVolume*) {
49 parent_->changed.emit();
50 });
51
52 signal_volume_removed_.Connect(volume_, "removed", [this] (GVolume*) {
53 parent_->removed.emit();
54 });
55 }
56
57 ~Impl()
58 {
59 g_cancellable_cancel(cancellable_);
60 }
61
62 bool CanBeEjected() const
63 {
64 return g_volume_can_eject(volume_) != FALSE;
65 }
66
67 bool CanBeRemoved() const
68 {
69 glib::Object<GDrive> drive(g_volume_get_drive(volume_));
70 return drive && g_drive_is_media_removable(drive) != FALSE;
71 }
72
73 bool CanBeStopped() const
74 {
75 glib::Object<GDrive> drive(g_volume_get_drive(volume_));
76 return drive && g_drive_can_stop(drive) != FALSE;
77 }
78
79 std::string GetName() const
80 {
81 return glib::String(g_volume_get_name(volume_)).Str();
82 }
83
84 std::string GetIconName() const
85 {
86 glib::Object<GIcon> icon(g_volume_get_icon(volume_));
87 return glib::String(g_icon_to_string(icon)).Str();
88 }
89
90 std::string GetIdentifier() const
91 {
92 return glib::String(g_volume_get_identifier(volume_, G_VOLUME_IDENTIFIER_KIND_UUID)).Str();
93 }
94
95 bool HasSiblings() const
96 {
97 glib::Object<GDrive> drive(g_volume_get_drive(volume_));
98
99 if (!drive)
100 return false;
101
102 GList* volumes = g_drive_get_volumes(drive);
103 bool has_sibilings = volumes && volumes->next;
104
105 if (volumes)
106 g_list_free_full(volumes, g_object_unref);
107
108 return has_sibilings;
109 }
110
111 bool IsMounted() const
112 {
113 glib::Object<GMount> mount(g_volume_get_mount(volume_));
114 return static_cast<bool>(mount);
115 }
116
117 void EjectAndShowNotification()
118 {
119 if (!CanBeEjected())
120 return;
121
122 glib::Object<GMountOperation> mount_op(gtk_mount_operation_new(nullptr));
123
124 g_volume_eject_with_operation(volume_,
125 (GMountUnmountFlags)0,
126 mount_op,
127 nullptr,
128 (GAsyncReadyCallback)OnEjectReady,
129 this);
130 }
131
132 static void OnEjectReady(GObject* object, GAsyncResult* result, Impl* self)
133 {
134 if (g_volume_eject_with_operation_finish(self->volume_, result, nullptr))
135 {
136 self->device_notification_display_->Display(self->GetIconName(), self->GetName());
137 }
138 }
139
140 void MountAndOpenInFileManager()
141 {
142 if (!IsMounted())
143 MountAndOnFinishOpenInFileManager();
144 else
145 OpenInFileManager();
146 }
147
148 void MountAndOnFinishOpenInFileManager()
149 {
150 g_volume_mount(volume_,
151 (GMountMountFlags) 0,
152 nullptr,
153 nullptr,
154 (GAsyncReadyCallback) &Impl::OnMountFinish,
155 this);
156 }
157
158 static void OnMountFinish(GObject* object,
159 GAsyncResult* result,
160 Impl* self)
161 {
162 if (g_volume_mount_finish(self->volume_, result, nullptr))
163 self->OpenInFileManager();
164 }
165
166 void OpenInFileManager()
167 {
168 file_manager_opener_->Open(GetUri());
169 }
170
171 std::string GetUri()
172 {
173 glib::Object<GMount> mount(g_volume_get_mount(volume_));
174 glib::Object<GFile> root(g_mount_get_root(mount));
175
176 if (root.IsType(G_TYPE_FILE))
177 return glib::String(g_file_get_uri(root)).Str();
178 else
179 return std::string();
180 }
181
182 void StopDrive()
183 {
184 if (!CanBeStopped())
185 return;
186
187 glib::Object<GDrive> drive(g_volume_get_drive(volume_));
188 glib::Object<GMountOperation> mount_op(gtk_mount_operation_new(NULL));
189
190 g_drive_stop(drive,
191 (GMountUnmountFlags)0,
192 mount_op,
193 nullptr, nullptr, nullptr);
194 }
195
196 void Unmount()
197 {
198 if (!IsMounted())
199 return;
200
201 glib::Object<GMount> mount(g_volume_get_mount(volume_));
202 glib::Object<GMountOperation> op(gtk_mount_operation_new(nullptr));
203
204 g_mount_unmount_with_operation(mount,
205 (GMountUnmountFlags)0,
206 op,
207 nullptr, nullptr, nullptr);
208 }
209
210 VolumeImp* parent_;
211 glib::Object<GCancellable> cancellable_;
212 glib::Object<GVolume> volume_;
213 FileManagerOpener::Ptr file_manager_opener_;
214 DeviceNotificationDisplay::Ptr device_notification_display_;
215
216 glib::Signal<void, GVolume*> signal_volume_changed_;
217 glib::Signal<void, GVolume*> signal_volume_removed_;
218};
219
220//
221// End private implementation
222//
223
224VolumeImp::VolumeImp(glib::Object<GVolume> const& volume,
225 FileManagerOpener::Ptr const& file_manager_opener,
226 DeviceNotificationDisplay::Ptr const& device_notification_display)
227 : pimpl(new Impl(volume, file_manager_opener, device_notification_display, this))
228{}
229
230VolumeImp::~VolumeImp()
231{}
232
233bool VolumeImp::CanBeEjected() const
234{
235 return pimpl->CanBeEjected();
236}
237
238bool VolumeImp::CanBeRemoved() const
239{
240 return pimpl->CanBeRemoved();
241}
242
243bool VolumeImp::CanBeStopped() const
244{
245 return pimpl->CanBeStopped();
246}
247
248std::string VolumeImp::GetName() const
249{
250 return pimpl->GetName();
251}
252
253std::string VolumeImp::GetIconName() const
254{
255 return pimpl->GetIconName();
256}
257
258std::string VolumeImp::GetIdentifier() const
259{
260 return pimpl->GetIdentifier();
261}
262
263bool VolumeImp::HasSiblings() const
264{
265 return pimpl->HasSiblings();
266}
267
268bool VolumeImp::IsMounted() const
269{
270 return pimpl->IsMounted();
271}
272
273void VolumeImp::MountAndOpenInFileManager()
274{
275 pimpl->MountAndOpenInFileManager();
276}
277
278void VolumeImp::EjectAndShowNotification()
279{
280 pimpl->EjectAndShowNotification();
281}
282
283void VolumeImp::StopDrive()
284{
285 pimpl->StopDrive();
286}
287
288void VolumeImp::Unmount()
289{
290 pimpl->Unmount();
291}
292
293} // namespace launcher
294} // namespace unity
0295
=== added file 'launcher/VolumeImp.h'
--- launcher/VolumeImp.h 1970-01-01 00:00:00 +0000
+++ launcher/VolumeImp.h 2012-08-29 08:24:20 +0000
@@ -0,0 +1,68 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright (C) 2012 Canonical Ltd
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18 */
19
20#ifndef UNITYSHELL_VOLUME_IMP_H
21#define UNITYSHELL_VOLUME_IMP_H
22
23#include <memory>
24
25#include <UnityCore/GLibWrapper.h>
26
27#include "DeviceNotificationDisplay.h"
28#include "FileManagerOpener.h"
29#include "Volume.h"
30
31namespace unity
32{
33namespace launcher
34{
35
36class VolumeImp : public Volume
37{
38public:
39 typedef std::shared_ptr<VolumeImp> Ptr;
40
41 VolumeImp(glib::Object<GVolume> const& volume,
42 FileManagerOpener::Ptr const& file_manager_opener,
43 DeviceNotificationDisplay::Ptr const& device_notification_display);
44 virtual ~VolumeImp();
45
46 virtual bool CanBeEjected() const;
47 virtual bool CanBeRemoved() const;
48 virtual bool CanBeStopped() const;
49 virtual std::string GetName() const;
50 virtual std::string GetIconName() const;
51 virtual std::string GetIdentifier() const;
52 virtual bool HasSiblings() const;
53 virtual bool IsMounted() const;
54
55 virtual void EjectAndShowNotification();
56 virtual void MountAndOpenInFileManager();
57 virtual void StopDrive();
58 virtual void Unmount();
59
60private:
61 class Impl;
62 std::unique_ptr<Impl> pimpl;
63};
64
65}
66}
67
68#endif
069
=== renamed file 'launcher/DeviceLauncherIcon.cpp' => 'launcher/VolumeLauncherIcon.cpp'
--- launcher/DeviceLauncherIcon.cpp 2012-08-21 17:50:55 +0000
+++ launcher/VolumeLauncherIcon.cpp 2012-08-29 08:24:20 +0000
@@ -15,21 +15,17 @@
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *16 *
17 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>17 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
18 * Andrea Azzarone <andrea.azzarone@canonical.com>
18 */19 */
1920
20#include "DeviceLauncherIcon.h"
21
22#include <algorithm>
23#include <list>
2421
25#include <glib/gi18n-lib.h>22#include <glib/gi18n-lib.h>
26#include <libnotify/notify.h>
27#include <NuxCore/Logger.h>23#include <NuxCore/Logger.h>
24#include <UnityCore/GLibSignal.h>
2825
29#include "DevicesSettings.h"26#include "DevicesSettings.h"
30#include "unity-shared/IconLoader.h"27#include "Volume.h"
31#include "unity-shared/ubus-server.h"28#include "VolumeLauncherIcon.h"
32#include "unity-shared/UBusMessages.h"
3329
34namespace unity30namespace unity
35{31{
@@ -44,381 +40,265 @@
4440
45}41}
4642
47DeviceLauncherIcon::DeviceLauncherIcon(glib::Object<GVolume> const& volume)43//
44// Start private implementation
45//
46class VolumeLauncherIcon::Impl
47{
48public:
49 typedef glib::Signal<void, DbusmenuMenuitem*, int> ItemSignal;
50
51 Impl(Volume::Ptr const& volume,
52 DevicesSettings::Ptr const& devices_settings,
53 VolumeLauncherIcon* parent)
54 : parent_(parent)
55 , volume_(volume)
56 , devices_settings_(devices_settings)
57 {
58 UpdateIcon();
59 UpdateVisibility();
60 ConnectSignals();
61 }
62
63 ~Impl()
64 {
65 volume_changed_conn_.disconnect();
66 volume_removed_conn_.disconnect();
67 settings_changed_conn_.disconnect();
68 }
69
70 void UpdateIcon()
71 {
72 parent_->tooltip_text = volume_->GetName();
73 parent_->icon_name = volume_->GetIconName();
74
75 parent_->SetQuirk(Quirk::RUNNING, false);
76 }
77
78 void UpdateVisibility()
79 {
80 UpdateKeepInLauncher();
81 parent_->SetQuirk(Quirk::VISIBLE, keep_in_launcher_);
82 }
83
84 void UpdateKeepInLauncher()
85 {
86 auto identifier = volume_->GetIdentifier();
87 keep_in_launcher_ = !devices_settings_->IsABlacklistedDevice(identifier);
88 }
89
90 void ConnectSignals()
91 {
92 volume_changed_conn_ = volume_->changed.connect(sigc::mem_fun(this, &Impl::OnVolumeChanged));
93 volume_removed_conn_ = volume_->removed.connect(sigc::mem_fun(this, &Impl::OnVolumeRemoved));
94 settings_changed_conn_ = devices_settings_->changed.connect(sigc::mem_fun(this, &Impl::OnSettingsChanged));
95 }
96
97 void OnVolumeChanged()
98 {
99 UpdateIcon();
100 }
101
102 void OnVolumeRemoved()
103 {
104 if (devices_settings_->IsABlacklistedDevice(volume_->GetIdentifier()))
105 devices_settings_->TryToUnblacklist(volume_->GetIdentifier());
106
107 parent_->Remove();
108 }
109
110 void OnSettingsChanged()
111 {
112 UpdateVisibility();
113 }
114
115 bool CanEject() const
116 {
117 return volume_->CanBeEjected();
118 }
119
120 void EjectAndShowNotification()
121 {
122 return volume_->EjectAndShowNotification();
123 }
124
125 bool CanStop() const
126 {
127 return volume_->CanBeStopped();
128 }
129
130 void StopDrive()
131 {
132 volume_->StopDrive();
133 }
134
135 void ActivateLauncherIcon(ActionArg arg)
136 {
137 parent_->SimpleLauncherIcon::ActivateLauncherIcon(arg);
138 volume_->MountAndOpenInFileManager();
139 }
140
141 MenuItemsVector GetMenus()
142 {
143 MenuItemsVector result;
144
145 AppendUnlockFromLauncherItem(result);
146 AppendOpenItem(result);
147 AppendEjectItem(result);
148 AppendSafelyRemoveItem(result);
149 AppendUnmountItem(result);
150
151 return result;
152 }
153
154 void AppendUnlockFromLauncherItem(MenuItemsVector& menu)
155 {
156 if (volume_->GetIdentifier().empty())
157 return;
158
159 glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
160
161 dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Unlock from Launcher"));
162 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
163 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
164
165 gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
166 auto identifier = volume_->GetIdentifier();
167 devices_settings_->TryToBlacklist(identifier);
168 }));
169
170 menu.push_back(menu_item);
171 }
172
173 void AppendOpenItem(MenuItemsVector& menu)
174 {
175 glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
176
177 dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Open"));
178 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
179 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
180
181 gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
182 volume_->MountAndOpenInFileManager();
183 }));
184
185 menu.push_back(menu_item);
186 }
187
188 void AppendEjectItem(MenuItemsVector& menu)
189 {
190 if (!volume_->CanBeEjected())
191 return;
192
193 glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
194
195 dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, volume_->HasSiblings() ? _("Eject parent drive") : _("Eject"));
196 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
197 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
198
199 gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
200 volume_->EjectAndShowNotification();
201 }));
202
203 menu.push_back(menu_item);
204 }
205
206 void AppendSafelyRemoveItem(MenuItemsVector& menu)
207 {
208 if (!volume_->CanBeStopped())
209 return;
210
211 glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
212
213 dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, volume_->HasSiblings() ? _("Safely remove parent drive") : _("Safely remove"));
214 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
215 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
216
217 gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
218 volume_->StopDrive();
219 }));
220
221 menu.push_back(menu_item);
222 }
223
224 void AppendUnmountItem(MenuItemsVector& menu)
225 {
226 if (!volume_->IsMounted() || volume_->CanBeEjected() || volume_->CanBeStopped())
227 return;
228
229 glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
230
231 dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Unmount"));
232 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
233 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
234
235 gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
236 volume_->Unmount();
237 }));
238
239 menu.push_back(menu_item);
240 }
241
242 VolumeLauncherIcon* parent_;
243 bool keep_in_launcher_;
244 Volume::Ptr volume_;
245 DevicesSettings::Ptr devices_settings_;
246
247 glib::SignalManager gsignals_;
248 sigc::connection settings_changed_conn_;
249 sigc::connection volume_changed_conn_;
250 sigc::connection volume_removed_conn_;
251};
252
253//
254// End private implementation
255//
256
257VolumeLauncherIcon::VolumeLauncherIcon(Volume::Ptr const& volume,
258 DevicesSettings::Ptr const& devices_settings)
48 : SimpleLauncherIcon(IconType::DEVICE)259 : SimpleLauncherIcon(IconType::DEVICE)
49 , volume_(volume)260 , pimpl_(new Impl(volume, devices_settings, this))
50{261{}
51 gsignals_.Add<void, GVolume*>(volume, "changed", sigc::mem_fun(this, &DeviceLauncherIcon::OnVolumeChanged));262
52 DevicesSettings::GetDefault().changed.connect(sigc::mem_fun(this, &DeviceLauncherIcon::OnSettingsChanged));263VolumeLauncherIcon::~VolumeLauncherIcon()
53264{}
54 // Checks if in favorites!265
55 glib::String uuid(g_volume_get_identifier(volume_, G_VOLUME_IDENTIFIER_KIND_UUID));266bool VolumeLauncherIcon::CanEject() const
56 DeviceList favorites = DevicesSettings::GetDefault().GetFavorites();267{
57 DeviceList::iterator pos = std::find(favorites.begin(), favorites.end(), uuid.Str());268 return pimpl_->CanEject();
58269}
59 keep_in_launcher_ = pos != favorites.end();270
60271void VolumeLauncherIcon::EjectAndShowNotification()
61 UpdateDeviceIcon();272{
62 UpdateVisibility();273 pimpl_->EjectAndShowNotification();
63}274}
64275
65void DeviceLauncherIcon::OnVolumeChanged(GVolume* volume)276bool VolumeLauncherIcon::CanStop() const
66{277{
67 if (!G_IS_VOLUME(volume))278 return pimpl_->CanStop();
68 return;279}
69280
70 changed_timeout_.reset(new glib::Timeout(volume_changed_timeout, [this]() {281void VolumeLauncherIcon::StopDrive()
71 UpdateDeviceIcon();282{
72 UpdateVisibility();283 return pimpl_->StopDrive();
73 return false;284}
74 }));285
75}286void VolumeLauncherIcon::ActivateLauncherIcon(ActionArg arg)
76287{
77void DeviceLauncherIcon::UpdateVisibility()288 pimpl_->ActivateLauncherIcon(arg);
78{289}
79 switch (DevicesSettings::GetDefault().GetDevicesOption())290
80 {291AbstractLauncherIcon::MenuItemsVector VolumeLauncherIcon::GetMenus()
81 case DevicesSettings::NEVER:292{
82 SetQuirk(Quirk::VISIBLE, false);293 return pimpl_->GetMenus();
83 break;294}
84 case DevicesSettings::ONLY_MOUNTED:295
85 if (keep_in_launcher_)296//
86 {297// Introspection
87 SetQuirk(Quirk::VISIBLE, true);298//
88 }299std::string VolumeLauncherIcon::GetName() const
89 else300{
90 {301 return "VolumeLauncherIcon";
91 glib::Object<GMount> mount(g_volume_get_mount(volume_));
92 SetQuirk(Quirk::VISIBLE, mount);
93 }
94 break;
95 case DevicesSettings::ALWAYS:
96 SetQuirk(Quirk::VISIBLE, true);
97 break;
98 }
99}
100
101void DeviceLauncherIcon::UpdateDeviceIcon()
102{
103 name_ = glib::String(g_volume_get_name(volume_)).Str();
104
105 glib::Object<GIcon> icon(g_volume_get_icon(volume_));
106 glib::String icon_string(g_icon_to_string(icon));
107
108 tooltip_text = name_;
109 icon_name = icon_string.Str();
110
111 SetQuirk(Quirk::RUNNING, false);
112}
113
114bool
115DeviceLauncherIcon::CanEject()
116{
117 return g_volume_can_eject(volume_);
118}
119
120bool
121DeviceLauncherIcon::CanStop()
122{
123 return g_drive_can_stop(g_volume_get_drive(volume_));
124}
125
126AbstractLauncherIcon::MenuItemsVector DeviceLauncherIcon::GetMenus()
127{
128 MenuItemsVector result;
129 glib::Object<DbusmenuMenuitem> menu_item;
130 glib::Object<GDrive> drive(g_volume_get_drive(volume_));
131 typedef glib::Signal<void, DbusmenuMenuitem*, int> ItemSignal;
132
133 // "Lock to Launcher"/"Unlock from Launcher" item
134 if (DevicesSettings::GetDefault().GetDevicesOption() == DevicesSettings::ONLY_MOUNTED
135 && drive && !g_drive_is_media_removable (drive))
136 {
137 menu_item = dbusmenu_menuitem_new();
138
139 dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, !keep_in_launcher_ ? _("Lock to Launcher") : _("Unlock from Launcher"));
140 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
141 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
142
143 gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
144 sigc::mem_fun(this, &DeviceLauncherIcon::OnTogglePin)));
145 result.push_back(menu_item);
146 }
147
148 // "Open" item
149 menu_item = dbusmenu_menuitem_new();
150
151 dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Open"));
152 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
153 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
154
155 gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
156 ActivateLauncherIcon(ActionArg(ActionArg::OTHER, 0));
157 }));
158
159 result.push_back(menu_item);
160
161 // "Eject" item
162 if (drive && g_drive_can_eject(drive))
163 {
164 menu_item = dbusmenu_menuitem_new();
165
166 GList *list = g_drive_get_volumes(drive);
167 if (list)
168 {
169 if (!list->next) // If the list has only one item
170 dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Eject"));
171 else
172 dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Eject parent drive"));
173
174 g_list_free_full(list, g_object_unref);
175 }
176
177 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
178 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
179
180 gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
181 Eject();
182 }));
183
184 result.push_back(menu_item);
185 }
186
187 // "Safely remove" item
188 if (drive && g_drive_can_stop(drive))
189 {
190 menu_item = dbusmenu_menuitem_new();
191
192 GList *list = g_drive_get_volumes(drive);
193 if (list)
194 {
195 if (!list->next) // If the list has only one item
196 dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Safely remove"));
197 else
198 dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Safely remove parent drive"));
199
200 g_list_free_full(list, g_object_unref);
201 }
202
203 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
204 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
205
206 gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
207 StopDrive();
208 }));
209
210 result.push_back(menu_item);
211 }
212
213 // "Unmount" item
214 if (!g_volume_can_eject(volume_)) // Don't need Unmount if can Eject
215 {
216 glib::Object<GMount> mount(g_volume_get_mount(volume_));
217
218 if (mount && g_mount_can_unmount(mount))
219 {
220 menu_item = dbusmenu_menuitem_new();
221
222 dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, _("Unmount"));
223 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
224 dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
225
226 gsignals_.Add(new ItemSignal(menu_item, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, [this] (DbusmenuMenuitem*, int) {
227 Unmount();
228 }));
229
230 result.push_back(menu_item);
231 }
232 }
233
234 return result;
235}
236
237void DeviceLauncherIcon::ShowMount(GMount* mount)
238{
239 if (G_IS_MOUNT(mount))
240 {
241 glib::Object<GFile> root(g_mount_get_root(mount));
242
243 if (G_IS_FILE(root.RawPtr()))
244 {
245 glib::String uri(g_file_get_uri(root));
246 glib::Error error;
247
248 g_app_info_launch_default_for_uri(uri.Value(), NULL, &error);
249
250 if (error)
251 {
252 LOG_WARNING(logger) << "Cannot open volume '" << name_
253 << "': Unable to show " << uri
254 << ": " << error;
255 }
256 }
257 else
258 {
259 LOG_WARNING(logger) << "Cannot open volume '" << name_
260 << "': Mount has no root";
261 }
262 }
263 else
264 {
265 LOG_WARNING(logger) << "Cannot open volume '" << name_
266 << "': Mount-point is invalid";
267 }
268}
269
270void DeviceLauncherIcon::ActivateLauncherIcon(ActionArg arg)
271{
272 SimpleLauncherIcon::ActivateLauncherIcon(arg);
273 SetQuirk(Quirk::STARTING, true);
274
275 glib::Object<GMount> mount(g_volume_get_mount(volume_));
276
277 if (G_IS_MOUNT(mount.RawPtr()))
278 ShowMount(mount);
279 else
280 g_volume_mount(volume_,
281 (GMountMountFlags)0,
282 NULL,
283 NULL,
284 (GAsyncReadyCallback)&DeviceLauncherIcon::OnMountReady,
285 this);
286}
287
288void DeviceLauncherIcon::OnMountReady(GObject* object,
289 GAsyncResult* result,
290 DeviceLauncherIcon* self)
291{
292 glib::Error error;
293
294 if (g_volume_mount_finish(self->volume_, result, &error))
295 {
296 glib::Object<GMount> mount(g_volume_get_mount(self->volume_));
297 self->ShowMount(mount);
298 }
299 else
300 {
301 LOG_WARNING(logger) << "Cannot open volume '" << self->name_ << "' : " <<
302 (error ? error.Message() : "Mount operation failed");
303 }
304}
305
306void DeviceLauncherIcon::OnEjectReady(GObject* object,
307 GAsyncResult* result,
308 DeviceLauncherIcon* self)
309{
310 if (g_volume_eject_with_operation_finish(self->volume_, result, NULL))
311 {
312 IconLoader::GetDefault().LoadFromGIconString(self->icon_name(), 48,
313 sigc::bind(sigc::mem_fun(self, &DeviceLauncherIcon::ShowNotification), self->name_));
314 }
315}
316
317void DeviceLauncherIcon::ShowNotification(std::string const& icon_name,
318 unsigned size,
319 glib::Object<GdkPixbuf> const& pixbuf,
320 std::string const& name)
321{
322 glib::Object<NotifyNotification> notification(notify_notification_new(name.c_str(),
323 _("The drive has been successfully ejected"),
324 NULL));
325
326 notify_notification_set_hint(notification,
327 "x-canonical-private-synchronous",
328 g_variant_new_boolean(TRUE));
329
330 if (GDK_IS_PIXBUF(pixbuf.RawPtr()))
331 notify_notification_set_image_from_pixbuf(notification, pixbuf);
332
333 notify_notification_show(notification, NULL);
334}
335
336void DeviceLauncherIcon::Eject()
337{
338 glib::Object<GMountOperation> mount_op(gtk_mount_operation_new(NULL));
339
340 g_volume_eject_with_operation(volume_,
341 (GMountUnmountFlags)0,
342 mount_op,
343 NULL,
344 (GAsyncReadyCallback)OnEjectReady,
345 this);
346}
347
348void DeviceLauncherIcon::OnTogglePin(DbusmenuMenuitem* item, int time)
349{
350 glib::String uuid(g_volume_get_identifier(volume_, G_VOLUME_IDENTIFIER_KIND_UUID));
351
352 keep_in_launcher_ = !keep_in_launcher_;
353
354 if (!keep_in_launcher_)
355 {
356 // If the volume is not mounted hide the icon
357 glib::Object<GMount> mount(g_volume_get_mount(volume_));
358
359 if (!mount)
360 SetQuirk(Quirk::VISIBLE, false);
361
362 // Remove from favorites
363 if (!uuid.Str().empty())
364 DevicesSettings::GetDefault().RemoveFavorite(uuid.Str());
365 }
366 else
367 {
368 if (!uuid.Str().empty())
369 DevicesSettings::GetDefault().AddFavorite(uuid.Str());
370 }
371}
372
373void DeviceLauncherIcon::OnUnmountReady(GObject* object,
374 GAsyncResult* result,
375 DeviceLauncherIcon* self)
376{
377 if (G_IS_MOUNT(object))
378 g_mount_unmount_with_operation_finish(G_MOUNT(object), result, NULL);
379}
380
381void DeviceLauncherIcon::Unmount()
382{
383 glib::Object<GMount> mount(g_volume_get_mount(volume_));
384
385 if (mount)
386 {
387 glib::Object<GMountOperation> op(gtk_mount_operation_new(NULL));
388
389 g_mount_unmount_with_operation(mount, (GMountUnmountFlags)0, op, NULL,
390 (GAsyncReadyCallback)OnUnmountReady, this);
391 }
392}
393
394void DeviceLauncherIcon::OnRemoved()
395{
396 Remove();
397}
398
399void DeviceLauncherIcon::StopDrive()
400{
401 glib::Object<GDrive> drive(g_volume_get_drive(volume_));
402 glib::Object<GMountOperation> mount_op(gtk_mount_operation_new(NULL));
403
404 g_drive_stop(drive, (GMountUnmountFlags)0, mount_op, NULL, NULL, NULL);
405}
406
407void DeviceLauncherIcon::OnSettingsChanged()
408{
409 // Checks if in favourites!
410 glib::String uuid(g_volume_get_identifier(volume_, G_VOLUME_IDENTIFIER_KIND_UUID));
411 DeviceList favorites = DevicesSettings::GetDefault().GetFavorites();
412 DeviceList::iterator pos = std::find(favorites.begin(), favorites.end(), uuid.Str());
413
414 keep_in_launcher_ = pos != favorites.end();
415
416 UpdateVisibility();
417}
418
419std::string DeviceLauncherIcon::GetName() const
420{
421 return "DeviceLauncherIcon";
422}302}
423303
424} // namespace launcher304} // namespace launcher
425305
=== renamed file 'launcher/DeviceLauncherIcon.h' => 'launcher/VolumeLauncherIcon.h'
--- launcher/DeviceLauncherIcon.h 2012-08-21 17:59:29 +0000
+++ launcher/VolumeLauncherIcon.h 2012-08-29 08:24:20 +0000
@@ -15,15 +15,14 @@
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *16 *
17 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>17 * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
18 * Andrea Azzarone <andrea.azzarone@canonical.com>
18 */19 */
1920
20#ifndef _DEVICE_LAUNCHER_ICON_H__H21#ifndef UNITYSHELL_VOLUME_LAUNCHER_ICON_H
21#define _DEVICE_LAUNCHER_ICON_H__H22#define UNITYSHELL_VOLUME_LAUNCHER_ICON_H
2223
23#include <gio/gio.h>24#include "Volume.h"
24#include <UnityCore/GLibWrapper.h>25#include "DevicesSettings.h"
25#include <UnityCore/GLibSignal.h>
26
27#include "SimpleLauncherIcon.h"26#include "SimpleLauncherIcon.h"
2827
29namespace unity28namespace unity
@@ -31,48 +30,33 @@
31namespace launcher30namespace launcher
32{31{
3332
34class DeviceLauncherIcon : public SimpleLauncherIcon33class VolumeLauncherIcon : public SimpleLauncherIcon
35{34{
36public:35public:
37 typedef nux::ObjectPtr<DeviceLauncherIcon> Ptr;36 typedef nux::ObjectPtr<VolumeLauncherIcon> Ptr;
3837
39 DeviceLauncherIcon(glib::Object<GVolume> const& volume);38 VolumeLauncherIcon(Volume::Ptr const& volume,
4039 DevicesSettings::Ptr const& devices_settings);
41 void OnRemoved();40 virtual ~VolumeLauncherIcon();
42 bool CanEject();41
43 bool CanStop();42 bool CanEject() const; // TODO: rename to public virtual bool IsTrashable();
44 void Eject();43 void EjectAndShowNotification(); // TODO: rename to private virtual void DoDropToTrash();
44 bool CanStop() const;
45 void StopDrive();45 void StopDrive();
46 MenuItemsVector GetMenus();
4647
47protected:48protected:
48 MenuItemsVector GetMenus();49 virtual void ActivateLauncherIcon(ActionArg arg);
49 std::string GetName() const;50
5051 // Introspection
51private:52 virtual std::string GetName() const;
52 void UpdateVisibility();53
53 void UpdateDeviceIcon();54private:
54 void ActivateLauncherIcon(ActionArg arg);55 class Impl;
55 void ShowMount(GMount* mount);56 std::shared_ptr<Impl> pimpl_;
56 void Unmount();
57 void OnTogglePin(DbusmenuMenuitem* item, int time);
58 void OnSettingsChanged();
59 void ShowNotification(std::string const&, unsigned, glib::Object<GdkPixbuf> const&, std::string const&);
60 void OnVolumeChanged(GVolume* volume);
61 static void OnChanged(GVolume* volume, DeviceLauncherIcon* self);
62 static void OnMountReady(GObject* object, GAsyncResult* result, DeviceLauncherIcon* self);
63 static void OnEjectReady(GObject* object, GAsyncResult* result, DeviceLauncherIcon* self);
64 static void OnUnmountReady(GObject* object, GAsyncResult* result, DeviceLauncherIcon* self);
65
66private:
67 glib::Source::UniquePtr changed_timeout_;
68 glib::Object<GVolume> volume_;
69 glib::SignalManager gsignals_;
70
71 std::string name_;
72 bool keep_in_launcher_;
73};57};
7458
75}59}
76} // namespace unity60}
7761
78#endif // _DEVICE_LAUNCHER_ICON_H__H62#endif
7963
=== modified file 'plugins/unityshell/src/unityshell.cpp'
--- plugins/unityshell/src/unityshell.cpp 2012-08-27 19:08:38 +0000
+++ plugins/unityshell/src/unityshell.cpp 2012-08-29 08:24:20 +0000
@@ -29,7 +29,6 @@
29#include "Launcher.h"29#include "Launcher.h"
30#include "LauncherIcon.h"30#include "LauncherIcon.h"
31#include "LauncherController.h"31#include "LauncherController.h"
32#include "DevicesSettings.h"
33#include "PluginAdapter.h"32#include "PluginAdapter.h"
34#include "QuicklistManager.h"33#include "QuicklistManager.h"
35#include "StartupNotifyService.h"34#include "StartupNotifyService.h"
@@ -281,7 +280,6 @@
281 optionSetIconSizeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));280 optionSetIconSizeNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
282 optionSetAutohideAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));281 optionSetAutohideAnimationNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
283 optionSetDashBlurExperimentalNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));282 optionSetDashBlurExperimentalNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
284 optionSetDevicesOptionNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
285 optionSetShortcutOverlayNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));283 optionSetShortcutOverlayNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
286 optionSetShowDesktopIconNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));284 optionSetShowDesktopIconNotify(boost::bind(&UnityScreen::optionChanged, this, _1, _2));
287 optionSetShowLauncherInitiate(boost::bind(&UnityScreen::showLauncherKeyInitiate, this, _1, _2, _3));285 optionSetShowLauncherInitiate(boost::bind(&UnityScreen::showLauncherKeyInitiate, this, _1, _2, _3));
@@ -2925,9 +2923,6 @@
2925 case UnityshellOptions::AutomaximizeValue:2923 case UnityshellOptions::AutomaximizeValue:
2926 PluginAdapter::Default()->SetCoverageAreaBeforeAutomaximize(optionGetAutomaximizeValue() / 100.0f);2924 PluginAdapter::Default()->SetCoverageAreaBeforeAutomaximize(optionGetAutomaximizeValue() / 100.0f);
2927 break;2925 break;
2928 case UnityshellOptions::DevicesOption:
2929 unity::DevicesSettings::GetDefault().SetDevicesOption((unity::DevicesSettings::DevicesOption) optionGetDevicesOption());
2930 break;
2931 case UnityshellOptions::AltTabTimeout:2926 case UnityshellOptions::AltTabTimeout:
2932 switcher_controller_->detail_on_timeout = optionGetAltTabTimeout();2927 switcher_controller_->detail_on_timeout = optionGetAltTabTimeout();
2933 case UnityshellOptions::AltTabBiasViewport:2928 case UnityshellOptions::AltTabBiasViewport:
29342929
=== modified file 'plugins/unityshell/unityshell.xml.in'
--- plugins/unityshell/unityshell.xml.in 2012-08-07 10:41:46 +0000
+++ plugins/unityshell/unityshell.xml.in 2012-08-29 08:24:20 +0000
@@ -394,26 +394,6 @@
394 <default>75</default>394 <default>75</default>
395 </option>395 </option>
396396
397 <option name="devices_option" type="int">
398 <_short>Show Devices</_short>
399 <_long>Show devices in the launcher</_long>
400 <min>0</min>
401 <max>2</max>
402 <default>1</default>
403 <desc>
404 <value>0</value>
405 <_name>Never</_name>
406 </desc>
407 <desc>
408 <value>1</value>
409 <_name>Only Mounted</_name>
410 </desc>
411 <desc>
412 <value>2</value>
413 <_name>Always</_name>
414 </desc>
415 </option>
416
417 <option name="shortcut_overlay" type="bool">397 <option name="shortcut_overlay" type="bool">
418 <_short>Enable Shortcut Hints Overlay</_short>398 <_short>Enable Shortcut Hints Overlay</_short>
419 <_long>Enable Shortcut Hints Overlay</_long>399 <_long>Enable Shortcut Hints Overlay</_long>
420400
=== modified file 'po/POTFILES.in'
--- po/POTFILES.in 2012-08-23 06:15:27 +0000
+++ po/POTFILES.in 2012-08-29 08:24:20 +0000
@@ -11,11 +11,12 @@
11launcher/BFBLauncherIcon.cpp11launcher/BFBLauncherIcon.cpp
12launcher/BamfLauncherIcon.cpp12launcher/BamfLauncherIcon.cpp
13launcher/DesktopLauncherIcon.cpp13launcher/DesktopLauncherIcon.cpp
14launcher/DeviceLauncherIcon.cpp14launcher/DeviceNotificationShowerImp.cpp
15launcher/LauncherController.cpp15launcher/LauncherController.cpp
16launcher/SoftwareCenterLauncherIcon.cpp16launcher/SoftwareCenterLauncherIcon.cpp
17launcher/SpacerLauncherIcon.cpp17launcher/SpacerLauncherIcon.cpp
18launcher/TrashLauncherIcon.cpp18launcher/TrashLauncherIcon.cpp
19launcher/VolumeLauncherIcon.cpp
19panel/PanelMenuView.cpp20panel/PanelMenuView.cpp
20plugins/networkarearegion/networkarearegion.xml.in21plugins/networkarearegion/networkarearegion.xml.in
21plugins/unity-mt-grab-handles/unitymtgrabhandles.xml.in22plugins/unity-mt-grab-handles/unitymtgrabhandles.xml.in
2223
=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 2012-08-28 12:23:15 +0000
+++ tests/CMakeLists.txt 2012-08-29 08:24:20 +0000
@@ -227,6 +227,9 @@
227 test_switcher_model.cpp227 test_switcher_model.cpp
228 test_texture_cache.cpp228 test_texture_cache.cpp
229 test_thumbnail_generator.cpp229 test_thumbnail_generator.cpp
230 test_volume_imp.cpp
231 test_volume_launcher_icon.cpp
232 gmockmount.c
230 gmockvolume.c233 gmockvolume.c
231 ${CMAKE_SOURCE_DIR}/dash/AbstractPlacesGroup.cpp234 ${CMAKE_SOURCE_DIR}/dash/AbstractPlacesGroup.cpp
232 ${CMAKE_SOURCE_DIR}/dash/DashViewPrivate.cpp235 ${CMAKE_SOURCE_DIR}/dash/DashViewPrivate.cpp
@@ -258,14 +261,15 @@
258 ${CMAKE_SOURCE_DIR}/launcher/DNDCollectionWindow.cpp261 ${CMAKE_SOURCE_DIR}/launcher/DNDCollectionWindow.cpp
259 ${CMAKE_SOURCE_DIR}/launcher/Decaymulator.cpp262 ${CMAKE_SOURCE_DIR}/launcher/Decaymulator.cpp
260 ${CMAKE_SOURCE_DIR}/launcher/DesktopLauncherIcon.cpp263 ${CMAKE_SOURCE_DIR}/launcher/DesktopLauncherIcon.cpp
261 ${CMAKE_SOURCE_DIR}/launcher/DeviceLauncherIcon.cpp
262 ${CMAKE_SOURCE_DIR}/launcher/DeviceLauncherSection.cpp264 ${CMAKE_SOURCE_DIR}/launcher/DeviceLauncherSection.cpp
263 ${CMAKE_SOURCE_DIR}/launcher/DevicesSettings.cpp265 ${CMAKE_SOURCE_DIR}/launcher/DeviceNotificationDisplayImp.cpp
266 ${CMAKE_SOURCE_DIR}/launcher/DevicesSettingsImp.cpp
264 ${CMAKE_SOURCE_DIR}/launcher/DndData.cpp267 ${CMAKE_SOURCE_DIR}/launcher/DndData.cpp
265 ${CMAKE_SOURCE_DIR}/launcher/EdgeBarrierController.cpp268 ${CMAKE_SOURCE_DIR}/launcher/EdgeBarrierController.cpp
266 ${CMAKE_SOURCE_DIR}/launcher/FavoriteStore.cpp269 ${CMAKE_SOURCE_DIR}/launcher/FavoriteStore.cpp
267 ${CMAKE_SOURCE_DIR}/launcher/FavoriteStoreGSettings.cpp270 ${CMAKE_SOURCE_DIR}/launcher/FavoriteStoreGSettings.cpp
268 ${CMAKE_SOURCE_DIR}/launcher/FavoriteStorePrivate.cpp271 ${CMAKE_SOURCE_DIR}/launcher/FavoriteStorePrivate.cpp
272 ${CMAKE_SOURCE_DIR}/launcher/FileManagerOpenerImp.cpp
269 ${CMAKE_SOURCE_DIR}/launcher/HudLauncherIcon.cpp273 ${CMAKE_SOURCE_DIR}/launcher/HudLauncherIcon.cpp
270 ${CMAKE_SOURCE_DIR}/launcher/Launcher.cpp274 ${CMAKE_SOURCE_DIR}/launcher/Launcher.cpp
271 ${CMAKE_SOURCE_DIR}/launcher/LauncherController.cpp275 ${CMAKE_SOURCE_DIR}/launcher/LauncherController.cpp
@@ -296,6 +300,8 @@
296 ${CMAKE_SOURCE_DIR}/launcher/SwitcherView.cpp300 ${CMAKE_SOURCE_DIR}/launcher/SwitcherView.cpp
297 ${CMAKE_SOURCE_DIR}/launcher/Tooltip.cpp301 ${CMAKE_SOURCE_DIR}/launcher/Tooltip.cpp
298 ${CMAKE_SOURCE_DIR}/launcher/TrashLauncherIcon.cpp302 ${CMAKE_SOURCE_DIR}/launcher/TrashLauncherIcon.cpp
303 ${CMAKE_SOURCE_DIR}/launcher/VolumeImp.cpp
304 ${CMAKE_SOURCE_DIR}/launcher/VolumeLauncherIcon.cpp
299 ${CMAKE_SOURCE_DIR}/launcher/VolumeMonitorWrapper.cpp305 ${CMAKE_SOURCE_DIR}/launcher/VolumeMonitorWrapper.cpp
300 ${CMAKE_SOURCE_DIR}/unity-shared/Animator.cpp306 ${CMAKE_SOURCE_DIR}/unity-shared/Animator.cpp
301 ${CMAKE_SOURCE_DIR}/unity-shared/BackgroundEffectHelper.cpp307 ${CMAKE_SOURCE_DIR}/unity-shared/BackgroundEffectHelper.cpp
302308
=== added file 'tests/gmockmount.c'
--- tests/gmockmount.c 1970-01-01 00:00:00 +0000
+++ tests/gmockmount.c 2012-08-29 08:24:20 +0000
@@ -0,0 +1,167 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright 2012 Canonical Ltd.
4 *
5 * This program is free software: you can redistribute it and/or modify it
6 * under the terms of the GNU Lesser General Public License version 3, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranties of
11 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12 * PURPOSE. See the applicable version of the GNU Lesser General Public
13 * License for more details.
14 *
15 * You should have received a copy of both the GNU Lesser General Public
16 * License version 3 along with this program. If not, see
17 * <http://www.gnu.org/licenses/>
18 *
19 * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
20 *
21 */
22
23#include <glib.h>
24
25#include "gmockmount.h"
26
27static void g_mock_mount_iface_init (GMountIface *iface);
28
29G_DEFINE_TYPE_WITH_CODE (GMockMount, g_mock_mount, G_TYPE_OBJECT,
30 G_IMPLEMENT_INTERFACE (G_TYPE_MOUNT,
31 g_mock_mount_iface_init))
32
33static void
34g_mock_mount_finalize (GObject *object)
35{
36 G_OBJECT_CLASS (g_mock_mount_parent_class)->finalize (object);
37}
38
39static void
40g_mock_mount_dispose (GObject *object)
41{
42 G_OBJECT_CLASS (g_mock_mount_parent_class)->dispose (object);
43}
44
45
46static void
47g_mock_mount_class_init (GMockMountClass *klass)
48{
49 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
50
51 gobject_class->finalize = g_mock_mount_finalize;
52 gobject_class->dispose = g_mock_mount_dispose;
53}
54
55static void
56g_mock_mount_init (GMockMount *mock_mount)
57{}
58
59GMockMount *
60g_mock_mount_new ()
61{
62 GMockMount *mount;
63
64 mount = g_object_new (G_TYPE_MOCK_MOUNT, NULL);
65
66 return mount;
67}
68
69static GFile *
70g_mock_mount_get_root (GMount *mount)
71{
72 return g_file_new_for_path (ROOT_FILE_PATH);
73}
74
75static GIcon *
76g_mock_mount_get_icon (GMount *mount)
77{
78 return NULL;
79}
80
81static char *
82g_mock_mount_get_uuid (GMount *mount)
83{
84 return g_strdup ("");
85}
86
87static char *
88g_mock_mount_get_name (GMount *mount)
89{
90 return g_strdup ("");
91}
92
93static GDrive *
94g_mock_mount_get_drive (GMount *mount)
95{
96 return NULL;
97}
98
99static GVolume *
100g_mock_mount_get_volume (GMount *mount)
101{
102 return NULL;
103}
104
105static gboolean
106g_mock_mount_can_unmount (GMount *mount)
107{
108 return TRUE;
109}
110
111static gboolean
112g_mock_mount_can_eject (GMount *mount)
113{
114 return FALSE;
115}
116
117static void
118g_mock_mount_unmount (GMount *mount,
119 GMountUnmountFlags flags,
120 GCancellable *cancellable,
121 GAsyncReadyCallback callback,
122 gpointer user_data)
123{
124}
125
126static gboolean
127g_mock_mount_unmount_finish (GMount *mount,
128 GAsyncResult *result,
129 GError **error)
130{
131 return TRUE;
132}
133
134static void
135g_mock_mount_eject (GMount *mount,
136 GMountUnmountFlags flags,
137 GCancellable *cancellable,
138 GAsyncReadyCallback callback,
139 gpointer user_data)
140{
141}
142
143static gboolean
144g_mock_mount_eject_finish (GMount *mount,
145 GAsyncResult *result,
146 GError **error)
147{
148 return TRUE;
149}
150
151
152static void
153g_mock_mount_iface_init (GMountIface *iface)
154{
155 iface->get_root = g_mock_mount_get_root;
156 iface->get_name = g_mock_mount_get_name;
157 iface->get_icon = g_mock_mount_get_icon;
158 iface->get_uuid = g_mock_mount_get_uuid;
159 iface->get_drive = g_mock_mount_get_drive;
160 iface->get_volume = g_mock_mount_get_volume;
161 iface->can_unmount = g_mock_mount_can_unmount;
162 iface->can_eject = g_mock_mount_can_eject;
163 iface->unmount = g_mock_mount_unmount;
164 iface->unmount_finish = g_mock_mount_unmount_finish;
165 iface->eject = g_mock_mount_eject;
166 iface->eject_finish = g_mock_mount_eject_finish;
167}
0168
=== added file 'tests/gmockmount.h'
--- tests/gmockmount.h 1970-01-01 00:00:00 +0000
+++ tests/gmockmount.h 2012-08-29 08:24:20 +0000
@@ -0,0 +1,55 @@
1// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2/*
3 * Copyright 2012 Canonical Ltd.
4 *
5 * This program is free software: you can redistribute it and/or modify it
6 * under the terms of the GNU Lesser General Public License version 3, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranties of
11 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
12 * PURPOSE. See the applicable version of the GNU Lesser General Public
13 * License for more details.
14 *
15 * You should have received a copy of both the GNU Lesser General Public
16 * License version 3 along with this program. If not, see
17 * <http://www.gnu.org/licenses/>
18 *
19 * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
20 *
21 */
22
23#ifndef UNITYSHELL_G_MOCK_MOUNT_H
24#define UNITYSHELL_G_MOCK_MOUNT_H
25
26#include <gio/gio.h>
27
28G_BEGIN_DECLS
29
30#define ROOT_FILE_PATH "/some/directory/testfile"
31#define ROOT_FILE_URI "file://" ROOT_FILE_PATH
32
33#define G_TYPE_MOCK_MOUNT (g_mock_mount_get_type ())
34#define G_MOCK_MOUNT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_MOCK_MOUNT, GMockMount))
35#define G_MOCK_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_MOCK_MOUNT, GMockMountClass))
36#define G_IS_MOCK_MOUNT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_MOCK_MOUNT))
37#define G_IS_MOCK_MOUNT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_MOCK_MOUNT))
38
39typedef struct _GMockMount GMockMount;
40typedef struct _GMockMountClass GMockMountClass;
41
42struct _GMockMount {
43 GObject parent;
44};
45
46struct _GMockMountClass {
47 GObjectClass parent_class;
48};
49
50GType g_mock_mount_get_type (void) G_GNUC_CONST;
51GMockMount * g_mock_mount_new ();
52
53G_END_DECLS
54
55#endif // UNITYSHELL_G_MOCK_MOUNT_H
056
=== modified file 'tests/gmockvolume.c'
--- tests/gmockvolume.c 2012-07-18 22:47:34 +0000
+++ tests/gmockvolume.c 2012-08-29 08:24:20 +0000
@@ -22,13 +22,13 @@
2222
23#include <glib.h>23#include <glib.h>
2424
25#include "gmockmount.h"
25#include "gmockvolume.h"26#include "gmockvolume.h"
2627
27static void g_mock_volume_volume_iface_init (GVolumeIface *iface);28static void g_mock_volume_iface_init (GVolumeIface *iface);
2829
29G_DEFINE_TYPE_WITH_CODE (GMockVolume, g_mock_volume, G_TYPE_OBJECT,30G_DEFINE_TYPE_WITH_CODE (GMockVolume, g_mock_volume, G_TYPE_OBJECT,
30 G_IMPLEMENT_INTERFACE (G_TYPE_VOLUME,31 G_IMPLEMENT_INTERFACE (G_TYPE_VOLUME, g_mock_volume_iface_init))
31 g_mock_volume_volume_iface_init))
3232
33static void33static void
34g_mock_volume_finalize (GObject *object)34g_mock_volume_finalize (GObject *object)
@@ -37,44 +37,119 @@
37}37}
3838
39static void39static void
40g_mock_volume_dispose (GObject *object)
41{
42 GMockVolume *self = G_MOCK_VOLUME (object);
43
44 self->can_eject = FALSE;
45
46 if (self->name)
47 {
48 g_free(self->name);
49 self->name = NULL;
50 }
51
52 if (self->icon)
53 {
54 g_object_unref(self->icon);
55 self->icon = NULL;
56 }
57
58 if (self->uuid)
59 {
60 g_free(self->uuid);
61 self->uuid = NULL;
62 }
63
64 if (self->mount)
65 {
66 g_object_unref(self->mount);
67 self->mount = NULL;
68 }
69
70 G_OBJECT_CLASS (g_mock_volume_parent_class)->dispose (object);
71}
72
73
74static void
40g_mock_volume_class_init (GMockVolumeClass *klass)75g_mock_volume_class_init (GMockVolumeClass *klass)
41{76{
42 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);77 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
4378
44 gobject_class->finalize = g_mock_volume_finalize;79 gobject_class->finalize = g_mock_volume_finalize;
80 gobject_class->dispose = g_mock_volume_dispose;
45}81}
4682
47static void83static void
48g_mock_volume_init (GMockVolume *mock_volume)84g_mock_volume_init (GMockVolume *mock_volume)
49{85{
86 mock_volume->name = g_strdup("");
87 mock_volume->icon = g_icon_new_for_string("", NULL);
88 mock_volume->uuid = g_strdup("");
89 mock_volume->mount = NULL;
50}90}
5191
52GMockVolume *92GMockVolume *
53g_mock_volume_new ()93g_mock_volume_new ()
54{94{
55 GMockVolume *volume;95 GMockVolume *volume;
56 96
57 volume = g_object_new (G_TYPE_MOCK_VOLUME, NULL);97 volume = g_object_new (G_TYPE_MOCK_VOLUME, NULL);
5898
59 return volume;99 return volume;
60}100}
61101
102void
103g_mock_volume_set_name (GMockVolume *volume, const char* name)
104{
105 if (volume->name)
106 g_free(volume->name);
107
108 volume->name = g_strdup (name);
109}
110
62static char *111static char *
63g_mock_volume_get_name (GVolume *volume)112g_mock_volume_get_name (GVolume *volume)
64{113{
65 return g_strdup ("");114 GMockVolume *self = G_MOCK_VOLUME (volume);
66}115 return g_strdup (self->name);
116}
117
118void
119g_mock_volume_set_icon (GMockVolume *volume, GIcon *icon)
120{
121 if (volume->icon)
122 g_object_unref(volume->icon);
123
124 volume->icon = icon;
125}
126
67127
68static GIcon *128static GIcon *
69g_mock_volume_get_icon (GVolume *volume)129g_mock_volume_get_icon (GVolume *volume)
70{130{
71 return g_icon_new_for_string("", NULL);131 GMockVolume *self = G_MOCK_VOLUME (volume);
132
133 if (self->icon)
134 return g_object_ref (self->icon);
135 else
136 return NULL;
137}
138
139void
140g_mock_volume_set_uuid (GMockVolume *volume, const char* uuid)
141{
142 if (volume->uuid)
143 g_free(volume->uuid);
144
145 volume->uuid = g_strdup (uuid);
72}146}
73147
74static char *148static char *
75g_mock_volume_get_uuid (GVolume *volume)149g_mock_volume_get_uuid (GVolume *volume)
76{150{
77 return NULL;151 GMockVolume *self = G_MOCK_VOLUME (volume);
152 return g_strdup (self->uuid);
78}153}
79154
80static GDrive *155static GDrive *
@@ -83,10 +158,23 @@
83 return NULL;158 return NULL;
84}159}
85160
161void
162g_mock_volume_set_mount (GMockVolume *volume, GMount *mount)
163{
164 if (volume->mount)
165 g_object_unref(volume->mount);
166
167 volume->mount = mount;
168}
169
86static GMount *170static GMount *
87g_mock_volume_get_mount (GVolume *volume)171g_mock_volume_get_mount (GVolume *volume)
88{172{
89 return NULL;173 GMockVolume *self = G_MOCK_VOLUME (volume);
174 if (self->mount)
175 return g_object_ref (self->mount);
176 else
177 return NULL;
90}178}
91179
92static gboolean180static gboolean
@@ -98,7 +186,14 @@
98static gboolean186static gboolean
99g_mock_volume_can_eject (GVolume *volume)187g_mock_volume_can_eject (GVolume *volume)
100{188{
101 return FALSE;189 GMockVolume *self = G_MOCK_VOLUME (volume);
190 return self->can_eject;
191}
192
193void
194g_mock_volume_set_can_eject (GMockVolume* mock_volume, gboolean can_eject)
195{
196 mock_volume->can_eject = can_eject;
102}197}
103198
104static gboolean199static gboolean
@@ -115,6 +210,11 @@
115 GAsyncReadyCallback callback,210 GAsyncReadyCallback callback,
116 gpointer user_data)211 gpointer user_data)
117{212{
213 g_mock_volume_set_mount(G_MOCK_VOLUME(volume), G_MOUNT(g_mock_mount_new()));
214
215 callback(NULL,
216 G_ASYNC_RESULT (g_simple_async_result_new (NULL, NULL, NULL, NULL)),
217 user_data);
118}218}
119219
120static gboolean220static gboolean
@@ -132,7 +232,10 @@
132 GAsyncReadyCallback callback,232 GAsyncReadyCallback callback,
133 gpointer user_data)233 gpointer user_data)
134{234{
135}235
236 callback(NULL,
237 G_ASYNC_RESULT (g_simple_async_result_new (NULL, NULL, NULL, NULL)),
238 user_data);}
136239
137static gboolean240static gboolean
138g_mock_volume_eject_finish (GVolume *volume,241g_mock_volume_eject_finish (GVolume *volume,
@@ -146,6 +249,11 @@
146g_mock_volume_get_identifier (GVolume *volume,249g_mock_volume_get_identifier (GVolume *volume,
147 const gchar *kind)250 const gchar *kind)
148{251{
252 GMockVolume *self = G_MOCK_VOLUME (volume);
253
254 if (!g_strcmp0 (kind, G_VOLUME_IDENTIFIER_KIND_UUID))
255 return g_strdup (self->uuid);
256
149 return NULL;257 return NULL;
150}258}
151259
@@ -156,7 +264,7 @@
156}264}
157265
158static void266static void
159g_mock_volume_volume_iface_init (GVolumeIface *iface)267g_mock_volume_iface_init (GVolumeIface *iface)
160{268{
161 iface->get_name = g_mock_volume_get_name;269 iface->get_name = g_mock_volume_get_name;
162 iface->get_icon = g_mock_volume_get_icon;270 iface->get_icon = g_mock_volume_get_icon;
@@ -173,4 +281,3 @@
173 iface->get_identifier = g_mock_volume_get_identifier;281 iface->get_identifier = g_mock_volume_get_identifier;
174 iface->enumerate_identifiers = g_mock_volume_enumerate_identifiers;282 iface->enumerate_identifiers = g_mock_volume_enumerate_identifiers;
175}283}
176
177284
=== modified file 'tests/gmockvolume.h'
--- tests/gmockvolume.h 2012-07-18 22:47:34 +0000
+++ tests/gmockvolume.h 2012-08-29 08:24:20 +0000
@@ -38,14 +38,26 @@
3838
39struct _GMockVolume {39struct _GMockVolume {
40 GObject parent;40 GObject parent;
41
42 gboolean can_eject;
43 char *name;
44 GIcon *icon;
45 char *uuid;
46 GMount *mount;
41};47};
4248
43struct _GMockVolumeClass {49struct _GMockVolumeClass {
44 GObjectClass parent_class;50 GObjectClass parent_class;
45};51};
4652
47GType g_mock_volume_get_type (void) G_GNUC_CONST;53GType g_mock_volume_get_type (void) G_GNUC_CONST;
48GMockVolume * g_mock_volume_new ();54GMockVolume * g_mock_volume_new ();
55
56void g_mock_volume_set_can_eject (GMockVolume* volume, gboolean can_eject);
57void g_mock_volume_set_name (GMockVolume *volume, const char *name);
58void g_mock_volume_set_icon (GMockVolume *volume, GIcon *icon);
59void g_mock_volume_set_uuid (GMockVolume *volume, const char *uuid);
60void g_mock_volume_set_mount (GMockVolume *volume, GMount *mount);
4961
50G_END_DECLS62G_END_DECLS
5163
5264
=== modified file 'tests/test_device_launcher_section.cpp'
--- tests/test_device_launcher_section.cpp 2012-07-18 22:47:34 +0000
+++ tests/test_device_launcher_section.cpp 2012-08-29 08:24:20 +0000
@@ -24,6 +24,7 @@
24using namespace testing;24using namespace testing;
2525
26#include "DeviceLauncherSection.h"26#include "DeviceLauncherSection.h"
27#include "DevicesSettings.h"
27#include "AbstractVolumeMonitorWrapper.h"28#include "AbstractVolumeMonitorWrapper.h"
28using namespace unity;29using namespace unity;
29using namespace unity::launcher;30using namespace unity::launcher;
@@ -74,12 +75,20 @@
74 glib::Object<GVolume> volume2;75 glib::Object<GVolume> volume2;
75};76};
7677
78class MockDevicesSettings : public DevicesSettings
79{
80 MOCK_CONST_METHOD1(IsABlacklistedDevice, bool(std::string const& uuid));
81 MOCK_METHOD1(TryToBlacklist, void(std::string const& uuid));
82 MOCK_METHOD1(TryToUnblacklist, void(std::string const& uuid));
83};
84
77class TestDeviceLauncherSection : public Test85class TestDeviceLauncherSection : public Test
78{86{
79public:87public:
80 TestDeviceLauncherSection()88 TestDeviceLauncherSection()
81 : monitor_(new MockVolumeMonitorWrapper)89 : monitor_(new MockVolumeMonitorWrapper)
82 , section_(monitor_)90 , devices_settings_(new MockDevicesSettings)
91 , section_(monitor_, devices_settings_)
83 {}92 {}
8493
85 void SetUp()94 void SetUp()
@@ -89,6 +98,7 @@
89 }98 }
9099
91 MockVolumeMonitorWrapper::Ptr monitor_;100 MockVolumeMonitorWrapper::Ptr monitor_;
101 DevicesSettings::Ptr devices_settings_;
92 DeviceLauncherSection section_;102 DeviceLauncherSection section_;
93};103};
94104
95105
=== added file 'tests/test_volume_imp.cpp'
--- tests/test_volume_imp.cpp 1970-01-01 00:00:00 +0000
+++ tests/test_volume_imp.cpp 2012-08-29 08:24:20 +0000
@@ -0,0 +1,163 @@
1/*
2 * Copyright 2012 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * version 3 along with this program. If not, see
15 * <http://www.gnu.org/licenses/>
16 *
17 * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18 */
19
20#include <memory>
21
22#include <gmock/gmock.h>
23using namespace testing;
24
25#include "gmockmount.h"
26#include "gmockvolume.h"
27#include "launcher/VolumeImp.h"
28#include "test_utils.h"
29using namespace unity;
30
31namespace
32{
33
34class MockFileManagerOpener : public launcher::FileManagerOpener
35{
36public:
37 typedef std::shared_ptr<MockFileManagerOpener> Ptr;
38
39 MOCK_METHOD1(Open, void(std::string const& uri));
40};
41
42class MockDeviceNotificationDisplay : public launcher::DeviceNotificationDisplay
43{
44public:
45 typedef std::shared_ptr<MockDeviceNotificationDisplay> Ptr;
46
47 MOCK_METHOD2(Display, void(std::string const& icon_name, std::string const& device_name));
48};
49
50class TestVolumeImp : public Test
51{
52public:
53 void SetUp()
54 {
55 gvolume_ = g_mock_volume_new();
56 file_manager_opener_.reset(new MockFileManagerOpener);
57 device_notification_display_.reset(new MockDeviceNotificationDisplay);
58 volume_.reset(new launcher::VolumeImp(glib::Object<GVolume>(G_VOLUME(gvolume_.RawPtr()), glib::AddRef()),
59 file_manager_opener_, device_notification_display_));
60 }
61
62 glib::Object<GMockVolume> gvolume_;
63 MockFileManagerOpener::Ptr file_manager_opener_;
64 MockDeviceNotificationDisplay::Ptr device_notification_display_;
65 launcher::VolumeImp::Ptr volume_;
66};
67
68TEST_F(TestVolumeImp, TestCtor)
69{
70 EXPECT_FALSE(volume_->IsMounted());
71}
72
73TEST_F(TestVolumeImp, TestCanBeEjected)
74{
75 EXPECT_FALSE(volume_->CanBeEjected());
76
77 g_mock_volume_set_can_eject(gvolume_, TRUE);
78 EXPECT_TRUE(volume_->CanBeEjected());
79}
80
81TEST_F(TestVolumeImp, TestGetName)
82{
83 std::string const volume_name("Test Device");
84
85 // g_mock_volume_set_name is equivalent to
86 // EXPECT_CALL(gvolume_, g_volume_get_name) ...
87 g_mock_volume_set_name(gvolume_, volume_name.c_str());
88 EXPECT_EQ(volume_->GetName(), volume_name);
89}
90
91TEST_F(TestVolumeImp, TestGetIconName)
92{
93 std::string const icon_name("gnome-dev-cdrom");
94
95 g_mock_volume_set_icon(gvolume_, g_icon_new_for_string(icon_name.c_str(), NULL));
96 EXPECT_EQ(volume_->GetIconName(), icon_name);
97}
98
99TEST_F(TestVolumeImp, TestGetIdentifier)
100{
101 std::string const uuid("0123456789abc");
102
103 g_mock_volume_set_uuid(gvolume_, uuid.c_str());
104 EXPECT_EQ(volume_->GetIdentifier(), uuid);
105}
106
107TEST_F(TestVolumeImp, TestIsMounted)
108{
109 g_mock_volume_set_mount(gvolume_, nullptr);
110 ASSERT_FALSE(volume_->IsMounted());
111
112 g_mock_volume_set_mount(gvolume_, G_MOUNT(g_mock_mount_new()));
113 EXPECT_TRUE(volume_->IsMounted());
114}
115
116TEST_F(TestVolumeImp, TestEjectAndShowNotification)
117{
118 g_mock_volume_set_can_eject(gvolume_, TRUE);
119
120 EXPECT_CALL(*device_notification_display_, Display(volume_->GetIconName(), volume_->GetName()))
121 .Times(1);
122
123 volume_->EjectAndShowNotification();
124}
125
126TEST_F(TestVolumeImp, TestMountAndOpenInFileManager)
127{
128 EXPECT_CALL(*file_manager_opener_, Open(ROOT_FILE_URI))
129 .Times(1);
130
131 volume_->MountAndOpenInFileManager();
132 EXPECT_TRUE(volume_->IsMounted());
133
134 EXPECT_CALL(*file_manager_opener_, Open(ROOT_FILE_URI))
135 .Times(1);
136
137 volume_->MountAndOpenInFileManager();
138 EXPECT_TRUE(volume_->IsMounted());
139}
140
141TEST_F(TestVolumeImp, TestChangedSignal)
142{
143 bool callback_called = false;
144 volume_->changed.connect([&]() {
145 callback_called = true;
146 });
147
148 g_signal_emit_by_name(gvolume_, "changed", nullptr);
149 Utils::WaitUntil(callback_called);
150}
151
152TEST_F(TestVolumeImp, TestRemovedSignal)
153{
154 bool callback_called = false;
155 volume_->removed.connect([&]() {
156 callback_called = true;
157 });
158
159 g_signal_emit_by_name(gvolume_, "removed", nullptr);
160 Utils::WaitUntil(callback_called);
161}
162
163}
0164
=== added file 'tests/test_volume_launcher_icon.cpp'
--- tests/test_volume_launcher_icon.cpp 1970-01-01 00:00:00 +0000
+++ tests/test_volume_launcher_icon.cpp 2012-08-29 08:24:20 +0000
@@ -0,0 +1,498 @@
1/*
2 * Copyright 2012 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * version 3 along with this program. If not, see
15 * <http://www.gnu.org/licenses/>
16 *
17 * Authored by: Andrea Azzarone <andrea.azzarone@canonical.com>
18 */
19
20#include <gmock/gmock.h>
21using namespace testing;
22
23#include "launcher/DevicesSettings.h"
24#include "launcher/Volume.h"
25#include "launcher/VolumeLauncherIcon.h"
26#include "test_utils.h"
27using namespace unity;
28using namespace unity::launcher;
29
30namespace
31{
32
33class MockVolume : public Volume
34{
35public:
36 typedef std::shared_ptr<MockVolume> Ptr;
37
38 MOCK_CONST_METHOD0(CanBeRemoved, bool(void));
39 MOCK_CONST_METHOD0(CanBeStopped, bool(void));
40 MOCK_CONST_METHOD0(GetName, std::string(void));
41 MOCK_CONST_METHOD0(GetIconName, std::string(void));
42 MOCK_CONST_METHOD0(GetIdentifier, std::string(void));
43 MOCK_CONST_METHOD0(HasSiblings, bool(void));
44 MOCK_CONST_METHOD0(CanBeEjected, bool(void));
45 MOCK_CONST_METHOD0(IsMounted, bool(void));
46
47 MOCK_METHOD0(EjectAndShowNotification, void(void));
48 MOCK_METHOD0(MountAndOpenInFileManager, void(void));
49 MOCK_METHOD0(StopDrive, void(void));
50 MOCK_METHOD0(Unmount, void(void));
51};
52
53class MockDevicesSettings : public DevicesSettings
54{
55public:
56 typedef std::shared_ptr<MockDevicesSettings> Ptr;
57
58 MOCK_CONST_METHOD1(IsABlacklistedDevice, bool(std::string const& uuid));
59 MOCK_METHOD1(TryToBlacklist, void(std::string const& uuid));
60 MOCK_METHOD1(TryToUnblacklist, void(std::string const& uuid));
61};
62
63
64class TestVolumeLauncherIcon : public Test
65{
66public:
67 virtual void SetUp()
68 {
69 volume_.reset(new MockVolume);
70 settings_.reset(new MockDevicesSettings);
71
72 SetupVolumeDefaultBehavior();
73 SetupSettingsDefaultBehavior();
74 }
75
76 void CreateIcon()
77 {
78 icon_ = new VolumeLauncherIcon(volume_, settings_);
79 }
80
81 void SetupSettingsDefaultBehavior()
82 {
83 EXPECT_CALL(*settings_, IsABlacklistedDevice(_))
84 .WillRepeatedly(Return(false));
85 }
86
87 void SetupVolumeDefaultBehavior()
88 {
89 EXPECT_CALL(*volume_, CanBeRemoved())
90 .WillRepeatedly(Return(false));
91
92 EXPECT_CALL(*volume_, CanBeStopped())
93 .WillRepeatedly(Return(false));
94
95 EXPECT_CALL(*volume_, GetName())
96 .WillRepeatedly(Return("Test Name"));
97
98 EXPECT_CALL(*volume_, GetIconName())
99 .WillRepeatedly(Return("Test Icon Name"));
100
101 EXPECT_CALL(*volume_, GetIdentifier())
102 .WillRepeatedly(Return("Test Identifier"));
103
104 EXPECT_CALL(*volume_, HasSiblings())
105 .WillRepeatedly(Return(false));
106
107 EXPECT_CALL(*volume_, CanBeEjected())
108 .WillRepeatedly(Return(false));
109
110 EXPECT_CALL(*volume_, IsMounted())
111 .WillRepeatedly(Return(true));
112 }
113
114 glib::Object<DbusmenuMenuitem> GetMenuItemAtIndex(int index)
115 {
116 auto menuitems = icon_->GetMenus();
117 auto menuitem = menuitems.begin();
118 std::advance(menuitem, index);
119
120 return *menuitem;
121 }
122
123 MockVolume::Ptr volume_;
124 MockDevicesSettings::Ptr settings_;
125 VolumeLauncherIcon::Ptr icon_;
126};
127
128TEST_F(TestVolumeLauncherIcon, TestIconType)
129{
130 CreateIcon();
131 EXPECT_EQ(icon_->GetIconType(), AbstractLauncherIcon::IconType::DEVICE);
132}
133
134TEST_F(TestVolumeLauncherIcon, TestQuirks)
135{
136 CreateIcon();
137
138 EXPECT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::RUNNING));
139}
140
141TEST_F(TestVolumeLauncherIcon, TestTooltipText)
142{
143 CreateIcon();
144
145 ASSERT_EQ(icon_->tooltip_text, "Test Name");
146}
147
148TEST_F(TestVolumeLauncherIcon, TestIconName)
149{
150 CreateIcon();
151
152 ASSERT_EQ(icon_->icon_name, "Test Icon Name");
153}
154
155TEST_F(TestVolumeLauncherIcon, TestVisibility_InitiallyMountedVolume)
156{
157 CreateIcon();
158
159 EXPECT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
160}
161
162TEST_F(TestVolumeLauncherIcon, TestVisibility_InitiallyMountedBlacklistedVolume)
163{
164 EXPECT_CALL(*settings_, IsABlacklistedDevice(_))
165 .WillRepeatedly(Return(true));
166
167 CreateIcon();
168
169 ASSERT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
170}
171
172
173TEST_F(TestVolumeLauncherIcon, TestVisibility_InitiallyUnmountedVolume)
174{
175 EXPECT_CALL(*volume_, IsMounted())
176 .WillRepeatedly(Return(false));
177
178 CreateIcon();
179
180 EXPECT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
181}
182
183
184TEST_F(TestVolumeLauncherIcon, TestVisibility_InitiallyUnmountedBlacklistedVolume)
185{
186 EXPECT_CALL(*volume_, IsMounted())
187 .WillRepeatedly(Return(false));
188
189 EXPECT_CALL(*settings_, IsABlacklistedDevice(_))
190 .WillRepeatedly(Return(true));
191
192 CreateIcon();
193
194 EXPECT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
195}
196
197TEST_F(TestVolumeLauncherIcon, TestSettingsChangedSignal)
198{
199 CreateIcon();
200
201 EXPECT_CALL(*settings_, IsABlacklistedDevice(_))
202 .WillRepeatedly(Return(true));
203 settings_->changed.emit();
204
205 EXPECT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
206}
207
208TEST_F(TestVolumeLauncherIcon, TestVisibilityAfterUnmount)
209{
210 CreateIcon();
211
212 EXPECT_CALL(*volume_, IsMounted())
213 .WillRepeatedly(Return(false));
214
215 EXPECT_CALL(*settings_, TryToBlacklist(_))
216 .Times(0);
217
218 volume_->changed.emit();
219 Utils::WaitForTimeout(1);
220
221 EXPECT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
222}
223
224TEST_F(TestVolumeLauncherIcon, TestVisibilityAfterUnmount_BlacklistedVolume)
225{
226 EXPECT_CALL(*settings_, IsABlacklistedDevice(_))
227 .WillRepeatedly(Return(true));
228
229 CreateIcon();
230
231 EXPECT_CALL(*volume_, IsMounted())
232 .WillRepeatedly(Return(false));
233
234 EXPECT_CALL(*settings_, TryToUnblacklist(_))
235 .Times(0);
236
237 volume_->changed.emit();
238 Utils::WaitForTimeout(1);
239
240 EXPECT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
241}
242
243TEST_F(TestVolumeLauncherIcon, TestUnlockFromLauncherMenuItem_VolumeWithoutIdentifier)
244{
245 EXPECT_CALL(*volume_, GetIdentifier())
246 .WillRepeatedly(Return(""));
247
248 CreateIcon();
249
250 for (auto menuitem : icon_->GetMenus())
251 ASSERT_STRNE(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Unlock from Launcher");
252}
253
254TEST_F(TestVolumeLauncherIcon, TestUnlockFromLauncherMenuItem_Success)
255{
256 CreateIcon();
257
258 auto menuitem = GetMenuItemAtIndex(0);
259
260 ASSERT_STREQ(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Unlock from Launcher");
261 EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE));
262 EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_ENABLED));
263
264 EXPECT_CALL(*settings_, TryToBlacklist(_))
265 .Times(1);
266
267 EXPECT_CALL(*settings_, IsABlacklistedDevice(_))
268 .WillRepeatedly(Return(true));
269
270 dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, 0);
271 settings_->changed.emit(); // TryToBlacklist() works if DevicesSettings emits a changed signal.
272 Utils::WaitForTimeout(1);
273
274 ASSERT_FALSE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
275}
276
277TEST_F(TestVolumeLauncherIcon, TestUnlockFromLauncherMenuItem_Failure)
278{
279 CreateIcon();
280
281 auto menuitem = GetMenuItemAtIndex(0);
282
283 ASSERT_STREQ(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Unlock from Launcher");
284 EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE));
285 EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_ENABLED));
286
287 EXPECT_CALL(*settings_, TryToBlacklist(_))
288 .Times(1);
289
290 dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, 0);
291 Utils::WaitForTimeout(1);
292
293 ASSERT_TRUE(icon_->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE));
294}
295
296TEST_F(TestVolumeLauncherIcon, TestOpenMenuItem)
297{
298 CreateIcon();
299
300 auto menuitem = GetMenuItemAtIndex(1);
301
302 ASSERT_STREQ(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Open");
303 EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE));
304 EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_ENABLED));
305
306 EXPECT_CALL(*volume_, MountAndOpenInFileManager())
307 .Times(1);
308
309 dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, 0);
310 Utils::WaitForTimeout(1);
311}
312
313TEST_F(TestVolumeLauncherIcon, TestEjectMenuItem_NotEjectableVolume)
314{
315 CreateIcon();
316
317 for (auto menuitem : icon_->GetMenus())
318 ASSERT_STRNE(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Eject");
319}
320
321TEST_F(TestVolumeLauncherIcon, TestEjectMenuItem)
322{
323 EXPECT_CALL(*volume_, CanBeEjected())
324 .WillRepeatedly(Return(true));
325
326 CreateIcon();
327
328 auto menuitem = GetMenuItemAtIndex(2);
329
330 EXPECT_CALL(*volume_, EjectAndShowNotification())
331 .Times(1);
332
333 ASSERT_STREQ(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Eject");
334 EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE));
335 EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_ENABLED));
336
337 dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, 0);
338 Utils::WaitForTimeout(1);
339}
340
341TEST_F(TestVolumeLauncherIcon, TestEjectMenuItem_NotStoppableVolume)
342{
343 CreateIcon();
344
345 for (auto menuitem : icon_->GetMenus())
346 ASSERT_STRNE(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Safely remove");
347}
348
349TEST_F(TestVolumeLauncherIcon, TestSafelyRemoveMenuItem)
350{
351 EXPECT_CALL(*volume_, CanBeStopped())
352 .WillRepeatedly(Return(true));
353
354 CreateIcon();
355
356 auto menuitem = GetMenuItemAtIndex(2);
357
358 EXPECT_CALL(*volume_, StopDrive())
359 .Times(1);
360
361 ASSERT_STREQ(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Safely remove");
362 EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE));
363 EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_ENABLED));
364
365 dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, 0);
366 Utils::WaitForTimeout(1);
367}
368
369TEST_F(TestVolumeLauncherIcon, TestUnmountMenuItem_UnmountedVolume)
370{
371 EXPECT_CALL(*volume_, IsMounted())
372 .WillRepeatedly(Return(false));
373
374 CreateIcon();
375
376 for (auto menuitem : icon_->GetMenus())
377 ASSERT_STRNE(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Unmount");
378}
379
380
381TEST_F(TestVolumeLauncherIcon, TestUnmountMenuItem_EjectableVolume)
382{
383 EXPECT_CALL(*volume_, CanBeEjected())
384 .WillRepeatedly(Return(true));
385
386 EXPECT_CALL(*volume_, IsMounted())
387 .WillRepeatedly(Return(true));
388
389 CreateIcon();
390
391 for (auto menuitem : icon_->GetMenus())
392 ASSERT_STRNE(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Unmount");
393}
394
395TEST_F(TestVolumeLauncherIcon, TestUnmountMenuItem_StoppableVolume)
396{
397 EXPECT_CALL(*volume_, CanBeStopped())
398 .WillRepeatedly(Return(true));
399
400 EXPECT_CALL(*volume_, IsMounted())
401 .WillRepeatedly(Return(true));
402
403 CreateIcon();
404
405 for (auto menuitem : icon_->GetMenus())
406 ASSERT_STRNE(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Unmount");
407}
408
409TEST_F(TestVolumeLauncherIcon, TestUnmountMenuItem)
410{
411 EXPECT_CALL(*volume_, IsMounted())
412 .WillRepeatedly(Return(true));
413
414 CreateIcon();
415
416 auto menuitem = GetMenuItemAtIndex(2);
417
418 EXPECT_CALL(*volume_, Unmount())
419 .Times(1);
420
421 ASSERT_STREQ(dbusmenu_menuitem_property_get(menuitem, DBUSMENU_MENUITEM_PROP_LABEL), "Unmount");
422 EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE));
423 EXPECT_TRUE(dbusmenu_menuitem_property_get_bool(menuitem, DBUSMENU_MENUITEM_PROP_ENABLED));
424
425 dbusmenu_menuitem_handle_event(menuitem, DBUSMENU_MENUITEM_EVENT_ACTIVATED, nullptr, 0);
426 Utils::WaitForTimeout(1);
427}
428
429TEST_F(TestVolumeLauncherIcon, TestCanBeEject)
430{
431 CreateIcon();
432
433 EXPECT_CALL(*volume_, CanBeEjected())
434 .WillRepeatedly(Return(true));
435 ASSERT_TRUE(icon_->CanEject());
436
437 EXPECT_CALL(*volume_, CanBeEjected())
438 .WillRepeatedly(Return(false));
439 ASSERT_FALSE(icon_->CanEject());
440
441}
442
443TEST_F(TestVolumeLauncherIcon, TestEject)
444{
445 EXPECT_CALL(*volume_, CanBeEjected())
446 .WillRepeatedly(Return(true));
447
448 CreateIcon();
449
450 EXPECT_CALL(*volume_, EjectAndShowNotification())
451 .Times(1);
452
453 icon_->EjectAndShowNotification();
454}
455
456TEST_F(TestVolumeLauncherIcon, OnRemoved)
457{
458 CreateIcon();
459
460 EXPECT_CALL(*settings_, TryToBlacklist(_))
461 .Times(0);
462 EXPECT_CALL(*settings_, TryToUnblacklist(_))
463 .Times(0);
464
465 volume_->removed.emit();
466}
467
468TEST_F(TestVolumeLauncherIcon, OnRemoved_RemovabledVolume)
469{
470 EXPECT_CALL(*volume_, CanBeRemoved())
471 .WillRepeatedly(Return(true));
472 CreateIcon();
473
474 EXPECT_CALL(*settings_, TryToBlacklist(_))
475 .Times(0);
476 EXPECT_CALL(*settings_, TryToUnblacklist(_))
477 .Times(0);
478
479 volume_->removed.emit();
480}
481
482TEST_F(TestVolumeLauncherIcon, OnRemoved_RemovableAndBlacklistedVolume)
483{
484 EXPECT_CALL(*volume_, CanBeRemoved())
485 .WillRepeatedly(Return(true));
486 EXPECT_CALL(*settings_, IsABlacklistedDevice(_))
487 .WillRepeatedly(Return(true));
488 CreateIcon();
489
490 EXPECT_CALL(*settings_, TryToBlacklist(_))
491 .Times(0);
492 EXPECT_CALL(*settings_, TryToUnblacklist(_))
493 .Times(1);
494
495 volume_->removed.emit();
496}
497
498}