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

« back to all changes in this revision

Viewing changes to src/ui/ui_feedlist.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 ui_feedlist.c GUI feed list handling
3
 
 *
4
 
 * Copyright (C) 2004-2009 Lars Lindner <lars.lindner@gmail.com>
5
 
 * Copyright (C) 2004-2006 Nathan J. Conrad <t98502@users.sourceforge.net>
6
 
 * Copyright (C) 2005 Raphael Slinckx <raphael@slinckx.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/ui_feedlist.h"
24
 
 
25
 
#include <gtk/gtk.h>
26
 
#include <gdk/gdkkeysyms.h>
27
 
 
28
 
#include "common.h"
29
 
#include "conf.h"
30
 
#include "debug.h"
31
 
#include "feed.h"
32
 
#include "feedlist.h"
33
 
#include "folder.h"
34
 
#include "net.h"
35
 
#include "newsbin.h"
36
 
#include "vfolder.h"
37
 
#include "ui/browser_tabs.h"
38
 
#include "ui/liferea_shell.h"
39
 
#include "ui/ui_common.h"
40
 
#include "ui/ui_dnd.h"
41
 
#include "ui/ui_node.h"
42
 
#include "ui/ui_subscription.h"
43
 
#include "fl_sources/node_source.h"
44
 
 
45
 
GtkTreeModel            *filter;
46
 
GtkTreeStore            *feedstore = NULL;
47
 
 
48
 
gboolean                feedlist_reduced_unread = FALSE;
49
 
 
50
 
static void
51
 
ui_feedlist_row_changed_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter)
52
 
{
53
 
        nodePtr node;
54
 
        
55
 
        gtk_tree_model_get (model, iter, FS_PTR, &node, -1);
56
 
        if (node)
57
 
                ui_node_update_iter(node->id, iter);
58
 
}
59
 
 
60
 
static void
61
 
ui_feedlist_selection_changed_cb (GtkTreeSelection *selection, gpointer data)
62
 
{
63
 
        GtkTreeIter             iter;
64
 
        GtkTreeModel            *model;
65
 
        nodePtr                 node;
66
 
        gboolean                realNode = TRUE;
67
 
 
68
 
        if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
69
 
                gtk_tree_model_get (model, &iter, FS_PTR, &node, -1);
70
 
 
71
 
                debug1 (DEBUG_GUI, "feed list selection changed to \"%s\"", node_get_title(node));
72
 
 
73
 
                /* make sure thats no grouping iterator */
74
 
                // FIXME: check based on node capabilities!!!
75
 
                realNode = (node && (IS_FEED (node) || 
76
 
                                     IS_NEWSBIN (node) || 
77
 
                                     IS_VFOLDER (node) || 
78
 
                                     IS_NODE_SOURCE (node)));
79
 
                if (realNode)
80
 
                        browser_tabs_show_headlines ();
81
 
                
82
 
                /* update feed list and item list states */
83
 
                feedlist_selection_changed (node);
84
 
                
85
 
                if (node) {
86
 
                        gboolean allowModify = (NODE_SOURCE_TYPE (node->source->root)->capabilities & NODE_SOURCE_CAPABILITY_WRITABLE_FEEDLIST);
87
 
                        liferea_shell_update_update_menu ((NODE_TYPE (node)->capabilities & NODE_CAPABILITY_UPDATE) ||
88
 
                                                          (NODE_TYPE (node)->capabilities & NODE_CAPABILITY_UPDATE_CHILDS));
89
 
                        liferea_shell_update_feed_menu (allowModify, TRUE, allowModify);
90
 
                } else {
91
 
                        liferea_shell_update_feed_menu (TRUE, FALSE, FALSE);
92
 
                }
93
 
        } else {
94
 
                /* If we cannot get the new selection we keep the old one
95
 
                   this happens when we're doing drag&drop for example. */
96
 
        }
97
 
}
98
 
 
99
 
static void
100
 
ui_feedlist_row_activated_cb (GtkTreeView *tv, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
101
 
{
102
 
        GtkTreeIter     iter;
103
 
        nodePtr         node;
104
 
        
105
 
        gtk_tree_model_get_iter (gtk_tree_view_get_model (tv), &iter, path);
106
 
        gtk_tree_model_get (gtk_tree_view_get_model (tv), &iter, FS_PTR, &node, -1);
107
 
        if (node && IS_FOLDER (node)) {
108
 
                if (gtk_tree_view_row_expanded (tv, path))
109
 
                        gtk_tree_view_collapse_row (tv, path);
110
 
                else
111
 
                        gtk_tree_view_expand_row (tv, path, FALSE);
112
 
        }
113
 
 
114
 
}
115
 
 
116
 
static gboolean
117
 
ui_feedlist_key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer data)
118
 
