~ubuntu-branches/ubuntu/precise/file-browser-applet/precise

« back to all changes in this revision

Viewing changes to src/vfs.c

  • Committer: Bazaar Package Importer
  • Author(s): Andrew Starr-Bochicchio
  • Date: 2008-08-29 13:50:51 UTC
  • mfrom: (2.1.1 squeeze)
  • Revision ID: james.westby@ubuntu.com-20080829135051-bani7mwsfjdbs9fx
Tags: 0.5.9-1
* New upstream release. (Closes: #497078)
* debian/control:
 - Remove Build-Depend on libgnomevfs2-dev and add Build-Depend
   on libglib2.0-dev as upstream has moved to GIO. (Closes: #493878)
 - Remove depreciated Depends and Build Depends on libgnome-desktop{-dev}
* Fixes Lintian warning: timewarp-standards-version

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * File:                                vfs.c
3
 
 * Created:                             February 2008
 
3
 * Created:                             August 2008
4
4
 * Created by:                  Axel von Bertoldi
5
5
 * Last Modified:               March 2008
6
6
 * Last Modified by:    Axel von Bertoldi
26
26
#include "vfs.h"
27
27
#include "utils.h"
28
28
 
 
29
#include <string.h>
 
30
#include <gio/gio.h>
 
31
#include <gio/gdesktopappinfo.h>
29
32
#include <glib/gprintf.h>
30
 
#include <libgnomevfs/gnome-vfs.h>
31
 
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
32
 
#include <libgnome/gnome-desktop-item.h>
 
33
 
 
34
GtkIconTheme *icon_theme = NULL;
33
35
 
34
36
/******************************************************************************/
35
37
gboolean
36
38
vfs_file_is_executable (const gchar *file_name) {
37
 
        gchar *mime_type = gnome_vfs_get_mime_type (file_name); 
38
 
        gboolean is_executable = FALSE;
39
 
        is_executable =  g_file_test (file_name, G_FILE_TEST_IS_EXECUTABLE) &&
40
 
                                        !g_file_test (file_name, G_FILE_TEST_IS_DIR) &&
41
 
                                        (g_str_has_prefix (mime_type, "application/x-") ||
42
 
                                         g_str_has_prefix (mime_type, "text/x-"));
43
 
        g_free (mime_type);
44
 
        return is_executable;
 
39
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
40
 
 
41
        GFileInfo* file_info =  g_file_query_info (g_file_new_for_path (file_name),
 
42
                                                                                           G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE,
 
43
                                                                                           0,
 
44
                                                                                           NULL,
 
45
                                                                                           NULL);
 
46
 
 
47
        return (g_file_info_get_attribute_boolean (file_info,
 
48
                                                                                          G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE)) &&
 
49
                                !vfs_file_is_directory (file_name); 
45
50
}
46
51
/******************************************************************************/
47
52
gboolean
48
53
vfs_file_is_desktop (const gchar *file_name) {
49
 
        return g_str_has_suffix (file_name, ".desktop");
50
 
}
51
 
/******************************************************************************/
 
54
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
55
 
 
56
        return !(g_desktop_app_info_new_from_filename (file_name) == NULL);
 
57
}
 
58
/******************************************************************************/
 
59
gboolean
 
60
vfs_file_is_directory (const gchar *file_name) {
 
61
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);;
 
62
 
 
63
        GFileInfo* file_info =  g_file_query_info (g_file_new_for_path (file_name),
 
64
                                                                                           "standard::*",
 
65
                                                                                           0,
 
66
                                                                                           NULL,
 
67
                                                                                           NULL);
 
68
 
 
69
        return (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY);
 
70
}
 
71
/******************************************************************************/
 
72
/* Gets the executable file name of the application associated  with the passed
 
73
 * file*/
