~midori/midori/cmake-make-dist

« back to all changes in this revision

Viewing changes to midori/midori-browser.c

  • Committer: Christian Dywan
  • Date: 2008-06-01 21:47:27 UTC
  • Revision ID: git-v1:b511f12b9b4b063610161f2229b94a24a86be0fc
Rename folder 'src' to 'midori'

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
 
3
 
 
4
 This library is free software; you can redistribute it and/or
 
5
 modify it under the terms of the GNU Lesser General Public
 
6
 License as published by the Free Software Foundation; either
 
7
 version 2.1 of the License, or (at your option) any later version.
 
8
 
 
9
 See the file COPYING for the full license text.
 
10
*/
 
11
 
 
12
#include "config.h"
 
13
 
 
14
#include "midori-browser.h"
 
15
 
 
16
#include "webSearch.h"
 
17
 
 
18
#include "main.h"
 
19
#include "sokoke.h"
 
20
#include "midori-webview.h"
 
21
#include "midori-preferences.h"
 
22
#include "midori-panel.h"
 
23
#include "midori-addons.h"
 
24
#include "midori-console.h"
 
25
#include "midori-trash.h"
 
26
 
 
27
#include <glib/gi18n.h>
 
28
#include <gdk/gdkkeysyms.h>
 
29
#include <gtk/gtk.h>
 
30
#include <libsexy/sexy.h>
 
31
#include <string.h>
 
32
 
 
33
G_DEFINE_TYPE (MidoriBrowser, midori_browser, GTK_TYPE_WINDOW)
 
34
 
 
35
struct _MidoriBrowserPrivate
 
36
{
 
37
    GtkActionGroup* action_group;
 
38
    GtkWidget* menubar;
 
39
    GtkWidget* menu_bookmarks;
 
40
    GtkWidget* menu_tools;
 
41
    GtkWidget* menu_window;
 
42
    GtkWidget* popup_bookmark;
 
43
    GtkWidget* throbber;
 
44
    GtkWidget* navigationbar;
 
45
    GtkWidget* button_tab_new;
 
46
    GtkWidget* button_homepage;
 
47
    GtkWidget* location_icon;
 
48
    GtkWidget* location;
 
49
    GtkWidget* search;
 
50
    GtkWidget* button_trash;
 
51
    GtkWidget* button_fullscreen;
 
52
    GtkWidget* bookmarkbar;
 
53
 
 
54
    GtkWidget* panel;
 
55
    GtkWidget* panel_bookmarks;
 
56
    GtkWidget* panel_console;
 
57
    GtkWidget* panel_pageholder;
 
58
    GtkWidget* notebook;
 
59
 
 
60
    GtkWidget* find;
 
61
    GtkWidget* find_text;
 
62
    GtkToolItem* find_case;
 
63
    GtkToolItem* find_highlight;
 
64
 
 
65
    GtkWidget* statusbar;
 
66
    GtkWidget* progressbar;
 
67
 
 
68
    gchar* uri;
 
69
    gchar* title;
 
70
    gchar* statusbar_text;
 
71
    MidoriWebSettings* settings;
 
72
 
 
73
    KatzeXbelItem* proxy_xbel_folder;
 
74
    MidoriTrash* trash;
 
75
};
 
76
 
 
77
#define MIDORI_BROWSER_GET_PRIVATE(obj) \
 
78
    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
 
79
     MIDORI_TYPE_BROWSER, MidoriBrowserPrivate))
 
80
 
 
81
enum
 
82
{
 
83
    PROP_0,
 
84
 
 
85
    PROP_MENUBAR,
 
86
    PROP_NAVIGATIONBAR,
 
87
    PROP_TAB,
 
88
    PROP_STATUSBAR,
 
89
    PROP_SETTINGS,
 
90
    PROP_STATUSBAR_TEXT,
 
91
    PROP_TRASH
 
92
};
 
93
 
 
94
enum
 
95
{
 
96
    WINDOW_OBJECT_CLEARED,
 
97
    STATUSBAR_TEXT_CHANGED,
 
98
    ELEMENT_MOTION,
 
99
    NEW_WINDOW,
 
100
 
 
101
    ADD_TAB,
 
102
    ADD_URI,
 
103
    ACTIVATE_ACTION,
 
104
    QUIT,
 
105
 
 
106
    LAST_SIGNAL
 
107
};
 
108
 
 
109
static guint signals[LAST_SIGNAL];
 
110
 
 
111
static void
 
112
midori_browser_finalize (GObject* object);
 
113
 
 
114
static void
 
115
midori_browser_set_property (GObject*      object,
 
116
                             guint         prop_id,
 
117
                             const GValue* value,
 
118
                             GParamSpec*   pspec);
 
119
 
 
120
static void
 
121
midori_browser_get_property (GObject*    object,
 
122
                             guint       prop_id,
 
123
                             GValue*     value,
 
124
                             GParamSpec* pspec);
 
125
 
 
126
static GtkAction*
 
127
_action_by_name (MidoriBrowser* browser,
 
128
                 const gchar*   name)
 
129
{
 
130
    MidoriBrowserPrivate* priv = browser->priv;
 
131
 
 
132
    return gtk_action_group_get_action (priv->action_group, name);
 
133
}
 
134
 
 
135
static void
 
136
_action_set_sensitive (MidoriBrowser* browser,
 
137
                       const gchar*   name,
 
138
                       gboolean       sensitive)
 
139
{
 
140
    gtk_action_set_sensitive (_action_by_name (browser, name), sensitive);
 
141
}
 
142
 
 
143
static void
 
144
_action_set_active (MidoriBrowser* browser,
 
145
                    const gchar*   name,
 
146
                    gboolean       active)
 
147
{
 
148
    GtkAction* action = _action_by_name (browser, name);
 
149
    gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), active);
 
150
}
 
151
 
 
152
static void
 
153
_midori_browser_update_actions (MidoriBrowser* browser)
 
154
{
 
155
    MidoriBrowserPrivate* priv = browser->priv;
 
156
 
 
157
    guint n = gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook));
 
158
    gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->notebook), n > 1);
 
159
    _action_set_sensitive (browser, "TabClose", n > 1);
 
160
    _action_set_sensitive (browser, "TabPrevious", n > 1);
 
161
    _action_set_sensitive (browser, "TabNext", n > 1);
 
162
 
 
163
    if (priv->trash)
 
164
    {
 
165
        gboolean trash_empty = midori_trash_is_empty (priv->trash);
 
166
        _action_set_sensitive (browser, "UndoTabClose", !trash_empty);
 
167
        _action_set_sensitive (browser, "Trash", !trash_empty);
 
168
    }
 
169
}
 
170
 
 
171
static void
 
172
_midori_browser_update_interface (MidoriBrowser* browser)
 
173
{
 
174
    MidoriBrowserPrivate* priv = browser->priv;
 
175
 
 
176
    gboolean loading = FALSE;
 
177
    GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
178
    if (web_view)
 
179
    {
 
180
        loading = midori_web_view_is_loading (MIDORI_WEB_VIEW (web_view));
 
181
        _action_set_sensitive (browser, "ZoomNormal",
 
182
            midori_web_view_get_zoom_level (MIDORI_WEB_VIEW (web_view)) != 1.0);
 
183
        if (!g_object_class_find_property (G_OBJECT_GET_CLASS (web_view),
 
184
                                           "zoom-level"))
 
185
        {
 
186
            _action_set_sensitive (browser, "ZoomIn", FALSE);
 
187
            _action_set_sensitive (browser, "ZoomOut", FALSE);
 
188
        }
 
189
        _action_set_sensitive (browser, "Back",
 
190
            webkit_web_view_can_go_back (WEBKIT_WEB_VIEW (web_view)));
 
191
        _action_set_sensitive (browser, "Forward",
 
192
            webkit_web_view_can_go_forward (WEBKIT_WEB_VIEW (web_view)));
 
193
        _action_set_sensitive (browser, "Reload", !loading);
 
194
        _action_set_sensitive (browser, "Stop", loading);
 
195
        _action_set_sensitive (browser, "Print", TRUE);
 
196
    }
 
197
    else
 
198
        _action_set_sensitive (browser, "Print", FALSE);
 
199
 
 
200
    GtkAction* action = gtk_action_group_get_action (priv->action_group,
 
201
                                                     "ReloadStop");
 
202
    if (!loading)
 
203
    {
 
204
        gtk_widget_set_sensitive (priv->throbber, FALSE);
 
205
        g_object_set (action,
 
206
                      "stock-id", GTK_STOCK_REFRESH,
 
207
                      "tooltip", _("Reload the current page"), NULL);
 
208
        gtk_widget_hide (priv->progressbar);
 
209
    }
 
210
    else
 
211
    {
 
212
        gtk_widget_set_sensitive (priv->throbber, TRUE);
 
213
        g_object_set (action,
 
214
                      "stock-id", GTK_STOCK_STOP,
 
215
                      "tooltip", _("Stop loading the current page"), NULL);
 
216
        gtk_widget_show (priv->progressbar);
 
217
    }
 
218
    katze_throbber_set_animated (KATZE_THROBBER (priv->throbber), loading);
 
219
    gtk_image_set_from_stock (GTK_IMAGE (priv->location_icon),
 
220
                              GTK_STOCK_FILE, GTK_ICON_SIZE_MENU);
 
221
}
 
222
 
 
223
static GtkWidget*
 
224
_midori_browser_scrolled_for_child (MidoriBrowser* browser,
 
225
                                    GtkWidget*     child)
 
226
{
 
227
    GtkWidget* scrolled = gtk_widget_get_parent (child);
 
228
    if (GTK_IS_VIEWPORT (scrolled))
 
229
        scrolled = gtk_widget_get_parent (scrolled);
 
230
    return scrolled;
 
231
}
 
232
 
 
233
static GtkWidget*
 
234
_midori_browser_child_for_scrolled (MidoriBrowser* browser,
 
235
                                    GtkWidget*     scrolled)
 
236
{
 
237
    GtkWidget* child = gtk_bin_get_child (GTK_BIN (scrolled));
 
238
    if (GTK_IS_VIEWPORT (child))
 
239
        child = gtk_bin_get_child (GTK_BIN (child));
 
240
    return child;
 
241
}
 
242
 
 
243
static void
 
244
_midori_browser_set_statusbar_text (MidoriBrowser* browser,
 
245
                                    const gchar*   text)
 
246
{
 
247
    MidoriBrowserPrivate* priv = browser->priv;
 
248
 
 
249
    katze_assign (priv->statusbar_text, g_strdup (text));
 
250
    gtk_statusbar_pop (GTK_STATUSBAR (priv->statusbar), 1);
 
251
    gtk_statusbar_push (GTK_STATUSBAR (priv->statusbar), 1,
 
252
                        priv->statusbar_text ? priv->statusbar_text : "");
 
253
}
 
254
 
 
255
static void
 
256
_midori_browser_set_current_page_smartly (MidoriBrowser* browser,
 
257
                                          gint           n)
 
258
{
 
259
    MidoriBrowserPrivate* priv = browser->priv;
 
260
 
 
261
    gboolean open_tabs_in_the_background;
 
262
    g_object_get (priv->settings, "open-tabs-in-the-background",
 
263
                  &open_tabs_in_the_background, NULL);
 
264
    if (!open_tabs_in_the_background)
 
265
        midori_browser_set_current_page (browser, n);
 
266
}
 
267
 
 
268
static void
 
269
_midori_browser_update_progress (MidoriBrowser* browser,
 
270
                                 gint           progress)
 
271
{
 
272
    MidoriBrowserPrivate* priv = browser->priv;
 
273
 
 
274
    if (progress > -1)
 
275
    {
 
276
        gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (priv->progressbar),
 
277
                                       progress ? progress / 100.0 : 0);
 
278
        gchar* message = g_strdup_printf (_("%d%% loaded"), progress);
 
279
        gtk_progress_bar_set_text (GTK_PROGRESS_BAR (priv->progressbar),
 
280
                                   message);
 
281
        g_free (message);
 
282
    }
 
283
    else
 
284
    {
 
285
            gtk_progress_bar_pulse (GTK_PROGRESS_BAR (priv->progressbar));
 
286
            gtk_progress_bar_set_text (GTK_PROGRESS_BAR (priv->progressbar),
 
287
                                       NULL);
 
288
    }
 
289
}
 
290
 
 
291
static void
 
292
midori_web_view_window_object_cleared_cb (GtkWidget*         web_view,
 
293
                                          WebKitWebFrame*    web_frame,
 
294
                                          JSGlobalContextRef js_context,
 
295
                                          JSObjectRef        js_window,
 
296
                                          MidoriBrowser*     browser)
 
297
{
 
298
    g_signal_emit (browser, signals[WINDOW_OBJECT_CLEARED], 0,
 
299
                   web_frame, js_context, js_window);
 
300
}
 
301
 
 
302
static void
 
303
midori_web_view_load_started_cb (GtkWidget*      web_view,
 
304
                                 WebKitWebFrame* web_frame,
 
305
                                 MidoriBrowser*  browser)
 
306
{
 
307
    if (web_view == midori_browser_get_current_web_view (browser))
 
308
    {
 
309
        _midori_browser_update_interface (browser);
 
310
        _midori_browser_set_statusbar_text (browser, NULL);
 
311
    }
 
312
}
 
313
 
 
314
static void
 
315
midori_web_view_progress_started_cb (GtkWidget*     web_view,
 
316
                                     guint          progress,
 
317
                                     MidoriBrowser* browser)
 
318
{
 
319
    if (web_view == midori_browser_get_current_web_view (browser))
 
320
        _midori_browser_update_progress (browser, progress);
 
321
}
 
322
 
 
323
static void
 
324
midori_web_view_progress_changed_cb (GtkWidget*     web_view,
 
325
                                     guint          progress,
 
326
                                     MidoriBrowser* browser)
 
327
{
 
328
    if (web_view == midori_browser_get_current_web_view (browser))
 
329
        _midori_browser_update_progress (browser, progress);
 
330
}
 
331
 
 
332
static void
 
333
midori_web_view_progress_done_cb (GtkWidget*     web_view,
 
334
                                  guint          progress,
 
335
                                  MidoriBrowser* browser)
 
336
{
 
337
    if (web_view == midori_browser_get_current_web_view (browser))
 
338
        _midori_browser_update_progress (browser, progress);
 
339
}
 
340
 
 
341
static void
 
342
midori_web_view_load_done_cb (GtkWidget*      web_view,
 
343
                              WebKitWebFrame* web_frame,
 
344
                              MidoriBrowser*  browser)
 
345
{
 
346
    if (web_view == midori_browser_get_current_web_view (browser))
 
347
    {
 
348
        _midori_browser_update_interface (browser);
 
349
        _midori_browser_set_statusbar_text (browser, NULL);
 
350
    }
 
351
}
 
352
 
 
353
static void
 
354
midori_web_view_title_changed_cb (GtkWidget*      web_view,
 
355
                                  WebKitWebFrame* web_frame,
 
356
                                  const gchar*    title,
 
357
                                  MidoriBrowser*  browser)
 
358
{
 
359
    if (web_view == midori_browser_get_current_web_view (browser))
 
360
    {
 
361
        const gchar* title = midori_web_view_get_display_title (
 
362
            MIDORI_WEB_VIEW (web_view));
 
363
        gchar* window_title = g_strconcat (title, " - ",
 
364
            g_get_application_name (), NULL);
 
365
        gtk_window_set_title (GTK_WINDOW (browser), window_title);
 
366
        g_free (window_title);
 
367
    }
 
368
}
 
369
 
 
370
static void
 
371
midori_web_view_statusbar_text_changed_cb (MidoriWebView*  web_view,
 
372
                                           const gchar*    text,
 
373
                                           MidoriBrowser*  browser)
 
374
{
 
375
    _midori_browser_set_statusbar_text (browser, text);
 
376
}
 
377
 
 
378
static void
 
379
midori_web_view_element_motion_cb (MidoriWebView* web_View,
 
380
                                   const gchar*   link_uri,
 
381
                                   MidoriBrowser* browser)
 
382
{
 
383
    _midori_browser_set_statusbar_text (browser, link_uri);
 
384
}
 
385
 
 
386
static void
 
387
midori_web_view_load_committed_cb (GtkWidget*      web_view,
 
388
                                   WebKitWebFrame* web_frame,
 
389
                                   MidoriBrowser*  browser)
 
390
{
 
391
    MidoriBrowserPrivate* priv = browser->priv;
 
392
 
 
393
    if (web_view == midori_browser_get_current_web_view (browser))
 
394
    {
 
395
        const gchar* uri = midori_web_view_get_display_uri (MIDORI_WEB_VIEW (web_view));
 
396
        gtk_entry_set_text (GTK_ENTRY (priv->location), uri);
 
397
        _midori_browser_set_statusbar_text (browser, NULL);
 
398
    }
 
399
}
 
400
 
 
401
static gboolean
 
402
midori_web_view_console_message_cb (GtkWidget*     web_view,
 
403
                                    const gchar*   message,
 
404
                                    gint           line,
 
405
                                    const gchar*   source_id,
 
406
                                    MidoriBrowser* browser)
 
407
{
 
408
    MidoriBrowserPrivate* priv = browser->priv;
 
409
 
 
410
    midori_console_add (MIDORI_CONSOLE (priv->panel_console),
 
411
                        message, line, source_id);
 
412
    return TRUE;
 
413
}
 
414
 
 
415
static void
 
416
midori_web_view_populate_popup_cb (GtkWidget*     web_view,
 
417
                                   GtkWidget*     menu,
 
418
                                   MidoriBrowser* browser)
 
419
{
 
420
    const gchar* uri = midori_web_view_get_link_uri (MIDORI_WEB_VIEW (web_view));
 
421
    if (uri)
 
422
    {
 
423
        // TODO: bookmark link
 
424
    }
 
425
 
 
426
    if (webkit_web_view_has_selection (WEBKIT_WEB_VIEW (web_view)))
 
427
    {
 
428
        // TODO: view selection source
 
429
    }
 
430
 
 
431
    if (!uri && !webkit_web_view_has_selection (WEBKIT_WEB_VIEW (web_view)))
 
432
    {
 
433
        GtkAction* action = _action_by_name (browser, "UndoTabClose");
 
434
        GtkWidget* menuitem = gtk_action_create_menu_item (action);
 
435
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
 
436
        menuitem = gtk_separator_menu_item_new ();
 
437
        gtk_widget_show (menuitem);
 
438
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
 
439
        action = _action_by_name (browser, "BookmarkAdd");
 
440
        menuitem = gtk_action_create_menu_item (action);
 
441
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
 
442
        action = _action_by_name (browser, "SaveAs");
 
443
        menuitem = gtk_action_create_menu_item (action);
 
444
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
 
445
        action = _action_by_name (browser, "SourceView");
 
446
        menuitem = gtk_action_create_menu_item (action);
 
447
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
 
448
        action = _action_by_name (browser, "Print");
 
449
        menuitem = gtk_action_create_menu_item (action);
 
450
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
 
451
    }
 
452
}
 
453
 
 
454
static gboolean
 
455
midori_web_view_leave_notify_event_cb (GtkWidget*        web_view,
 
456
                                       GdkEventCrossing* event,
 
457
                                       MidoriBrowser*    browser)
 
458
{
 
459
    _midori_browser_set_statusbar_text (browser, NULL);
 
460
    return TRUE;
 
461
}
 
462
 
 
463
static void
 
464
midori_web_view_new_tab_cb (GtkWidget*     web_view,
 
465
                            const gchar*   uri,
 
466
                            MidoriBrowser* browser)
 
467
{
 
468
    gint n = midori_browser_add_uri (browser, uri);
 
469
    _midori_browser_set_current_page_smartly (browser, n);
 
470
}
 
471
 
 
472
static void
 
473
midori_web_view_new_window_cb (GtkWidget*     web_view,
 
474
                               const gchar*   uri,
 
475
                               MidoriBrowser* browser)
 
476
{
 
477
    g_signal_emit (browser, signals[NEW_WINDOW], 0, uri);
 
478
}
 
479
 
 
480
static void
 
481
midori_web_view_close_cb (GtkWidget*     web_view,
 
482
                          MidoriBrowser* browser)
 
483
{
 
484
    MidoriBrowserPrivate* priv = browser->priv;
 
485
 
 
486
    if (priv->proxy_xbel_folder)
 
487
    {
 
488
        KatzeXbelItem* xbel_item = midori_web_view_get_proxy_xbel_item (
 
489
            MIDORI_WEB_VIEW (web_view));
 
490
        const gchar* uri = katze_xbel_bookmark_get_href (xbel_item);
 
491
        if (priv->trash && uri && *uri)
 
492
            midori_trash_prepend_xbel_item (priv->trash, xbel_item);
 
493
        katze_xbel_folder_remove_item (priv->proxy_xbel_folder, xbel_item);
 
494
        katze_xbel_item_unref (xbel_item);
 
495
    }
 
496
    GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, web_view);
 
497
    guint n = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled);
 
498
    gtk_notebook_remove_page (GTK_NOTEBOOK (priv->notebook), n);
 
499
 
 
500
    _midori_browser_update_actions (browser);
 
501
}
 
502
 
 
503
static gboolean
 
504
midori_web_view_destroy_cb (GtkWidget*     widget,
 
505
                            MidoriBrowser* browser)
 
506
{
 
507
    _midori_browser_update_actions (browser);
 
508
    return FALSE;
 
509
}
 
510
 
 
511
static void
 
512
midori_cclosure_marshal_VOID__OBJECT_POINTER_POINTER (GClosure*     closure,
 
513
                                                      GValue*       return_value,
 
514
                                                      guint         n_param_values,
 
515
                                                      const GValue* param_values,
 
516
                                                      gpointer      invocation_hint,
 
517
                                                      gpointer      marshal_data)
 
