~elementary-apps/pantheon-files/trunk

« back to all changes in this revision

Viewing changes to src/marlin-clipboard-manager.c

  • Committer: Jeremy Wootten
  • Date: 2016-07-10 17:45:51 UTC
  • mto: (2228.2.5 vala-icon-renderer)
  • mto: This revision was merged to the branch mainline in revision 2409.
  • Revision ID: jeremy@elementaryos.org-20160710174551-hritsz1dbriac98q
Rewrite ClipboardManager in Vala

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id$ */
2
 
/*-
3
 
 * Imported from thunar
4
 
 * Copyright (c) 2005-2006 Benedikt Meurer <benny@xfce.org>
5
 
 * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org>
6
 
 *
7
 
 * This program is free software; you can redistribute it and/or modify it
8
 
 * under the terms of the GNU General Public License as published by the Free
9
 
 * Software Foundation; either version 2 of the License, or (at your option)
10
 
 * any later version.
11
 
 *
12
 
 * This program is distributed in the hope that it will be useful, but WITHOUT
13
 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
 
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15
 
 * more details.
16
 
 *
17
 
 * You should have received a copy of the GNU General Public License along with
18
 
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19
 
 * Place, Suite 330, Boston, MA  02111-1307  USA
20
 
 */
21
 
 
22
 
#ifdef HAVE_CONFIG_H
23
 
#include <config.h>
24
 
#endif
25
 
 
26
 
#ifdef HAVE_MEMORY_H
27
 
#include <memory.h>
28
 
#endif
29
 
#ifdef HAVE_STRING_H
30
 
#include <string.h>
31
 
#endif
32
 
 
33
 
#include "marlin-clipboard-manager.h"
34
 
#include <glib.h>
35
 
#include <glib/gi18n.h>
36
 
#include "eel-stock-dialogs.h"
37
 
 
38
 
/*#include <thunar/thunar-application.h>
39
 
#include <thunar/thunar-clipboard-manager.h>
40
 
#include <thunar/thunar-dialogs.h>
41
 
#include <thunar/thunar-gobject-extensions.h>
42
 
#include <thunar/thunar-private.h>*/
43
 
 
44
 
 
45
 
enum
46
 
{
47
 
    PROP_0,
48
 
    PROP_CAN_PASTE,
49
 
};
50
 
 
51
 
enum
52
 
{
53
 
    CHANGED,
54
 
    LAST_SIGNAL,
55
 
};
56
 
 
57
 
enum
58
 
{
59
 
    TARGET_GNOME_COPIED_FILES,
60
 
    TARGET_UTF8_STRING,
61
 
};
62
 
 
63
 
 
64
 
 
65
 
static void marlin_clipboard_manager_finalize           (GObject                     *object);
66
 
static void marlin_clipboard_manager_get_property       (GObject                     *object,
67
 
                                                         guint                        prop_id,
68
 
                                                         GValue                      *value,
69
 
                                                         GParamSpec                  *pspec);
70
 
static void marlin_clipboard_manager_file_destroyed     (GOFFile                  *file,
71
 
                                                         MarlinClipboardManager      *manager);
72
 
static void marlin_clipboard_manager_owner_changed      (GtkClipboard                *clipboard,
73
 
                                                         GdkEventOwnerChange         *event,
74
 
                                                         MarlinClipboardManager      *manager);
75
 
static void marlin_clipboard_manager_contents_received  (GtkClipboard                *clipboard,
76
 
                                                         GtkSelectionData            *selection_data,
77
 
                                                         gpointer                     user_data);
78
 
static void marlin_clipboard_manager_targets_received   (GtkClipboard                *clipboard,
79
 
                                                         GtkSelectionData            *selection_data,
80
 
                                                         gpointer                     user_data);
81
 
static void marlin_clipboard_manager_get_callback       (GtkClipboard                *clipboard,
82
 
                                                         GtkSelectionData            *selection_data,
83
 
                                                         guint                        info,
84
 
                                                         gpointer                     user_data);
85
 
static void marlin_clipboard_manager_clear_callback     (GtkClipboard                *clipboard,
86
 
                                                         gpointer                     user_data);
87
 
