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

« back to all changes in this revision

Viewing changes to src/menu-browser.c

  • Committer: Bazaar Package Importer
  • Author(s): Andrew Starr-Bochicchio
  • Date: 2009-04-11 17:15:39 UTC
  • mfrom: (1.1.4 upstream) (2.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090411171539-jk4kgkvm4i39nv3c
Tags: 0.6.2-1
* New upstream release. (Closes: #504525)
 - Added context menu with a few actions (open-with, new folder here, 
   delete file/folder, create/extract archive, create CD/DVD from 
   file/folder, compile a tex file).
 - Added configuration option to make text vertical/horizontal when 
   the panel is vertical.
 - Added tooltips to configuration dialog.
 - Fixes upstream bugs #21, #30, #34, #37, #39, #43, #44, #45, #49, 
   #51, #56, #59, #60, and #62.
 - Added mnemonic keyboard shortcut to menus for 
   faster keyboard navigation.
 - Added recent documents' support.
 - Improved menu browser focus after context menu close.
 - Added preliminary DnD dragging out of applet. MOVE is the default 
   behaviour.
 - Some code cleanups and plugged memory leaks.
 - Slightly improved "New Folder" dialog.
 - Migrated to gtk+ builder from libglade.
* debian/control:
 - Add suggests on file-roller, brasero, and rubber 
   for new features.
 - Add Vcs-Bzr field.
 - Drop depricated libglade2-dev Build-Depend
 - Drop unneeded libpanel-applet2-0 Depend. Already picked up by 
   shlibs:Depends.
 - Add versionized Build-Depend on libgtk2.0-dev (>= 2.14)
 - Bump Standards-Version to 3.8.1
* debian/copyright:
 - Use /usr/share/common-licenses/GPL-2 rather than just GLP.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * File:                                menu-browser.c
3
 
 * Created:                             September 2005
4
 
 * Created by:                  Axel von Bertoldi
5
 
 * Last Modified:               August 2008
6
 
 * Last Modified by:    Axel von Bertoldi
7
 
 * (C) 2005-2008                Axel von Bertoldi
 
2
 * File:                menu-browser.c
 
3
 * Created:             September 2005
 
4
 * Created by:          Axel von Bertoldi
 
5
 * Last Modified:       August 2008
 
6
 * Last Modified by:    Axel von Bertoldi
 
7
 * (C) 2005-2008        Axel von Bertoldi
8
8
 *
9
9
 * This program is free software; you can redistribute it and/or modify it
10
10
 * under the terms of the GNU General Public License as published by the Free
37
37
#define G_OBJECT_DATA_NAME "item_path"
38
38
/******************************************************************************/
39
39
struct _MenuBrowserPrivate {
40
 
        GtkWidget               *menu_item_label;
41
 
        GtkMenuShell    *parent_menu_shell;
42
 
        Garbage                 garbage;
 
40
    GtkWidget       *menu_item_label;
 
41
    GtkMenuShell    *parent_menu_shell;
 
42
    Garbage         garbage;
43
43
};
44
44
#define MENU_BROWSER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_MENU_BROWSER, MenuBrowserPrivate))
45
45
enum  {
46
 
        MENU_BROWSER_DUMMY_PROPERTY
 
46
    MENU_BROWSER_DUMMY_PROPERTY
 
47
};
 
48
/******************************************************************************/
 
49
static GtkTargetEntry menu_item_target[] = {
 
50
    { "text/uri-list", GTK_TARGET_OTHER_APP, 0 }
47
51
};
48
52
/******************************************************************************/
49
53
static gpointer menu_browser_parent_class = NULL;
52
56
/******************************************************************************/
53
57
static void
54
58
menu_browser_clear_menu (GtkWidget *menu_item) {
55
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
59
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
56
60
 
57
 
        GtkWidget *menu = menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu_item));
58
 
        gtk_container_foreach (GTK_CONTAINER (menu), (GtkCallback) gtk_widget_destroy, NULL);
 
61
    GtkWidget *menu = menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu_item));
 
62
    gtk_container_foreach (GTK_CONTAINER (menu), (GtkCallback) gtk_widget_destroy, NULL);