518
{
 
519
    typedef gboolean(*GMarshalFunc_VOID__OBJECT_POINTER_POINTER) (gpointer  data1,
 
520
                                                                  gpointer  arg_1,
 
521
                                                                  gpointer  arg_2,
 
522
                                                                  gpointer  arg_3,
 
523
                                                                  gpointer  data2);
 
524
    register GMarshalFunc_VOID__OBJECT_POINTER_POINTER callback;
 
525
    register GCClosure* cc = (GCClosure*) closure;
 
526
    register gpointer data1, data2;
 
527
 
 
528
    g_return_if_fail (n_param_values == 4);
 
529
 
 
530
    if (G_CCLOSURE_SWAP_DATA (closure))
 
531
    {
 
532
        data1 = closure->data;
 
533
        data2 = g_value_peek_pointer (param_values + 0);
 
534
    }
 
535
    else
 
536
    {
 
537
        data1 = g_value_peek_pointer (param_values + 0);
 
538
        data2 = closure->data;
 
539
    }
 
540
    callback = (GMarshalFunc_VOID__OBJECT_POINTER_POINTER) (marshal_data
 
541
        ? marshal_data : cc->callback);
 
542
 
 
543
    callback (data1,
 
544
              g_value_get_object (param_values + 1),
 
545
              g_value_get_pointer (param_values + 2),
 
546
              g_value_get_pointer (param_values + 3),
 
547
              data2);
 
548
}
 
549
 
 
550
static void
 
551
midori_cclosure_marshal_INT__OBJECT (GClosure*     closure,
 
552
                                     GValue*       return_value,
 
553
                                     guint         n_param_values,
 
554
                                     const GValue* param_values,
 
555
                                     gpointer      invocation_hint,
 
556
                                     gpointer      marshal_data)
 
557
{
 
558
    typedef gint(*GMarshalFunc_INT__OBJECT) (gpointer  data1,
 
559
                                             gpointer  arg_1,
 
560
                                             gpointer  data2);
 
561
    register GMarshalFunc_INT__OBJECT callback;
 
562
    register GCClosure* cc = (GCClosure*) closure;
 
563
    register gpointer data1, data2;
 
564
    gint v_return;
 
565
 
 
566
    g_return_if_fail (return_value != NULL);
 
567
    g_return_if_fail (n_param_values == 2);
 
568
 
 
569
    if (G_CCLOSURE_SWAP_DATA (closure))
 
570
    {
 
571
        data1 = closure->data;
 
572
        data2 = g_value_peek_pointer (param_values + 0);
 
573
    }
 
574
    else
 
575
    {
 
576
        data1 = g_value_peek_pointer (param_values + 0);
 
577
        data2 = closure->data;
 
578
    }
 
579
    callback = (GMarshalFunc_INT__OBJECT) (marshal_data
 
580
        ? marshal_data : cc->callback);
 
581
    v_return = callback (data1,
 
582
                         g_value_get_object (param_values + 1),
 
583
                         data2);
 
584
    g_value_set_int (return_value, v_return);
 
585
}
 
586
 
 
587
static void
 
588
midori_cclosure_marshal_INT__STRING (GClosure*     closure,
 
589
                                     GValue*       return_value,
 
590
                                     guint         n_param_values,
 
591
                                     const GValue* param_values,
 
592
                                     gpointer      invocation_hint,
 
593
                                     gpointer      marshal_data)
 
594
{
 
595
    typedef gint(*GMarshalFunc_INT__STRING) (gpointer      data1,
 
596
                                             const gchar*  arg_1,
 
597
                                             gpointer      data2);
 
598
    register GMarshalFunc_INT__STRING callback;
 
599
    register GCClosure* cc = (GCClosure*) closure;
 
600
    register gpointer data1, data2;
 
601
    gint v_return;
 
602
 
 
603
    g_return_if_fail (return_value != NULL);
 
604
    g_return_if_fail (n_param_values == 2);
 
605
 
 
606
    if (G_CCLOSURE_SWAP_DATA (closure))
 
607
    {
 
608
        data1 = closure->data;
 
609
        data2 = g_value_peek_pointer (param_values + 0);
 
610
    }
 
611
    else
 
612
    {
 
613
        data1 = g_value_peek_pointer (param_values + 0);
 
614
        data2 = closure->data;
 
615
    }
 
616
    callback = (GMarshalFunc_INT__STRING) (marshal_data
 
617
        ? marshal_data : cc->callback);
 
618
    v_return = callback (data1,
 
619
                         g_value_get_string (param_values + 1),
 
620
                         data2);
 
621
    g_value_set_int (return_value, v_return);
 
622
}
 
623
 
 
624
static void
 
625
midori_browser_class_init (MidoriBrowserClass* class)
 
626
{
 
627
    signals[WINDOW_OBJECT_CLEARED] = g_signal_new (
 
628
        "window-object-cleared",
 
629
        G_TYPE_FROM_CLASS (class),
 
630
        (GSignalFlags)(G_SIGNAL_RUN_LAST),
 
631
        G_STRUCT_OFFSET (MidoriBrowserClass, window_object_cleared),
 
632
        0,
 
633
        NULL,
 
634
        midori_cclosure_marshal_VOID__OBJECT_POINTER_POINTER,
 
635
        G_TYPE_NONE, 3,
 
636
        WEBKIT_TYPE_WEB_FRAME,
 
637
        G_TYPE_POINTER,
 
638
        G_TYPE_POINTER);
 
639
 
 
640
    signals[STATUSBAR_TEXT_CHANGED] = g_signal_new (
 
641
        "statusbar-text-changed",
 
642
        G_TYPE_FROM_CLASS (class),
 
643
        (GSignalFlags)(G_SIGNAL_RUN_LAST),
 
644
        G_STRUCT_OFFSET (MidoriBrowserClass, statusbar_text_changed),
 
645
        0,
 
646
        NULL,
 
647
        g_cclosure_marshal_VOID__STRING,
 
648
        G_TYPE_NONE, 1,
 
649
        G_TYPE_STRING);
 
650
 
 
651
    signals[ELEMENT_MOTION] = g_signal_new (
 
652
        "element-motion",
 
653
        G_TYPE_FROM_CLASS (class),
 
654
        (GSignalFlags)(G_SIGNAL_RUN_LAST),
 
655
        G_STRUCT_OFFSET (MidoriBrowserClass, element_motion),
 
656
        0,
 
657
        NULL,
 
658
        g_cclosure_marshal_VOID__STRING,
 
659
        G_TYPE_NONE, 1,
 
660
        G_TYPE_STRING);
 
661
 
 
662
    signals[NEW_WINDOW] = g_signal_new (
 
663
        "new-window",
 
664
        G_TYPE_FROM_CLASS (class),
 
665
        (GSignalFlags)(G_SIGNAL_RUN_LAST),
 
666
        G_STRUCT_OFFSET (MidoriBrowserClass, new_window),
 
667
        0,
 
668
        NULL,
 
669
        g_cclosure_marshal_VOID__STRING,
 
670
        G_TYPE_NONE, 1,
 
671
        G_TYPE_STRING);
 
672
 
 
673
    signals[ADD_TAB] = g_signal_new (
 
674
        "add-tab",
 
675
        G_TYPE_FROM_CLASS (class),
 
676
        (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
 
677
        G_STRUCT_OFFSET (MidoriBrowserClass, add_tab),
 
678
        0,
 
679
        NULL,
 
680
        midori_cclosure_marshal_INT__OBJECT,
 
681
        G_TYPE_INT, 1,
 
682
        GTK_TYPE_WIDGET);
 
683
 
 
684
    signals[ADD_URI] = g_signal_new (
 
685
        "add-uri",
 
686
        G_TYPE_FROM_CLASS (class),
 
687
        (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
 
688
        G_STRUCT_OFFSET (MidoriBrowserClass, add_uri),
 
689
        0,
 
690
        NULL,
 
691
        midori_cclosure_marshal_INT__STRING,
 
692
        G_TYPE_INT, 1,
 
693
        G_TYPE_STRING);
 
694
 
 
695
    signals[ACTIVATE_ACTION] = g_signal_new (
 
696
        "activate-action",
 
697
        G_TYPE_FROM_CLASS (class),
 
698
        (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
 
699
        G_STRUCT_OFFSET (MidoriBrowserClass, activate_action),
 
700
        0,
 
701
        NULL,
 
702
        g_cclosure_marshal_VOID__STRING,
 
703
        G_TYPE_NONE, 1,
 
704
        G_TYPE_STRING);
 
705
 
 
706
    signals[QUIT] = g_signal_new (
 
707
        "quit",
 
708
        G_TYPE_FROM_CLASS (class),
 
709
        (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
 
710
        G_STRUCT_OFFSET (MidoriBrowserClass, quit),
 
711
        0,
 
712
        NULL,
 
713
        g_cclosure_marshal_VOID__VOID,
 
714
        G_TYPE_NONE, 0);
 
715
 
 
716
    class->add_tab = midori_browser_add_tab;
 
717
    class->add_uri = midori_browser_add_uri;
 
718
    class->activate_action = midori_browser_activate_action;
 
719
    class->quit = midori_browser_quit;
 
720
 
 
721
    GObjectClass* gobject_class = G_OBJECT_CLASS (class);
 
722
    gobject_class->finalize = midori_browser_finalize;
 
723
    gobject_class->set_property = midori_browser_set_property;
 
724
    gobject_class->get_property = midori_browser_get_property;
 
725
 
 
726
    GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
 
727
 
 
728
    g_object_class_install_property (gobject_class,
 
729
                                     PROP_MENUBAR,
 
730
                                     g_param_spec_object (
 
731
                                     "menubar",
 
732
                                     _("Menubar"),
 
733
                                     _("The menubar"),
 
734
                                     GTK_TYPE_MENU_BAR,
 
735
                                     G_PARAM_READABLE));
 
736
 
 
737
    g_object_class_install_property (gobject_class,
 
738
                                     PROP_NAVIGATIONBAR,
 
739
                                     g_param_spec_object (
 
740
                                     "navigationbar",
 
741
                                     _("Navigationbar"),
 
742
                                     _("The navigationbar"),
 
743
                                     GTK_TYPE_TOOLBAR,
 
744
                                     G_PARAM_READABLE));
 
745
 
 
746
    g_object_class_install_property (gobject_class,
 
747
                                     PROP_TAB,
 
748
                                     g_param_spec_object (
 
749
                                     "tab",
 
750
                                     _("Tab"),
 
751
                                     _("The current tab"),
 
752
                                     GTK_TYPE_WIDGET,
 
753
                                     G_PARAM_READWRITE));
 
754
 
 
755
    g_object_class_install_property (gobject_class,
 
756
                                     PROP_STATUSBAR,
 
757
                                     g_param_spec_object (
 
758
                                     "statusbar",
 
759
                                     _("Statusbar"),
 
760
                                     _("The statusbar"),
 
761
                                     GTK_TYPE_STATUSBAR,
 
762
                                     G_PARAM_READABLE));
 
763
 
 
764
    /**
 
765
    * MidoriBrowser:settings:
 
766
    *
 
767
    * An associated settings instance that is shared among all web views.
 
768
    *
 
769
    * Setting this value is propagated to every present web view. Also
 
770
    * every newly created web view will use this instance automatically.
 
771
    */
 
772
    g_object_class_install_property (gobject_class,
 
773
                                     PROP_SETTINGS,
 
774
                                     g_param_spec_object (
 
775
                                     "settings",
 
776
                                     _("Settings"),
 
777
                                     _("The associated settings"),
 
778
                                     MIDORI_TYPE_WEB_SETTINGS,
 
779
                                     G_PARAM_READWRITE));
 
780
 
 
781
    /**
 
782
    * MidoriBrowser:statusbar-text:
 
783
    *
 
784
    * The text that is displayed in the statusbar.
 
785
    *
 
786
    * This value reflects changes to the text visible in the statusbar, such
 
787
    * as the uri of a hyperlink the mouse hovers over or the description of
 
788
    * a menuitem.
 
789
    *
 
790
    * Setting this value changes the displayed text until the next change.
 
791
    */
 
792
    g_object_class_install_property (gobject_class,
 
793
                                     PROP_STATUSBAR_TEXT,
 
794
                                     g_param_spec_string (
 
795
                                     "statusbar-text",
 
796
                                     _("Statusbar Text"),
 
797
                                     _("The text that is displayed in the statusbar"),
 
798
                                     "",
 
799
                                     flags));
 
800
 
 
801
    /**
 
802
    * MidoriBrowser:trash:
 
803
    *
 
804
    * The trash, that collects all closed tabs and windows.
 
805
    *
 
806
    * This is actually a reference to a trash instance, so if a trash should
 
807
    * be used it must be initially set.
 
808
    *
 
809
    * Note: In the future the trash might collect other types of items.
 
810
    */
 
811
    g_object_class_install_property (gobject_class,
 
812
                                     PROP_TRASH,
 
813
                                     g_param_spec_object (
 
814
                                     "trash",
 
815
                                     _("Trash"),
 
816
                                     _("The trash, collecting recently closed tabs and windows"),
 
817
                                     MIDORI_TYPE_TRASH,
 
818
                                     G_PARAM_READWRITE));
 
819
 
 
820
    g_type_class_add_private (class, sizeof (MidoriBrowserPrivate));
 
821
}
 
822
 
 
823
static void
 
824
_action_window_new_activate (GtkAction*     action,
 
825
                             MidoriBrowser* browser)
 
826
{
 
827
    g_signal_emit (browser, signals[NEW_WINDOW], 0, "");
 
828
}
 
829
 
 
830
static void
 
831
_action_tab_new_activate (GtkAction*     action,
 
832
                          MidoriBrowser* browser)
 
833
{
 
834
    MidoriBrowserPrivate* priv = browser->priv;
 
835
 
 
836
    gint n = midori_browser_add_uri (browser, "");
 
837
    midori_browser_set_current_page (browser, n);
 
838
    gtk_widget_grab_focus (priv->location);
 
839
}
 
840
 
 
841
static void
 
842
_action_open_activate (GtkAction*     action,
 
843
                       MidoriBrowser* browser)
 
844
{
 
845
    static gchar* last_dir = NULL;
 
846
    gchar* uri = NULL;
 
847
    gboolean folder_set = FALSE;
 
848
    GtkWidget* dialog = gtk_file_chooser_dialog_new (
 
849
        ("Open file"), GTK_WINDOW (browser),
 
850
        GTK_FILE_CHOOSER_ACTION_OPEN,
 
851
        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 
852
        GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
 
853
        NULL);
 
854
     gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_OPEN);
 
855
     gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (browser));
 
856
 
 
857
     // base the start folder on the current web view's uri if it is local
 
858
     GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
859
     if (web_view)
 
860
         g_object_get (web_view, "uri", &uri, NULL);
 
861
     if (uri)
 
862
     {
 
863
         gchar* filename = g_filename_from_uri (uri, NULL, NULL);
 
864
         if (filename)
 
865
         {
 
866
             gchar* dirname = g_path_get_dirname (filename);
 
867
             if (dirname && g_file_test (dirname, G_FILE_TEST_IS_DIR))
 
868
             {
 
869
                 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), dirname);
 
870
                 folder_set = TRUE;
 
871
             }
 
872
 
 
873
             g_free (dirname);
 
874
             g_free (filename);
 
875
         }
 
876
         g_free (uri);
 
877
     }
 
878
 
 
879
     if (!folder_set && last_dir && *last_dir)
 
880
         gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), last_dir);
 
881
 
 
882
     if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
 
883
     {
 
884
         uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
 
885
         gchar* folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
 
886
         g_object_set (web_view, "uri", uri, NULL);
 
887
 
 
888
         g_free (last_dir);
 
889
         last_dir = folder;
 
890
         g_free (uri);
 
891
     }
 
892
    gtk_widget_destroy (dialog);
 
893
}
 
894
 
 
895
static void
 
896
_action_tab_close_activate (GtkAction*     action,
 
897
                            MidoriBrowser* browser)
 
898
{
 
899
    GtkWidget* widget = midori_browser_get_current_tab (browser);
 
900
    GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, widget);
 
901
    gtk_widget_destroy (scrolled);
 
902
}
 
903
 
 
904
static void
 
905
_action_window_close_activate (GtkAction*     action,
 
906
                               MidoriBrowser* browser)
 
907
{
 
908
    gtk_widget_destroy (GTK_WIDGET (browser));
 
909
}
 
910
 
 
911
static void
 
912
_action_print_activate (GtkAction*     action,
 
913
                        MidoriBrowser* browser)
 
914
{
 
915
    GtkWidget* web_view = midori_browser_get_current_tab (browser);
 
916
    if (web_view)
 
917
        webkit_web_view_execute_script (WEBKIT_WEB_VIEW (web_view), "print ();");
 
918
}
 
919
 
 
920
static void
 
921
_action_quit_activate (GtkAction*     action,
 
922
                       MidoriBrowser* browser)
 
923
{
 
924
    g_signal_emit (browser, signals[QUIT], 0);
 
925
}
 
926
 
 
927
static void
 
928
_action_edit_activate (GtkAction*     action,
 
929
                       MidoriBrowser* browser)
 
930
{
 
931
    GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser));
 
932
    gboolean can_cut = FALSE, can_copy = FALSE, can_paste = FALSE;
 
933
    gboolean has_selection;
 
934
 
 
935
    if (WEBKIT_IS_WEB_VIEW (widget))
 
936
    {
 
937
        WebKitWebView* web_view = WEBKIT_WEB_VIEW (widget);
 
938
        can_cut = webkit_web_view_can_cut_clipboard (web_view);
 
939
        can_copy = webkit_web_view_can_copy_clipboard (web_view);
 
940
        can_paste = webkit_web_view_can_paste_clipboard (web_view);
 
941
    }
 
942
    else if (GTK_IS_EDITABLE (widget))
 
943
    {
 
944
        GtkEditable* editable = GTK_EDITABLE (widget);
 
945
        has_selection = gtk_editable_get_selection_bounds (editable, NULL, NULL);
 
946
        can_cut = has_selection && gtk_editable_get_editable (editable);
 
947
        can_copy = has_selection;
 
948
        can_paste = gtk_editable_get_editable (editable);
 
949
    }
 
950
 
 
951
    _action_set_sensitive (browser, "Cut", can_cut);
 
952
    _action_set_sensitive (browser, "Copy", can_copy);
 
953
    _action_set_sensitive (browser, "Paste", can_paste);
 
954
    _action_set_sensitive (browser, "Delete", can_cut);
 
955
    _action_set_sensitive (browser, "SelectAll", FALSE);
 
956
}
 
957
 
 
958
static void
 
959
_action_cut_activate (GtkAction*     action,
 
960
                      MidoriBrowser* browser)
 
961
{
 
962
    GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser));
 
963
    if (G_LIKELY (widget))
 
964
        g_signal_emit_by_name (widget, "cut-clipboard");
 
965
}
 
966
 
 
967
static void
 
968
_action_copy_activate (GtkAction*     action,
 
969
                       MidoriBrowser* browser)
 
970
{
 
971
    GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser));
 
972
    if (G_LIKELY (widget))
 
973
        g_signal_emit_by_name (widget, "copy-clipboard");
 
974
}
 
975
 
 
976
static void
 
977
_action_paste_activate (GtkAction*     action,
 
978
                        MidoriBrowser* browser)
 
979
{
 
980
    GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser));
 
981
    if (G_LIKELY (widget))
 
982
        g_signal_emit_by_name (widget, "paste-clipboard");
 
983
}
 
984
 
 
985
static void
 
986
_action_delete_activate (GtkAction*     action,
 
987
                         MidoriBrowser* browser)
 
988
{
 
989
    GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser));
 
990
    if (G_LIKELY (widget))
 
991
    {
 
992
        if (WEBKIT_IS_WEB_VIEW (widget))
 
993
            webkit_web_view_delete_selection (WEBKIT_WEB_VIEW (widget));
 
994
        else if (GTK_IS_EDITABLE(widget))
 
995
            gtk_editable_delete_selection (GTK_EDITABLE (widget));
 
996
    }
 
997
}
 
998
 
 
999
static void
 
1000
_action_select_all_activate (GtkAction*     action,
 
1001
                             MidoriBrowser* browser)
 
1002
{
 
1003
    GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser));
 
1004
    if (G_LIKELY (widget))
 
1005
    {
 
1006
        if (GTK_IS_EDITABLE (widget))
 
1007
            gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
 
1008
        else
 
1009
            g_signal_emit_by_name (widget, "select-all");
 
1010
    }
 
1011
}
 
1012
 
 
1013
static void
 
1014
_action_find_activate(GtkAction*     action,
 
1015
                      MidoriBrowser* browser)
 
1016
{
 
1017
    MidoriBrowserPrivate* priv = browser->priv;
 
1018
 
 
1019
    if (GTK_WIDGET_VISIBLE (priv->find))
 
1020
    {
 
1021
        GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
1022
        webkit_web_view_unmark_text_matches (WEBKIT_WEB_VIEW (web_view));
 
1023
        gtk_toggle_tool_button_set_active (
 
1024
            GTK_TOGGLE_TOOL_BUTTON (priv->find_highlight), FALSE);
 
1025
        gtk_widget_hide (priv->find);
 
1026
    }
 
1027
    else
 
1028
    {
 
1029
        GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_FIND,
 
1030
                                                    GTK_ICON_SIZE_MENU);
 
1031
        sexy_icon_entry_set_icon (SEXY_ICON_ENTRY (priv->find_text),
 
1032
                                  SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE (icon));
 
1033
        gtk_entry_set_text (GTK_ENTRY (priv->find_text), "");
 
1034
        gtk_widget_show (priv->find);
 
1035
        gtk_widget_grab_focus (GTK_WIDGET (priv->find_text));
 
1036
    }
 
1037
}
 
1038
 
 
1039
static void
 
1040
_midori_browser_find (MidoriBrowser* browser,
 
1041
                      gboolean       forward)
 
