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

« back to all changes in this revision

Viewing changes to .pc/libindicate.patch/src/ui/liferea_shell.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_shell.c  UI layout handling
3
 
 *
4
 
 * Copyright (C) 2004-2006 Nathan J. Conrad <t98502@users.sourceforge.net>
5
 
 * Copyright (C) 2007-2008 Lars Lindner <lars.lindner@gmail.com>
6
 
 *
7
 
 * This program is free software; you can redistribute it and/or modify
8
 
 * it under the terms of the GNU General Public License as published by
9
 
 * the Free Software Foundation; either version 2 of the License, or
10
 
 * (at your option) any later version. 
11
 
 *
12
 
 * This program is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 * GNU General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU General Public License
18
 
 * along with this program; if not, write to the Free Software
19
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 
 */
21
 
 
22
 
#ifdef HAVE_CONFIG_H
23
 
#  include <config.h>
24
 
#endif
25
 
 
26
 
#include "ui/liferea_shell.h"
27
 
 
28
 
#include <gtk/gtk.h>
29
 
#include <gdk/gdk.h>
30
 
#include <gdk/gdkkeysyms.h>
31
 
#include <glade/glade.h>
32
 
#include <string.h>             /* strcmp() and strsep() */
33
 
 
34
 
#include "browser.h"
35
 
#include "common.h"
36
 
#include "conf.h"
37
 
#include "debug.h"
38
 
#include "export.h"
39
 
#include "feedlist.h"
40
 
#include "htmlview.h"
41
 
#include "itemlist.h"
42
 
#include "net.h"
43
 
#include "notification/notification.h"
44
 
#include "ui/browser_tabs.h"
45
 
#include "ui/itemview.h"
46
 
#include "ui/liferea_dialog.h"
47
 
#include "ui/ui_common.h"
48
 
#include "ui/ui_feedlist.h"
49
 
#include "ui/ui_itemlist.h"
50
 
#include "ui/ui_prefs.h"
51
 
#include "ui/ui_script.h"
52
 
#include "ui/ui_search.h"
53
 
#include "ui/search_dialog.h"
54
 
#include "ui/ui_session.h"
55
 
#include "ui/ui_tray.h"
56
 
#include "ui/ui_update.h"
57
 
 
58
 
/* all used icons (FIXME: evil) */
59
 
GdkPixbuf *icons[MAX_ICONS];
60
 
 
61
 
static void liferea_shell_class_init    (LifereaShellClass *klass);
62
 
static void liferea_shell_init          (LifereaShell *ls);
63
 
 
64
 
#define LIFEREA_SHELL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), LIFEREA_SHELL_TYPE, LifereaShellPrivate))
65
 
 
66
 
struct LifereaShellPrivate {
67
 
        GladeXML        *xml;
68
 
 
69
 
        GtkWindow       *window;                /**< Liferea main window */
70
 
        GtkWidget       *menubar;
71
 
        GtkWidget       *toolbar;
72
 
        GtkTreeView     *feedlistView;
73
 
        
74
 
        GtkStatusbar    *statusbar;             /**< main window status bar */
75
 
        gboolean        statusbarLocked;        /**< flag locking important message on status bar */
76
 
        guint           statusbarLockTimer;     /**< timer id for status bar lock reset timer */
77
 
 
78
 
        GtkWidget       *statusbar_feedsinfo;
79
 
        GtkActionGroup  *generalActions;
80
 
        GtkActionGroup  *addActions;            /**< all types of "New" options */
81
 
        GtkActionGroup  *feedActions;           /**< update and mark read */
82
 
        GtkActionGroup  *readWriteActions;      /**< node remove and properties, node itemset items remove */
83
 
        GtkActionGroup  *itemActions;           /**< item state toggline, single item remove */
84
 
        
85
 
        FeedList        *feedlist;
86
 
        ItemView        *itemview;
87
 
        BrowserTabs     *tabs;
88
 
};
89
 
 
90
 
static GObjectClass *parent_class = NULL;
91
 
static LifereaShell *shell = NULL;
92
 
 
93
 
GType
94
 
liferea_shell_get_type (void) 
95
 
{
96
 
        static GType type = 0;
97
 
 
98
 
        if (G_UNLIKELY (type == 0)) 
99
 
        {
100
 
                static const GTypeInfo our_info = 
101
 
                {
102
 
                        sizeof (LifereaShellClass),
103
 
                        NULL, /* base_init */
104
 
                        NULL, /* base_finalize */
105
 
                        (GClassInitFunc) liferea_shell_class_init,
106
 
                        NULL,
107
 
                        NULL, /* class_data */
108
 
                        sizeof (LifereaShell),
109
 
                        0, /* n_preallocs */
110
 
                        (GInstanceInitFunc) liferea_shell_init
111
 
                };
112
 
 
113
 
                type = g_type_register_static (G_TYPE_OBJECT,
114
 
                                               "LifereaShell",
115
 
                                               &our_info, 0);
116
 
        }
117
 
 
118
 
        return type;
119
 
}
120
 
 
121
 
static void
122
 
liferea_shell_finalize (GObject *object)
123
 
{
124
 
        LifereaShell *ls = LIFEREA_SHELL (object);
125
 
        
126
 
        g_object_unref (ls->priv->xml);
127
 
 
128
 
        G_OBJECT_CLASS (parent_class)->finalize (object);
129
 
}
130
 
 
131
 
static void
132
 
liferea_shell_class_init (LifereaShellClass *klass)
133
 
{
134
 
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
135
 
 
136
 
        parent_class = g_type_class_peek_parent (klass);
137
 
 
138
 
        object_class->finalize = liferea_shell_finalize;
139
 
 
140
 
        g_type_class_add_private (object_class, sizeof(LifereaShellPrivate));
141
 
}
142
 
 
143
 
GtkWidget *
144
 
liferea_shell_lookup (const gchar *name)
145
 
{
146
 
        g_return_val_if_fail (shell != NULL, NULL);
147
 
        g_return_val_if_fail (shell->priv != NULL, NULL);
148
 
 
149
 
        return glade_xml_get_widget (shell->priv->xml, name);
150
 
}
151
 
 
152
 
static void
153
 
liferea_shell_init (LifereaShell *ls)
154
 
{
155
 
        /* globally accessible singleton */
156
 
        g_assert (NULL == shell);
157
 
        shell = ls;
158
 
        
159
 
        shell->priv = LIFEREA_SHELL_GET_PRIVATE (ls);
160
 
        shell->priv->xml = glade_xml_new (PACKAGE_DATA_DIR G_DIR_SEPARATOR_S PACKAGE G_DIR_SEPARATOR_S "liferea.glade", "mainwindow", GETTEXT_PACKAGE);
161
 
        glade_xml_signal_autoconnect (shell->priv->xml);
162
 
}
163
 
 
164
 
/**
165
 
 * Restore the window position from the values saved into gconf. Note
166
 
 * that this does not display/present/show the mainwindow.
167
 
 */
168
 
static void
169
 
liferea_shell_restore_position (void)
170
 
{
171
 
        /* load window position */
172
 
        int x, y, w, h;
173
 
 
174
 
        x = conf_get_int_value (LAST_WINDOW_X);
175
 
        y = conf_get_int_value (LAST_WINDOW_Y);
176
 
 
177
 
        w = conf_get_int_value (LAST_WINDOW_WIDTH);
178
 
        h = conf_get_int_value (LAST_WINDOW_HEIGHT);
179
 
        
180
 
        debug4 (DEBUG_GUI, "Retrieved saved setting: size %dx%d position %d:%d", w, h, x, y);
181
 
        
182
 
        /* Restore position only if the width and height were saved */
183
 
        if (w != 0 && h != 0) {
184
 
        
185
 
                if (x >= gdk_screen_width ())
186
 
                        x = gdk_screen_width () - 100;
187
 
                else if (x + w < 0)
188
 
                        x  = 100;
189
 
 
190
 
                if (y >= gdk_screen_height ())
191
 
                        y = gdk_screen_height () - 100;
192
 
                else if (y + w < 0)
193
 
                        y  = 100;
194
 
                        
195
 
                debug4 (DEBUG_GUI, "Restoring to size %dx%d position %d:%d", w, h, x, y);
196
 
 
197
 
                gtk_window_move (GTK_WINDOW (shell->priv->window), x, y);
198
 
 
199
 
                /* load window size */
200
 
                gtk_window_resize (GTK_WINDOW (shell->priv->window), w, h);
201
 
        }
202
 
 
203
 
        if (conf_get_bool_value (LAST_WINDOW_MAXIMIZED))
204
 
                gtk_window_maximize (GTK_WINDOW (shell->priv->window));
205
 
        else
206
 
                gtk_window_unmaximize (GTK_WINDOW (shell->priv->window));
207
 
 
208
 
}
209
 
 
210
 
void
211
 
liferea_shell_save_position (void)
212
 