59
63
}
60
64
/******************************************************************************/
61
65
static void
62
66
menu_browser_clean_up (MenuBrowser *self) {
63
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
64
 
 
65
 
        g_return_if_fail (IS_MENU_BROWSER (self));
66
 
 
67
 
        menu_browser_clear_menu (GTK_WIDGET (self));
68
 
 
69
 
        garbage_empty (&(self->priv->garbage), TRUE);
 
67
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
68
 
 
69
    g_return_if_fail (IS_MENU_BROWSER (self));
 
70
 
 
71
    menu_browser_clear_menu (GTK_WIDGET (self));
 
72
 
 
73
    garbage_empty (&(self->priv->garbage), TRUE);
70
74
}
71
75
/******************************************************************************/
72
76
static void
73
77
menu_browser_on_dir_middle_click (const gchar *path, MenuBrowser *self) {
74
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
75
 
 
76
 
        g_return_if_fail (IS_MENU_BROWSER (self));
77
 
 
78
 
        gchar **args = g_strv_new (ARGS_SIZE);
79
 
        args[ARG_APP]  = g_strdup (self->prefs->terminal);
80
 
        args[ARG_FILE] = g_strdup (path);
81
 
        vfs_launch_application ((const gchar*const*)args);
82
 
        g_strfreev (args);
 
78
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
79
 
 
80
    g_return_if_fail (IS_MENU_BROWSER (self));
 
81
 
 
82
    gchar **args = g_strv_new (ARGS_SIZE);
 
83
    args[ARG_APP]  = g_strdup (self->prefs->terminal);
 
84
    args[ARG_FILE] = g_strdup (path);
 
85
    vfs_launch_application ((const gchar*const*)args);
 
86
    g_strfreev (args);
83
87
}
84
88
/******************************************************************************/
85
89
static void
86
90
menu_browser_on_file_left_click (const gchar *file_name_and_path, MenuBrowser *self) {
87
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
88
 
 
89
 
        g_return_if_fail (IS_MENU_BROWSER (self));
90
 
 
91
 
        vfs_file_do_default_action (file_name_and_path);
 
91
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
92
 
 
93
    g_return_if_fail (IS_MENU_BROWSER (self));
 
94
 
 
95
    vfs_file_do_default_action (file_name_and_path);
92
96
}
93
97
/******************************************************************************/
94
98
static void
95
99
menu_browser_on_file_middle_click (const gchar *file_name_and_path, MenuBrowser *self) {
96
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
97
 
 
98
 
        g_return_if_fail (IS_MENU_BROWSER (self));
99
 
 
100
 
        gchar **args = g_strv_new (ARGS_SIZE);
101
 
        args[ARG_APP]  = g_strdup (self->prefs->editor);
102
 
        args[ARG_FILE] = g_strdup (file_name_and_path);
103
 
        vfs_launch_application ((const gchar*const*)args);
104
 
        g_strfreev (args);
 
100
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
101
 
 
102
    g_return_if_fail (IS_MENU_BROWSER (self));
 
103
 
 
104
    gchar **args = g_strv_new (ARGS_SIZE);
 
105
    args[ARG_APP]  = g_strdup (self->prefs->editor);
 
106
    args[ARG_FILE] = g_strdup (file_name_and_path);
 
107
    vfs_launch_application ((const gchar*const*)args);
 
108
    g_strfreev (args);
105
109
}
106
110
/******************************************************************************/
107
111
static gboolean
108
112
menu_browser_on_file_right_click (const gchar *file_name_and_path, GtkWidget *menu_item) {
109
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
113
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
110
114
#ifdef ENABLE_CONTEXT_MENU
111
 
        return context_menu_display (file_name_and_path, menu_item);
 
115
    return context_menu_display (file_name_and_path, menu_item);
112
116
#else
113
 
        utils_show_dialog (_("Error"),
114
 
                                           _("Right-click on file action not yet implemented."),
115
 
                                           GTK_MESSAGE_INFO);
116
 
        return TRUE;
 
117
    utils_show_dialog (_("Error"),
 
118
                       _("Right-click on file action not yet implemented."),
 
119
                       GTK_MESSAGE_INFO);
 
120
    return TRUE;
117
121
#endif
118
122
}
119
123
/******************************************************************************/
120
124
static void
121
125
menu_browser_on_item_activate (GtkMenuItem *menu_item, MenuBrowser *self) {
122
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
123
 
 
124
 
        g_return_if_fail (IS_MENU_BROWSER (self));
125
 
 
126
 
        gchar *path = (gchar*)g_object_get_data (G_OBJECT (menu_item), G_OBJECT_DATA_NAME);
127
 
 
128
 
        if (!vfs_file_exists (path)) {
129
 
                gchar *tmp = g_strdup_printf (_("Error: The file \"%s\" does not exists."), path);
130
 
                utils_show_dialog (_("Error"), tmp, GTK_MESSAGE_ERROR);
131
 
                g_free (tmp);
132
 
                return;
133
 
        }
134
 
 
135
 
        menu_browser_on_file_left_click (path, self);
 
126
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
127
 
 
128
    g_return_if_fail (IS_MENU_BROWSER (self));
 
129
 
 
130
    gchar *path = (gchar*)g_object_get_data (G_OBJECT (menu_item), G_OBJECT_DATA_NAME);
 
131
 
 
132
    if (!vfs_file_exists (path)) {
 
133
        gchar *tmp = g_strdup_printf (_("Error: The file \"%s\" does not exists."), path);
 
134
        utils_show_dialog (_("Error"), tmp, GTK_MESSAGE_ERROR);
 
135
        g_free (tmp);
 
136
        return;
 
137
    }
 
138
 
 
139
    menu_browser_on_file_left_click (path, self);
136
140
}
137
141
/******************************************************************************/
138
142
static gboolean
139
143
menu_browser_on_item_button_release (GtkWidget *menu_item,
140
 
                                                                     GdkEventButton *event,
 
144
                                     GdkEventButton *event,
141
145
                                     MenuBrowser *self) {
142
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
143
 
 
144
 
        g_return_val_if_fail (IS_MENU_BROWSER (self), FALSE);
145
 
 
146
 
        gchar *path = (gchar*)g_object_get_data (G_OBJECT (menu_item), G_OBJECT_DATA_NAME);
147
 
 
148
 
        if (!vfs_file_exists (path)) {
149
 
                gchar *tmp = g_strdup_printf (_("Error: The file \"%s\" does not exists."), path);
150
 
                utils_show_dialog (_("Error"), tmp, GTK_MESSAGE_ERROR);
151
 
                g_free (tmp);
152
 
                return FALSE;
153
 
        }
 
146
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
147
 
 
148
    g_return_val_if_fail (IS_MENU_BROWSER (self), FALSE);
 
149
 
 
150
    gchar *path = (gchar*)g_object_get_data (G_OBJECT (menu_item), G_OBJECT_DATA_NAME);
 
151
 
 
152
    if (!vfs_file_exists (path)) {
 
153
        gchar *tmp = g_strdup_printf (_("Error: The file \"%s\" does not exists."), path);
 
154
        utils_show_dialog (_("Error"), tmp, GTK_MESSAGE_ERROR);
 
155
        g_free (tmp);
 
156
        return FALSE;
 
157
    }
154
158
    
155
159
    if (event->button == 2) {
156
 
                vfs_file_is_directory (path) ?
157
 
                        menu_browser_on_dir_middle_click (path, self) :
158
 
                        menu_browser_on_file_middle_click (path, self);
 
160
        vfs_file_is_directory (path) ?
 
161
            menu_browser_on_dir_middle_click (path, self) :
 
162
            menu_browser_on_file_middle_click (path, self);
159
163
        gtk_menu_shell_deactivate (self->priv->parent_menu_shell);
160
164
        return TRUE;
161
 
        }
162
 
        else if (event->button == 3) {
 
165
    }
 
166
    else if (event->button == 3) {
163
167
        /* Sigh! Have to set the event button to 0 because the menu items in
164
168
         * the "open with" sub menu in the context menu aren't activated
165
169
         * otherwise. This bug appeared when "button_press_event" was changed
167
171
         * of the main menu. */
168
172
        event->button = 0;
169
173
 
170
 
                g_object_set_data (G_OBJECT (menu_item), "menu_browser", self);
171
 
                g_object_set_data (G_OBJECT (menu_item), "button_event", event);
172
 
                return menu_browser_on_file_right_click (path, menu_item);
173
 
        }
 
174
        g_object_set_data (G_OBJECT (menu_item), "menu_browser", self);
 
175
        g_object_set_data (G_OBJECT (menu_item), "button_event", event);
 
176
        return menu_browser_on_file_right_click (path, menu_item);
 
177
    }