1042
{
 
1043
    MidoriBrowserPrivate* priv = browser->priv;
 
1044
 
 
1045
    const gchar* text = gtk_entry_get_text (GTK_ENTRY (priv->find_text));
 
1046
    const gboolean case_sensitive = gtk_toggle_tool_button_get_active (
 
1047
        GTK_TOGGLE_TOOL_BUTTON(priv->find_case));
 
1048
    GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
1049
    if (GTK_WIDGET_VISIBLE (priv->find))
 
1050
        webkit_web_view_unmark_text_matches (WEBKIT_WEB_VIEW (web_view));
 
1051
    gboolean found = webkit_web_view_search_text (WEBKIT_WEB_VIEW (web_view),
 
1052
        text, case_sensitive, forward, TRUE);
 
1053
    if (GTK_WIDGET_VISIBLE (priv->find))
 
1054
    {
 
1055
        GtkWidget* icon;
 
1056
        if (found)
 
1057
            icon = gtk_image_new_from_stock (GTK_STOCK_FIND, GTK_ICON_SIZE_MENU);
 
1058
        else
 
1059
            icon = gtk_image_new_from_stock (GTK_STOCK_STOP, GTK_ICON_SIZE_MENU);
 
1060
        sexy_icon_entry_set_icon (SEXY_ICON_ENTRY (priv->find_text),
 
1061
            SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(icon));
 
1062
        webkit_web_view_mark_text_matches (WEBKIT_WEB_VIEW (web_view), text,
 
1063
                                           case_sensitive, 0);
 
1064
        const gboolean highlight = gtk_toggle_tool_button_get_active (
 
1065
            GTK_TOGGLE_TOOL_BUTTON (priv->find_highlight));
 
1066
        webkit_web_view_set_highlight_text_matches (WEBKIT_WEB_VIEW (web_view),
 
1067
                                                    highlight);
 
1068
    }
 
1069
}
 
1070
 
 
1071
static void
 
1072
_action_find_next_activate (GtkAction*     action,
 
1073
                            MidoriBrowser* browser)
 
1074
{
 
1075
    _midori_browser_find (browser, TRUE);
 
1076
}
 
1077
 
 
1078
static void
 
1079
_action_find_previous_activate (GtkAction*     action,
 
1080
                                MidoriBrowser* browser)
 
1081
{
 
1082
    _midori_browser_find (browser, FALSE);
 
1083
}
 
1084
 
 
1085
static void
 
1086
_find_highlight_toggled (GtkToggleToolButton* toolitem,
 
1087
                         MidoriBrowser*       browser)
 
1088
{
 
1089
    GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
1090
    const gboolean highlight = gtk_toggle_tool_button_get_active (toolitem);
 
1091
    webkit_web_view_set_highlight_text_matches (WEBKIT_WEB_VIEW (web_view),
 
1092
                                                highlight);
 
1093
}
 
1094
 
 
1095
static void
 
1096
midori_browser_find_button_close_clicked_cb (GtkWidget*     widget,
 
1097
                                             MidoriBrowser* browser)
 
1098
{
 
1099
    MidoriBrowserPrivate* priv = browser->priv;
 
1100
 
 
1101
    gtk_widget_hide (priv->find);
 
1102
}
 
1103
 
 
1104
static void
 
1105
midori_browser_navigationbar_notify_style_cb (GObject*       object,
 
1106
                                              GParamSpec*    arg1,
 
1107
                                              MidoriBrowser* browser)
 
1108
{
 
1109
    MidoriBrowserPrivate* priv = browser->priv;
 
1110
 
 
1111
    MidoriToolbarStyle toolbar_style;
 
1112
    GtkToolbarStyle gtk_toolbar_style;
 
1113
 
 
1114
    g_object_get (priv->settings, "toolbar-style", &toolbar_style, NULL);
 
1115
    if (toolbar_style == MIDORI_TOOLBAR_DEFAULT)
 
1116
    {
 
1117
        g_object_get (priv->settings,
 
1118
                      "gtk-toolbar-style", &gtk_toolbar_style, NULL);
 
1119
        gtk_toolbar_set_style (GTK_TOOLBAR (priv->navigationbar),
 
1120
                               gtk_toolbar_style);
 
1121
    }
 
1122
}
 
1123
 
 
1124
static void
 
1125
midori_browser_menu_trash_item_activate_cb (GtkWidget*     menuitem,
 
1126
                                            MidoriBrowser* browser)
 
1127
{
 
1128
    // Create a new web view with an uri which has been closed before
 
1129
    KatzeXbelItem* item = g_object_get_data (G_OBJECT (menuitem),
 
1130
                                             "KatzeXbelItem");
 
1131
    const gchar* uri = katze_xbel_bookmark_get_href (item);
 
1132
    gint n = midori_browser_add_uri (browser, uri);
 
1133
    midori_browser_set_current_page (browser, n);
 
1134
    katze_xbel_item_unref (item);
 
1135
}
 
1136
 
 
1137
static void
 
1138
midori_browser_menu_trash_activate_cb (GtkWidget*     widget,
 
1139
                                       MidoriBrowser* browser)
 
1140
{
 
1141
    MidoriBrowserPrivate* priv = browser->priv;
 
1142
 
 
1143
    GtkWidget* menu = gtk_menu_new ();
 
1144
    guint n = midori_trash_get_n_items (priv->trash);
 
1145
    GtkWidget* menuitem;
 
1146
    guint i;
 
1147
    for (i = 0; i < n; i++)
 
1148
    {
 
1149
        KatzeXbelItem* item = midori_trash_get_nth_xbel_item (priv->trash, i);
 
1150
        const gchar* title = katze_xbel_item_get_title (item);
 
1151
        const gchar* uri = katze_xbel_bookmark_get_href (item);
 
1152
        menuitem = gtk_image_menu_item_new_with_label (title ? title : uri);
 
1153
        // FIXME: Get the real icon
 
1154
        GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_FILE,
 
1155
                                                    GTK_ICON_SIZE_MENU);
 
1156
        gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon);
 
1157
        gtk_menu_shell_append(GTK_MENU_SHELL (menu), menuitem);
 
1158
        g_object_set_data (G_OBJECT (menuitem), "KatzeXbelItem", item);
 
1159
        g_signal_connect (menuitem, "activate",
 
1160
            G_CALLBACK (midori_browser_menu_trash_item_activate_cb), browser);
 
1161
        gtk_widget_show (menuitem);
 
1162
    }
 
1163
 
 
1164
    menuitem = gtk_separator_menu_item_new ();
 
1165
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
 
1166
    gtk_widget_show (menuitem);
 
1167
    GtkAction* action = gtk_action_group_get_action (priv->action_group,
 
1168
                                                     "TrashEmpty");
 
1169
    menuitem = gtk_action_create_menu_item (action);
 
1170
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
 
1171
    gtk_widget_show (menuitem);
 
1172
    if (GTK_IS_MENU_ITEM (widget))
 
1173
        gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), menu);
 
1174
    else
 
1175
        sokoke_widget_popup (widget, GTK_MENU (menu), NULL,
 
1176
                             SOKOKE_MENU_POSITION_RIGHT);
 
1177
}
 
1178
 
 
1179
static void
 
1180
_action_preferences_activate (GtkAction*     action,
 
1181
                              MidoriBrowser* browser)
 
1182
{
 
1183
    // Show the preferences dialog. Create it if necessary.
 
1184
    static GtkWidget* dialog = NULL;
 
1185
    if (GTK_IS_DIALOG (dialog))
 
1186
        gtk_window_present (GTK_WINDOW (dialog));
 
1187
    else
 
1188
    {
 
1189
        MidoriBrowserPrivate* priv = browser->priv;
 
1190
 
 
1191
        dialog = midori_preferences_new (GTK_WINDOW (browser),
 
1192
                                         priv->settings);
 
1193
        gtk_widget_show (dialog);
 
1194
    }
 
1195
}
 
1196
 
 
1197
static void
 
1198
_action_navigationbar_activate (GtkToggleAction* action,
 
1199
                                MidoriBrowser*   browser)
 
1200
{
 
1201
    MidoriBrowserPrivate* priv = browser->priv;
 
1202
 
 
1203
    gboolean active = gtk_toggle_action_get_active (action);
 
1204
    g_object_set (priv->settings, "show-navigationbar", active, NULL);
 
1205
    sokoke_widget_set_visible (priv->navigationbar, active);
 
1206
}
 
1207
 
 
1208
static void
 
1209
_action_bookmarkbar_activate (GtkToggleAction* action,
 
1210
                              MidoriBrowser*   browser)
 
1211
{
 
1212
    MidoriBrowserPrivate* priv = browser->priv;
 
1213
 
 
1214
    gboolean active = gtk_toggle_action_get_active (action);
 
1215
    g_object_set (priv->settings, "show-bookmarkbar", active, NULL);
 
1216
    sokoke_widget_set_visible (priv->bookmarkbar, active);
 
1217
}
 
1218
 
 
1219
static void
 
1220
_action_statusbar_activate (GtkToggleAction* action,
 
1221
                            MidoriBrowser*   browser)
 
1222
{
 
1223
    MidoriBrowserPrivate* priv = browser->priv;
 
1224
 
 
1225
    gboolean active = gtk_toggle_action_get_active (action);
 
1226
    g_object_set (priv->settings, "show-statusbar", active, NULL);
 
1227
    sokoke_widget_set_visible (priv->statusbar, active);
 
1228
}
 
1229
 
 
1230
static void
 
1231
_action_reload_stop_activate (GtkAction*     action,
 
1232
                              MidoriBrowser* browser)
 
1233
{
 
1234
    gchar* stock_id;
 
1235
    g_object_get (action, "stock-id", &stock_id, NULL);
 
1236
    GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
1237
    // Refresh or stop, depending on the stock id
 
1238
    if (!strcmp (stock_id, GTK_STOCK_REFRESH))
 
1239
    {
 
1240
        /*GdkModifierType state = (GdkModifierType)0;
 
1241
        gint x, y;
 
1242
        gdk_window_get_pointer (NULL, &x, &y, &state);
 
1243
        gboolean from_cache = state & GDK_SHIFT_MASK;*/
 
1244
        webkit_web_view_reload (WEBKIT_WEB_VIEW (web_view));
 
1245
    }
 
1246
    else
 
1247
        webkit_web_view_stop_loading (WEBKIT_WEB_VIEW (web_view));
 
1248
    g_free (stock_id);
 
1249
}
 
1250
 
 
1251
static void
 
1252
_action_zoom_in_activate (GtkAction*     action,
 
1253
                          MidoriBrowser* browser)
 
1254
{
 
1255
    GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
1256
    if (web_view && g_object_class_find_property (
 
1257
        G_OBJECT_GET_CLASS (web_view), "zoom-level"))
 
1258
    {
 
1259
        MidoriBrowserPrivate* priv = browser->priv;
 
1260
 
 
1261
        gfloat zoom_level, zoom_step;
 
1262
        g_object_get (web_view, "zoom-level", &zoom_level, NULL);
 
1263
        g_object_get (priv->settings, "zoom-step", &zoom_step, NULL);
 
1264
        g_object_set (web_view, "zoom-level", zoom_level + zoom_step, NULL);
 
1265
    }
 
1266
}
 
1267
 
 
1268
static void
 
1269
_action_zoom_out_activate (GtkAction*     action,
 
1270
                           MidoriBrowser* browser)
 
1271
{
 
1272
    GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
1273
    if (web_view && g_object_class_find_property (
 
1274
        G_OBJECT_GET_CLASS (web_view), "zoom-level"))
 
1275
    {
 
1276
        MidoriBrowserPrivate* priv = browser->priv;
 
1277
 
 
1278
        gfloat zoom_level, zoom_step;
 
1279
        g_object_get (web_view, "zoom-level", &zoom_level, NULL);
 
1280
        g_object_get (priv->settings, "zoom-step", &zoom_step, NULL);
 
1281
        g_object_set (web_view, "zoom-level", zoom_level - zoom_step, NULL);
 
1282
    }
 
1283
}
 
1284
 
 
1285
static void
 
1286
_action_zoom_normal_activate (GtkAction*     action,
 
1287
                              MidoriBrowser* browser)
 
1288
{
 
1289
    GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
1290
    if (web_view && g_object_class_find_property (
 
1291
        G_OBJECT_GET_CLASS (web_view), "zoom-level"))
 
1292
        g_object_set (web_view, "zoom-level", 1.0, NULL);
 
1293
}
 
1294
 
 
1295
/*static void
 
1296
_action_source_view_activate (GtkAction*     action,
 
1297
                              MidoriBrowser* browser)
 
1298
{
 
1299
    GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
1300
    gchar* source = webkit_web_view_copy_source (WEBKIT_WEB_VIEW (web_view));
 
1301
    webkit_web_view_load_html_string (WEBKIT_WEB_VIEW (web_view), source, "");
 
1302
    g_free (source);
 
1303
}*/
 
1304
 
 
1305
static void
 
1306
_action_fullscreen_activate (GtkAction*     action,
 
1307
                             MidoriBrowser* browser)
 
1308
{
 
1309
    GdkWindowState state = gdk_window_get_state (GTK_WIDGET (browser)->window);
 
1310
    if (state & GDK_WINDOW_STATE_FULLSCREEN)
 
1311
        gtk_window_unfullscreen (GTK_WINDOW (browser));
 
1312
    else
 
1313
        gtk_window_fullscreen (GTK_WINDOW (browser));
 
1314
}
 
1315
 
 
1316
static void
 
1317
_action_back_activate (GtkAction*     action,
 
1318
                       MidoriBrowser* browser)
 
1319
{
 
1320
    GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
1321
    webkit_web_view_go_back (WEBKIT_WEB_VIEW (web_view));
 
1322
}
 
1323
 
 
1324
static void
 
1325
_action_forward_activate (GtkAction*     action,
 
1326
                          MidoriBrowser* browser)
 
1327
{
 
1328
    GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
1329
    webkit_web_view_go_forward (WEBKIT_WEB_VIEW (web_view));
 
1330
}
 
1331
 
 
1332
static void
 
1333
_action_homepage_activate (GtkAction*     action,
 
1334
                           MidoriBrowser* browser)
 
1335
{
 
1336
    MidoriBrowserPrivate* priv = browser->priv;
 
1337
 
 
1338
    gchar* homepage;
 
1339
 
 
1340
    GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
1341
    g_object_get (priv->settings, "homepage", &homepage, NULL);
 
1342
    g_object_set (web_view, "uri", homepage, NULL);
 
1343
    g_free (homepage);
 
1344
}
 
1345
 
 
1346
static gboolean
 
1347
midori_browser_location_key_press_event_cb (GtkWidget*     widget,
 
1348
                                            GdkEventKey*   event,
 
1349
                                            MidoriBrowser* browser)
 
1350
{
 
1351
    MidoriBrowserPrivate* priv = browser->priv;
 
1352
    gchar* location_entry_search;
 
1353
 
 
1354
    switch (event->keyval)
 
1355
    {
 
1356
    case GDK_ISO_Enter:
 
1357
    case GDK_KP_Enter:
 
1358
    case GDK_Return:
 
1359
    {
 
1360
        const gchar* uri = gtk_entry_get_text (GTK_ENTRY (widget));
 
1361
        if (uri)
 
1362
        {
 
1363
            g_object_get (priv->settings, "location-entry-search",
 
1364
                          &location_entry_search, NULL);
 
1365
            gchar* new_uri = sokoke_magic_uri (uri, location_entry_search);
 
1366
            g_free (location_entry_search);
 
1367
            // TODO: Use new_uri intermediately when completion is better
 
1368
            /* TODO Completion should be generated from history, that is
 
1369
                    the uri as well as the title. */
 
1370
            sokoke_entry_append_completion (GTK_ENTRY (widget), uri);
 
1371
            GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
1372
            g_object_set (web_view, "uri", new_uri, NULL);
 
1373
            g_free (new_uri);
 
1374
            gtk_widget_grab_focus (web_view);
 
1375
        }
 
1376
        return TRUE;
 
1377
    }
 
1378
    case GDK_Escape:
 
1379
    {
 
1380
        GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
1381
        const gchar* uri = midori_web_view_get_display_uri (
 
1382
            MIDORI_WEB_VIEW (web_view));
 
1383
        gtk_entry_set_text (GTK_ENTRY (widget), uri);
 
1384
        return TRUE;
 
1385
    }
 
1386
    }
 
1387
    return FALSE;
 
1388
}
 
1389
 
 
1390
static void
 
1391
_action_location_activate (GtkAction*     action,
 
1392
                           MidoriBrowser* browser)
 
1393
{
 
1394
    MidoriBrowserPrivate* priv = browser->priv;
 
1395
 
 
1396
    if (!GTK_WIDGET_VISIBLE (priv->navigationbar))
 
1397
        gtk_widget_show (priv->navigationbar);
 
1398
    gtk_widget_grab_focus (priv->location);
 
1399
}
 
1400
 
 
1401
static gboolean
 
1402
midori_browser_location_focus_out_event_cb (GtkWidget*     widget,
 
1403
                                            GdkEventFocus* event,
 
1404
                                            MidoriBrowser* browser)
 
1405
{
 
1406
    MidoriBrowserPrivate* priv = browser->priv;
 
1407
 
 
1408
    gboolean show_navigationbar;
 
1409
    g_object_get (priv->settings,
 
1410
                  "show-navigationbar", &show_navigationbar,
 
1411
                  NULL);
 
1412
    if (!show_navigationbar)
 
1413
        gtk_widget_hide (priv->navigationbar);
 
1414
    return FALSE;
 
1415
}
 
1416
 
 
1417
static void
 
1418
_action_search_activate (GtkAction*     action,
 
1419
                         MidoriBrowser* browser)
 
1420
{
 
1421
    MidoriBrowserPrivate* priv = browser->priv;
 
1422
 
 
1423
    if (!GTK_WIDGET_VISIBLE (priv->search))
 
1424
        gtk_widget_show (priv->search);
 
1425
    if (!GTK_WIDGET_VISIBLE (priv->navigationbar))
 
1426
        gtk_widget_show (priv->navigationbar);
 
1427
    gtk_widget_grab_focus (priv->search);
 
1428
}
 
1429
 
 
1430
static gboolean
 
1431
midori_browser_search_focus_out_event_cb (GtkWidget*     widget,
 
1432
                                          GdkEventFocus* event,
 
1433
                                          MidoriBrowser* browser)
 
1434
{
 
1435
    MidoriBrowserPrivate* priv = browser->priv;
 
1436
 
 
1437
    gboolean show_navigationbar;
 
1438
    gboolean show_web_search;
 
1439
    g_object_get (priv->settings,
 
1440
                  "show-navigationbar", &show_navigationbar,
 
1441
                  "show-web-search", &show_web_search,
 
1442
                  NULL);
 
1443
    if (!show_navigationbar)
 
1444
        gtk_widget_hide (priv->navigationbar);
 
1445
    if (!show_web_search)
 
1446
        gtk_widget_hide (priv->search);
 
1447
    return FALSE;
 
1448
}
 
1449
 
 
1450
static void
 
1451
midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser,
 
1452
                                         KatzeXbelItem* bookmark)
 
1453
{
 
1454
    MidoriBrowserPrivate* priv = browser->priv;
 
1455
 
 
1456
    gboolean new_bookmark = !bookmark;
 
1457
    GtkWidget* dialog = gtk_dialog_new_with_buttons (
 
1458
        new_bookmark ? _("New bookmark") : _("Edit bookmark"),
 
1459
        GTK_WINDOW (browser),
 
1460
        GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
 
1461
        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 
1462
        new_bookmark ? GTK_STOCK_ADD : GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
 
1463
        NULL);
 
1464
    gtk_window_set_icon_name (GTK_WINDOW (dialog),
 
1465
        new_bookmark ? GTK_STOCK_ADD : GTK_STOCK_REMOVE);
 
1466
    gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
 
1467
    gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 5);
 
1468
    GtkSizeGroup* sizegroup =  gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
 
1469
 
 
1470
    if (new_bookmark)
 
1471
        bookmark = katze_xbel_bookmark_new ();
 
1472
 
 
1473
    GtkWidget* hbox = gtk_hbox_new (FALSE, 8);
 
1474
    gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
 
1475
    GtkWidget* label = gtk_label_new_with_mnemonic (_("_Title:"));
 
1476
    gtk_size_group_add_widget (sizegroup, label);
 
1477
    gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 
1478
    GtkWidget* entry_title = gtk_entry_new ();
 
1479
    gtk_entry_set_activates_default (GTK_ENTRY (entry_title), TRUE);
 
1480
    if (!new_bookmark)
 
1481
    {
 
1482
        const gchar* title = katze_xbel_item_get_title (bookmark);
 
1483
        gtk_entry_set_text (GTK_ENTRY (entry_title), title ? title : "");
 
1484
    }
 
1485
    gtk_box_pack_start (GTK_BOX (hbox), entry_title, TRUE, TRUE, 0);
 
1486
    gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
 
1487
    gtk_widget_show_all (hbox);
 
1488
 
 
1489
    hbox = gtk_hbox_new (FALSE, 8);
 
1490
    gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
 
1491
    label = gtk_label_new_with_mnemonic (_("_Description:"));
 
1492
    gtk_size_group_add_widget (sizegroup, label);
 
1493
    gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 
1494
    GtkWidget* entry_desc = gtk_entry_new ();
 
1495
    gtk_entry_set_activates_default (GTK_ENTRY (entry_desc), TRUE);
 
1496
    if (!new_bookmark)
 
1497
    {
 
1498
        const gchar* desc = katze_xbel_item_get_desc (bookmark);
 
1499
        gtk_entry_set_text (GTK_ENTRY (entry_desc), desc ? desc : "");
 
1500
    }
 
1501
    gtk_box_pack_start (GTK_BOX (hbox), entry_desc, TRUE, TRUE, 0);
 
1502
    gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
 
1503
    gtk_widget_show_all (hbox);
 
1504
 
 
1505
    GtkWidget* entry_uri = NULL;
 
1506
    if (katze_xbel_item_is_bookmark (bookmark))
 
1507
    {
 
1508
        hbox = gtk_hbox_new (FALSE, 8);
 
1509
        gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
 
1510
        label = gtk_label_new_with_mnemonic (_("_URL:"));
 
1511
        gtk_size_group_add_widget (sizegroup, label);
 
1512
        gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 
1513
        entry_uri = gtk_entry_new ();
 
1514
        gtk_entry_set_activates_default (GTK_ENTRY (entry_uri), TRUE);
 
1515
        if (!new_bookmark)
 
1516
            gtk_entry_set_text (GTK_ENTRY (entry_uri),
 
1517
                                katze_xbel_bookmark_get_href (bookmark));
 
1518
        gtk_box_pack_start (GTK_BOX(hbox), entry_uri, TRUE, TRUE, 0);
 
1519
        gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
 
1520
        gtk_widget_show_all (hbox);
 
1521
    }
 
1522
 
 
1523
    GtkWidget* combo_folder = NULL;
 
