2
* Copyright (C) 2007, 2008, 2009 Rodney Cryderman <rcryderman@gmail.com>
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22
#include "gnome-menu-builder.h"
24
#define GMENU_I_KNOW_THIS_IS_UNSTABLE
25
#include <gnome-menus/gmenu-tree.h>
26
#include <glib/gi18n.h>
27
#include <libdesktop-agnostic/fdo.h>
30
#include <libawn/libawn.h>
31
#include "cairo-menu.h"
32
#include "cairo-menu-item.h"
34
#include "cairo-menu-applet.h"
36
GMenuTree * main_menu_tree = NULL;
37
GMenuTree * settings_menu_tree = NULL;
39
GtkWidget * menu_build (MenuInstance * instance);
40
static GtkWidget * submenu_build (MenuInstance * instance);
43
get_image_from_gicon (GIcon * gicon)
45
const gchar *const * icon_names =NULL;
46
GtkWidget * image = NULL;
47
if (G_IS_THEMED_ICON (gicon))
49
icon_names = g_themed_icon_get_names (G_THEMED_ICON(gicon));
53
const gchar *const *i;
54
for (i=icon_names; *i; i++)
56
image = get_gtk_image (*i);
67
add_special_item (GtkWidget * menu,
69
const gchar * icon_name,
78
bin_path = g_find_program_in_path (binary);
83
if (bin_path != binary)
87
item = cairo_menu_item_new_with_label (name);
88
image = get_gtk_image (icon_name);
91
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),image);
93
exec = g_strdup_printf("%s %s", binary ,args);
94
g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_exec), exec);
95
g_object_weak_ref (G_OBJECT(item),(GWeakNotify) g_free,exec);
96
gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
101
_fill_session_menu (GtkWidget * menu)
103
gboolean have_gnome_session_manager = dbus_service_exists ("org.gnome.SessionManager");
105
if (have_gnome_session_manager)
107
add_special_item (menu,_("Logout"),"gnome-logout","gnome-session-save","--logout-dialog --gui");
109
else if (dbus_service_exists ("org.xfce.SessionManager") )
111
add_special_item (menu,_("Logout"),"gnome-logout","xfce4-session-logout","");
115
/* hope that gnome-session-save exists; needed for GNOME 2.22, at least. */
116
add_special_item (menu, _("Logout"), "gnome-logout", "gnome-session-save",
119
if (dbus_service_exists ("org.gnome.ScreenSaver"))
121
if (!add_special_item (menu,_("Lock Screen"),"gnome-lockscreen","gnome-screensaver-command","--lock"))
123
add_special_item (menu,_("Lock Screen"),"gnome-lockscreen","dbus-send","--session --dest=org.gnome.ScreenSaver --type=method_call --print-reply --reply-timeout=2000 /org/gnome/ScreenSaver org.gnome.ScreenSaver.Lock");
128
add_special_item (menu,_("Lock Screen"),"system-lock-screen","xscreensaver-command","-lock");
130
if (dbus_service_exists ("org.freedesktop.PowerManagement"))
132
if (!add_special_item (menu,_("Suspend"),"gnome-session-suspend","gnome-power-cmd","suspend"))
134
add_special_item (menu,_("Suspend"),"gnome-session-suspend","dbus-send","--session --dest=org.freedesktop.PowerManagement --type=method_call --print-reply --reply-timeout=2000 /org/freedesktop/PowerManagement org.freedesktop.PowerManagement.Suspend");
137
if (!add_special_item (menu,_("Hibernate"),"gnome-session-hibernate","gnome-power-cmd","hibernate"))
139
add_special_item (menu,_("Hibernate"),"gnome-session-hibernate","dbus-send","--session --dest=org.freedesktop.PowerManagement --type=method_call --print-reply --reply-timeout=2000 /org/freedesktop/PowerManagement org.freedesktop.PowerManagement.Hibernate");
143
else if (dbus_service_exists ("org.gnome.PowerManagement"))
145
if (!add_special_item (menu,_("Suspend"),"gnome-session-suspend","gnome-power-cmd","suspend"))
150
if (!add_special_item (menu,_("Hibernate"),"gnome-session-hibernate","gnome-power-cmd","hibernate"))
156
if (have_gnome_session_manager)
158
add_special_item (menu,_("Shutdown"),"gnome-logout","gnome-session-save","--shutdown-dialog --gui");
160
gtk_widget_show_all (menu);
165
get_session_menu(void)
167
GtkWidget *menu = cairo_menu_new();
168
/*so we don't stall checking the dbus services on applet startup*/
169
g_idle_add ((GSourceFunc)_fill_session_menu,menu);
174
check for existence of the various bins.
175
why are vfs network mounts not showing?
176
The menu item order needs to be fixed.
179
_get_places_menu (GtkWidget * menu)
181
static GVolumeMonitor* vol_monitor = NULL;
182
static DesktopAgnosticVFSGtkBookmarks *bookmarks_parser = NULL;
184
GtkWidget *item = NULL;
185
GError *error = NULL;
188
const gchar *desktop_dir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
189
const gchar *homedir = g_get_home_dir();
191
gtk_container_foreach (GTK_CONTAINER (menu),(GtkCallback)_remove_menu_item,menu);
193
add_special_item (menu,_("Computer"),"computer","nautilus","computer:///");
194
add_special_item (menu,_("Home"),"stock_home",XDG_OPEN,homedir);
195
add_special_item (menu,_("Desktop"),"desktop",XDG_OPEN,desktop_dir?desktop_dir:homedir);
197
TODO: check the trash and set to stock_trash_empty if trash is empty
199
add_special_item (menu,_("Trash"),"stock_trash_full","nautilus","trash:///");
200
add_special_item (menu,_("File System"),"system",XDG_OPEN,"/");
204
/*this is structured like this because get_places() is
205
invoked any time there is a change in places... only want perform
206
these actions once.*/
207
vol_monitor = g_volume_monitor_get();
208
bookmarks_parser = desktop_agnostic_vfs_gtk_bookmarks_new (NULL, TRUE);
210
g_signal_handlers_disconnect_by_func (vol_monitor, G_CALLBACK(_get_places_menu), menu);
211
g_signal_handlers_disconnect_by_func (vol_monitor, G_CALLBACK(_get_places_menu), menu);
212
g_signal_handlers_disconnect_by_func (vol_monitor, G_CALLBACK(_get_places_menu), menu);
213
g_signal_handlers_disconnect_by_func (vol_monitor, G_CALLBACK(_get_places_menu), menu);
214
g_signal_handlers_disconnect_by_func (vol_monitor, G_CALLBACK(_get_places_menu), menu);
215
g_signal_handlers_disconnect_by_func (vol_monitor, G_CALLBACK(_get_places_menu), menu);
216
g_signal_handlers_disconnect_by_func (vol_monitor, G_CALLBACK(_get_places_menu), menu);
217
g_signal_handlers_disconnect_by_func (G_OBJECT (bookmarks_parser), G_CALLBACK (_get_places_menu), menu);
219
g_signal_connect_swapped(vol_monitor, "volume-changed", G_CALLBACK(_get_places_menu), menu);
220
g_signal_connect_swapped(vol_monitor, "drive-changed", G_CALLBACK(_get_places_menu), menu);
221
g_signal_connect_swapped(vol_monitor, "drive-connected", G_CALLBACK(_get_places_menu), menu);
222
g_signal_connect_swapped(vol_monitor, "drive-disconnected", G_CALLBACK(_get_places_menu), menu);
223
g_signal_connect_swapped(vol_monitor, "mount-changed", G_CALLBACK(_get_places_menu), menu);
224
g_signal_connect_swapped(vol_monitor, "mount-added", G_CALLBACK(_get_places_menu), menu);
225
g_signal_connect_swapped(vol_monitor, "mount-removed", G_CALLBACK(_get_places_menu), menu);
226
g_signal_connect_swapped (G_OBJECT (bookmarks_parser), "changed",
227
G_CALLBACK (_get_places_menu), menu);
229
/*process mount etc*/
230
GList *drives = g_volume_monitor_get_connected_drives(vol_monitor);
231
GList *mounts = g_volume_monitor_get_mounts (vol_monitor);
236
g_message("Number of volumes: %d", g_list_length(volumes));
237
g_list_foreach(volumes, (GFunc)_fillin_connected, menu);
240
this iterating through mounts then drives may change.
241
May go to using mounts and volumes.
243
for (iter = mounts; iter ; iter = g_list_next (iter))
245
GMount *mount = iter->data;
246
gchar * name = g_mount_get_name (mount);
247
GIcon * gicon = g_mount_get_icon (mount);
248
GFile * file = g_mount_get_root (mount);
249
gchar * uri = g_file_get_uri (file);
250
item = cairo_menu_item_new_with_label (name);
251
image = get_image_from_gicon (gicon);
254
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),image);
256
gtk_menu_shell_append (GTK_MENU_SHELL(menu),item);
258
exec = g_strdup_printf("%s %s", XDG_OPEN, uri);
259
g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_exec), exec);
260
g_object_weak_ref (G_OBJECT(item), (GWeakNotify)g_free,exec);
264
g_object_unref (file);
265
g_object_unref (gicon);
270
item = gtk_separator_menu_item_new ();
271
gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
274
for (iter = drives; iter ; iter = g_list_next (iter))
276
GDrive * drive = iter->data;
277
if (g_drive_has_volumes (drive))
279
GList * drive_volumes = g_drive_get_volumes (drive);
280
GList * vol_iter = NULL;
281
for (vol_iter =drive_volumes;vol_iter;vol_iter=g_list_next(vol_iter))
283
GVolume * volume = vol_iter->data;
284
GIcon * gicon = g_volume_get_icon (volume);
285
gchar * name = g_volume_get_name (volume);
287
item = cairo_menu_item_new_with_label (name);
288
image = get_image_from_gicon (gicon);
291
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),image);
293
gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
296
g_list_foreach (drive_volumes,(GFunc)g_object_unref,NULL);
297
g_list_free (drive_volumes);
301
gboolean mounted = FALSE;
302
gchar * name = g_drive_get_name (drive);
303
GIcon * gicon = g_drive_get_icon (drive);
305
item = cairo_menu_item_new_with_label (name);
306
image = get_image_from_gicon (gicon);
309
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),image);
311
gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
316
g_list_foreach (drives,(GFunc)g_object_unref,NULL);
317
g_list_free (drives);
318
g_list_foreach (mounts,(GFunc)g_object_unref,NULL);
319
g_list_free (mounts);
321
add_special_item (menu,_("Network"),"network","nautilus","network:/");
322
add_special_item (menu,_("Connect to Server"),"stock_connect","nautilus-connect-server","");
323
item = gtk_separator_menu_item_new ();
324
gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
331
bookmarks = desktop_agnostic_vfs_gtk_bookmarks_get_bookmarks (bookmarks_parser);
332
for (node = bookmarks; node != NULL; node = node->next)
334
DesktopAgnosticVFSBookmark *bookmark;
335
DesktopAgnosticVFSFile *b_file;
336
const gchar *b_alias;
339
gchar *shell_quoted = NULL;
340
gchar *icon_name = NULL;
342
bookmark = (DesktopAgnosticVFSBookmark*)node->data;
343
b_file = desktop_agnostic_vfs_bookmark_get_file (bookmark);
344
b_alias = desktop_agnostic_vfs_bookmark_get_alias (bookmark);
345
b_path = desktop_agnostic_vfs_file_get_path (b_file);
346
b_uri = desktop_agnostic_vfs_file_get_uri (b_file);
350
shell_quoted = g_shell_quote (b_path);
351
exec = g_strdup_printf("%s %s", XDG_OPEN,shell_quoted);
352
g_free (shell_quoted);
355
item = cairo_menu_item_new_with_label (b_alias);
356
icon_name = g_utf8_strdown (b_alias,-1);
360
gchar * base = g_path_get_basename (b_path);
361
item = cairo_menu_item_new_with_label (base);
362
icon_name = g_utf8_strdown (base,-1);
365
g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_exec), exec);
366
gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
368
else if ( strncmp(b_uri, "http", 4)==0 )
370
shell_quoted = g_shell_quote (b_uri);
371
exec = g_strdup_printf("%s %s",XDG_OPEN,shell_quoted);
372
g_free (shell_quoted);
375
item = cairo_menu_item_new_with_label (b_alias);
376
icon_name = g_utf8_strdown (b_alias,-1);
380
gchar * base = g_path_get_basename (b_uri);
381
item = cairo_menu_item_new_with_label (b_uri);
382
icon_name = g_utf8_strdown (base,-1);
385
g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_exec), exec);
386
gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
389
non-http(s) uris. open with nautils. obviously we should be smarter about
394
shell_quoted = g_shell_quote (b_uri);
395
exec = g_strdup_printf("%s %s", "nautilus" ,shell_quoted);
396
g_free (shell_quoted);
399
item = cairo_menu_item_new_with_label (b_alias);
400
icon_name = g_utf8_strdown (b_alias,-1);
404
gchar * base = g_path_get_basename (b_uri);
405
item = cairo_menu_item_new_with_label (base);
406
icon_name = g_utf8_strdown (base,-1);
409
g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(_exec), exec);
410
gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
414
g_object_ref_sink (item);
422
gchar * folderfied_icon_name = g_strdup_printf("folder-%s",icon_name);
424
icon_name = folderfied_icon_name;
425
image = get_gtk_image (icon_name);
430
image = get_gtk_image ("stock_folder");
434
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),image);
440
gtk_widget_show_all (menu);
445
get_places_menu (void)
447
GtkWidget *menu = cairo_menu_new();
448
_get_places_menu (menu);
453
fill_er_up(MenuInstance * instance,GMenuTreeDirectory *directory, GtkWidget * menu)
455
static gint sanity_depth_count = 0;
456
GSList * items = gmenu_tree_directory_get_contents(directory);
457
GSList * tmp = items;
458
GtkWidget * menu_item = NULL;
459
GtkWidget * sub_menu = NULL;
461
gchar * desktop_file;
462
DesktopAgnosticFDODesktopEntry *entry;
464
gboolean detached_sub = FALSE;
467
sanity_depth_count++;
468
if (sanity_depth_count>6)
470
sanity_depth_count--;
471
g_warning ("%s: Exceeded max menu depth of 6 at %s",__func__,gmenu_tree_directory_get_name((GMenuTreeDirectory*)directory));
472
return cairo_menu_new ();
476
menu = cairo_menu_new ();
481
GMenuTreeItem *item = tmp->data;
483
switch (gmenu_tree_item_get_type(item))
486
case GMENU_TREE_ITEM_ENTRY:
488
if (gmenu_tree_entry_get_is_excluded ((GMenuTreeEntry *) item))
492
if (gmenu_tree_entry_get_is_nodisplay ((GMenuTreeEntry *) item))
496
txt = gmenu_tree_entry_get_name( (GMenuTreeEntry*)item);
497
desktop_file = g_strdup (gmenu_tree_entry_get_desktop_file_path ((GMenuTreeEntry*)item));
498
uri = g_strdup_printf("file://%s\n",desktop_file);
501
entry = get_desktop_entry (desktop_file);
506
if (desktop_agnostic_fdo_desktop_entry_key_exists (entry,"Icon"))
508
icon_name = g_strdup(desktop_agnostic_fdo_desktop_entry_get_icon (entry));
512
icon_name = g_strdup ("stock_missing-image");
514
image = get_gtk_image (icon_name);
515
menu_item = cairo_menu_item_new_with_label (txt?txt:"unknown");
518
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),image);
520
gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
521
gtk_widget_show_all (menu_item);
522
g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(_launch), desktop_file);
523
// g_signal_connect(G_OBJECT(menu_item), "button-release-event", G_CALLBACK(_launch), desktop_file);
524
cairo_menu_item_set_source (AWN_CAIRO_MENU_ITEM(menu_item),uri);
526
g_object_unref (entry);
531
case GMENU_TREE_ITEM_DIRECTORY:
532
if (!gmenu_tree_directory_get_is_nodisplay ( (GMenuTreeDirectory *) item) )
534
CallbackContainer * c;
536
c = g_malloc0 (sizeof(CallbackContainer));
537
c->icon_name = g_strdup(gmenu_tree_directory_get_icon ((GMenuTreeDirectory *)item));
538
image = get_gtk_image (c->icon_name);
541
image = get_gtk_image ("stock_folder");
543
sub_menu = GTK_WIDGET(fill_er_up( instance,(GMenuTreeDirectory*)item,NULL));
544
txt = gmenu_tree_directory_get_name((GMenuTreeDirectory*)item);
545
menu_item = cairo_menu_item_new_with_label (txt?txt:"unknown");
546
gtk_menu_item_set_submenu (GTK_MENU_ITEM(menu_item),sub_menu);
549
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),image);
551
gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
552
c->file_path = g_strdup(gmenu_tree_directory_get_desktop_file_path ((GMenuTreeDirectory*)item));
553
c->display_name = g_strdup (gmenu_tree_directory_get_name ((GMenuTreeDirectory*)item));
554
c->instance = instance;
556
TODO: possibly change data
558
drop_data = g_strdup_printf("cairo_menu_item_dir:///@@@%s@@@%s@@@%s\n",c->file_path,c->display_name,c->icon_name);
559
cairo_menu_item_set_source (AWN_CAIRO_MENU_ITEM(menu_item),drop_data);
561
g_signal_connect (menu_item, "button-press-event",G_CALLBACK(_button_press_dir),c);
562
g_object_weak_ref (G_OBJECT(menu_item),(GWeakNotify)_free_callback_container,c);
566
case GMENU_TREE_ITEM_HEADER:
567
// printf("GMENU_TREE_ITEM_HEADER\n");
570
case GMENU_TREE_ITEM_SEPARATOR:
571
menu_item = gtk_separator_menu_item_new ();
572
gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
575
case GMENU_TREE_ITEM_ALIAS:
576
// printf("GMENU_TREE_ITEM_ALIAS\n");
578
GMenuTreeItem *aliased_item;
580
aliased_item = gmenu_tree_alias_get_item (GMENU_TREE_ALIAS (item));
581
if (gmenu_tree_item_get_type (aliased_item) == GMENU_TREE_ITEM_ENTRY)
582
print_entry (GMENU_TREE_ENTRY (aliased_item), path);
587
g_assert_not_reached();
591
gmenu_tree_item_unref(tmp->data);
597
gtk_widget_show_all (menu);
599
sanity_depth_count--;
604
_run_dialog (GtkMenuItem * item, MenuInstance *instance)
608
cmd = instance->run_cmd_fn (AWN_APPLET(instance->applet));
611
g_spawn_command_line_async (cmd,NULL);
616
_search_dialog (GtkMenuItem * item, MenuInstance * instance)
619
cmd = instance->search_cmd_fn (AWN_APPLET(instance->applet));
622
g_spawn_command_line_async (cmd,NULL);
627
_delayed_update (MenuInstance * instance)
629
instance->source_id=0;
630
instance->menu = menu_build (instance);
635
_menu_modified_cb(GMenuTree *tree,MenuInstance * instance)
639
keeps a runaway stream of callbacks from occurring in certain circumstances
641
if (!instance->source_id)
643
instance->source_id = g_timeout_add_seconds (5,(GSourceFunc)_delayed_update,instance);
647
static GMenuTreeDirectory *
648
find_menu_dir (MenuInstance * instance, GMenuTreeDirectory * root)
650
g_return_val_if_fail (root,NULL);
651
GSList * items = NULL;
653
GMenuTreeDirectory * result = NULL;
654
const gchar * txt = NULL;
656
txt = gmenu_tree_directory_get_desktop_file_path (root);
657
if (g_strcmp0(txt,instance->submenu_name)==0 )
659
gmenu_tree_item_ref (root);
663
items = gmenu_tree_directory_get_contents(root);
667
GMenuTreeItem *item = tmp->data;
669
switch (gmenu_tree_item_get_type(item))
671
case GMENU_TREE_ITEM_DIRECTORY:
672
if (!gmenu_tree_directory_get_is_nodisplay ( (GMenuTreeDirectory *) item) )
674
txt = gmenu_tree_directory_get_desktop_file_path ((GMenuTreeDirectory*)item);
675
if (g_strcmp0(txt,instance->submenu_name)==0 )
677
result = (GMenuTreeDirectory*)item;
680
else if (!result) /*we're continuing looping if result to unref the remaining items*/
682
result = find_menu_dir (instance, (GMenuTreeDirectory *) item);
685
/*deliberately falling through*/
686
case GMENU_TREE_ITEM_ENTRY:
687
case GMENU_TREE_ITEM_HEADER:
688
case GMENU_TREE_ITEM_SEPARATOR:
689
case GMENU_TREE_ITEM_ALIAS:
690
gmenu_tree_item_unref(tmp->data);
693
g_assert_not_reached();
703
clear_menu (MenuInstance * instance)
707
GList * children = gtk_container_get_children (GTK_CONTAINER(instance->menu));
709
for (iter = children;iter;)
711
if ( (iter->data !=instance->places) && (iter->data!=instance->recent)&& (iter->data!=instance->session))
713
gtk_container_remove (GTK_CONTAINER (instance->menu),iter->data);
714
/*TODO check if this is necessary*/
715
g_list_free (children);
716
children = iter = gtk_container_get_children (GTK_CONTAINER(instance->menu));
719
iter=g_list_next (iter);
723
g_list_free (children);
729
_submenu_delayed_update (MenuInstance * instance)
731
instance->source_id=0;
732
instance->menu = submenu_build (instance);
738
_submenu_modified_cb(GMenuTree *tree,MenuInstance * instance)
742
keeps a runaway stream of callbacks from occurring in certain circumstances
744
if (!instance->source_id)
746
instance->source_id = g_timeout_add_seconds (5,(GSourceFunc)_submenu_delayed_update,instance);
751
_remove_main_submenu_cb(MenuInstance * instance,GObject *where_the_object_was)
753
g_debug ("%s",__func__);
754
GMenuTreeDirectory *main_root;
755
gmenu_tree_remove_monitor (main_menu_tree,(GMenuTreeChangedFunc)_submenu_modified_cb,instance);
759
_remove_settings_submenu_cb(MenuInstance * instance,GObject *where_the_object_was)
761
g_debug ("%s",__func__);
762
GMenuTreeDirectory *main_root;
763
gmenu_tree_remove_monitor (settings_menu_tree,(GMenuTreeChangedFunc)_submenu_modified_cb,instance);
767
submenu_build (MenuInstance * instance)
769
GMenuTreeDirectory *main_root;
770
GMenuTreeDirectory *settings_root;
771
GtkWidget * menu = NULL;
773
if the menu is set then clear any menu items (except for places or recent)
775
clear_menu (instance);
778
main_menu_tree = gmenu_tree_lookup("applications.menu", GMENU_TREE_FLAGS_NONE);
780
if (!settings_menu_tree)
782
settings_menu_tree = gmenu_tree_lookup("settings.menu", GMENU_TREE_FLAGS_NONE);
784
g_assert (main_menu_tree);
786
get_places_menu() and get_recent_menu() are
787
responsible for managing updates in place. Session should only need
788
to be created once or may eventually need to follow the previously mentioned
789
behaviour. Regardless... they should only need to be created here from scratch,
790
this fn should _not_ be invoked in a refresh of those menus.
792
We don't want to rebuild the whole menu tree everytime a vfs change occurs
793
or a document is accessed
795
if (g_strcmp0(instance->submenu_name,":::PLACES")==0)
797
g_assert (!instance->menu);
798
menu = get_places_menu ();
800
else if (g_strcmp0(instance->submenu_name,":::RECENT")==0)
802
g_assert (!instance->menu);
803
menu = get_recent_menu ();
805
else if (g_strcmp0(instance->submenu_name,":::SESSION")==0)
807
g_assert (!instance->menu);
808
menu = get_session_menu ();
812
GMenuTreeDirectory * menu_dir = NULL;
814
main_root = gmenu_tree_get_root_directory(main_menu_tree);
815
g_assert (gmenu_tree_item_get_type( (GMenuTreeItem*)main_root) == GMENU_TREE_ITEM_DIRECTORY);
816
g_assert (main_root);
817
settings_root = gmenu_tree_get_root_directory(settings_menu_tree);
818
if ( menu_dir = find_menu_dir (instance,main_root) )
820
/* if instance->menu then we're refreshing in a monitor callback*/
821
gmenu_tree_remove_monitor (main_menu_tree,(GMenuTreeChangedFunc)_submenu_modified_cb,instance);
822
gmenu_tree_add_monitor (main_menu_tree,(GMenuTreeChangedFunc)_submenu_modified_cb,instance);
823
menu = fill_er_up(instance,menu_dir,instance->menu);
824
g_object_weak_ref (G_OBJECT(menu), (GWeakNotify)_remove_main_submenu_cb,instance);
826
else if ( settings_root && (menu_dir = find_menu_dir (instance,settings_root)) )
828
gmenu_tree_remove_monitor (main_menu_tree,(GMenuTreeChangedFunc)_submenu_modified_cb,instance);
829
gmenu_tree_add_monitor (main_menu_tree,(GMenuTreeChangedFunc)_submenu_modified_cb,instance);
830
menu = fill_er_up(instance,menu_dir,instance->menu);
831
g_object_weak_ref (G_OBJECT(menu), (GWeakNotify)_remove_settings_submenu_cb,instance);
835
gmenu_tree_item_unref(menu_dir);
837
gmenu_tree_item_unref(main_root);
840
gmenu_tree_item_unref(settings_root);
843
return instance->menu = menu;
847
TODO: add network, and trash
851
menu_build (MenuInstance * instance)
853
GMenuTreeDirectory *root;
854
GtkWidget * image = NULL;
855
GtkWidget *menu_item;
856
GtkWidget * sub_menu;
858
CallbackContainer * c;
861
if (instance->submenu_name)
863
return instance->menu = submenu_build (instance);
866
clear_menu (instance);
869
main_menu_tree = gmenu_tree_lookup("applications.menu", GMENU_TREE_FLAGS_NONE);
871
if (!settings_menu_tree)
873
settings_menu_tree = gmenu_tree_lookup("settings.menu", GMENU_TREE_FLAGS_NONE);
878
root = gmenu_tree_get_root_directory(main_menu_tree);
881
g_assert (!instance->submenu_name);
882
gmenu_tree_remove_monitor (main_menu_tree,(GMenuTreeChangedFunc)_menu_modified_cb,instance);
883
gmenu_tree_add_monitor (main_menu_tree,(GMenuTreeChangedFunc)_menu_modified_cb,instance);
884
instance->menu = fill_er_up(instance,root,instance->menu);
885
gmenu_tree_item_unref(root);
890
menu_item = gtk_separator_menu_item_new ();
891
gtk_menu_shell_append(GTK_MENU_SHELL(instance->menu),menu_item);
893
if (settings_menu_tree)
895
root = gmenu_tree_get_root_directory(settings_menu_tree);
896
gmenu_tree_remove_monitor (settings_menu_tree,(GMenuTreeChangedFunc)_menu_modified_cb,instance);
897
gmenu_tree_add_monitor (settings_menu_tree,(GMenuTreeChangedFunc)_menu_modified_cb,instance);
900
g_debug ("%s: No applications menu????",__func__);
901
instance->menu = fill_er_up(instance,root,instance->menu);
905
sub_menu = fill_er_up (instance, root,instance->menu);
907
sub_menu = fill_er_up(instance,root,NULL);
908
c = g_malloc0 (sizeof(CallbackContainer));
909
c->icon_name = g_strdup(gmenu_tree_directory_get_icon (root));
910
image = get_gtk_image (c->icon_name);
911
txt = gmenu_tree_entry_get_name((GMenuTreeEntry*)root);
912
menu_item = cairo_menu_item_new_with_label (txt?txt:"unknown");
913
gtk_menu_item_set_submenu (GTK_MENU_ITEM(menu_item),sub_menu);
916
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),image);
918
gtk_menu_shell_append(GTK_MENU_SHELL(instance->menu),menu_item);
919
c->file_path = g_strdup(gmenu_tree_directory_get_desktop_file_path (root));
920
c->display_name = g_strdup ("Settings");
921
drop_data = g_strdup_printf("cairo_menu_item_dir:///@@@%s@@@%s@@@%s\n",c->file_path,c->display_name,c->icon_name);
922
cairo_menu_item_set_source (AWN_CAIRO_MENU_ITEM(menu_item),drop_data);
924
c->instance = instance;
925
g_signal_connect (menu_item, "button-press-event",G_CALLBACK(_button_press_dir),c);
926
g_object_weak_ref (G_OBJECT(menu_item),(GWeakNotify)_free_callback_container,c);
929
gmenu_tree_item_unref(root);
932
/*TODO Check to make sure it is needed. Should not be displayed if
933
all flags are of the NO persuasion.*/
936
menu_item = gtk_separator_menu_item_new ();
937
gtk_menu_shell_append(GTK_MENU_SHELL(instance->menu),menu_item);
940
if (! (instance->flags & MENU_BUILD_NO_PLACES) )
942
if (instance->places)
944
GList * children = gtk_container_get_children (GTK_CONTAINER(instance->menu));
945
menu_item =instance->places;
946
gtk_menu_reorder_child (GTK_MENU(instance->menu),menu_item,g_list_length (children));
947
g_list_free (children);
951
sub_menu = get_places_menu ();
953
instance->places = menu_item = cairo_menu_item_new_with_label (_("Places"));
954
image = get_gtk_image (icon_name = "places");
957
image = get_gtk_image(icon_name = "stock_folder");
961
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),image);
963
gtk_menu_item_set_submenu (GTK_MENU_ITEM(menu_item),sub_menu);
964
gtk_menu_shell_append(GTK_MENU_SHELL(instance->menu),menu_item);
965
c = g_malloc0 (sizeof(CallbackContainer));
966
c->file_path = g_strdup(":::PLACES");
967
c->display_name = g_strdup (_("Places"));
968
c->icon_name = g_strdup(icon_name);
969
drop_data = g_strdup_printf("cairo_menu_item_dir:///@@@%s@@@%s@@@%s\n",c->file_path,c->display_name,c->icon_name);
970
cairo_menu_item_set_source (AWN_CAIRO_MENU_ITEM(menu_item),drop_data);
972
c->instance = instance;
973
g_signal_connect (menu_item, "button-press-event",G_CALLBACK(_button_press_dir),c);
974
g_object_weak_ref (G_OBJECT(menu_item),(GWeakNotify)_free_callback_container,c);
978
if (! (instance->flags & MENU_BUILD_NO_RECENT))
980
if (instance->recent)
982
GList * children = gtk_container_get_children (GTK_CONTAINER(instance->menu));
983
menu_item =instance->recent;
984
gtk_menu_reorder_child (GTK_MENU(instance->menu),menu_item,g_list_length (children));
985
g_list_free (children);
989
sub_menu = get_recent_menu ();
991
instance->recent = menu_item = cairo_menu_item_new_with_label (_("Recent Documents"));
992
image = get_gtk_image (icon_name = "document-open-recent");
995
image = get_gtk_image(icon_name = "stock_folder");
999
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),image);
1001
gtk_menu_item_set_submenu (GTK_MENU_ITEM(menu_item),sub_menu);
1002
gtk_menu_shell_append(GTK_MENU_SHELL(instance->menu),menu_item);
1003
c = g_malloc0 (sizeof(CallbackContainer));
1004
c->file_path = g_strdup(":::RECENT");
1005
c->display_name = g_strdup (_("Recent Documents"));
1006
c->icon_name = g_strdup (icon_name);
1007
drop_data = g_strdup_printf("cairo_menu_item_dir:///@@@%s@@@%s@@@%s\n",c->file_path,c->display_name,c->icon_name);
1008
cairo_menu_item_set_source (AWN_CAIRO_MENU_ITEM(menu_item),drop_data);
1010
c->instance = instance;
1011
g_signal_connect (menu_item, "button-press-event",G_CALLBACK(_button_press_dir),c);
1012
g_object_weak_ref (G_OBJECT(menu_item),(GWeakNotify)_free_callback_container,c);
1016
/*TODO Check to make sure it is needed. avoid double separators*/
1017
if (instance->menu && (!(instance->flags & MENU_BUILD_NO_RECENT) || !(instance->flags & MENU_BUILD_NO_PLACES))&&
1018
(!instance->check_menu_hidden_fn (instance->applet,":::RECENT") || !instance->check_menu_hidden_fn (instance->applet,":::PLACES")) )
1020
menu_item = gtk_separator_menu_item_new ();
1021
gtk_menu_shell_append(GTK_MENU_SHELL(instance->menu),menu_item);
1024
if (! (instance->flags & MENU_BUILD_NO_SESSION))
1026
if (instance->session)
1028
GList * children = gtk_container_get_children (GTK_CONTAINER(instance->menu));
1029
menu_item =instance->session;
1030
gtk_menu_reorder_child (GTK_MENU(instance->menu),menu_item,g_list_length (children));
1031
g_list_free (children);
1035
sub_menu = get_session_menu ();
1036
instance->session = menu_item = cairo_menu_item_new_with_label (_("Session"));
1037
image = get_gtk_image ("session-properties");
1040
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),image);
1042
gtk_menu_item_set_submenu (GTK_MENU_ITEM(menu_item),sub_menu);
1043
gtk_menu_shell_append(GTK_MENU_SHELL(instance->menu),menu_item);
1045
c = g_malloc0 (sizeof(CallbackContainer));
1046
c->file_path = g_strdup(":::SESSION");
1047
c->display_name = g_strdup (_("Session"));
1048
c->icon_name = g_strdup ("session-properties");
1049
drop_data = g_strdup_printf("cairo_menu_item_dir:///@@@%s@@@%s@@@%s\n",c->file_path,c->display_name,c->icon_name);
1050
cairo_menu_item_set_source (AWN_CAIRO_MENU_ITEM(menu_item),drop_data);
1052
c->instance = instance;
1053
g_signal_connect (menu_item, "button-press-event",G_CALLBACK(_button_press_dir),c);
1054
g_object_weak_ref (G_OBJECT(menu_item),(GWeakNotify)_free_callback_container,c);
1058
if (! (instance->flags & MENU_BUILD_NO_SEARCH))
1060
if ( !instance->submenu_name)
1062
/*generates a compiler warning due to the ellipse*/
1063
menu_item = cairo_menu_item_new_with_label (_("Search\u2026"));
1064
/* add proper ellipse*/
1065
image = get_gtk_image ("stock_search");
1068
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),image);
1070
gtk_menu_shell_append(GTK_MENU_SHELL(instance->menu),menu_item);
1071
g_signal_connect (menu_item,"activate",G_CALLBACK(_search_dialog),instance);
1075
if (! (instance->flags & MENU_BUILD_NO_RUN))
1077
if ( !instance->submenu_name)
1079
/*generates a compiler warning due to the ellipse*/
1080
menu_item = cairo_menu_item_new_with_label (_("Launch\u2026"));
1081
/* add proper ellipse*/
1082
image = get_gtk_image ("gnome-run");
1085
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),image);
1087
gtk_menu_shell_append(GTK_MENU_SHELL(instance->menu),menu_item);
1088
g_signal_connect (menu_item,"activate",G_CALLBACK(_run_dialog),instance);
1092
gtk_widget_show_all (instance->menu);
1094
if ( !instance->check_menu_hidden_fn || instance->check_menu_hidden_fn (instance->applet,":::RECENT"))
1096
if (instance->recent)
1098
gtk_widget_hide (instance->recent);
1101
if ( !instance->check_menu_hidden_fn || instance->check_menu_hidden_fn (instance->applet,":::PLACES"))
1103
if (instance->places)
1105
gtk_widget_hide (instance->places);
1108
if ( !instance->check_menu_hidden_fn || instance->check_menu_hidden_fn (instance->applet,":::SESSION"))
1110
if (instance->session)
1112
gtk_widget_hide (instance->session);
1115
instance->done_once = TRUE;
1116
return instance->menu;