174
178
 
175
 
        return FALSE;
 
179
    return FALSE;
176
180
}
177
181
/******************************************************************************/
178
182
static gboolean
179
183
menu_browser_on_menu_key_release (GtkWidget *menu,
180
184
                                  GdkEventKey *event,
181
185
                                  MenuBrowser *self) {
182
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
183
 
 
184
 
        g_return_val_if_fail (IS_MENU_BROWSER (self), FALSE);
185
 
 
186
 
        GtkMenuShell *menu_shell = GTK_MENU_SHELL (menu);
187
 
        GtkWidget *menu_item = menu_shell->active_menu_item;
188
 
 
189
 
        /* huh!? */
190
 
        if (!self->priv->parent_menu_shell->active || !menu_item) {
191
 
                return FALSE;
192
 
        }
193
 
 
194
 
        gchar *path = (gchar*)g_object_get_data (G_OBJECT (menu_item), G_OBJECT_DATA_NAME);
195
 
 
196
 
        if (!vfs_file_exists (path)) {
197
 
                gchar *tmp = g_strdup_printf ("Error: The file \"%s\" does not exists.", path);
198
 
                utils_show_dialog (_("Error"), tmp, GTK_MESSAGE_ERROR);
199
 
                g_free (tmp);
200
 
                return FALSE;
201
 
        }
 
186
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
187
 
 
188
    g_return_val_if_fail (IS_MENU_BROWSER (self), FALSE);
 
189
 
 
190
    GtkMenuShell *menu_shell = GTK_MENU_SHELL (menu);
 
191
    GtkWidget *menu_item = menu_shell->active_menu_item;
 
192
 
 
193
    /* huh!? */
 
194
    if (!self->priv->parent_menu_shell->active || !menu_item) {
 
195
        return FALSE;
 
196
    }
 
197
 
 
198
    gchar *path = (gchar*)g_object_get_data (G_OBJECT (menu_item), G_OBJECT_DATA_NAME);
 
199
 
 
200
    if (!vfs_file_exists (path)) {
 
201
        gchar *tmp = g_strdup_printf ("Error: The file \"%s\" does not exists.", path);
 
202
        utils_show_dialog (_("Error"), tmp, GTK_MESSAGE_ERROR);
 
203
        g_free (tmp);
 
204
        return FALSE;
 
205
    }
202
206
 
203
207
    /* "Enter" or equivalent a are handled by menu_browser_on_item_activate */
204
208
 
205
 
        if (event->keyval == GDK_F4 ||
206
 
                         event->keyval == GDK_KP_F4) {
 
209
    if (event->keyval == GDK_F4 ||
 
210
             event->keyval == GDK_KP_F4) {
207
211
 
208
 
                vfs_file_is_directory (path) ?
209
 
                        menu_browser_on_dir_middle_click (path, self) :
210
 
                        menu_browser_on_file_middle_click (path, self);
211
 
                gtk_menu_shell_deactivate (self->priv->parent_menu_shell);
 
212
        vfs_file_is_directory (path) ?
 
213
            menu_browser_on_dir_middle_click (path, self) :
 
214
            menu_browser_on_file_middle_click (path, self);
 
215
        gtk_menu_shell_deactivate (self->priv->parent_menu_shell);
212
216
        return TRUE;
213
 
        }
214
 
        else if ((event->keyval == GDK_Menu) ||
215
 
                         (event->keyval == GDK_F10 &&
216
 
                         (event->state & gtk_accelerator_get_default_mod_mask ()) == GDK_SHIFT_MASK)){
217
 
                g_object_set_data (G_OBJECT (menu_item), "menu_browser", self);
218
 
                g_object_set_data (G_OBJECT (menu_item), "button_event", event);
219
 
                return menu_browser_on_file_right_click (path, menu_item);
220
 
        }
221
 
        return FALSE;
 
217
    }
 
218
    else if ((event->keyval == GDK_Menu) ||
 
219
             (event->keyval == GDK_F10 &&
 
220
             (event->state & gtk_accelerator_get_default_mod_mask ()) == GDK_SHIFT_MASK)){
 
221
        g_object_set_data (G_OBJECT (menu_item), "menu_browser", self);
 
222
        g_object_set_data (G_OBJECT (menu_item), "button_event", event);
 
223
        return menu_browser_on_file_right_click (path, menu_item);
 
224
    }
 
225
    return FALSE;
 
226
}
 
