~ubuntu-branches/ubuntu/vivid/liferea/vivid-proposed

« back to all changes in this revision

Viewing changes to src/ui/popup_menu.c

  • Committer: Package Import Robot
  • Author(s): bojo42
  • Date: 2012-03-29 14:17:21 UTC
  • mfrom: (1.3.9) (3.2.5 sid)
  • Revision ID: package-import@ubuntu.com-20120329141721-tbfopcrc5797wxt7
Tags: 1.8.3-0.1ubuntu1
* New upstream release (LP: #290666, #371754, #741543, #716688)
* Merge from Debian unstable (LP: #935147), remaining changes:
* debian/patches:
  - drop gtk-status-icon.patch & notification-append as in upstream
  - drop fix_systray_behavior as mostly upstreamed and rest seems unused
  - 01_ubuntu_feedlists: update & rename, move planets to "Open Source"  
  - add_X-Ubuntu-Gettext-Domain: rebase
  - libunity.patch: rebase, apply before indicator patch (liferea_shell.c)
  - libindicate_increase_version.patch: exclude from libindicate.patch
  - deactivate libindicate.patch, seems partly upstreamed and needs rework
* debian/control: libindicate-dev, libindicate-gtk-dev & libunity-dev
* debian/liferea.indicate & liferea.install: ship indicator desktop file
* debian/rules: enable libindicate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * @file popup_menu.c popup menus
 
3
 *
 
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>
 
7
 *
 
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.
 
12
 *
 
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.
 
17
 *
 
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 
 
21
 */
 
22
 
 
23
#include "ui/popup_menu.h"
 
24
 
 
25
#include <string.h>
 
26
 
 
27
#include "common.h"
 
28
#include "feed.h"
 
29
#include "feedlist.h"
 
30
#include "folder.h"
 
31
#include "itemlist.h"
 
32
#include "net_monitor.h"
 
33
#include "newsbin.h"
 
34
#include "node.h"
 
35
#include "social.h"
 
36
#include "vfolder.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"
 
44
 
 
45
#define UI_POPUP_ITEM_IS_TOGGLE         1
 
46
 
 
47
static void
 
48
on_popup_quit (void)
 
49
{
 
50
        liferea_shutdown ();
 
51
}
 
52
 
 
53
static void
 
54
on_toggle_visibility (void)
 
55
{
 
56
        liferea_shell_toggle_visibility ();
 
57
}
 
58
 
 
59
static void
 
60
ui_popup_menu_at_pos (GtkWidget *menu, GtkMenuPositionFunc func, guint button, guint32 activate_time, gpointer user_data)
 
61
{
 
62
        g_signal_connect_after (G_OBJECT(menu), "unmap-event", G_CALLBACK(gtk_widget_destroy), NULL);
 
63
 
 
64
        gtk_widget_show_all (menu);
 
65
 
 
66
        gtk_menu_popup (GTK_MENU(menu), NULL, NULL, func, user_data, button, activate_time);
 
67
}
 
68
 
 
69
static void
 
70
ui_popup_menu (GtkWidget *menu, guint button, guint32 activate_time)
 
71
{
 
72
        ui_popup_menu_at_pos(menu, NULL, button, activate_time, NULL);
 
73
}
 
74
 
 
75
static GtkWidget*
 
76
ui_popup_add_menuitem (GtkWidget *menu, const gchar *label, gpointer callback, gpointer data, const gchar *icon, gint toggle)
 
77
{
 
78
        GtkWidget       *item;
 
79
        GtkWidget       *image;
 
80
 
 
81
        if (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);
 
84
        } else {
 
85
                if (icon) {
 
86
                        if (label) {
 
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);
 
90
                        } else {
 
91
                                item = gtk_image_menu_item_new_from_stock (icon, NULL);
 
92
                        }
 
93
                } else {
 
94
                        item = gtk_menu_item_new_with_label (label);
 
95
                }
 
96
        }
 
97
 
 
98
        if (callback)
 
99
                g_signal_connect_swapped (G_OBJECT(item), "activate", G_CALLBACK(callback), data);
 
100
 
 
101
        gtk_menu_item_set_use_underline (GTK_MENU_ITEM(item), TRUE);
 
102
        gtk_menu_shell_append (GTK_MENU_SHELL(menu), item);
 
103
 
 
104
        return item;
 
105
}
 
106
 
 
107
void
 
108
ui_popup_item_menu (itemPtr item, guint button, guint32 activate_time)
 
109
{
 
110
        GtkWidget       *menu;
 
111
        GSList          *iter;
 
112
        gchar           *text;
 
113
 
 
114
        menu = gtk_menu_new ();
 
115
 
 
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);
 