52
74
gchar *
53
75
vfs_get_mime_application (const gchar *file_name_and_path) {
54
 
        GnomeVFSMimeApplication *mime_application = NULL;
55
 
        gchar *mime_type = NULL;
56
 
        gchar *file_mime_app_exec = NULL;
57
 
        
58
 
        mime_type                = gnome_vfs_get_mime_type (file_name_and_path);        
59
 
        mime_application = gnome_vfs_mime_get_default_application (mime_type);
60
 
 
61
 
        if (mime_application) {
62
 
                file_mime_app_exec = g_strdup ((gchar *)mime_application->command);     
63
 
        }
64
 
 
65
 
        g_free (mime_type);
66
 
        g_free (mime_application);
67
 
 
68
 
        return file_mime_app_exec;
 
76
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
77
 
 
78
        GFileInfo* file_info =  g_file_query_info (g_file_new_for_path (file_name_and_path),
 
79
                                                                                           "standard::*",
 
80
                                                                                           0,
 
81
                                                                                           NULL,
 
82
                                                                                           NULL);
 
83
 
 
84
        return (gchar *)g_app_info_get_executable (
 
85
                                        g_app_info_get_default_for_type (
 
86
                                        g_file_info_get_content_type (file_info), FALSE));
69
87
}
70
88
/******************************************************************************/
71
89
gboolean
73
91
        return g_file_test (file_name, G_FILE_TEST_EXISTS);
74
92
}
75
93
/******************************************************************************/
 
94
/* Gets the contents of a directory. Puts the files and directories in separate
 
95
 * arrays, and sorts them both. */
76
96
gchar *
77
 