1524
    if (new_bookmark)
 
1525
    {
 
1526
        hbox = gtk_hbox_new (FALSE, 8);
 
1527
        gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
 
1528
        label = gtk_label_new_with_mnemonic (_("_Folder:"));
 
1529
        gtk_size_group_add_widget (sizegroup, label);
 
1530
        gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
 
1531
        combo_folder = gtk_combo_box_new_text ();
 
1532
        gtk_combo_box_append_text (GTK_COMBO_BOX (combo_folder), _("Root"));
 
1533
        gtk_widget_set_sensitive (combo_folder, FALSE);
 
1534
        gtk_box_pack_start (GTK_BOX (hbox), combo_folder, TRUE, TRUE, 0);
 
1535
        gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
 
1536
        gtk_widget_show_all (hbox);
 
1537
    }
 
1538
 
 
1539
    gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
 
1540
    if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
 
1541
    {
 
1542
        katze_xbel_item_set_title (bookmark,
 
1543
            gtk_entry_get_text (GTK_ENTRY (entry_title)));
 
1544
        katze_xbel_item_set_desc (bookmark,
 
1545
            gtk_entry_get_text(GTK_ENTRY(entry_desc)));
 
1546
        if (katze_xbel_item_is_bookmark (bookmark))
 
1547
            katze_xbel_bookmark_set_href (bookmark,
 
1548
                gtk_entry_get_text (GTK_ENTRY (entry_uri)));
 
1549
 
 
1550
        // FIXME: We want to choose a folder
 
1551
        if (new_bookmark)
 
1552
        {
 
1553
            katze_xbel_folder_append_item (bookmarks, bookmark);
 
1554
            GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks);
 
1555
            GtkTreeModel* treemodel = gtk_tree_view_get_model (treeview);
 
1556
            GtkTreeIter iter;
 
1557
            gtk_tree_store_insert_with_values (GTK_TREE_STORE (treemodel),
 
1558
                &iter, NULL, G_MAXINT, 0, bookmark, -1);
 
1559
            katze_xbel_item_ref (bookmark);
 
1560
        }
 
1561
 
 
1562
        // FIXME: update navigationbar
 
1563
        // FIXME: Update panel in other windows
 
1564
    }
 
1565
    gtk_widget_destroy (dialog);
 
1566
}
 
1567
 
 
1568
static void
 
1569
midori_panel_bookmarks_row_activated_cb (GtkTreeView*       treeview,
 
1570
                                         GtkTreePath*       path,
 
1571
                                         GtkTreeViewColumn* column,
 
1572
                                         MidoriBrowser*     browser)
 
1573
{
 
1574
    GtkTreeModel* model = gtk_tree_view_get_model (treeview);
 
1575
    GtkTreeIter iter;
 
1576
    if (gtk_tree_model_get_iter (model, &iter, path))
 
1577
    {
 
1578
        KatzeXbelItem* item;
 
1579
        gtk_tree_model_get (model, &iter, 0, &item, -1);
 
1580
        if (katze_xbel_item_is_bookmark (item))
 
1581
        {
 
1582
            GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
1583
            const gchar* uri = katze_xbel_bookmark_get_href (item);
 
1584
            g_object_set (web_view, "uri", uri, NULL);
 
1585
        }
 
1586
    }
 
1587
}
 
1588
 
 
1589
static void
 
1590
midori_panel_bookmarks_cursor_or_row_changed_cb (GtkTreeView*   treeview,
 
1591
                                                 MidoriBrowser* browser)
 
1592
{
 
1593
    GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview);
 
1594
    if (selection)
 
1595
    {
 
1596
        GtkTreeModel* model;
 
1597
        GtkTreeIter iter;
 
1598
        if (gtk_tree_selection_get_selected (selection, &model, &iter))
 
1599
        {
 
1600
            KatzeXbelItem* item;
 
1601
            gtk_tree_model_get (model, &iter, 0, &item, -1);
 
1602
 
 
1603
            gboolean is_separator = katze_xbel_item_is_separator (item);
 
1604
            _action_set_sensitive (browser, "BookmarkEdit", !is_separator);
 
1605
            _action_set_sensitive (browser, "BookmarkDelete", TRUE);
 
1606
        }
 
1607
        else
 
1608
        {
 
1609
            _action_set_sensitive (browser, "BookmarkEdit", FALSE);
 
1610
            _action_set_sensitive (browser, "BookmarkDelete", FALSE);
 
1611
        }
 
1612
    }
 
1613
}
 
1614
 
 
1615
static void
 
1616
_midori_panel_bookmarks_popup (GtkWidget*      widget,
 
1617
                               GdkEventButton* event,
 
1618
                               KatzeXbelItem*  item,
 
1619
                               MidoriBrowser*  browser)
 
1620
{
 
1621
    MidoriBrowserPrivate* priv = browser->priv;
 
1622
 
 
1623
    gboolean is_bookmark = katze_xbel_item_is_bookmark (item);
 
1624
 
 
1625
    _action_set_sensitive (browser, "BookmarkOpen", is_bookmark);
 
1626
    _action_set_sensitive (browser, "BookmarkOpenTab", is_bookmark);
 
1627
    _action_set_sensitive (browser, "BookmarkOpenWindow", is_bookmark);
 
1628
 
 
1629
    sokoke_widget_popup (widget, GTK_MENU (priv->popup_bookmark),
 
1630
                         event, SOKOKE_MENU_POSITION_CURSOR);
 
1631
}
 
1632
 
 
1633
static gboolean
 
1634
midori_panel_bookmarks_button_release_event_cb (GtkWidget*      widget,
 
1635
                                                GdkEventButton* event,
 
1636
                                                MidoriBrowser*  browser)
 
1637
{
 
1638
    if (event->button != 2 && event->button != 3)
 
1639
        return FALSE;
 
1640
 
 
1641
    GtkTreeSelection* selection = gtk_tree_view_get_selection (
 
1642
        GTK_TREE_VIEW (widget));
 
1643
    if (selection)
 
1644
    {
 
1645
        GtkTreeModel* model;
 
1646
        GtkTreeIter iter;
 
1647
        if (gtk_tree_selection_get_selected (selection, &model, &iter))
 
1648
        {
 
1649
            KatzeXbelItem* item;
 
1650
            gtk_tree_model_get (model, &iter, 0, &item, -1);
 
1651
            if (event->button == 2 && katze_xbel_item_is_bookmark (item))
 
1652
            {
 
1653
                const gchar* uri = katze_xbel_bookmark_get_href (item);
 
1654
                gint n = midori_browser_add_uri (browser, uri);
 
1655
                midori_browser_set_current_page (browser, n);
 
1656
            }
 
1657
            else
 
1658
                _midori_panel_bookmarks_popup (widget, event, item, browser);
 
1659
            return TRUE;
 
1660
        }
 
1661
    }
 
1662
    return FALSE;
 
1663
}
 
1664
 
 
1665
static void
 
1666
midori_panel_bookmarks_popup_menu_cb (GtkWidget*     widget,
 
1667
                                      MidoriBrowser* browser)
 
1668
{
 
1669
    GtkTreeSelection* selection = gtk_tree_view_get_selection (
 
1670
        GTK_TREE_VIEW (widget));
 
1671
    if (selection)
 
1672
    {
 
1673
        GtkTreeModel* model;
 
1674
        GtkTreeIter iter;
 
1675
        if (gtk_tree_selection_get_selected (selection, &model, &iter))
 
1676
        {
 
1677
            KatzeXbelItem* item;
 
1678
            gtk_tree_model_get (model, &iter, 0, &item, -1);
 
1679
            _midori_panel_bookmarks_popup (widget, NULL, item, browser);
 
1680
        }
 
1681
    }
 
1682
}
 
1683
 
 
1684
static void
 
1685
_tree_store_insert_folder (GtkTreeStore*  treestore,
 
1686
                           GtkTreeIter*   parent,
 
1687
                           KatzeXbelItem* folder)
 
1688
{
 
1689
    guint n = katze_xbel_folder_get_n_items (folder);
 
1690
    guint i;
 
1691
    for (i = 0; i < n; i++)
 
1692
    {
 
1693
        KatzeXbelItem* item = katze_xbel_folder_get_nth_item (folder, i);
 
1694
        GtkTreeIter iter;
 
1695
        gtk_tree_store_insert_with_values (treestore, &iter, parent, n,
 
1696
                                           0, item, -1);
 
1697
        katze_xbel_item_ref (item);
 
1698
        if (katze_xbel_item_is_folder (item))
 
1699
            _tree_store_insert_folder (treestore, &iter, item);
 
1700
    }
 
1701
}
 
1702
 
 
1703
static void
 
1704
midori_browser_bookmarks_item_render_icon_cb (GtkTreeViewColumn* column,
 
1705
                                              GtkCellRenderer*   renderer,
 
1706
                                              GtkTreeModel*      model,
 
1707
                                              GtkTreeIter*       iter,
 
1708
                                              GtkWidget*         treeview)
 
1709
{
 
1710
    KatzeXbelItem* item;
 
1711
    gtk_tree_model_get (model, iter, 0, &item, -1);
 
1712
 
 
1713
    if (G_UNLIKELY (!item))
 
1714
        return;
 
1715
    if (G_UNLIKELY (!katze_xbel_item_get_parent (item)))
 
1716
    {
 
1717
        gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
 
1718
        katze_xbel_item_unref (item);
 
1719
        return;
 
1720
    }
 
1721
 
 
1722
    // TODO: Would it be better to not do this on every redraw?
 
1723
    GdkPixbuf* pixbuf = NULL;
 
1724
    if (katze_xbel_item_is_bookmark (item))
 
1725
        pixbuf = gtk_widget_render_icon (treeview, STOCK_BOOKMARK,
 
1726
                                         GTK_ICON_SIZE_MENU, NULL);
 
1727
    else if (katze_xbel_item_is_folder (item))
 
1728
        pixbuf = gtk_widget_render_icon (treeview, GTK_STOCK_DIRECTORY,
 
1729
                                         GTK_ICON_SIZE_MENU, NULL);
 
1730
    g_object_set (renderer, "pixbuf", pixbuf, NULL);
 
1731
    if (pixbuf)
 
1732
        g_object_unref (pixbuf);
 
1733
}
 
1734
 
 
1735
static void
 
1736
midori_browser_bookmarks_item_render_text_cb (GtkTreeViewColumn* column,
 
1737
                                              GtkCellRenderer*   renderer,
 
1738
                                              GtkTreeModel*      model,
 
1739
                                              GtkTreeIter*       iter,
 
1740
                                              GtkWidget*         treeview)
 
1741
{
 
1742
    KatzeXbelItem* item;
 
1743
    gtk_tree_model_get (model, iter, 0, &item, -1);
 
1744
 
 
1745
    if (G_UNLIKELY (!item))
 
1746
        return;
 
1747
    if (G_UNLIKELY (!katze_xbel_item_get_parent (item)))
 
1748
    {
 
1749
        gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
 
1750
        katze_xbel_item_unref (item);
 
1751
        return;
 
1752
    }
 
1753
 
 
1754
    if (katze_xbel_item_is_separator (item))
 
1755
        g_object_set (renderer, "markup", _("<i>Separator</i>"), NULL);
 
1756
    else
 
1757
        g_object_set (renderer, "markup", NULL,
 
1758
                      "text", katze_xbel_item_get_title (item), NULL);
 
1759
}
 
1760
 
 
1761
static void
 
1762
_midori_browser_create_bookmark_menu (MidoriBrowser* browser,
 
1763
                                      KatzeXbelItem* folder,
 
1764
                                      GtkWidget*     menu);
 
1765
 
 
1766
static void
 
1767
midori_browser_bookmark_menu_folder_activate_cb (GtkWidget*     menuitem,
 
1768
                                                 MidoriBrowser* browser)
 
1769
{
 
1770
    GtkWidget* menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (menuitem));
 
1771
    gtk_container_foreach (GTK_CONTAINER (menu), (GtkCallback) gtk_widget_destroy, NULL);//...
 
1772
    KatzeXbelItem* folder = (KatzeXbelItem*)g_object_get_data(G_OBJECT (menuitem), "KatzeXbelItem");
 
1773
    _midori_browser_create_bookmark_menu (browser, folder, menu);
 
1774
    // Remove all menuitems when the menu is hidden.
 
1775
    // FIXME: We really *want* the line below, but it won't work like that
 
1776
    //g_signal_connect_after (menu, "hide", G_CALLBACK (gtk_container_foreach), gtk_widget_destroy);
 
1777
    gtk_widget_show (menuitem);
 
1778
}
 
1779
 
 
1780
static void
 
1781
midori_browser_bookmarkbar_folder_activate_cb (GtkToolItem*   toolitem,
 
1782
                                               MidoriBrowser* browser)
 
1783
{
 
1784
    GtkWidget* menu = gtk_menu_new ();
 
1785
    KatzeXbelItem* folder = (KatzeXbelItem*)g_object_get_data (
 
1786
        G_OBJECT (toolitem), "KatzeXbelItem");
 
1787
    _midori_browser_create_bookmark_menu (browser, folder, menu);
 
1788
    // Remove all menuitems when the menu is hidden.
 
1789
    // FIXME: We really *should* run the line below, but it won't work like that
 
1790
    /*g_signal_connect (menu, "hide", G_CALLBACK (gtk_container_foreach),
 
1791
                      gtk_widget_destroy);*/
 
1792
    sokoke_widget_popup (GTK_WIDGET (toolitem), GTK_MENU (menu),
 
1793
                         NULL, SOKOKE_MENU_POSITION_LEFT);
 
1794
}
 
1795
 
 
1796
static void
 
1797
midori_browser_menu_bookmarks_item_activate_cb (GtkWidget*     widget,
 
1798
                                                MidoriBrowser* browser)
 
1799
{
 
1800
    KatzeXbelItem* item = (KatzeXbelItem*)g_object_get_data (G_OBJECT (widget),
 
1801
                                                             "KatzeXbelItem");
 
1802
    GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
1803
    g_object_set (web_view, "uri", katze_xbel_bookmark_get_href (item), NULL);
 
1804
    gtk_widget_grab_focus (web_view);
 
1805
}
 
1806
 
 
1807
static void
 
1808
_midori_browser_create_bookmark_menu (MidoriBrowser* browser,
 
1809
                                      KatzeXbelItem* folder,
 
1810
                                      GtkWidget*     menu)
 
1811
{
 
1812
    guint n = katze_xbel_folder_get_n_items (folder);
 
1813
    guint i;
 
1814
    for (i = 0; i < n; i++)
 
1815
    {
 
1816
        KatzeXbelItem* item = katze_xbel_folder_get_nth_item (folder, i);
 
1817
        const gchar* title = katze_xbel_item_is_separator (item)
 
1818
            ? "" : katze_xbel_item_get_title (item);
 
1819
        /* const gchar* desc = katze_xbel_item_is_separator (item)
 
1820
            ? "" : katze_xbel_item_get_desc (item); */
 
1821
        GtkWidget* menuitem = NULL;
 
1822
        switch (katze_xbel_item_get_kind (item))
 
1823
        {
 
1824
        case KATZE_XBEL_ITEM_KIND_FOLDER:
 
1825
            // FIXME: what about katze_xbel_folder_is_folded?
 
1826
            menuitem = gtk_image_menu_item_new_with_label (title);
 
1827
            gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem),
 
1828
                gtk_image_new_from_stock (GTK_STOCK_DIRECTORY,
 
1829
                                          GTK_ICON_SIZE_MENU));
 
1830
            GtkWidget* _menu = gtk_menu_new ();
 
1831
            gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), _menu);
 
1832
            g_signal_connect (menuitem, "activate",
 
1833
                G_CALLBACK (midori_browser_bookmark_menu_folder_activate_cb),
 
1834
                browser);
 
1835
            g_object_set_data (G_OBJECT (menuitem), "KatzeXbelItem", item);
 
1836
            break;
 
1837
        case KATZE_XBEL_ITEM_KIND_BOOKMARK:
 
1838
            menuitem = gtk_image_menu_item_new_with_label (title);
 
1839
            GtkWidget* image = gtk_image_new_from_stock (STOCK_BOOKMARK,
 
1840
                                                         GTK_ICON_SIZE_MENU);
 
1841
            gtk_widget_show (image);
 
1842
            gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem),
 
1843
                                           image);
 
1844
            g_signal_connect (menuitem, "activate",
 
1845
                G_CALLBACK (midori_browser_menu_bookmarks_item_activate_cb),
 
1846
                browser);
 
1847
            g_object_set_data (G_OBJECT (menuitem), "KatzeXbelItem", item);
 
1848
            break;
 
1849
        case KATZE_XBEL_ITEM_KIND_SEPARATOR:
 
1850
            menuitem = gtk_separator_menu_item_new ();
 
1851
            break;
 
1852
        default:
 
1853
            g_warning ("Unknown xbel item kind");
 
1854
         }
 
1855
         gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
 
1856
         gtk_widget_show (menuitem);
 
1857
    }
 
1858
}
 
1859
 
 
1860
static void
 
1861
_action_bookmark_add_activate (GtkAction*     action,
 
1862
                               MidoriBrowser* browser)
 
1863
{
 
1864
    midori_browser_edit_bookmark_dialog_new (browser, NULL);
 
1865
}
 
1866
 
 
1867
static void
 
1868
_action_manage_search_engines_activate (GtkAction*     action,
 
1869
                                        MidoriBrowser* browser)
 
1870
{
 
1871
    // Show the Manage search engines dialog. Create it if necessary.
 
1872
    static GtkWidget* dialog;
 
1873
    if (GTK_IS_DIALOG (dialog))
 
1874
        gtk_window_present (GTK_WINDOW (dialog));
 
1875
    else
 
1876
    {
 
1877
        dialog = webSearch_manageSearchEngines_dialog_new (browser);
 
1878
        gtk_widget_show (dialog);
 
1879
    }
 
1880
}
 
1881
 
 
1882
static void
 
1883
_action_tab_previous_activate (GtkAction*     action,
 
1884
                               MidoriBrowser* browser)
 
1885
{
 
1886
    MidoriBrowserPrivate* priv = browser->priv;
 
1887
 
 
1888
    gint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
 
1889
    gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n - 1);
 
1890
}
 
1891
 
 
1892
static void
 
1893
_action_tab_next_activate (GtkAction*     action,
 
1894
                           MidoriBrowser* browser)
 
1895
{
 
1896
    MidoriBrowserPrivate* priv = browser->priv;
 
1897
 
 
1898
    // Advance one tab or jump to the first one if we are at the last one
 
1899
    gint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
 
1900
    if (n == gtk_notebook_get_n_pages (GTK_NOTEBOOK (priv->notebook)) - 1)
 
1901
        n = -1;
 
1902
    gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n + 1);
 
1903
}
 
1904
 
 
1905
static void
 
1906
midori_browser_window_menu_item_activate_cb (GtkWidget* widget,
 
1907
                                             GtkWidget* web_view)
 
1908
{
 
1909
    MidoriBrowser* browser = MIDORI_BROWSER (gtk_widget_get_toplevel (web_view));
 
1910
    if (!browser)
 
1911
    {
 
1912
        g_warning ("Orphaned web view");
 
1913
        return;
 
1914
    }
 
1915
 
 
1916
    MidoriBrowserPrivate* priv = browser->priv;
 
1917
 
 
1918
    GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, web_view);
 
1919
    guint n = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled);
 
1920
    gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n);
 
1921
}
 
1922
 
 
1923
static const gchar* credits_authors[] = {
 
1924
    "Christian Dywan <christian@twotoasts.de>", NULL };
 
1925
static const gchar* credits_documenters/*[]*/ = /*{
 
1926
    */NULL/* }*/;
 
1927
static const gchar* credits_artists[] = {
 
1928
    "Nancy Runge <nancy@twotoasts.de>", NULL };
 
1929
 
 
1930
static const gchar* license =
 
1931
 "This library is free software; you can redistribute it and/or\n"
 
1932
 "modify it under the terms of the GNU Lesser General Public\n"
 
1933
 "License as published by the Free Software Foundation; either\n"
 
1934
 "version 2.1 of the License, or (at your option) any later version.\n";
 
1935
 
 
1936
static void
 
1937
_action_about_activate (GtkAction*     action,
 
1938
                        MidoriBrowser* browser)
 
1939
{
 
1940
    gtk_show_about_dialog (GTK_WINDOW (browser),
 
1941
        "logo-icon-name", gtk_window_get_icon_name (GTK_WINDOW (browser)),
 
1942
        "name", PACKAGE_NAME,
 
1943
        "version", PACKAGE_VERSION,
 
1944
        "comments", _("A lightweight web browser."),
 
1945
        "copyright", "Copyright © 2007-2008 Christian Dywan",
 
1946
        "website", "http://software.twotoasts.de",
 
1947
        "authors", credits_authors,
 
1948
        "documenters", credits_documenters,
 
1949
        "artists", credits_artists,
 
1950
        "license", license,
 
1951
        "wrap-license", TRUE,
 
1952
        "translator-credits", _("translator-credits"),
 
1953
        NULL);
 
1954
}
 
1955
 
 
1956
static void
 
1957
midori_browser_location_changed_cb (GtkWidget*     widget,
 
1958
                                    MidoriBrowser* browser)
 
1959
{
 
1960
    // Preserve changes to the uri
 
1961
    /*const gchar* newUri = gtk_entry_get_text(GTK_ENTRY(widget));
 
1962
    katze_xbel_bookmark_set_href(browser->sessionItem, newUri);*/
 
1963
    // FIXME: If we want this feature, this is the wrong approach
 
1964
}
 
1965
 
 
1966
static void
 
1967
_action_panel_activate (GtkToggleAction* action,
 
1968
                        MidoriBrowser*   browser)
 
1969
{
 
1970
    MidoriBrowserPrivate* priv = browser->priv;
 
1971
 
 
1972
    gboolean active = gtk_toggle_action_get_active (action);
 
1973
    g_object_set (priv->settings, "show-panel", active, NULL);
 
1974
    sokoke_widget_set_visible (priv->panel, active);
 
1975
}
 
1976
 
 
1977
static void
 
1978
_action_open_in_panel_activate (GtkAction*     action,
 
1979
                                MidoriBrowser* browser)
 