227
/******************************************************************************/
 
228
/*static void*/
 
229
/*on_drag_end (GtkWidget *widget,*/
 
230
             /*GdkDragContext *context,*/
 
231
             /*gpointer user_data) {*/
 
232
    /*[> ??? <]*/
 
233
/*}*/
 
234
/******************************************************************************/
 
235
static void
 
236
on_drag_data_get (GtkWidget *widget,
 
237
                  GdkDragContext *context,
 
238
                  GtkSelectionData *selection_data,
 
239
                  guint target_type,
 
240
                  guint time,
 
241
                  const char *uri) {
 
242
 
 
243
    gtk_selection_data_set (selection_data,
 
244
                            selection_data->target,
 
245
                            8,
 
246
                            (guchar *)uri,
 
247
                            strlen(uri));
 
248
}
 
249
/******************************************************************************/
 
250
static void
 
251
on_drag_begin (GtkWidget *menu_item, GdkDragContext *context) {
 
252
 
 
253
    GIcon *icon = NULL;
 
254
    GtkIconSize size;
 
255
    const gchar *icon_name = NULL;
 
256
    gchar *tmp = NULL;
 
257
 
 
258
    GtkWidget *image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (menu_item));
 
259
    gtk_image_get_gicon (GTK_IMAGE(image), &icon, &size);
 
260
 
 
261
    if (G_IS_FILE_ICON(icon)) {
 
262
        /* What do I do now!? */
 
263
        GFile *file = g_file_icon_get_file(G_FILE_ICON(icon));
 
264
        gchar *tmp1 = g_file_get_basename (file);
 
265
        tmp = g_strndup (tmp1, strlen(tmp1) - 4);
 
266
        icon_name = (const gchar*)tmp;
 
267
        g_free(tmp1);
 
268
    }
 
269
    else if (G_IS_THEMED_ICON(icon)) {
 
270
        /* ugly */
 
271
        const char*const* icon_names = g_themed_icon_get_names (G_THEMED_ICON(icon));
 
272
        icon_name = icon_names ? icon_names[0] : NULL;
 
273
    }
 
274
 
 
275
    if (icon_name) {
 
276
        /* Sigh! gtk_drag_source_set_icon_name can't load drag icon from icon
 
277
         * name inode-directory "i.e. folders". Since that will probably be the
 
278
         * most common case, make sure it looks OK. */
 
279
        if (strcmp(icon_name, "inode-directory") == 0)
 
280
            icon_name = "folder";
 
281
 
 
282
        gtk_drag_source_set_icon_name (menu_item, icon_name);
 
283
    }
 
284
    g_free(tmp);
 
285
}
 
286
/******************************************************************************/
 
287
static void
 
288
menu_browser_dnd_setup (GtkWidget *menu_item) {
 
289
    gchar *file_name = g_object_get_data (G_OBJECT (menu_item), G_OBJECT_DATA_NAME);
 
290
    gchar *uri = g_filename_to_uri(file_name, NULL, NULL);
 
291
 
 
292
    gtk_drag_source_set (menu_item,
 
293
                         GDK_BUTTON1_MASK,
 
294
                         menu_item_target,
 
295
                         1,
 
296
                         GDK_ACTION_MOVE | GDK_ACTION_ASK);
 
297
 
 
298
    g_signal_connect_data (menu_item,
 
299
                           "drag_data_get",
 
300
                           G_CALLBACK (on_drag_data_get),
 
301
                           uri,
 
302
                           (GClosureNotify)g_free,
 
303
                            0);
 
304
 
 
305
    g_signal_connect (menu_item,
 
306
                      "drag_begin",
 
307
                      G_CALLBACK (on_drag_begin),
 
308
                      NULL);
 
309
    /*g_signal_connect (menu_item,*/
 
310
                      /*"drag_end",*/
 
311
                      /*G_CALLBACK (on_drag_end),*/
 
312
                      /*NULL);*/
222
313
}
223
314
/******************************************************************************/
224
315
static void
225
316
menu_browser_add_signals (GtkWidget *menu_item, MenuBrowser *self) {
226
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
317
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
227
318
 
228
 
        g_return_if_fail (IS_MENU_BROWSER (self));
 
319
    g_return_if_fail (IS_MENU_BROWSER (self));
229
320
 
230
321
    g_signal_connect (menu_item,
231
322
                      "button_release_event",
236
327
                      "activate",
237
328
                      G_CALLBACK (menu_browser_on_item_activate),
238
329
                      self);
 
330
 
 
331
    menu_browser_dnd_setup (menu_item);
239
332
}
240
333
/******************************************************************************/
241
334
static GtkWidget*
242
335
menu_browser_entry_new (VfsFileInfo *file_info, MenuBrowser *self) {
243
336
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
244
337
 
245
 
        g_return_val_if_fail (IS_MENU_BROWSER (self), NULL);
 
338
    g_return_val_if_fail (IS_MENU_BROWSER (self), NULL);
246
339
 
247
340
    /* Make a menu item for this file/dir, limit the length of the text in the
248
341
     * menu WTH is going on here! Because we're using a mnemonic, we have to
256
349
    /* set the ellipsizig and tooltip */
257
350
    GtkWidget *label = gtk_bin_get_child (GTK_BIN (menu_item));
258
351
    if (GTK_IS_LABEL (label)) {
259
 
        gtk_label_set_max_width_chars (GTK_LABEL (label), MAX_FILE_NAME_LENGTH);        
 
352
        gtk_label_set_max_width_chars (GTK_LABEL (label), MAX_FILE_NAME_LENGTH);    
260
353
        gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_MIDDLE);
261
354
    }