{
213
 
        GtkWidget       *pane;
214
 
        gint            x, y, w, h;
215
 
 
216
 
        /* save pane proportions */
217
 
        pane = liferea_shell_lookup ("leftpane");
218
 
        if (pane) {
219
 
                x = gtk_paned_get_position (GTK_PANED (pane));
220
 
                conf_set_int_value (LAST_VPANE_POS, x);
221
 
        }
222
 
 
223
 
        pane = liferea_shell_lookup ("normalViewPane");
224
 
        if (pane) {
225
 
                y = gtk_paned_get_position (GTK_PANED (pane));
226
 
                conf_set_int_value (LAST_HPANE_POS, y);
227
 
        }
228
 
 
229
 
        pane = liferea_shell_lookup ("wideViewPane");
230
 
        if (pane) {
231
 
                y = gtk_paned_get_position (GTK_PANED (pane));
232
 
                conf_set_int_value (LAST_WPANE_POS, y);
233
 
        }
234
 
        
235
 
        /* The following needs to be skipped when the window is not visible */
236
 
        if (!GTK_WIDGET_VISIBLE (shell->priv->window))
237
 
                return;
238
 
 
239
 
        if (conf_get_bool_value (LAST_WINDOW_MAXIMIZED))
240
 
                return;
241
 
 
242
 
        gtk_window_get_position (shell->priv->window, &x, &y);
243
 
        gtk_window_get_size (shell->priv->window, &w, &h);
244
 
 
245
 
        if (x+w<0 || y+h<0 ||
246
 
            x > gdk_screen_width () ||
247
 
            y > gdk_screen_height ())
248
 
                return;
249
 
 
250
 
        debug4 (DEBUG_GUI, "Saving window size and position: %dx%d %d:%d", w, h, x, y);
251
 
 
252
 
        /* save window position */
253
 
        conf_set_int_value (LAST_WINDOW_X, x);
254
 
        conf_set_int_value (LAST_WINDOW_Y, y);
255
 
 
256
 
        /* save window size */
257
 
        conf_set_int_value (LAST_WINDOW_WIDTH, w);
258
 
        conf_set_int_value (LAST_WINDOW_HEIGHT, h);
259
 
}
260
 
 
261
 
void
262
 
liferea_shell_set_toolbar_style (const gchar *toolbar_style)
263
 
{       
264
 
        if (!toolbar_style) /* default to icons */
265
 
                gtk_toolbar_set_style (GTK_TOOLBAR (shell->priv->toolbar), GTK_TOOLBAR_ICONS);
266
 
        else if (!strcmp (toolbar_style, "text"))
267
 
                gtk_toolbar_set_style (GTK_TOOLBAR (shell->priv->toolbar), GTK_TOOLBAR_TEXT);
268
 
        else if (!strcmp (toolbar_style, "both"))
269
 
                gtk_toolbar_set_style (GTK_TOOLBAR (shell->priv->toolbar), GTK_TOOLBAR_BOTH);
270
 
        else if (!strcmp (toolbar_style, "both_horiz") || !strcmp (toolbar_style, "both-horiz") )
271
 
                gtk_toolbar_set_style (GTK_TOOLBAR (shell->priv->toolbar), GTK_TOOLBAR_BOTH_HORIZ);
272
 
        else /* default to icons */
273
 
                gtk_toolbar_set_style (GTK_TOOLBAR (shell->priv->toolbar), GTK_TOOLBAR_ICONS);
274
 
}
275
 
 
276
 
void
277
 
liferea_shell_update_toolbar (void)
278
 
{
279
 
        if (conf_get_bool_value (DISABLE_TOOLBAR))
280
 
                gtk_widget_hide (shell->priv->toolbar);
281
 
        else
282
 
                gtk_widget_show (shell->priv->toolbar);
283
 
}
284
 
 
285
 
void
286
 
liferea_shell_update_update_menu (gboolean enabled)
287
 
{
288
 
        gtk_action_set_sensitive (gtk_action_group_get_action (shell->priv->feedActions, "UpdateSelected"),     enabled);
289
 
}
290
 
 
291
 
void
292
 
liferea_shell_update_feed_menu (gboolean add, gboolean enabled, gboolean readWrite)
293
 
{
294
 
        gtk_action_group_set_sensitive (shell->priv->addActions, add);
295
 
        gtk_action_group_set_sensitive (shell->priv->feedActions, enabled);
296
 
        gtk_action_group_set_sensitive (shell->priv->readWriteActions, readWrite);
297
 
}
298
 
 
299
 
void
300
 
liferea_shell_update_item_menu (gboolean enabled)
301
 
{
302
 
        gtk_action_group_set_sensitive (shell->priv->itemActions, enabled);
303
 
}
304
 
 
305
 
void
306
 
liferea_shell_update_allitems_actions (gboolean isNotEmpty, gboolean isRead)
307
 
{
308
 
        gtk_action_set_sensitive (gtk_action_group_get_action (shell->priv->generalActions, "RemoveAllItems"), isNotEmpty);
309
 
        gtk_action_set_sensitive (gtk_action_group_get_action (shell->priv->feedActions, "MarkFeedAsRead"), isRead);
310
 
}
311
 
 
312
 
void
313
 
liferea_shell_update_unread_stats (void)
314
 
{
315
 
        gint    new_items, unread_items;
316
 
        gchar   *msg, *tmp;
317
 
 
318
 
        if (!shell->priv)
319
 
                return;
320
 
 
321
 
        new_items = feedlist_get_new_item_count ();
322
 
        unread_items = feedlist_get_unread_item_count ();
323
 
 
324
 
        if (new_items != 0)
325
 
                msg = g_strdup_printf (ngettext (" (%d new)", " (%d new)", new_items), new_items);
326
 
        else
327
 
                msg = g_strdup ("");
328
 
 
329
 
        if (unread_items != 0)
330
 
                tmp = g_strdup_printf (ngettext ("%d unread%s", "%d unread%s", unread_items), unread_items, msg);
331
 
        else
332
 
                tmp = g_strdup ("");
333
 
 
334
 
        gtk_label_set_text (GTK_LABEL (shell->priv->statusbar_feedsinfo), tmp);
335
 
        g_free (tmp);
336
 
        g_free (msg);
337
 
}
338
 
 
339
 
/*
340
 
   Do to the unsuitable GtkStatusBar stack handling which doesn't
341
 
   allow to keep messages on top of the stack for some time without
342
 
   overwriting them with newly arriving messages we need some extra
343
 
   handling here.
344
 
   
345
 
   Liferea knows two types of status messages:
346
 
   
347
 
     -> low prio messages (e.g. updating status messages)
348
 
     -> high prio messages (caused by user interaction, e.g. link hovering)
349
 
   
350
 
   The ideas is to keep the high prio messages always visible no matter
351
 
   what low prio messages arrive. To solve this we define the status bar
352
 
   stack is always a stack of two messages at most. At the bottom of the
353
 
   stack is always the latest low prio message and on top of the stack
354
 
   is the latest high prio message (or none at all).
355
 
   
356
 
   To enforce this using GtkStatusBar we use a lock to avoid adding
357
 
   low prio messages on top of high priority ones. This lock is valid
358
 
   for at most 5s which should be enough to read the high priority
359
 
   message. Afterwards new low priority messages will overrule the
360
 
   out-dated high priority message.  
361
 
 */
362
 
 
363
 
static gboolean
364
 
liferea_shell_unlock_status_bar_cb (gpointer user_data)
365
 
{
366
 
        shell->priv->statusbarLocked = FALSE;
367
 
        
368
 
        return FALSE;
369
 
}
370
 
 
371
 
static gboolean
372
 
liferea_shell_set_status_bar_important_cb (gpointer user_data)
373
 
{
374
 
        gchar           *text = (gchar *)user_data;
375
 
        guint           id;
376
 
        GtkStatusbar    *statusbar;
377
 
        
378
 
        statusbar = GTK_STATUSBAR (shell->priv->statusbar);
379
 
        id = gtk_statusbar_get_context_id (statusbar, "important");
380
 
        gtk_statusbar_pop (statusbar, id);
381
 
        gtk_statusbar_push (statusbar, id, text);
382
 
        g_free(text);
383
 
 
384
 
        return FALSE;
385
 
}
386
 
 
387
 
static gboolean
388
 
liferea_shell_set_status_bar_default_cb (gpointer user_data)
389
 
{
390
 
        gchar           *text = (gchar *)user_data;
391
 
        guint           id;
392
 
        GtkStatusbar    *statusbar;
393
 
 
394
 
        statusbar = GTK_STATUSBAR (shell->priv->statusbar);
395
 
        id = gtk_statusbar_get_context_id (statusbar, "default");
396
 
        gtk_statusbar_pop (statusbar, id);
397
 
        gtk_statusbar_push (statusbar, id, text);
398
 
        g_free(text);
399
 
 
400
 
        return FALSE;
401
 
}
402
 
 
403
 
void
404
 
liferea_shell_set_status_bar (const char *format, ...)
405
 
{
406
 
        va_list         args;
407
 
        gchar           *text;
408
 
        
409
 
        if (shell->priv->statusbarLocked)
410
 
                return;
411
 
 
412
 
        g_return_if_fail (format != NULL);
413
 
 
414
 
        va_start (args, format);
415
 
        text = g_strdup_vprintf (format, args);
416
 
        va_end (args);
417
 
 
418
 
        g_idle_add ((GSourceFunc)liferea_shell_set_status_bar_default_cb, (gpointer)text);
419
 
}
420
 
 
421
 
void
422
 
liferea_shell_set_important_status_bar (const char *format, ...)
423
 