static void marlin_clipboard_manager_transfer_files     (MarlinClipboardManager      *manager,
88
 
                                                         gboolean                     copy,
89
 
                                                         GList                       *files);
90
 
 
91
 
 
92
 
 
93
 
struct _MarlinClipboardManagerClass
94
 
{
95
 
    GObjectClass __parent__;
96
 
 
97
 
    void (*changed) (MarlinClipboardManager *manager);
98
 
};
99
 
 
100
 
struct _MarlinClipboardManager
101
 
{
102
 
    GObject __parent__;
103
 
 
104
 
    GtkClipboard *clipboard;
105
 
    gboolean      can_paste;
106
 
    GdkAtom       x_special_gnome_copied_files;
107
 
 
108
 
    gboolean      files_cutted;
109
 
    GList        *files;
110
 
};
111
 
 
112
 
typedef struct
113
 
{
114
 
    MarlinClipboardManager *manager;
115
 
    GFile                  *target_file;
116
 
    GtkWidget              *widget;
117
 
    GCallback               *new_files_closure;
118
 
} MarlinClipboardPasteRequest;
119
 
 
120
 
 
121
 
 
122
 
static const GtkTargetEntry clipboard_targets[] =
123
 
{
124
 
    { "x-special/gnome-copied-files", 0, TARGET_GNOME_COPIED_FILES },
125
 
    { "UTF8_STRING", 0, TARGET_UTF8_STRING }
126
 
};
127
 
 
128
 
static GQuark marlin_clipboard_manager_quark = 0;
129
 
static guint  manager_signals[LAST_SIGNAL];
130
 
 
131
 
 
132
 
 
133
 
G_DEFINE_TYPE (MarlinClipboardManager, marlin_clipboard_manager, G_TYPE_OBJECT)
134
 
 
135
 
 
136
 
 
137
 
static void
138
 
marlin_clipboard_manager_class_init (MarlinClipboardManagerClass *klass)
139
 
{
140
 
    GObjectClass *gobject_class;
141
 
 
142
 
    gobject_class = G_OBJECT_CLASS (klass);
143
 
    gobject_class->finalize = marlin_clipboard_manager_finalize;
144
 
    gobject_class->get_property = marlin_clipboard_manager_get_property;
145
 
 
146
 
    /**
147
 
     * MarlinClipboardManager:can-paste:
148
 
     *
149
 
     * This property tells whether the current clipboard content of
150
 
     * this #MarlinClipboardManager can be pasted into a folder
151
 
     * displayed by a #MarlinView.
152
 
    **/
153
 
    g_object_class_install_property (gobject_class,
154
 
                                     PROP_CAN_PASTE,
155
 
                                     g_param_spec_boolean ("can-paste", "can-paste", "can-paste",
156
 
                                                           FALSE,
157
 
                                                           G_PARAM_READABLE));
158
 
    //amtest
159
 
    // EXO_PARAM_READABLE));
160
 
 
161
 
    /**
162
 
     * MarlinClipboardManager::changed:
163
 
     * @manager : a #MarlinClipboardManager.
164
 
     *
165
 
     * This signal is emitted whenever the contents of the
166
 
     * clipboard associated with @manager changes.
167
 
    **/
168
 
    manager_signals[CHANGED] =
169
 
        g_signal_new ("changed",
170
 
                      G_TYPE_FROM_CLASS (klass),
171
 
                      G_SIGNAL_RUN_FIRST,
172
 
                      G_STRUCT_OFFSET (MarlinClipboardManagerClass, changed),
173
 
                      NULL, NULL,
174
 
                      g_cclosure_marshal_VOID__VOID,
175
 
                      G_TYPE_NONE, 0);
176
 
}
177
 
 
178
 
 
179
 
 
180
 
static void
181
 
marlin_clipboard_manager_init (MarlinClipboardManager *manager)
182
 
{
183
 
    manager->x_special_gnome_copied_files = gdk_atom_intern_static_string ("x-special/gnome-copied-files");
184
 
}
185
 
 
186
 
 
187
 
 
188
 
static void
189
 
marlin_clipboard_manager_finalize (GObject *object)
190
 