262
355
    if (strlen (file_info->display_name) > MAX_FILE_NAME_LENGTH) {
286
379
/******************************************************************************/
287
380
static void
288
381
menu_browser_add_files (GtkWidget *menu, GPtrArray *files, MenuBrowser *self) {
289
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
290
 
 
291
 
        g_return_if_fail (IS_MENU_BROWSER (self));
292
 
 
293
 
        int i;
294
 
        for (i=0; i<files->len; i++) {
295
 
                VfsFileInfo *vfs_file_info = (VfsFileInfo*)g_ptr_array_index (files, i);
 
382
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
383
 
 
384
    g_return_if_fail (IS_MENU_BROWSER (self));
 
385
 
 
386
    int i;
 
387
    for (i=0; i<files->len; i++) {
 
388
        VfsFileInfo *vfs_file_info = (VfsFileInfo*)g_ptr_array_index (files, i);
296
389
 
297
390
        GtkWidget *menu_item = menu_browser_entry_new (vfs_file_info, self);
298
391
 
299
 
                gtk_menu_shell_append (GTK_MENU_SHELL(menu), menu_item);
 
392
        gtk_menu_shell_append (GTK_MENU_SHELL(menu), menu_item);
300
393
 
301
394
        menu_browser_add_signals (menu_item, self);
302
 
        }
 
395
    }
303
396
}
304
397
/******************************************************************************/
305
398
static void
306
 
menu_browser_add_folders (GtkWidget *menu, GPtrArray *dirs, MenuBrowser *self) {
307
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
308
 
 
309
 
        g_return_if_fail (IS_MENU_BROWSER (self));
310
 
 
311
 
        int i;
312
 
        for (i=0; i<dirs->len; i++) {
313
 
                VfsFileInfo *vfs_file_info = (VfsFileInfo*)g_ptr_array_index (dirs, i);
 
399
menu_browser_add_folders (GtkWidget *menu, GPtrArray *dirs, MenuBrowser *self) {
 
400
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
401
 
 
402
    g_return_if_fail (IS_MENU_BROWSER (self));
 
403
 
 
404
    int i;
 
405
    for (i=0; i<dirs->len; i++) {
 
406
        VfsFileInfo *vfs_file_info = (VfsFileInfo*)g_ptr_array_index (dirs, i);
314
407
 
315
408
        GtkWidget *menu_item = menu_browser_entry_new (vfs_file_info, self);
316
409
 
317
 
                gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
318
 
                /*make the sub menu to show all the files in this dir*/
319
 
                gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), gtk_menu_new ());
 
410
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
 
411
        /*make the sub menu to show all the files in this dir*/
 
412
        gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), gtk_menu_new ());
320
413
 
321
 
                g_signal_connect (GTK_MENU_ITEM (menu_item),
322
 
                                                  "activate",
323
 
                                                  G_CALLBACK (menu_browser_populate_menu),
324
 
                                                  self);
 
414
        g_signal_connect (GTK_MENU_ITEM (menu_item),
 
415
                          "activate",
 
416
                          G_CALLBACK (menu_browser_populate_menu),
 
417
                          self);
325
418
 
326
419
        g_signal_connect (GTK_WIDGET (menu_item),
327
420
                          "button_press_event",
328
421
                          G_CALLBACK (menu_browser_on_item_button_release),
329
422
                          self);
330
423
 
331
 
        }
 
424
    }
332
425
}
333
426
/******************************************************************************/
334
427
static void
335
428
menu_browser_add_menu_header (GtkWidget *menu, gchar *path, MenuBrowser *self) {
336
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
337
 
 
338
 
        g_return_if_fail (IS_MENU_BROWSER (self));
339
 
 
340
 
        VfsFileInfo *vfs_file_info   = g_new0 (VfsFileInfo, 1);
 
429
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
430
 
 
431
    g_return_if_fail (IS_MENU_BROWSER (self));
 
432
 
 
433
    VfsFileInfo *vfs_file_info   = g_new0 (VfsFileInfo, 1);
341
434
    vfs_file_info->display_name  = g_strdup (g_path_get_basename(path));
342
435
    vfs_file_info->file_name     = g_strdup (path);
343
436
    vfs_file_info->icon          = vfs_get_icon_for_file (path);
346
439
    GtkWidget *menu_item = menu_browser_entry_new (vfs_file_info, self);
347
440
    g_free (vfs_file_info);
348
441
 
349
 
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
 
442
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
350
443
 
351
444
    menu_browser_add_signals (menu_item, self);
352
445
 
353
 
        gtk_menu_shell_append (GTK_MENU_SHELL (menu),
354
 
                                                   gtk_separator_menu_item_new());
 
446
    gtk_menu_shell_append (GTK_MENU_SHELL (menu),
 
447
                           gtk_separator_menu_item_new());
355
448
}
356
449
/******************************************************************************/
357
450
static void
358
451
menu_browser_populate_menu (GtkWidget *parent_menu_item, MenuBrowser *self) {
359
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
360
 
 
361
 
        g_return_if_fail (IS_MENU_BROWSER (self));
362
 
 
363
 
        gchar           *current_path = NULL;
364
 
        gchar           *error = NULL;
365
 
        GtkWidget       *menu_item = NULL;
366
 
        GtkWidget       *current_menu = NULL;
367
 
        GPtrArray       *files = g_ptr_array_new();
368
 
        GPtrArray       *dirs = g_ptr_array_new();
369
 
 
370
 
        /* empty the menu of its existing contents first */
371
 
        menu_browser_clear_menu (parent_menu_item);
372
 
 
373
 
        current_path = (gchar*)g_object_get_data (G_OBJECT (parent_menu_item), G_OBJECT_DATA_NAME);
374
 
 
375
 
        /* get the menu widget to pack all the menu items for this dir into */
376
 
        current_menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (parent_menu_item));
 
