1
/* vi:set et ai sw=2 sts=2 ts=2: */
3
* Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org>
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License as
7
* published by the Free Software Foundation; either version 2 of
8
* the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public
16
* License along with this program; if not, write to the Free
17
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18
* Boston, MA 02110-1301, USA.
25
#include <glib-object.h>
27
#include <thunar/thunar-browser.h>
28
#include <thunar/thunar-file.h>
29
#include <thunar/thunar-private.h>
30
#include <thunar/thunar-util.h>
34
typedef struct _PokeFileData PokeFileData;
35
typedef struct _PokeVolumeData PokeVolumeData;
39
ThunarBrowser *browser;
42
ThunarBrowserPokeFileFunc func;
46
struct _PokeVolumeData
48
ThunarBrowser *browser;
50
ThunarFile *mount_point;
51
ThunarBrowserPokeVolumeFunc func;
58
thunar_browser_get_type (void)
60
static volatile gsize type__volatile = 0;
63
if (g_once_init_enter (&type__volatile))
65
type = g_type_register_static_simple (G_TYPE_INTERFACE,
67
sizeof (ThunarBrowserIface),
73
g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
75
g_once_init_leave (&type__volatile, type);
78
return type__volatile;
84
thunar_browser_poke_file_data_new (ThunarBrowser *browser,
87
ThunarBrowserPokeFileFunc func,
90
PokeFileData *poke_data;
92
_thunar_return_val_if_fail (THUNAR_IS_BROWSER (browser), NULL);
93
_thunar_return_val_if_fail (THUNAR_IS_FILE (source), NULL);
94
_thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
96
poke_data = g_slice_new0 (PokeFileData);
97
poke_data->browser = g_object_ref (browser);
98
poke_data->source = g_object_ref (source);
99
poke_data->file = g_object_ref (file);
100
poke_data->func = func;
101
poke_data->user_data = user_data;
109
thunar_browser_poke_file_data_free (PokeFileData *poke_data)
111
_thunar_return_if_fail (poke_data != NULL);
112
_thunar_return_if_fail (THUNAR_IS_BROWSER (poke_data->browser));
113
_thunar_return_if_fail (THUNAR_IS_FILE (poke_data->source));
114
_thunar_return_if_fail (THUNAR_IS_FILE (poke_data->file));
116
g_object_unref (poke_data->browser);
117
g_object_unref (poke_data->source);
118
g_object_unref (poke_data->file);
120
g_slice_free (PokeFileData, poke_data);
125
static PokeVolumeData *
126
thunar_browser_poke_volume_data_new (ThunarBrowser *browser,
128
ThunarBrowserPokeVolumeFunc func,
131
PokeVolumeData *poke_data;
133
_thunar_return_val_if_fail (THUNAR_IS_BROWSER (browser), NULL);
134
_thunar_return_val_if_fail (G_IS_VOLUME (volume), NULL);
136
poke_data = g_slice_new0 (PokeVolumeData);
137
poke_data->browser = g_object_ref (browser);
138
poke_data->volume = g_object_ref (volume);
139
poke_data->func = func;
140
poke_data->user_data = user_data;
148
thunar_browser_poke_volume_data_free (PokeVolumeData *poke_data)
150
_thunar_return_if_fail (poke_data != NULL);
151
_thunar_return_if_fail (THUNAR_IS_BROWSER (poke_data->browser));
152
_thunar_return_if_fail (G_IS_VOLUME (poke_data->volume));
154
g_object_unref (poke_data->browser);
155
g_object_unref (poke_data->volume);
157
g_slice_free (PokeVolumeData, poke_data);
162
static GMountOperation *
163
thunar_browser_mount_operation_new (gpointer parent)
165
GMountOperation *mount_operation;
166
GtkWindow *window = NULL;
167
GdkScreen *screen = NULL;
169
mount_operation = gtk_mount_operation_new (NULL);
171
screen = thunar_util_parse_parent (parent, &window);
172
gtk_mount_operation_set_screen (GTK_MOUNT_OPERATION (mount_operation), screen);
173
gtk_mount_operation_set_parent (GTK_MOUNT_OPERATION (mount_operation), window);
175
return mount_operation;
181
thunar_browser_poke_mountable_finish (GObject *object,
182
GAsyncResult *result,
185
PokeFileData *poke_data = user_data;
186
ThunarFile *target = NULL;
187
GError *error = NULL;
190
_thunar_return_if_fail (G_IS_FILE (object));
191
_thunar_return_if_fail (G_IS_ASYNC_RESULT (result));
192
_thunar_return_if_fail (user_data != NULL);
193
_thunar_return_if_fail (THUNAR_IS_BROWSER (poke_data->browser));
194
_thunar_return_if_fail (THUNAR_IS_FILE (poke_data->file));
196
if (!g_file_mount_mountable_finish (G_FILE (object), result, &error))
198
if (error->domain == G_IO_ERROR)
200
if (error->code == G_IO_ERROR_ALREADY_MOUNTED)
201
g_clear_error (&error);
207
thunar_file_reload (poke_data->file);
209
location = thunar_file_get_target_location (poke_data->file);
210
target = thunar_file_get (location, &error);
211
g_object_unref (location);
214
if (poke_data->func != NULL)
216
(poke_data->func) (poke_data->browser, poke_data->source, target, error,
217
poke_data->user_data);
220
g_clear_error (&error);
223
g_object_unref (target);
225
thunar_browser_poke_file_data_free (poke_data);
231
thunar_browser_poke_file_finish (GObject *object,
232
GAsyncResult *result,
235
PokeFileData *poke_data = user_data;
236
GError *error = NULL;
238
_thunar_return_if_fail (G_IS_FILE (object));
239
_thunar_return_if_fail (G_IS_ASYNC_RESULT (result));
240
_thunar_return_if_fail (user_data != NULL);
241
_thunar_return_if_fail (THUNAR_IS_BROWSER (poke_data->browser));
242
_thunar_return_if_fail (THUNAR_IS_FILE (poke_data->file));
244
if (!g_file_mount_enclosing_volume_finish (G_FILE (object), result, &error))
246
if (error->domain == G_IO_ERROR)
248
if (error->code == G_IO_ERROR_ALREADY_MOUNTED)
249
g_clear_error (&error);
254
thunar_file_reload (poke_data->file);
256
if (poke_data->func != NULL)
260
(poke_data->func) (poke_data->browser, poke_data->source, poke_data->file,
261
NULL, poke_data->user_data);
265
(poke_data->func) (poke_data->browser, poke_data->source, NULL, error,
266
poke_data->user_data);
270
g_clear_error (&error);
272
thunar_browser_poke_file_data_free (poke_data);
278
thunar_browser_poke_file_internal (ThunarBrowser *browser,
282
ThunarBrowserPokeFileFunc func,
285
GMountOperation *mount_operation;
287
PokeFileData *poke_data;
288
GError *error = NULL;
291
_thunar_return_if_fail (THUNAR_IS_BROWSER (browser));
292
_thunar_return_if_fail (THUNAR_IS_FILE (source));
293
_thunar_return_if_fail (THUNAR_IS_FILE (file));
295
if (thunar_file_get_kind (file) == G_FILE_TYPE_SHORTCUT)
297
location = thunar_file_get_target_location (file);
298
target = thunar_file_get (location, &error);
299
g_object_unref (location);
303
/* TODO in very rare occasions (shortcut X -> other shortcut -> shortcut X),
304
* this can lead to endless recursion */
305
thunar_browser_poke_file_internal (browser, source, target, widget,
311
func (browser, source, NULL, error, user_data);
314
g_clear_error (&error);
317
g_object_unref (target);
319
else if (thunar_file_get_kind (file) == G_FILE_TYPE_MOUNTABLE)
321
if (thunar_file_is_mounted (file))
323
location = thunar_file_get_target_location (file);
324
target = thunar_file_get (location, &error);
325
g_object_unref (location);
328
func (browser, source, target, error, user_data);
330
g_clear_error (&error);
333
g_object_unref (target);
337
poke_data = thunar_browser_poke_file_data_new (browser, source, file,
340
mount_operation = thunar_browser_mount_operation_new (widget);
342
g_file_mount_mountable (thunar_file_get_file (file),
343
G_MOUNT_MOUNT_NONE, mount_operation, NULL,
344
thunar_browser_poke_mountable_finish,
347
g_object_unref (mount_operation);
350
else if (!thunar_file_is_mounted (file))
352
poke_data = thunar_browser_poke_file_data_new (browser, source, file,
355
mount_operation = thunar_browser_mount_operation_new (widget);
357
g_file_mount_enclosing_volume (thunar_file_get_file (file),
358
G_MOUNT_MOUNT_NONE, mount_operation, NULL,
359
thunar_browser_poke_file_finish,
362
g_object_unref (mount_operation);
367
func (browser, source, file, NULL, user_data);
374
* thunar_browser_poke_file:
375
* @browser : a #ThunarBrowser.
376
* @file : a #ThunarFile.
377
* @widget : a #GtkWidget, a #GdkScreen or %NULL.
378
* @func : a #ThunarBrowserPokeFileFunc callback or %NULL.
379
* @user_data : pointer to arbitrary user data or %NULL.
381
* Pokes a #ThunarFile to see what's behind it.
383
* If @file has the type %G_FILE_TYPE_SHORTCUT, it tries to load and mount
384
* the file that is referred to by the %G_FILE_ATTRIBUTE_STANDARD_TARGET_URI
387
* If @file has the type %G_FILE_TYPE_MOUNTABLE, it tries to mount the @file.
389
* In the other cases, if the enclosing volume of the @file is not mounted
390
* yet, it tries to mount it.
392
* When finished or if an error occured, it calls @func with the provided
393
* @user data. The #GError parameter to @func is set if, and only if there
397
thunar_browser_poke_file (ThunarBrowser *browser,
400
ThunarBrowserPokeFileFunc func,
403
_thunar_return_if_fail (THUNAR_IS_BROWSER (browser));
404
_thunar_return_if_fail (THUNAR_IS_FILE (file));
406
thunar_browser_poke_file_internal (browser, file, file, widget, func, user_data);
412
thunar_browser_poke_volume_finish (GObject *object,
413
GAsyncResult *result,
416
PokeVolumeData *poke_data = user_data;
418
GError *error = NULL;
422
_thunar_return_if_fail (G_IS_VOLUME (object));
423
_thunar_return_if_fail (G_IS_ASYNC_RESULT (result));
424
_thunar_return_if_fail (user_data != NULL);
425
_thunar_return_if_fail (THUNAR_IS_BROWSER (poke_data->browser));
426
_thunar_return_if_fail (G_IS_VOLUME (poke_data->volume));
427
_thunar_return_if_fail (G_VOLUME (object) == poke_data->volume);
429
if (!g_volume_mount_finish (G_VOLUME (object), result, &error))
431
if (error->domain == G_IO_ERROR)
433
if (error->code == G_IO_ERROR_ALREADY_MOUNTED)
434
g_clear_error (&error);
440
mount = g_volume_get_mount (poke_data->volume);
441
mount_point = g_mount_get_root (mount);
443
file = thunar_file_get (mount_point, &error);
445
g_object_unref (mount_point);
446
g_object_unref (mount);
448
if (poke_data->func != NULL)
450
(poke_data->func) (poke_data->browser, poke_data->volume, file, error,
451
poke_data->user_data);
455
g_object_unref (file);
459
if (poke_data->func != NULL)
461
(poke_data->func) (poke_data->browser, poke_data->volume, NULL, error,
462
poke_data->user_data);
466
thunar_browser_poke_volume_data_free (poke_data);
472
* thunar_browser_poke_volume:
473
* @browser : a #ThunarBrowser.
474
* @volume : a #GVolume.
475
* @widget : a #GtkWidget, a #GdkScreen or %NULL.
476
* @func : a #ThunarBrowserPokeVolumeFunc callback or %NULL.
477
* @user_data : pointer to arbitrary user data or %NULL.
479
* This function checks if @volume is mounted or not. If it is, it loads
480
* a #ThunarFile for the mount root and calls @func. If it is not mounted,
481
* it first mounts the volume asynchronously and calls @func with the
482
* #ThunarFile corresponding to the mount root when the mounting is finished.
484
* The #ThunarFile passed to @func will be %NULL if, and only if mounting
485
* the @volume failed. The #GError passed to @func will be set if, and only if
489
thunar_browser_poke_volume (ThunarBrowser *browser,
492
ThunarBrowserPokeVolumeFunc func,
495
GMountOperation *mount_operation;
496
PokeVolumeData *poke_data;
498
GError *error = NULL;
502
_thunar_return_if_fail (THUNAR_IS_BROWSER (browser));
503
_thunar_return_if_fail (G_IS_VOLUME (volume));
505
if (thunar_g_volume_is_mounted (volume))
507
mount = g_volume_get_mount (volume);
508
mount_point = g_mount_get_root (mount);
510
file = thunar_file_get (mount_point, &error);
512
g_object_unref (mount_point);
513
g_object_unref (mount);
516
func (browser, volume, file, error, user_data);
518
g_clear_error (&error);
521
g_object_unref (file);
525
poke_data = thunar_browser_poke_volume_data_new (browser, volume, func, user_data);
527
mount_operation = thunar_browser_mount_operation_new (widget);
529
g_volume_mount (volume, G_MOUNT_MOUNT_NONE, mount_operation, NULL,
530
thunar_browser_poke_volume_finish, poke_data);
532
g_object_unref (mount_operation);