static void thunar_chooser_button_pressed (ThunarChooserButton *chooser_button, GtkWidget *button) { ThunarVfsMimeApplication *default_application; ThunarVfsMimeInfo *info; ThunarIconFactory *icon_factory; GtkIconTheme *icon_theme; const gchar *icon_name; GdkPixbuf *icon; GtkWidget *image; GtkWidget *item; GtkWidget *menu; GList *applications; GList *lp; gint icon_size; _thunar_return_if_fail (THUNAR_IS_CHOOSER_BUTTON (chooser_button)); _thunar_return_if_fail (chooser_button->button == button); _thunar_return_if_fail (GTK_IS_BUTTON (button)); /* verify that we have a valid file */ if (G_UNLIKELY (chooser_button->file == NULL)) return; /* determine the mime info for the file */ info = thunar_file_get_mime_info (chooser_button->file); /* determine the default application */ default_application = thunar_vfs_mime_database_get_default_application (chooser_button->database, info); if (G_UNLIKELY (default_application == NULL)) { /* no default application, just popup the application chooser */ thunar_chooser_button_activate_other (chooser_button); return; } /* determine all applications that claim to be able to handle the file */ applications = thunar_vfs_mime_database_get_applications (chooser_button->database, info); /* make sure the default application comes first */ lp = g_list_find (applications, default_application); if (G_LIKELY (lp != NULL)) { applications = g_list_delete_link (applications, lp); g_object_unref (G_OBJECT (default_application)); } applications = g_list_prepend (applications, default_application); /* allocate a new popup menu */ menu = gtk_menu_new (); /* determine the icon size for menus */ gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_size, &icon_size); /* determine the icon factory for our screen */ icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (button)); icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme); /* add the other possible applications */ for (lp = applications; lp != NULL; lp = lp->next) { item = gtk_image_menu_item_new_with_label (thunar_vfs_mime_handler_get_name (lp->data)); g_object_set_data_full (G_OBJECT (item), I_("thunar-vfs-mime-application"), lp->data, g_object_unref); g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_chooser_button_activate), chooser_button); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); /* setup the icon for the application */ icon_name = thunar_vfs_mime_handler_lookup_icon_name (lp->data, icon_theme); icon = thunar_icon_factory_load_icon (icon_factory, icon_name, icon_size, NULL, FALSE); image = gtk_image_new_from_pixbuf (icon); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); gtk_widget_show (image); if (G_LIKELY (icon != NULL)) g_object_unref (icon); } /* cleanup */ g_object_unref (G_OBJECT (icon_factory)); /* append a separator */ item = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); /* release the applications list */ g_list_free (applications); /* add the "Other Application..." choice */ item = gtk_image_menu_item_new_with_mnemonic (_("_Other Application...")); g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (thunar_chooser_button_activate_other), chooser_button); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); /* make sure the menu has atleast the same width as the chooser */ if (menu->allocation.width < button->allocation.width) gtk_widget_set_size_request (menu, button->allocation.width, -1); /* run the menu on the button's screen (takes over the floating reference of menu) */ thunar_gtk_menu_run (GTK_MENU (menu), button, menu_position, button, 0, gtk_get_current_event_time ()); /* yeppa, that's a requirement */ gtk_button_released (GTK_BUTTON (button)); }
static void thunar_location_entry_button_clicked (GtkWidget *button, ThunarLocationEntry *location_entry) { ThunarShortcutsModel *model; ThunarIconFactory *icon_factory; ThunarVfsVolume *volume; GtkIconTheme *icon_theme; const gchar *icon_name; GtkTreeIter iter; ThunarFile *file; GtkWidget *image; GtkWidget *item; GtkWidget *menu; GdkPixbuf *icon; gint icon_size; gint width; _thunar_return_if_fail (THUNAR_IS_LOCATION_ENTRY (location_entry)); _thunar_return_if_fail (GTK_IS_TOGGLE_BUTTON (button)); /* allocate a new menu */ menu = gtk_menu_new (); /* determine the icon theme and factory */ icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (button)); icon_factory = thunar_icon_factory_get_for_icon_theme (icon_theme); /* determine the icon size for menus */ gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_size, &icon_size); /* load the menu items from the shortcuts model */ model = thunar_shortcuts_model_get_default (); if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter)) { do { /* determine the file and volume for the item */ gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, THUNAR_SHORTCUTS_MODEL_COLUMN_FILE, &file, THUNAR_SHORTCUTS_MODEL_COLUMN_VOLUME, &volume, -1); /* check if we have a separator here */ if (G_UNLIKELY (file == NULL && volume == NULL)) { /* generate a separator the menu */ item = gtk_separator_menu_item_new (); } else if (G_UNLIKELY (volume != NULL)) { /* generate an image menu item for the volume */ item = gtk_image_menu_item_new_with_label (thunar_vfs_volume_get_name (volume)); /* load the icon for the volume */ icon_name = thunar_vfs_volume_lookup_icon_name (volume, icon_theme); icon = thunar_icon_factory_load_icon (icon_factory, icon_name, icon_size, NULL, FALSE); if (G_LIKELY (icon != NULL)) { /* generate an image for the menu item */ image = gtk_image_new_from_pixbuf (icon); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); g_object_unref (G_OBJECT (icon)); gtk_widget_show (image); } } else { /* generate an image menu item for the file */ item = gtk_image_menu_item_new_with_label (thunar_file_get_display_name (file)); /* load the icon for the file and generate the image for the menu item */ icon = thunar_icon_factory_load_file_icon (icon_factory, file, THUNAR_FILE_ICON_STATE_DEFAULT, icon_size); image = gtk_image_new_from_pixbuf (icon); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); g_object_unref (G_OBJECT (icon)); gtk_widget_show (image); } /* connect the file and volume to the item */ g_object_set_data_full (G_OBJECT (item), I_("thunar-vfs-volume"), volume, g_object_unref); g_object_set_data_full (G_OBJECT (item), I_("thunar-file"), file, g_object_unref); /* append the new item to the menu */ g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (thunar_location_entry_item_activated), location_entry); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &iter)); } /* make sure the menu has atleast the same width as the location entry */ width = GTK_WIDGET (location_entry)->allocation.width - 2 * gtk_container_get_border_width (GTK_CONTAINER (location_entry)); if (G_LIKELY (menu->allocation.width < width)) gtk_widget_set_size_request (menu, width, -1); /* select the first visible or selectable item in the menu */ gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), TRUE); /* enable the button, making sure that we do not recurse on the "clicked" signal by temporarily blocking the handler */ g_signal_handlers_block_by_func (G_OBJECT (button), G_CALLBACK (thunar_location_entry_button_clicked), location_entry); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); g_signal_handlers_unblock_by_func (G_OBJECT (button), G_CALLBACK (thunar_location_entry_button_clicked), location_entry); /* run the menu, taking ownership over the menu object */ thunar_gtk_menu_run (GTK_MENU (menu), button, menu_position, location_entry, 1, gtk_get_current_event_time ()); /* disable the button, making sure that we do not recurse on the "clicked" signal by temporarily blocking the handler */ g_signal_handlers_block_by_func (G_OBJECT (button), G_CALLBACK (thunar_location_entry_button_clicked), location_entry); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE); g_signal_handlers_unblock_by_func (G_OBJECT (button), G_CALLBACK (thunar_location_entry_button_clicked), location_entry); /* clean up */ g_object_unref (G_OBJECT (icon_factory)); g_object_unref (G_OBJECT (model)); }
/** * 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; }