{
424
 
        va_list         args;
425
 
        gchar           *text;
426
 
        
427
 
        g_return_if_fail (format != NULL);
428
 
 
429
 
        va_start (args, format);
430
 
        text = g_strdup_vprintf (format, args);
431
 
        va_end (args);
432
 
 
433
 
        shell->priv->statusbarLocked = FALSE;
434
 
        if (shell->priv->statusbarLockTimer) {
435
 
                g_source_remove (shell->priv->statusbarLockTimer);
436
 
                shell->priv->statusbarLockTimer = 0;
437
 
        }
438
 
        
439
 
        /* URL hover messages are reset with an empty string, so 
440
 
           we must locking the status bar on empty strings! */
441
 
        if (!g_str_equal (text, "")) {
442
 
                /* Realize 5s locking for important messages... */
443
 
                shell->priv->statusbarLocked = TRUE;
444
 
                shell->priv->statusbarLockTimer = g_timeout_add_seconds (5, liferea_shell_unlock_status_bar_cb, NULL);
445
 
        }
446
 
        
447
 
        g_idle_add ((GSourceFunc)liferea_shell_set_status_bar_important_cb, (gpointer)text);
448
 
}
449
 
 
450
 
static void
451
 
liferea_shell_do_zoom (gboolean in)
452
 
{
453
 
        /* We must apply the zoom either to the item view
454
 
           or to an open tab, depending on the browser tabs
455
 
           GtkNotebook page that is active... */
456
 
        if (!browser_tabs_get_active_htmlview ())
457
 
                itemview_do_zoom (in);
458
 
        else
459
 
                browser_tabs_do_zoom (in);
460
 
}
461
 
 
462
 
static gboolean
463
 
on_key_press_event_null_cb (GtkWidget *widget, GdkEventKey *event, gpointer data)
464
 
{
465
 
        return FALSE;
466
 
}
467
 
 
468
 
static gboolean
469
 
on_notebook_scroll_event_null_cb (GtkWidget *widget, GdkEventScroll *event)
470
 
{
471
 
        GtkNotebook *notebook = GTK_NOTEBOOK (widget);
472
 
 
473
 
        GtkWidget* child;
474
 
        GtkWidget* originator;
475
 
 
476
 
        if (!notebook->cur_page)
477
 
                return FALSE;
478
 
 
479
 
        child = gtk_notebook_get_nth_page (notebook, gtk_notebook_get_current_page (notebook));
480
 
        originator = gtk_get_event_widget ((GdkEvent *)event);
481
 
 
482
 
        /* ignore scroll events from the content of the page */
483
 
        if (!originator || gtk_widget_is_ancestor (originator, child))
484
 
                return FALSE;
485
 
 
486
 
        return TRUE;
487
 
}
488
 
 
489
 
static gboolean
490
 
on_close (GtkWidget *widget, GdkEvent *event, gpointer user_data)
491
 
{
492
 
        if ((ui_tray_get_count() == 0) || (conf_get_bool_value (DONT_MINIMIZE_TO_TRAY))) {
493
 
                liferea_shutdown ();
494
 
                return TRUE;
495
 
        }
496
 
                
497
 
        liferea_shell_save_position ();
498
 
        gtk_widget_hide (GTK_WIDGET (shell->priv->window));
499
 
        
500
 
        return TRUE;
501
 
}
502
 
 
503
 
static gboolean
504
 
on_window_state_event (GtkWidget *widget, GdkEvent *event, gpointer user_data)
505
 
{
506
 
        if (event->type == GDK_WINDOW_STATE) {
507
 
                GdkWindowState changed = ((GdkEventWindowState*)event)->changed_mask, state = ((GdkEventWindowState*)event)->new_window_state;
508
 
 
509
 
                if (changed == GDK_WINDOW_STATE_MAXIMIZED && !(state & GDK_WINDOW_STATE_WITHDRAWN)) {
510
 
                        if (state & GDK_WINDOW_STATE_MAXIMIZED)
511
 
                                conf_set_bool_value (LAST_WINDOW_MAXIMIZED, TRUE);
512
 
                        else
513
 
                                conf_set_bool_value (LAST_WINDOW_MAXIMIZED, FALSE);
514
 
                }
515
 
                if (state & GDK_WINDOW_STATE_ICONIFIED)
516
 
                        session_set_cmd (NULL, MAINWINDOW_ICONIFIED);
517
 
                else if(state & GDK_WINDOW_STATE_WITHDRAWN)
518
 
                        session_set_cmd (NULL, MAINWINDOW_HIDDEN);
519
 
                else
520
 
                        session_set_cmd (NULL, MAINWINDOW_SHOWN);
521
 
        }
522
 
        return FALSE;
523
 
}
524
 
 
525
 
static gboolean
526
 
on_key_press_event (GtkWidget *widget, GdkEventKey *event, gpointer data)
527
 
{
528
 
        gboolean        modifier_matches = FALSE;
529
 
        guint           default_modifiers;
530
 
        const gchar     *type;
531
 
        GtkWidget       *focusw;
532
 
 
533
 
        if (event->type == GDK_KEY_PRESS) {
534
 
                default_modifiers = gtk_accelerator_get_default_mod_mask ();
535
 
 
536
 
                /* handle [<modifier>+]<Space> headline skimming hotkey */
537
 
                switch (event->keyval) {
538
 
                        case GDK_space:
539
 
                                switch (conf_get_int_value (BROWSE_KEY_SETTING)) {
540
 
                                        default:
541
 
                                        case 0:
542
 
                                                modifier_matches = ((event->state & default_modifiers) == 0);
543
 
                                                /* Hack to make space handled in the module. This is necessary
544
 
                                                   because the HTML widget code must be able to catch spaces
545
 
                                                   for input fields.
546
 
                                                   
547
 
                                                   By ignoring the space here it will be passed to the HTML
548
 
                                                   widget which in turn will pass it back if it is not eaten by
549
 
                                                   any input field currently focussed. */
550
 
                                                return FALSE;
551
 
                                        case 1:
552
 
                                                modifier_matches = ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK);
553
 
                                                break;
554
 
                                        case 2:
555
 
                                                modifier_matches = ((event->state & GDK_MOD1_MASK) == GDK_MOD1_MASK);
556
 
                                                break;
557
 
                                }
558
 
                                
559
 
                                if (modifier_matches) {
560
 
                                        itemview_scroll ();
561
 
                                        return TRUE;
562
 
                                }
563
 
                                break;
564
 
                }
565
 
                
566
 
                /* some <Ctrl> hotkeys that overrule the HTML view */
567
 
                if ((event->state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK) {
568
 
                        switch (event->keyval) {
569
 
                                case GDK_KP_Add:
570
 
                                case GDK_equal:
571
 
                                case GDK_plus:
572
 
                                        liferea_shell_do_zoom (TRUE);
573
 
                                        return TRUE;
574
 
                                        break;
575
 
                                case GDK_KP_Subtract:
576
 
                                case GDK_minus:
577
 
                                        liferea_shell_do_zoom (FALSE);
578
 
                                        return TRUE;
579
 
                                        break;
580
 
                        }
581
 
                }
582
 
 
583
 
                /* prevent usage of navigation keys in entries */
584
 
                focusw = gtk_window_get_focus (GTK_WINDOW (widget));
585
 
                if (!focusw || GTK_IS_ENTRY (focusw))
586
 
                        return FALSE;
587
 
 
588
 
                /* prevent usage of navigation keys in HTML view */
589
 
                type = g_type_name (GTK_WIDGET_TYPE (focusw));
590
 
                if (type && (!strcmp (type, "WebKitWebView")))
591
 
                        return FALSE;
592
 
                
593
 
                /* check for treeview navigation */
594
 
                if (0 == (event->state & default_modifiers)) {
595
 
                        switch (event->keyval) {
596
 
                                case GDK_KP_Delete:
597
 
 
598
 
                                case GDK_Delete:
599
 
                                        if (focusw == GTK_WIDGET (shell->priv->feedlistView))
600
 
                                                return FALSE;   /* to be handled in ui_feedlist_key_press_cb() */
601
 
                                                
602
 
                                        on_remove_item_activate (NULL, NULL);
603
 
                                        return TRUE;
604
 
                                        break;
605
 
                                case GDK_n: 
606
 
                                        on_next_unread_item_activate (NULL, NULL);
607
 
                                        return TRUE;
608
 
                                        break;
609
 
                                case GDK_f:
610
 
                                        itemview_move_cursor (1);
611
 
                                        return TRUE;
612
 
                                        break;
613
 
                                case GDK_b:
614
 
                                        itemview_move_cursor (-1);
615
 
                                        return TRUE;
616
 
                                        break;
617
 
                                case GDK_u:
618
 
                                        ui_common_treeview_move_cursor (shell->priv->feedlistView, -1);
619
 
                                        itemview_move_cursor_to_first ();
620
 
                                        return TRUE;
621
 
                                        break;
622
 
                                case GDK_d:
623
 
                                        ui_common_treeview_move_cursor (shell->priv->feedlistView, 1);
624
 
                                        itemview_move_cursor_to_first ();
625
 
                                        return TRUE;
626
 
                                        break;
627
 
                        }
628
 
                }
629
 
        }
630
 
        
631
 
        return FALSE;
632
 
}
633
 
 
634
 
static gboolean
635
 
liferea_shell_save_accels (gpointer data)
636
 
