summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Soriano <carlos.sorian89@gmail.com>2015-01-14 18:50:24 +0100
committerCarlos Soriano <carlos.sorian89@gmail.com>2015-01-14 18:51:08 +0100
commit7269fbf5a753a3db8415b55c36b058a134cf9ba7 (patch)
treee7ed465b264b2c6c224bfe699df266e5a213411b
parentebe5bdcbcbbe63d5892f3d3881a94d706185a3c5 (diff)
downloadnautilus-wip/gaction.tar.gz
general: Implement extensions for GActionwip/gaction
The last commit rework the menus and ported to GAction. Update the extension mechanism to that. The changes are very little. Now menu items in extensions lost the property 'priority' since gmenu doesn't have one, and gain two properties, menu_name, which is in which menu do you want the extension to add a menu item, it can be background or selection, and menu_section, which indicates in which section of the menu do you want to add the items of the extension.
-rw-r--r--libnautilus-extension/nautilus-menu-item.c51
-rw-r--r--libnautilus-extension/nautilus-menu.h4
-rw-r--r--nautilus-sendto-extension/nautilus-nste.c23
-rw-r--r--src/nautilus-view-context-menus.xml7
-rw-r--r--src/nautilus-view.c258
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", &section_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);
}