summaryrefslogtreecommitdiff
diff options
authorMarco Trevisan (Treviño) <mail@3v1n0.net>2015-11-24 16:15:08 +0100
committerMarco Trevisan (Treviño) <mail@3v1n0.net>2015-11-24 16:15:08 +0100
commit8e685b5cecf96359b288d635b366a0a0ce561053 (patch)
tree718f06f9ade373f8a110c583308e7153a7e1264b
parent7ebd55716bb8cd86259330f90b01e7eee9213fd9 (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.h14
-rw-r--r--unity-shared/FileManager.h8
-rw-r--r--unity-shared/GnomeFileManager.cpp144
-rw-r--r--unity-shared/GnomeFileManager.h4
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();