{
191
 
    MarlinClipboardManager *manager = MARLIN_CLIPBOARD_MANAGER (object);
192
 
    GList                  *lp;
193
 
 
194
 
    /* release any pending files */
195
 
    for (lp = manager->files; lp != NULL; lp = lp->next)
196
 
    {
197
 
        g_signal_handlers_disconnect_by_func (G_OBJECT (lp->data), marlin_clipboard_manager_file_destroyed, manager);
198
 
        g_object_unref (G_OBJECT (lp->data));
199
 
    }
200
 
    g_list_free (manager->files);
201
 
 
202
 
    /* disconnect from the clipboard */
203
 
    g_signal_handlers_disconnect_by_func (G_OBJECT (manager->clipboard), marlin_clipboard_manager_owner_changed, manager);
204
 
    g_object_set_qdata (G_OBJECT (manager->clipboard), marlin_clipboard_manager_quark, NULL);
205
 
    g_object_unref (G_OBJECT (manager->clipboard));
206
 
 
207
 
    (*G_OBJECT_CLASS (marlin_clipboard_manager_parent_class)->finalize) (object);
208
 
}
209
 
 
210
 
 
211
 
 
212
 
static void
213
 
marlin_clipboard_manager_get_property (GObject    *object,
214
 
                                       guint       prop_id,
215
 
                                       GValue     *value,
216
 
                                       GParamSpec *pspec)
217
 
{
218
 
    MarlinClipboardManager *manager = MARLIN_CLIPBOARD_MANAGER (object);
219
 
 
220
 
    switch (prop_id)
221
 
    {
222
 
    case PROP_CAN_PASTE:
223
 
        g_value_set_boolean (value, marlin_clipboard_manager_get_can_paste (manager));
224
 
        break;
225
 
 
226
 
    default:
227
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
228
 
        break;
229
 
    }
230
 
}
231
 
 
232
 
 
233
 
 
234
 
static void
235
 
marlin_clipboard_manager_file_destroyed (GOFFile             *file,
236
 
                                         MarlinClipboardManager *manager)
237
 
{
238
 
    g_return_if_fail (MARLIN_IS_CLIPBOARD_MANAGER (manager));
239
 
    g_return_if_fail (g_list_find (manager->files, file) != NULL);
240
 
 
241
 
    /* remove the file from our list */
242
 
    manager->files = g_list_remove (manager->files, file);
243
 
 
244
 
    /* disconnect from the file */
245
 
    g_signal_handlers_disconnect_by_func (G_OBJECT (file), marlin_clipboard_manager_file_destroyed, manager);
246
 
    g_object_unref (G_OBJECT (file));
247
 
}
248
 
 
249
 
 
250
 
 
251
 
static void
252
 
marlin_clipboard_manager_owner_changed (GtkClipboard           *clipboard,
253
 
                                        GdkEventOwnerChange    *event,
254
 
                                        MarlinClipboardManager *manager)
255
 
{
256
 
    g_return_if_fail (GTK_IS_CLIPBOARD (clipboard));
257
 
    g_return_if_fail (MARLIN_IS_CLIPBOARD_MANAGER (manager));
258
 
    g_return_if_fail (manager->clipboard == clipboard);
259
 
 
260
 
    /* need to take a reference on the manager, because the clipboards
261
 
     * "targets received callback" mechanism is not cancellable.
262
 
     */
263
 
    g_object_ref (G_OBJECT (manager));
264
 
 
265
 
    /* request the list of supported targets from the new owner */
266
 
    gtk_clipboard_request_contents (clipboard, gdk_atom_intern_static_string ("TARGETS"),
267
 
                                    marlin_clipboard_manager_targets_received, manager);
268
 
}
269
 
 
270
 
static GList *
271
 
convert_lines_to_gfile_list (char **lines)
272
 
{
273
 
    int i;
274
 
    GList *result;
275
 
 
276
 
    if (lines[0] == NULL) {
277
 
        return NULL;
278
 
    }
279
 
 
280
 
    result = NULL;
281
 
    for (i=0; lines[i] != NULL; i++) {
282
 
        result = g_list_prepend (result, g_file_new_for_uri (lines[i]));
283
 
    }
284
 
    return g_list_reverse (result);
285
 
}
286
 
 
287
 
static void
288
 
marlin_clipboard_manager_contents_received (GtkClipboard     *clipboard,
289
 
                                            GtkSelectionData *selection_data,
290
 
                                            gpointer          user_data)
