2
* @file popup_menu.c popup menus
4
* Copyright (C) 2003-2011 Lars Lindner <lars.lindner@gmail.com>
5
* Copyright (C) 2004-2006 Nathan J. Conrad <t98502@users.sourceforge.net>
6
* Copyright (C) 2009 Adrian Bunk <bunk@users.sourceforge.net>
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
#include "ui/popup_menu.h"
32
#include "net_monitor.h"
37
#include "ui/enclosure_list_view.h"
38
#include "ui/item_list_view.h"
39
#include "ui/itemview.h"
40
#include "ui/liferea_shell.h"
41
#include "ui/feed_list_view.h"
42
#include "ui/ui_prefs.h"
43
#include "fl_sources/node_source.h"
45
#define UI_POPUP_ITEM_IS_TOGGLE 1
54
on_toggle_visibility (void)
56
liferea_shell_toggle_visibility ();
60
ui_popup_menu_at_pos (GtkWidget *menu, GtkMenuPositionFunc func, guint button, guint32 activate_time, gpointer user_data)
62
g_signal_connect_after (G_OBJECT(menu), "unmap-event", G_CALLBACK(gtk_widget_destroy), NULL);
64
gtk_widget_show_all (menu);
66
gtk_menu_popup (GTK_MENU(menu), NULL, NULL, func, user_data, button, activate_time);
70
ui_popup_menu (GtkWidget *menu, guint button, guint32 activate_time)
72
ui_popup_menu_at_pos(menu, NULL, button, activate_time, NULL);
76
ui_popup_add_menuitem (GtkWidget *menu, const gchar *label, gpointer callback, gpointer data, const gchar *icon, gint toggle)
82
item = gtk_check_menu_item_new_with_label (label);
83
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(item), toggle - UI_POPUP_ITEM_IS_TOGGLE);
87
item = gtk_image_menu_item_new_with_label (label);
88
image = gtk_image_new_from_stock (icon, GTK_ICON_SIZE_MENU);
89
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
91
item = gtk_image_menu_item_new_from_stock (icon, NULL);
94
item = gtk_menu_item_new_with_label (label);
99
g_signal_connect_swapped (G_OBJECT(item), "activate", G_CALLBACK(callback), data);
101
gtk_menu_item_set_use_underline (GTK_MENU_ITEM(item), TRUE);
102
gtk_menu_shell_append (GTK_MENU_SHELL(menu), item);
108
ui_popup_item_menu (itemPtr item, guint button, guint32 activate_time)
114
menu = gtk_menu_new ();
116
ui_popup_add_menuitem (menu, _("Launch Item In _Tab"), on_popup_launchitem_in_tab_selected, NULL, NULL, 0);
117
ui_popup_add_menuitem (menu, _("_Launch Item In Browser"), on_popup_launchitem_selected, NULL, NULL, 0);
119
gtk_menu_shell_append (GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
121
iter = newsbin_get_list ();
127
submenu = gtk_menu_new ();
129
item = ui_popup_add_menuitem (menu, _("Copy to News Bin"), NULL, NULL, NULL, 0);
132
nodePtr node = (nodePtr)iter->data;
133
ui_popup_add_menuitem (submenu, node_get_title (node), on_popup_copy_to_newsbin, GINT_TO_POINTER(i), NULL, 0);
134
iter = g_slist_next (iter);
138
gtk_menu_item_set_submenu (GTK_MENU_ITEM(item), submenu);
140
gtk_menu_shell_append (GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
143
text = g_strdup_printf (_("_Bookmark Link at %s"), social_get_bookmark_site ());
144
ui_popup_add_menuitem (menu, text, on_popup_social_bm_item_selected, NULL, NULL, 0);
147
ui_popup_add_menuitem (menu, _("Copy Item _URL to Clipboard"), on_popup_copy_URL_clipboard, NULL, NULL, 0);
149
gtk_menu_shell_append (GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
151
ui_popup_add_menuitem (menu, _("Toggle _Read Status"), on_popup_toggle_read, NULL, GTK_STOCK_APPLY, 0);
152
ui_popup_add_menuitem (menu, _("Toggle Item _Flag"), on_popup_toggle_flag, NULL, NULL, 0);
153
ui_popup_add_menuitem (menu, _("R_emove Item"), on_popup_remove_selected, NULL, GTK_STOCK_DELETE, 0);
155
ui_popup_menu (menu, button, activate_time);
159
ui_popup_enclosure_menu (enclosurePtr enclosure, guint button,
160
guint32 activate_time)
164
menu = gtk_menu_new ();
166
ui_popup_add_menuitem (menu, _("Open Enclosure..."), on_popup_open_enclosure, enclosure, NULL, 0);
167
ui_popup_add_menuitem (menu, _("Save As..."), on_popup_save_enclosure, enclosure, NULL, 0);
168
ui_popup_add_menuitem (menu, _("Copy Link Location"), on_popup_copy_enclosure, enclosure, NULL, 0);
170
ui_popup_menu (menu, button, activate_time);
174
ui_popup_systray_menu (GtkMenuPositionFunc func, guint button, guint32 activate_time, gpointer user_data)
177
GtkWidget *mainwindow = liferea_shell_get_window ();
179
menu = gtk_menu_new ();
181
ui_popup_add_menuitem (menu, _("_Work Offline"), on_onlinebtn_clicked, NULL, NULL, (!network_monitor_is_online ()) + UI_POPUP_ITEM_IS_TOGGLE);
182
ui_popup_add_menuitem (menu, _("_Update All"), on_menu_update_all, NULL, GTK_STOCK_REFRESH, 0);
183
ui_popup_add_menuitem (menu, NULL, on_prefbtn_clicked, NULL, GTK_STOCK_PREFERENCES, 0);
185
gtk_menu_shell_append (GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
187
ui_popup_add_menuitem (menu, _("_Show Liferea"), on_toggle_visibility, NULL, NULL, (!(gdk_window_get_state (gtk_widget_get_window (mainwindow)) & GDK_WINDOW_STATE_ICONIFIED) && gtk_widget_get_visible (mainwindow)) + UI_POPUP_ITEM_IS_TOGGLE);
188
ui_popup_add_menuitem (menu, NULL, on_popup_quit, NULL, GTK_STOCK_QUIT, 0);
190
ui_popup_menu_at_pos (menu, func, button, activate_time, user_data);
193
/* popup callback wrappers */
196
ui_popup_mark_as_read (gpointer callback_data)
198
feedlist_mark_all_read ((nodePtr)callback_data);
202
ui_popup_add_feed (void)
204
node_type_request_interactive_add (feed_get_node_type ());
208
ui_popup_add_folder (void)
210
node_type_request_interactive_add (folder_get_node_type ());
214
ui_popup_add_vfolder (void)
216
node_type_request_interactive_add (vfolder_get_node_type ());
220
ui_popup_rebuild_vfolder (gpointer callback_data)
222
vfolder_rebuild ((nodePtr)callback_data);
226
ui_popup_add_source (void)
228
node_type_request_interactive_add (node_source_get_node_type ());
232
ui_popup_add_newsbin (void)
234
node_type_request_interactive_add (newsbin_get_node_type ());
238
ui_popup_properties (gpointer callback_data)
240
nodePtr node = (nodePtr) callback_data;
242
NODE_TYPE (node)->request_properties (node);
246
ui_popup_delete (gpointer callback_data)
248
feed_list_view_delete_prompt ((nodePtr)callback_data);
252
ui_popup_sort_feeds (gpointer callback_data)
254
feed_list_view_sort_folder ((nodePtr)callback_data);
258
* Shows popup menus for the feed list depending on the
262
ui_popup_node_menu (nodePtr node, gboolean validSelection, guint button, guint32 activate_time)
265
gboolean writeableFeedlist, isRoot, isHierarchic;
267
menu = gtk_menu_new ();
270
writeableFeedlist = NODE_SOURCE_TYPE (node->parent->source->root)->capabilities & NODE_SOURCE_CAPABILITY_WRITABLE_FEEDLIST;
271
isRoot = NODE_SOURCE_TYPE (node->parent->source->root)->capabilities & NODE_SOURCE_CAPABILITY_IS_ROOT;
272
isHierarchic = NODE_SOURCE_TYPE (node->parent->source->root)->capabilities & NODE_SOURCE_CAPABILITY_HIERARCHIC_FEEDLIST;
274
/* if we have no parent then we have the root node... */
275
writeableFeedlist = TRUE;
280
if (validSelection) {
281
if (NODE_TYPE (node)->capabilities & NODE_CAPABILITY_UPDATE)
282
ui_popup_add_menuitem (menu, _("_Update"), on_menu_update, node, GTK_STOCK_REFRESH, 0);
283
else if (NODE_TYPE (node)->capabilities & NODE_CAPABILITY_UPDATE_CHILDS)
284
ui_popup_add_menuitem (menu, _("_Update Folder"), on_menu_update, node, GTK_STOCK_REFRESH, 0);
286
ui_popup_add_menuitem (menu, _("_Mark All As Read"), ui_popup_mark_as_read, node, GTK_STOCK_APPLY, 0);
289
if (writeableFeedlist) {
290
if (NODE_TYPE (node->source->root)->capabilities & NODE_CAPABILITY_ADD_CHILDS) {
294
submenu = gtk_menu_new ();
296
item = ui_popup_add_menuitem (menu, _("_New"), NULL, NULL, NULL, 0);
298
ui_popup_add_menuitem (submenu, _("New _Subscription..."), ui_popup_add_feed, NULL, NULL, 0);
301
ui_popup_add_menuitem (submenu, _("New _Folder..."), ui_popup_add_folder, NULL, NULL, 0);
304
ui_popup_add_menuitem (submenu, _("New S_earch Folder..."), ui_popup_add_vfolder, NULL, NULL, 0);
305
ui_popup_add_menuitem (submenu, _("New S_ource..."), ui_popup_add_source, NULL, NULL, 0);
306
ui_popup_add_menuitem (submenu, _("New _News Bin..."), ui_popup_add_newsbin, NULL, NULL, 0);
309
gtk_menu_item_set_submenu (GTK_MENU_ITEM(item), submenu);
312
if (node->children) {
313
gtk_menu_shell_append (GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
314
ui_popup_add_menuitem (menu, _("Sort Feeds"), ui_popup_sort_feeds, node, GTK_STOCK_SORT_ASCENDING, 0);
318
if (IS_VFOLDER (node)) {
319
gtk_menu_shell_append (GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
320
ui_popup_add_menuitem (menu, _("_Rebuild"), ui_popup_rebuild_vfolder, node, NULL, 0);
323
if (validSelection) {
324
if (writeableFeedlist) {
325
gtk_menu_shell_append (GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
326
ui_popup_add_menuitem (menu, NULL, ui_popup_delete, node, GTK_STOCK_DELETE, 0);
327
ui_popup_add_menuitem (menu, NULL, ui_popup_properties, node, GTK_STOCK_PROPERTIES, 0);
331
ui_popup_menu (menu, button, activate_time);
334
/* mouse button handler */
336
on_mainfeedlist_button_press_event (GtkWidget *widget,
337
GdkEventButton *event,
345
gboolean selected = TRUE;
348
treeview = liferea_shell_lookup ("feedlist");
350
if (event->type != GDK_BUTTON_PRESS)
353
eb = (GdkEventButton*)event;
356
if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (treeview), event->x, event->y, &path, NULL, NULL, NULL)) {
357
model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
358
gtk_tree_model_get_iter (model, &iter, path);
359
gtk_tree_path_free (path);
360
gtk_tree_model_get (model, &iter, FS_PTR, &node, -1);
363
node = feedlist_get_root ();
367
switch (eb->button) {
373
feedlist_mark_all_read (node);
374
itemview_update_node_info (node);
380
feed_list_view_select (node);
382
/* This happens when an "empty" node or nothing (feed list root) is clicked */
384
node = feedlist_get_root ();
387
gtk_widget_grab_focus (widget);
388
ui_popup_node_menu (node, selected, eb->button, eb->time);
395
/* popup key handler */
397
on_mainfeedlist_popup_menu (GtkWidget *widget,
401
GtkTreeSelection *selection;
404
gboolean selected = TRUE;
407
treeview = liferea_shell_lookup ("feedlist");
408
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
409
if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
410
gtk_tree_model_get (model, &iter, FS_PTR, &node, -1);
413
node = feedlist_get_root ();
416
ui_popup_node_menu (node, selected, 3, gtk_get_current_event_time ());