1980
{
 
1981
    MidoriBrowserPrivate* priv = browser->priv;
 
1982
 
 
1983
    GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
1984
    const gchar* uri = midori_web_view_get_display_uri (MIDORI_WEB_VIEW (web_view));
 
1985
    // FIXME: Don't assign the uri here, update it properly while navigating
 
1986
    g_object_set (priv->settings, "last-pageholder-uri", uri, NULL);
 
1987
    gint n = midori_panel_page_num (MIDORI_PANEL (priv->panel),
 
1988
                                    priv->panel_pageholder);
 
1989
    midori_panel_set_current_page (MIDORI_PANEL (priv->panel), n);
 
1990
    gtk_widget_show (priv->panel);
 
1991
    g_object_set (priv->panel_pageholder, "uri", uri, NULL);
 
1992
}
 
1993
 
 
1994
 
 
1995
static void
 
1996
midori_panel_notify_position_cb (GObject*       object,
 
1997
                                 GParamSpec*    arg1,
 
1998
                                 MidoriBrowser* browser)
 
1999
{
 
2000
    MidoriBrowserPrivate* priv = browser->priv;
 
2001
 
 
2002
    gboolean position = gtk_paned_get_position (GTK_PANED (object));
 
2003
    g_object_set (priv->settings, "last-panel-position", position, NULL);
 
2004
}
 
2005
 
 
2006
static gboolean
 
2007
midori_panel_close_cb (MidoriPanel*   panel,
 
2008
                       MidoriBrowser* browser)
 
2009
{
 
2010
    _action_set_active (browser, "Panel", FALSE);
 
2011
    return FALSE;
 
2012
}
 
2013
 
 
2014
static void
 
2015
gtk_notebook_switch_page_cb (GtkWidget*       widget,
 
2016
                             GtkNotebookPage* page,
 
2017
                             guint            page_num,
 
2018
                             MidoriBrowser*   browser)
 
2019
{
 
2020
    MidoriBrowserPrivate* priv = browser->priv;
 
2021
 
 
2022
    GtkWidget* web_view = midori_browser_get_current_web_view (browser);
 
2023
    const gchar* uri = midori_web_view_get_display_uri (MIDORI_WEB_VIEW (web_view));
 
2024
    gtk_entry_set_text (GTK_ENTRY (priv->location), uri);
 
2025
    const gchar* title = midori_web_view_get_display_title (
 
2026
        MIDORI_WEB_VIEW (web_view));
 
2027
    gchar* window_title = g_strconcat (title, " - ",
 
2028
                                       g_get_application_name (), NULL);
 
2029
    gtk_window_set_title (GTK_WINDOW (browser), window_title);
 
2030
    g_free (window_title);
 
2031
    _midori_browser_set_statusbar_text (browser, NULL);
 
2032
    _midori_browser_update_interface (browser);
 
2033
}
 
2034
 
 
2035
static void
 
2036
_action_bookmark_open_activate (GtkAction*     action,
 
2037
                                MidoriBrowser* browser)
 
2038
{
 
2039
    MidoriBrowserPrivate* priv = browser->priv;
 
2040
 
 
2041
    GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks);
 
2042
    GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview);
 
2043
    if (selection)
 
2044
    {
 
2045
        GtkTreeModel* model;
 
2046
        GtkTreeIter iter;
 
2047
        if (gtk_tree_selection_get_selected (selection, &model, &iter))
 
2048
        {
 
2049
            KatzeXbelItem* item;
 
2050
            gtk_tree_model_get (model, &iter, 0, &item, -1);
 
2051
            if (katze_xbel_item_is_bookmark (item))
 
2052
                g_object_set (midori_browser_get_current_web_view (browser),
 
2053
                              "uri", katze_xbel_bookmark_get_href(item), NULL);
 
2054
        }
 
2055
    }
 
2056
}
 
2057
 
 
2058
static void
 
2059
_action_bookmark_open_tab_activate (GtkAction*     action,
 
2060
                                    MidoriBrowser* browser)
 
2061
{
 
2062
    MidoriBrowserPrivate* priv = browser->priv;
 
2063
 
 
2064
    GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks);
 
2065
    GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview);
 
2066
    if (selection)
 
2067
    {
 
2068
        GtkTreeModel* model;
 
2069
        GtkTreeIter iter;
 
2070
        if (gtk_tree_selection_get_selected (selection, &model, &iter))
 
2071
        {
 
2072
            KatzeXbelItem* item;
 
2073
            gtk_tree_model_get (model, &iter, 0, &item, -1);
 
2074
            if (katze_xbel_item_is_bookmark (item))
 
2075
            {
 
2076
                gint n = midori_browser_add_xbel_item (browser, item);
 
2077
                _midori_browser_set_current_page_smartly (browser, n);
 
2078
            }
 
2079
        }
 
2080
    }
 
2081
}
 
2082
 
 
2083
static void
 
2084
_action_bookmark_open_window_activate (GtkAction*     action,
 
2085
                                       MidoriBrowser* browser)
 
2086
{
 
2087
    MidoriBrowserPrivate* priv = browser->priv;
 
2088
 
 
2089
    GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks);
 
2090
    GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview);
 
2091
    if (selection)
 
2092
    {
 
2093
        GtkTreeModel* model;
 
2094
        GtkTreeIter iter;
 
2095
        if (gtk_tree_selection_get_selected (selection, &model, &iter))
 
2096
        {
 
2097
            KatzeXbelItem* item;
 
2098
            gtk_tree_model_get (model, &iter, 0, &item, -1);
 
2099
            if (katze_xbel_item_is_bookmark (item))
 
2100
            {
 
2101
                gint n = midori_browser_add_xbel_item (browser, item);
 
2102
                _midori_browser_set_current_page_smartly (browser, n);
 
2103
            }
 
2104
        }
 
2105
    }
 
2106
}
 
2107
 
 
2108
static void
 
2109
_action_bookmark_edit_activate (GtkAction*     action,
 
2110
                                MidoriBrowser* browser)
 
2111
{
 
2112
    MidoriBrowserPrivate* priv = browser->priv;
 
2113
 
 
2114
    GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks);
 
2115
    GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview);
 
2116
    if (selection)
 
2117
    {
 
2118
        GtkTreeModel* model;
 
2119
        GtkTreeIter iter;
 
2120
        if (gtk_tree_selection_get_selected (selection, &model, &iter))
 
2121
        {
 
2122
            KatzeXbelItem* item;
 
2123
            gtk_tree_model_get (model, &iter, 0, &item, -1);
 
2124
            if (!katze_xbel_item_is_separator (item))
 
2125
                midori_browser_edit_bookmark_dialog_new (browser, item);
 
2126
        }
 
2127
    }
 
2128
}
 
2129
 
 
2130
static void
 
2131
_action_undo_tab_close_activate (GtkAction*     action,
 
2132
                                 MidoriBrowser* browser)
 
2133
{
 
2134
    MidoriBrowserPrivate* priv = browser->priv;
 
2135
 
 
2136
    // Reopen the most recent trash item
 
2137
    KatzeXbelItem* item = midori_trash_get_nth_xbel_item (priv->trash, 0);
 
2138
    gint n = midori_browser_add_xbel_item (browser, item);
 
2139
    midori_browser_set_current_page (browser, n);
 
2140
    midori_trash_remove_nth_item (priv->trash, 0);
 
2141
    _midori_browser_update_actions (browser);
 
2142
}
 
2143
 
 
2144
static void
 
2145
_action_trash_empty_activate (GtkAction*     action,
 
2146
                              MidoriBrowser* browser)
 
2147
{
 
2148
    MidoriBrowserPrivate* priv = browser->priv;
 
2149
 
 
2150
    midori_trash_empty (priv->trash);
 
2151
    _midori_browser_update_actions (browser);
 
2152
}
 
2153
 
 
2154
static void
 
2155
_action_bookmark_delete_activate (GtkAction* action,
 
2156
                                  MidoriBrowser* browser)
 
2157
{
 
2158
    MidoriBrowserPrivate* priv = browser->priv;
 
2159
 
 
2160
    GtkTreeView* treeview = GTK_TREE_VIEW (priv->panel_bookmarks);
 
2161
    GtkTreeSelection* selection = gtk_tree_view_get_selection (treeview);
 
2162
    if (selection)
 
2163
    {
 
2164
        GtkTreeModel* model;
 
2165
        GtkTreeIter iter;
 
2166
        if (gtk_tree_selection_get_selected (selection, &model, &iter))
 
2167
        {
 
2168
            KatzeXbelItem* item;
 
2169
            gtk_tree_model_get (model, &iter, 0, &item, -1);
 
2170
            KatzeXbelItem* parent = katze_xbel_item_get_parent (item);
 
2171
            katze_xbel_folder_remove_item (parent, item);
 
2172
            katze_xbel_item_unref (item);
 
2173
        }
 
2174
    }
 
2175
}
 
2176
 
 
2177
static const GtkActionEntry entries[] = {
 
2178
 { "File", NULL, N_("_File") },
 
2179
 { "WindowNew", STOCK_WINDOW_NEW,
 
2180
   NULL, "<Ctrl>n",
 
2181
   N_("Open a new window"), G_CALLBACK (_action_window_new_activate) },
 
2182
 { "TabNew", STOCK_TAB_NEW,
 
2183
   NULL, "<Ctrl>t",
 
2184
   N_("Open a new tab"), G_CALLBACK (_action_tab_new_activate) },
 
2185
 { "Open", GTK_STOCK_OPEN,
 
2186
   NULL, "<Ctrl>o",
 
2187
   N_("Open a file"), G_CALLBACK (_action_open_activate) },
 
2188
 { "SaveAs", GTK_STOCK_SAVE_AS,
 
2189
   NULL, "<Ctrl>s",
 
2190
   N_("Save to a file"), NULL/*G_CALLBACK (_action_saveas_activate)*/ },
 
2191
 { "TabClose", NULL,
 
2192
   N_("_Close Tab"), "<Ctrl>w",
 
2193
   N_("Close the current tab"), G_CALLBACK (_action_tab_close_activate) },
 
2194
 { "WindowClose", NULL,
 
2195
   N_("C_lose Window"), "<Ctrl><Shift>w",
 
2196
   N_("Close this window"), G_CALLBACK (_action_window_close_activate) },
 
2197
 { "PageSetup", GTK_STOCK_PROPERTIES,
 
2198
   N_("Pa_ge Setup"), "",
 
2199
   "Configure your print settings", NULL/*G_CALLBACK (_action_page_setup_activate)*/ },
 
2200
 { "PrintPreview", GTK_STOCK_PRINT_PREVIEW,
 
2201
   NULL, "",
 
2202
   N_("Show a preview of the printed page"), NULL/*G_CALLBACK (_action_print_preview_activate)*/ },
 
2203
 { "Print", GTK_STOCK_PRINT,
 
2204
   NULL, "<Ctrl>p",
 
2205
   N_("Print the current page"), G_CALLBACK (_action_print_activate) },
 
2206
 { "Quit", GTK_STOCK_QUIT,
 
2207
   NULL, "<Ctrl>q",
 
2208
   N_("Quit the application"), G_CALLBACK (_action_quit_activate) },
 
2209
 
 
2210
 { "Edit", NULL, N_("_Edit"), NULL, NULL, G_CALLBACK (_action_edit_activate) },
 
2211
 { "Undo", GTK_STOCK_UNDO,
 
2212
   NULL, "<Ctrl>z",
 
2213
   N_("Undo the last modification"), NULL/*G_CALLBACK (_action_undo_activate)*/ },
 
2214
 { "Redo", GTK_STOCK_REDO,
 
2215
   NULL, "<Ctrl><Shift>z",
 
2216
   N_("Redo the last modification"), NULL/*G_CALLBACK (_action_redo_activate)*/ },
 
2217
 { "Cut", GTK_STOCK_CUT,
 
2218
   NULL, "<Ctrl>x",
 
2219
   N_("Cut the selected text"), G_CALLBACK (_action_cut_activate) },
 
2220
 { "Copy", GTK_STOCK_COPY,
 
2221
   NULL, "<Ctrl>c",
 
2222
   N_("Copy the selected text"), G_CALLBACK (_action_copy_activate) },
 
2223
 { "Copy_", GTK_STOCK_COPY,
 
2224
   NULL, "<Ctrl>c",
 
2225
   N_("Copy the selected text"), G_CALLBACK (_action_copy_activate) },
 
2226
 { "Paste", GTK_STOCK_PASTE,
 
2227
   NULL, "<Ctrl>v",
 
2228
   N_("Paste text from the clipboard"), G_CALLBACK (_action_paste_activate) },
 
2229
 { "Delete", GTK_STOCK_DELETE,
 
2230
   NULL, NULL,
 
2231
   N_("Delete the selected text"), G_CALLBACK (_action_delete_activate) },
 
2232
 { "SelectAll", GTK_STOCK_SELECT_ALL,
 
2233
   NULL, "<Ctrl>a",
 
2234
   N_("Select all text"), G_CALLBACK (_action_select_all_activate) },
 
2235
 { "Find", GTK_STOCK_FIND,
 
2236
   NULL, "<Ctrl>f",
 
2237
   N_("Find a word or phrase in the page"), G_CALLBACK (_action_find_activate) },
 
2238
 { "FindNext", GTK_STOCK_GO_FORWARD,
 
2239
   N_("Find _Next"), "<Ctrl>g",
 
2240
   N_("Find the next occurrence of a word or phrase"), G_CALLBACK (_action_find_next_activate) },
 
2241
 { "FindPrevious", GTK_STOCK_GO_BACK,
 
2242
   N_("Find _Previous"), "<Ctrl><Shift>g",
 
2243
   N_("Find the previous occurrence of a word or phrase"), G_CALLBACK (_action_find_previous_activate) },
 
2244
 { "FindQuick", GTK_STOCK_FIND,
 
2245
   N_("_Quick Find"), "period",
 
2246
   N_("Quickly jump to a word or phrase"), NULL/*G_CALLBACK (_action_find_quick_activate)*/ },
 
2247
 { "Preferences", GTK_STOCK_PREFERENCES,
 
2248
   NULL, "<Ctrl><Alt>p",
 
2249
   N_("Configure the application preferences"), G_CALLBACK (_action_preferences_activate) },
 
2250
 
 
2251
 { "View", NULL, N_("_View") },
 
2252
 { "Toolbars", NULL, N_("_Toolbars") },
 
2253
 { "Reload", GTK_STOCK_REFRESH,
 
2254
   NULL, "<Ctrl>r",
 
2255
   N_("Reload the current page"), G_CALLBACK (_action_reload_stop_activate) },
 
2256
 { "Stop", GTK_STOCK_STOP,
 
2257
   NULL, "Escape",
 
2258
   N_("Stop loading the current page"), G_CALLBACK (_action_reload_stop_activate) },
 
2259
 { "ReloadStop", GTK_STOCK_STOP,
 
2260
   NULL, "<Ctrl>r",
 
2261
   N_("Reload the current page"), G_CALLBACK (_action_reload_stop_activate) },
 
2262
 { "ZoomIn", GTK_STOCK_ZOOM_IN,
 
2263
   NULL, "<Ctrl>plus",
 
2264
   N_("Increase the zoom level"), G_CALLBACK (_action_zoom_in_activate) },
 
2265
 { "ZoomOut", GTK_STOCK_ZOOM_OUT,
 
2266
   NULL, "<Ctrl>minus",
 
2267
   N_("Decrease the zoom level"), G_CALLBACK (_action_zoom_out_activate) },
 
2268
 { "ZoomNormal", GTK_STOCK_ZOOM_100,
 
2269
   NULL, "<Ctrl>0",
 
2270
   N_("Reset the zoom level"), G_CALLBACK (_action_zoom_normal_activate) },
 
2271
 { "SourceView", NULL,
 
2272
   N_("View Source"), "",
 
2273
   N_("View the source code of the page"), /*G_CALLBACK (_action_source_view_activate)*/ },
 
2274
 { "SelectionSourceView", NULL,
 
2275
    N_("View Selection Source"), "",
 
2276
    N_("View the source code of the selection"), NULL/*G_CALLBACK (_action_selection_source_view_activate)*/ },
 
2277
 { "Fullscreen", GTK_STOCK_FULLSCREEN,
 
2278
   NULL, "F11",
 
2279
   N_("Toggle fullscreen view"), G_CALLBACK (_action_fullscreen_activate) },
 
2280
 
 
2281
 { "Go", NULL, N_("_Go") },
 
2282
 { "Back", GTK_STOCK_GO_BACK,
 
2283
   NULL, "<Alt>Left",
 
2284
   N_("Go back to the previous page"), G_CALLBACK (_action_back_activate) },
 
2285
 { "Forward", GTK_STOCK_GO_FORWARD,
 
2286
   NULL, "<Alt>Right",
 
2287
   N_("Go forward to the next page"), G_CALLBACK (_action_forward_activate) },
 
2288
 { "Homepage", STOCK_HOMEPAGE,
 
2289
   NULL, "<Alt>Home",
 
2290
   N_("Go to your homepage"), G_CALLBACK (_action_homepage_activate) },
 
2291
 { "Location", GTK_STOCK_JUMP_TO,
 
2292
   N_("Location..."), "<Ctrl>l",
 
2293
   N_("Open a particular location"), G_CALLBACK (_action_location_activate) },
 
2294
 { "Search", GTK_STOCK_FIND,
 
2295
   N_("Web Search..."), "<Ctrl><Shift>f",
 
2296
   N_("Run a web search"), G_CALLBACK (_action_search_activate) },
 
2297
 { "OpenInPageholder", GTK_STOCK_JUMP_TO,
 
2298
   N_("Open in Page_holder..."), "",
 
2299
   N_("Open the current page in the pageholder"), G_CALLBACK (_action_open_in_panel_activate) },
 
2300
 { "Trash", STOCK_USER_TRASH,
 
2301
   N_("Closed Tabs and Windows"), "",
 
2302
   N_("Reopen a previously closed tab or window"), NULL },
 
2303
 { "TrashEmpty", GTK_STOCK_CLEAR,
 
2304
   N_("Empty Trash"), "",
 
2305
   N_("Delete the contents of the trash"), G_CALLBACK (_action_trash_empty_activate) },
 
2306
 { "UndoTabClose", GTK_STOCK_UNDELETE,
 
2307
   N_("Undo Close Tab"), "",
 
2308
   N_("Open the last closed tab"), G_CALLBACK (_action_undo_tab_close_activate) },
 
2309
 
 
2310
 { "Bookmarks", NULL, N_("_Bookmarks") },
 
2311
 { "BookmarkAdd", STOCK_BOOKMARK_ADD,
 
2312
   NULL, "<Ctrl>d",
 
2313
   N_("Add a new bookmark"), G_CALLBACK (_action_bookmark_add_activate) },
 
2314
 { "BookmarksManage", NULL,
 
2315
   N_("_Manage Bookmarks"), "<Ctrl>b",
 
2316
   N_("Add, edit and remove bookmarks..."), NULL/*G_CALLBACK (_action_bookmarks_manage_activate)*/ },
 
2317
 { "BookmarkOpen", GTK_STOCK_OPEN,
 
2318
   NULL, "",
 
2319
   N_("Open the selected bookmark"), G_CALLBACK (_action_bookmark_open_activate) },
 
2320
 { "BookmarkOpenTab", STOCK_TAB_NEW,
 
2321
   N_("Open in New _Tab"), "",
 
2322
   N_("Open the selected bookmark in a new tab"), G_CALLBACK (_action_bookmark_open_tab_activate) },
 
2323
 { "BookmarkOpenWindow", STOCK_WINDOW_NEW,
 
2324
   N_("Open in New _Window"), "",
 
2325
   N_("Open the selected bookmark in a new window"), G_CALLBACK (_action_bookmark_open_window_activate) },
 
2326
 { "BookmarkEdit", GTK_STOCK_EDIT,
 
2327
   NULL, "",
 
2328
   N_("Edit the selected bookmark"), G_CALLBACK (_action_bookmark_edit_activate) },
 
2329
 { "BookmarkDelete", GTK_STOCK_DELETE,
 
2330
   NULL, "",
 
2331
   N_("Delete the selected bookmark"), G_CALLBACK (_action_bookmark_delete_activate) },
 
2332
 
 
2333
 { "Tools", NULL, N_("_Tools") },
 
2334
 { "ManageSearchEngines", GTK_STOCK_PROPERTIES,
 
2335
   N_("_Manage Search Engines"), "<Ctrl><Alt>s",
 
2336
   N_("Add, edit and remove search engines..."),
 
2337
   G_CALLBACK (_action_manage_search_engines_activate) },
 
2338
 
 
2339
 { "Window", NULL, N_("_Window") },
 
2340
 { "TabPrevious", GTK_STOCK_GO_BACK,
 
2341
   N_("_Previous Tab"), "<Ctrl>Page_Up",
 
2342
   N_("Switch to the previous tab"), G_CALLBACK (_action_tab_previous_activate) },
 
2343
 { "TabNext", GTK_STOCK_GO_FORWARD,
 
2344
   N_("_Next Tab"), "<Ctrl>Page_Down",
 
2345
   N_("Switch to the next tab"), G_CALLBACK (_action_tab_next_activate) },
 
2346
 { "TabOverview", NULL,
 
2347
   N_("Tab _Overview"), "",
 
2348
   N_("Show an overview of all open tabs"), NULL/*G_CALLBACK (_action_tab_overview_activate)*/ },
 
2349
 
 
2350
 { "Help", NULL, N_("_Help") },
 
2351
 { "HelpContents", GTK_STOCK_HELP,
 
2352
   N_("_Contents"), "F1",
 
2353
   N_("Show the documentation"), NULL/*G_CALLBACK (_action_help_contents_activate)*/ },
 
2354
 { "About", GTK_STOCK_ABOUT,
 
2355
   NULL, "",
 
2356
   N_("Show information about the program"), G_CALLBACK (_action_about_activate) },
 
2357
 };
 
2358
 static const guint entries_n = G_N_ELEMENTS (entries);
 