291
 
{
292
 
    MarlinClipboardPasteRequest *request = user_data;
293
 
    MarlinClipboardManager      *manager = MARLIN_CLIPBOARD_MANAGER (request->manager);
294
 
    gboolean                     path_copy = TRUE;
295
 
    GList                       *file_list = NULL;
296
 
    char                        **lines;
297
 
    gchar                       *data;
298
 
 
299
 
    /* check whether the retrieval worked */
300
 
    if (G_LIKELY (gtk_selection_data_get_length (selection_data) > 0))
301
 
    {
302
 
        /* be sure the selection data is zero-terminated */
303
 
        data = (gchar *) gtk_selection_data_get_data (selection_data);
304
 
        data[gtk_selection_data_get_length (selection_data)] = '\0';
305
 
 
306
 
        /* check whether to copy or move */
307
 
        if (g_ascii_strncasecmp (data, "copy", 4) == 0)
308
 
        {
309
 
            path_copy = TRUE;
310
 
            data += 5;
311
 
        }
312
 
        else if (g_ascii_strncasecmp (data, "cut", 3) == 0)
313
 
        {
314
 
            path_copy = FALSE;
315
 
            data += 4;
316
 
        }
317
 
 
318
 
        /* get uris list from selection_data */
319
 
        lines = g_strsplit (data, "\n", 0);
320
 
        file_list = convert_lines_to_gfile_list (lines);
321
 
        g_strfreev (lines);
322
 
    }
323
 
 
324
 
    /* perform the action if possible */
325
 
    if (G_LIKELY (file_list != NULL))
326
 
    {
327
 
        if (G_LIKELY (path_copy))
328
 
        {
329
 
            marlin_file_operations_copy_move (file_list,
330
 
                                              NULL,
331
 
                                              request->target_file,
332
 
                                              GDK_ACTION_COPY,
333
 
                                              request->widget,
334
 
                                              request->new_files_closure,
335
 
                                              request->widget);
336
 
        } else {
337
 
            marlin_file_operations_copy_move (file_list,
338
 
                                              NULL,
339
 
                                              request->target_file,
340
 
                                              GDK_ACTION_MOVE,
341
 
                                              request->widget,
342
 
                                              request->new_files_closure,
343
 
                                              request->widget);
344
 
        }
345
 
 
346
 
        g_list_free_full (file_list, g_object_unref);
347
 
 
348
 
        /* clear the clipboard if it contained "cutted data"
349
 
         * (gtk_clipboard_clear takes care of not clearing
350
 
         * the selection if we don't own it)
351
 
         */
352
 
        if (G_UNLIKELY (!path_copy))
353
 
            gtk_clipboard_clear (manager->clipboard);
354
 
 
355
 
        /* check the contents of the clipboard again if either the Xserver or
356
 
         * our GTK+ version doesn't support the XFixes extension */
357
 
        if (!gdk_display_supports_selection_notification (gtk_clipboard_get_display (manager->clipboard)))
358
 
        {
359
 
            marlin_clipboard_manager_owner_changed (manager->clipboard, NULL, manager);
360
 
        }
361
 
    }
362
 
    else
363
 
    {
364
 
        /* tell the user that we cannot paste */
365
 
        marlin_dialogs_show_error (request->widget, NULL, _("There is nothing on the clipboard to paste"));
366
 
    }
367
 
 
368
 
    /* free the request */
369
 
    if (G_LIKELY (request->widget != NULL))
370
 
        g_object_remove_weak_pointer (G_OBJECT (request->widget), (gpointer) &request->widget);
371
 
 
372
 
    g_object_unref (G_OBJECT (request->manager));
373
 
    g_object_unref (request->target_file);
374
 
    g_slice_free (MarlinClipboardPasteRequest, request);
375
 
}
376
 
 
377
 
 
378
 
 
379
 
static void
380
 
marlin_clipboard_manager_targets_received (GtkClipboard     *clipboard,
381
 
                                           GtkSelectionData *selection_data,
382
 
                                           gpointer          user_data)
383
 