{
637
 
        gchar *accels_file = NULL;
638
 
 
639
 
        accels_file = g_build_filename (common_get_cache_path (), "accels", NULL);
640
 
        gtk_accel_map_save (accels_file);
641
 
        g_free (accels_file);
642
 
        return FALSE;
643
 
}
644
 
 
645
 
static void
646
 
on_accel_change (GtkAccelMap *object, gchar *accel_path,
647
 
                guint accel_key, GdkModifierType accel_mode,
648
 
                gpointer user_data)
649
 
{
650
 
        g_idle_add (liferea_shell_save_accels, NULL);
651
 
}
652
 
 
653
 
static void
654
 
on_searchbtn_clicked (GtkButton *button, gpointer user_data)
655
 
{
656
 
        simple_search_dialog_open ();
657
 
}
658
 
 
659
 
void
660
 
on_onlinebtn_clicked (GtkButton *button, gpointer user_data)
661
 
{
662
 
        network_set_online (!network_is_online ());
663
 
}
664
 
 
665
 
static void
666
 
on_work_offline_activate (GtkToggleAction *menuitem, gpointer user_data)
667
 
{
668
 
        network_set_online (!gtk_toggle_action_get_active (menuitem));
669
 
}
670
 
 
671
 
static void
672
 
on_about_activate (GtkMenuItem *menuitem, gpointer user_data)
673
 
{
674
 
        GtkWidget *dialog;
675
 
 
676
 
        dialog = liferea_dialog_new (NULL, "aboutdialog");
677
 
        gtk_about_dialog_set_version (GTK_ABOUT_DIALOG (dialog), VERSION);
678
 
        g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_hide), NULL);
679
 
        gtk_widget_show (dialog);
680
 
}
681
 
 
682
 
static void
683
 
on_topics_activate (GtkMenuItem *menuitem, gpointer user_data)
684
 
{
685
 
        gchar *filename = g_strdup_printf ("file://" PACKAGE_DATA_DIR "/" PACKAGE "/doc/html/%s", _("topics_en.html"));
686
 
        browser_tabs_add_new (filename, _("Help Topics"), TRUE);
687
 
        g_free (filename);
688
 
}
689
 
 
690
 
static void
691
 
on_quick_reference_activate (GtkMenuItem *menuitem, gpointer user_data)
692
 
{
693
 
        gchar *filename = g_strdup_printf ("file://" PACKAGE_DATA_DIR "/" PACKAGE "/doc/html/%s", _("reference_en.html"));
694
 
        browser_tabs_add_new (filename, _("Quick Reference"), TRUE);
695
 
        g_free (filename);
696
 
}
697
 
 
698
 
static void
699
 
on_faq_activate (GtkMenuItem *menuitem, gpointer user_data)
700
 
{
701
 
        gchar *filename = g_strdup_printf ("file://" PACKAGE_DATA_DIR "/" PACKAGE "/doc/html/%s", _("faq_en.html"));
702
 
        browser_tabs_add_new (filename, _("FAQ"), TRUE);
703
 
        g_free (filename);
704
 
}
705
 
 
706
 
static void
707
 
on_menu_quit (GtkMenuItem *menuitem, gpointer user_data)
708
 
{
709
 
        liferea_shutdown ();
710
 
}
711
 
 
712
 
static void
713
 
on_menu_zoomin_selected (gpointer callback_data, guint callback_action, GtkWidget *widget)
714
 
{
715
 
        liferea_shell_do_zoom (TRUE);
716
 
}
717
 
 
718
 
static void
719
 
on_menu_zoomout_selected (gpointer callback_data, guint callback_action, GtkWidget *widget)
720
 
{
721
 
        liferea_shell_do_zoom (FALSE);
722
 
}
723
 
 
724
 
static void
725
 
on_menu_import (gpointer callback_data, guint callback_action, GtkWidget *widget)
726
 
{
727
 
        import_OPML_file ();
728
 
}
729
 
 
730
 
static void
731
 
on_menu_export (gpointer callback_data, guint callback_action, GtkWidget *widget)
732
 
{
733
 
        export_OPML_file ();
734
 
}
735
 
 
736
 
// FIXME: change to signal callback
737
 
void
738
 
liferea_shell_online_status_changed (int online)
739
 
{
740
 
        GtkWidget       *widget;
741
 
 
742
 
        if (!shell)
743
 
                return; // FIXME: this check shouldn't be necessary
744
 
 
745
 
        widget = liferea_shell_lookup ("onlineimage");
746
 
 
747
 
        if (online) {
748
 
                liferea_shell_set_status_bar (_("Liferea is now online"));
749
 
                gtk_image_set_from_pixbuf (GTK_IMAGE (widget), icons[ICON_ONLINE]);
750
 
                atk_object_set_name (gtk_widget_get_accessible (widget), _("Work Offline"));            
751
 
        } else {
752
 
                liferea_shell_set_status_bar (_("Liferea is now offline"));
753
 
                gtk_image_set_from_pixbuf (GTK_IMAGE (widget), icons[ICON_OFFLINE]);
754
 
                atk_object_set_name (gtk_widget_get_accessible (widget), _("Work Online"));     
755
 
        }
756
 
        gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (gtk_action_group_get_action (shell->priv->generalActions, "ToggleOfflineMode")), !online);
757
 
 
758
 
        /* Propagate new online status to other interested widgets */
759
 
        // FIXME: bad design, HTML view implementation needs to register for network events itself
760
 
        liferea_htmlview_set_online (online);
761
 
        ui_tray_update ();
762
 
}
763
 
 
764
 
/* methods to receive URLs which were dropped anywhere in the main window */
765
 
static void
766
 
liferea_shell_URL_received (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint info, guint time)
767
 
{
768
 
        gchar           *tmp1, *tmp2, *freeme;
769
 
        GtkWidget       *mainwindow;
770
 
        GtkAllocation   alloc;
771
 
        GtkTreeView     *treeview;
772
 
        GtkTreeModel    *model;
773
 
        GtkTreePath     *path;
774
 
        GtkTreeIter     iter;
775
 
        nodePtr         node;
776
 
        gint            tx, ty;
777
 
        
778
 
        g_return_if_fail (data->data != NULL);
779
 
                
780
 
        mainwindow = GTK_WIDGET (liferea_shell_lookup ("mainwindow"));
781
 
        treeview = GTK_TREE_VIEW (liferea_shell_lookup ("feedlist"));
782
 
        model = gtk_tree_view_get_model (treeview);
783
 
 
784
 
        /* Allow link drops only over feed list widget. This is to avoid
785
 
           the frequent accidental text drops in the HTML view. */
786
 
 
787
 
        gtk_widget_get_allocation(GTK_WIDGET(treeview), &alloc);
788
 
 
789
 
        if((x > alloc.x+alloc.width) || (x < alloc.x) ||
790
 
           (y > alloc.y+alloc.height) || (y < alloc.y)) {
791
 
                gtk_drag_finish (context, FALSE, FALSE, time);
792
 
                return;
793
 
        }               
794
 
 
795
 
        /* x and y are relative to the main window, make them relative to the treeview */
796
 
        g_assert (gtk_widget_translate_coordinates (mainwindow, GTK_WIDGET (treeview), x, y, &tx, &ty));
797
 
 
798
 
        if ((data->length >= 0) && (data->format == 8)) {
799
 
                /* extra handling to accept multiple drops */   
800
 
                freeme = tmp1 = g_strdup (data->data);
801
 
                while ((tmp2 = strsep (&tmp1, "\n\r"))) {
802
 
                        if (strlen (tmp2)) {
803
 
                                /* if the drop is over a node, select it so that feedlist_add_subscription()
804
 
                                 * adds it in the correct folder */
805
 
                                if (gtk_tree_view_get_dest_row_at_pos (treeview, tx, ty, &path, NULL)) {
806
 
                                        if (gtk_tree_model_get_iter (model, &iter, path)) {
807
 
                                                gtk_tree_model_get (model, &iter, FS_PTR, &node, -1);
808
 
                                                /* if node is NULL, ui_feedlist_select() will unselect the tv */
809
 
                                                ui_feedlist_select (node);
810
 
                                        }
811
 
                                        gtk_tree_path_free (path);
812
 
                                }
813
 
                                feedlist_add_subscription (g_strdup (tmp2), NULL, NULL,
814
 
                                                           FEED_REQ_RESET_TITLE |
815
 
                                                           FEED_REQ_PRIORITY_HIGH);
816
 
                        }
817
 
                }
818
 
                g_free (freeme);
819
 
                gtk_drag_finish (context, TRUE, FALSE, time);           
820
 
        } else {
821
 
                gtk_drag_finish (context, FALSE, FALSE, time);
822
 
        }
823
 
}
824
 
 
825
 
void
826
 
liferea_shell_setup_URL_receiver (GtkWidget *widget)
827
 
{
828
 
        GtkTargetEntry target_table[] = {
829
 
                { "STRING",                     0, 0 },
830
 
                { "text/plain",                 0, 0 },
831
 
                { "text/uri-list",              0, 1 },
832
 
                { "_NETSCAPE_URL",              0, 1 },
833
 
                { "application/x-rootwin-drop", 0, 2 }
834
 
        };
835
 
 
836
 
        /* doesn't work with GTK_DEST_DEFAULT_DROP... */
837
 
        gtk_drag_dest_set (widget, GTK_DEST_DEFAULT_ALL,
838
 
                           target_table, sizeof (target_table)/sizeof (target_table[0]),
839
 
                           GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK);
840
 
                       
841
 
        g_signal_connect (G_OBJECT (widget), "drag_data_received",
842
 
                          G_CALLBACK (liferea_shell_URL_received), NULL);
843
 
}
844
 
 
845
 