2359
 
 
2360
static const GtkToggleActionEntry toggle_entries[] = {
 
2361
 { "PrivateBrowsing", NULL,
 
2362
   N_("P_rivate Browsing"), "",
 
2363
   N_("Don't save any private data while browsing"), NULL/*G_CALLBACK (_action_private_browsing_activate)*/,
 
2364
   FALSE },
 
2365
 { "WorkOffline", GTK_STOCK_DISCONNECT,
 
2366
   N_("_Work Offline"), "",
 
2367
   N_("Work without a network connection"), NULL/*G_CALLBACK (_action_work_offline_activate)*/,
 
2368
   FALSE },
 
2369
 
 
2370
 { "Navigationbar", NULL,
 
2371
   N_("_Navigationbar"), "",
 
2372
   N_("Show navigationbar"), G_CALLBACK (_action_navigationbar_activate),
 
2373
   FALSE },
 
2374
 { "Panel", NULL,
 
2375
   N_("Side_panel"), "F9",
 
2376
   N_("Show sidepanel"), G_CALLBACK (_action_panel_activate),
 
2377
   FALSE },
 
2378
 { "Bookmarkbar", NULL,
 
2379
   N_("_Bookmarkbar"), "",
 
2380
   N_("Show bookmarkbar"), G_CALLBACK (_action_bookmarkbar_activate),
 
2381
   FALSE },
 
2382
 { "Transferbar", NULL,
 
2383
   N_("_Transferbar"), "",
 
2384
   N_("Show transferbar"), NULL/*G_CALLBACK (_action_transferbar_activate)*/,
 
2385
   FALSE },
 
2386
 { "Statusbar", NULL,
 
2387
   N_("_Statusbar"), "",
 
2388
   N_("Show statusbar"), G_CALLBACK (_action_statusbar_activate),
 
2389
   FALSE },
 
2390
 };
 
2391
 static const guint toggle_entries_n = G_N_ELEMENTS (toggle_entries);
 
2392
 
 
2393
static void
 
2394
midori_browser_window_state_event_cb (MidoriBrowser*       browser,
 
2395
                                      GdkEventWindowState* event)
 
2396
{
 
2397
    MidoriBrowserPrivate* priv = browser->priv;
 
2398
 
 
2399
    if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN)
 
2400
    {
 
2401
        if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)
 
2402
        {
 
2403
            gtk_widget_hide (priv->menubar);
 
2404
            g_object_set (priv->button_fullscreen,
 
2405
                          "stock-id", GTK_STOCK_LEAVE_FULLSCREEN, NULL);
 
2406
            gtk_widget_show (priv->button_fullscreen);
 
2407
        }
 
2408
        else
 
2409
        {
 
2410
            gtk_widget_show (priv->menubar);
 
2411
            gtk_widget_hide (priv->button_fullscreen);
 
2412
            g_object_set (priv->button_fullscreen,
 
2413
                          "stock-id", GTK_STOCK_FULLSCREEN, NULL);
 
2414
        }
 
2415
    }
 
2416
}
 
2417
 
 
2418
static void
 
2419
midori_browser_size_allocate_cb (MidoriBrowser* browser,
 
2420
                                 GtkAllocation* allocation)
 
2421
{
 
2422
    MidoriBrowserPrivate* priv = browser->priv;
 
2423
    GtkWidget* widget = GTK_WIDGET (browser);
 
2424
 
 
2425
    if (GTK_WIDGET_REALIZED (widget))
 
2426
    {
 
2427
        GdkWindowState state = gdk_window_get_state (widget->window);
 
2428
        if (!(state & (GDK_WINDOW_STATE_MAXIMIZED | GDK_WINDOW_STATE_FULLSCREEN)))
 
2429
        {
 
2430
            g_object_set (priv->settings,
 
2431
                          "last-window-width", allocation->width,
 
2432
                          "last-window-height", allocation->height, NULL);
 
2433
        }
 
2434
    }
 
2435
}
 
2436
 
 
2437
static void
 
2438
midori_browser_destroy_cb (MidoriBrowser* browser)
 
2439
{
 
2440
    MidoriBrowserPrivate* priv = browser->priv;
 
2441
 
 
2442
    // Destroy tabs first, so widgets can still see window elements on destroy
 
2443
    gtk_container_foreach (GTK_CONTAINER (priv->notebook),
 
2444
                           (GtkCallback) gtk_widget_destroy, NULL);
 
2445
}
 
2446
 
 
2447
static const gchar* ui_markup =
 
2448
 "<ui>"
 
2449
  "<menubar>"
 
2450
   "<menu action='File'>"
 
2451
    "<menuitem action='WindowNew'/>"
 
2452
    "<menuitem action='TabNew'/>"
 
2453
    "<separator/>"
 
2454
    "<menuitem action='Open'/>"
 
2455
    "<separator/>"
 
2456
    "<menuitem action='SaveAs'/>"
 
2457
    "<separator/>"
 
2458
    "<menuitem action='TabClose'/>"
 
2459
    "<menuitem action='WindowClose'/>"
 
2460
    "<separator/>"
 
2461
    "<menuitem action='PageSetup'/>"
 
2462
    "<menuitem action='PrintPreview'/>"
 
2463
    "<menuitem action='Print'/>"
 
2464
    "<separator/>"
 
2465
    "<menuitem action='PrivateBrowsing'/>"
 
2466
    "<menuitem action='WorkOffline'/>"
 
2467
    "<separator/>"
 
2468
    "<menuitem action='Quit'/>"
 
2469
   "</menu>"
 
2470
   "<menu action='Edit'>"
 
2471
    "<menuitem action='Undo'/>"
 
2472
    "<menuitem action='Redo'/>"
 
2473
    "<separator/>"
 
2474
    "<menuitem action='Cut'/>"
 
2475
    "<menuitem action='Copy'/>"
 
2476
    "<menuitem action='Paste'/>"
 
2477
    "<menuitem action='Delete'/>"
 
2478
    "<separator/>"
 
2479
    "<menuitem action='SelectAll'/>"
 
2480
    "<separator/>"
 
2481
    "<menuitem action='Preferences'/>"
 
2482
   "</menu>"
 
2483
   "<menu action='View'>"
 
2484
    "<menu action='Toolbars'>"
 
2485
     "<menuitem action='Navigationbar'/>"
 
2486
     "<menuitem action='Bookmarkbar'/>"
 
2487
     "<menuitem action='Transferbar'/>"
 
2488
     "<menuitem action='Statusbar'/>"
 
2489
    "</menu>"
 
2490
    "<menuitem action='Panel'/>"
 
2491
    "<separator/>"
 
2492
    "<menuitem action='Reload'/>"
 
2493
    "<menuitem action='Stop'/>"
 
2494
    "<separator/>"
 
2495
    "<menuitem action='ZoomIn'/>"
 
2496
    "<menuitem action='ZoomOut'/>"
 
2497
    "<menuitem action='ZoomNormal'/>"
 
2498
    "<separator/>"
 
2499
    "<menuitem action='SourceView'/>"
 
2500
    "<menuitem action='Fullscreen'/>"
 
2501
   "</menu>"
 
2502
   "<menu action='Go'>"
 
2503
    "<menuitem action='Back'/>"
 
2504
    "<menuitem action='Forward'/>"
 
2505
    "<menuitem action='Homepage'/>"
 
2506
    "<menuitem action='Location'/>"
 
2507
    "<menuitem action='Search'/>"
 
2508
    "<menuitem action='OpenInPageholder'/>"
 
2509
    "<menu action='Trash'>"
 
2510
    // Closed tabs shall be prepended here
 
2511
     "<separator/>"
 
2512
     "<menuitem action='TrashEmpty'/>"
 
2513
    "</menu>"
 
2514
    "<menuitem action='UndoTabClose'/>"
 
2515
    "<separator/>"
 
2516
    "<menuitem action='Find'/>"
 
2517
    "<menuitem action='FindNext'/>"
 
2518
    "<menuitem action='FindPrevious'/>"
 
2519
   "</menu>"
 
2520
   "<menu action='Bookmarks'>"
 
2521
    "<menuitem action='BookmarkAdd'/>"
 
2522
    "<menuitem action='BookmarksManage'/>"
 
2523
    "<separator/>"
 
2524
    // Bookmarks shall be appended here
 
2525
   "</menu>"
 
2526
   "<menu action='Tools'>"
 
2527
    "<menuitem action='ManageSearchEngines'/>"
 
2528
    // Panel items shall be appended here
 
2529
   "</menu>"
 
2530
   "<menu action='Window'>"
 
2531
    "<menuitem action='TabPrevious'/>"
 
2532
    "<menuitem action='TabNext'/>"
 
2533
    "<menuitem action='TabOverview'/>"
 
2534
    "<separator/>"
 
2535
    // All open tabs shall be appended here
 
2536
   "</menu>"
 
2537
   "<menu action='Help'>"
 
2538
    "<menuitem action='HelpContents'/>"
 
2539
    "<menuitem action='About'/>"
 
2540
   "</menu>"
 
2541
  "</menubar>"
 
2542
  "<toolbar name='toolbar_navigation'>"
 
2543
   "<toolitem action='TabNew'/>"
 
2544
   "<toolitem action='Back'/>"
 
2545
   "<toolitem action='Forward'/>"
 
2546
   "<toolitem action='ReloadStop'/>"
 
2547
   "<toolitem action='Homepage'/>"
 
2548
   "<placeholder name='Location'/>"
 
2549
   "<placeholder name='Search'/>"
 
2550
   "<placeholder name='TabTrash'/>"
 
2551
  "</toolbar>"
 
2552
  "<toolbar name='toolbar_bookmarks'>"
 
2553
   "<toolitem action='BookmarkAdd'/>"
 
2554
   "<toolitem action='BookmarkEdit'/>"
 
2555
   "<toolitem action='BookmarkDelete'/>"
 
2556
  "</toolbar>"
 
2557
  "<popup name='popup_bookmark'>"
 
2558
   "<menuitem action='BookmarkOpen'/>"
 
2559
   "<menuitem action='BookmarkOpenTab'/>"
 
2560
   "<menuitem action='BookmarkOpenWindow'/>"
 
2561
   "<separator/>"
 
2562
   "<menuitem action='BookmarkEdit'/>"
 
2563
   "<menuitem action='BookmarkDelete'/>"
 
2564
  "</popup>"
 
2565
 "</ui>";
 
2566
 
 
2567
static void
 
2568
midori_browser_realize_cb (GtkStyle* style, MidoriBrowser* browser)
 
2569
{
 
2570
    GdkScreen* screen = gtk_widget_get_screen (GTK_WIDGET (browser));
 
2571
    if (screen)
 
2572
    {
 
2573
        GtkIconTheme* icon_theme = gtk_icon_theme_get_for_screen (screen);
 
2574
        if (gtk_icon_theme_has_icon (icon_theme, "midori"))
 
2575
            gtk_window_set_icon_name (GTK_WINDOW (browser), "midori");
 
2576
        else
 
2577
            gtk_window_set_icon_name (GTK_WINDOW (browser), "web-browser");
 
2578
    }
 
2579
}
 
2580
 
 
2581
static void
 
2582
midori_browser_init (MidoriBrowser* browser)
 
2583
{
 
2584
    browser->priv = MIDORI_BROWSER_GET_PRIVATE (browser);
 
2585
 
 
2586
    MidoriBrowserPrivate* priv = browser->priv;
 
2587
 
 
2588
    // Setup the window metrics
 
2589
    g_signal_connect (browser, "realize",
 
2590
                      G_CALLBACK (midori_browser_realize_cb), browser);
 
2591
    g_signal_connect (browser, "window-state-event",
 
2592
                      G_CALLBACK (midori_browser_window_state_event_cb), NULL);
 
2593
    g_signal_connect (browser, "size-allocate",
 
2594
                      G_CALLBACK (midori_browser_size_allocate_cb), NULL);
 
2595
    g_signal_connect (browser, "destroy",
 
2596
                      G_CALLBACK (midori_browser_destroy_cb), NULL);
 
2597
    gtk_window_set_icon_name (GTK_WINDOW (browser), "web-browser");
 
2598
    gtk_window_set_title (GTK_WINDOW (browser), g_get_application_name ());
 
2599
    GtkWidget* vbox = gtk_vbox_new (FALSE, 0);
 
2600
    gtk_container_add (GTK_CONTAINER (browser), vbox);
 
2601
    gtk_widget_show (vbox);
 
2602
 
 
2603
    // Let us see some ui manager magic
 
2604
    priv->action_group = gtk_action_group_new ("Browser");
 
2605
    gtk_action_group_set_translation_domain (priv->action_group, GETTEXT_PACKAGE);
 
2606
    gtk_action_group_add_actions (priv->action_group,
 
2607
                                  entries, entries_n, browser);
 
2608
    gtk_action_group_add_toggle_actions (priv->action_group,
 
2609
        toggle_entries, toggle_entries_n, browser);
 
2610
    GtkUIManager* ui_manager = gtk_ui_manager_new ();
 
2611
    gtk_ui_manager_insert_action_group (ui_manager, priv->action_group, 0);
 
2612
    gtk_window_add_accel_group (GTK_WINDOW (browser),
 
2613
                                gtk_ui_manager_get_accel_group (ui_manager));
 
2614
 
 
2615
    GError* error = NULL;
 
2616
    if (!gtk_ui_manager_add_ui_from_string(ui_manager, ui_markup, -1, &error))
 
2617
    {
 
2618
        // TODO: Should this be a message dialog? When does this happen?
 
2619
        g_message ("User interface couldn't be created: %s", error->message);
 
2620
        g_error_free (error);
 
2621
    }
 
2622
 
 
2623
    GtkAction* action;
 
2624
    // Make all actions except toplevel menus which lack a callback insensitive
 
2625
    // This will vanish once all actions are implemented
 
2626
    guint i;
 
2627
    for (i = 0; i < entries_n; i++)
 
2628
    {
 
2629
        action = gtk_action_group_get_action(priv->action_group,
 
2630
                                             entries[i].name);
 
2631
        gtk_action_set_sensitive (action,
 
2632
                                  entries[i].callback || !entries[i].tooltip);
 
2633
    }
 
2634
    for (i = 0; i < toggle_entries_n; i++)
 
2635
    {
 
2636
        action = gtk_action_group_get_action (priv->action_group,
 
2637
                                              toggle_entries[i].name);
 
2638
        gtk_action_set_sensitive (action, toggle_entries[i].callback != NULL);
 
2639
    }
 
2640
 
 
2641
    //_action_set_active(browser, "Transferbar", config->toolbarTransfers);
 
2642
 
 
2643
    // Create the menubar
 
2644
    priv->menubar = gtk_ui_manager_get_widget (ui_manager, "/menubar");
 
2645
    GtkWidget* menuitem = gtk_menu_item_new ();
 
2646
    gtk_widget_show (menuitem);
 
2647
    priv->throbber = katze_throbber_new();
 
2648
    gtk_widget_show(priv->throbber);
 
2649
    gtk_container_add (GTK_CONTAINER (menuitem), priv->throbber);
 
2650
    gtk_widget_set_sensitive (menuitem, FALSE);
 
2651
    gtk_menu_item_set_right_justified (GTK_MENU_ITEM (menuitem), TRUE);
 
2652
    gtk_menu_shell_append (GTK_MENU_SHELL (priv->menubar), menuitem);
 
2653
    gtk_box_pack_start (GTK_BOX (vbox), priv->menubar, FALSE, FALSE, 0);
 
2654
    menuitem = gtk_ui_manager_get_widget (ui_manager, "/menubar/Go/Trash");
 
2655
    g_signal_connect (menuitem, "activate",
 
2656
                      G_CALLBACK (midori_browser_menu_trash_activate_cb),
 
2657
                      browser);
 
2658
    priv->menu_bookmarks = gtk_menu_item_get_submenu (GTK_MENU_ITEM (
 
2659
        gtk_ui_manager_get_widget (ui_manager, "/menubar/Bookmarks")));
 
2660
    menuitem = gtk_separator_menu_item_new ();
 
2661
    gtk_widget_show (menuitem);
 
2662
    gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_bookmarks), menuitem);
 
2663
    priv->popup_bookmark = gtk_ui_manager_get_widget (
 
2664
        ui_manager, "/popup_bookmark");
 
2665
    g_object_ref (priv->popup_bookmark);
 
2666
    priv->menu_tools = gtk_menu_item_get_submenu (GTK_MENU_ITEM (
 
2667
        gtk_ui_manager_get_widget (ui_manager, "/menubar/Tools")));
 
2668
    menuitem = gtk_separator_menu_item_new();
 
2669
    gtk_widget_show (menuitem);
 
2670
    gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_tools), menuitem);
 
2671
    priv->menu_window = gtk_menu_item_get_submenu (GTK_MENU_ITEM (
 
2672
        gtk_ui_manager_get_widget (ui_manager, "/menubar/Window")));
 
2673
    menuitem = gtk_separator_menu_item_new();
 
2674
    gtk_widget_show (menuitem);
 
2675
    gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_window), menuitem);
 
2676
    gtk_widget_show (priv->menubar);
 
2677
    _action_set_sensitive (browser, "PrivateBrowsing", FALSE);
 
2678
    _action_set_sensitive (browser, "WorkOffline", FALSE);
 
2679
 
 
2680
    // Create the navigationbar
 
2681
    priv->navigationbar = gtk_ui_manager_get_widget (
 
2682
        ui_manager, "/toolbar_navigation");
 
2683
    // FIXME: settings should be connected with screen changes
 
2684
    GtkSettings* gtk_settings = gtk_widget_get_settings (GTK_WIDGET (browser));
 
2685
    if (gtk_settings)
 
2686
        g_signal_connect (gtk_settings, "notify::gtk-toolbar-style",
 
2687
            G_CALLBACK (midori_browser_navigationbar_notify_style_cb), browser);
 
2688
    gtk_toolbar_set_show_arrow (GTK_TOOLBAR (priv->navigationbar), TRUE);
 
2689
    gtk_box_pack_start (GTK_BOX (vbox), priv->navigationbar, FALSE, FALSE, 0);
 
2690
    priv->button_tab_new = gtk_ui_manager_get_widget (
 
2691
        ui_manager, "/toolbar_navigation/TabNew");
 
2692
    g_object_set (_action_by_name (browser, "Back"), "is-important", TRUE, NULL);
 
2693
    priv->button_homepage = gtk_ui_manager_get_widget (
 
2694
        ui_manager, "/toolbar_navigation/Homepage");
 
2695
 
 
2696
    // Location
 
2697
    priv->location = sexy_icon_entry_new ();
 
2698
    sokoke_entry_setup_completion (GTK_ENTRY (priv->location));
 
2699
    priv->location_icon = gtk_image_new ();
 
2700
    sexy_icon_entry_set_icon (SEXY_ICON_ENTRY (priv->location)
 
2701
     , SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE (priv->location_icon));
 
2702
    sexy_icon_entry_add_clear_button (SEXY_ICON_ENTRY (priv->location));
 
2703
    g_object_connect (priv->location,
 
2704
                      "signal::key-press-event",
 
2705
                      midori_browser_location_key_press_event_cb, browser,
 
2706
                      "signal::focus-out-event",
 
2707
                      midori_browser_location_focus_out_event_cb, browser,
 
2708
                      "signal::changed",
 
2709
                      midori_browser_location_changed_cb, browser,
 
2710
                      NULL);
 
2711
    GtkToolItem* toolitem = gtk_tool_item_new ();
 
2712
    gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE);
 
2713
    gtk_container_add (GTK_CONTAINER(toolitem), priv->location);
 
2714
    gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar), toolitem, -1);
 
2715
 
 
2716
    // Search
 
2717
    priv->search = sexy_icon_entry_new ();
 
2718
    sexy_icon_entry_set_icon_highlight (SEXY_ICON_ENTRY (priv->search),
 
2719
                                        SEXY_ICON_ENTRY_PRIMARY, TRUE);
 
2720
    // TODO: Make this actively resizable or enlarge to fit contents?
 
2721
    // FIXME: The interface is somewhat awkward and ought to be rethought
 
2722
    // TODO: Display "show in context menu" search engines as "completion actions"
 
2723
    sokoke_entry_setup_completion (GTK_ENTRY (priv->search));
 
2724
    g_object_connect (priv->search,
 
2725
                      "signal::icon-released",
 
2726
                      on_webSearch_icon_released, browser,
 
2727
                      "signal::key-press-event",
 
2728
                      on_webSearch_key_down, browser,
 
2729
                      "signal::scroll-event",
 
2730
                      on_webSearch_scroll, browser,
 
2731
                      "signal::activate",
 
2732
                      on_webSearch_activate, browser,
 
2733
                      "signal::focus-out-event",
 
2734
                      midori_browser_search_focus_out_event_cb, browser,
 
2735
                      NULL);
 
2736
    toolitem = gtk_tool_item_new ();
 
2737
    gtk_container_add (GTK_CONTAINER (toolitem), priv->search);
 
2738
    gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar), toolitem, -1);
 
2739
    action = gtk_action_group_get_action (priv->action_group, "Trash");
 
2740
    priv->button_trash = gtk_action_create_tool_item (action);
 
2741
    g_signal_connect (priv->button_trash, "clicked",
 
2742
                      G_CALLBACK (midori_browser_menu_trash_activate_cb), browser);
 
2743
    gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar),
 
2744
                        GTK_TOOL_ITEM (priv->button_trash), -1);
 
2745
    sokoke_container_show_children (GTK_CONTAINER (priv->navigationbar));
 
2746
    action = gtk_action_group_get_action (priv->action_group, "Fullscreen");
 
2747
    priv->button_fullscreen = gtk_action_create_tool_item (action);
 
2748
    gtk_widget_hide (priv->button_fullscreen);
 
2749
    g_signal_connect (priv->button_fullscreen, "clicked",
 
2750
                      G_CALLBACK (_action_fullscreen_activate), browser);
 
2751
    gtk_toolbar_insert (GTK_TOOLBAR (priv->navigationbar),
 
2752
                        GTK_TOOL_ITEM (priv->button_fullscreen), -1);
 
2753
 
 
2754
    // Bookmarkbar
 
2755
    priv->bookmarkbar = gtk_toolbar_new ();
 
2756
    gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->bookmarkbar),
 
2757
                               GTK_ICON_SIZE_MENU);
 
2758
    gtk_toolbar_set_style (GTK_TOOLBAR (priv->bookmarkbar),
 
2759
                           GTK_TOOLBAR_BOTH_HORIZ);
 