452
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
453
 
 
454
    g_return_if_fail (IS_MENU_BROWSER (self));
 
455
 
 
456
    gchar       *current_path = NULL;
 
457
    gchar       *error = NULL;
 
458
    GtkWidget   *menu_item = NULL;
 
459
    GtkWidget   *current_menu = NULL;
 
460
    GPtrArray   *files = g_ptr_array_new();
 
461
    GPtrArray   *dirs = g_ptr_array_new();
 
462
 
 
463
    /* empty the menu of its existing contents first */
 
464
    menu_browser_clear_menu (parent_menu_item);
 
465
 
 
466
    current_path = (gchar*)g_object_get_data (G_OBJECT (parent_menu_item), G_OBJECT_DATA_NAME);
 
467
 
 
468
    /* get the menu widget to pack all the menu items for this dir into */
 
469
    current_menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (parent_menu_item));
377
470
 
378
471
    /* If we want to catch key presses/releases, we have to do it before
379
472
     * menu_item signals are emitted. So, we have to watch the menu. */
380
 
        g_signal_connect (current_menu,
381
 
                                          "key_release_event",
382
 
                                          G_CALLBACK (menu_browser_on_menu_key_release),
383
 
                                          self),
384
 
 
385
 
        /* add the dir name and events */
386
 
        menu_browser_add_menu_header (current_menu, current_path, self);
387
 
 
388
 
        /* read the contents of the dir. */
389
 
        error = vfs_get_dir_listings (files,
390
 
                                                                  dirs,
391
 
                                                                  self->prefs->show_hidden,
392
 
                                                                  current_path);
393
 
 
394
 
        /* add the folders*/
395
 
        menu_browser_add_folders (current_menu, dirs, self);
396
 
 
397
 
        if ((dirs->len > 0) & (files->len > 0)) {
398
 
                /*add a separator between dirs and files*/
399
 
                gtk_menu_shell_append (GTK_MENU_SHELL (current_menu),
400
 
                                                           gtk_separator_menu_item_new());
401
 
        }
402
 
 
403
 
        /* add the files */
404
 
        menu_browser_add_files (current_menu, files, self);
405
 
 
406
 
        /* add any error or other messages */
407
 
        if (error != NULL) {
408
 
                menu_item = gtk_menu_item_new_with_label (error);
409
 
                g_free (error);
410
 
                gtk_menu_shell_append (GTK_MENU_SHELL (current_menu), menu_item);
411
 
                gtk_widget_set_sensitive (GTK_WIDGET (menu_item), FALSE);
412
 
        } /* the folder was empty */
413
 
        else if ((dirs->len == 0) & (files->len == 0)) {
414
 
                menu_item = gtk_menu_item_new_with_label (_("(Empty)"));
415
 
                gtk_menu_shell_append (GTK_MENU_SHELL (current_menu), menu_item);
416
 
                gtk_widget_set_sensitive (GTK_WIDGET (menu_item), FALSE);
417
 
        }
418
 
        gtk_widget_show_all (current_menu);
419
 
 
420
 
        /* clean up */
421
 
        g_ptr_array_foreach (dirs, (GFunc)g_free, NULL);
422
 
        g_ptr_array_foreach (files, (GFunc)g_free, NULL);
423
 
        g_ptr_array_free (dirs, TRUE);
424
 
        g_ptr_array_free (files, TRUE);
 
473
    g_signal_connect (current_menu,
 
474
                      "key_release_event",
 
475
                      G_CALLBACK (menu_browser_on_menu_key_release),
 
476
                      self),
 
477
 
 
478
    /* add the dir name and events */
 
479
    menu_browser_add_menu_header (current_menu, current_path, self);
 
480
 
 
481
    /* read the contents of the dir. */
 
482
    error = vfs_get_dir_listings (files,
 
483
                                  dirs,
 
484
                                  self->prefs->show_hidden,
 
485
                                  current_path);
 
486
 
 
487
    /* add the folders*/
 
488
    menu_browser_add_folders (current_menu, dirs, self);
 
489
 
 
490
    if ((dirs->len > 0) & (files->len > 0)) {
 
491
        /*add a separator between dirs and files*/
 
492
        gtk_menu_shell_append (GTK_MENU_SHELL (current_menu),
 
493
                               gtk_separator_menu_item_new());
 
494
    }
 
495
 
 
496
    /* add the files */
 
497
    menu_browser_add_files (current_menu, files, self);
 
498
 
 
499
    /* add any error or other messages */
 
500
    if (error != NULL) {
 
501
        menu_item = gtk_menu_item_new_with_label (error);
 
502
        g_free (error);
 
503
        gtk_menu_shell_append (GTK_MENU_SHELL (current_menu), menu_item);
 
504
        gtk_widget_set_sensitive (GTK_WIDGET (menu_item), FALSE);
 
505
    } /* the folder was empty */
 
506
    else if ((dirs->len == 0) & (files->len == 0)) {
 
507
        menu_item = gtk_menu_item_new_with_label (_("(Empty)"));
 
508
        gtk_menu_shell_append (GTK_MENU_SHELL (current_menu), menu_item);
 
509
        gtk_widget_set_sensitive (GTK_WIDGET (menu_item), FALSE);
 
510
    }
 
511
    gtk_widget_show_all (current_menu);
 
512
 
 
513
    /* clean up */
 