{
384
 
    MarlinClipboardManager *manager = MARLIN_CLIPBOARD_MANAGER (user_data);
385
 
    GdkAtom                *targets;
386
 
    gint                    n_targets;
387
 
    gint                    n;
388
 
 
389
 
    g_return_if_fail (GTK_IS_CLIPBOARD (clipboard));
390
 
    g_return_if_fail (MARLIN_IS_CLIPBOARD_MANAGER (manager));
391
 
    g_return_if_fail (manager->clipboard == clipboard);
392
 
 
393
 
    /* reset the "can-paste" state */
394
 
    manager->can_paste = FALSE;
395
 
 
396
 
    /* check the list of targets provided by the owner */
397
 
    if (gtk_selection_data_get_targets (selection_data, &targets, &n_targets))
398
 
    {
399
 
        for (n = 0; n < n_targets; ++n)
400
 
            if (targets[n] == manager->x_special_gnome_copied_files)
401
 
            {
402
 
                manager->can_paste = TRUE;
403
 
                break;
404
 
            }
405
 
 
406
 
        g_free (targets);
407
 
    }
408
 
 
409
 
    /* notify listeners that we have a new clipboard state */
410
 
    g_signal_emit (manager, manager_signals[CHANGED], 0);
411
 
    g_object_notify (G_OBJECT (manager), "can-paste");
412
 
 
413
 
    /* drop the reference taken for the callback */
414
 
    g_object_unref (manager);
415
 
}
416
 
 
417
 
static char *
418
 
marlin_clipboard_file_list_to_string (MarlinClipboardManager *manager,
419
 
                                      gboolean format_for_text,
420
 
                                      gsize *len)
421
 
{
422
 
    GString *uris;
423
 
    char *uri, *tmp;
424
 
    GFile *f;
425
 
    guint i;
426
 
    GList *l;
427
 
 
428
 
    if (format_for_text) {
429
 
        uris = g_string_new (NULL);
430
 
    } else {
431
 
        uris = g_string_new (manager->files_cutted ? "cut" : "copy");
432
 
    }
433
 
 
434
 
    for (i = 0, l = manager->files; l != NULL; l = l->next, i++) {
435
 
        uri = g_file_get_uri(GOF_FILE(l->data)->location);
436
 
 
437
 
        if (format_for_text) {
438
 
            f = g_file_new_for_uri (uri);
439
 
            tmp = g_file_get_parse_name (f);
440
 
            g_object_unref (f);
441
 
 
442
 
            if (tmp != NULL) {
443
 
                g_string_append (uris, tmp);
444
 
                g_free (tmp);
445
 
            } else {
446
 
                g_string_append (uris, uri);
447
 
            }
448
 
 
449
 
            /* skip newline for last element */
450
 
            if (i + 1 < g_list_length (manager->files)) {
451
 
                g_string_append_c (uris, '\n');
452
 
            }
453
 
        } else {
454
 
            g_string_append_c (uris, '\n');
455
 
            g_string_append (uris, uri);
456
 
        }
457
 
 
458
 
        g_free (uri);
459
 
    }
460
 
 
461
 
    *len = uris->len;
462
 
    return g_string_free (uris, FALSE);
463
 
}
464
 
 
465
 
static void
466
 
marlin_clipboard_manager_get_callback (GtkClipboard     *clipboard,
467
 
                                       GtkSelectionData *selection_data,
468
 
                                       guint             target_info,
469
 
                                       gpointer          user_data)
470
 
{
471
 
    MarlinClipboardManager *manager = MARLIN_CLIPBOARD_MANAGER (user_data);
472
 
    char *str;
473
 
    gsize len;
474
 
 
475
 
    g_return_if_fail (GTK_IS_CLIPBOARD (clipboard));
476
 
    g_return_if_fail (MARLIN_IS_CLIPBOARD_MANAGER (manager));
477
 
    g_return_if_fail (manager->clipboard == clipboard);
478
 
 
479
 
    switch (target_info)
480
 
    {
481
 
    case TARGET_GNOME_COPIED_FILES:
482
 
        str = marlin_clipboard_file_list_to_string (manager, FALSE, &len);
483
 
        gtk_selection_data_set (selection_data, gtk_selection_data_get_target (selection_data), 8, (guchar *) str, len);
484
 
        g_free (str);
485
 
        break;
486
 
 
487
 
    case TARGET_UTF8_STRING:
488
 
        str = marlin_clipboard_file_list_to_string (manager, TRUE, &len);
489
 
        gtk_selection_data_set_text (selection_data, str, len);
490
 
        //gtk_selection_data_set (selection_data, gtk_selection_data_get_target (selection_data), 8, (guchar *) string_list, strlen (string_list));
491
 
        g_free (str);
492
 
        break;
493
 
 
494
 
    default:
495
 
        g_assert_not_reached ();
496
 
    }
497
 
}
498
 
 
499
 
 
500
 
 
501
 
