~unity-team/unity/trusty-1066971

2540.12.5 by Andrea Azzarone
Add TestMountAndOpenInFileManager method and test it.
1
// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
2
/*
3212.1.1 by Marco Trevisan (Treviño)
FileManagerOpener: pass the timestamp to the Open method and set to context
3
 * Copyright (C) 2012-2013 Canonical Ltd
2540.12.5 by Andrea Azzarone
Add TestMountAndOpenInFileManager method and test it.
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>
3212.1.1 by Marco Trevisan (Treviño)
FileManagerOpener: pass the timestamp to the Open method and set to context
18
 *              Marco Trevisan <marco.trevisan@canonical.com>
2540.12.5 by Andrea Azzarone
Add TestMountAndOpenInFileManager method and test it.
19
 */
20
3212.3.3 by Marco Trevisan (Treviño)
FileManagerOpener: moved to unity-shared and renamed as FileManager
21
#include "GnomeFileManager.h"
3212.1.1 by Marco Trevisan (Treviño)
FileManagerOpener: pass the timestamp to the Open method and set to context
22
#include <NuxCore/Logger.h>
3212.4.8 by Marco Trevisan (Treviño)
FileManager: add OpenTrash and IsTrashOpened and IsDeviceOpened
23
#include <UnityCore/DesktopUtilities.h>
3212.1.1 by Marco Trevisan (Treviño)
FileManagerOpener: pass the timestamp to the Open method and set to context
24
#include <UnityCore/GLibWrapper.h>
3212.3.7 by Marco Trevisan (Treviño)
GnomeFileManager: implement EmptyTrash and add Activate
25
#include <UnityCore/GLibDBusProxy.h>
3212.1.1 by Marco Trevisan (Treviño)
FileManagerOpener: pass the timestamp to the Open method and set to context
26
#include <gdk/gdk.h>
3212.3.7 by Marco Trevisan (Treviño)
GnomeFileManager: implement EmptyTrash and add Activate
27
#include <gio/gio.h>
2540.12.5 by Andrea Azzarone
Add TestMountAndOpenInFileManager method and test it.
28
2540.12.7 by Andrea Azzarone
Move device settings from a favorite list to a blacklist.
29
namespace unity
2540.12.5 by Andrea Azzarone
Add TestMountAndOpenInFileManager method and test it.
30
{
3212.3.3 by Marco Trevisan (Treviño)
FileManagerOpener: moved to unity-shared and renamed as FileManager
31
3212.3.7 by Marco Trevisan (Treviño)
GnomeFileManager: implement EmptyTrash and add Activate
32
namespace
33
{
3212.3.3 by Marco Trevisan (Treviño)
FileManagerOpener: moved to unity-shared and renamed as FileManager
34
DECLARE_LOGGER(logger, "unity.filemanager.gnome");
35
3212.3.7 by Marco Trevisan (Treviño)
GnomeFileManager: implement EmptyTrash and add Activate
36
const std::string TRASH_URI = "trash:";
3555.2.2 by Marco Trevisan (Treviño)
GnomeFileManager: use nwe nautilus dbus paths for actions
37
const std::string FILE_SCHEMA = "file://";
38
const std::string TRASH_PATH = FILE_SCHEMA + DesktopUtilities::GetUserDataDirectory() + "/Trash/files";
39
const std::string DEVICES_PREFIX = FILE_SCHEMA + "/media/" + std::string(g_get_user_name());
40
41
const std::string NAUTILUS_NAME = "org.gnome.Nautilus";
42
const std::string NAUTILUS_PATH = "/org/gnome/Nautilus";
3212.3.7 by Marco Trevisan (Treviño)
GnomeFileManager: implement EmptyTrash and add Activate
43
}
44
3212.3.17 by Marco Trevisan (Treviño)
GnomeFileManager: added impl, connect to FileManager proxy and get OpenLocations property
45
struct GnomeFileManager::Impl
46
{
47
  Impl(GnomeFileManager* parent)
48
    : parent_(parent)
49
    , filemanager_proxy_("org.freedesktop.FileManager1", "/org/freedesktop/FileManager1", "org.freedesktop.FileManager1")
50
  {
51
    auto callback = sigc::mem_fun(this, &Impl::OnOpenLocationsUpdated);
52
    filemanager_proxy_.GetProperty("OpenLocations", callback);
53
    filemanager_proxy_.ConnectProperty("OpenLocations", callback);
54
  }
55
56
  void OnOpenLocationsUpdated(GVariant* value)
57
  {
58
    if (!g_variant_is_of_type(value, G_VARIANT_TYPE_STRING_ARRAY))
59
    {
60
      LOG_ERROR(logger) << "Locations value type is not matching the expected one!";
61
      return;
62
    }
63
64
    opened_locations_.clear();
65
3212.3.19 by Marco Trevisan (Treviño)
GnomeFileManager: add IsPrefixOpened method
66
    GVariantIter iter;
3212.3.17 by Marco Trevisan (Treviño)
GnomeFileManager: added impl, connect to FileManager proxy and get OpenLocations property
67
    const char *str;
68
3212.3.19 by Marco Trevisan (Treviño)
GnomeFileManager: add IsPrefixOpened method
69
    g_variant_iter_init(&iter, value);
70
71
    while (g_variant_iter_loop(&iter, "s", &str))
3212.3.17 by Marco Trevisan (Treviño)
GnomeFileManager: added impl, connect to FileManager proxy and get OpenLocations property
72
    {
73
      LOG_DEBUG(logger) << "Opened location " << str;
74
      opened_locations_.push_back(str);
75
    }
76
77
    parent_->locations_changed.emit();
78
  }
79
3212.4.8 by Marco Trevisan (Treviño)
FileManager: add OpenTrash and IsTrashOpened and IsDeviceOpened
80
  std::string GetOpenedPrefix(std::string const& uri, bool allow_equal = true)
3212.3.36 by Marco Trevisan (Treviño)
FileManager: add OpenActiveChild to reopen an opened view with given prefix
81
  {
82
    glib::Object<GFile> uri_file(g_file_new_for_uri(uri.c_str()));
83
84
    for (auto const& loc : opened_locations_)
85
    {
3212.4.8 by Marco Trevisan (Treviño)
FileManager: add OpenTrash and IsTrashOpened and IsDeviceOpened
86
      bool equal = false;
87
3212.3.36 by Marco Trevisan (Treviño)
FileManager: add OpenActiveChild to reopen an opened view with given prefix
88
      glib::Object<GFile> loc_file(g_file_new_for_uri(loc.c_str()));
89
3212.4.8 by Marco Trevisan (Treviño)
FileManager: add OpenTrash and IsTrashOpened and IsDeviceOpened
90
      if (allow_equal && g_file_equal(loc_file, uri_file))
91
        equal = true;
92
93
      if (equal || g_file_has_prefix(loc_file, uri_file))
3212.3.36 by Marco Trevisan (Treviño)
FileManager: add OpenActiveChild to reopen an opened view with given prefix
94
        return loc;
95
    }
96
97
    return "";
98
  }
99
3555.2.2 by Marco Trevisan (Treviño)
GnomeFileManager: use nwe nautilus dbus paths for actions
100
  glib::DBusProxy::Ptr NautilusOperationsProxy() const
101
  {
102
    return std::make_shared<glib::DBusProxy>(NAUTILUS_NAME, NAUTILUS_PATH,
103
                                             "org.gnome.Nautilus.FileOperations");
104
  }
105
3212.3.17 by Marco Trevisan (Treviño)
GnomeFileManager: added impl, connect to FileManager proxy and get OpenLocations property
106
  GnomeFileManager* parent_;
107
  glib::DBusProxy filemanager_proxy_;
108
  std::vector<std::string> opened_locations_;
109
};
110
3212.3.31 by Marco Trevisan (Treviño)
GnomeFileManager: add static getter to share resources
111
112
FileManager::Ptr GnomeFileManager::Get()
113
{
114
  static FileManager::Ptr instance(new GnomeFileManager());
115
  return instance;
116
}
117
3212.3.17 by Marco Trevisan (Treviño)
GnomeFileManager: added impl, connect to FileManager proxy and get OpenLocations property
118
GnomeFileManager::GnomeFileManager()
119
  : impl_(new Impl(this))
120
{}
121
122
GnomeFileManager::~GnomeFileManager()
123
{}
124
3310.5.7 by Marco Trevisan (Treviño)
Unity: "s/unsigned long long/uint64_t/g"
125
void GnomeFileManager::Open(std::string const& uri, uint64_t timestamp)
2540.12.5 by Andrea Azzarone
Add TestMountAndOpenInFileManager method and test it.
126
{
3212.1.1 by Marco Trevisan (Treviño)
FileManagerOpener: pass the timestamp to the Open method and set to context
127
  if (uri.empty())
128
  {
129
    LOG_ERROR(logger) << "Impossible to open an empty location";
130
    return;
131
  }
132
133
  glib::Error error;
134
  GdkDisplay* display = gdk_display_get_default();
135
  glib::Object<GdkAppLaunchContext> context(gdk_display_get_app_launch_context(display));
136
137
  if (timestamp > 0)
138
    gdk_app_launch_context_set_timestamp(context, timestamp);
139
140
  auto const& gcontext = glib::object_cast<GAppLaunchContext>(context);
141
  g_app_info_launch_default_for_uri(uri.c_str(), gcontext, &error);
142
143
  if (error)
144
  {
145
    LOG_ERROR(logger) << "Impossible to open the location: " << error.Message();
146
  }
2540.12.5 by Andrea Azzarone
Add TestMountAndOpenInFileManager method and test it.
147
}
148
3310.5.7 by Marco Trevisan (Treviño)
Unity: "s/unsigned long long/uint64_t/g"
149
void GnomeFileManager::OpenActiveChild(std::string const& uri, uint64_t timestamp)
3212.3.36 by Marco Trevisan (Treviño)
FileManager: add OpenActiveChild to reopen an opened view with given prefix
150
{
151
  auto const& opened = impl_->GetOpenedPrefix(uri);
152
153
  Open(opened.empty() ? uri : opened, timestamp);
154
}
155
3310.5.7 by Marco Trevisan (Treviño)
Unity: "s/unsigned long long/uint64_t/g"
156
void GnomeFileManager::OpenTrash(uint64_t timestamp)
3212.4.8 by Marco Trevisan (Treviño)
FileManager: add OpenTrash and IsTrashOpened and IsDeviceOpened
157
{
158
  if (IsPrefixOpened(TRASH_PATH))
159
  {
160
    OpenActiveChild(TRASH_PATH, timestamp);
161
  }
162
  else
163
  {
164
    OpenActiveChild(TRASH_URI, timestamp);
165
  }
166
}
167
3310.5.7 by Marco Trevisan (Treviño)
Unity: "s/unsigned long long/uint64_t/g"
168
void GnomeFileManager::Activate(uint64_t timestamp)
3212.3.7 by Marco Trevisan (Treviño)
GnomeFileManager: implement EmptyTrash and add Activate
169
{
170
  glib::Cancellable cancellable;
171
  glib::Object<GFile> file(g_file_new_for_uri(TRASH_URI.c_str()));
172
  glib::Object<GAppInfo> app_info(g_file_query_default_handler(file, cancellable, nullptr));
173
174
  if (app_info)
175
  {
176
    GdkDisplay* display = gdk_display_get_default();
177
    glib::Object<GdkAppLaunchContext> context(gdk_display_get_app_launch_context(display));
178
179
    if (timestamp > 0)
180
      gdk_app_launch_context_set_timestamp(context, timestamp);
181
182
    auto const& gcontext = glib::object_cast<GAppLaunchContext>(context);
3555.2.2 by Marco Trevisan (Treviño)
GnomeFileManager: use nwe nautilus dbus paths for actions
183
    auto proxy = std::make_shared<glib::DBusProxy>(NAUTILUS_NAME, NAUTILUS_PATH,
184
                                                   "org.freedesktop.Application");
3212.3.7 by Marco Trevisan (Treviño)
GnomeFileManager: implement EmptyTrash and add Activate
185
186
    glib::String context_string(g_app_launch_context_get_startup_notify_id(gcontext, app_info, nullptr));
187
188
    if (context_string && g_utf8_validate(context_string, -1, nullptr))
189
    {
190
      GVariantBuilder builder;
191
      g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
192
      g_variant_builder_add(&builder, "{sv}", "desktop-startup-id", g_variant_new("s", context_string.Value()));
193
      GVariant *param = g_variant_new("(@a{sv})", g_variant_builder_end(&builder));
194
195
      // Passing the proxy to the lambda we ensure that it will be destroyed when needed
196
      proxy->CallBegin("Activate", param, [proxy] (GVariant*, glib::Error const&) {});
197
    }
198
  }
199
}
200
3477.5.40 by Marco Trevisan (Treviño)
FileManager: add TrashFile action
201
bool GnomeFileManager::TrashFile(std::string const& uri)
202
{
203
  glib::Cancellable cancellable;
204
  glib::Object<GFile> file(g_file_new_for_uri(uri.c_str()));
205
  glib::Error error;
206
207
  if (g_file_trash(file, cancellable, &error))
208
    return true;
209
210
  LOG_ERROR(logger) << "Impossible to trash file '" << uri << "': " << error;
211
  return false;
212
}
213
3310.5.7 by Marco Trevisan (Treviño)
Unity: "s/unsigned long long/uint64_t/g"
214
void GnomeFileManager::EmptyTrash(uint64_t timestamp)
3212.3.7 by Marco Trevisan (Treviño)
GnomeFileManager: implement EmptyTrash and add Activate
215
{
216
  Activate(timestamp);
3555.2.2 by Marco Trevisan (Treviño)
GnomeFileManager: use nwe nautilus dbus paths for actions
217
  auto const& proxy = impl_->NautilusOperationsProxy();
3212.3.7 by Marco Trevisan (Treviño)
GnomeFileManager: implement EmptyTrash and add Activate
218
219
  // Passing the proxy to the lambda we ensure that it will be destroyed when needed
220
  proxy->CallBegin("EmptyTrash", nullptr, [proxy] (GVariant*, glib::Error const&) {});
221
}
222
3555.2.12 by Marco Trevisan (Treviño)
FileManager: add CopyFiles method, implement it for GnomeFileManager using nautilus APIs
223
void GnomeFileManager::CopyFiles(std::set<std::string> const& uris, std::string const& dest, uint64_t timestamp)
224
{
3555.2.17 by Marco Trevisan (Treviño)
GnomeFileManager: don't try to copy files from o to invalid locations
225
  if (uris.empty() || dest.empty())
226
    return;
227
3555.2.12 by Marco Trevisan (Treviño)
FileManager: add CopyFiles method, implement it for GnomeFileManager using nautilus APIs
228
  bool found_valid = false;
229
  GVariantBuilder b;
230
  g_variant_builder_init(&b, G_VARIANT_TYPE("(ass)"));
231
  g_variant_builder_open(&b, G_VARIANT_TYPE("as"));
232
233
  for (auto const& uri : uris)
234
  {
235
    if (uri.find(FILE_SCHEMA) == 0)
236
    {
237
      found_valid = true;
238
      g_variant_builder_add(&b, "s", uri.c_str());
239
    }
240
  }
241
242
  g_variant_builder_close(&b);
243
  g_variant_builder_add(&b, "s", dest.c_str());
244
  glib::Variant parameters(g_variant_builder_end(&b));
245
246
  if (found_valid)
247
  {
248
    // Passing the proxy to the lambda we ensure that it will be destroyed when needed
249
    auto const& proxy = impl_->NautilusOperationsProxy();
250
    proxy->CallBegin("CopyURIs", parameters, [proxy] (GVariant*, glib::Error const&) {});
251
    Activate(timestamp);
252
  }
253
}
254
3212.3.14 by Marco Trevisan (Treviño)
FileManager: add OpenedLocations virtual method
255
std::vector<std::string> GnomeFileManager::OpenedLocations() const
256
{
3212.3.18 by Marco Trevisan (Treviño)
GnomeFileManager: return correct value on OpenedLocations
257
  return impl_->opened_locations_;
3212.3.14 by Marco Trevisan (Treviño)
FileManager: add OpenedLocations virtual method
258
}
259
3212.3.19 by Marco Trevisan (Treviño)
GnomeFileManager: add IsPrefixOpened method
260
bool GnomeFileManager::IsPrefixOpened(std::string const& uri) const
261
{
3212.3.36 by Marco Trevisan (Treviño)
FileManager: add OpenActiveChild to reopen an opened view with given prefix
262
  return !impl_->GetOpenedPrefix(uri).empty();
3212.3.19 by Marco Trevisan (Treviño)
GnomeFileManager: add IsPrefixOpened method
263
}
264
3212.4.8 by Marco Trevisan (Treviño)
FileManager: add OpenTrash and IsTrashOpened and IsDeviceOpened
265
bool GnomeFileManager::IsTrashOpened() const
266
{
267
  return (IsPrefixOpened(TRASH_URI) || IsPrefixOpened(TRASH_PATH));
268
}
269
270
bool GnomeFileManager::IsDeviceOpened() const
271
{
272
  return !impl_->GetOpenedPrefix(DEVICES_PREFIX, false).empty();
273
}
274
275
2540.12.5 by Andrea Azzarone
Add TestMountAndOpenInFileManager method and test it.
276
}