static const GtkActionEntry ui_mainwindow_action_entries[] = {
846
 
        {"SubscriptionsMenu", NULL, N_("_Subscriptions")},
847
 
        {"UpdateAll", "gtk-refresh", N_("Update _All"), "<control>U", N_("Updates all subscriptions."),
848
 
         G_CALLBACK(on_menu_update_all)},
849
 
        {"MarkAllFeedsAsRead", "gtk-apply", N_("Mark All As _Read"), NULL, N_("Marks read every item of every subscription."),
850
 
         G_CALLBACK(on_menu_allfeedsread)},
851
 
        {"ImportFeedList", "gtk-open", N_("_Import Feed List..."), NULL, N_("Imports an OPML feed list."), G_CALLBACK(on_menu_import)},
852
 
        {"ExportFeedList", "gtk-save-as", N_("_Export Feed List..."), NULL, N_("Exports the feed list as OPML."), G_CALLBACK(on_menu_export)},
853
 
        {"Quit",GTK_STOCK_QUIT, N_("_Quit"), "<control>Q", NULL, G_CALLBACK(on_menu_quit)},
854
 
 
855
 
        {"FeedMenu", NULL, N_("_Feed")},
856
 
        {"RemoveAllItems", "gtk-delete", N_("Remove _All Items"), NULL, N_("Removes all items of the currently selected feed."),
857
 
         G_CALLBACK(on_remove_items_activate)},
858
 
 
859
 
        {"ItemMenu", NULL, N_("_Item")},
860
 
        {"NextUnreadItem", GTK_STOCK_GO_FORWARD, N_("_Next Unread Item"), "<control>N", N_("Jumps to the next unread item. If necessary selects the next feed with unread items."),
861
 
         G_CALLBACK(on_next_unread_item_activate)},
862
 
 
863
 
        {"ViewMenu", NULL, N_("_View")},
864
 
        {"ZoomIn", "gtk-zoom-in", N_("_Increase Text Size"), "<control>plus", N_("Increases the text size of the item view."),
865
 
         G_CALLBACK(on_menu_zoomin_selected)},
866
 
        {"ZoomOut", "gtk-zoom-out", N_("_Decrease Text Size"), "<control>minus", N_("Decreases the text size of the item view."),
867
 
         G_CALLBACK(on_menu_zoomout_selected)},
868
 
 
869
 
        {"ToolsMenu", NULL, N_("_Tools")},
870
 
        {"ShowUpdateMonitor", NULL, N_("_Update Monitor"), NULL, N_("Show a list of all feeds currently in the update queue"),
871
 
         G_CALLBACK(on_menu_show_update_monitor)},
872
 
        {"ShowScriptManager", NULL, N_("_Script Manager"), NULL, N_("Allows to configure and edit LUA hook scripts"),
873
 
         G_CALLBACK(on_menu_show_script_manager)},
874
 
        {"ShowPreferences", GTK_STOCK_PREFERENCES, N_("_Preferences"), NULL, N_("Edit Preferences."),
875
 
         G_CALLBACK(on_prefbtn_clicked)},
876
 
 
877
 
        {"SearchMenu", NULL, N_("S_earch")},
878
 
        {"SearchFeeds", "gtk-find", N_("Search All Feeds..."), "<control>F", N_("Show the search dialog."), G_CALLBACK(on_searchbtn_clicked)},
879
 
        {"CreateEngineSearch", NULL, N_("Search With ...")},
880
 
 
881
 
        {"HelpMenu", NULL, N_("_Help")},
882
 
        {"ShowHelpContents", "gtk-help", N_("_Contents"), "F1", N_("View help for this application."), G_CALLBACK(on_topics_activate)},
883
 
        {"ShowHelpQuickReference", NULL, N_("_Quick Reference"), NULL, N_("View a list of all Liferea shortcuts."),
884
 
         G_CALLBACK(on_quick_reference_activate)},
885
 
        {"ShowHelpFAQ", NULL, N_("_FAQ"), NULL, N_("View the FAQ for this application."), G_CALLBACK(on_faq_activate)},
886
 
        {"ShowAbout", "gtk-about", N_("_About"), NULL, N_("Shows an about dialog."), G_CALLBACK(on_about_activate)}
887
 
};
888
 
 
889
 
static const GtkRadioActionEntry ui_mainwindow_view_radio_entries[] = {
890
 
        {"NormalView", NULL, N_("_Normal View"), NULL, N_("Set view mode to mail client mode."),
891
 
         0},
892
 
        {"WideView", NULL, N_("_Wide View"), NULL, N_("Set view mode to use three vertical panes."),
893
 
         1},
894
 
        {"CombinedView", NULL, N_("_Combined View"), NULL, N_("Set view mode to two pane mode."),
895
 
         2}
896
 
};
897
 
 
898
 
static GtkToggleActionEntry ui_mainwindow_feedlist_toggle_entries[] = {
899
 
        {"ReducedFeedList", NULL, N_("_Reduced Feed List"), NULL, N_("Hide feeds with no unread items."),
900
 
        G_CALLBACK(on_feedlist_reduced_activate)}
901
 
};
902
 
 
903
 
static const GtkActionEntry ui_mainwindow_add_action_entries[] = {
904
 
        {"NewSubscription", "gtk-add", N_("_New Subscription..."), NULL, N_("Adds a subscription to the feed list."),
905
 
         G_CALLBACK(on_menu_feed_new)},
906
 
        {"NewFolder", NULL, N_("New _Folder..."), NULL, N_("Adds a folder to the feed list."), G_CALLBACK(on_menu_folder_new)},
907
 
        {"NewVFolder", NULL, N_("New S_earch Folder..."), NULL, N_("Adds a new search folder to the feed list."), G_CALLBACK(on_new_vfolder_activate)},
908
 
        {"NewSource", NULL, N_("New _Source..."), NULL, N_("Adds a new feed list source."), G_CALLBACK(on_new_plugin_activate)},
909
 
        {"NewNewsBin", NULL, N_("New _News Bin..."), NULL, N_("Adds a new news bin."), G_CALLBACK(on_new_newsbin_activate)}
910
 
};
911
 
 
912
 
static const GtkActionEntry ui_mainwindow_feed_action_entries[] = {
913
 
        {"MarkFeedAsRead", "gtk-apply", N_("_Mark Items Read"), "<control>R", N_("Marks all items of the selected feed list node / in the item list as read."), 
914
 
         G_CALLBACK(on_menu_allread)},
915
 
        {"UpdateSelected", "gtk-refresh", N_("_Update"), NULL, N_("Updates the selected subscription or all subscriptions of the selected folder."),
916
 
         G_CALLBACK(on_menu_update)}
917
 
};
918
 
 
919
 
static const GtkActionEntry ui_mainwindow_read_write_action_entries[] = {
920
 
        {"Properties", "gtk-properties", N_("_Properties"), NULL, N_("Opens the property dialog for the selected subscription."), G_CALLBACK(on_menu_properties)},
921
 
        {"DeleteSelected", "gtk-delete", N_("_Remove"), NULL, N_("Removes the selected subscription."), G_CALLBACK(on_menu_delete)}
922
 
};
923
 
 
924
 
static const GtkActionEntry ui_mainwindow_item_action_entries[] = {
925
 
        {"ToggleItemReadStatus", "gtk-apply", N_("Toggle _Read Status"), "<control>M", N_("Toggles the read status of the selected item."),
926
 
         G_CALLBACK(on_toggle_unread_status)},
927
 
        {"ToggleItemFlag", NULL, N_("Toggle Item _Flag"), "<control>T", N_("Toggles the flag status of the selected item."),
928
 
         G_CALLBACK(on_toggle_item_flag)},
929
 
        {"RemoveSelectedItem", "gtk-delete", N_("R_emove"), NULL, N_("Removes the selected item."),
930
 
         G_CALLBACK(on_remove_item_activate)},
931
 
        {"LaunchItemInBrowser", NULL, N_("_Launch In Browser"), NULL, N_("Launches the item's link in the configured browser."),
932
 
         G_CALLBACK(on_popup_launchitem_selected)}
933
 
};
934
 
 
935
 
static const GtkToggleActionEntry ui_mainwindow_action_toggle_entries[] = {
936
 
        {"ToggleOfflineMode", NULL, N_("_Work Offline"), NULL, N_("This option allows you to disable subscription updating."),
937
 
         G_CALLBACK(on_work_offline_activate)}
938
 
};
939
 
 
940
 
static const char *ui_mainwindow_ui_desc =
941
 
"<ui>"
942
 
"  <menubar name='MainwindowMenubar'>"
943
 
"    <menu action='SubscriptionsMenu'>"
944
 
"      <menuitem action='UpdateAll'/>"
945
 
"      <menuitem action='MarkAllFeedsAsRead'/>"
946
 
"      <separator/>"
947
 
"      <menuitem action='NewSubscription'/>"
948
 
"      <menuitem action='NewFolder'/>"
949
 
"      <menuitem action='NewVFolder'/>"
950
 
"      <menuitem action='NewSource'/>"
951
 
"      <menuitem action='NewNewsBin'/>"
952
 