static void
502
 
marlin_clipboard_manager_clear_callback (GtkClipboard *clipboard,
503
 
                                         gpointer      user_data)
504
 
{
505
 
    MarlinClipboardManager *manager = MARLIN_CLIPBOARD_MANAGER (user_data);
506
 
    GList                  *lp;
507
 
 
508
 
    g_return_if_fail (GTK_IS_CLIPBOARD (clipboard));
509
 
    g_return_if_fail (MARLIN_IS_CLIPBOARD_MANAGER (manager));
510
 
    g_return_if_fail (manager->clipboard == clipboard);
511
 
 
512
 
    /* release the pending files */
513
 
    for (lp = manager->files; lp != NULL; lp = lp->next)
514
 
    {
515
 
        g_signal_handlers_disconnect_by_func (G_OBJECT (lp->data), marlin_clipboard_manager_file_destroyed, manager);
516
 
        g_object_unref (G_OBJECT (lp->data));
517
 
    }
518
 
    g_list_free (manager->files);
519
 
    manager->files = NULL;
520
 
}
521
 
 
522
 
 
523
 
 
524
 
static void
525
 
marlin_clipboard_manager_transfer_files (MarlinClipboardManager *manager,
526
 
                                         gboolean                copy,
527
 
                                         GList                  *files)
528
 
{
529
 
    GOFFile *file;
530
 
    GList      *lp;
531
 
 
532
 
    /* release any pending files */
533
 
    for (lp = manager->files; lp != NULL; lp = lp->next)
534
 
    {
535
 
        g_signal_handlers_disconnect_by_func (G_OBJECT (lp->data), marlin_clipboard_manager_file_destroyed, manager);
536
 
        g_object_unref (G_OBJECT (lp->data));
537
 
    }
538
 
    g_list_free (manager->files);
539
 
 
540
 
    /* remember the transfer operation */
541
 
    manager->files_cutted = !copy;
542
 
 
543
 
    /* setup the new file list */
544
 
    for (lp = files, manager->files = NULL; lp != NULL; lp = lp->next)
545
 
    {
546
 
        file = g_object_ref (G_OBJECT (lp->data));
547
 
        manager->files = g_list_prepend (manager->files, file);
548
 
        g_signal_connect (G_OBJECT (file), "destroy", G_CALLBACK (marlin_clipboard_manager_file_destroyed), manager);
549
 
    }
550
 
 
551
 
    /* acquire the CLIPBOARD ownership */
552
 
    gtk_clipboard_set_with_owner (manager->clipboard, clipboard_targets,
553
 
                                  G_N_ELEMENTS (clipboard_targets),
554
 
                                  marlin_clipboard_manager_get_callback,
555
 
                                  marlin_clipboard_manager_clear_callback,
556
 
                                  G_OBJECT (manager));
557
 
 
558
 
    /* Need to fake a "owner-change" event here if the Xserver doesn't support clipboard notification */
559
 
    if (!gdk_display_supports_selection_notification (gtk_clipboard_get_display (manager->clipboard)))
560
 
        marlin_clipboard_manager_owner_changed (manager->clipboard, NULL, manager);
561
 
}
562
 
 
563
 
 
564
 
 
565
 
/**
566
 
 * marlin_clipboard_manager_new_get_for_display:
567
 
 * @display : a #GdkDisplay.
568
 
 *
569
 
 * Determines the #MarlinClipboardManager that is used to manage
570
 
 * the clipboard on the given @display.
571
 
 *
572
 
 * The caller is responsible for freeing the returned object
573
 
 * using g_object_unref() when it's no longer needed.
574
 
 *
575
 
 * Return value: the #MarlinClipboardManager for @display.
576
 
**/
577
 
