int get_property_page (ThunarxProviderFactory* f, GList *flist, const char *class_name, GtkWidget **pp, char *title, int tlen, GtkWindow *win) { GList *ps, *lp; ps = thunarx_provider_factory_list_providers(f, THUNARX_TYPE_PROPERTY_PAGE_PROVIDER); *pp = NULL; for (lp = ps; lp != NULL; lp = lp->next) { GList *pgs, *lpg; pgs = thunarx_property_page_provider_get_pages(lp->data, flist); for (lpg = pgs; lpg != NULL && *pp == NULL; lpg = lpg->next) { if (strncmp(class_name, G_OBJECT_TYPE_NAME(lpg->data), 256) == 0) { *pp = GTK_WIDGET(g_object_ref(lpg->data)); } } g_list_foreach (pgs, (GFunc) g_object_ref_sink, NULL); g_list_foreach (pgs, (GFunc) g_object_unref, NULL); g_list_free (pgs); } g_list_foreach (ps, (GFunc) g_object_unref, NULL); g_list_free (ps); if (*pp != NULL) { if (g_list_length(flist) == 1) { snprintf(title, tlen, "%s: %s", gtk_label_get_text(GTK_LABEL(thunarx_property_page_get_label_widget(THUNARX_PROPERTY_PAGE(*pp)))), thunarx_file_info_get_name(THUNARX_FILE_INFO(flist->data))); } else { snprintf(title, tlen, "%s", gtk_label_get_text(GTK_LABEL(thunarx_property_page_get_label_widget(THUNARX_PROPERTY_PAGE(*pp))))); } /* Try to adjust some buttons to close the window on click */ gtk_container_foreach (*pp, adjust_destroy, win); } return *pp != NULL; }
int get_actions_page (ThunarxProviderFactory* f, GList *flist, gboolean dirs_as_files, GtkWindow *win, const char *class_name, GtkWidget **page, char *title, int tlen) { GList *ps, *lp, *files, *dirs, *fas, *das, *as; GtkWidget *vbox; files = NULL; dirs = NULL; if (! dirs_as_files) { for (flist; flist != NULL; flist = flist->next) { if (thunarx_file_info_is_directory(THUNARX_FILE_INFO(flist->data))) { dirs = g_list_append(dirs, flist->data); } else { files = g_list_append(files, flist->data); } } } else { files = flist; } ps = thunarx_provider_factory_list_providers(f, THUNARX_TYPE_MENU_PROVIDER); snprintf(title, tlen, "Choose an action for the %i selected object(s)\n", g_list_length(files) + g_list_length(dirs)); *page = gtk_frame_new (title); gtk_container_set_border_width (GTK_CONTAINER(*page), 10); vbox = gtk_vbox_new(TRUE, 10); gtk_container_set_border_width (GTK_CONTAINER(vbox), 10); gtk_container_add(GTK_CONTAINER(*page), GTK_WIDGET(vbox)); fas = NULL; das = NULL; for (lp = ps; lp != NULL; lp = lp->next) { GList *dp, *as; if (strncmp(class_name, G_OBJECT_TYPE_NAME(lp->data), 256) == 0) { as = thunarx_menu_provider_get_file_actions(lp->data, GTK_WIDGET(win), files); fas = g_list_merge(fas, as); for (dp = dirs; dp != NULL; dp = dp->next) { GList *as; as = thunarx_menu_provider_get_folder_actions(lp->data, GTK_WIDGET(win), dp->data); das = g_list_merge(das, as); g_list_foreach (as, (GFunc) g_object_unref, NULL); g_list_free (as); } g_list_foreach (as, (GFunc) g_object_unref, NULL); g_list_free (as); } } g_list_foreach (ps, (GFunc) g_object_unref, NULL); g_list_free (ps); fas = g_list_merge(fas, das); g_list_foreach (das, (GFunc) g_object_unref, NULL); g_list_free (das); if (g_list_length(fas) > 0) { GList *ap; for (ap = fas; ap != NULL; ap = ap->next) { GtkWidget *b; b = gtk_button_new (); gtk_action_connect_proxy (GTK_ACTION(ap->data), b); gtk_container_add(GTK_CONTAINER(vbox), GTK_WIDGET(b)); g_signal_connect_object (G_OBJECT(b), "clicked", G_CALLBACK(gtk_widget_destroy), win, G_CONNECT_AFTER | G_CONNECT_SWAPPED); } return 1; } else { gtk_container_add(GTK_CONTAINER(vbox), gtk_label_new ("No actions available")); return 1; } }
/** * thunar_dnd_ask: * @widget : the widget on which the drop was performed. * @folder : the #ThunarFile to which the @path_list is being dropped. * @path_list : the #GFile<!---->s of the files being dropped to @file. * @timestamp : the time of the drop event. * @actions : the list of actions supported for the drop. * * Pops up a menu that asks the user to choose one of the * @actions or to cancel the drop. If the user chooses a * valid #GdkDragAction from @actions, then this action is * returned. Else if the user cancels the drop, 0 will be * returned. * * This method can be used to implement a response to the * #GDK_ACTION_ASK action on drops. * * Return value: the selected #GdkDragAction or 0 to cancel. **/ GdkDragAction thunar_dnd_ask (GtkWidget *widget, ThunarFile *folder, GList *path_list, guint timestamp, GdkDragAction dnd_actions) { static const GdkDragAction dnd_action_items[] = { GDK_ACTION_COPY, GDK_ACTION_MOVE, GDK_ACTION_LINK }; static const gchar *dnd_action_names[] = { N_ ("_Copy here"), N_ ("_Move here"), N_ ("_Link here") }; static const gchar *dnd_action_icons[] = { "stock_folder-copy", "stock_folder-move", NULL }; ThunarxProviderFactory *factory; GdkDragAction dnd_action = 0; ThunarFile *file; GtkWidget *window; GtkWidget *image; GtkWidget *menu; GtkWidget *item; GList *file_list = NULL; GList *providers = NULL; GList *actions = NULL; GList *lp; guint n; _thunar_return_val_if_fail (thunar_file_is_directory (folder), 0); _thunar_return_val_if_fail (GTK_IS_WIDGET (widget), 0); /* connect to the provider factory */ factory = thunarx_provider_factory_get_default (); /* prepare the popup menu */ menu = gtk_menu_new (); /* append the various items */ for (n = 0; n < G_N_ELEMENTS (dnd_action_items); ++n) if (G_LIKELY ((dnd_actions & dnd_action_items[n]) != 0)) { item = gtk_image_menu_item_new_with_mnemonic (_(dnd_action_names[n])); g_object_set_data (G_OBJECT (item), I_("dnd-action"), GUINT_TO_POINTER (dnd_action_items[n])); g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (dnd_action_selected), &dnd_action); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); /* add image to the menu item */ if (G_LIKELY (dnd_action_icons[n] != NULL)) { image = gtk_image_new_from_icon_name (dnd_action_icons[n], GTK_ICON_SIZE_MENU); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); } } /* append the separator */ item = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); /* determine the toplevel window the widget belongs to */ window = gtk_widget_get_toplevel (widget); if (G_LIKELY (window != NULL && gtk_widget_get_toplevel (window))) { /* check if we can resolve all paths */ for (lp = path_list; lp != NULL; lp = lp->next) { /* try to resolve this path */ file = thunar_file_cache_lookup (lp->data); if (G_LIKELY (file != NULL)) file_list = g_list_prepend (file_list, file); else break; } /* check if we resolved all paths (and have atleast one file) */ if (G_LIKELY (file_list != NULL && lp == NULL)) { /* load the menu providers from the provider factory */ providers = thunarx_provider_factory_list_providers (factory, THUNARX_TYPE_MENU_PROVIDER); /* load the dnd actions offered by the menu providers */ for (lp = providers; lp != NULL; lp = lp->next) { /* merge the actions from this provider */ actions = g_list_concat (actions, thunarx_menu_provider_get_dnd_actions (lp->data, window, THUNARX_FILE_INFO (folder), file_list)); g_object_unref (G_OBJECT (lp->data)); } g_list_free (providers); /* check if we have atleast one action */ if (G_UNLIKELY (actions != NULL)) { /* add menu items for all actions */ for (lp = actions; lp != NULL; lp = lp->next) { /* add a menu item for the action */ item = gtk_action_create_menu_item (lp->data); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); g_object_unref (G_OBJECT (lp->data)); gtk_widget_show (item); } g_list_free (actions); /* append another separator */ item = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); } } } /* append the cancel item */ item = gtk_image_menu_item_new_from_stock (GTK_STOCK_CANCEL, NULL); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); /* run the menu on the widget's screen (takes over the floating reference of menu) */ thunar_gtk_menu_run (GTK_MENU (menu), widget, NULL, NULL, 3, timestamp); /* cleanup */ g_object_unref (G_OBJECT (factory)); g_list_free_full (file_list, g_object_unref); return dnd_action; }