514
    g_ptr_array_foreach (dirs, (GFunc)g_free, NULL);
 
515
    g_ptr_array_foreach (files, (GFunc)g_free, NULL);
 
516
    g_ptr_array_free (dirs, TRUE);
 
517
    g_ptr_array_free (files, TRUE);
425
518
}
426
519
/******************************************************************************/
427
520
void
428
521
menu_browser_update (MenuBrowser *self, const gchar *path, const gchar *label) {
429
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
430
 
 
431
 
        g_return_if_fail (IS_MENU_BROWSER (self));
432
 
 
433
 
        GtkWidget *item_label = GTK_BIN (self)->child;
434
 
        gtk_label_set_text (GTK_LABEL (item_label), label);
435
 
 
436
 
        g_free (g_object_get_data (G_OBJECT (self), G_OBJECT_DATA_NAME));
437
 
        g_object_set_data (G_OBJECT (self), G_OBJECT_DATA_NAME, g_strdup (path));
 
522
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
523
 
 
524
    g_return_if_fail (IS_MENU_BROWSER (self));
 
525
 
 
526
    GtkWidget *item_label = GTK_BIN (self)->child;
 
527
    gtk_label_set_text (GTK_LABEL (item_label), label);
 
528
 
 
529
    g_free (g_object_get_data (G_OBJECT (self), G_OBJECT_DATA_NAME));
 
530
    g_object_set_data (G_OBJECT (self), G_OBJECT_DATA_NAME, g_strdup (path));
438
531
}
439
532
/******************************************************************************/
440
533
static void
441
534
menu_browser_class_init (MenuBrowserClass *klass) {
442
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
535
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
443
536
 
444
 
        menu_browser_parent_class = g_type_class_peek_parent (klass);
445
 
        g_type_class_add_private (klass, sizeof (MenuBrowserPrivate));
446
 
        G_OBJECT_CLASS (klass)->dispose = menu_browser_dispose;
 
537
    menu_browser_parent_class = g_type_class_peek_parent (klass);
 
538
    g_type_class_add_private (klass, sizeof (MenuBrowserPrivate));
 
539
    G_OBJECT_CLASS (klass)->dispose = menu_browser_dispose;
447
540
}
448
541
/******************************************************************************/
449
542
static void
450
543
menu_browser_init (MenuBrowser *self) {
451
 
        
452
 
        g_return_if_fail (IS_MENU_BROWSER (self));
 
544
    
 
545
    g_return_if_fail (IS_MENU_BROWSER (self));
453
546
 
454
 
        self->priv = MENU_BROWSER_GET_PRIVATE (self);
 
547
    self->priv = MENU_BROWSER_GET_PRIVATE (self);
455
548
}
456
549
/******************************************************************************/
457
550
static void
458
551
menu_browser_dispose (GObject *obj) {
459
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
460
 
 
461
 
        MenuBrowser *self = MENU_BROWSER (obj);
462
 
/*      MenuBrowserClass *klass = MENU_BROWSER_CLASS (g_type_class_peek (TYPE_MENU_BROWSER));*/
463
 
 
464
 
        (self->priv->menu_item_label == NULL ? NULL : (self->priv->menu_item_label = (gtk_widget_destroy (self->priv->menu_item_label), NULL)));
465
 
        (self->priv->garbage == NULL ? NULL : garbage_empty (&(self->priv->garbage), FALSE));
466
 
 
467
 
        G_OBJECT_CLASS (menu_browser_parent_class)->dispose (obj);
 
552
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
553
 
 
554
    MenuBrowser *self = MENU_BROWSER (obj);
 
555
/*  MenuBrowserClass *klass = MENU_BROWSER_CLASS (g_type_class_peek (TYPE_MENU_BROWSER));*/
 
556
 
 
557
    (self->priv->menu_item_label == NULL ? NULL : (self->priv->menu_item_label = (gtk_widget_destroy (self->priv->menu_item_label), NULL)));
 
558
    (self->priv->garbage == NULL ? NULL : garbage_empty (&(self->priv->garbage), FALSE));
 
559
 
 
560
    G_OBJECT_CLASS (menu_browser_parent_class)->dispose (obj);
468
561
}
469
562
/******************************************************************************/
470
563
GType
471
564
menu_browser_get_type (void) {
472
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
473
 
 
474
 
        static GType menu_browser_type_id = 0;
475
 
        if (G_UNLIKELY (menu_browser_type_id == 0)) {
476
 
                static const GTypeInfo g_define_type_info = {sizeof (MenuBrowserClass),
477
 
                                                                                                        (GBaseInitFunc) NULL,
478
 
                                                                                                        (GBaseFinalizeFunc) NULL,
479
 
                                                                                                        (GClassInitFunc) menu_browser_class_init,
480
 
                                                                                                        (GClassFinalizeFunc) NULL,
481
 
                                                                                                        NULL,
482
 
                                                                                                        sizeof (MenuBrowser),
483
 
                                                                                                        0,
484
 
                                                                                                        (GInstanceInitFunc) menu_browser_init };
485
 
 
486
 
                menu_browser_type_id = g_type_register_static (GTK_TYPE_IMAGE_MENU_ITEM,
487
 
                                                                                                           "MenuBrowser",
488
 
                                                                                                           &g_define_type_info, 0);
489
 
        }
490
 
        return menu_browser_type_id;
 
565
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
566
 
 
567
    static GType menu_browser_type_id = 0;
 
568
    if (G_UNLIKELY (menu_browser_type_id == 0)) {
 
569
        static const GTypeInfo g_define_type_info = {sizeof (MenuBrowserClass),
 
570
                                                    (GBaseInitFunc) NULL,
 
571
                                                    (GBaseFinalizeFunc) NULL,
 
572
                                                    (GClassInitFunc) menu_browser_class_init,
 
573
                                                    (GClassFinalizeFunc) NULL,
 
574
                                                    NULL,
 
575
                                                    sizeof (MenuBrowser),
 
576
                                                    0,
 
577
                                                    (GInstanceInitFunc) menu_browser_init };
 
578
 
 
579
        menu_browser_type_id = g_type_register_static (GTK_TYPE_IMAGE_MENU_ITEM,
 
580
                                                       "MenuBrowser",
 
581
                                                       &g_define_type_info, 0);
 
582
    }
 
583
    return menu_browser_type_id;
491
584
}
492
585
/******************************************************************************/
493
586
static gboolean
494
587
menu_browser_activate_main_menu (MenuBrowser *self) {
495
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
588
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
496
589
 
497
 
        g_return_val_if_fail (IS_MENU_BROWSER (self), FALSE);
 
590
    g_return_val_if_fail (IS_MENU_BROWSER (self), FALSE);
498
591
 
499
592
    menu_browser_clean_up (self);
500
593
 
501
 
        self->priv->parent_menu_shell =
502
 
                        GTK_MENU_SHELL (gtk_widget_get_parent (GTK_WIDGET (self)));
503
 
 
504
 
        GtkWidget *menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (self));