"      <separator/>"
953
 
"      <menuitem action='ImportFeedList'/>"
954
 
"      <menuitem action='ExportFeedList'/>"
955
 
"      <separator/>"
956
 
"      <menuitem action='ToggleOfflineMode'/>"
957
 
"      <separator/>"
958
 
"      <menuitem action='Quit'/>"
959
 
"    </menu>"
960
 
"    <menu action='FeedMenu'>"
961
 
"      <menuitem action='UpdateSelected'/>"
962
 
"      <menuitem action='MarkFeedAsRead'/>"
963
 
"      <separator/>"
964
 
"      <menuitem action='RemoveAllItems'/>"
965
 
"      <menuitem action='DeleteSelected'/>"
966
 
"      <separator/>"
967
 
"      <menuitem action='Properties'/>"
968
 
"    </menu>"
969
 
"    <menu action='ItemMenu'>"
970
 
"      <menuitem action='NextUnreadItem'/>"
971
 
"      <separator/>"
972
 
"      <menuitem action='ToggleItemReadStatus'/>"
973
 
"      <menuitem action='ToggleItemFlag'/>"
974
 
"      <menuitem action='RemoveSelectedItem'/>"
975
 
"      <separator/>"
976
 
"      <menuitem action='LaunchItemInBrowser'/>"
977
 
"    </menu>"
978
 
"    <menu action='ViewMenu'>"
979
 
"      <menuitem action='ZoomIn'/>"
980
 
"      <menuitem action='ZoomOut'/>"
981
 
"      <separator/>"
982
 
"      <menuitem action='NormalView'/>"
983
 
"      <menuitem action='WideView'/>"
984
 
"      <menuitem action='CombinedView'/>"
985
 
"      <separator/>"
986
 
"      <menuitem action='ReducedFeedList'/>"
987
 
"    </menu>"
988
 
"    <menu action='ToolsMenu'>"
989
 
"      <menuitem action='ShowUpdateMonitor'/>"
990
 
"      <menuitem action='ShowScriptManager'/>"
991
 
"      <menuitem action='ShowPreferences'/>"
992
 
"    </menu>"
993
 
"    <menu action='SearchMenu'>"
994
 
"      <menuitem action='SearchFeeds'/>"
995
 
"      <menu action='CreateEngineSearch'/>"
996
 
"    </menu>"
997
 
"    <menu action='HelpMenu'>"
998
 
"      <menuitem action='ShowHelpContents'/>"
999
 
"      <menuitem action='ShowHelpQuickReference'/>"
1000
 
"      <menuitem action='ShowHelpFAQ'/>"
1001
 
"      <separator/>"
1002
 
"      <menuitem action='ShowAbout'/>"
1003
 
"    </menu>"
1004
 
"  </menubar>"
1005
 
"  <toolbar action='maintoolbar'>"
1006
 
"    <separator/>"
1007
 
"    <toolitem name='newFeedButton' action='NewSubscription'/>"
1008
 
"    <toolitem name='nextUnreadButton' action='NextUnreadItem'/>"
1009
 
"    <toolitem name='MarkAsReadButton' action='MarkFeedAsRead'/>"
1010
 
"    <toolitem name='UpdateAllButton' action='UpdateAll'/>"
1011
 
"    <toolitem name='SearchButton' action='SearchFeeds'/>"
1012
 
"    <separator/>"
1013
 
"  </toolbar>"
1014
 
"</ui>";
1015
 
 
1016
 
static GdkPixbuf *
1017
 
liferea_shell_get_theme_icon (GtkIconTheme *icon_theme, const gchar *name, gint size)
1018
 
{
1019
 
        GError *error = NULL;
1020
 
        GdkPixbuf *pixbuf;
1021
 
 
1022
 
        pixbuf = gtk_icon_theme_load_icon (icon_theme,
1023
 
                                           name, /* icon name */
1024
 
                                           size, /* size */
1025
 
                                           0,  /* flags */
1026
 
                                           &error);
1027
 
        if (!pixbuf) {
1028
 
                debug1(DEBUG_GUI, "Couldn't load icon: %s", error->message);
1029
 
                g_error_free (error);
1030
 
        }
1031
 
        return pixbuf;
1032
 
}
1033
 
 
1034
 
static void
1035
 
liferea_shell_restore_state (void)
1036
 
{
1037
 
        gchar *toolbar_style, *accels_file;
1038
 
        
1039
 
        debug0 (DEBUG_GUI, "Setting toolbar style");
1040
 
        
1041
 
        toolbar_style = conf_get_toolbar_style ();      
1042
 
        liferea_shell_set_toolbar_style (toolbar_style);
1043
 
        g_free (toolbar_style);
1044
 
 
1045
 
        debug0 (DEBUG_GUI, "Loading accelerators");
1046
 
        
1047
 
        accels_file = g_build_filename (common_get_cache_path(), "accels", NULL);
1048
 
        gtk_accel_map_load (accels_file);
1049
 
        g_free (accels_file);   
1050
 
 
1051
 
        debug0 (DEBUG_GUI, "Restoring window position");
1052
 
        
1053
 
        liferea_shell_restore_position ();
1054
 
 
1055
 
        debug0 (DEBUG_GUI, "Loading pane proportions");
1056
 
                
1057
 
        if (0 != conf_get_int_value (LAST_VPANE_POS))
1058
 
                gtk_paned_set_position (GTK_PANED (liferea_shell_lookup ("leftpane")), conf_get_int_value (LAST_VPANE_POS));
1059
 
        if (0 != conf_get_int_value (LAST_HPANE_POS))
1060
 
                gtk_paned_set_position (GTK_PANED (liferea_shell_lookup ("normalViewPane")), conf_get_int_value (LAST_HPANE_POS));
1061
 
        if (0 != conf_get_int_value (LAST_WPANE_POS))
1062
 
                gtk_paned_set_position (GTK_PANED (liferea_shell_lookup ("wideViewPane")), conf_get_int_value (LAST_WPANE_POS));
1063
 
}
1064
 
 
1065
 
void
1066
 
liferea_shell_create (int initialState)
1067
 