{
119
 
        if ((event->type == GDK_KEY_PRESS) &&
120
 
            (event->state == 0) &&
121
 
            (event->keyval == GDK_Delete)) {
122
 
                nodePtr node = feedlist_get_selected ();
123
 
                                
124
 
                if(node) {
125
 
                        if (event->state & GDK_SHIFT_MASK)
126
 
                                feedlist_remove_node (node);
127
 
                        else
128
 
                                ui_feedlist_delete_prompt (node);
129
 
                        return TRUE;
130
 
                }
131
 
        }
132
 
        return FALSE;
133
 
}
134
 
 
135
 
static gboolean
136
 
ui_feedlist_filter_visible_function (GtkTreeModel *model, GtkTreeIter *iter, gpointer data)
137
 
{
138
 
        gint count;
139
 
        nodePtr np;
140
 
 
141
 
        if (!feedlist_reduced_unread)
142
 
                return TRUE;
143
 
 
144
 
        gtk_tree_model_get (model, iter, FS_PTR, &np, FS_UNREAD, &count, -1);
145
 
 
146
 
        if (np && (IS_FOLDER (np) || IS_NODE_SOURCE (np))) 
147
 
                return FALSE;
148
 
 
149
 
        if (0 != count)
150
 
                return TRUE;
151
 
        else
152
 
                return FALSE;
153
 
}
154
 
 
155
 
static void
156
 
ui_feedlist_reduce_unread (gboolean reduced) {
157
 
        GtkTreeView             *treeview;
158
 
 
159
 
        treeview = GTK_TREE_VIEW (liferea_shell_lookup ("feedlist"));
160
 
 
161
 
        feedlist_reduced_unread = reduced;
162
 
        conf_set_bool_value (REDUCED_FEEDLIST, reduced);
163
 
 
164
 
        if (reduced) {
165
 
                gtk_tree_view_set_reorderable (GTK_TREE_VIEW(treeview), FALSE);
166
 
                gtk_tree_view_set_model (GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(filter));
167
 
                gtk_tree_model_filter_refilter( GTK_TREE_MODEL_FILTER (filter));
168
 
        }
169
 
        else {
170
 
                gtk_tree_view_set_reorderable (GTK_TREE_VIEW(treeview), TRUE);
171
 
                gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER (filter));
172
 
                gtk_tree_view_set_model (GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(feedstore));
173
 
        }
174
 
}
175
 
 
176
 
/* sets up the entry list store and connects it to the entry list
177
 
   view in the main window */
178
 
void
179
 
ui_feedlist_init (GtkTreeView *treeview)
180
 
{
181
 
        GtkCellRenderer         *textRenderer;
182
 
        GtkCellRenderer         *iconRenderer;  
183
 
        GtkTreeViewColumn       *column;
184
 
        GtkTreeSelection        *select;        
185
 
        
186
 
        debug_enter ("ui_feedlist_init");
187
 
 
188
 
        /* Set up store */
189
 
        feedstore = gtk_tree_store_new (FS_LEN,
190
 
                                        G_TYPE_STRING,
191
 
                                        GDK_TYPE_PIXBUF,
192
 
                                        G_TYPE_POINTER,
193
 
                                        G_TYPE_UINT);
194
 
 
195
 
        gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (feedstore));
196
 
 
197
 
        /* Prepare filter */
198
 
        filter = gtk_tree_model_filter_new (GTK_TREE_MODEL(feedstore), NULL);
199
 
        gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER(filter),
200
 
                                                ui_feedlist_filter_visible_function,
201
 
                                                NULL,
202
 
                                                NULL);
203
 
 
204
 
        g_signal_connect (G_OBJECT (feedstore), "row-changed", G_CALLBACK (ui_feedlist_row_changed_cb), NULL);
205
 
 
206
 
        /* we only render the state and title */
207
 
        iconRenderer = gtk_cell_renderer_pixbuf_new ();
208
 
        textRenderer = gtk_cell_renderer_text_new ();
209
 
 
210
 
        column = gtk_tree_view_column_new ();
211
 
        
212
 
        gtk_tree_view_column_pack_start (column, iconRenderer, FALSE);
213
 
        gtk_tree_view_column_pack_start (column, textRenderer, TRUE);
214
 
        
215
 
        gtk_tree_view_column_add_attribute (column, iconRenderer, "pixbuf", FS_ICON);