118
 
 
119
        gtk_menu_shell_append (GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
 
120
 
 
121
        iter = newsbin_get_list ();
 
122
        if (iter) {
 
123
                GtkWidget       *item;
 
124
                GtkWidget       *submenu;
 
125
                int             i = 0;
 
126
 
 
127
                submenu = gtk_menu_new ();
 
128
 
 
129
                item = ui_popup_add_menuitem (menu, _("Copy to News Bin"), NULL, NULL, NULL, 0);
 
130
 
 
131
                while (iter) {
 
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);
 
135
                        i++;
 
136
                }
 
137
 
 
138
                gtk_menu_item_set_submenu (GTK_MENU_ITEM(item), submenu);
 
139
 
 
140
                gtk_menu_shell_append (GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
 
141
        }
 
142
 
 
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);
 
145
        g_free (text);
 
146
 
 
147
        ui_popup_add_menuitem (menu, _("Copy Item _URL to Clipboard"), on_popup_copy_URL_clipboard, NULL, NULL, 0);
 
148
        
 
149
        gtk_menu_shell_append (GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
 
150
 
 
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);
 
154
 
 
155
        ui_popup_menu (menu, button, activate_time);
 
156
}
 
157
 
 
158
void
 
159
ui_popup_enclosure_menu (enclosurePtr enclosure, guint button,
 
160
                         guint32 activate_time)
 
161
{
 
162
        GtkWidget       *menu;
 
163
 
 
164
        menu = gtk_menu_new ();
 
165
 
 
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);
 
169
 
 
170
        ui_popup_menu (menu, button, activate_time);
 
171
}
 
172
 
 
173
void
 
174
ui_popup_systray_menu (GtkMenuPositionFunc func, guint button, guint32 activate_time, gpointer user_data)
 
175
{
 
176
        GtkWidget       *menu;
 
177
        GtkWidget       *mainwindow = liferea_shell_get_window ();
 
178
 
 
179
        menu = gtk_menu_new ();
 
180
 
 
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);
 
184
 
 
185
        gtk_menu_shell_append (GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
 
186
 
 
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);
 
189
 
 
190
        ui_popup_menu_at_pos (menu, func, button, activate_time, user_data);
 
191
}
 
192
 
 
193
/* popup callback wrappers */
 
194
 
 
195
static void
 
196
ui_popup_mark_as_read (gpointer callback_data) 
 
197
{
 
198
        feedlist_mark_all_read ((nodePtr)callback_data);
 
199
}
 
200
 
 
201
static void
 
202
ui_popup_add_feed (void)
 
203
{
 
204
        node_type_request_interactive_add (feed_get_node_type ());
 
205
}
 
206
 
 
207
static void
 
208
ui_popup_add_folder (void)
 
209
{
 
210
        node_type_request_interactive_add (folder_get_node_type ());
 
211
}
 
212
 
 
213
static void
 
214
ui_popup_add_vfolder (void)
 
215
{
 
216
        node_type_request_interactive_add (vfolder_get_node_type ());
 
217
}
 
218
 
 
219
static void
 
220
ui_popup_rebuild_vfolder (gpointer callback_data)
 
221
{
 
222
        vfolder_rebuild ((nodePtr)callback_data);
 
223
}
 
224
 
 
225
static void
 
226
ui_popup_add_source (void)
 
227
{
 
228
        node_type_request_interactive_add (node_source_get_node_type ());
 
229
}
 
230
 
 
231
static void
 
232
ui_popup_add_newsbin (void)
 
233
{
 
234
        node_type_request_interactive_add (newsbin_get_node_type ());
 
235
}
 
236
 
 
237
static void
 
238
ui_popup_properties (gpointer callback_data)
 
239
{
 
240
        nodePtr node = (nodePtr) callback_data;
 
241
        
 
242
        NODE_TYPE (node)->request_properties (node);
 
243
}
 
244
 
 
245
static void
 
246
ui_popup_delete (gpointer callback_data)
 
247
{
 
248
        feed_list_view_delete_prompt ((nodePtr)callback_data);
 
249
}
 
250
 
 
251
static void
 
252
ui_popup_sort_feeds (gpointer callback_data)
 
253
{
 
254
        feed_list_view_sort_folder ((nodePtr)callback_data);
 
255
}
 
256
 
 
257
/** 
 
258
 * Shows popup menus for the feed list depending on the
 
259
 * node type.
 
260
 */
 
261
static void
 
262
ui_popup_node_menu (nodePtr node, gboolean validSelection, guint button, guint32 activate_time)
 
