Index: ephy-rss-extension.c =================================================================== RCS file: /cvs/gnome/epiphany-extensions/extensions/rss/ephy-rss-extension.c,v retrieving revision 1.1 diff -p -u -u -p -r1.1 ephy-rss-extension.c --- ephy-rss-extension.c 10 Apr 2005 18:52:19 -0000 1.1 +++ ephy-rss-extension.c 16 Apr 2005 11:18:14 -0000 @@ -71,8 +71,7 @@ static void ephy_rss_display_cb (GtkAct EphyWindow *window); static void ephy_rss_update_statusbar (EphyWindow *window, gboolean show); -static void ephy_rss_update_action (EphyWindow *window, - EphyEmbed *embed); +static void ephy_rss_update_action (EphyWindow *window); typedef struct { @@ -112,7 +111,7 @@ ephy_rss_ge_feed_cb (EphyEmbed *embed, LOG ("Got a new feed for the site: type=%s, title=%s, address=%s\nWe now have %d feeds", type, title, address, rss_feedlist_length (list)); - ephy_rss_update_action (window, embed); + ephy_rss_update_action (window); } static void @@ -168,7 +167,7 @@ ephy_rss_ge_content_cb (EphyEmbed *embed g_object_set_data (G_OBJECT (embed), FEEDLIST_DATA_KEY, NULL); - ephy_rss_update_action (window, embed); + ephy_rss_update_action (window); } static void @@ -187,12 +186,14 @@ ephy_rss_update_statusbar (EphyWindow *w /* Update the menu item availability */ static void -ephy_rss_update_action (EphyWindow *window, - EphyEmbed *embed) +ephy_rss_update_action (EphyWindow *window) { WindowData *data; FeedList *list; gboolean show = TRUE; + EphyEmbed *embed; + + embed = ephy_window_get_active_embed (window); /* The page is loaded, do we have a feed ? */ list = (FeedList *) g_object_get_data (G_OBJECT (embed), FEEDLIST_DATA_KEY); @@ -201,6 +202,7 @@ ephy_rss_update_action (EphyWindow *wind /* Disable the menu item when loading the page */ data = (WindowData *) g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY); + g_return_if_fail (data != NULL); g_object_set (data->action, "sensitive", show, NULL); @@ -209,14 +211,13 @@ ephy_rss_update_action (EphyWindow *wind /* Called when the user changes tab */ static void -ephy_rss_switch_page_cb (GtkNotebook *notebook, - GtkNotebookPage *page, - guint page_num, - EphyWindow *window) +ephy_rss_sync_active_tab (EphyWindow *window, + GParamSpec *pspec, + gpointer data) { if (GTK_WIDGET_REALIZED (window) == FALSE) return; /* on startup */ - ephy_rss_update_action (window, ephy_tab_get_embed (ephy_window_get_active_tab (window))); + ephy_rss_update_action (window); } /* When the load status changes update menu item */ @@ -227,7 +228,7 @@ ephy_rss_load_status_cb (EphyTab *tab, { if (tab == ephy_window_get_active_tab (window)) { - ephy_rss_update_action (window, ephy_tab_get_embed (tab)); + ephy_rss_update_action (window); } } @@ -357,7 +358,6 @@ impl_attach_window (EphyExtension *ext, GtkUIManager *manager; guint ui_id; WindowData *data; - GtkWidget *notebook; manager = GTK_UI_MANAGER (ephy_window_get_ui_manager (window)); @@ -382,10 +382,9 @@ impl_attach_window (EphyExtension *ext, GTK_UI_MANAGER_SEPARATOR, FALSE); /* Register for tab switch events */ - notebook = ephy_window_get_notebook (window); - - g_signal_connect_after (notebook, "switch_page", - G_CALLBACK (ephy_rss_switch_page_cb), window); + ephy_rss_sync_active_tab (window, NULL, NULL); + g_signal_connect_after (window, "notify::active-tab", + G_CALLBACK (ephy_rss_sync_active_tab), NULL); /* store data */ data = g_new (WindowData, 1); @@ -396,7 +395,7 @@ impl_attach_window (EphyExtension *ext, data->ui_id = ui_id; g_object_set_data_full (G_OBJECT (window), WINDOW_DATA_KEY, data, - (GDestroyNotify) g_free); + (GDestroyNotify) g_free); /* Create the status bar icon */ ephy_rss_create_statusbar_icon (window, data); @@ -409,7 +408,6 @@ impl_detach_window (EphyExtension *ext, { GtkUIManager *manager; WindowData *data; - GtkWidget *notebook; manager = GTK_UI_MANAGER (ephy_window_get_ui_manager (window)); @@ -421,10 +419,8 @@ impl_detach_window (EphyExtension *ext, gtk_ui_manager_remove_action_group (manager, data->action_group); /* Remove the tab switch notification */ - notebook = ephy_window_get_notebook (window); - g_signal_handlers_disconnect_by_func - (notebook, G_CALLBACK (ephy_rss_switch_page_cb), window); + (window, G_CALLBACK (ephy_rss_sync_active_tab), NULL); /* Remove the status bar icon */ ephy_rss_destroy_statusbar_icon (window, data); Index: rss-ui.c =================================================================== RCS file: /cvs/gnome/epiphany-extensions/extensions/rss/rss-ui.c,v retrieving revision 1.1 diff -p -u -u -p -r1.1 rss-ui.c --- rss-ui.c 10 Apr 2005 18:52:19 -0000 1.1 +++ rss-ui.c 16 Apr 2005 11:18:14 -0000 @@ -22,6 +22,8 @@ #include "rss-ui.h" +#include "ephy-gui.h" +#include "ephy-dnd.h" #include "ephy-debug.h" #include @@ -34,10 +36,15 @@ #include #include #include +#include +#include +#include +#include +#include #include -#include +#include #define RSS_UI_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE((object), TYPE_RSS_UI, RssUIPrivate)) @@ -109,8 +116,15 @@ typedef struct char *hostname; } FeedSelectionDecision; +/* Drag and drop stuff */ +static GtkTargetEntry drag_targets[] = +{ + { EPHY_DND_URL_TYPE, 0, 0 }, + { EPHY_DND_TEXT_TYPE, 0, 1 } +}; + /* glade callbacks */ -void rss_ui_response_cb (GtkWidget *button, +void rss_ui_response_cb (GtkWidget *button, int response, RssUI *dialog); @@ -296,6 +310,169 @@ rss_feed_toggle_cb (GtkCellRendererToggl gtk_list_store_set (store, &iter, COL_TOGGLE, !active, -1); } +static NewsFeed * +rss_ui_get_selected_feed (RssUI *dialog) +{ + RssUIPrivate *priv = dialog->priv; + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + NewsFeed *feed = NULL; + + selection = gtk_tree_view_get_selection (priv->treeview); + if (gtk_tree_selection_get_selected (selection, &model, &iter)) + { + gtk_tree_model_get (model, &iter, COL_FEED, &feed, -1); + } + + return feed; +} + +static void +rss_ui_treeview_page_copy_selected (GtkWidget *widget, + RssUI *dialog) +{ + NewsFeed *feed; + + LOG ("Copying selected feed"); + + feed = rss_ui_get_selected_feed (dialog); + if (feed != NULL) + { + gtk_clipboard_set_text (gtk_clipboard_get (GDK_NONE), + feed->address, -1); + gtk_clipboard_set_text (gtk_clipboard_get (GDK_SELECTION_PRIMARY), + feed->address, -1); + + rss_newsfeed_free (feed); + } +} + +static GtkMenu * +rss_ui_build_context_menu (RssUI *dialog) +{ + GtkWidget *menu; + GtkWidget *item, *image; + + LOG ("Building context menu"); + + menu = gtk_menu_new (); + + image = gtk_image_new_from_stock (GTK_STOCK_COPY, GTK_ICON_SIZE_BUTTON); + gtk_widget_show (image); + + item = gtk_image_menu_item_new_with_mnemonic (_("_Copy Feed Address")); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); + g_signal_connect (item, "activate", + G_CALLBACK (rss_ui_treeview_page_copy_selected), + dialog); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show (item); + + return GTK_MENU (menu); +} + +static gboolean +rss_ui_treeview_show_popup (GtkTreeView *treeview, + RssUI *dialog) +{ + GtkMenu *menu; + + LOG ("Got a keyboard popup"); + + menu = rss_ui_build_context_menu (dialog); + gtk_menu_popup (menu, NULL, NULL, + ephy_gui_menu_position_tree_selection, treeview, 0, + gtk_get_current_event_time ()); + gtk_menu_shell_select_first (GTK_MENU_SHELL (menu), FALSE); + + return TRUE; +} + +static gboolean +rss_ui_treeview_button_pressed_cb (GtkTreeView *treeview, + GdkEventButton *event, + RssUI *dialog) +{ + RssUIPrivate *priv = dialog->priv; + GtkTreeModel *model = GTK_TREE_MODEL (priv->store); + GtkTreeSelection *selection; + GtkTreeIter iter; + GtkTreePath *path = NULL; + GtkMenu *menu; + + LOG ("Got a button press"); + + /* right-click? */ + if (event->button != 3) + { + return FALSE; + } + + /* Get tree path for row that was clicked */ + if (!gtk_tree_view_get_path_at_pos (treeview, + event->x, event->y, + &path, NULL, NULL, NULL)) + { + return FALSE; + } + + if (!gtk_tree_model_get_iter (model, &iter, path)) + { + gtk_tree_path_free(path); + return FALSE; + } + + /* Select the row the user clicked on */ + selection = gtk_tree_view_get_selection (treeview); + if (gtk_tree_selection_count_selected_rows (selection) == 1) + { + gtk_tree_selection_unselect_all (selection); + gtk_tree_selection_select_path (selection, path); + gtk_tree_path_free (path); + } + + /* now popup the menu */ + menu = rss_ui_build_context_menu (dialog); + gtk_menu_popup (menu, NULL, NULL, NULL, NULL, + event->button, event->time); + + return TRUE; +} + +/* Set dnd cursor to the default dnd Gtk one and not the GtktreeView one */ +static void +rss_ui_drag_begin_cb (GtkWidget *widget, + GdkDragContext *dc, + RssUI *dialog) +{ + gtk_drag_set_icon_default (dc); +} + +static void +rss_ui_drag_data_get_cb (GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint32 time, + RssUI *dialog) +{ + NewsFeed *feed; + + LOG ("Drag trying to get data"); + + feed = rss_ui_get_selected_feed (dialog); + if (feed == NULL || feed->address == NULL) return; + + gtk_selection_data_set (selection_data, + selection_data->target, + 8, + feed->address, + strlen (feed->address)); + + rss_newsfeed_free (feed); +} + static gboolean rss_ui_select_feeds (GtkTreeModel *model, GtkTreePath *path, @@ -422,6 +599,7 @@ rss_ui_constructor (GType type, RssUIPrivate *priv; EphyDialog *edialog; GtkCellRenderer *renderer; + GtkTreeSelection *selection; object = parent_class->constructor (type, n_construct_properties, construct_params); @@ -477,6 +655,26 @@ rss_ui_constructor (GType type, gtk_tree_view_set_search_column (priv->treeview, COL_SEARCH); g_object_unref (priv->store); + + selection = gtk_tree_view_get_selection (priv->treeview); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); + + /* Build the context menu stuff */ + g_signal_connect (priv->treeview, "popup-menu", + G_CALLBACK (rss_ui_treeview_show_popup), dialog); + g_signal_connect (priv->treeview, "button-press-event", + G_CALLBACK (rss_ui_treeview_button_pressed_cb), dialog); + + /* Set up drag and drop */ + gtk_tree_view_enable_model_drag_source (priv->treeview, GDK_BUTTON1_MASK, + drag_targets, G_N_ELEMENTS (drag_targets), + GDK_ACTION_COPY); + g_signal_connect (priv->treeview, "drag_data_get", + G_CALLBACK(rss_ui_drag_data_get_cb), dialog); + + /* Be careful, default handler forces dnd icon to be an image of the row ! */ + g_signal_connect_after (priv->treeview, "drag_begin", + G_CALLBACK (rss_ui_drag_begin_cb), dialog); return object; }