diff options
-rw-r--r-- | libnautilus-extension/nautilus-menu-item.c | 51 | ||||
-rw-r--r-- | libnautilus-extension/nautilus-menu.h | 4 | ||||
-rw-r--r-- | nautilus-sendto-extension/nautilus-nste.c | 23 | ||||
-rw-r--r-- | src/nautilus-view-context-menus.xml | 7 | ||||
-rw-r--r-- | src/nautilus-view.c | 258 |
5 files changed, 318 insertions, 25 deletions
diff --git a/libnautilus-extension/nautilus-menu-item.c b/libnautilus-extension/nautilus-menu-item.c index dfe3e2712..a76e9ca4c 100644 --- a/libnautilus-extension/nautilus-menu-item.c +++ b/libnautilus-extension/nautilus-menu-item.c @@ -37,7 +37,8 @@ enum { PROP_TIP, PROP_ICON, PROP_SENSITIVE, - PROP_PRIORITY, + PROP_MENU_NAME, + PROP_SECTION_NAME, PROP_MENU, LAST_PROP }; @@ -47,6 +48,8 @@ struct _NautilusMenuItemDetails { char *label; char *tip; char *icon; + char *menu_name; + char *section_name; NautilusMenu *menu; gboolean sensitive; gboolean priority; @@ -71,7 +74,9 @@ NautilusMenuItem * nautilus_menu_item_new (const char *name, const char *label, const char *tip, - const char *icon) + const char *icon, + const char *menu_name, + const char *section_name) { NautilusMenuItem *item; @@ -84,6 +89,8 @@ nautilus_menu_item_new (const char *name, "label", label, "tip", tip, "icon", icon, + "menu_name", menu_name, + "section_name", section_name, NULL); return item; @@ -140,8 +147,11 @@ nautilus_menu_item_get_property (GObject *object, case PROP_SENSITIVE : g_value_set_boolean (value, item->details->sensitive); break; - case PROP_PRIORITY : - g_value_set_boolean (value, item->details->priority); + case PROP_MENU_NAME : + g_value_set_string (value, item->details->menu_name); + break; + case PROP_SECTION_NAME : + g_value_set_string (value, item->details->section_name); break; case PROP_MENU : g_value_set_object (value, item->details->menu); @@ -187,9 +197,15 @@ nautilus_menu_item_set_property (GObject *object, item->details->sensitive = g_value_get_boolean (value); g_object_notify (object, "sensitive"); break; - case PROP_PRIORITY : - item->details->priority = g_value_get_boolean (value); - g_object_notify (object, "priority"); + case PROP_MENU_NAME : + g_free (item->details->menu_name); + item->details->menu_name = g_strdup (g_value_get_string (value)); + g_object_notify (object, "menu_name"); + break; + case PROP_SECTION_NAME : + g_free (item->details->section_name); + item->details->section_name = g_strdup (g_value_get_string (value)); + g_object_notify (object, "section_name"); break; case PROP_MENU : if (item->details->menu) { @@ -215,6 +231,8 @@ nautilus_menu_item_finalize (GObject *object) g_free (item->details->label); g_free (item->details->tip); g_free (item->details->icon); + g_free (item->details->section_name); + g_free (item->details->menu_name); if (item->details->menu) { g_object_unref (item->details->menu); } @@ -288,12 +306,19 @@ nautilus_menu_item_class_init (NautilusMenuItemClass *class) TRUE, G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (class), - PROP_PRIORITY, - g_param_spec_boolean ("priority", - "Priority", - "Show priority text in toolbars", - TRUE, - G_PARAM_READWRITE)); + PROP_MENU_NAME, + g_param_spec_string ("menu_name", + "Menu name", + "The name of the menu to for inserting the item. It can be 'background' or 'selection'", + NULL, + G_PARAM_READWRITE)); + g_object_class_install_property (G_OBJECT_CLASS (class), + PROP_SECTION_NAME, + g_param_spec_string ("section_name", + "Section name", + "The name of the section to be the insertion point for the item", + NULL, + G_PARAM_READWRITE)); g_object_class_install_property (G_OBJECT_CLASS (class), PROP_MENU, g_param_spec_object ("menu", diff --git a/libnautilus-extension/nautilus-menu.h b/libnautilus-extension/nautilus-menu.h index fd132be4e..2f9623dc2 100644 --- a/libnautilus-extension/nautilus-menu.h +++ b/libnautilus-extension/nautilus-menu.h @@ -95,7 +95,9 @@ GType nautilus_menu_item_get_type (void); NautilusMenuItem *nautilus_menu_item_new (const char *name, const char *label, const char *tip, - const char *icon); + const char *icon, + const char *menu_name, + const char *section_name); void nautilus_menu_item_activate (NautilusMenuItem *item); void nautilus_menu_item_set_submenu (NautilusMenuItem *item, diff --git a/nautilus-sendto-extension/nautilus-nste.c b/nautilus-sendto-extension/nautilus-nste.c index 92f347e0a..9859d61b4 100644 --- a/nautilus-sendto-extension/nautilus-nste.c +++ b/nautilus-sendto-extension/nautilus-nste.c @@ -78,6 +78,7 @@ nautilus_nste_get_file_items (NautilusMenuProvider *provider, gboolean one_item; NautilusMenuItem *item; NautilusNste *nste; + char *tip; nste = NAUTILUS_NSTE (provider); if (!nste->nst_present) @@ -91,17 +92,17 @@ nautilus_nste_get_file_items (NautilusMenuProvider *provider, one_item = (files != NULL) && (files->next == NULL); if (one_item && - !nautilus_file_info_is_directory ((NautilusFileInfo *)files->data)) { - item = nautilus_menu_item_new ("NautilusNste::sendto", - _("Email…"), - _("Send file by mail…"), - "document-send"); - } else { - item = nautilus_menu_item_new ("NautilusNste::sendto", - _("Email…"), - _("Send files by mail…"), - "document-send"); - } + !nautilus_file_info_is_directory ((NautilusFileInfo *)files->data)) + tip = _("Send file by mail…"); + else + tip = _("Send files by mail…"); + + item = nautilus_menu_item_new ("nautilus-nste-send-to", + _("Email…"), + tip, + "document-send", + "selection", + "file-actions-section"); g_signal_connect (item, "activate", G_CALLBACK (sendto_callback), diff --git a/src/nautilus-view-context-menus.xml b/src/nautilus-view-context-menus.xml index ffda16e6b..96f45184b 100644 --- a/src/nautilus-view-context-menus.xml +++ b/src/nautilus-view-context-menus.xml @@ -48,6 +48,9 @@ <attribute name="hidden-when">action-disabled</attribute> </item> </section> + <section> + <attribute name="id">extensions</attribute> + </section> </menu> <menu id="selection-menu"> <section> @@ -139,6 +142,7 @@ </item> </section> <section> + <attribute name="id">file-actions-section</attribute> <item> <attribute name="label" translatable="yes">Move to…</attribute> <attribute name="action">view.move-to</attribute> @@ -189,6 +193,9 @@ <attribute name="action">view.properties</attribute> </item> </section> + <section> + <attribute name="id">extensions</attribute> + </section> </menu> <menu id="pathbar-menu"> <section> diff --git a/src/nautilus-view.c b/src/nautilus-view.c index 38424f3ad..65699e2b5 100644 --- a/src/nautilus-view.c +++ b/src/nautilus-view.c @@ -3662,6 +3662,262 @@ get_menu_icon_for_file (NautilusFile *file, return pixbuf; } +static GList * +get_all_extension_menu_items (GtkWidget *window, + GList *selection) +{ + GList *items; + GList *providers; + GList *l; + + providers = nautilus_module_get_extensions_for_type (NAUTILUS_TYPE_MENU_PROVIDER); + items = NULL; + + for (l = providers; l != NULL; l = l->next) { + NautilusMenuProvider *provider; + GList *file_items; + + provider = NAUTILUS_MENU_PROVIDER (l->data); + file_items = nautilus_menu_provider_get_file_items (provider, + window, + selection); + items = g_list_concat (items, file_items); + } + + nautilus_module_extension_list_free (providers); + + return items; +} + +typedef struct +{ + NautilusMenuItem *item; + NautilusView *view; + GList *selection; + GAction *action; +} ExtensionActionCallbackData; + + +static void +extension_action_callback_data_free (ExtensionActionCallbackData *data) +{ + g_object_unref (data->item); + nautilus_file_list_free (data->selection); + + g_free (data); +} + +static gboolean +search_in_menu_items (GList * items, + const char *item_name) +{ + GList* list; + + for (list = items; list != NULL; list = list->next) { + NautilusMenu* menu; + char *name; + + g_object_get (list->data, "name", &name, NULL); + if (strcmp (name, item_name) == 0) { + g_free (name); + return TRUE; + } + g_free (name); + + menu = NULL; + g_object_get (list->data, "menu", &menu, NULL); + if (menu != NULL) { + gboolean ret; + GList* submenus; + + submenus = nautilus_menu_get_items (menu); + ret = search_in_menu_items (submenus, item_name); + nautilus_menu_item_list_free (submenus); + g_object_unref (menu); + if (ret) { + return TRUE; + } + } + } + return FALSE; +} + +static void +extension_action_callback (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + ExtensionActionCallbackData *data; + char *item_name; + gboolean is_valid; + GList *l; + GList *items; + + data = user_data; + + /* Make sure the selected menu item is valid for the final sniffed + * mime type */ + g_object_get (data->item, "name", &item_name, NULL); + items = get_all_extension_menu_items (gtk_widget_get_toplevel (GTK_WIDGET (data->view)), + data->selection); + + is_valid = search_in_menu_items (items, item_name); + + for (l = items; l != NULL; l = l->next) { + g_object_unref (l->data); + } + g_list_free (items); + + g_free (item_name); + + if (is_valid) { + nautilus_menu_item_activate (data->item); + } +} + +static void +add_extension_action_for_files (NautilusView *view, + NautilusMenuItem *item, + GList *files) +{ + char *name, *label, *tip, *icon; + gboolean sensitive; + GAction *action; + ExtensionActionCallbackData *data; + + g_object_get (G_OBJECT (item), + "name", &name, "label", &label, + "tip", &tip, "icon", &icon, + "sensitive", &sensitive, + NULL); + + action = G_ACTION (g_simple_action_new (name, NULL)); + + data = g_new0 (ExtensionActionCallbackData, 1); + data->item = g_object_ref (item); + data->view = view; + data->selection = nautilus_file_list_copy (files); + data->action = action; + + g_signal_connect_data (action, "activate", + G_CALLBACK (extension_action_callback), + data, + (GClosureNotify)extension_action_callback_data_free, 0); + + g_action_map_add_action (G_ACTION_MAP (view->details->view_action_group), + action); + g_simple_action_set_enabled (G_SIMPLE_ACTION (action), sensitive); + g_object_unref (action); + + g_free (name); + g_free (label); + g_free (tip); + g_free (icon); +} + +static GMenu * +add_extension_menu_items (NautilusView *view, + GList *files, + GList *menu_items, + GMenuItem *parent) +{ + GList *l; + GMenuItem *menu_item; + GMenu *gmenu, *target, *children_menu; + char *name, *label, *tip, *icon, *menu_name, *section_name, *detailed_action_name; + gboolean sensitive; + GdkPixbuf *pixbuf; + + gmenu = g_menu_new (); + + for (l = menu_items; l; l = l->next) { + NautilusMenuItem *item; + NautilusMenu *menu; + + item = NAUTILUS_MENU_ITEM (l->data); + + g_object_get (item, "menu", &menu, NULL); + + g_object_get (G_OBJECT (item), + "name", &name, "label", &label, + "tip", &tip, "icon", &icon, + "sensitive", &sensitive, + "menu_name", &menu_name, + "section_name", §ion_name, + NULL); + + add_extension_action_for_files (view, item, files); + detailed_action_name = g_strconcat ("view.", name, NULL); + menu_item = g_menu_item_new (label, detailed_action_name); + if (menu != NULL) { + GList *children; + + children = nautilus_menu_get_items (menu); + + children_menu = add_extension_menu_items (view, + files, + children, + menu_item); + + nautilus_menu_item_list_free (children); + g_menu_item_set_submenu (menu_item, G_MENU_MODEL (children_menu)); + } + + if (icon != NULL) { + pixbuf = nautilus_ui_get_menu_icon (icon, GTK_WIDGET (view)); + if (pixbuf != NULL) { + g_menu_item_set_icon (menu_item, pixbuf); + g_object_unref (pixbuf); + } + } + + g_menu_append_item (gmenu, menu_item); + } + + if (g_strcmp0(menu_name, "background") == 0) + target = view->details->background_menu; + else if (g_strcmp0(menu_name, "selection") == 0) + target = view->details->selection_menu; + else + goto clean_up; + + if (parent) { + g_menu_item_set_submenu (parent, G_MENU_MODEL (gmenu)); + } else { + nautilus_gmenu_merge (target, + gmenu, + section_name, + FALSE); + } +clean_up: + g_free (name); + g_free (label); + g_free (tip); + g_free (icon); + g_free (menu_name); + g_free (section_name); + + return gmenu; +} + +static void +update_extensions_menus (NautilusView *view) +{ + GList *items; + GList *selection; + + selection = nautilus_view_get_selection (view); + + items = get_all_extension_menu_items (gtk_widget_get_toplevel (GTK_WIDGET (view)), + selection); + if (items != NULL) { + add_extension_menu_items (view, selection, items, NULL); + + g_list_foreach (items, (GFunc) g_object_unref, NULL); + g_list_free (items); + } +} + static char * change_to_view_directory (NautilusView *view) { @@ -5812,6 +6068,8 @@ real_update_context_menus (NautilusView *view) update_selection_menu (view); update_background_menu (view); + update_extensions_menus (view); + nautilus_view_update_actions_state (view); } |