216
 
        gtk_tree_view_column_add_attribute (column, textRenderer, "markup", FS_LABEL);
217
 
        
218
 
        gtk_tree_view_column_set_resizable (column, TRUE);
219
 
        gtk_tree_view_append_column (treeview, column);
220
 
        
221
 
        g_object_set (textRenderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
222
 
 
223
 
        g_signal_connect (G_OBJECT (treeview), "row-activated", G_CALLBACK (ui_feedlist_row_activated_cb), NULL);
224
 
        g_signal_connect (G_OBJECT (treeview), "key-press-event", G_CALLBACK (ui_feedlist_key_press_cb), NULL);
225
 
 
226
 
        select = gtk_tree_view_get_selection (treeview);
227
 
        gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
228
 
        
229
 
        g_signal_connect (G_OBJECT (select), "changed",
230
 
                          G_CALLBACK (ui_feedlist_selection_changed_cb),
231
 
                          liferea_shell_lookup ("feedlist"));
232
 
                          
233
 
        ui_feedlist_reduce_unread (conf_get_bool_value (REDUCED_FEEDLIST));     /* before menu setup for reduced mode check box to be correct */
234
 
        
235
 
        ui_dnd_setup_feedlist (feedstore);
236
 
        liferea_shell_update_feed_menu (TRUE, FALSE, FALSE);
237
 
        liferea_shell_update_allitems_actions (FALSE, FALSE);
238
 
        
239
 
        debug_exit ("ui_feedlist_init");
240
 
}
241
 
 
242
 
static void
243
 
ui_feedlist_expand_parents (nodePtr parentNode)
244
 
{
245
 
        if (parentNode->parent)
246
 
                ui_feedlist_expand_parents (parentNode->parent);
247
 
                
248
 
        ui_node_set_expansion (parentNode, TRUE);
249
 
}
250
 
 
251
 
void
252
 
ui_feedlist_select (nodePtr node)
253
 
{
254
 
        GtkTreeView             *treeview;
255
 
        GtkTreeModel            *model;
256
 
        GtkWindow               *mainwindow;
257
 
        
258
 
        mainwindow = GTK_WINDOW (liferea_shell_get_window ());
259
 
        treeview = GTK_TREE_VIEW (liferea_shell_lookup ("feedlist"));
260
 
        model = gtk_tree_view_get_model (treeview);
261
 
        
262
 
        if (node && node != feedlist_get_root ()) {
263
 
                GtkTreePath *path;
264
 
 
265
 
                /* in filtered mode we need to convert the iterator */
266
 
                if (feedlist_reduced_unread) {
267
 
                        GtkTreeIter iter;
268
 
                        gtk_tree_model_filter_convert_child_iter_to_iter (GTK_TREE_MODEL_FILTER (filter), &iter, ui_node_to_iter (node->id));
269
 
                        path = gtk_tree_model_get_path (model, &iter);
270
 
                } else {
271
 
                        path = gtk_tree_model_get_path (model, ui_node_to_iter (node->id));
272
 
                }
273
 
                
274
 
                if (node->parent)
275
 
                        ui_feedlist_expand_parents (node->parent);
276
 
 
277
 
                gtk_tree_view_scroll_to_cell (treeview, path, NULL, FALSE, 0.0, 0.0);
278
 
                gtk_tree_view_set_cursor (treeview, path, NULL, FALSE);
279
 
                gtk_tree_path_free (path);
280
 
 
281
 
        } else {
282
 
                GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
283
 
                gtk_tree_selection_unselect_all (selection);
284
 
        }
285
 
}
286
 
 
287
 
/* delete feed callbacks */
288
 
 
289
 
static void
290
 
ui_feedlist_delete_response_cb (GtkDialog *dialog, gint response_id, gpointer user_data)
291
 
{       
292
 
        switch (response_id) {
293
 
                case GTK_RESPONSE_ACCEPT:
294
 
                        feedlist_remove_node ((nodePtr)user_data);
295
 
                        break;
296
 
        }
297
 
        gtk_widget_destroy (GTK_WIDGET (dialog));
298
 
}
299
 
 
300
 
void
301
 
ui_feedlist_delete_prompt (nodePtr node)
302
 