2760
    _midori_browser_create_bookmark_menu (browser, bookmarks,
 
2761
                                          priv->menu_bookmarks);
 
2762
    for (i = 0; i < katze_xbel_folder_get_n_items (bookmarks); i++)
 
2763
    {
 
2764
        KatzeXbelItem* item = katze_xbel_folder_get_nth_item (bookmarks, i);
 
2765
        const gchar* title = katze_xbel_item_is_separator (item)
 
2766
         ? "" : katze_xbel_item_get_title (item);
 
2767
        const gchar* desc = katze_xbel_item_is_separator (item)
 
2768
         ? "" : katze_xbel_item_get_desc (item);
 
2769
        switch (katze_xbel_item_get_kind (item))
 
2770
        {
 
2771
        case KATZE_XBEL_ITEM_KIND_FOLDER:
 
2772
            toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_DIRECTORY);
 
2773
            gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), title);
 
2774
            gtk_tool_item_set_is_important(toolitem, TRUE);
 
2775
            g_signal_connect (toolitem, "clicked",
 
2776
                G_CALLBACK (midori_browser_bookmarkbar_folder_activate_cb),
 
2777
                browser);
 
2778
            sokoke_tool_item_set_tooltip_text(toolitem, desc);
 
2779
            g_object_set_data (G_OBJECT (toolitem), "KatzeXbelItem", item);
 
2780
            break;
 
2781
        case KATZE_XBEL_ITEM_KIND_BOOKMARK:
 
2782
            toolitem = gtk_tool_button_new_from_stock (STOCK_BOOKMARK);
 
2783
            gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), title);
 
2784
            gtk_tool_item_set_is_important(toolitem, TRUE);
 
2785
            g_signal_connect (toolitem, "clicked",
 
2786
                G_CALLBACK (midori_browser_menu_bookmarks_item_activate_cb),
 
2787
                browser);
 
2788
            sokoke_tool_item_set_tooltip_text(toolitem, desc);
 
2789
            g_object_set_data (G_OBJECT (toolitem), "KatzeXbelItem", item);
 
2790
            break;
 
2791
        case KATZE_XBEL_ITEM_KIND_SEPARATOR:
 
2792
            toolitem = gtk_separator_tool_item_new ();
 
2793
            break;
 
2794
        default:
 
2795
            g_warning ("Unknown item kind");
 
2796
        }
 
2797
        gtk_toolbar_insert (GTK_TOOLBAR (priv->bookmarkbar), toolitem, -1);
 
2798
    }
 
2799
    sokoke_container_show_children (GTK_CONTAINER (priv->bookmarkbar));
 
2800
    gtk_box_pack_start (GTK_BOX (vbox), priv->bookmarkbar, FALSE, FALSE, 0);
 
2801
 
 
2802
    // Superuser warning
 
2803
    GtkWidget* hbox;
 
2804
    if ((hbox = sokoke_superuser_warning_new ()))
 
2805
        gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
 
2806
 
 
2807
    // Create the panel
 
2808
    GtkWidget* hpaned = gtk_hpaned_new ();
 
2809
    g_signal_connect (hpaned, "notify::position",
 
2810
                      G_CALLBACK (midori_panel_notify_position_cb),
 
2811
                      browser);
 
2812
    gtk_box_pack_start (GTK_BOX (vbox), hpaned, TRUE, TRUE, 0);
 
2813
    gtk_widget_show (hpaned);
 
2814
    priv->panel = g_object_new (MIDORI_TYPE_PANEL,
 
2815
                                "shadow-type", GTK_SHADOW_IN,
 
2816
                                "menu", priv->menu_tools,
 
2817
                                NULL);
 
2818
    g_signal_connect (priv->panel, "close",
 
2819
                      G_CALLBACK (midori_panel_close_cb), browser);
 
2820
    gtk_paned_pack1 (GTK_PANED (hpaned), priv->panel, FALSE, FALSE);
 
2821
 
 
2822
    // Bookmarks
 
2823
    GtkWidget* box = gtk_vbox_new (FALSE, 0);
 
2824
    GtkTreeViewColumn* column;
 
2825
    GtkCellRenderer* renderer_text;
 
2826
    GtkCellRenderer* renderer_pixbuf;
 
2827
    GtkTreeStore* treestore = gtk_tree_store_new (1, KATZE_TYPE_XBEL_ITEM);
 
2828
    GtkWidget* treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (treestore));
 
2829
    gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
 
2830
    column = gtk_tree_view_column_new ();
 
2831
    renderer_pixbuf = gtk_cell_renderer_pixbuf_new ();
 
2832
    gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE);
 
2833
    gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf,
 
2834
        (GtkTreeCellDataFunc)midori_browser_bookmarks_item_render_icon_cb,
 
2835
        treeview, NULL);
 
2836
    renderer_text = gtk_cell_renderer_text_new ();
 
2837
    gtk_tree_view_column_pack_start (column, renderer_text, FALSE);
 
2838
    gtk_tree_view_column_set_cell_data_func (column, renderer_text,
 
2839
        (GtkTreeCellDataFunc)midori_browser_bookmarks_item_render_text_cb,
 
2840
        treeview, NULL);
 
2841
    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
 
2842
    _tree_store_insert_folder (GTK_TREE_STORE (treestore), NULL, bookmarks);
 
2843
    g_object_unref (treestore);
 
2844
    g_object_connect (treeview,
 
2845
                      "signal::row-activated",
 
2846
                      midori_panel_bookmarks_row_activated_cb, browser,
 
2847
                      "signal::cursor-changed",
 
2848
                      midori_panel_bookmarks_cursor_or_row_changed_cb, browser,
 
2849
                      "signal::columns-changed",
 
2850
                      midori_panel_bookmarks_cursor_or_row_changed_cb, browser,
 
2851
                      "signal::button-release-event",
 
2852
                      midori_panel_bookmarks_button_release_event_cb, browser,
 
2853
                      "signal::popup-menu",
 
2854
                      midori_panel_bookmarks_popup_menu_cb, browser,
 
2855
                      NULL);
 
2856
    midori_panel_bookmarks_cursor_or_row_changed_cb (GTK_TREE_VIEW (treeview),
 
2857
                                                     browser);
 
2858
    gtk_box_pack_start (GTK_BOX (box), treeview, TRUE, TRUE, 0);
 
2859
    priv->panel_bookmarks = treeview;
 
2860
    gtk_widget_show_all (box);
 
2861
    GtkWidget* toolbar = gtk_ui_manager_get_widget (ui_manager,
 
2862
                                                    "/toolbar_bookmarks");
 
2863
    gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_MENU);
 
2864
    gtk_widget_show_all (toolbar);
 
2865
    midori_panel_append_page (MIDORI_PANEL (priv->panel),
 
2866
                              box, toolbar,
 
2867
                              "vcard", _("Bookmarks"));
 
2868
 
 
2869
    // Transfers
 
2870
    GtkWidget* panel = midori_web_view_new ();
 
2871
    gtk_widget_show (panel);
 
2872
    midori_panel_append_page (MIDORI_PANEL (priv->panel),
 
2873
                              panel, NULL,
 
2874
                              "package", _("Transfers"));
 
2875
 
 
2876
    // Console
 
2877
    priv->panel_console = midori_console_new ();
 
2878
    gtk_widget_show (priv->panel_console);
 
2879
    toolbar = midori_console_get_toolbar (MIDORI_CONSOLE (priv->panel_console));
 
2880
    gtk_widget_show (toolbar);
 
2881
    midori_panel_append_page (MIDORI_PANEL (priv->panel),
 
2882
                              priv->panel_console, toolbar,
 
2883
                              "terminal", _("Console"));
 
2884
 
 
2885
    // History
 
2886
    panel = midori_web_view_new ();
 
2887
    gtk_widget_show (panel);
 
2888
    midori_panel_append_page (MIDORI_PANEL (priv->panel),
 
2889
                              panel, NULL,
 
2890
                              "document-open-recent", _("History"));
 
2891
 
 
2892
    // Pageholder
 
2893
    priv->panel_pageholder = g_object_new (MIDORI_TYPE_WEB_VIEW,
 
2894
                                           "uri", "",
 
2895
                                           NULL);
 
2896
    gtk_widget_show (priv->panel_pageholder);
 
2897
    midori_panel_append_page (MIDORI_PANEL (priv->panel),
 
2898
                              priv->panel_pageholder, NULL,
 
2899
                              GTK_STOCK_CONVERT, _("Pageholder"));
 
2900
 
 
2901
    // Userscripts
 
2902
    panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_USER_SCRIPTS);
 
2903
    gtk_widget_show (panel);
 
2904
    toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel));
 
2905
    gtk_widget_show (toolbar);
 
2906
    midori_panel_append_page (MIDORI_PANEL (priv->panel),
 
2907
                              panel, toolbar,
 
2908
                              "", _("Userscripts"));
 
2909
    // Userstyles
 
2910
    /*panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_USER_STYLES);
 
2911
    gtk_widget_show (panel);
 
2912
    toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel));
 
2913
    gtk_widget_show (toolbar);
 
2914
    midori_panel_append_page (MIDORI_PANEL (priv->panel),
 
2915
                              panel, toolbar,
 
2916
                              "", _("Userstyles"));*/
 
2917
 
 
2918
    // Notebook, containing all web_views
 
2919
    priv->notebook = gtk_notebook_new ();
 
2920
    gtk_notebook_set_scrollable (GTK_NOTEBOOK (priv->notebook), TRUE);
 
2921
    gtk_paned_pack2 (GTK_PANED (hpaned), priv->notebook, FALSE, FALSE);
 
2922
    g_signal_connect_after (priv->notebook, "switch-page",
 
2923
                            G_CALLBACK (gtk_notebook_switch_page_cb),
 
2924
                            browser);
 
2925
    gtk_widget_show (priv->notebook);
 
2926
 
 
2927
    // Incremental findbar
 
2928
    priv->find = gtk_toolbar_new ();
 
2929
    gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->find), GTK_ICON_SIZE_MENU);
 
2930
    gtk_toolbar_set_style (GTK_TOOLBAR (priv->find), GTK_TOOLBAR_BOTH_HORIZ);
 
2931
    toolitem = gtk_tool_item_new ();
 
2932
    gtk_container_set_border_width (GTK_CONTAINER (toolitem), 6);
 
2933
    gtk_container_add (GTK_CONTAINER (toolitem),
 
2934
                       gtk_label_new_with_mnemonic (_("_Inline find:")));
 
2935
    gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1);
 
2936
    priv->find_text = sexy_icon_entry_new ();
 
2937
    GtkWidget* icon = gtk_image_new_from_stock (GTK_STOCK_FIND,
 
2938
                                                GTK_ICON_SIZE_MENU);
 
2939
    sexy_icon_entry_set_icon (SEXY_ICON_ENTRY(priv->find_text),
 
2940
                              SEXY_ICON_ENTRY_PRIMARY, GTK_IMAGE(icon));
 
2941
    sexy_icon_entry_add_clear_button (SEXY_ICON_ENTRY(priv->find_text));
 
2942
    g_signal_connect (priv->find_text, "activate",
 
2943
        G_CALLBACK (_action_find_next_activate), browser);
 
2944
    toolitem = gtk_tool_item_new ();
 
2945
    gtk_container_add (GTK_CONTAINER (toolitem), priv->find_text);
 
2946
    gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE);
 
2947
    gtk_toolbar_insert (GTK_TOOLBAR(priv->find), toolitem, -1);
 
2948
    toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_GO_BACK);
 
2949
    gtk_tool_item_set_is_important (toolitem, TRUE);
 
2950
    g_signal_connect (toolitem, "clicked",
 
2951
        G_CALLBACK (_action_find_previous_activate), browser);
 
2952
    gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1);
 
2953
    toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_GO_FORWARD);
 
2954
    gtk_tool_item_set_is_important (toolitem, TRUE);
 
2955
    g_signal_connect (toolitem, "clicked",
 
2956
        G_CALLBACK (_action_find_next_activate), browser);
 
2957
    gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1);
 
2958
    priv->find_case = gtk_toggle_tool_button_new_from_stock (
 
2959
        GTK_STOCK_SPELL_CHECK);
 
2960
    gtk_tool_button_set_label (GTK_TOOL_BUTTON (priv->find_case), _("Match Case"));
 
2961
    gtk_tool_item_set_is_important (GTK_TOOL_ITEM (priv->find_case), TRUE);
 
2962
    gtk_toolbar_insert (GTK_TOOLBAR (priv->find), priv->find_case, -1);
 
2963
    priv->find_highlight = gtk_toggle_tool_button_new_from_stock (
 
2964
        GTK_STOCK_SELECT_ALL);
 
2965
    g_signal_connect (priv->find_highlight, "toggled",
 
2966
                      G_CALLBACK (_find_highlight_toggled), browser);
 
2967
    gtk_tool_button_set_label (GTK_TOOL_BUTTON (priv->find_highlight),
 
2968
                               "Highlight Matches");
 
2969
    gtk_tool_item_set_is_important (GTK_TOOL_ITEM (priv->find_highlight), TRUE);
 
2970
    gtk_toolbar_insert (GTK_TOOLBAR (priv->find), priv->find_highlight, -1);
 
2971
    toolitem = gtk_separator_tool_item_new ();
 
2972
    gtk_separator_tool_item_set_draw (
 
2973
        GTK_SEPARATOR_TOOL_ITEM (toolitem), FALSE);
 
2974
    gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE);
 
2975
    gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1);
 
2976
    toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_CLOSE);
 
2977
    gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), _("Close Findbar"));
 
2978
    g_signal_connect (toolitem, "clicked",
 
2979
        G_CALLBACK (midori_browser_find_button_close_clicked_cb), browser);
 
2980
    gtk_toolbar_insert (GTK_TOOLBAR (priv->find), toolitem, -1);
 
2981
    sokoke_container_show_children (GTK_CONTAINER (priv->find));
 
2982
    gtk_box_pack_start (GTK_BOX (vbox), priv->find, FALSE, FALSE, 0);
 
2983
 
 
2984
    // Statusbar
 
2985
    // TODO: fix children overlapping statusbar border
 
2986
    priv->statusbar = gtk_statusbar_new ();
 
2987
    gtk_box_pack_start (GTK_BOX (vbox), priv->statusbar, FALSE, FALSE, 0);
 
2988
    priv->progressbar = gtk_progress_bar_new ();
 
2989
    // Setting the progressbar's height to 1 makes it fit in the statusbar
 
2990
    gtk_widget_set_size_request (priv->progressbar, -1, 1);
 
2991
    gtk_box_pack_start (GTK_BOX (priv->statusbar), priv->progressbar,
 
2992
                        FALSE, FALSE, 3);
 
2993
 
 
2994
    // Extensions
 
2995
    panel = midori_addons_new (GTK_WIDGET (browser), MIDORI_ADDON_EXTENSIONS);
 
2996
    gtk_widget_show (panel);
 
2997
    toolbar = midori_addons_get_toolbar (MIDORI_ADDONS (panel));
 
2998
    gtk_widget_show (toolbar);
 
2999
    midori_panel_append_page (MIDORI_PANEL (priv->panel),
 
3000
                              panel, toolbar,
 
3001
                              "", _("Extensions"));
 
3002
 
 
3003
    g_object_unref (ui_manager);
 
3004
}
 
3005
 
 
3006
static void
 
3007
midori_browser_finalize (GObject* object)
 
3008
{
 
3009
    MidoriBrowser* browser = MIDORI_BROWSER (object);
 
3010
    MidoriBrowserPrivate* priv = browser->priv;
 
3011
 
 
3012
    g_free (priv->uri);
 
3013
    g_free (priv->title);
 
3014
    g_free (priv->statusbar_text);
 
3015
 
 
3016
    if (priv->proxy_xbel_folder)
 
3017
        katze_xbel_item_unref (priv->proxy_xbel_folder);
 
3018
 
 
3019
    if (priv->settings)
 
3020
        g_object_unref (priv->settings);
 
3021
    if (priv->trash)
 
3022
        g_object_unref (priv->trash);
 
3023
 
 
3024
    G_OBJECT_CLASS (midori_browser_parent_class)->finalize (object);
 
3025
}
 
3026
 
 
3027
static void
 
3028
_midori_browser_set_toolbar_style (MidoriBrowser*     browser,
 
3029
                                   MidoriToolbarStyle toolbar_style)
 
3030
{
 
3031
    MidoriBrowserPrivate* priv = browser->priv;
 
3032
 
 
3033
    GtkToolbarStyle gtk_toolbar_style;
 
3034
    GtkSettings* gtk_settings = gtk_widget_get_settings (GTK_WIDGET (browser));
 
3035
    if (toolbar_style == MIDORI_TOOLBAR_DEFAULT && gtk_settings)
 
3036
        g_object_get (gtk_settings, "gtk-toolbar-style", &gtk_toolbar_style, NULL);
 
3037
    else
 
3038
    {
 
3039
        switch (toolbar_style)
 
3040
        {
 
3041
        case MIDORI_TOOLBAR_ICONS:
 
3042
            gtk_toolbar_style = GTK_TOOLBAR_ICONS;
 
3043
            break;
 
3044
        case MIDORI_TOOLBAR_TEXT:
 
3045
            gtk_toolbar_style = GTK_TOOLBAR_TEXT;
 
3046
            break;
 
3047
        case MIDORI_TOOLBAR_BOTH:
 
3048
            gtk_toolbar_style = GTK_TOOLBAR_BOTH;
 
3049
            break;
 
3050
        case MIDORI_TOOLBAR_BOTH_HORIZ:
 
3051
        case MIDORI_TOOLBAR_DEFAULT:
 
3052
            gtk_toolbar_style = GTK_TOOLBAR_BOTH_HORIZ;
 
3053
        }
 
3054
    }
 
3055
    gtk_toolbar_set_style (GTK_TOOLBAR (priv->navigationbar),
 
3056
                           gtk_toolbar_style);
 
3057
}
 
3058
 
 
3059
static void
 
3060
_midori_browser_update_settings (MidoriBrowser* browser)
 
3061
{
 
3062
    MidoriBrowserPrivate* priv = browser->priv;
 
3063
 
 
3064
    gboolean remember_last_window_size;
 
3065
    gint last_window_width, last_window_height;
 
3066
    gint last_panel_position, last_panel_page;
 
3067
    gboolean show_navigationbar, show_bookmarkbar, show_panel, show_statusbar;
 
3068
    gboolean small_toolbar, show_new_tab, show_homepage,
 
3069
        show_web_search, show_trash;
 
3070
    MidoriToolbarStyle toolbar_style;
 
3071
    gint last_web_search;
 
3072
    gchar* last_pageholder_uri;
 
3073
    g_object_get (priv->settings,
 
3074
                  "remember-last-window-size", &remember_last_window_size,
 
3075
                  "last-window-width", &last_window_width,
 
3076
                  "last-window-height", &last_window_height,
 
3077
                  "last-panel-position", &last_panel_position,
 
3078
                  "last-panel-page", &last_panel_page,
 
3079
                  "show-navigationbar", &show_navigationbar,
 
3080
                  "show-bookmarkbar", &show_bookmarkbar,
 
3081
                  "show-panel", &show_panel,
 
3082
                  "show-statusbar", &show_statusbar,
 
3083
                  "small-toolbar", &small_toolbar,
 
3084
                  "show-new-tab", &show_new_tab,
 
3085
                  "show-homepage", &show_homepage,
 
3086
                  "show-web-search", &show_web_search,
 
3087
                  "show-trash", &show_trash,
 
3088
                  "toolbar-style", &toolbar_style,
 
3089
                  "last-web-search", &last_web_search,
 
3090
                  "last-pageholder-uri", &last_pageholder_uri,
 
3091
                  NULL);
 
3092
 
 
3093
    GdkScreen* screen = gtk_window_get_screen (GTK_WINDOW (browser));
 
3094
    const gint default_width = (gint)gdk_screen_get_width (screen) / 1.7;
 
3095
    const gint default_height = (gint)gdk_screen_get_height (screen) / 1.7;
 
3096
 
 
3097
    if (remember_last_window_size)
 
3098
    {
 
3099
        if (last_window_width && last_window_height)
 
3100
            gtk_window_set_default_size (GTK_WINDOW (browser),
 
3101
                                         last_window_width, last_window_height);
 
3102
        else
 
3103
            gtk_window_set_default_size (GTK_WINDOW (browser),
 
3104
                                         default_width, default_height);
 
3105
    }
 
3106
 
 
3107
    _midori_browser_set_toolbar_style (browser, toolbar_style);
 
3108
    gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->navigationbar),
 
3109
                               small_toolbar ? GTK_ICON_SIZE_SMALL_TOOLBAR
 
3110
                               : GTK_ICON_SIZE_LARGE_TOOLBAR);
 
3111
 
 
3112
    update_searchEngine (last_web_search, priv->search);
 
3113
 
 
3114
    gtk_paned_set_position (GTK_PANED (gtk_widget_get_parent (priv->panel)),
 
3115
                            last_panel_position);
 
3116
    midori_panel_set_current_page (MIDORI_PANEL (priv->panel), last_panel_page);
 
3117
    g_object_set (priv->panel_pageholder, "uri", last_pageholder_uri, NULL);
 
3118
 
 
3119
    _action_set_active (browser, "Navigationbar", show_navigationbar);
 
3120
    _action_set_active (browser, "Bookmarkbar", show_bookmarkbar);
 
3121
    _action_set_active (browser, "Panel", show_panel);
 
3122
    _action_set_active (browser, "Statusbar", show_statusbar);
 
3123
 
 
3124
    sokoke_widget_set_visible (priv->button_tab_new, show_new_tab);
 
3125
    sokoke_widget_set_visible (priv->button_homepage, show_homepage);
 
3126
    sokoke_widget_set_visible (priv->search, show_web_search);
 
3127
    sokoke_widget_set_visible (priv->button_trash, show_trash);
 
3128
 
 
3129
    g_free (last_pageholder_uri);
 
3130
}
 
3131
 
 
3132
static void
 
3133
midori_browser_settings_notify (MidoriWebSettings* web_settings,
 
3134
                                GParamSpec*        pspec,
 
3135
                                MidoriBrowser*     browser)
 