{
1068
 
        GtkUIManager    *ui_manager;
1069
 
        GtkAccelGroup   *accel_group;
1070
 
        GError          *error = NULL;  
1071
 
        GtkWidget       *widget;
1072
 
        int             i;
1073
 
        GString         *buffer;
1074
 
        GtkIconTheme    *icon_theme;
1075
 
        
1076
 
        debug_enter ("liferea_shell_create");
1077
 
 
1078
 
        /* 1.) object setup */
1079
 
 
1080
 
        g_object_new (LIFEREA_SHELL_TYPE, NULL);
1081
 
 
1082
 
        shell->priv->window = GTK_WINDOW (liferea_shell_lookup ("mainwindow"));
1083
 
 
1084
 
        // FIXME: do we use this anywhere?
1085
 
        gtk_widget_set_name (liferea_shell_lookup ("feedlist"), "feedlist");
1086
 
        
1087
 
        /* 2.) menu creation */
1088
 
        
1089
 
        debug0 (DEBUG_GUI, "Setting up menues");
1090
 
 
1091
 
        /* Prepare some toggle button states */ 
1092
 
        ui_mainwindow_feedlist_toggle_entries[0].is_active = conf_get_bool_value (REDUCED_FEEDLIST);
1093
 
 
1094
 
        ui_manager = gtk_ui_manager_new ();
1095
 
 
1096
 
        shell->priv->generalActions = gtk_action_group_new ("GeneralActions");
1097
 
        gtk_action_group_set_translation_domain (shell->priv->generalActions, PACKAGE);
1098
 
        gtk_action_group_add_actions (shell->priv->generalActions, ui_mainwindow_action_entries, G_N_ELEMENTS (ui_mainwindow_action_entries), shell->priv);
1099
 
        gtk_action_group_add_toggle_actions (shell->priv->generalActions, ui_mainwindow_action_toggle_entries, G_N_ELEMENTS (ui_mainwindow_action_toggle_entries), shell->priv);
1100
 
        gtk_action_group_add_radio_actions (shell->priv->generalActions, ui_mainwindow_view_radio_entries, G_N_ELEMENTS (ui_mainwindow_view_radio_entries), itemlist_get_view_mode (), (GCallback)on_view_activate, (gpointer)TRUE);
1101
 
        gtk_action_group_add_toggle_actions (shell->priv->generalActions, ui_mainwindow_feedlist_toggle_entries, G_N_ELEMENTS (ui_mainwindow_feedlist_toggle_entries), shell->priv);
1102
 
        gtk_ui_manager_insert_action_group (ui_manager, shell->priv->generalActions, 0);
1103
 
 
1104
 
        shell->priv->addActions = gtk_action_group_new ("AddActions");
1105
 
        gtk_action_group_set_translation_domain (shell->priv->addActions, PACKAGE);
1106
 
        gtk_action_group_add_actions (shell->priv->addActions, ui_mainwindow_add_action_entries, G_N_ELEMENTS (ui_mainwindow_add_action_entries), shell->priv);
1107
 
        gtk_ui_manager_insert_action_group (ui_manager, shell->priv->addActions, 0);
1108
 
 
1109
 
        shell->priv->feedActions = gtk_action_group_new ("FeedActions");
1110
 
        gtk_action_group_set_translation_domain (shell->priv->feedActions, PACKAGE);
1111
 
        gtk_action_group_add_actions (shell->priv->feedActions, ui_mainwindow_feed_action_entries, G_N_ELEMENTS (ui_mainwindow_feed_action_entries), shell->priv);
1112
 
        gtk_ui_manager_insert_action_group (ui_manager, shell->priv->feedActions, 0);
1113
 
 
1114
 
        shell->priv->readWriteActions = gtk_action_group_new("ReadWriteActions");
1115
 
        gtk_action_group_set_translation_domain (shell->priv->readWriteActions, PACKAGE);
1116
 
        gtk_action_group_add_actions (shell->priv->readWriteActions, ui_mainwindow_read_write_action_entries, G_N_ELEMENTS (ui_mainwindow_read_write_action_entries), shell->priv);
1117
 
        gtk_ui_manager_insert_action_group (ui_manager, shell->priv->readWriteActions, 0);
1118
 
 
1119
 
        shell->priv->itemActions = gtk_action_group_new ("ItemActions");
1120
 
        gtk_action_group_set_translation_domain (shell->priv->itemActions, PACKAGE);
1121
 
        gtk_action_group_add_actions (shell->priv->itemActions, ui_mainwindow_item_action_entries, G_N_ELEMENTS (ui_mainwindow_item_action_entries), shell->priv);
1122
 
        gtk_ui_manager_insert_action_group (ui_manager, shell->priv->itemActions, 0);
1123
 
 
1124
 
        accel_group = gtk_ui_manager_get_accel_group (ui_manager);
1125
 
        gtk_window_add_accel_group (GTK_WINDOW (shell->priv->window), accel_group);
1126
 
        g_object_unref (accel_group);
1127
 
 
1128
 
        g_signal_connect (gtk_accel_map_get (), "changed", G_CALLBACK (on_accel_change), NULL);
1129
 
 
1130
 
        if (!gtk_ui_manager_add_ui_from_string (ui_manager, ui_mainwindow_ui_desc, -1, &error))
1131
 
                g_error ("building menus failed: %s", error->message);
1132
 
 
1133
 
        ui_search_engines_setup_menu (ui_manager);
1134
 
 
1135
 
        shell->priv->menubar = gtk_ui_manager_get_widget (ui_manager, "/MainwindowMenubar");
1136
 
        shell->priv->toolbar = gtk_ui_manager_get_widget (ui_manager, "/maintoolbar");
1137
 
 
1138
 
        /* what a pain, why is there no markup for this option? */
1139
 
        g_object_set (G_OBJECT (gtk_ui_manager_get_widget (ui_manager, "/maintoolbar/newFeedButton")), "is_important", TRUE, NULL);
1140
 
        g_object_set (G_OBJECT (gtk_ui_manager_get_widget (ui_manager, "/maintoolbar/nextUnreadButton")), "is_important", TRUE, NULL);
1141
 
        g_object_set (G_OBJECT (gtk_ui_manager_get_widget (ui_manager, "/maintoolbar/MarkAsReadButton")), "is_important", TRUE, NULL);
1142
 
        g_object_set (G_OBJECT (gtk_ui_manager_get_widget (ui_manager, "/maintoolbar/UpdateAllButton")), "is_important", TRUE, NULL);
1143
 
        g_object_set (G_OBJECT (gtk_ui_manager_get_widget (ui_manager, "/maintoolbar/SearchButton")), "is_important", TRUE, NULL);
1144
 
 
1145
 
        /* 2.) setup containers */
1146
 
        
1147
 
        debug0 (DEBUG_GUI, "Setting up widget containers");
1148
 
 
1149
 
        gtk_box_pack_start (GTK_BOX (liferea_shell_lookup ("vbox1")), shell->priv->toolbar, FALSE, FALSE, 0);
1150
 
        gtk_box_reorder_child (GTK_BOX (liferea_shell_lookup ("vbox1")), shell->priv->toolbar, 0);
1151
 
        gtk_box_pack_start (GTK_BOX (liferea_shell_lookup ("vbox1")), shell->priv->menubar, FALSE, FALSE, 0);
1152
 
        gtk_box_reorder_child (GTK_BOX (liferea_shell_lookup ("vbox1")), shell->priv->menubar, 0);
1153
 
 
1154
 
        gtk_widget_show_all(GTK_WIDGET(shell->priv->toolbar));
1155
 
 
1156
 
        g_signal_connect ((gpointer) liferea_shell_lookup ("itemtabs"), "key_press_event",
1157
 
                          G_CALLBACK (on_key_press_event_null_cb), NULL);
1158
 
 
1159
 
        g_signal_connect ((gpointer) liferea_shell_lookup ("itemtabs"), "key_release_event",
1160
 
                          G_CALLBACK (on_key_press_event_null_cb), NULL);
1161
 
        
1162
 
        g_signal_connect ((gpointer) liferea_shell_lookup ("itemtabs"), "scroll_event",
1163
 
                          G_CALLBACK (on_notebook_scroll_event_null_cb), NULL);
1164
 
        
1165
 
        g_signal_connect (G_OBJECT (shell->priv->window), "delete_event", G_CALLBACK(on_close), shell->priv);
1166
 
        g_signal_connect (G_OBJECT (shell->priv->window), "window_state_event", G_CALLBACK(on_window_state_event), shell->priv);
1167
 
        g_signal_connect (G_OBJECT (shell->priv->window), "key_press_event", G_CALLBACK(on_key_press_event), shell->priv);
1168
 
        
1169
 
        /* 3.) setup status bar */
1170
 
        
1171
 
        debug0 (DEBUG_GUI, "Setting up status bar");
1172
 
        
1173
 
        shell->priv->statusbar = GTK_STATUSBAR (liferea_shell_lookup ("statusbar"));
1174
 
        shell->priv->statusbarLocked = FALSE;
1175
 
        shell->priv->statusbarLockTimer = 0;
1176
 
        shell->priv->statusbar_feedsinfo = gtk_label_new("");
1177
 
        gtk_widget_show(shell->priv->statusbar_feedsinfo);
1178
 
        gtk_box_pack_start (GTK_BOX (shell->priv->statusbar), shell->priv->statusbar_feedsinfo, FALSE, FALSE, 5);
1179
 
        
1180
 
        /* 4.) setup tabs */
1181
 
        
1182
 
        debug0 (DEBUG_GUI, "Setting up tabbed browsing");       
1183
 
        shell->priv->tabs = browser_tabs_create (GTK_NOTEBOOK (liferea_shell_lookup ("browsertabs")));
1184
 
        
1185
 
        /* 5.) setup feed list */
1186
 
 
1187
 
        debug0 (DEBUG_GUI, "Setting up feed list");
1188
 
        shell->priv->feedlistView = GTK_TREE_VIEW (liferea_shell_lookup ("feedlist"));
1189
 
        ui_feedlist_init (shell->priv->feedlistView);
1190
 
 
1191
 
        /* 6.) setup menu sensivity */
1192
 
        
1193
 
        debug0 (DEBUG_GUI, "Initialising menues");
1194
 
                
1195
 
        /* On start, no item or feed is selected, so Item menu should be insensitive: */
1196
 
        liferea_shell_update_item_menu (FALSE);
1197
 
 
1198
 
        /* necessary to prevent selection signals when filling the feed list
1199
 
           and setting the 2/3 pane mode view */
1200
 
        gtk_widget_set_sensitive (GTK_WIDGET (shell->priv->feedlistView), FALSE);
1201
 
        
1202
 
        /* 7.) setup item view */
1203
 
        
1204
 
        debug0 (DEBUG_GUI, "Setting up item view");
1205
 
 
1206
 
        shell->priv->itemview = itemview_create (ui_itemlist_new (GTK_WIDGET (shell->priv->window)));
1207
 
        
1208
 
        /* 8.) load icons as required */
1209
 
        
1210
 
        debug0 (DEBUG_GUI, "Loading icons");
1211
 
        
1212
 
        ui_common_add_pixmap_directory (PACKAGE_DATA_DIR G_DIR_SEPARATOR_S PACKAGE G_DIR_SEPARATOR_S "pixmaps");
1213
 
        
1214
 
        /* first try to load icons from theme */
1215
 
        static const gchar *iconThemeNames[] = {
1216
 
                NULL,                   /* ICON_READ */
1217
 
                NULL,                   /* ICON_UNREAD */
1218
 
                "emblem-important",     /* ICON_FLAG */
1219
 
                NULL,                   /* ICON_AVAILABLE */
1220
 
                NULL,                   /* ICON_AVAILABLE_OFFLINE */
1221
 
                NULL,                   /* ICON_UNAVAILABLE */
1222
 
                NULL,                   /* ICON_DEFAULT */
1223
 
                NULL,                   /* ICON_FOLDER_EMPTY */
1224
 
                "folder",               /* ICON_FOLDER */
1225
 
                "folder-saved-search",  /* ICON_VFOLDER */
1226
 
                NULL,                   /* ICON_NEWSBIN */
1227
 
                NULL,                   /* ICON_EMPTY */
1228
 
                NULL,                   /* ICON_EMPTY_OFFLINE */
1229
 
                "gtk-connect",          /* ICON_ONLINE */
1230
 
                "gtk-disconnect",       /* ICON_OFFLINE */
1231
 
                NULL,                   /* ICON_UPDATED */
1232
 
                "mail-attachment",      /* ICON_ENCLOSURE */
1233
 
                NULL
1234
 
        };
1235
 
 
1236
 
        icon_theme = gtk_icon_theme_get_default ();
1237
 
        for (i = 0; i < MAX_ICONS; i++)
1238
 
                if (iconThemeNames[i])
1239
 
                        icons[i] = liferea_shell_get_theme_icon (icon_theme, iconThemeNames[i], 16);
1240
 
 
1241
 
        /* and then load own default icons */
1242
 
        static const gchar *iconNames[] = {
1243
 
                "read.xpm",             /* ICON_READ */
1244
 
                "unread.png",           /* ICON_UNREAD */
1245
 
                "flag.png",             /* ICON_FLAG */
1246
 
                "available.png",        /* ICON_AVAILABLE */
1247
 
                "available_offline.png",        /* ICON_AVAILABLE_OFFLINE */
1248
 
                NULL,                   /* ICON_UNAVAILABLE */
1249
 
                "default.png",          /* ICON_DEFAULT */
1250
 
                "folder_empty.png",     /* ICON_FOLDER_EMPTY */
1251
 
                "directory.png",        /* ICON_FOLDER */
1252
 
                "vfolder.png",          /* ICON_VFOLDER */
1253
 
                "newsbin.png",          /* ICON_NEWSBIN */
1254
 
                "empty.png",            /* ICON_EMPTY */
1255
 
                "empty_offline.png",    /* ICON_EMPTY_OFFLINE */
1256
 
                "online.png",           /* ICON_ONLINE */
1257
 
                "offline.png",          /* ICON_OFFLINE */
1258
 
                "edit.png",             /* ICON_UPDATED */
1259
 
                "attachment.png",       /* ICON_ENCLOSURE */
1260
 
                NULL
1261
 
        };
1262
 
 
1263
 
        for (i = 0; i < MAX_ICONS; i++)
1264
 
                if (!icons[i])
1265
 
                        icons[i] = ui_common_create_pixbuf (iconNames[i]);
1266
 
 
1267
 
        /* set up icons that are build from stock */
1268
 
        widget = gtk_button_new ();
1269
 
        icons[ICON_UNAVAILABLE] = gtk_widget_render_icon (widget, GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_MENU, "");
1270
 
        gtk_widget_destroy (widget);
1271
 
        
1272
 
        liferea_shell_update_toolbar ();
1273
 
        liferea_shell_online_status_changed (network_is_online ());
1274
 
        
1275
 
        liferea_shell_setup_URL_receiver (GTK_WIDGET (shell->priv->window));    /* setup URL dropping support */
1276
 
 
1277
 
        shell->priv->feedlist = feedlist_create ();
1278
 
        
1279
 
        ui_tray_enable (conf_get_bool_value (SHOW_TRAY_ICON));          /* init tray icon */
1280
 
 
1281
 
        liferea_shell_restore_state ();
1282
 
        
1283
 
        if (initialState == MAINWINDOW_ICONIFIED || 
1284
 
            (initialState == MAINWINDOW_HIDDEN && ui_tray_get_count () == 0)) {
1285
 
                gtk_window_iconify (shell->priv->window);
1286
 
                gtk_widget_show (GTK_WIDGET (shell->priv->window));
1287
 
        } else if (initialState == MAINWINDOW_SHOWN) {
1288
 
                gtk_widget_show (GTK_WIDGET (shell->priv->window));
1289
 
        } else {
1290
 
                /* Needed so that the window structure can be
1291
 
                   accessed... otherwise will GTK warning when window is
1292
 
                   shown by clicking on notification icon. */
1293
 
                // gtk_widget_realize (GTK_WIDGET (shell->priv->window));
1294
 
                // Does not work with gtkmozembed...
1295
 
                
1296
 
                gtk_widget_show (GTK_WIDGET (shell->priv->window));
1297
 
                gtk_widget_hide (GTK_WIDGET (shell->priv->window));
1298
 
        }
1299
 
 
1300
 
        gtk_widget_set_sensitive (GTK_WIDGET (shell->priv->feedlistView), TRUE);
1301
 
        
1302
 
        /* 9. Create welcome text */
1303
 
 
1304
 
        /* force two pane mode */
1305
 
        /*   For some reason, this causes the first item to be selected and then
1306
 
             unselected... strange. */
1307
 
        ui_feedlist_select (NULL);
1308
 
        
1309
 
        itemview_set_layout (NODE_VIEW_MODE_COMBINED);
1310
 
        
1311
 
        buffer = g_string_new (NULL);
1312
 
        htmlview_start_output (buffer, NULL, TRUE, FALSE);
1313
 
        g_string_append (buffer,   "<div style=\"padding:8px\">"
1314
 
                                   "<table class=\"headmeta\" style=\"border:solid 1px #aaa;font-size:120%\" border=\"0\" cellspacing=\"0\" cellpadding=\"5px\"><tr><td>"
1315
 
                                   // Display application icon
1316
 
                                   "<img src=\""
1317
 
                                   PACKAGE_DATA_DIR G_DIR_SEPARATOR_S "icons" G_DIR_SEPARATOR_S
1318
 
                                   "hicolor" G_DIR_SEPARATOR_S "48x48" G_DIR_SEPARATOR_S "apps"
1319
 
                                   G_DIR_SEPARATOR_S "liferea.png\" />"
1320
 
                                   "</td><td><h3>");
1321
 
        g_string_append (buffer,   _("Liferea - Linux Feed Reader"));
1322
 
        g_string_append (buffer,   "</h3></td></tr><tr><td colspan=\"2\">");
1323
 
        g_string_append (buffer,   _("<p>Welcome to <b>Liferea</b>, a desktop news aggregator for online news "
1324
 
                                   "feeds.</p>"
1325
 
                                   "<p>The left pane contains the list of your subscriptions. To add a "
1326
 
                                   "subscription select Feeds -&gt; New Subscription. To browse the headlines "
1327
 
                                   "of a feed select it in the feed list and the headlines will be loaded "
1328
 
                                   "into the right pane.</p>"));
1329
 
        g_string_append (buffer,   "</td></tr></table>");
1330
 
 
1331
 
        g_string_append (buffer,   "</div>");
1332
 
 
1333
 
        htmlview_finish_output (buffer);
1334
 
        itemview_display_info (buffer->str);
1335
 
        g_string_free (buffer, TRUE);
1336
 
        
1337
 
        debug_exit ("liferea_shell_create");
1338
 
}
1339
 
 
1340
 
