~ubuntu-branches/ubuntu/oneiric/libfm/oneiric

« back to all changes in this revision

Viewing changes to .pc/02-libfm-0.1.14-API-changes.patch/src/gtk/fm-gtk-utils.c

  • Committer: Bazaar Package Importer
  • Author(s): Julien Lavergne
  • Date: 2011-02-21 21:55:43 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20110221215543-m7gn2snkhpk1kk9u
Tags: 0.1.15+git-3625952cea-0ubuntu1
* New upstream snapshot (2011-02-15)
 - Use x-schemas-handler (LP: #683922)
* debian/patches/
 - 90_add_gobject_link.patch: Remove, merged upstream.
 - 02-libfm-0.1.14-API-changes.patch: Refresh.
 - 03_disable_deprecated_gio_module.patch: Refresh.
 - 04_fix_docs_linker.patch: Fix DSO linking in docs/.
* debian/libfm0.install:
 - Remove usr/lib/libfm/gnome-terminal, dropped upstream.
 - Remove gio module, dropped upstream.
* debian/rules:
 - Add --enable-gtk-doc to configure.
* debian/libfm-gtk0.symbols:
 - Update with new symbols.
* debian/apport/source_libfm.py
 - Fix location of pcmanfm config files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *      fm-gtk-utils.c
3
 
 *
4
 
 *      Copyright 2009 PCMan <pcman@debian>
5
 
 *
6
 
 *      This program is free software; you can redistribute it and/or modify
7
 
 *      it under the terms of the GNU General Public License as published by
8
 
 *      the Free Software Foundation; either version 2 of the License, or
9
 
 *      (at your option) any later version.
10
 
 *
11
 
 *      This program is distributed in the hope that it will be useful,
12
 
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 *      GNU General Public License for more details.
15
 
 *
16
 
 *      You should have received a copy of the GNU General Public License
17
 
 *      along with this program; if not, write to the Free Software
18
 
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 
 *      MA 02110-1301, USA.
20
 
 */
21
 
 
22
 
#ifdef HAVE_CONFIG_H
23
 
#include <config.h>
24
 
#endif
25
 
 
26
 
#include <glib/gi18n-lib.h>
27
 
#include <gio/gdesktopappinfo.h>
28
 
 
29
 
#include "fm-gtk-utils.h"
30
 
#include "fm-file-ops-job.h"
31
 
#include "fm-progress-dlg.h"
32
 
#include "fm-path-entry.h"
33
 
#include "fm-app-chooser-dlg.h"
34
 
 
35
 
#include "fm-config.h"
36
 
 
37
 
static GtkDialog*   _fm_get_user_input_dialog   (GtkWindow* parent, const char* title, const char* msg);
38
 
static gchar*       _fm_user_input_dialog_run   (GtkDialog* dlg, GtkEntry *entry);
39
 
 
40
 
void fm_show_error(GtkWindow* parent, const char* msg)
41
 
{
42
 
    GtkWidget* dlg = gtk_message_dialog_new(parent, 0,
43
 
                                            GTK_MESSAGE_ERROR,
44
 
                                            GTK_BUTTONS_OK, msg);
45
 
    gtk_window_set_title((GtkWindow*)dlg, _("Error"));
46
 
    gtk_dialog_run((GtkDialog*)dlg);
47
 
    gtk_widget_destroy(dlg);
48
 
}
49
 
 
50
 
gboolean fm_yes_no(GtkWindow* parent, const char* question, gboolean default_yes)
51
 
{
52
 
    int ret;
53
 
    GtkWidget* dlg = gtk_message_dialog_new_with_markup(parent, 0,
54
 
                                GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, question);
55
 
    gtk_dialog_set_default_response(GTK_DIALOG(dlg), default_yes ? GTK_RESPONSE_YES : GTK_RESPONSE_NO);
56
 
    ret = gtk_dialog_run((GtkDialog*)dlg);
57
 
    gtk_widget_destroy(dlg);
58
 
    return ret == GTK_RESPONSE_YES;
59
 
}
60
 
 
61
 
gboolean fm_ok_cancel(GtkWindow* parent, const char* question, gboolean default_ok)
62
 
{
63
 
    int ret;
64
 
    GtkWidget* dlg = gtk_message_dialog_new_with_markup(parent, 0,
65
 
                                GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, question);
66
 
    gtk_dialog_set_default_response(GTK_DIALOG(dlg), default_ok ? GTK_RESPONSE_OK : GTK_RESPONSE_CANCEL);
67
 
    ret = gtk_dialog_run((GtkDialog*)dlg);
68
 
    gtk_widget_destroy(dlg);
69
 
    return ret == GTK_RESPONSE_OK;
70
 
}
71
 
 
72
 
int fm_ask(GtkWindow* parent, const char* question, ...)
73
 
{
74
 
    int ret;
75
 
    va_list args;
76
 
    va_start (args, question);
77
 
    ret = fm_ask_valist(parent, question, args);
78
 
    va_end (args);
79
 
    return ret;
80
 
}
81
 
 
82
 
int fm_askv(GtkWindow* parent, const char* question, const char** options)
83
 
{
84
 
    int ret;
85
 
    guint id = 1;
86
 
    GtkWidget* dlg = gtk_message_dialog_new_with_markup(parent, 0,
87
 
                                GTK_MESSAGE_QUESTION, 0, question);
88
 
    /* FIXME: need to handle defualt button and alternative button
89
 
     * order problems. */
90
 
    while(*options)
91
 
    {
92
 
        /* FIXME: handle button image and stock buttons */
93
 
        GtkWidget* btn = gtk_dialog_add_button(GTK_DIALOG( dlg ), *options, id);
94
 
        ++options;
95
 
        ++id;
96
 
    }
97
 
    ret = gtk_dialog_run((GtkDialog*)dlg);
98
 
    if(ret >= 1)
99
 
        ret -= 1;
100
 
    else
101
 
        ret == -1;
102
 
    gtk_widget_destroy(dlg);
103
 
    return ret;
104
 
}
105
 
 
106
 
int fm_ask_valist(GtkWindow* parent, const char* question, va_list options)
107
 
{
108
 
    GArray* opts = g_array_sized_new(TRUE, TRUE, sizeof(char*), 6);
109
 
    gint ret;
110
 
    const char* opt = va_arg(options, const char*);
111
 
    while(opt)
112
 
    {
113
 
        g_array_append_val(opts, opt);
114
 
        opt = va_arg (options, const char *);
115
 
    }
116
 
    ret = fm_askv(parent, question, opts->data);
117
 
    g_array_free(opts, TRUE);
118
 
    return ret;
119
 
}
120
 
 
121
 
 
122
 
 
123
 
gchar* fm_get_user_input(GtkWindow* parent, const char* title, const char* msg, const char* default_text)
124
 
{
125
 
    GtkDialog* dlg = _fm_get_user_input_dialog( parent, title, msg);
126
 
    GtkWidget* entry = gtk_entry_new();
127
 
    gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
128
 
 
129
 
    if(default_text && default_text[0])
130
 
        gtk_entry_set_text(GTK_ENTRY( entry ), default_text);
131
 
 
132
 
    return _fm_user_input_dialog_run( dlg,  GTK_ENTRY( entry ) );
133
 
}
134
 
 
135
 
FmPath* fm_get_user_input_path(GtkWindow* parent, const char* title, const char* msg, FmPath* default_path)
136
 
{
137
 
 
138
 
    GtkDialog* dlg = _fm_get_user_input_dialog( parent, title, msg);
139
 
    GtkWidget* entry = gtk_entry_new();
140
 
    char *str, *path_str = NULL;
141
 
    FmPath* path;
142
 
 
143
 
    gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
144
 
 
145
 
    if(default_path)
146
 
    {
147
 
        path_str = fm_path_display_name(default_path, FALSE);
148
 
        gtk_entry_set_text(GTK_ENTRY( entry ), path_str);
149
 
    }
150
 
 
151
 
    str = _fm_user_input_dialog_run( dlg,  GTK_ENTRY( entry ) );
152
 
    path = fm_path_new(str);
153
 
 
154
 
    g_free(path_str);
155
 
    g_free(str);
156
 
    return path;
157
 
}
158
 
 
159
 
 
160
 
gchar* fm_get_user_input_rename(GtkWindow* parent, const char* title, const char* msg, const char* default_text)
161
 
{
162
 
    GtkDialog* dlg = _fm_get_user_input_dialog( parent, title, msg);
163
 
    GtkWidget* entry = gtk_entry_new();
164
 
    gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
165
 
 
166
 
    if(default_text && default_text[0])
167
 
    {
168
 
        gtk_entry_set_text(GTK_ENTRY( entry ), default_text);
169
 
        /* only select filename part without extension name. */
170
 
        if(default_text[1])
171
 
        {
172
 
            /* FIXME: handle the special case for *.tar.gz or *.tar.bz2
173
 
             * We should exam the file extension with g_content_type_guess, and
174
 
             * find out a longest valid extension name.
175
 
             * For example, the extension name of foo.tar.gz is .tar.gz, not .gz. */
176
 
            const char* dot = g_utf8_strrchr(default_text, -1, '.');
177
 
            if(dot)
178
 
                gtk_editable_select_region(GTK_EDITABLE(entry), 0, g_utf8_pointer_to_offset(default_text, dot));
179
 
            else
180
 
                gtk_editable_select_region(GTK_EDITABLE(entry), 0, -1);
181
 
            /*
182
 
            const char* dot = default_text;
183
 
            while( dot = g_utf8_strchr(dot + 1, -1, '.') )
184
 
            {
185
 
                gboolean uncertain;
186
 
                char* type = g_content_type_guess(dot-1, NULL, 0, &uncertain);
187
 
                if(!g_content_type_is_unknown(type))
188
 
                {
189
 
                    g_free(type);
190
 
                    gtk_editable_select_region(entry, 0, g_utf8_pointer_to_offset(default_text, dot));
191
 
                    break;
192
 
                }
193
 
                g_free(type);
194
 
            }
195
 
            */
196
 
        }
197
 
    }
198
 
 
199
 
    return _fm_user_input_dialog_run( dlg,  GTK_ENTRY( entry ) );
200
 
}
201
 
 
202
 
static GtkDialog* _fm_get_user_input_dialog(GtkWindow* parent, const char* title, const char* msg)
203
 
{
204
 
    GtkWidget* dlg = gtk_dialog_new_with_buttons(title, parent, GTK_DIALOG_NO_SEPARATOR,
205
 
                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
206
 
                                GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
207
 
    GtkWidget* label = gtk_label_new(msg);
208
 
    gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
209
 
 
210
 
    gtk_dialog_set_alternative_button_order(GTK_DIALOG(dlg), GTK_RESPONSE_OK, GTK_RESPONSE_CANCEL, -1);
211
 
    gtk_box_set_spacing((GtkBox*)gtk_dialog_get_content_area(GTK_DIALOG(dlg)), 6);
212
 
    gtk_box_pack_start((GtkBox*)gtk_dialog_get_content_area(GTK_DIALOG(dlg)), label, FALSE, TRUE, 6);
213
 
 
214
 
    gtk_container_set_border_width(GTK_CONTAINER((GtkBox*)gtk_dialog_get_content_area(GTK_DIALOG(dlg))), 12);
215
 
    gtk_container_set_border_width(GTK_CONTAINER(dlg), 5);
216
 
    gtk_dialog_set_default_response(GTK_DIALOG(dlg), GTK_RESPONSE_OK);
217
 
    gtk_window_set_default_size(GTK_WINDOW(dlg), 480, -1);
218
 
 
219
 
    return dlg;
220
 
}
221
 
 
222
 
static gchar* _fm_user_input_dialog_run( GtkDialog* dlg, GtkEntry *entry)
223
 
{
224
 
    char* str = NULL;
225
 
    int sel_start, sel_end;
226
 
    gboolean has_sel;
227
 
 
228
 
    /* FIXME: this workaround is used to overcome bug of gtk+.
229
 
     * gtk+ seems to ignore select region and select all text for entry in dialog. */
230
 
    has_sel = gtk_editable_get_selection_bounds(GTK_EDITABLE(entry), &sel_start, &sel_end);
231
 
    gtk_box_pack_start(GTK_BOX( GTK_DIALOG(dlg)->vbox ), GTK_WIDGET( entry ), FALSE, TRUE, 6);
232
 
    gtk_widget_show_all(GTK_WIDGET(dlg));
233
 
 
234
 
    if(has_sel)
235
 
        gtk_editable_select_region(GTK_EDITABLE(entry), sel_start, sel_end);
236
 
 
237
 
    while(gtk_dialog_run(dlg) == GTK_RESPONSE_OK)
238
 
    {
239
 
        const char* pstr = gtk_entry_get_text(entry);
240
 
        if( pstr && *pstr )
241
 
        {
242
 
            str = g_strdup(pstr);
243
 
            break;
244
 
        }
245
 
    }
246
 
    gtk_widget_destroy(GTK_WIDGET(dlg));
247
 
    return str;
248
 
}
249
 
 
250
 
FmPath* fm_select_folder(GtkWindow* parent)
251
 
{
252
 
    FmPath* path;
253
 
    GtkFileChooser* chooser;
254
 
    chooser = (GtkFileChooser*)gtk_file_chooser_dialog_new(_("Please select a folder"),
255
 
                                        parent, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
256
 
                                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
257
 
                                        GTK_STOCK_OK, GTK_RESPONSE_OK,
258
 
                                        NULL);
259
 
    gtk_dialog_set_alternative_button_order((GtkDialog*)chooser,
260
 
                                        GTK_RESPONSE_CANCEL,
261
 
                                        GTK_RESPONSE_OK, NULL);
262
 
    if( gtk_dialog_run((GtkDialog*)chooser) == GTK_RESPONSE_OK )
263
 
    {
264
 
        char* file = gtk_file_chooser_get_filename(chooser);
265
 
        if(!file)
266
 
            file = gtk_file_chooser_get_uri(chooser);
267
 
        path = fm_path_new(file);
268
 
        g_free(file);
269
 
    }
270
 
    else
271
 
        path = NULL;
272
 
    gtk_widget_destroy((GtkWidget*)chooser);
273
 
    return path;
274
 
}
275
 
 
276
 
typedef enum
277
 
{
278
 
    MOUNT_VOLUME,
279
 
    MOUNT_GFILE,
280
 
    UMOUNT_MOUNT,
281
 
    EJECT_MOUNT,
282
 
    EJECT_VOLUME
283
 
}MountAction;
284
 
 
285
 
struct MountData
286
 
{
287
 
    GMainLoop *loop;
288
 
    MountAction action;
289
 
    GError* err;
290
 
    gboolean ret;
291
 
};
292
 
 
293
 
static void on_mount_action_finished(GObject* src, GAsyncResult *res, gpointer user_data)
294
 
{
295
 
    struct MountData* data = user_data;
296
 
g_debug("on_mount_action_finished");
297
 
    switch(data->action)
298
 
    {
299
 
    case MOUNT_VOLUME:
300
 
        data->ret = g_volume_mount_finish(G_VOLUME(src), res, &data->err);
301
 
        break;
302
 
    case MOUNT_GFILE:
303
 
        data->ret = g_file_mount_enclosing_volume_finish(G_FILE(src), res, &data->err);
304
 
        break;
305
 
    case UMOUNT_MOUNT:
306
 
#if GLIB_CHECK_VERSION(2, 22, 0)
307
 
        data->ret = g_mount_unmount_with_operation_finish(G_MOUNT(src), res, &data->err);
308
 
#else
309
 
        data->ret = g_mount_unmount_finish(G_MOUNT(src), res, &data->err);
310
 
#endif
311
 
        break;
312
 
    case EJECT_MOUNT:
313
 
#if GLIB_CHECK_VERSION(2, 22, 0)
314
 
        data->ret = g_mount_eject_with_operation_finish(G_MOUNT(src), res, &data->err);
315
 
#else
316
 
        data->ret = g_mount_eject_finish(G_MOUNT(src), res, &data->err);
317
 
#endif
318
 
        break;
319
 
    case EJECT_VOLUME:
320
 
#if GLIB_CHECK_VERSION(2, 22, 0)
321
 
        data->ret = g_volume_eject_with_operation_finish(G_VOLUME(src), res, &data->err);
322
 
#else
323
 
        data->ret = g_volume_eject_finish(G_VOLUME(src), res, &data->err);
324
 
#endif
325
 
        break;
326
 
    }
327
 
    g_main_loop_quit(data->loop);
328
 
}
329
 
 
330
 
static gboolean fm_do_mount(GtkWindow* parent, GObject* obj, MountAction action, gboolean interactive)
331
 
{
332
 
    gboolean ret;
333
 
    struct MountData* data = g_new0(struct MountData, 1);
334
 
    GMountOperation* op = interactive ? gtk_mount_operation_new(parent) : NULL;
335
 
    GCancellable* cancellable = g_cancellable_new();
336
 
 
337
 
    data->loop = g_main_loop_new (NULL, TRUE);
338
 
    data->action = action;
339
 
 
340
 
    switch(data->action)
341
 
    {
342
 
    case MOUNT_VOLUME:
343
 
        g_volume_mount(G_VOLUME(obj), 0, op, cancellable, on_mount_action_finished, data);
344
 
        break;
345
 
    case MOUNT_GFILE:
346
 
        g_file_mount_enclosing_volume(G_FILE(obj), 0, op, cancellable, on_mount_action_finished, data);
347
 
        break;
348
 
    case UMOUNT_MOUNT:
349
 
#if GLIB_CHECK_VERSION(2, 22, 0)
350
 
        g_mount_unmount_with_operation(G_MOUNT(obj), G_MOUNT_UNMOUNT_NONE, op, cancellable, on_mount_action_finished, data);
351
 
#else
352
 
        g_mount_unmount(G_MOUNT(obj), G_MOUNT_UNMOUNT_NONE, cancellable, on_mount_action_finished, data);
353
 
#endif
354
 
        break;
355
 
    case EJECT_MOUNT:
356
 
#if GLIB_CHECK_VERSION(2, 22, 0)
357
 
        g_mount_eject_with_operation(G_MOUNT(obj), G_MOUNT_UNMOUNT_NONE, op, cancellable, on_mount_action_finished, data);
358
 
#else
359
 
        g_mount_eject(G_MOUNT(obj), G_MOUNT_UNMOUNT_NONE, cancellable, on_mount_action_finished, data);
360
 
#endif
361
 
        break;
362
 
    case EJECT_VOLUME:
363
 
#if GLIB_CHECK_VERSION(2, 22, 0)
364
 
        g_volume_eject_with_operation(G_VOLUME(obj), G_MOUNT_UNMOUNT_NONE, op, cancellable, on_mount_action_finished, data);
365
 
#else
366
 
        g_volume_eject(G_VOLUME(obj), G_MOUNT_UNMOUNT_NONE, cancellable, on_mount_action_finished, data);
367
 
#endif
368
 
        break;
369
 
    }
370
 
 
371
 
    if (g_main_loop_is_running(data->loop))
372
 
    {
373
 
        GDK_THREADS_LEAVE();
374
 
        g_main_loop_run(data->loop);
375
 
        GDK_THREADS_ENTER();
376
 
    }
377
 
 
378
 
    g_main_loop_unref(data->loop);
379
 
 
380
 
    ret = data->ret;
381
 
    if(data->err)
382
 
    {
383
 
        if(interactive)
384
 
        {
385
 
            if(data->err->domain == G_IO_ERROR)
386
 
            {
387
 
                if(data->err->code == G_IO_ERROR_FAILED)
388
 
                {
389
 
                    /* Generate a more human-readable error message instead of using a gvfs one. */
390
 
 
391
 
                    /* The original error message is something like:
392
 
                     * Error unmounting: umount exited with exit code 1:
393
 
                     * helper failed with: umount: only root can unmount
394
 
                     * UUID=18cbf00c-e65f-445a-bccc-11964bdea05d from /media/sda4 */
395
 
 
396
 
                    /* Why they pass this back to us?
397
 
                     * This is not human-readable for the users at all. */
398
 
 
399
 
                    if(strstr(data->err->message, "only root can "))
400
 
                    {
401
 
                        g_debug("%s", data->err->message);
402
 
                        g_free(data->err->message);
403
 
                        data->err->message = g_strdup(_("Only system administrators have the permission to do this."));
404
 
                    }
405
 
                }
406
 
                else if(data->err->code == G_IO_ERROR_FAILED_HANDLED)
407
 
                    interactive = FALSE;
408
 
            }
409
 
            if(interactive)
410
 
                fm_show_error(parent, data->err->message);
411
 
        }
412
 
        g_error_free(data->err);
413
 
    }
414
 
 
415
 
    g_free(data);
416
 
    g_object_unref(cancellable);
417
 
    if(op)
418
 
        g_object_unref(op);
419
 
    return ret;
420
 
}
421
 
 
422
 
gboolean fm_mount_path(GtkWindow* parent, FmPath* path, gboolean interactive)
423
 
{
424
 
    GFile* gf = fm_path_to_gfile(path);
425
 
    gboolean ret = fm_do_mount(parent, G_OBJECT(gf), MOUNT_GFILE, interactive);
426
 
    g_object_unref(gf);
427
 
    return ret;
428
 
}
429
 
 
430
 
gboolean fm_mount_volume(GtkWindow* parent, GVolume* vol, gboolean interactive)
431
 
{
432
 
    return fm_do_mount(parent, G_OBJECT(vol), MOUNT_VOLUME, interactive);
433
 
}
434
 
 
435
 
gboolean fm_unmount_mount(GtkWindow* parent, GMount* mount, gboolean interactive)
436
 
{
437
 
    return fm_do_mount(parent, G_OBJECT(mount), UMOUNT_MOUNT, interactive);
438
 
}
439
 
 
440
 
gboolean fm_unmount_volume(GtkWindow* parent, GVolume* vol, gboolean interactive)
441
 
{
442
 
    GMount* mount = g_volume_get_mount(vol);
443
 
    gboolean ret;
444
 
    if(!mount)
445
 
        return FALSE;
446
 
    ret = fm_do_mount(parent, G_OBJECT(vol), UMOUNT_MOUNT, interactive);
447
 
    g_object_unref(mount);
448
 
    return ret;
449
 
}
450
 
 
451
 
gboolean fm_eject_mount(GtkWindow* parent, GMount* mount, gboolean interactive)
452
 
{
453
 
    return fm_do_mount(parent, G_OBJECT(mount), EJECT_MOUNT, interactive);
454
 
}
455
 
 
456
 
gboolean fm_eject_volume(GtkWindow* parent, GVolume* vol, gboolean interactive)
457
 
{
458
 
    return fm_do_mount(parent, G_OBJECT(vol), EJECT_VOLUME, interactive);
459
 
}
460
 
 
461
 
 
462
 
/* File operations */
463
 
/* FIXME: only show the progress dialog if the job isn't finished
464
 
 * in 1 sec. */
465
 
 
466
 
void fm_copy_files(FmPathList* files, FmPath* dest_dir)
467
 
{
468
 
    FmJob* job = fm_file_ops_job_new(FM_FILE_OP_COPY, files);
469
 
    fm_file_ops_job_set_dest(FM_FILE_OPS_JOB(job), dest_dir);
470
 
    fm_file_ops_job_run_with_progress(FM_FILE_OPS_JOB(job));
471
 
}
472
 
 
473
 
void fm_move_files(FmPathList* files, FmPath* dest_dir)
474
 
{
475
 
    FmJob* job = fm_file_ops_job_new(FM_FILE_OP_MOVE, files);
476
 
    fm_file_ops_job_set_dest(FM_FILE_OPS_JOB(job), dest_dir);
477
 
    fm_file_ops_job_run_with_progress(FM_FILE_OPS_JOB(job));
478
 
}
479
 
 
480
 
void fm_trash_files(FmPathList* files)
481
 
{
482
 
    if(!fm_config->confirm_del || fm_yes_no(NULL, _("Do you want to move the selected files to trash can?"), TRUE))
483
 
    {
484
 
        FmJob* job = fm_file_ops_job_new(FM_FILE_OP_TRASH, files);
485
 
        fm_file_ops_job_run_with_progress(FM_FILE_OPS_JOB(job));
486
 
    }
487
 
}
488
 
 
489
 
void fm_untrash_files(FmPathList* files)
490
 
{
491
 
    FmJob* job = fm_file_ops_job_new(FM_FILE_OP_UNTRASH, files);
492
 
    fm_file_ops_job_run_with_progress(FM_FILE_OPS_JOB(job));
493
 
}
494
 
 
495
 
static void fm_delete_files_internal(FmPathList* files)
496
 
{
497
 
    FmJob* job = fm_file_ops_job_new(FM_FILE_OP_DELETE, files);
498
 
    fm_file_ops_job_run_with_progress(FM_FILE_OPS_JOB(job));
499
 
}
500
 
 
501
 
void fm_delete_files(FmPathList* files)
502
 
{
503
 
    if(!fm_config->confirm_del || fm_yes_no(NULL, _("Do you want to delete the selected files?"), TRUE))
504
 
        fm_delete_files_internal(files);
505
 
}
506
 
 
507
 
void fm_trash_or_delete_files(FmPathList* files)
508
 
{
509
 
    if( !fm_list_is_empty(files) )
510
 
    {
511
 
        gboolean all_in_trash = TRUE;
512
 
        if(fm_config->use_trash)
513
 
        {
514
 
            GList* l = fm_list_peek_head_link(files);
515
 
            for(;l;l=l->next)
516
 
            {
517
 
                FmPath* path = FM_PATH(l->data);
518
 
                if(!fm_path_is_trash(path))
519
 
                    all_in_trash = FALSE;
520
 
            }
521
 
        }
522
 
 
523
 
        /* files already in trash:/// should only be deleted and cannot be trashed again. */
524
 
        if(fm_config->use_trash && !all_in_trash)
525
 
            fm_trash_files(files);
526
 
        else
527
 
            fm_delete_files(files);
528
 
    }
529
 
}
530
 
 
531
 
void fm_move_or_copy_files_to(FmPathList* files, gboolean is_move)
532
 
{
533
 
    FmPath* dest = fm_select_folder(NULL);
534
 
    if(dest)
535
 
    {
536
 
        if(is_move)
537
 
            fm_move_files(files, dest);
538
 
        else
539
 
            fm_copy_files(files, dest);
540
 
        fm_path_unref(dest);
541
 
    }
542
 
}
543
 
 
544
 
 
545
 
void fm_rename_file(FmPath* file)
546
 
{
547
 
    GFile* gf = fm_path_to_gfile(file), *parent, *dest;
548
 
    GError* err = NULL;
549
 
    gchar* new_name = fm_get_user_input_rename( NULL, _("Rename File"), _("Please enter a new name:"), file->name);
550
 
    if( !new_name )
551
 
        return;
552
 
    parent = g_file_get_parent(gf);
553
 
    dest = g_file_get_child(parent, new_name);
554
 
    g_object_unref(parent);
555
 
    if(!g_file_move(gf, dest,
556
 
                G_FILE_COPY_ALL_METADATA|
557
 
                G_FILE_COPY_NO_FALLBACK_FOR_MOVE|
558
 
                G_FILE_COPY_NOFOLLOW_SYMLINKS,
559
 
                NULL, /* make this cancellable later. */
560
 
                NULL, NULL, &err))
561
 
    {
562
 
        fm_show_error(NULL, err->message);
563
 
        g_error_free(err);
564
 
    }
565
 
    g_object_unref(dest);
566
 
    g_object_unref(gf);
567
 
}
568
 
 
569
 
void fm_empty_trash()
570
 
{
571
 
    if(fm_yes_no(NULL, _("Are you sure you want to empty the trash can?"), TRUE))
572
 
    {
573
 
        FmPathList* paths = fm_path_list_new();
574
 
        fm_list_push_tail(paths, fm_path_get_trash());
575
 
        fm_delete_files_internal(paths);
576
 
        fm_list_unref(paths);
577
 
    }
578
 
}
579
 
 
580
 
static GAppInfo* choose_app(GList* file_infos, FmMimeType* mime_type, gpointer user_data, GError** err)
581
 
{
582
 
    gpointer* data = (gpointer*)user_data;
583
 
    GtkWindow* parent = (GtkWindow*)data[0];
584
 
    return fm_choose_app_for_mime_type(parent, mime_type, mime_type != NULL);
585
 
}
586
 
 
587
 
static gboolean on_launch_error(GAppLaunchContext* ctx, GError* err, gpointer user_data)
588
 
{
589
 
    gpointer* data = (gpointer*)user_data;
590
 
    GtkWindow* parent = (GtkWindow*)data[0];
591
 
    fm_show_error(parent, err->message);
592
 
    return TRUE;
593
 
}
594
 
 
595
 
static gboolean on_open_folder(GAppLaunchContext* ctx, GList* folder_infos, gpointer user_data, GError** err)
596
 
{
597
 
    gpointer* data = (gpointer*)user_data;
598
 
    FmLaunchFolderFunc func = (FmLaunchFolderFunc)data[1];
599
 
    return func(ctx, folder_infos, data[2], err);
600
 
}
601
 
 
602
 
gboolean fm_launch_files_simple(GtkWindow* parent, GAppLaunchContext* ctx, GList* file_infos, FmLaunchFolderFunc func, gpointer user_data)
603
 
{
604
 
    FmFileLauncher launcher = {
605
 
        choose_app,
606
 
        on_open_folder,
607
 
        on_launch_error
608
 
    };
609
 
    gpointer data[] = {parent, func, user_data};
610
 
    GAppLaunchContext* _ctx = NULL;
611
 
    gboolean ret;
612
 
    if(ctx == NULL)
613
 
    {
614
 
        _ctx = ctx = gdk_app_launch_context_new();
615
 
        gdk_app_launch_context_set_screen(GDK_APP_LAUNCH_CONTEXT(ctx), parent ? gtk_widget_get_screen(GTK_WIDGET(parent)) : gdk_screen_get_default());
616
 
        gdk_app_launch_context_set_timestamp(GDK_APP_LAUNCH_CONTEXT(ctx), gtk_get_current_event_time());
617
 
        /* FIXME: how to handle gdk_app_launch_context_set_icon? */
618
 
    }
619
 
    ret = fm_launch_files(ctx, file_infos, &launcher, data);
620
 
    if(_ctx)
621
 
        g_object_unref(_ctx);
622
 
    return ret;
623
 
}
624
 
 
625
 
gboolean fm_launch_paths_simple(GtkWindow* parent, GAppLaunchContext* ctx, GList* paths, FmLaunchFolderFunc func, gpointer user_data)
626
 
{
627
 
    FmFileLauncher launcher = {
628
 
        choose_app,
629
 
        on_open_folder,
630
 
        on_launch_error
631
 
    };
632
 
    gpointer data[] = {parent, func, user_data};
633
 
    GAppLaunchContext* _ctx = NULL;
634
 
    gboolean ret;
635
 
    if(ctx == NULL)
636
 
    {
637
 
        _ctx = ctx = gdk_app_launch_context_new();
638
 
        gdk_app_launch_context_set_screen(GDK_APP_LAUNCH_CONTEXT(ctx), parent ? gtk_widget_get_screen(GTK_WIDGET(parent)) : gdk_screen_get_default());
639
 
        gdk_app_launch_context_set_timestamp(GDK_APP_LAUNCH_CONTEXT(ctx), gtk_get_current_event_time());
640
 
        /* FIXME: how to handle gdk_app_launch_context_set_icon? */
641
 
    }
642
 
    ret = fm_launch_paths(ctx, paths, &launcher, data);
643
 
    if(_ctx)
644
 
        g_object_unref(_ctx);
645
 
    return ret;
646
 
}
647
 
 
648
 
gboolean fm_launch_file_simple(GtkWindow* parent, GAppLaunchContext* ctx, FmFileInfo* file_info, FmLaunchFolderFunc func, gpointer user_data)
649
 
{
650
 
    gboolean ret;
651
 
    GList* files = g_list_prepend(NULL, file_info);
652
 
    ret = fm_launch_files_simple(parent, ctx, files, func, user_data);
653
 
    g_list_free(files);
654
 
    return ret;
655
 
}
656
 
 
657
 
gboolean fm_launch_path_simple(GtkWindow* parent, GAppLaunchContext* ctx, FmPath* path, FmLaunchFolderFunc func, gpointer user_data)
658
 
{
659
 
    gboolean ret;
660
 
    GList* files = g_list_prepend(NULL, path);
661
 
    ret = fm_launch_paths_simple(parent, ctx, files, func, user_data);
662
 
    g_list_free(files);
663
 
    return ret;
664
 
}