3136
{
 
3137
    MidoriBrowserPrivate* priv = browser->priv;
 
3138
 
 
3139
    const gchar* name = g_intern_string (pspec->name);
 
3140
    GValue value = {0, };
 
3141
 
 
3142
    g_value_init (&value, pspec->value_type);
 
3143
    g_object_get_property (G_OBJECT (priv->settings), name, &value);
 
3144
 
 
3145
    if (name == g_intern_string ("toolbar-style"))
 
3146
        _midori_browser_set_toolbar_style (browser, g_value_get_enum (&value));
 
3147
    else if (name == g_intern_string ("small-toolbar"))
 
3148
        gtk_toolbar_set_icon_size (GTK_TOOLBAR (priv->navigationbar),
 
3149
            g_value_get_boolean (&value) ? GTK_ICON_SIZE_SMALL_TOOLBAR
 
3150
            : GTK_ICON_SIZE_LARGE_TOOLBAR);
 
3151
    else if (name == g_intern_string ("show-new-tab"))
 
3152
        sokoke_widget_set_visible (priv->button_tab_new,
 
3153
            g_value_get_boolean (&value));
 
3154
    else if (name == g_intern_string ("show-homepage"))
 
3155
        sokoke_widget_set_visible (priv->button_homepage,
 
3156
            g_value_get_boolean (&value));
 
3157
    else if (name == g_intern_string ("show-web-search"))
 
3158
        sokoke_widget_set_visible (priv->search,
 
3159
            g_value_get_boolean (&value));
 
3160
    else if (name == g_intern_string ("show-trash"))
 
3161
        sokoke_widget_set_visible (priv->button_trash,
 
3162
            g_value_get_boolean (&value));
 
3163
    else if (!g_object_class_find_property (G_OBJECT_GET_CLASS (web_settings),
 
3164
                                             name))
 
3165
         g_warning (_("Unexpected setting '%s'"), name);
 
3166
    g_value_unset (&value);
 
3167
}
 
3168
 
 
3169
static void
 
3170
midori_browser_set_property (GObject*      object,
 
3171
                             guint         prop_id,
 
3172
                             const GValue* value,
 
3173
                             GParamSpec*   pspec)
 
3174
{
 
3175
    MidoriBrowser* browser = MIDORI_BROWSER (object);
 
3176
    MidoriBrowserPrivate* priv = browser->priv;
 
3177
 
 
3178
    switch (prop_id)
 
3179
    {
 
3180
    case PROP_TAB:
 
3181
        midori_browser_set_current_tab (browser, g_value_get_object (value));
 
3182
        break;
 
3183
    case PROP_STATUSBAR_TEXT:
 
3184
        _midori_browser_set_statusbar_text (browser, g_value_get_string (value));
 
3185
        break;
 
3186
    case PROP_SETTINGS:
 
3187
        if (priv->settings)
 
3188
            g_signal_handlers_disconnect_by_func (priv->settings,
 
3189
                                                  midori_browser_settings_notify,
 
3190
                                                  browser);
 
3191
        katze_object_assign (priv->settings, g_value_get_object (value));
 
3192
        g_object_ref (priv->settings);
 
3193
        _midori_browser_update_settings (browser);
 
3194
        g_signal_connect (priv->settings, "notify",
 
3195
                      G_CALLBACK (midori_browser_settings_notify), browser);
 
3196
        // FIXME: Assigning settings must be conditional, if web view or not
 
3197
        // FIXME: Assign settings only if the same settings object was used
 
3198
        gtk_container_foreach (GTK_CONTAINER (priv->notebook),
 
3199
                               (GtkCallback) midori_web_view_set_settings,
 
3200
                               priv->settings);
 
3201
        break;
 
3202
    case PROP_TRASH:
 
3203
        ; // FIXME: Disconnect handlers
 
3204
        katze_object_assign (priv->trash, g_value_get_object (value));
 
3205
        g_object_ref (priv->trash);
 
3206
        // FIXME: Connect to updates
 
3207
        _midori_browser_update_actions (browser);
 
3208
        break;
 
3209
    default:
 
3210
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
3211
        break;
 
3212
    }
 
3213
}
 
3214
 
 
3215
static void
 
3216
midori_browser_get_property (GObject*    object,
 
3217
                             guint       prop_id,
 
3218
                             GValue*     value,
 
3219
                             GParamSpec* pspec)
 
3220
{
 
3221
    MidoriBrowser* browser = MIDORI_BROWSER (object);
 
3222
    MidoriBrowserPrivate* priv = browser->priv;
 
3223
 
 
3224
    switch (prop_id)
 
3225
    {
 
3226
    case PROP_MENUBAR:
 
3227
        g_value_set_object (value, priv->menubar);
 
3228
        break;
 
3229
    case PROP_NAVIGATIONBAR:
 
3230
        g_value_set_object (value, priv->navigationbar);
 
3231
        break;
 
3232
    case PROP_TAB:
 
3233
        g_value_set_object (value, midori_browser_get_current_tab (browser));
 
3234
        break;
 
3235
    case PROP_STATUSBAR:
 
3236
        g_value_set_object (value, priv->statusbar);
 
3237
        break;
 
3238
    case PROP_STATUSBAR_TEXT:
 
3239
        g_value_set_string (value, priv->statusbar_text);
 
3240
        break;
 
3241
    case PROP_SETTINGS:
 
3242
        g_value_set_object (value, priv->settings);
 
3243
        break;
 
3244
    case PROP_TRASH:
 
3245
        g_value_set_object (value, priv->trash);
 
3246
        break;
 
3247
    default:
 
3248
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
3249
        break;
 
3250
    }
 
3251
}
 
3252
 
 
3253
/**
 
3254
 * midori_browser_new:
 
3255
 *
 
3256
 * Creates a new browser widget.
 
3257
 *
 
3258
 * A browser is a window with a menubar, toolbars, a notebook, panels
 
3259
 * and a statusbar. You should mostly treat it as an opaque widget.
 
3260
 *
 
3261
 * Return value: a new #MidoriBrowser
 
3262
 **/
 
3263
MidoriBrowser*
 
3264
midori_browser_new (void)
 
3265
{
 
3266
    MidoriBrowser* browser = g_object_new (MIDORI_TYPE_BROWSER,
 
3267
                                           NULL);
 
3268
 
 
3269
    return browser;
 
3270
}
 
3271
 
 
3272
/**
 
3273
 * midori_browser_add_tab:
 
3274
 * @browser: a #MidoriBrowser
 
3275
 * @widget: a tab
 
3276
 *
 
3277
 * Appends an arbitrary widget in the form of a new tab and creates an
 
3278
 * according item in the Window menu.
 
3279
 *
 
3280
 * Return value: the index of the new tab, or -1 in case of an error
 
3281
 **/
 
3282
gint
 
3283
midori_browser_add_tab (MidoriBrowser* browser,
 
3284
                        GtkWidget*     widget)
 
3285
{
 
3286
    g_return_val_if_fail (GTK_IS_WIDGET (widget), -1);
 
3287
 
 
3288
    MidoriBrowserPrivate* priv = browser->priv;
 
3289
 
 
3290
    GtkWidget* scrolled = gtk_scrolled_window_new (NULL, NULL);
 
3291
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
 
3292
                                    GTK_POLICY_AUTOMATIC,
 
3293
                                    GTK_POLICY_AUTOMATIC);
 
3294
    GTK_WIDGET_SET_FLAGS (scrolled, GTK_CAN_FOCUS);
 
3295
    GtkWidget* child;
 
3296
    GObjectClass* gobject_class = G_OBJECT_GET_CLASS (widget);
 
3297
    if (GTK_WIDGET_CLASS (gobject_class)->set_scroll_adjustments_signal)
 
3298
        child = widget;
 
3299
    else
 
3300
    {
 
3301
        child = gtk_viewport_new (NULL, NULL);
 
3302
        gtk_widget_show (child);
 
3303
        gtk_container_add (GTK_CONTAINER (child), widget);
 
3304
    }
 
3305
    gtk_container_add (GTK_CONTAINER (scrolled), child);
 
3306
    gtk_widget_show (scrolled);
 
3307
 
 
3308
    GtkWidget* label = NULL;
 
3309
    GtkWidget* menuitem = NULL;
 
3310
 
 
3311
    if (MIDORI_IS_WEB_VIEW (widget))
 
3312
    {
 
3313
        label = midori_web_view_get_proxy_tab_label (MIDORI_WEB_VIEW (widget));
 
3314
 
 
3315
        menuitem = midori_web_view_get_proxy_menu_item (MIDORI_WEB_VIEW (widget));
 
3316
 
 
3317
        if (priv->proxy_xbel_folder)
 
3318
        {
 
3319
            KatzeXbelItem* xbel_item = midori_web_view_get_proxy_xbel_item (
 
3320
                MIDORI_WEB_VIEW (widget));
 
3321
            katze_xbel_item_ref (xbel_item);
 
3322
            katze_xbel_folder_append_item (priv->proxy_xbel_folder, xbel_item);
 
3323
        }
 
3324
 
 
3325
        g_object_connect (widget,
 
3326
                          "signal::window-object-cleared",
 
3327
                          midori_web_view_window_object_cleared_cb, browser,
 
3328
                          "signal::load-started",
 
3329
                          midori_web_view_load_started_cb, browser,
 
3330
                          "signal::load-committed",
 
3331
                          midori_web_view_load_committed_cb, browser,
 
3332
                          "signal::progress-started",
 
3333
                          midori_web_view_progress_started_cb, browser,
 
3334
                          "signal::progress-changed",
 
3335
                          midori_web_view_progress_changed_cb, browser,
 
3336
                          "signal::progress-done",
 
3337
                          midori_web_view_progress_done_cb, browser,
 
3338
                          "signal::load-done",
 
3339
                          midori_web_view_load_done_cb, browser,
 
3340
                          "signal::title-changed",
 
3341
                          midori_web_view_title_changed_cb, browser,
 
3342
                          "signal::status-bar-text-changed",
 
3343
                          midori_web_view_statusbar_text_changed_cb, browser,
 
3344
                          "signal::element-motion",
 
3345
                          midori_web_view_element_motion_cb, browser,
 
3346
                          "signal::console-message",
 
3347
                          midori_web_view_console_message_cb, browser,
 
3348
                          "signal::close",
 
3349
                          midori_web_view_close_cb, browser,
 
3350
                          "signal::new-tab",
 
3351
                          midori_web_view_new_tab_cb, browser,
 
3352
                          "signal::new-window",
 
3353
                          midori_web_view_new_window_cb, browser,
 
3354
                          "signal::populate-popup",
 
3355
                          midori_web_view_populate_popup_cb, browser,
 
3356
                          "signal::leave-notify-event",
 
3357
                          midori_web_view_leave_notify_event_cb, browser,
 
3358
                          "signal::destroy",
 
3359
                          midori_web_view_destroy_cb, browser,
 
3360
                          NULL);
 
3361
    }
 
3362
 
 
3363
    if (menuitem)
 
3364
    {
 
3365
        gtk_widget_show (menuitem);
 
3366
        g_signal_connect (menuitem, "activate",
 
3367
            G_CALLBACK (midori_browser_window_menu_item_activate_cb), scrolled);
 
3368
        gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_window), menuitem);
 
3369
    }
 
3370
 
 
3371
    guint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
 
3372
    gtk_notebook_insert_page (GTK_NOTEBOOK (priv->notebook), scrolled,
 
3373
                              label, n + 1);
 
3374
    #if GTK_CHECK_VERSION(2, 10, 0)
 
3375
    gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (priv->notebook),
 
3376
                                      scrolled, TRUE);
 
3377
    gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (priv->notebook),
 
3378
                                     scrolled, TRUE);
 
3379
    #endif
 
3380
    _midori_browser_update_actions (browser);
 
3381
 
 
3382
    n = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled);
 
3383
    return n;
 
3384
}
 
3385
 
 
3386
/**
 
3387
 * midori_browser_remove_tab:
 
3388
 * @browser: a #MidoriBrowser
 
3389
 * @widget: a tab
 
3390
 *
 
3391
 * Removes an existing tab from the browser, including an associated menu item.
 
3392
 **/
 
3393
void
 
3394
midori_browser_remove_tab (MidoriBrowser* browser,
 
3395
                           GtkWidget*     widget)
 
3396
{
 
3397
    MidoriBrowserPrivate* priv = browser->priv;
 
3398
 
 
3399
    GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, widget);
 
3400
    gtk_container_remove (GTK_CONTAINER (priv->notebook), scrolled);
 
3401
 
 
3402
    // FIXME: Remove the menuitem if this is a web view
 
3403
}
 
3404
 
 
3405
/**
 
3406
 * midori_browser_add_xbel_item:
 
3407
 * @browser: a #MidoriBrowser
 
3408
 * @xbel_item: a bookmark
 
3409
 *
 
3410
 * Appends a #KatzeXbelItem in the form of a new tab.
 
3411
 *
 
3412
 * Return value: the index of the new tab, or -1 in case of an error
 
3413
 **/
 
3414
gint
 
3415
midori_browser_add_xbel_item (MidoriBrowser* browser,
 
3416
                              KatzeXbelItem* xbel_item)
 
3417
{
 
3418
    MidoriBrowserPrivate* priv = browser->priv;
 
3419
 
 
3420
    g_return_val_if_fail (katze_xbel_item_is_bookmark (xbel_item), -1);
 
3421
 
 
3422
    const gchar* uri = katze_xbel_bookmark_get_href (xbel_item);
 
3423
    const gchar* title = katze_xbel_item_get_title (xbel_item);
 
3424
    GtkWidget* web_view = g_object_new (MIDORI_TYPE_WEB_VIEW,
 
3425
                                        "uri", uri,
 
3426
                                        "title", title,
 
3427
                                        "settings", priv->settings,
 
3428
                                        NULL);
 
3429
    gtk_widget_show (web_view);
 
3430
 
 
3431
    return midori_browser_add_tab (browser, web_view);
 
3432
}
 
3433
 
 
3434
/**
 
3435
 * midori_browser_add_uri:
 
3436
 * @browser: a #MidoriBrowser
 
3437
 * @uri: an URI
 
3438
 *
 
3439
 * Appends an uri in the form of a new tab.
 
3440
 *
 
3441
 * Return value: the index of the new tab, or -1
 
3442
 **/
 
3443
gint
 
3444
midori_browser_add_uri (MidoriBrowser* browser,
 
3445
                        const gchar*   uri)
 
3446
{
 
3447
    MidoriBrowserPrivate* priv = browser->priv;
 
3448
 
 
3449
    GtkWidget* web_view = g_object_new (MIDORI_TYPE_WEB_VIEW,
 
3450
                                        "uri", uri,
 
3451
                                        "settings", priv->settings,
 
3452
                                        NULL);
 
3453
    gtk_widget_show (web_view);
 
3454
 
 
3455
    return midori_browser_add_tab (browser, web_view);
 
3456
}
 
3457
 
 
3458
/**
 
3459
 * midori_browser_activate_action:
 
3460
 * @browser: a #MidoriBrowser
 
3461
 * @name: name of the action
 
3462
 *
 
3463
 * Activates the specified action.
 
3464
 **/
 
3465
void
 
3466
midori_browser_activate_action (MidoriBrowser* browser,
 
3467
                                const gchar*   name)
 
3468
{
 
3469
    GtkAction* action = _action_by_name (browser, name);
 
3470
    if (action)
 
3471
        gtk_action_activate (action);
 
3472
    else
 
3473
        g_warning (_("Unexpected action '%s'."), name);
 
3474
}
 
3475
 
 
3476
/**
 
3477
 * midori_browser_set_current_page:
 
3478
 * @browser: a #MidoriBrowser
 
3479
 * @n: the index of a page
 
3480
 *
 
3481
 * Switches to the page with the index @n.
 
3482
 *
 
3483
 * The widget will also grab the focus automatically.
 
3484
 **/
 
3485
void
 
3486
midori_browser_set_current_page (MidoriBrowser* browser,
 
3487
                                 gint           n)
 
3488
{
 
3489
    MidoriBrowserPrivate* priv = browser->priv;
 
3490
 
 
3491
    gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n);
 
3492
    GtkWidget* scrolled = gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), n);
 
3493
    GtkWidget* widget = _midori_browser_child_for_scrolled (browser, scrolled);
 
3494
    if (widget && MIDORI_IS_WEB_VIEW (widget)
 
3495
        && !strcmp (midori_web_view_get_display_uri (
 
3496
        MIDORI_WEB_VIEW (widget)), ""))
 
3497
        gtk_widget_grab_focus (priv->location);
 
3498
    else
 
3499
        gtk_widget_grab_focus (widget);
 
3500
}
 
3501
 
 
3502
/**
 
3503
 * midori_browser_get_current_page:
 
3504
 * @browser: a #MidoriBrowser
 
3505
 *
 
3506
 * Determines the currently selected page.
 
3507
 *
 
3508
 * If there is no page present at all, %NULL is returned.
 
3509
 *
 
3510
 * Return value: the selected page, or -1
 
3511
 **/
 
3512
gint
 
3513
midori_browser_get_current_page (MidoriBrowser* browser)
 
3514
{
 
3515
    g_return_val_if_fail (MIDORI_IS_BROWSER (browser), -1);
 
3516
 
 
3517
    MidoriBrowserPrivate* priv = browser->priv;
 
3518
 
 
3519
    return gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
 
3520
}
 
3521
 
 
3522
/**
 
3523
 * midori_browser_set_current_tab:
 
3524
 * @browser: a #MidoriBrowser
 
3525
 * @widget: a #GtkWidget
 
3526
 *
 
3527
 * Switches to the page containing @widget.
 
3528
 *
 
3529
 * The widget will also grab the focus automatically.
 
3530
 **/
 
3531
void
 
3532
midori_browser_set_current_tab (MidoriBrowser* browser,
 
3533
                                GtkWidget*     widget)
 
3534
{
 
3535
    MidoriBrowserPrivate* priv = browser->priv;
 
3536
 
 
3537
    GtkWidget* scrolled = _midori_browser_scrolled_for_child (browser, widget);
 
3538
    gint n = gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), scrolled);
 
3539
    gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), n);
 
3540
    if (widget && MIDORI_IS_WEB_VIEW (widget)
 
3541
        && !strcmp (midori_web_view_get_display_uri (
 
3542
        MIDORI_WEB_VIEW (widget)), ""))
 
3543
        gtk_widget_grab_focus (priv->location);
 
3544
    else
 
3545
        gtk_widget_grab_focus (widget);
 
3546
}
 
3547
 
 
3548
/**
 
3549
 * midori_browser_get_current_tab:
 
3550
 * @browser: a #MidoriBrowser
 
3551
 *
 
3552
 * Retrieves the currently selected tab.
 
3553
 *
 
3554
 * If there is no tab present at all, %NULL is returned.
 
3555
 *
 
3556
 * Return value: the selected tab, or %NULL
 
3557
 **/
 
3558
GtkWidget*
 
3559
midori_browser_get_current_tab (MidoriBrowser* browser)
 
3560
{
 
3561
    g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL);
 
3562
 
 
3563
    MidoriBrowserPrivate* priv = browser->priv;
 
3564
 
 
3565
    gint n = gtk_notebook_get_current_page (GTK_NOTEBOOK (priv->notebook));
 
3566
    if (n >= 0)
 
3567
    {
 
3568
        GtkWidget* widget = _midori_browser_child_for_scrolled (browser,
 
3569
            gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), n));
 
3570
        return widget;
 
3571
    }
 
3572
    else
 
3573
        return NULL;
 
3574
}
 
3575
 
 
3576
/**
 
3577
 * midori_browser_get_current_web_view:
 
3578
 * @browser: a #MidoriBrowser
 
3579
 *
 
3580
 * Determines the currently selected web view.
 
3581
 *
 
3582
 * If there is no web view selected or if there is no tab present
 
3583
 * at all, %NULL is returned.
 
3584
 *
 
3585
 * See also midori_browser_get_current_page
 
3586
 *
 
3587
 * Return value: the selected web view, or %NULL
 
3588
 **/
 
3589
GtkWidget*
 
3590
midori_browser_get_current_web_view (MidoriBrowser* browser)
 
3591
{
 
3592
    g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL);
 
3593
 
 
3594
    GtkWidget* web_view = midori_browser_get_current_tab (browser);
 
3595
    return MIDORI_IS_WEB_VIEW (web_view) ? web_view : NULL;
 
3596
}
 
3597
 
 
3598
/**
 
3599
 * midori_browser_get_proxy_xbel_folder:
 
3600
 * @browser: a #MidoriBrowser
 
3601
 *
 
3602
 * Retrieves a proxy xbel folder representing the respective proxy xbel items
 
3603
 * of the present web views that can be used for session management.
 
3604
 *
 
3605
 * The folder is created on the first call and will be updated to reflect
 
3606
 * changes to all items automatically.
 
3607
 *
 
3608
 * Note that this implicitly creates proxy xbel items of all web views.
 
3609
 *
 
3610
 * Return value: the proxy #KatzeXbelItem
 
3611
 **/
 
3612
KatzeXbelItem*
 
3613
midori_browser_get_proxy_xbel_folder (MidoriBrowser* browser)
 
3614
{
 
3615
    g_return_val_if_fail (MIDORI_IS_BROWSER (browser), NULL);
 
3616
 
 
3617
    MidoriBrowserPrivate* priv = browser->priv;
 
3618
 
 
3619
    if (!priv->proxy_xbel_folder)
 
3620
    {
 
3621
        priv->proxy_xbel_folder = katze_xbel_folder_new ();
 
3622
        // FIXME: Fill in xbel items of all present web views
 
3623
    }
 
3624
    return priv->proxy_xbel_folder;
 
3625
}
 
3626
 
 
3627
/**
 
3628
 * midori_browser_quit:
 
3629
 * @browser: a #MidoriBrowser
 
3630
 *
 
3631
 * Quits the browser, including any other browser windows.
 
3632
 **/
 
3633
void
 
3634
midori_browser_quit (MidoriBrowser* browser)
 
3635
{
 
3636
    g_return_if_fail (MIDORI_IS_BROWSER (browser));
 
3637
 
 
3638
    g_signal_emit (browser, signals[QUIT], 0);
 
3639
}