MarlinClipboardManager*
578
 
marlin_clipboard_manager_new_get_for_display (GdkDisplay *display)
579
 
{
580
 
    MarlinClipboardManager *manager;
581
 
    GtkClipboard           *clipboard;
582
 
 
583
 
    g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
584
 
 
585
 
    /* generate the quark on-demand */
586
 
    if (G_UNLIKELY (marlin_clipboard_manager_quark == 0))
587
 
        marlin_clipboard_manager_quark = g_quark_from_static_string ("marlin-clipboard-manager");
588
 
 
589
 
    /* figure out the clipboard for the given display */
590
 
    clipboard = gtk_clipboard_get_for_display (display, GDK_SELECTION_CLIPBOARD);
591
 
 
592
 
    /* check if a clipboard manager exists */
593
 
    manager = g_object_get_qdata (G_OBJECT (clipboard), marlin_clipboard_manager_quark);
594
 
    if (G_LIKELY (manager != NULL))
595
 
    {
596
 
        g_object_ref (G_OBJECT (manager));
597
 
        return manager;
598
 
    }
599
 
 
600
 
    /* allocate a new manager */
601
 
    manager = g_object_new (MARLIN_TYPE_CLIPBOARD_MANAGER, NULL);
602
 
    manager->clipboard = g_object_ref (G_OBJECT (clipboard));
603
 
    g_object_set_qdata (G_OBJECT (clipboard), marlin_clipboard_manager_quark, manager);
604
 
 
605
 
    /* listen for the "owner-change" signal on the clipboard */
606
 
    g_signal_connect (G_OBJECT (manager->clipboard), "owner-change",
607
 
                      G_CALLBACK (marlin_clipboard_manager_owner_changed), manager);
608
 
 
609
 
    return manager;
610
 
}
611
 
 
612
 
 
613
 
 
614
 
/**
615
 
 * marlin_clipboard_manager_get_can_paste:
616
 
 * @manager : a #MarlinClipboardManager.
617
 
 *
618
 
 * Tells whether the contents of the clipboard represented
619
 
 * by @manager can be pasted into a folder.
620
 
 *
621
 
 * Return value: %TRUE if the contents of the clipboard
622
 
 *               represented by @manager can be pasted
623
 
 *               into a folder.
624
 
**/
625
 
gboolean
626
 
marlin_clipboard_manager_get_can_paste (MarlinClipboardManager *manager)
627
 
{
628
 
    g_return_val_if_fail (MARLIN_IS_CLIPBOARD_MANAGER (manager), FALSE);
629
 
    return manager->can_paste;
630
 
}
631
 
 
632
 
 
633
 
 
634
 
/**
635
 
 * marlin_clipboard_manager_has_cutted_file:
636
 
 * @manager : a #MarlinClipboardManager.
637
 
 * @file    : a #GOFFile.
638
 
 *
639
 
 * Checks whether @file was cutted to the given @manager earlier.
640
 
 *
641
 
 * Return value: %TRUE if @file is on the cutted list of @manager.
642
 
**/
643
 
gboolean
644
 
marlin_clipboard_manager_has_cutted_file (MarlinClipboardManager *manager,
645
 
                                          const GOFFile       *file)
646
 
{
647
 
    g_return_val_if_fail (MARLIN_IS_CLIPBOARD_MANAGER (manager), FALSE);
648
 
    g_return_val_if_fail (GOF_IS_FILE (file), FALSE);
649
 
 
650
 
    return (manager->files_cutted && g_list_find (manager->files, file) != NULL);
651
 
}
652
 
 
653
 
gboolean
654
 
marlin_clipboard_manager_has_file (MarlinClipboardManager *manager,
655
 
                                   const GOFFile       *file)
656
 
{
657
 
    g_return_val_if_fail (MARLIN_IS_CLIPBOARD_MANAGER (manager), FALSE);
658
 
    g_return_val_if_fail (GOF_IS_FILE (file), FALSE);
659
 
 
660
 
    return (g_list_find (manager->files, file) != NULL);
661
 
}
662
 
 
663
 
guint
664
 
marlin_clipboard_manager_count_files (MarlinClipboardManager *manager)
665
 