505
 
 
506
 
        /* this is here because of the solution to the focus problem caused by the
507
 
         * popped context menu */
508
 
        gtk_widget_set_sensitive (GTK_WIDGET (menu), TRUE);
509
 
 
510
 
        menu_browser_populate_menu (GTK_WIDGET (self), self);
511
 
 
512
 
        gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE);
513
 
        gtk_menu_reposition (GTK_MENU (menu));
514
 
        return TRUE;
 
594
    self->priv->parent_menu_shell =
 
595
            GTK_MENU_SHELL (gtk_widget_get_parent (GTK_WIDGET (self)));
 
596
 
 
597
    GtkWidget *menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (self));
 
598
 
 
599
    /* this is here because of the solution to the focus problem caused by the
 
600
     * popped context menu */
 
601
    gtk_widget_set_sensitive (GTK_WIDGET (menu), TRUE);
 
602
 
 
603
    menu_browser_populate_menu (GTK_WIDGET (self), self);
 
604
 
 
605
    gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE);
 
606
    gtk_menu_reposition (GTK_MENU (menu));
 
607
    return TRUE;
515
608
}
516
609
/******************************************************************************/
517
610
GtkWidget*
518
611
menu_browser_new (const gchar* path,
519
 
                                  const gchar* label,
520
 
                                  BrowserPrefs *prefs) {
521
 
        if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
522
 
 
523
 
        MenuBrowser *self = g_object_newv (TYPE_MENU_BROWSER, 0, NULL);
524
 
 
525
 
        self->priv->parent_menu_shell = NULL;
526
 
 
527
 
        if (prefs == NULL) {
528
 
                /* get the default config if none passed. */
529
 
        /*      prefs = preferences_browser_get_default ();*/
530
 
        }
531
 
        self->prefs = prefs;
532
 
 
533
 
        garbage_init(&(self->priv->garbage));
534
 
 
535
 
        GtkWidget *item_label = gtk_label_new (label);
536
 
        gtk_misc_set_alignment (GTK_MISC (item_label), 0.0, 0.5);
537
 
        gtk_container_add (GTK_CONTAINER (self), item_label);
538
 
        self->priv->menu_item_label = item_label;
539
 
 
540
 
        /*make the main menu*/
541
 
        gtk_menu_item_set_submenu (GTK_MENU_ITEM (self), gtk_menu_new());
542
 
 
543
 
        g_object_set_data (G_OBJECT (self), G_OBJECT_DATA_NAME, g_strdup (path));
544
 
 
545
 
        g_signal_connect_after (GTK_MENU_ITEM (self),
 
612
                  const gchar* label,
 
613
                  BrowserPrefs *prefs) {
 
614
    if (DEBUG) g_printf ("In %s\n", __FUNCTION__);
 
615
 
 
616
    MenuBrowser *self = g_object_newv (TYPE_MENU_BROWSER, 0, NULL);
 
617
 
 
618
    self->priv->parent_menu_shell = NULL;
 
619
 
 
620
    if (prefs == NULL) {
 
621
        /* get the default config if none passed. */
 
622
    /*  prefs = preferences_browser_get_default ();*/
 
623
    }
 
624
    self->prefs = prefs;
 
625
 
 
626
    garbage_init(&(self->priv->garbage));
 
627
 
 
628
    GtkWidget *item_label = gtk_label_new (label);
 
629
    gtk_misc_set_alignment (GTK_MISC (item_label), 0.0, 0.5);
 
630
    gtk_container_add (GTK_CONTAINER (self), item_label);
 
631
    self->priv->menu_item_label = item_label;
 
632
 
 
633
    /*make the main menu*/
 
634
    gtk_menu_item_set_submenu (GTK_MENU_ITEM (self), gtk_menu_new());
 
635
 
 
636
    g_object_set_data (G_OBJECT (self), G_OBJECT_DATA_NAME, g_strdup (path));
 
637
 
 
638
    g_signal_connect_after (GTK_MENU_ITEM (self),
546
639
                            "activate",
547
640
                            G_CALLBACK (menu_browser_activate_main_menu),
548
641
                            NULL);
552
645
                              /*G_CALLBACK (menu_browser_clean_up),*/
553
646
                              /*self);*/
554
647
 
555
 
        return GTK_WIDGET (self);
 
648
    return GTK_WIDGET (self);
556
649
}
557
650
/******************************************************************************/