void
1341
 
liferea_shell_destroy (void)
1342
 
{
1343
 
        ui_feedlist_select (NULL);
1344
 
        liferea_shell_save_position ();
1345
 
        ui_tray_enable (FALSE);
1346
 
        notification_enable (FALSE);
1347
 
        g_object_unref (shell->priv->tabs);
1348
 
        g_object_unref (shell->priv->feedlist);
1349
 
 
1350
 
        gtk_widget_destroy (GTK_WIDGET (shell->priv->window));
1351
 
}
1352
 
 
1353
 
void
1354
 
liferea_shell_present (void)
1355
 
{
1356
 
        GtkWidget *mainwindow = GTK_WIDGET (shell->priv->window);
1357
 
        
1358
 
        if ((gdk_window_get_state (mainwindow->window) & GDK_WINDOW_STATE_ICONIFIED) || !GTK_WIDGET_VISIBLE (mainwindow))
1359
 
                liferea_shell_restore_position ();
1360
 
 
1361
 
        gtk_window_present (shell->priv->window);
1362
 
}
1363
 
 
1364
 
void
1365
 
liferea_shell_toggle_visibility (void)
1366
 
{
1367
 
        GtkWidget *mainwindow = GTK_WIDGET (shell->priv->window);
1368
 
        
1369
 
        if(gdk_window_get_state(GTK_WIDGET(mainwindow)->window) & GDK_WINDOW_STATE_ICONIFIED) {
1370
 
                /* The window is either iconified, or on another workspace */
1371
 
                /* Raise it in one click */
1372
 
                if (GTK_WIDGET_VISIBLE(mainwindow)) {
1373
 
                        liferea_shell_save_position ();
1374
 
                        gtk_widget_hide(mainwindow);
1375
 
                }
1376
 
                liferea_shell_restore_position();
1377
 
                gtk_window_present(GTK_WINDOW(mainwindow));
1378
 
        }
1379
 
        else if(!GTK_WIDGET_VISIBLE(mainwindow)) {
1380
 
                /* The window is neither iconified nor on another workspace, but is not visible */
1381
 
                liferea_shell_restore_position ();
1382
 
                gtk_window_present (shell->priv->window);
1383
 
        } else {
1384
 
                liferea_shell_save_position ();
1385
 
                gtk_widget_hide (mainwindow);
1386
 
        }
1387
 
}
1388
 
 
1389
 
GtkWidget *
1390
 
liferea_shell_get_window (void)
1391
 
{
1392
 
        return GTK_WIDGET (shell->priv->window);
1393
 
}
1394
 
 
1395
 
void liferea_shell_set_view_mode (nodeViewType newMode)
1396
 
{
1397
 
        GtkRadioAction       *action;
1398
 
 
1399
 
        action = GTK_RADIO_ACTION (gtk_action_group_get_action (shell->priv->generalActions, "NormalView"));
1400
 
        gtk_radio_action_set_current_value (action, newMode);
1401
 
}