diff options
| author | Marco Trevisan (Treviño) <mail@3v1n0.net> | 2015-11-24 16:15:08 +0100 |
|---|---|---|
| committer | Marco Trevisan (Treviño) <mail@3v1n0.net> | 2015-11-24 16:15:08 +0100 |
| commit | 8e685b5cecf96359b288d635b366a0a0ce561053 (patch) | |
| tree | 718f06f9ade373f8a110c583308e7153a7e1264b | |
| parent | 7ebd55716bb8cd86259330f90b01e7eee9213fd9 (diff) | |
GnomeFileManager: add WindowsForLocation and LocationsForWindow APIs
We use the XUbuntuOpenLocationsXids property from org.freedesktop.FileManager1 to get the list of locations that every window is showing (bzr r4036.11.7)
| -rw-r--r-- | tests/test_mock_filemanager.h | 14 | ||||
| -rw-r--r-- | unity-shared/FileManager.h | 8 | ||||
| -rw-r--r-- | unity-shared/GnomeFileManager.cpp | 144 | ||||
| -rw-r--r-- | unity-shared/GnomeFileManager.h | 4 |
4 files changed, 136 insertions, 34 deletions
diff --git a/tests/test_mock_filemanager.h b/tests/test_mock_filemanager.h index 231c0074e..2dc8c9ea4 100644 --- a/tests/test_mock_filemanager.h +++ b/tests/test_mock_filemanager.h @@ -37,10 +37,22 @@ struct MockFileManager : FileManager MOCK_METHOD1(TrashFile, bool(std::string const& uri)); MOCK_METHOD1(EmptyTrash, void(uint64_t time)); MOCK_METHOD3(CopyFiles, void(std::set<std::string> const& files, std::string const& dest, uint64_t time)); - MOCK_CONST_METHOD0(OpenedLocations, std::vector<std::string>()); + MOCK_CONST_METHOD0(OpenedLocations, std::vector<std::string> const&()); + MOCK_CONST_METHOD1(WindowsForLocation, WindowList(std::string const&)); + MOCK_CONST_METHOD1(LocationsForWindow, std::vector<std::string> const&(ApplicationWindowPtr const&)); MOCK_CONST_METHOD1(IsPrefixOpened, bool(std::string const& uri)); MOCK_CONST_METHOD0(IsTrashOpened, bool()); MOCK_CONST_METHOD0(IsDeviceOpened, bool()); + + MockFileManager() + { + using namespace testing; + ON_CALL(*this, WindowsForLocation(_)).WillByDefault(Return(WindowList())); + ON_CALL(*this, OpenedLocations()).WillByDefault(Invoke([this] { return EMPTY_LOCATIONS; })); + ON_CALL(*this, LocationsForWindow(_)).WillByDefault(Invoke([this] (ApplicationWindowPtr const&) { return EMPTY_LOCATIONS; })); + } + + const std::vector<std::string> EMPTY_LOCATIONS; }; } diff --git a/unity-shared/FileManager.h b/unity-shared/FileManager.h index 55647d2c0..5537677e1 100644 --- a/unity-shared/FileManager.h +++ b/unity-shared/FileManager.h @@ -27,6 +27,8 @@ #include <vector> #include <set> #include <sigc++/sigc++.h> +#include "ApplicationManager.h" + namespace unity { @@ -42,13 +44,15 @@ public: virtual void Open(std::string const& uri, uint64_t timestamp = 0) = 0; virtual void OpenActiveChild(std::string const& uri, uint64_t timestamp = 0) = 0; virtual void OpenTrash(uint64_t timestamp) = 0; - virtual std::vector<std::string> OpenedLocations() const = 0; + virtual std::vector<std::string> const& OpenedLocations() const = 0; virtual bool IsPrefixOpened(std::string const& uri) const = 0; virtual bool IsTrashOpened() const = 0; virtual bool IsDeviceOpened() const = 0; virtual void CopyFiles(std::set<std::string> const& uris, std::string const& dest, uint64_t timestamp = 0) = 0; virtual bool TrashFile(std::string const& uri) = 0; virtual void EmptyTrash(uint64_t timestamp = 0) = 0; + virtual WindowList WindowsForLocation(std::string const& location) const = 0; + virtual std::vector<std::string> const& LocationsForWindow(ApplicationWindowPtr const&) const = 0; sigc::signal<void> locations_changed; @@ -57,6 +61,6 @@ private: FileManager& operator=(FileManager const&) = delete; }; -} +} // namespace unity #endif diff --git a/unity-shared/GnomeFileManager.cpp b/unity-shared/GnomeFileManager.cpp index 2f142f836..c6e704871 100644 --- a/unity-shared/GnomeFileManager.cpp +++ b/unity-shared/GnomeFileManager.cpp @@ -21,8 +21,9 @@ #include "GnomeFileManager.h" #include <NuxCore/Logger.h> #include <UnityCore/DesktopUtilities.h> -#include <UnityCore/GLibWrapper.h> +#include <UnityCore/GLibSource.h> #include <UnityCore/GLibDBusProxy.h> +#include <UnityCore/GLibWrapper.h> #include <gdk/gdk.h> #include <gio/gio.h> @@ -36,7 +37,8 @@ DECLARE_LOGGER(logger, "unity.filemanager.gnome"); const std::string TRASH_URI = "trash:"; const std::string FILE_SCHEMA = "file://"; const std::string TRASH_PATH = FILE_SCHEMA + DesktopUtilities::GetUserDataDirectory() + "/Trash/files"; -const std::string DEVICES_PREFIX = FILE_SCHEMA + "/media/" + std::string(g_get_user_name()); +const std::string DEVICES_PREFIX = FILE_SCHEMA + "/media/" + glib::gchar_to_string(g_get_user_name()); +const std::vector<std::string> EMPTY_LOCATIONS; const std::string NAUTILUS_NAME = "org.gnome.Nautilus"; const std::string NAUTILUS_PATH = "/org/gnome/Nautilus"; @@ -48,33 +50,9 @@ struct GnomeFileManager::Impl : parent_(parent) , filemanager_proxy_("org.freedesktop.FileManager1", "/org/freedesktop/FileManager1", "org.freedesktop.FileManager1") { - auto callback = sigc::mem_fun(this, &Impl::OnOpenLocationsUpdated); - filemanager_proxy_.GetProperty("OpenLocations", callback); - filemanager_proxy_.ConnectProperty("OpenLocations", callback); - } - - void OnOpenLocationsUpdated(GVariant* value) - { - if (!g_variant_is_of_type(value, G_VARIANT_TYPE_STRING_ARRAY)) - { - LOG_ERROR(logger) << "Locations value type is not matching the expected one!"; - return; - } - - opened_locations_.clear(); - - GVariantIter iter; - const char *str; - - g_variant_iter_init(&iter, value); - - while (g_variant_iter_loop(&iter, "s", &str)) - { - LOG_DEBUG(logger) << "Opened location " << str; - opened_locations_.push_back(str); - } - - parent_->locations_changed.emit(); + auto callback = sigc::mem_fun(this, &Impl::OnOpenLocationsXidsUpdated); + filemanager_proxy_.GetProperty("XUbuntuOpenLocationsXids", callback); + filemanager_proxy_.ConnectProperty("XUbuntuOpenLocationsXids", callback); } std::string GetOpenedPrefix(std::string const& uri, bool allow_equal = true) @@ -103,9 +81,72 @@ struct GnomeFileManager::Impl "org.gnome.Nautilus.FileOperations"); } + void OnOpenLocationsXidsUpdated(GVariant* value) + { + opened_locations_.clear(); + opened_locations_xids_.clear(); + + if (!value) + { + LOG_WARN(logger) << "Locations have been invalidated, maybe there's no filemanager around..."; + parent_->locations_changed.emit(); + return; + } + + if (!g_variant_is_of_type(value, G_VARIANT_TYPE("a{uas}"))) + { + LOG_ERROR(logger) << "Locations value type is not matching the expected one!"; + parent_->locations_changed.emit(); + return; + } + + GVariantIter iter; + GVariantIter *str_iter; + const char *str; + guint32 xid; + + g_variant_iter_init(&iter, value); + + while (g_variant_iter_loop(&iter, "{uas}", &xid, &str_iter)) + { + while (g_variant_iter_loop(str_iter, "s", &str)) + { + LOG_DEBUG(logger) << xid << ": Opened location " << str; + opened_locations_xids_[xid].push_back(str); + opened_locations_.push_back(str); + } + } + + // We must ensure that we emit the locations_changed signal only when all + // the parent windows have been registered on the app-manager + auto app_manager_not_synced = [this] + { + auto& app_manager = ApplicationManager::Default(); + bool synced = true; + + for (auto const& pair : opened_locations_xids_) + { + synced = (app_manager.GetWindowForId(pair.first) != nullptr); + + if (!synced) + break; + } + + if (synced) + parent_->locations_changed.emit(); + + return !synced; + }; + + if (app_manager_not_synced()) + idle_.reset(new glib::Idle(app_manager_not_synced)); + } + GnomeFileManager* parent_; glib::DBusProxy filemanager_proxy_; + glib::Source::UniquePtr idle_; std::vector<std::string> opened_locations_; + std::map<Window, std::vector<std::string>> opened_locations_xids_; }; @@ -252,7 +293,7 @@ void GnomeFileManager::CopyFiles(std::set<std::string> const& uris, std::string } } -std::vector<std::string> GnomeFileManager::OpenedLocations() const +std::vector<std::string> const& GnomeFileManager::OpenedLocations() const { return impl_->opened_locations_; } @@ -272,5 +313,48 @@ bool GnomeFileManager::IsDeviceOpened() const return !impl_->GetOpenedPrefix(DEVICES_PREFIX, false).empty(); } +WindowList GnomeFileManager::WindowsForLocation(std::string const& location) const +{ + std::vector<ApplicationWindowPtr> windows; + auto& app_manager = ApplicationManager::Default(); + + glib::Object<GFile> location_file(g_file_new_for_uri(location.c_str())); + + for (auto const& pair : impl_->opened_locations_xids_) + { + auto const& win_loc = pair.second; + + for (auto const& loc : win_loc) + { + glib::Object<GFile> loc_file(g_file_new_for_uri(loc.c_str())); + glib::String relative(g_file_get_relative_path(location_file, loc_file)); + + if (relative) + { + auto const& win = app_manager.GetWindowForId(pair.first); + + if (win && std::find(windows.rbegin(), windows.rend(), win) == windows.rend()) + windows.push_back(win); + + break; + } + } + } + + return windows; +} + +std::vector<std::string> const& GnomeFileManager::LocationsForWindow(ApplicationWindowPtr const& win) const +{ + if (win) + { + auto it = impl_->opened_locations_xids_.find(win->window_id()); + + if (it != end(impl_->opened_locations_xids_)) + return it->second; + } + return EMPTY_LOCATIONS; } + +} // namespace unity diff --git a/unity-shared/GnomeFileManager.h b/unity-shared/GnomeFileManager.h index 5b9ac1203..86043abab 100644 --- a/unity-shared/GnomeFileManager.h +++ b/unity-shared/GnomeFileManager.h @@ -40,10 +40,12 @@ public: bool TrashFile(std::string const& uri); void EmptyTrash(uint64_t timestamp); - std::vector<std::string> OpenedLocations() const; + std::vector<std::string> const& OpenedLocations() const; bool IsPrefixOpened(std::string const& uri) const; bool IsTrashOpened() const; bool IsDeviceOpened() const; + WindowList WindowsForLocation(std::string const& location) const; + std::vector<std::string> const& LocationsForWindow(ApplicationWindowPtr const&) const; private: GnomeFileManager(); |