{
666
 
    g_return_val_if_fail (MARLIN_IS_CLIPBOARD_MANAGER (manager), 0);
667
 
 
668
 
    return g_list_length (manager->files);
669
 
}
670
 
 
671
 
/**
672
 
 * marlin_clipboard_manager_copy_files:
673
 
 * @manager : a #MarlinClipboardManager.
674
 
 * @files   : a list of #GOFFile<!---->s.
675
 
 *
676
 
 * Sets the clipboard represented by @manager to
677
 
 * contain the @files and marks them to be copied
678
 
 * when the user pastes from the clipboard.
679
 
**/
680
 
void
681
 
marlin_clipboard_manager_copy_files (MarlinClipboardManager *manager,
682
 
                                     GList                  *files)
683
 
{
684
 
    g_return_if_fail (MARLIN_IS_CLIPBOARD_MANAGER (manager));
685
 
    marlin_clipboard_manager_transfer_files (manager, TRUE, files);
686
 
}
687
 
 
688
 
 
689
 
 
690
 
/**
691
 
 * marlin_clipboard_manager_cut_files:
692
 
 * @manager : a #MarlinClipboardManager.
693
 
 * @files   : a list of #GOFFile<!---->s.
694
 
 *
695
 
 * Sets the clipboard represented by @manager to
696
 
 * contain the @files and marks them to be moved
697
 
 * when the user pastes from the clipboard.
698
 
**/
699
 
void
700
 
marlin_clipboard_manager_cut_files (MarlinClipboardManager *manager,
701
 
                                    GList                  *files)
702
 
{
703
 
    g_return_if_fail (MARLIN_IS_CLIPBOARD_MANAGER (manager));
704
 
    marlin_clipboard_manager_transfer_files (manager, FALSE, files);
705
 
}
706
 
 
707
 
 
708
 
 
709
 
/**
710
 
 * marlin_clipboard_manager_paste_files:
711
 
 * @manager           : a #MarlinClipboardManager.
712
 
 * @target_file       : the #GFile of the folder to which the contents on the clipboard
713
 
 *                      should be pasted.
714
 
 * @widget            : a #GtkWidget, on which to perform the paste or %NULL if no widget is
715
 
 *                      known.
716
 
 * @new_files_closure : a #GClosure to connect to the job's "new-files" signal,
717
 
 *                      which will be emitted when the job finishes with the
718
 
 *                      list of #GFile<!---->s created by the job, or
719
 
 *                      %NULL if you're not interested in the signal.
720
 
 *
721
 
 * Pastes the contents from the clipboard associated with @manager to the directory
722
 
 * referenced by @target_file.
723
 
**/
724
 
void
725
 
marlin_clipboard_manager_paste_files (MarlinClipboardManager *manager,
726
 
                                      GFile                  *target_file,
727
 
                                      GtkWidget              *widget,
728
 
                                      GCallback     *new_files_closure)
729
 
{
730
 
    MarlinClipboardPasteRequest *request;
731
 
    g_return_if_fail (MARLIN_IS_CLIPBOARD_MANAGER (manager));
732
 
    g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
733
 
 
734
 
    /* prepare the paste request */
735
 
    request = g_slice_new0 (MarlinClipboardPasteRequest);
736
 
    request->manager = g_object_ref (G_OBJECT (manager));
737
 
    request->target_file = g_object_ref (target_file);
738
 
    request->widget = widget;
739
 
 
740
 
    /* take a reference on the closure (if any) */
741
 
    if (G_LIKELY (new_files_closure != NULL))
742
 
    {
743
 
        request->new_files_closure = new_files_closure;
744
 
    }
745
 
 
746
 
    /* get notified when the widget is destroyed prior to
747
 
     * completing the clipboard contents retrieval
748
 
     */
749
 
    if (G_LIKELY (request->widget != NULL))
750
 
        g_object_add_weak_pointer (G_OBJECT (request->widget), (gpointer) &request->widget);
751
 
 
752
 
    /* schedule the request */
753
 
    gtk_clipboard_request_contents (manager->clipboard, manager->x_special_gnome_copied_files,
754
 
                                    marlin_clipboard_manager_contents_received, request);
755
 
}
756