{
303
 
        GtkWidget       *dialog;
304
 
        GtkWindow       *mainwindow;
305
 
        gchar           *text;
306
 
        
307
 
        g_assert (node == feedlist_get_selected ());
308
 
 
309
 
        liferea_shell_set_status_bar ("%s \"%s\"", _("Deleting entry"), node_get_title (node));
310
 
        text = g_strdup_printf (IS_FOLDER (node)?_("Are you sure that you want to delete \"%s\" and its contents?"):_("Are you sure that you want to delete \"%s\"?"), node_get_title (node));
311
 
 
312
 
        mainwindow = GTK_WINDOW (liferea_shell_get_window ());
313
 
        dialog = gtk_message_dialog_new (mainwindow,
314
 
                                         GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
315
 
                                         GTK_MESSAGE_QUESTION,
316
 
                                         GTK_BUTTONS_NONE,
317
 
                                         "%s", text);
318
 
        gtk_dialog_add_buttons (GTK_DIALOG (dialog),
319
 
                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
320
 
                                GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT,
321
 
                                NULL);
322
 
        gtk_window_set_title (GTK_WINDOW (dialog), _("Deletion Confirmation"));
323
 
        gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
324
 
        gtk_window_set_transient_for (GTK_WINDOW (dialog), mainwindow);
325
 
 
326
 
        g_free (text);
327
 
        
328
 
        gtk_widget_show_all (dialog);
329
 
 
330
 
        g_signal_connect (G_OBJECT (dialog), "response",
331
 
                          G_CALLBACK (ui_feedlist_delete_response_cb), node);
332
 
}
333
 
 
334
 
void
335
 
on_menu_properties (GtkMenuItem *menuitem, gpointer user_data)
336
 
{
337
 
        nodePtr node = feedlist_get_selected ();
338
 
        
339
 
        NODE_TYPE (node)->request_properties (node);
340
 
}
341
 
 
342
 
void on_menu_delete(GtkWidget *widget, gpointer user_data)
343
 
{
344
 
        ui_feedlist_delete_prompt (feedlist_get_selected());
345
 
}
346
 
 
347
 
void
348
 
on_menu_update (void)
349
 
{
350
 
        if (!feedlist_get_selected ()) {
351
 
                ui_show_error_box (_("You have to select a feed entry"));
352
 
                return;
353
 
        }
354
 
 
355
 
        if (network_is_online ()) 
356
 
                node_update_subscription (feedlist_get_selected (), GUINT_TO_POINTER (FEED_REQ_PRIORITY_HIGH));
357
 
        else
358
 
                liferea_shell_set_status_bar (_("Liferea is in offline mode. No update possible."));
359
 
}
360
 
 
361
 
void
362
 
on_menu_update_all(void)
363
 
364
 
        if (network_is_online ()) 
365
 
                node_update_subscription (feedlist_get_root(), GUINT_TO_POINTER (FEED_REQ_PRIORITY_HIGH));
366
 
        else
367
 
                liferea_shell_set_status_bar (_("Liferea is in offline mode. No update possible."));
368
 
}
369
 
 
370
 
void
371
 
on_menu_allread (GtkWidget *widget, gpointer user_data)
372
 
{       
373
 
        feedlist_mark_all_read (feedlist_get_selected ());
374
 
}
375
 
 
376
 
void
377
 
on_menu_allfeedsread (GtkWidget *widget, gpointer user_data)
378
 
{
379
 
        feedlist_mark_all_read (feedlist_get_root ());
380
 
}
381
 
 
382
 
void
383
 
on_newbtn_clicked (GtkButton *button, gpointer user_data)
384
 
{       
385
 
        node_type_request_interactive_add (feed_get_node_type ());
386
 
}
387
 
 
388
 
void
389
 
on_menu_feed_new (GtkMenuItem *menuitem, gpointer user_data)
390
 
{
391
 
        node_type_request_interactive_add (feed_get_node_type ());
392
 
}
393
 
 
394
 
void
395
 
on_new_plugin_activate (GtkMenuItem *menuitem, gpointer user_data)
396
 
{
397
 
        node_type_request_interactive_add (node_source_get_node_type ());
398
 
}
399
 
 
400
 
void
401
 
on_new_newsbin_activate (GtkMenuItem *menuitem, gpointer user_data)
402
 
{
403
 
        node_type_request_interactive_add (newsbin_get_node_type ());
404
 
}
405
 
 
406
 
void
407
 
on_menu_folder_new (GtkMenuItem *menuitem, gpointer user_data)
408
 
{
409
 
        node_type_request_interactive_add (folder_get_node_type ());
410
 
}
411
 
 
412
 
void
413
 
on_feedlist_reduced_activate (GtkToggleAction *menuitem, gpointer user_data)
414
 
{
415
 
        ui_feedlist_reduce_unread (gtk_toggle_action_get_active (menuitem));
416
 
        ui_node_reload_feedlist ();
417
 
}