263
{
 
264
        GtkWidget       *menu;
 
265
        gboolean        writeableFeedlist, isRoot, isHierarchic;
 
266
 
 
267
        menu = gtk_menu_new ();
 
268
        
 
269
        if (node->parent) {
 
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;
 
273
        } else {
 
274
                /* if we have no parent then we have the root node... */
 
275
                writeableFeedlist = TRUE;
 
276
                isRoot = TRUE;
 
277
                isHierarchic = TRUE;
 
278
        }
 
279
 
 
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);
 
285
 
 
286
                ui_popup_add_menuitem (menu, _("_Mark All As Read"), ui_popup_mark_as_read, node, GTK_STOCK_APPLY, 0);
 
287
        }
 
288
 
 
289
        if (writeableFeedlist) {
 
290
                if (NODE_TYPE (node->source->root)->capabilities & NODE_CAPABILITY_ADD_CHILDS) {
 
291
                        GtkWidget       *item;
 
292
                        GtkWidget       *submenu;
 
293
 
 
294
                        submenu = gtk_menu_new ();
 
295
 
 
296
                        item = ui_popup_add_menuitem (menu, _("_New"), NULL, NULL, NULL, 0);
 
297
 
 
298
                        ui_popup_add_menuitem (submenu, _("New _Subscription..."), ui_popup_add_feed, NULL, NULL, 0);
 
299
                        
 
300
                        if (isHierarchic)
 
301
                                ui_popup_add_menuitem (submenu, _("New _Folder..."), ui_popup_add_folder, NULL, NULL, 0);
 
302
                                
 
303
                        if (isRoot) {
 
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);
 
307
                        }
 
308
 
 
309
                        gtk_menu_item_set_submenu (GTK_MENU_ITEM(item), submenu);
 
310
                }
 
311
                
 
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);
 
315
                }
 
316
        }
 
317
 
 
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);
 
321
        }
 
322
 
 
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);
 
328
                }
 
329
        }
 
330
 
 
331
        ui_popup_menu (menu, button, activate_time);
 
332
}
 
333
 
 
334
/* mouse button handler */
 
335
gboolean
 
336
on_mainfeedlist_button_press_event (GtkWidget *widget,
 
337
                                    GdkEventButton *event,
 
338
                                    gpointer user_data)
 
339
{
 
340
        GdkEventButton  *eb;
 
341
        GtkWidget       *treeview;
 
342
        GtkTreeModel    *model;
 
343
        GtkTreePath     *path;
 
344
        GtkTreeIter     iter;
 
345
        gboolean        selected = TRUE;
 
346
        nodePtr         node = NULL;
 
347
 
 
348
        treeview = liferea_shell_lookup ("feedlist");
 
349
 
 
350
        if (event->type != GDK_BUTTON_PRESS)
 
351
                return FALSE;
 
352
 
 
353
        eb = (GdkEventButton*)event;
 
354
 
 
355
        /* determine node */    
 
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);
 
361
        } else {
 
362
                selected = FALSE;
 
363
                node = feedlist_get_root ();
 
364
        }
 
365
        
 
366
        /* apply action */
 
367
        switch (eb->button) {
 
368
                default:
 
369
                        return FALSE;
 
370
                        break;
 
371
                case 2:
 
372
                        if (node) {
 
373
                                feedlist_mark_all_read (node);
 
374
                                itemview_update_node_info (node);
 
375
                                itemview_update ();
 
376
                        }
 
377
                        break;
 
378
                case 3:
 
379
                        if (node) {
 
380
                                feed_list_view_select (node);
 
381
                        } else {
 
382
                                /* This happens when an "empty" node or nothing (feed list root) is clicked */
 
383
                                selected = FALSE;
 
384
                                node = feedlist_get_root ();
 
385
                        }
 
386
 
 
387
                        gtk_widget_grab_focus (widget);
 
388
                        ui_popup_node_menu (node, selected, eb->button, eb->time);
 
389
                        break;
 
390
        }
 
391
                        
 
392
        return TRUE;
 
393
}
 
394
 
 
395
/* popup key handler */
 
396
gboolean
 
397
on_mainfeedlist_popup_menu (GtkWidget *widget,
 
398
                            gpointer   user_data)
 
399
{
 
400
        GtkWidget       *treeview;
 
401
        GtkTreeSelection *selection;
 
402
        GtkTreeModel    *model;
 
403
        GtkTreeIter     iter;
 
404
        gboolean        selected = TRUE;
 
405
        nodePtr         node = NULL;
 
406
 
 
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);
 
411
        } else {
 
412
                selected = FALSE;
 
413
                node = feedlist_get_root ();
 
414
        }
 
415
 
 
416
        ui_popup_node_menu (node, selected, 3, gtk_get_current_event_time ());
 
417
        return TRUE;
 
418
}