vfs_get_dir_contents (GPtrArray *files,
 
97
vfs_get_dir_listings (GPtrArray *files,
78
98
                                          GPtrArray *dirs,
79
99
                                          gboolean show_hidden,
80
100
                                          gchar *path) {
81
 
 
82
 
        GnomeVFSDirectoryHandle *vfs_dir_handle = NULL;
83
 
        GnomeVFSResult                  vfs_result;
84
 
        GnomeVFSFileInfo                *vfs_file_info = NULL;
85
 
        gchar                                   *error = NULL;
86
 
 
87
 
        /*make struct for getting file info, open the dir for reading and get the first entry*/
88
 
        vfs_file_info = gnome_vfs_file_info_new();
89
 
        
90
 
        vfs_result = gnome_vfs_directory_open (&vfs_dir_handle,
91
 
                                                                                   path,
92
 
/*                                                                                 GNOME_VFS_FILE_INFO_GET_MIME_TYPE |*/
93
 
                                                                                   GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
94
 
 
95
 
        /* make sure the dir was opened OK. This fixes bug #3 */
96
 
        if (vfs_result == GNOME_VFS_OK) {
97
 
                /* get the first entry */
98
 
                vfs_result = gnome_vfs_directory_read_next (vfs_dir_handle,
99
 
                                                                                                        vfs_file_info);
100
 
                /* if it opened OK and while its not empty, keep reading items */
101
 
                while (vfs_result == GNOME_VFS_OK) {    
102
 
                        /*if it's not a hidden file or were showing hidden files...*/
103
 
                        if ((g_ascii_strncasecmp (vfs_file_info->name, ".", 1) != 0 || show_hidden) &&
104
 
                                 g_ascii_strcasecmp (vfs_file_info->name, ".") != 0 &&
105
 
                                 g_ascii_strcasecmp (vfs_file_info->name, "..") != 0) {
106
 
 
107
 
                                if (vfs_file_info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) {
108
 
                                        /*make an array that holds all the dirs in this dir*/
109
 
                                        g_ptr_array_add (dirs, (gpointer)g_strdup (vfs_file_info->name));
110
 
                                }
111
 
                                if (vfs_file_info->type == GNOME_VFS_FILE_TYPE_REGULAR) {
112
 
                                        /*make an array that holds all the files in this dir*/
113
 
                                        g_ptr_array_add (files, (gpointer)g_strdup (vfs_file_info->name));
114
 
                                }
115
 
                        }
116
 
                /*get the next entry*/
117
 
                        vfs_result = gnome_vfs_directory_read_next (vfs_dir_handle,
118
 
                                                                                                                vfs_file_info);
119
 
                }
120
 
                /*close the dir*/
121
 
                vfs_result = gnome_vfs_directory_close (vfs_dir_handle);
122
 
        }
123
 
        else {
124
 
                error = g_strdup_printf ("(%s)",gnome_vfs_result_to_string (vfs_result));
125
 
                if (DEBUG) g_printf ("Error opening directory. GNOME_VFS error: %s\n",
126
 
                                                         error);
127
 
        }
128
 
        /**************************** Finished reading dir contents ************************/
129
 
        
130
 
        /*sort the arrays containing the directory and file listings*/
 
101
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
102
 
 
103
        GError *error = NULL;
 
104
        GFile *file = NULL;
 
105
        GFileInfo *file_info = NULL;
 
106
        GFileEnumerator *enummerator = NULL;
 
107
 
 
108
        file = g_file_new_for_path (path);
 
109
        enummerator = g_file_enumerate_children (file,
 
110
                                                                                         "standard::*",
 
111
                                                                                         0,
 
112
                                                                                         NULL,
 
113
                                                                                         &error);
 
114
        /* did we read the dir correctly? */
 
115
        if (error) {
 
116
                gchar *error_msg = g_strdup (error->message);
 
117
                g_error_free (error);
 
118
                error = NULL;
 
119
                return error_msg;
 
120
        }
 
121
 
 
122
        while ((file_info = g_file_enumerator_next_file (enummerator, NULL, &error)) != NULL) {
 
123
                /* skip the file if it's hidden and we aren't showing hidden files */
 
124
                if (g_file_info_get_is_hidden (file_info) && !show_hidden) {
 
125
                        continue;
 
126
                }
 
127
 
 
128
                /* get eh file's human readable name */
 
129
                gchar *display_name = g_strdup (g_file_info_get_display_name (file_info));
 
130
 
 
131
                /* add it to the array */
 
132
                if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY) {
 
133
                        g_ptr_array_add (dirs, (gpointer)display_name);
 
134
                }
 
135
                else {
 
136
                        g_ptr_array_add (files, (gpointer)display_name);
 
137
                }
 
138
        }
 
139
 
 
140
        /* always check for errors */
 
141
        if (error) {
 
142
                gchar *error_msg = g_strdup (error->message);
 
143
                g_error_free (error);
 
144
                error = NULL;
 
145
                return error_msg;
 
146
        }
 
147
 
131
148
        g_ptr_array_sort (dirs, (GCompareFunc)&utils_sort_alpha);
132
149
        g_ptr_array_sort (files, (GCompareFunc)&utils_sort_alpha);
133
150
 
134
 
        gnome_vfs_file_info_clear (vfs_file_info);
135
 
        g_free (vfs_file_info);
136
 
        return error;
 
151
        return NULL;
 
152
}
 
153
/******************************************************************************/
 
154
gboolean
 
155
vfs_launch_desktop_file (const gchar *file_name) {
 
156
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
157
 
 
158
        if (!vfs_file_is_desktop (file_name)) {
 
159
                return FALSE;
 
160
        }
 
161
 
 
162
        GDesktopAppInfo *info = NULL;
 
163
        if ((info = g_desktop_app_info_new_from_filename (file_name)) != NULL) {
 
164
                return g_app_info_launch (G_APP_INFO (info),
 
165
                                                                  NULL,
 
166
                                                                  NULL,
 
167
                                                                  NULL);
 
168
                }
 
169
        return FALSE;
 
170
}
 
171
/******************************************************************************/
 
172
void
 
173
vfs_launch_app (gchar **args, const gchar *working_dir) {
 
174
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
175
 
 
176
        GError *error = NULL;
 
177
        gint child_pid;
 
178
        gboolean ret;
 
179
 
 
180
        ret = g_spawn_async_with_pipes (working_dir,
 
181
                                                                        args,
 
182
                                                                        NULL,
 
183
                                                                        G_SPAWN_SEARCH_PATH,
 
184
                                                                        NULL,
 
185
                                                                        NULL,
 
186
                                                                        &child_pid,
 
187
                                                                        NULL,
 
188
                                                                        NULL,
 
189
                                                                        NULL,
 
190
                                                                        &error);
 
191
 
 
192
        if (utils_check_gerror (&error)) {
 
193
                gchar *tmp = g_strdup_printf ("Error: Failed to launch \"%s\".", args[0]);
 
194
                utils_show_dialog ("Error: Failed to launch application",
 
195
                                                   tmp,
 
196
                                                   GTK_MESSAGE_ERROR);
 
197
                g_free (tmp);
 
198
        }
 
199
        return;
 
200
}
 
201
/******************************************************************************/
 
202
void
 
203
vfs_edit_file (const gchar *file_name_and_path, gchar *editor_bin) {
 
204
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
205
 
 
206
        gchar **args = NULL;
 
207
        gchar *arg = NULL;
 
208
        gchar *working_dir = NULL;
 
209
        int i;
 
210
 
 
211
        working_dir = g_path_get_dirname (file_name_and_path);
 
212
        arg = g_strdelimit (editor_bin, " ", '\1');
 
213
        arg = g_strconcat (arg, "\1", file_name_and_path, NULL);
 
214
        args = g_strsplit (arg, "\1", 0);
 
215
        vfs_launch_app (args, working_dir);
 
216
 
 
217
        g_free (arg);
 
218
        for (i = 0; args[i]; i++) {
 
219
                g_free (args[i]);
 
220
        }
 
221
        g_free (args);
 
222
        g_free (working_dir);
 
223
}
 
224
/******************************************************************************/
 
225
void
 
226
vfs_launch_terminal (const gchar *path, gchar *terminal_bin) {
 
227
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
228
 
 
229
        gchar **args = NULL;
 
230
 
 
231
        args = g_strsplit (terminal_bin, " ", 0);
 
232
 
 
233
        vfs_launch_app (args, path);
 
234
        g_free (args);
 
235
 
 
236
}
 
237
/******************************************************************************/
 
238
void
 
239
vfs_open_file (const gchar *file_name_and_path, gint exec_action) {
 
240
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
241
 
 
242
        gchar **args = NULL;
 
243
        gchar *arg = NULL;
 
244
        gchar *file_mime_app_exec = NULL;
 
245
        gchar *working_dir = NULL;
 
246
        gboolean is_executable;
 
247
        int i;
 
248
 
 
249
        working_dir = g_path_get_dirname (file_name_and_path);
 
250
        is_executable = vfs_file_is_executable (file_name_and_path);
 
251
 
 
252
        file_mime_app_exec = vfs_get_mime_application (file_name_and_path);
 
253
 
 
254
        /* if it's a binary file run it*/
 
255
        if (is_executable) {
 
256
                arg = g_strdup_printf ("%s", file_name_and_path);
 
257
                args = g_strsplit (arg, "\1", 0);
 
258
        }
 
259
        else {
 
260
                if (file_mime_app_exec) {
 
261
                        arg = g_strdelimit (file_mime_app_exec, " ", '\1');
 
262
                        arg = g_strconcat (arg, "\1", file_name_and_path, NULL);
 
263
                        args = g_strsplit (arg, "\1", 0);
 
264
                        if (DEBUG) g_printf ("%s ", file_mime_app_exec);
 
265
                }
 
266
                else {
 
267
                        if (DEBUG) g_printf ("Error: failed to get mime application for %s\n", file_name_and_path);
 
268
                        gchar *message = g_strdup_printf ("Cannot open %s:\n"
 
269
                                                                                          "No application is known for this kind of file.",
 
270
                                                                                          file_name_and_path);
 
271
 
 
272
                        utils_show_dialog ("Error: no application found",
 
273
                                                                                   message,
 
274
                                                                                   GTK_MESSAGE_ERROR);
 
275
                        g_free (message);
 
276
                        return;
 
277
                }
 
278
        }
 
279
        if (DEBUG) g_printf ("%s\n", file_name_and_path);
 
280
        vfs_launch_app (args, working_dir);
 
281
 
 
282
        g_free (arg);
 
283
        for (i = 0; args[i]; i++) {
 
284
                g_free (args[i]);
 
285
        }
 
286
        g_free (args);
 
287
        g_free (file_mime_app_exec);
 
288
}
 
289
/******************************************************************************/
 
290
void
 
291
vfs_trash_file (gchar *file_name) {
 
292
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
293
 
 
294
        GError *error = NULL;
 
295
        GFile *file = g_file_new_for_path (file_name);
 
296
 
 
297
        /* Try moving it to the trash */
 
298
        g_file_trash (file,
 
299
                                  NULL,
 
300
                                  &error);
 
301
 
 
302
        /* Let the user know if we failed. */
 
303
        if (utils_check_gerror (&error)) {
 
304
                gchar *message = g_strdup_printf ("Error: Failed to move \"%s\" to Trash.",
 
305
                                                                                  file_name);
 
306
                utils_show_dialog ("Error: Failed to move tile to Trash",
 
307
                                                   message,
 
308
                                                   GTK_MESSAGE_ERROR);
 
309
                g_free (message);
 
310
        }
 
311
}
 
312
/******************************************************************************/
 
313
/******************************************************************************/
 
314
/* Blatantly stolen (and modified) from nautilus-mime-application-chooser.c.
 
315
 * Returns a pixmap of the image associated with the passed file. .desktop
 
316
 * files will generally be handles by the G_IS_FILE_ICON section. Theme images
 
317
 * are handles by the G_IS_THEMED_ICON section where we first do some shit I
 
318
 * don't understand and if that fails, we ask gtk_icon_theme_choose_icon to
 
319
 * figure out wat icon to use. */
 
320
static GdkPixbuf *
 
321
vfs_get_pixbuf_for_icon (GIcon *icon) {
 
322
        GdkPixbuf  *pixbuf = NULL;
 
323
        gchar *filename;
 
324
 
 
325
        if (G_IS_THEMED_ICON (icon)) {
 
326
                const gchar * const *names = g_themed_icon_get_names (G_THEMED_ICON (icon));
 
327
                GtkIconInfo *icon_info = gtk_icon_theme_choose_icon (icon_theme,
 
328
                                                                                                                         (const gchar **)names,
 
329
                                                                                                                         ICON_MENU_SIZE,
 
330
                                                                                                                         0);
 
331
                pixbuf = gtk_icon_info_load_icon (icon_info, NULL);
 
332
 
 
333
                if (pixbuf == NULL) {
 
334
                        if (names != NULL && names[0] != NULL) {
 
335
                                gchar *icon_no_extension = g_strdup (names[0]);
 
336
                                gchar *p = strrchr (icon_no_extension, '.');
 
337
                                if (p &&
 
338
                                        (strcmp (p, ".png") == 0 ||
 
339
                                         strcmp (p, ".xpm") == 0 ||
 
340
                                         strcmp (p, ".svg") == 0)) {
 
341
                                        *p = 0;
 
342
                                }
 
343
 
 
344
                                pixbuf = gtk_icon_theme_load_icon (icon_theme,
 
345
                                                                                                   icon_no_extension,
 
346
                                                                                                   ICON_MENU_SIZE,
 
347
                                                                                                   0,
 
348
                                                                                                   NULL);
 
349
                                g_free (icon_no_extension);
 
350
                        }
 
351
                }
 
352
        }
 
353
        else if (G_IS_FILE_ICON (icon)) {
 
354
                filename = g_file_get_path (g_file_icon_get_file (G_FILE_ICON (icon)));
 
355
                if (filename) {
 
356
                        pixbuf = gdk_pixbuf_new_from_file_at_size (filename,
 
357
                                                                                                           ICON_MENU_SIZE,
 
358
                                                                                                           ICON_MENU_SIZE,
 
359
                                                                                                           NULL);
 
360
                }
 
361
                g_free (filename);
 
362
        }
 
363
        return pixbuf;
 
364
}
 
365
/******************************************************************************/
 
366
/* Returns the image associated with a file. Works on both normal and desktop
 
367
 * files. */
 
368
GtkWidget *
 
369
vfs_get_icon_for_file (const gchar *file_name) {
 
370
        if (icon_theme == NULL) {
 
371
                icon_theme = gtk_icon_theme_get_default();
 
372
        }
 
373
 
 
374
        GIcon *icon = NULL;
 
375
        GdkPixbuf *icon_pixbuf = NULL; 
 
376
 
 
377
        /* try for desktop file */
 
378
        if (vfs_file_is_desktop (file_name)) {
 
379
                GDesktopAppInfo *info = g_desktop_app_info_new_from_filename (file_name);
 
380
                icon = g_app_info_get_icon (G_APP_INFO (info));
 
381
        }       /* not a desktop file */
 
382
        else {
 
383
                GFileInfo* file_info = g_file_query_info (g_file_new_for_path (file_name),
 
384
                                                                                                  G_FILE_ATTRIBUTE_STANDARD_ICON,
 
385
                                                                                                  0,
 
386
                                                                                                  NULL,
 
387
                                                                                                  NULL);        
 
388
                icon = g_file_info_get_icon (file_info);
 
389
        }
 
390
 
 
391
        if (icon != NULL) {
 
392
                icon_pixbuf = vfs_get_pixbuf_for_icon (icon);
 
393
        }
 
394
 
 
395
        GtkWidget *icon_widget = gtk_image_new_from_pixbuf (icon_pixbuf);
 
396
        g_object_unref (icon_pixbuf);
 
397
 
 
398
        return icon_widget; 
 
399
}
 
400
/******************************************************************************/
 
401
const gchar *
 
402
vfs_get_desktop_app_name (const gchar *file_name) {
 
403
        GDesktopAppInfo *info = g_desktop_app_info_new_from_filename (file_name);
 
404
        return g_app_info_get_name (G_APP_INFO (info));
137
405
}
138
406
/******************************************************************************/