Merge lp:~elementary-apps/midori/browser-vala into lp:midori
- browser-vala
- Merge into trunk
Proposed by
Tom Beckmann
Status: | Work in progress | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~elementary-apps/midori/browser-vala | ||||
Merge into: | lp:midori | ||||
Diff against target: |
7009 lines (+5330/-1305) (has conflicts) 17 files modified
CMakeLists.txt (+25/-6) katze/midori-paths.vala (+0/-1) midori/CMakeLists.txt (+5/-2) midori/midori-app.h (+1/-1) midori/midori-browser.h (+0/-199) midori/midori-browser.vala (+5053/-1002) midori/midori-download.vala (+1/-5) midori/midori-privatedata.h (+1/-1) midori/midori-speeddial.vala (+0/-4) midori/midori-view.c (+1/-1) midori/midori.h (+0/-1) vapi/gobject-fixes.vapi (+23/-0) vapi/gtk-fixes.vapi (+27/-0) vapi/katze.vapi (+44/-4) vapi/midori.vapi (+147/-77) vapi/webkit2gtk-3.0.vapi (+1/-1) vapi/webkitgtk-3.0.vapi (+1/-0) Text conflict in midori/midori-browser.vala |
||||
To merge this branch: | bzr merge lp:~elementary-apps/midori/browser-vala | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Cris Dywan | Pending | ||
Review via email: mp+231592@code.launchpad.net |
Commit message
Description of the change
This is a port of midori/
To post a comment you must log in.
- 6778. By Tom Beckmann
-
Fix some errors, copy gtk and gobject vapis to local source to override faults in
GtkActionCallback and ParamSpec* type id bindings - 6779. By Tom Beckmann
-
Removed copies of gobject and gtk vapis in favor of minimal fixes vapis. Moved all vapis
to a vapi directory
Unmerged revisions
- 6779. By Tom Beckmann
-
Removed copies of gobject and gtk vapis in favor of minimal fixes vapis. Moved all vapis
to a vapi directory - 6778. By Tom Beckmann
-
Fix some errors, copy gtk and gobject vapis to local source to override faults in
GtkActionCallback and ParamSpec* type id bindings - 6777. By Tom Beckmann
-
Fix all errors, one valac crash remaining
- 6776. By Tom Beckmann
-
Start porting midori-browser.c to vala
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2014-07-11 01:36:48 +0000 |
3 | +++ CMakeLists.txt 2014-09-01 23:11:13 +0000 |
4 | @@ -212,13 +212,11 @@ |
5 | add_definitions("-DHAVE_WEBKIT2") |
6 | add_definitions("-DGTK_VERSION=\"${DEPS_GTK_gtk+-3.0_VERSION}\"") |
7 | add_definitions("-DWEBKIT_VERSION=\"${DEPS_GTK_webkit2gtk-3.0_VERSION}\"") |
8 | - set(PKGS ${PKGS} gtk+-3.0) |
9 | + set(PKGS ${PKGS} gtk+-3.0 webkit2gtk-3.0) |
10 | set(EXTRA_VAPIS ${EXTRA_VAPIS} "${CMAKE_SOURCE_DIR}/midori/webkit2gtk-3.0.vapi") |
11 | set(VALAFLAGS ${VALAFLAGS} -D HAVE_GTK3) |
12 | set(VALAFLAGS ${VALAFLAGS} -D HAVE_WEBKIT2) |
13 | - if (${DEPS_GTK_webkit2gtk-3.0_VERSION} VERSION_GREATER "2.3.90") |
14 | - set(VALAFLAGS ${VALAFLAGS} -D HAVE_WEBKIT2_3_91) |
15 | - endif () |
16 | + set(VALAFLAGS ${VALAFLAGS} -D HAVE_WEBKIT2_3_91) |
17 | elseif (USE_GTK3) |
18 | pkg_check_modules(DEPS_GTK REQUIRED |
19 | gtk+-3.0>=3.0.0 |
20 | @@ -227,7 +225,7 @@ |
21 | ) |
22 | add_definitions("-DGTK_VERSION=\"${DEPS_GTK_gtk+-3.0_VERSION}\"") |
23 | add_definitions("-DWEBKIT_VERSION=\"${DEPS_GTK_webkitgtk-3.0_VERSION}\"") |
24 | - set(PKGS ${PKGS} gtk+-3.0) |
25 | + set(PKGS ${PKGS} gtk+-3.0 webkitgtk-3.0) |
26 | set(EXTRA_VAPIS ${EXTRA_VAPIS} "${CMAKE_SOURCE_DIR}/midori/webkitgtk-3.0.vapi") |
27 | set(VALAFLAGS ${VALAFLAGS} -D HAVE_GTK3) |
28 | else () |
29 | @@ -238,10 +236,31 @@ |
30 | ) |
31 | add_definitions("-DGTK_VERSION=\"${DEPS_GTK_gtk+-2.0_VERSION}\"") |
32 | add_definitions("-DWEBKIT_VERSION=\"${DEPS_GTK_webkit-1.0_VERSION}\"") |
33 | - set(PKGS ${PKGS} gtk+-2.0) |
34 | + set(PKGS ${PKGS} gtk+-2.0 webkit-1.0) |
35 | set(EXTRA_VAPIS ${EXTRA_VAPIS} "${CMAKE_SOURCE_DIR}/midori/webkitgtk-3.0.vapi") |
36 | endif () |
37 | |
38 | +# vala has no GTK_CHECK_VERSION, so we need to cheat |
39 | +pkg_check_modules(GTK_3_1_10 gtk+-3.0>=3.0.0) |
40 | +if (GTK_3_0_0_FOUND) |
41 | + set(VALAFLAGS ${VALAFLAGS} -D GTK_VERSION_3_0_0) |
42 | +endif() |
43 | + |
44 | +pkg_check_modules(GTK_3_4_0 gtk+-3.0>=3.4.0) |
45 | +if (GTK_3_4_0_FOUND) |
46 | + set(VALAFLAGS ${VALAFLAGS} -D GTK_VERSION_3_4_0) |
47 | +endif() |
48 | + |
49 | +pkg_check_modules(GTK_3_2_0 gtk+-3.0>=3.2.0) |
50 | +if (GTK_3_2_0_FOUND) |
51 | + set(VALAFLAGS ${VALAFLAGS} -D GTK_VERSION_3_2_0) |
52 | +endif() |
53 | + |
54 | +pkg_check_modules(GTK_3_1_10 gtk+-3.0>=3.1.10) |
55 | +if (GTK_3_1_10_FOUND) |
56 | + set(VALAFLAGS ${VALAFLAGS} -D GTK_VERSION_3_1_10) |
57 | +endif() |
58 | + |
59 | # dh_translations detects this if there's no variable used |
60 | set (GETTEXT_PACKAGE "midori") |
61 | add_definitions("-DGETTEXT_PACKAGE=\"${GETTEXT_PACKAGE}\"") |
62 | |
63 | === modified file 'katze/midori-paths.vala' |
64 | --- katze/midori-paths.vala 2014-04-03 00:49:01 +0000 |
65 | +++ katze/midori-paths.vala 2014-09-01 23:11:13 +0000 |
66 | @@ -17,7 +17,6 @@ |
67 | |
68 | extern const string LIBDIR; |
69 | extern const string MDATADIR; |
70 | -extern const string PACKAGE_NAME; |
71 | extern const string SYSCONFDIR; |
72 | extern const string MIDORI_VERSION_SUFFIX; |
73 | const string MODULE_PREFIX = "lib"; |
74 | |
75 | === modified file 'midori/CMakeLists.txt' |
76 | --- midori/CMakeLists.txt 2013-09-08 21:38:36 +0000 |
77 | +++ midori/CMakeLists.txt 2014-09-01 23:11:13 +0000 |
78 | @@ -16,10 +16,13 @@ |
79 | ${MIDORI_VALA_SOURCE} |
80 | PACKAGES |
81 | ${PKGS} |
82 | + katze |
83 | + midori |
84 | + gobject-fixes |
85 | + gtk-fixes |
86 | OPTIONS |
87 | ${VALAFLAGS} |
88 | -CUSTOM_VAPIS |
89 | - ${EXTRA_VAPIS} |
90 | + --vapidir=${CMAKE_CURRENT_SOURCE_DIR}/../vapi |
91 | GENERATE_VAPI |
92 | "${CMAKE_PROJECT_NAME}-core" |
93 | GENERATE_HEADER |
94 | |
95 | === modified file 'midori/midori-app.h' |
96 | --- midori/midori-app.h 2013-03-28 17:27:56 +0000 |
97 | +++ midori/midori-app.h 2014-09-01 23:11:13 +0000 |
98 | @@ -14,7 +14,7 @@ |
99 | |
100 | #include <katze/katze.h> |
101 | |
102 | -#include "midori-browser.h" |
103 | +#include "midori-core.h" |
104 | #include "midori-websettings.h" |
105 | |
106 | G_BEGIN_DECLS |
107 | |
108 | === removed file 'midori/midori-browser.h' |
109 | --- midori/midori-browser.h 2013-03-26 23:09:09 +0000 |
110 | +++ midori/midori-browser.h 1970-01-01 00:00:00 +0000 |
111 | @@ -1,199 +0,0 @@ |
112 | -/* |
113 | - Copyright (C) 2008 Christian Dywan <christian@twotoasts.de> |
114 | - |
115 | - This library is free software; you can redistribute it and/or |
116 | - modify it under the terms of the GNU Lesser General Public |
117 | - License as published by the Free Software Foundation; either |
118 | - version 2.1 of the License, or (at your option) any later version. |
119 | - |
120 | - See the file COPYING for the full license text. |
121 | -*/ |
122 | - |
123 | -#ifndef __MIDORI_BROWSER_H__ |
124 | -#define __MIDORI_BROWSER_H__ |
125 | - |
126 | -#include <katze/katze.h> |
127 | -#include "midori-view.h" |
128 | - |
129 | -G_BEGIN_DECLS |
130 | - |
131 | -#define MIDORI_TYPE_BROWSER \ |
132 | - (midori_browser_get_type ()) |
133 | -#define MIDORI_BROWSER(obj) \ |
134 | - (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_BROWSER, MidoriBrowser)) |
135 | -#define MIDORI_BROWSER_CLASS(klass) \ |
136 | - (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_BROWSER, MidoriBrowserClass)) |
137 | -#define MIDORI_IS_BROWSER(obj) \ |
138 | - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_BROWSER)) |
139 | -#define MIDORI_IS_BROWSER_CLASS(klass) \ |
140 | - (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_BROWSER)) |
141 | -#define MIDORI_BROWSER_GET_CLASS(obj) \ |
142 | - (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_BROWSER, MidoriBrowserClass)) |
143 | - |
144 | -typedef struct _MidoriBrowser MidoriBrowser; |
145 | -typedef struct _MidoriBrowserClass MidoriBrowserClass; |
146 | - |
147 | -struct _MidoriBrowserClass |
148 | -{ |
149 | - GtkWindowClass parent_class; |
150 | - |
151 | - /* Signals */ |
152 | - void |
153 | - (*window_object_cleared) (MidoriBrowser* browser, |
154 | -#ifndef HAVE_WEBKIT2 |
155 | - WebKitWebFrame* web_frame, |
156 | -#else |
157 | - void* web_frame, |
158 | -#endif |
159 | - JSContextRef* context, |
160 | - JSObjectRef* window_object); |
161 | - void |
162 | - (*statusbar_text_changed) (MidoriBrowser* browser, |
163 | - const gchar* text); |
164 | - void |
165 | - (*element_motion) (MidoriBrowser* browser, |
166 | - const gchar* link_uri); |
167 | - void |
168 | - (*new_window) (MidoriBrowser* browser, |
169 | - const gchar* uri); |
170 | - |
171 | - void |
172 | - (*add_tab) (MidoriBrowser* browser, |
173 | - GtkWidget* view); |
174 | - void |
175 | - (*remove_tab) (MidoriBrowser* browser, |
176 | - GtkWidget* view); |
177 | - void |
178 | - (*activate_action) (MidoriBrowser* browser, |
179 | - const gchar* name); |
180 | - void |
181 | - (*quit) (MidoriBrowser* browser); |
182 | -}; |
183 | - |
184 | -GType |
185 | -midori_browser_get_type (void) G_GNUC_CONST; |
186 | - |
187 | -MidoriBrowser* |
188 | -midori_browser_new (void); |
189 | - |
190 | -void |
191 | -midori_browser_add_tab (MidoriBrowser* browser, |
192 | - GtkWidget* widget); |
193 | - |
194 | -void |
195 | -midori_browser_close_tab (MidoriBrowser* browser, |
196 | - GtkWidget* widget); |
197 | - |
198 | -GtkWidget* |
199 | -midori_browser_add_item (MidoriBrowser* browser, |
200 | - KatzeItem* item); |
201 | - |
202 | -GtkWidget* |
203 | -midori_browser_add_uri (MidoriBrowser* browser, |
204 | - const gchar* uri); |
205 | - |
206 | -void |
207 | -midori_browser_activate_action (MidoriBrowser* browser, |
208 | - const gchar* name); |
209 | - |
210 | -void |
211 | -midori_browser_assert_action (MidoriBrowser* browser, |
212 | - const gchar* name); |
213 | - |
214 | -void |
215 | -midori_browser_block_action (MidoriBrowser* browser, |
216 | - GtkAction* action); |
217 | - |
218 | -void |
219 | -midori_browser_unblock_action (MidoriBrowser* browser, |
220 | - GtkAction* action); |
221 | - |
222 | -void |
223 | -midori_browser_set_action_visible (MidoriBrowser* browser, |
224 | - const gchar* name, |
225 | - gboolean visible); |
226 | - |
227 | -GtkActionGroup* |
228 | -midori_browser_get_action_group (MidoriBrowser* browser); |
229 | - |
230 | -void |
231 | -midori_browser_set_current_uri (MidoriBrowser* browser, |
232 | - const gchar* uri); |
233 | - |
234 | -const gchar* |
235 | -midori_browser_get_current_uri (MidoriBrowser* browser); |
236 | - |
237 | -void |
238 | -midori_browser_set_current_page_smartly (MidoriBrowser* browser, |
239 | - gint n); |
240 | - |
241 | -void |
242 | -midori_browser_set_current_tab_smartly (MidoriBrowser* browser, |
243 | - GtkWidget* view); |
244 | - |
245 | -void |
246 | -midori_browser_set_current_page (MidoriBrowser* browser, |
247 | - gint n); |
248 | - |
249 | -gint |
250 | -midori_browser_get_current_page (MidoriBrowser* browser); |
251 | - |
252 | -void |
253 | -midori_browser_set_current_item (MidoriBrowser* browser, |
254 | - KatzeItem* item); |
255 | - |
256 | -GtkWidget* |
257 | -midori_browser_get_nth_tab (MidoriBrowser* browser, |
258 | - gint n); |
259 | - |
260 | -void |
261 | -midori_browser_set_current_tab (MidoriBrowser* browser, |
262 | - GtkWidget* widget); |
263 | -#define midori_browser_set_tab midori_browser_set_current_tab |
264 | - |
265 | -GtkWidget* |
266 | -midori_browser_get_current_tab (MidoriBrowser* browser); |
267 | -#define midori_browser_get_tab midori_browser_get_current_tab |
268 | - |
269 | -gint |
270 | -midori_browser_page_num (MidoriBrowser* browser, |
271 | - GtkWidget* view); |
272 | - |
273 | -GList* |
274 | -midori_browser_get_tabs (MidoriBrowser* browser); |
275 | - |
276 | -gint |
277 | -midori_browser_get_n_pages (MidoriBrowser* browser); |
278 | - |
279 | -KatzeArray* |
280 | -midori_browser_get_proxy_array (MidoriBrowser* browser); |
281 | - |
282 | -MidoriBrowser* |
283 | -midori_browser_get_for_widget (GtkWidget* widget); |
284 | - |
285 | -void |
286 | -midori_browser_quit (MidoriBrowser* browser); |
287 | - |
288 | -const gchar** |
289 | -midori_browser_get_toolbar_actions (MidoriBrowser* browser); |
290 | - |
291 | -MidoriWebSettings* |
292 | -midori_browser_get_settings (MidoriBrowser* browser); |
293 | - |
294 | -void |
295 | -midori_browser_update_history (KatzeItem* item, |
296 | - const gchar* type, |
297 | - const gchar* event); |
298 | - |
299 | -void |
300 | -midori_browser_save_uri (MidoriBrowser* browser, |
301 | - MidoriView* view, |
302 | - const gchar* uri); |
303 | - |
304 | -void |
305 | -midori_browser_set_inactivity_reset (MidoriBrowser* browser, |
306 | - gint inactivity_reset); |
307 | - |
308 | -G_END_DECLS |
309 | - |
310 | -#endif /* __MIDORI_BROWSER_H__ */ |
311 | |
312 | === renamed file 'midori/midori-browser.c' => 'midori/midori-browser.vala' |
313 | --- midori/midori-browser.c 2014-08-31 10:33:28 +0000 |
314 | +++ midori/midori-browser.vala 2014-09-01 23:11:13 +0000 |
315 | @@ -1,993 +1,923 @@ |
316 | -/* |
317 | - Copyright (C) 2007-2013 Christian Dywan <christian@twotoasts.de> |
318 | - Copyright (C) 2008 Dale Whittaker <dayul@users.sf.net> |
319 | - Copyright (C) 2009 Jérôme Geulfucci <jeromeg@xfce.org> |
320 | - |
321 | - This library is free software; you can redistribute it and/or |
322 | - modify it under the terms of the GNU Lesser General Public |
323 | - License as published by the Free Software Foundation; either |
324 | - version 2.1 of the License, or (at your option) any later version. |
325 | - |
326 | - See the file COPYING for the full license text. |
327 | -*/ |
328 | - |
329 | -#include "midori-browser.h" |
330 | - |
331 | -#include "midori-app.h" |
332 | -#include "midori-extension.h" |
333 | -#include "midori-array.h" |
334 | -#include "midori-view.h" |
335 | -#include "midori-preferences.h" |
336 | -#include "midori-panel.h" |
337 | -#include "midori-locationaction.h" |
338 | -#include "midori-searchaction.h" |
339 | -#include "midori-findbar.h" |
340 | -#include "midori-platform.h" |
341 | -#include "midori-privatedata.h" |
342 | -#include "midori-core.h" |
343 | -#include "midori-privatedata.h" |
344 | -#include "midori-bookmarks-db.h" |
345 | -#include "katze-cellrenderercomboboxtext.h" |
346 | - |
347 | -#include "marshal.h" |
348 | - |
349 | -#include <glib/gi18n.h> |
350 | -#include <glib/gstdio.h> |
351 | -#include <gdk/gdkkeysyms.h> |
352 | -#include <string.h> |
353 | - |
354 | -#include <config.h> |
355 | - |
356 | -#ifdef HAVE_GRANITE |
357 | - #include <granite.h> |
358 | -#endif |
359 | - |
360 | -#ifdef HAVE_ZEITGEIST |
361 | - #include <zeitgeist.h> |
362 | -#endif |
363 | - |
364 | -#ifdef HAVE_UNISTD_H |
365 | - #include <unistd.h> |
366 | -#endif |
367 | - |
368 | -#include <sqlite3.h> |
369 | - |
370 | -#ifdef HAVE_X11_EXTENSIONS_SCRNSAVER_H |
371 | - #include <X11/Xlib.h> |
372 | - #include <X11/Xutil.h> |
373 | - #include <X11/extensions/scrnsaver.h> |
374 | - #include <gdk/gdkx.h> |
375 | -#endif |
376 | - |
377 | -struct _MidoriBrowser |
378 | -{ |
379 | - GtkWindow parent_instance; |
380 | - GtkActionGroup* action_group; |
381 | - GtkWidget* menubar; |
382 | - GtkWidget* throbber; |
383 | - GtkWidget* navigationbar; |
384 | - GtkWidget* bookmarkbar; |
385 | - |
386 | - GtkWidget* panel; |
387 | - GtkWidget* notebook; |
388 | - |
389 | - GtkWidget* inspector; |
390 | - GtkWidget* inspector_view; |
391 | - |
392 | - GtkWidget* find; |
393 | - |
394 | - GtkWidget* statusbar; |
395 | - GtkWidget* statusbar_contents; |
396 | - gchar* statusbar_text; |
397 | - |
398 | - gint last_window_width, last_window_height; |
399 | - guint alloc_timeout; |
400 | - guint panel_timeout; |
401 | - |
402 | - MidoriWebSettings* settings; |
403 | - KatzeArray* proxy_array; |
404 | - MidoriBookmarksDb* bookmarks; |
405 | - KatzeArray* trash; |
406 | - KatzeArray* search_engines; |
407 | - KatzeArray* history; |
408 | - MidoriHistoryDatabase* history_database; |
409 | - MidoriSpeedDial* dial; |
410 | - gboolean show_tabs; |
411 | - |
412 | - gboolean show_navigationbar; |
413 | - gboolean show_statusbar; |
414 | - guint maximum_history_age; |
415 | - guint last_web_search; |
416 | - |
417 | - gboolean bookmarkbar_populate; |
418 | -}; |
419 | - |
420 | -G_DEFINE_TYPE (MidoriBrowser, midori_browser, GTK_TYPE_WINDOW) |
421 | - |
422 | -enum |
423 | -{ |
424 | - PROP_0, |
425 | - |
426 | - PROP_MENUBAR, |
427 | - PROP_NAVIGATIONBAR, |
428 | - PROP_NOTEBOOK, |
429 | - PROP_PANEL, |
430 | - PROP_URI, |
431 | - PROP_TAB, |
432 | - PROP_LOAD_STATUS, |
433 | - PROP_STATUSBAR, |
434 | - PROP_STATUSBAR_TEXT, |
435 | - PROP_SETTINGS, |
436 | - PROP_PROXY_ITEMS, |
437 | - PROP_BOOKMARKS, |
438 | - PROP_TRASH, |
439 | - PROP_SEARCH_ENGINES, |
440 | - PROP_HISTORY, |
441 | - PROP_SPEED_DIAL, |
442 | - PROP_SHOW_TABS, |
443 | -}; |
444 | - |
445 | -enum |
446 | -{ |
447 | - NEW_WINDOW, |
448 | - ADD_TAB, |
449 | - REMOVE_TAB, |
450 | - MOVE_TAB, |
451 | - SWITCH_TAB, |
452 | - ACTIVATE_ACTION, |
453 | - ADD_DOWNLOAD, |
454 | - SEND_NOTIFICATION, |
455 | - POPULATE_TOOL_MENU, |
456 | - POPULATE_TOOLBAR_MENU, |
457 | - QUIT, |
458 | - SHOW_PREFERENCES, |
459 | - |
460 | - LAST_SIGNAL |
461 | -}; |
462 | - |
463 | -static guint signals[LAST_SIGNAL]; |
464 | - |
465 | -static void |
466 | -midori_browser_dispose (GObject* object); |
467 | - |
468 | -static void |
469 | -midori_browser_finalize (GObject* object); |
470 | - |
471 | -#ifdef HAVE_WEBKIT2 |
472 | -void download_created_destination_cb (WebKitDownload *download, |
473 | - gchar *destination, |
474 | - gpointer user_data); |
475 | -#endif |
476 | - |
477 | -static void |
478 | -midori_browser_set_property (GObject* object, |
479 | - guint prop_id, |
480 | - const GValue* value, |
481 | - GParamSpec* pspec); |
482 | - |
483 | -static void |
484 | -midori_browser_get_property (GObject* object, |
485 | - guint prop_id, |
486 | - GValue* value, |
487 | - GParamSpec* pspec); |
488 | - |
489 | -gboolean |
490 | -midori_browser_open_bookmark (MidoriBrowser* browser, |
491 | - KatzeItem* item); |
492 | - |
493 | -static void |
494 | -midori_bookmarkbar_populate (MidoriBrowser* browser); |
495 | -static void |
496 | -midori_bookmarkbar_populate_idle (MidoriBrowser* browser); |
497 | - |
498 | -static void |
499 | -midori_bookmarkbar_clear (GtkWidget* toolbar); |
500 | - |
501 | -static void |
502 | -_midori_browser_set_toolbar_style (MidoriBrowser* browser, |
503 | - MidoriToolbarStyle toolbar_style); |
504 | - |
505 | -static void |
506 | -midori_browser_settings_notify (MidoriWebSettings* web_settings, |
507 | - GParamSpec* pspec, |
508 | - MidoriBrowser* browser); |
509 | - |
510 | -void |
511 | -midori_panel_set_toolbar_style (MidoriPanel* panel, |
512 | - GtkToolbarStyle style); |
513 | - |
514 | -static void |
515 | -midori_browser_set_bookmarks (MidoriBrowser* browser, |
516 | - MidoriBookmarksDb* bookmarks); |
517 | - |
518 | -static void |
519 | -midori_browser_add_speed_dial (MidoriBrowser* browser); |
520 | - |
521 | -static void |
522 | -midori_browser_step_history (MidoriBrowser* browser, |
523 | - MidoriView* view); |
524 | - |
525 | -#define _action_by_name(brwsr, nme) \ |
526 | - gtk_action_group_get_action (brwsr->action_group, nme) |
527 | -#define _action_set_sensitive(brwsr, nme, snstv) \ |
528 | - gtk_action_set_sensitive (_action_by_name (brwsr, nme), snstv); |
529 | -#define _action_set_visible(brwsr, nme, vsbl) \ |
530 | - gtk_action_set_visible (_action_by_name (brwsr, nme), vsbl); |
531 | -#define _action_set_active(brwsr, nme, actv) \ |
532 | - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION ( \ |
533 | - _action_by_name (brwsr, nme)), actv); |
534 | - |
535 | -static void |
536 | -midori_browser_disconnect_tab (MidoriBrowser* browser, |
537 | - MidoriView* view); |
538 | - |
539 | -static gboolean |
540 | -midori_browser_is_fullscreen (MidoriBrowser* browser) |
541 | -{ |
542 | - GdkWindow* window = gtk_widget_get_window (GTK_WIDGET (browser)); |
543 | - GdkWindowState state = window ? gdk_window_get_state (window) : 0; |
544 | - return state & GDK_WINDOW_STATE_FULLSCREEN; |
545 | -} |
546 | - |
547 | -static gboolean |
548 | -_toggle_tabbar_smartly (MidoriBrowser* browser, |
549 | - gboolean ignore_fullscreen) |
550 | -{ |
551 | - gboolean has_tabs = midori_browser_get_n_pages (browser) > 1; |
552 | - gboolean show_tabs = !midori_browser_is_fullscreen (browser) || ignore_fullscreen; |
553 | - if (!browser->show_tabs) |
554 | - show_tabs = FALSE; |
555 | - midori_notebook_set_labels_visible (MIDORI_NOTEBOOK (browser->notebook), show_tabs); |
556 | - return has_tabs; |
557 | -} |
558 | - |
559 | -static void |
560 | -midori_browser_trash_clear_cb (KatzeArray* trash, |
561 | - MidoriBrowser* browser) |
562 | -{ |
563 | - gboolean trash_empty = katze_array_is_empty (browser->trash); |
564 | - _action_set_sensitive (browser, "UndoTabClose", !trash_empty); |
565 | - _action_set_sensitive (browser, "Trash", !trash_empty); |
566 | -} |
567 | - |
568 | -static void |
569 | -_midori_browser_update_actions (MidoriBrowser* browser) |
570 | -{ |
571 | - gboolean has_tabs = _toggle_tabbar_smartly (browser, FALSE); |
572 | - _action_set_sensitive (browser, "TabPrevious", has_tabs); |
573 | - _action_set_sensitive (browser, "TabNext", has_tabs); |
574 | - |
575 | - if (browser->trash) |
576 | - midori_browser_trash_clear_cb (browser->trash, browser); |
577 | -} |
578 | - |
579 | -static void |
580 | -midori_browser_update_secondary_icon (MidoriBrowser* browser, |
581 | - MidoriView* view, |
582 | - GtkAction* action) |
583 | -{ |
584 | - if (g_object_get_data (G_OBJECT (view), "news-feeds")) |
585 | - { |
586 | - midori_location_action_set_secondary_icon ( |
587 | - MIDORI_LOCATION_ACTION (action), STOCK_NEWS_FEED); |
588 | - _action_set_sensitive (browser, "AddNewsFeed", TRUE); |
589 | - } |
590 | - else |
591 | - { |
592 | - midori_location_action_set_secondary_icon ( |
593 | - MIDORI_LOCATION_ACTION (action), NULL); |
594 | - _action_set_sensitive (browser, "AddNewsFeed", FALSE); |
595 | - } |
596 | -} |
597 | - |
598 | -static void |
599 | -_midori_browser_update_interface (MidoriBrowser* browser, |
600 | - MidoriView* view) |
601 | -{ |
602 | - GtkAction* action; |
603 | - |
604 | - _action_set_sensitive (browser, "Back", midori_view_can_go_back (view)); |
605 | - _action_set_sensitive (browser, "Forward", midori_tab_can_go_forward (MIDORI_TAB (view))); |
606 | - _action_set_sensitive (browser, "Previous", |
607 | - midori_view_get_previous_page (view) != NULL); |
608 | - _action_set_sensitive (browser, "Next", |
609 | - midori_view_get_next_page (view) != NULL); |
610 | - |
611 | - _action_set_sensitive (browser, "AddSpeedDial", !midori_view_is_blank (view)); |
612 | - _action_set_sensitive (browser, "BookmarkAdd", !midori_view_is_blank (view)); |
613 | - _action_set_sensitive (browser, "MailTo", !midori_view_is_blank (view)); |
614 | - _action_set_sensitive (browser, "SaveAs", midori_tab_can_save (MIDORI_TAB (view))); |
615 | - _action_set_sensitive (browser, "ZoomIn", midori_view_can_zoom_in (view)); |
616 | - _action_set_sensitive (browser, "ZoomOut", midori_view_can_zoom_out (view)); |
617 | - _action_set_sensitive (browser, "ZoomNormal", |
618 | - midori_view_get_zoom_level (view) != 1.0f); |
619 | - _action_set_sensitive (browser, "Encoding", |
620 | - midori_tab_can_view_source (MIDORI_TAB (view))); |
621 | - _action_set_sensitive (browser, "SourceView", |
622 | - midori_tab_can_view_source (MIDORI_TAB (view))); |
623 | - _action_set_sensitive (browser, "SourceViewDom", |
624 | - midori_tab_can_view_source (MIDORI_TAB (view))); |
625 | - |
626 | - action = _action_by_name (browser, "NextForward"); |
627 | - if (midori_tab_can_go_forward (MIDORI_TAB (view))) |
628 | - { |
629 | - g_object_set (action, |
630 | - "stock-id", GTK_STOCK_GO_FORWARD, |
631 | - "tooltip", _("Go forward to the next page"), |
632 | - "sensitive", TRUE, NULL); |
633 | - } |
634 | - else |
635 | - { |
636 | - g_object_set (action, |
637 | - "stock-id", GTK_STOCK_MEDIA_NEXT, |
638 | - "tooltip", _("Go to the next sub-page"), |
639 | - "sensitive", midori_view_get_next_page (view) != NULL, NULL); |
640 | - } |
641 | - |
642 | - action = _action_by_name (browser, "Location"); |
643 | - if (midori_tab_is_blank (MIDORI_TAB (view))) |
644 | - { |
645 | - gchar* icon_names[] = { "edit-find-symbolic", "edit-find", NULL }; |
646 | - GIcon* icon = g_themed_icon_new_from_names (icon_names, -1); |
647 | - midori_location_action_set_primary_icon ( |
648 | - MIDORI_LOCATION_ACTION (action), icon, _("Web Search…")); |
649 | - g_object_unref (icon); |
650 | - } |
651 | - else |
652 | - midori_location_action_set_security_hint ( |
653 | - MIDORI_LOCATION_ACTION (action), midori_tab_get_security (MIDORI_TAB (view))); |
654 | - midori_browser_update_secondary_icon (browser, view, action); |
655 | -} |
656 | - |
657 | -static void |
658 | -_midori_browser_set_statusbar_text (MidoriBrowser* browser, |
659 | - MidoriView* view, |
660 | - const gchar* text) |
661 | -{ |
662 | - #if GTK_CHECK_VERSION (3, 2, 0) |
663 | - gboolean is_location = FALSE; |
664 | - #else |
665 | - GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); |
666 | - gboolean is_location = widget && GTK_IS_ENTRY (widget) |
667 | - && GTK_IS_ALIGNMENT (gtk_widget_get_parent (widget)); |
668 | - #endif |
669 | - |
670 | - katze_assign (browser->statusbar_text, midori_uri_format_for_display (text)); |
671 | - if (view == NULL) |
672 | - return; |
673 | - |
674 | - if (!gtk_widget_get_visible (browser->statusbar) && !is_location |
675 | - && text && *text) |
676 | - { |
677 | - #if GTK_CHECK_VERSION (3, 2, 0) |
678 | - midori_view_set_overlay_text (view, browser->statusbar_text); |
679 | - #else |
680 | - GtkAction* action = _action_by_name (browser, "Location"); |
681 | - MidoriLocationAction* location_action = MIDORI_LOCATION_ACTION (action); |
682 | - midori_location_action_set_text (location_action, browser->statusbar_text); |
683 | - midori_location_action_set_secondary_icon (location_action, NULL); |
684 | - #endif |
685 | - } |
686 | - else if (!gtk_widget_get_visible (browser->statusbar) && !is_location) |
687 | - { |
688 | - #if GTK_CHECK_VERSION (3, 2, 0) |
689 | - midori_view_set_overlay_text (view, NULL); |
690 | - #else |
691 | - GtkAction* action = _action_by_name (browser, "Location"); |
692 | - MidoriLocationAction* location_action = MIDORI_LOCATION_ACTION (action); |
693 | - midori_browser_update_secondary_icon (browser, view, action); |
694 | - midori_location_action_set_text (location_action, |
695 | - midori_view_get_display_uri (view)); |
696 | - #endif |
697 | - } |
698 | - else |
699 | - { |
700 | - gtk_statusbar_pop (GTK_STATUSBAR (browser->statusbar), 1); |
701 | - gtk_statusbar_push (GTK_STATUSBAR (browser->statusbar), 1, |
702 | - katze_str_non_null (browser->statusbar_text)); |
703 | - } |
704 | -} |
705 | - |
706 | -void |
707 | -midori_browser_set_current_page_smartly (MidoriBrowser* browser, |
708 | - gint n) |
709 | -{ |
710 | - if (!katze_object_get_boolean (browser->settings, |
711 | - "open-tabs-in-the-background")) |
712 | - midori_browser_set_current_page (browser, n); |
713 | -} |
714 | - |
715 | -/** |
716 | - * midori_browser_set_current_tab_smartly: |
717 | - * @browser: a #MidoriBrowser |
718 | - * @view: a #GtkWidget |
719 | - * |
720 | - * Switches to the tab containing @view iff open-tabs-in-the-background is %FALSE. |
721 | - * |
722 | - * Since: 0.4.9 |
723 | - **/ |
724 | -void |
725 | -midori_browser_set_current_tab_smartly (MidoriBrowser* browser, |
726 | - GtkWidget* view) |
727 | -{ |
728 | - if (!katze_object_get_boolean (browser->settings, |
729 | - "open-tabs-in-the-background")) |
730 | - midori_browser_set_current_tab (browser, view); |
731 | -} |
732 | - |
733 | -static void |
734 | -_midori_browser_update_progress (MidoriBrowser* browser, |
735 | - MidoriView* view) |
736 | -{ |
737 | - GtkAction* action; |
738 | - gdouble progress = midori_view_get_progress (view); |
739 | - gboolean loading = progress > 0.0; |
740 | - |
741 | - action = _action_by_name (browser, "Location"); |
742 | - midori_location_action_set_progress (MIDORI_LOCATION_ACTION (action), progress); |
743 | - |
744 | - _action_set_sensitive (browser, "Reload", !loading); |
745 | - _action_set_sensitive (browser, "Stop", loading); |
746 | - |
747 | - action = _action_by_name (browser, "ReloadStop"); |
748 | - if (!loading) |
749 | - { |
750 | - g_object_set (action, |
751 | - "stock-id", GTK_STOCK_REFRESH, |
752 | - "tooltip", _("Reload the current page"), NULL); |
753 | - } |
754 | - else |
755 | - { |
756 | - g_object_set (action, |
757 | - "stock-id", GTK_STOCK_STOP, |
758 | - "tooltip", _("Stop loading the current page"), NULL); |
759 | - } |
760 | - |
761 | - g_object_set (browser->throbber, "active", loading, "visible", loading, NULL); |
762 | -} |
763 | - |
764 | -/** |
765 | - * midori_browser_update_history: |
766 | - * @item: a #KatzeItem |
767 | - * @type: "website", "bookmark" or "download" |
768 | - * @event: "access", "leave", "modify", "delete" |
769 | - * |
770 | - * Since: 0.4.7 |
771 | - **/ |
772 | -void |
773 | -midori_browser_update_history (KatzeItem* item, |
774 | - const gchar* type, |
775 | - const gchar* event) |
776 | -{ |
777 | - g_return_if_fail (!KATZE_ITEM_IS_SEPARATOR (item)); |
778 | - |
779 | - #ifdef HAVE_ZEITGEIST |
780 | - const gchar* inter; |
781 | - if (strstr (event, "access")) |
782 | - inter = ZEITGEIST_ZG_ACCESS_EVENT; |
783 | - else if (strstr (event, "leave")) |
784 | - inter = ZEITGEIST_ZG_LEAVE_EVENT; |
785 | - else if (strstr (event, "modify")) |
786 | - inter = ZEITGEIST_ZG_MODIFY_EVENT; |
787 | - else if (strstr (event, "create")) |
788 | - inter = ZEITGEIST_ZG_CREATE_EVENT; |
789 | - else if (strstr (event, "delete")) |
790 | - inter = ZEITGEIST_ZG_DELETE_EVENT; |
791 | - else |
792 | - g_assert_not_reached (); |
793 | - |
794 | - /* FIXME: Should insert folders into the log (ZEITGEIST_NFO_BOOKMARK_FOLDER) */ |
795 | - if (KATZE_ITEM_IS_FOLDER (item)) |
796 | - return; |
797 | - |
798 | - zeitgeist_log_insert_events_no_reply (zeitgeist_log_get_default (), |
799 | - zeitgeist_event_new_full (inter, ZEITGEIST_ZG_USER_ACTIVITY, |
800 | - "application://midori.desktop", |
801 | - zeitgeist_subject_new_full ( |
802 | - katze_item_get_uri (item), |
803 | - strstr (type, "bookmark") ? ZEITGEIST_NFO_BOOKMARK : ZEITGEIST_NFO_WEBSITE, |
804 | - zeitgeist_manifestation_for_uri (katze_item_get_uri (item)), |
805 | - katze_item_get_meta_string (item, "mime-type"), NULL, katze_item_get_name (item), NULL), |
806 | - NULL), |
807 | - NULL); |
808 | - #endif |
809 | -} |
810 | - |
811 | -static void |
812 | -midori_browser_update_history_title (MidoriBrowser* browser, |
813 | - KatzeItem* item) |
814 | -{ |
815 | - sqlite3* db; |
816 | - static sqlite3_stmt* stmt = NULL; |
817 | - |
818 | - g_return_if_fail (katze_item_get_uri (item) != NULL); |
819 | - |
820 | - db = g_object_get_data (G_OBJECT (browser->history), "db"); |
821 | - g_return_if_fail (db != NULL); |
822 | - if (!stmt) |
823 | - { |
824 | - const gchar* sqlcmd; |
825 | - |
826 | - sqlcmd = "UPDATE history SET title=? WHERE uri = ? and date=?"; |
827 | - sqlite3_prepare_v2 (db, sqlcmd, -1, &stmt, NULL); |
828 | - } |
829 | - sqlite3_bind_text (stmt, 1, katze_item_get_name (item), -1, 0); |
830 | - sqlite3_bind_text (stmt, 2, katze_item_get_uri (item), -1, 0); |
831 | - sqlite3_bind_int64 (stmt, 3, katze_item_get_added (item)); |
832 | - |
833 | - if (sqlite3_step (stmt) != SQLITE_DONE) |
834 | - g_printerr (_("Failed to update title: %s\n"), sqlite3_errmsg (db)); |
835 | - sqlite3_reset (stmt); |
836 | - sqlite3_clear_bindings (stmt); |
837 | - |
838 | - midori_browser_update_history (item, "website", "access"); |
839 | -} |
840 | - |
841 | -/** |
842 | - * midori_browser_assert_action: |
843 | - * @browser: a #MidoriBrowser |
844 | - * @name: action, setting=value expression or extension=true|false |
845 | - * |
846 | - * Assert that @name is a valid action or setting expression, |
847 | - * if it fails the program will terminate with an error. |
848 | - * To be used with command line interfaces. |
849 | - * |
850 | - * Since: 0.5.0 |
851 | - **/ |
852 | -void |
853 | -midori_browser_assert_action (MidoriBrowser* browser, |
854 | - const gchar* name) |
855 | -{ |
856 | - g_return_if_fail (MIDORI_IS_BROWSER (browser)); |
857 | - g_return_if_fail (name != NULL); |
858 | - |
859 | - if (strchr (name, '=')) |
860 | - { |
861 | - gchar** parts = g_strsplit (name, "=", 0); |
862 | - GObjectClass* class = G_OBJECT_GET_CLASS (browser->settings); |
863 | - GParamSpec* pspec = g_object_class_find_property (class, parts[0]); |
864 | - if (pspec != NULL) |
865 | - { |
866 | - GType type = G_PARAM_SPEC_TYPE (pspec); |
867 | - if (!( |
868 | - (type == G_TYPE_PARAM_BOOLEAN && (!strcmp (parts[1], "true") || !strcmp (parts[1], "false"))) |
869 | - || type == G_TYPE_PARAM_STRING |
870 | - || type == G_TYPE_PARAM_INT |
871 | - || type == G_TYPE_PARAM_FLOAT |
872 | - || type == G_TYPE_PARAM_DOUBLE |
873 | - || type == G_TYPE_PARAM_ENUM)) |
874 | - midori_error (_("Value '%s' is invalid for %s"), parts[1], parts[0]); |
875 | - } |
876 | - else |
877 | - { |
878 | - gchar* extension_path = midori_paths_get_lib_path (PACKAGE_NAME); |
879 | - GObject* extension = midori_extension_load_from_file (extension_path, parts[0], FALSE, FALSE); |
880 | - g_free (extension_path); |
881 | - if (!extension || (strcmp (parts[1], "true") && strcmp (parts[1], "false"))) |
882 | - midori_error (_("Unexpected setting '%s'"), name); |
883 | - } |
884 | - g_strfreev (parts); |
885 | - } |
886 | - else |
887 | - { |
888 | - GtkAction* action = _action_by_name (browser, name); |
889 | - if (!action) |
890 | - midori_error (_("Unexpected action '%s'."), name); |
891 | - } |
892 | -} |
893 | - |
894 | -void |
895 | -midori_app_set_browsers (MidoriApp* app, |
896 | - KatzeArray* browsers, |
897 | - MidoriBrowser* browser); |
898 | - |
899 | -static void |
900 | -_midori_browser_activate_action (MidoriBrowser* browser, |
901 | - const gchar* name) |
902 | -{ |
903 | - g_return_if_fail (name != NULL); |
904 | - |
905 | - if (strchr (name, '=')) |
906 | - { |
907 | - gchar** parts = g_strsplit (name, "=", 0); |
908 | - GObjectClass* class = G_OBJECT_GET_CLASS (browser->settings); |
909 | - GParamSpec* pspec = g_object_class_find_property (class, parts[0]); |
910 | - if (pspec != NULL) |
911 | - { |
912 | - GType type = G_PARAM_SPEC_TYPE (pspec); |
913 | - if (type == G_TYPE_PARAM_BOOLEAN && !strcmp ("true", parts[1])) |
914 | - g_object_set (browser->settings, parts[0], TRUE, NULL); |
915 | - else if (type == G_TYPE_PARAM_BOOLEAN && !strcmp ("false", parts[1])) |
916 | - g_object_set (browser->settings, parts[0], FALSE, NULL); |
917 | - else if (type == G_TYPE_PARAM_STRING) |
918 | - g_object_set (browser->settings, parts[0], parts[1], NULL); |
919 | - else if (type == G_TYPE_PARAM_INT || type == G_TYPE_PARAM_UINT) |
920 | - g_object_set (browser->settings, parts[0], atoi (parts[1]), NULL); |
921 | - else if (type == G_TYPE_PARAM_FLOAT || type == G_TYPE_PARAM_DOUBLE) |
922 | - g_object_set (browser->settings, parts[0], g_ascii_strtod (parts[1], NULL), NULL); |
923 | - else if (type == G_TYPE_PARAM_ENUM) |
924 | - { |
925 | - GEnumClass* enum_class = G_ENUM_CLASS (g_type_class_peek (pspec->value_type)); |
926 | - GEnumValue* enum_value = g_enum_get_value_by_name (enum_class, parts[1]); |
927 | - if (enum_value != NULL) |
928 | - g_object_set (browser->settings, parts[0], enum_value->value, NULL); |
929 | - else |
930 | - g_warning (_("Value '%s' is invalid for %s"), parts[1], parts[0]); |
931 | - } |
932 | - else |
933 | - g_warning (_("Value '%s' is invalid for %s"), parts[1], parts[0]); |
934 | - } |
935 | - else |
936 | - { |
937 | - gchar* extension_path = midori_paths_get_lib_path (PACKAGE_NAME); |
938 | - GObject* extension = midori_extension_load_from_file (extension_path, parts[0], TRUE, FALSE); |
939 | - MidoriApp* app = midori_app_new_proxy (NULL); |
940 | - g_object_set (app, |
941 | - "settings", browser->settings, |
942 | - NULL); |
943 | - /* FIXME: tabs of multiple windows */ |
944 | - KatzeArray* browsers = katze_array_new (MIDORI_TYPE_BROWSER); |
945 | - katze_array_add_item (browsers, browser); |
946 | - midori_app_set_browsers (app, browsers, browser); |
947 | - g_free (extension_path); |
948 | - if (extension && !strcmp (parts[1], "true")) |
949 | - midori_extension_activate (extension, parts[0], TRUE, app); |
950 | - else if (extension && !strcmp (parts[1], "false")) |
951 | - midori_extension_deactivate (MIDORI_EXTENSION (extension)); |
952 | - else |
953 | - g_warning (_("Unexpected setting '%s'"), name); |
954 | - } |
955 | - g_strfreev (parts); |
956 | - } |
957 | - else |
958 | - { |
959 | - GtkAction* action = _action_by_name (browser, name); |
960 | - if (action) |
961 | - gtk_action_activate (action); |
962 | - else |
963 | - g_warning (_("Unexpected action '%s'."), name); |
964 | - } |
965 | -} |
966 | - |
967 | -static void |
968 | -midori_view_notify_icon_cb (MidoriView* view, |
969 | - GParamSpec* pspec, |
970 | - MidoriBrowser* browser) |
971 | -{ |
972 | - if (midori_browser_get_current_tab (browser) != (GtkWidget*)view) |
973 | - return; |
974 | - |
975 | - if (midori_paths_get_runtime_mode () == MIDORI_RUNTIME_MODE_APP) |
976 | - gtk_window_set_icon (GTK_WINDOW (browser), midori_view_get_icon (view)); |
977 | -} |
978 | - |
979 | -static void |
980 | -midori_view_notify_load_status_cb (GtkWidget* widget, |
981 | - GParamSpec* pspec, |
982 | - MidoriBrowser* browser) |
983 | -{ |
984 | - MidoriView* view = MIDORI_VIEW (widget); |
985 | - MidoriLoadStatus load_status = midori_view_get_load_status (view); |
986 | - |
987 | - if (widget == midori_browser_get_current_tab (browser)) |
988 | - { |
989 | - if (load_status == MIDORI_LOAD_COMMITTED) |
990 | - { |
991 | - const gchar* uri = midori_view_get_display_uri (view); |
992 | - GtkAction* action = _action_by_name (browser, "Location"); |
993 | - midori_location_action_set_text ( |
994 | - MIDORI_LOCATION_ACTION (action), uri); |
995 | - |
996 | - /* Focus the urlbar on blank pages */ |
997 | - if (midori_view_is_blank (view)) |
998 | - midori_browser_activate_action (browser, "Location"); |
999 | - } |
1000 | - |
1001 | - _midori_browser_update_interface (browser, view); |
1002 | - _midori_browser_set_statusbar_text (browser, view, NULL); |
1003 | - } |
1004 | - |
1005 | - if (load_status == MIDORI_LOAD_FINISHED) |
1006 | - katze_item_set_meta_string (midori_view_get_proxy_item (view), |
1007 | - "history-step", NULL); |
1008 | - |
1009 | - g_object_notify (G_OBJECT (browser), "load-status"); |
1010 | -} |
1011 | - |
1012 | -static void |
1013 | -midori_view_notify_progress_cb (GtkWidget* view, |
1014 | - GParamSpec* pspec, |
1015 | - MidoriBrowser* browser) |
1016 | -{ |
1017 | - if (view == midori_browser_get_current_tab (browser)) |
1018 | - _midori_browser_update_progress (browser, MIDORI_VIEW (view)); |
1019 | -} |
1020 | - |
1021 | -static void |
1022 | -midori_view_notify_uri_cb (GtkWidget* widget, |
1023 | - GParamSpec* pspec, |
1024 | - MidoriBrowser* browser) |
1025 | -{ |
1026 | - if (widget == midori_browser_get_current_tab (browser)) |
1027 | - { |
1028 | - MidoriView* view = MIDORI_VIEW (widget); |
1029 | - const gchar* uri = midori_view_get_display_uri (view); |
1030 | - GtkAction* action = _action_by_name (browser, "Location"); |
1031 | - midori_location_action_set_text (MIDORI_LOCATION_ACTION (action), uri); |
1032 | - _action_set_sensitive (browser, "Back", midori_view_can_go_back (view)); |
1033 | - _action_set_sensitive (browser, "Forward", midori_tab_can_go_forward (MIDORI_TAB (view))); |
1034 | - g_object_notify (G_OBJECT (browser), "uri"); |
1035 | - } |
1036 | -} |
1037 | - |
1038 | -static void |
1039 | -midori_browser_set_title (MidoriBrowser* browser, |
1040 | - const gchar* title) |
1041 | -{ |
1042 | - const gchar* custom_title = midori_settings_get_custom_title (MIDORI_SETTINGS (browser->settings)); |
1043 | - if (custom_title && *custom_title) |
1044 | - gtk_window_set_title (GTK_WINDOW (browser), custom_title); |
1045 | - else if (katze_object_get_boolean (browser->settings, "enable-private-browsing")) |
1046 | - { |
1047 | - gchar* window_title = g_strdup_printf (_("%s (Private Browsing)"), title); |
1048 | - gtk_window_set_title (GTK_WINDOW (browser), window_title); |
1049 | - g_free (window_title); |
1050 | - } |
1051 | - else |
1052 | - gtk_window_set_title (GTK_WINDOW (browser), title); |
1053 | -} |
1054 | - |
1055 | -static void |
1056 | -midori_view_notify_title_cb (GtkWidget* widget, |
1057 | - GParamSpec* pspec, |
1058 | - MidoriBrowser* browser) |
1059 | -{ |
1060 | - MidoriView* view = MIDORI_VIEW (widget); |
1061 | - if (widget == midori_browser_get_current_tab (browser)) |
1062 | - { |
1063 | - midori_browser_set_title (browser, midori_view_get_display_title (view)); |
1064 | - g_object_notify (G_OBJECT (browser), "title"); |
1065 | - } |
1066 | - midori_browser_step_history (browser, view); |
1067 | -} |
1068 | - |
1069 | -static void |
1070 | -midori_browser_step_history (MidoriBrowser* browser, |
1071 | - MidoriView* view) |
1072 | -{ |
1073 | - if (midori_view_get_load_status (view) != MIDORI_LOAD_COMMITTED) |
1074 | - return; |
1075 | - if (!browser->history_database || !browser->maximum_history_age) |
1076 | - return; |
1077 | - |
1078 | - KatzeItem* proxy = midori_view_get_proxy_item (view); |
1079 | - const gchar* proxy_uri = katze_item_get_uri (proxy); |
1080 | - if (midori_uri_is_blank (proxy_uri)) |
1081 | - return; |
1082 | - |
1083 | - const gchar* history_step = katze_item_get_meta_string (proxy, "history-step"); |
1084 | - if (history_step == NULL) |
1085 | - { |
1086 | - GError* error = NULL; |
1087 | - time_t now = time (NULL); |
1088 | - katze_item_set_added (proxy, now); |
1089 | - gint64 day = sokoke_time_t_to_julian (&now); |
1090 | - midori_history_database_insert (browser->history_database, |
1091 | - katze_item_get_uri (proxy), |
1092 | - katze_item_get_name (proxy), |
1093 | - katze_item_get_added (proxy), day, &error); |
1094 | - if (error != NULL) |
1095 | - { |
1096 | - g_printerr (_("Failed to insert new history item: %s\n"), error->message); |
1097 | - g_error_free (error); |
1098 | - return; |
1099 | - } |
1100 | - katze_item_set_meta_string (proxy, "history-step", "update"); |
1101 | - /* FIXME: No signal for adding/ removing */ |
1102 | - katze_array_add_item (browser->history, proxy); |
1103 | - katze_array_remove_item (browser->history, proxy); |
1104 | - } |
1105 | - else if (!strcmp (history_step, "update")) |
1106 | - { |
1107 | - if (proxy->name != NULL) |
1108 | - midori_browser_update_history_title (browser, proxy); |
1109 | - } |
1110 | - else if (!strcmp (history_step, "ignore")) |
1111 | - { |
1112 | - /* This is set when restoring sessions */ |
1113 | - } |
1114 | - else |
1115 | - g_warning ("Unexpected history-step: %s", history_step); |
1116 | -} |
1117 | - |
1118 | -static void |
1119 | -midori_view_notify_zoom_level_cb (GtkWidget* view, |
1120 | - GParamSpec* pspec, |
1121 | - MidoriBrowser* browser) |
1122 | -{ |
1123 | - if (view == midori_browser_get_current_tab (browser)) |
1124 | - _action_set_sensitive (browser, "ZoomNormal", |
1125 | - midori_view_get_zoom_level (MIDORI_VIEW (view)) != 1.0f); |
1126 | -} |
1127 | - |
1128 | -static void |
1129 | -midori_view_notify_statusbar_text_cb (GtkWidget* view, |
1130 | - GParamSpec* pspec, |
1131 | - MidoriBrowser* browser) |
1132 | -{ |
1133 | - gchar* text; |
1134 | - |
1135 | - if (view == midori_browser_get_current_tab (browser)) |
1136 | - { |
1137 | - g_object_get (view, "statusbar-text", &text, NULL); |
1138 | - _midori_browser_set_statusbar_text (browser, MIDORI_VIEW (view), text); |
1139 | - g_free (text); |
1140 | - } |
1141 | -} |
1142 | - |
1143 | -static gboolean |
1144 | -midori_bookmark_folder_button_reach_parent (GtkTreeModel* model, GtkTreeIter *iter, gint64 parentid) |
1145 | -{ |
1146 | - do |
1147 | - { |
1148 | - gint64 id; |
1149 | - |
1150 | - gtk_tree_model_get (model, iter, 1, &id, -1); |
1151 | - |
1152 | - if (parentid == id) |
1153 | - return TRUE; |
1154 | - |
1155 | - if (gtk_tree_model_iter_has_child (model, iter)) |
1156 | - { |
1157 | - GtkTreeIter child; |
1158 | - gtk_tree_model_iter_children (model, &child, iter); |
1159 | - if (midori_bookmark_folder_button_reach_parent (model, &child, parentid)) |
1160 | - { |
1161 | - *iter = child; |
1162 | - return TRUE; |
1163 | - } |
1164 | - } |
1165 | - } |
1166 | - while (gtk_tree_model_iter_next (model, iter)); |
1167 | - |
1168 | - return FALSE; |
1169 | -} |
1170 | - |
1171 | -typedef struct _FolderEntry |
1172 | -{ |
1173 | - const gchar *title; |
1174 | - gint64 id; |
1175 | - gint64 parentid; |
1176 | -} FolderEntry; |
1177 | - |
1178 | -static void |
1179 | -midori_bookmark_folder_free_folder_entry (FolderEntry* folder) |
1180 | -{ |
1181 | - g_free ((gpointer)folder->title); |
1182 | -} |
1183 | - |
1184 | -static GtkWidget* |
1185 | -midori_bookmark_folder_button_new (MidoriBookmarksDb* array, |
1186 | - gint64 selected_parentid) |
1187 | -{ |
1188 | - GtkTreeStore* model; |
1189 | - GtkWidget* combo; |
1190 | - GtkCellRenderer* renderer; |
1191 | - guint n; |
1192 | - sqlite3* db; |
1193 | - sqlite3_stmt* statement; |
1194 | - gint result; |
1195 | - const gchar* sqlcmd = "SELECT title, id, parentid FROM bookmarks WHERE uri='' ORDER BY parentid, title ASC"; |
1196 | - gint64 current_parentid; |
1197 | - GtkTreeIter tree_iter; |
1198 | - GtkTreeIter stock_parent_iter; |
1199 | - GtkTreeIter* parent_iter; |
1200 | - GList *folders = NULL; |
1201 | - |
1202 | - db = g_object_get_data (G_OBJECT (array), "db"); |
1203 | - g_return_val_if_fail (db != NULL, NULL); |
1204 | - |
1205 | - /* folder combo box model content: |
1206 | - ** 0: title |
1207 | - ** 1: id |
1208 | - */ |
1209 | - model = gtk_tree_store_new (2, G_TYPE_STRING, G_TYPE_INT64); |
1210 | - combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (model)); |
1211 | - |
1212 | - /* setup combo layout |
1213 | - ** 0: a folder icon |
1214 | - ** 1: the folder name |
1215 | - */ |
1216 | - |
1217 | - gtk_cell_layout_clear (GTK_CELL_LAYOUT (combo)); |
1218 | - |
1219 | - renderer = gtk_cell_renderer_pixbuf_new (); |
1220 | - g_object_set (G_OBJECT (renderer), |
1221 | - "stock-id", GTK_STOCK_DIRECTORY, |
1222 | - "stock-size", GTK_ICON_SIZE_MENU, |
1223 | - NULL); |
1224 | - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, FALSE); |
1225 | - |
1226 | - renderer = katze_cell_renderer_combobox_text_new (); |
1227 | - g_object_set (G_OBJECT (renderer), |
1228 | - "width-chars", 40, /* FIXME: figure out a way to define an acceptable string length */ |
1229 | - "ellipsize", PANGO_ELLIPSIZE_END, |
1230 | - "unfolded-text", _("Select [text]"), |
1231 | - NULL); |
1232 | - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE); |
1233 | - gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), renderer, "text", 0); |
1234 | - |
1235 | - /* read the folders list from the database */ |
1236 | - /* FIXME: this should be a service of midori/midori-bookmarks-db */ |
1237 | - |
1238 | - if ((result = sqlite3_prepare_v2 (db, sqlcmd, -1, &statement, NULL)) == SQLITE_OK) |
1239 | - { |
1240 | - while ((result = sqlite3_step (statement)) == SQLITE_ROW) |
1241 | - { |
1242 | - FolderEntry* folder = g_new (FolderEntry, 1); |
1243 | - |
1244 | - folder->title = g_strdup ((const gchar*)sqlite3_column_text (statement, 0)); |
1245 | - folder->id = sqlite3_column_int64 (statement, 1); |
1246 | - folder->parentid = sqlite3_column_int64 (statement, 2); |
1247 | - |
1248 | - folders = g_list_append (folders, folder); |
1249 | - } |
1250 | - |
1251 | - sqlite3_clear_bindings (statement); |
1252 | - sqlite3_reset (statement); |
1253 | - } |
1254 | - |
1255 | - /* populate the combo box */ |
1256 | - /* FIXME: here we should have the root bookmark array's name and id, not hard encoded values */ |
1257 | - |
1258 | - gtk_tree_store_insert_with_values (model, &tree_iter, NULL, G_MAXINT, |
1259 | - 0, _("Bookmarks"), 1, (gint64)-1, -1); |
1260 | - gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo), &tree_iter); |
1261 | - |
1262 | - current_parentid = -1; |
1263 | - parent_iter = NULL; |
1264 | - n = 1; |
1265 | - while (g_list_first (folders)) |
1266 | - { |
1267 | - gboolean something_done = FALSE; |
1268 | - GList* list_iter = g_list_first (folders); |
1269 | - |
1270 | - do |
1271 | - { |
1272 | - FolderEntry* folder = list_iter->data; |
1273 | - const gchar* title = folder->title; |
1274 | - gint64 id = folder->id; |
1275 | - gint64 parentid = folder->parentid; |
1276 | - |
1277 | - if (parentid != current_parentid) /* optimize case of sub-folders of the same parent */ |
1278 | - { |
1279 | - if (!parentid) |
1280 | - { |
1281 | - /* folder's parent is the stree store root */ |
1282 | - |
1283 | - current_parentid = -1; |
1284 | - parent_iter = NULL; |
1285 | + |
1286 | +namespace Midori { |
1287 | + public class Browser : Gtk.Window { |
1288 | + struct FolderEntry { |
1289 | + string title; |
1290 | + int64 id; |
1291 | + int64 parentid; |
1292 | + } |
1293 | + |
1294 | + static construct { |
1295 | +#if GTK_VERSION_3_0_0 |
1296 | + Gtk.rc_parse ("style \"tool-button-style\"\n {\n" + |
1297 | + "GtkToolButton::icon-spacing = 2\n }\n" + |
1298 | + "widget \"MidoriBrowser.*.MidoriBookmarkbar.Gtk*ToolButton\" " + |
1299 | + "style \"tool-button-style\"\n" + |
1300 | + "widget \"MidoriBrowser.*.MidoriFindbar.Gtk*ToolButton\" " + |
1301 | + "style \"tool-button-style\"\n"); |
1302 | +#endif |
1303 | + } |
1304 | + |
1305 | + public signal Browser new_window (Browser? new_window); |
1306 | + public signal void move_tab (Gtk.Widget notebook, int current_position, int new_position); |
1307 | + public signal void switch_tab (Object old_tab, Object new_tab); |
1308 | + public signal void add_download (WebKit.Download download); |
1309 | + public signal void send_notification (string title, string message); |
1310 | + public signal void populate_tool_menu (Gtk.Menu menu); |
1311 | + public signal void populate_toolbar_menu (Gtk.Menu menu); |
1312 | + public signal void show_preferences (Katze.Preferences preferences); |
1313 | + |
1314 | + public Gtk.Toolbar navigationbar { get; private set; } |
1315 | + public Gtk.MenuBar menubar { get; private set; } |
1316 | + public Notebook notebook { get; private set; } |
1317 | + public Panel panel { get; private set; } |
1318 | + public Katze.Array proxy_array { get; private set; } |
1319 | + |
1320 | + public unowned string uri { |
1321 | + get { return get_current_uri (); } |
1322 | + set { set_current_uri (value); } |
1323 | + } |
1324 | + |
1325 | + public unowned Tab tab { |
1326 | + get { return get_current_tab (); } |
1327 | + set { set_current_tab (value); } |
1328 | + } |
1329 | + |
1330 | + public LoadStatus load_status { |
1331 | + get { |
1332 | + var tab = get_current_tab (); |
1333 | + return tab != null ? tab.load_status : LoadStatus.FINISHED; |
1334 | + } |
1335 | + } |
1336 | + |
1337 | + /** |
1338 | + * MidoriBrowser:statusbar: |
1339 | + * |
1340 | + * The widget representing the statusbar contents. This is |
1341 | + * not an actual #GtkStatusbar but rather a #GtkBox. |
1342 | + */ |
1343 | + public Gtk.Statusbar statusbar { get; private set; } |
1344 | + |
1345 | + /** |
1346 | + * MidoriBrowser:statusbar-text: |
1347 | + * |
1348 | + * The text that is displayed in the statusbar. |
1349 | + * |
1350 | + * This value reflects changes to the text visible in the statusbar, such |
1351 | + * as the uri of a hyperlink the mouse hovers over or the description of |
1352 | + * a menuitem. |
1353 | + * |
1354 | + * Setting this value changes the displayed text until the next change. |
1355 | + */ |
1356 | + public string statusbar_text { |
1357 | + get { |
1358 | + return _statusbar_text; |
1359 | + } |
1360 | + set { |
1361 | + _set_statusbar_text ((View) tab, value); |
1362 | + } |
1363 | + } |
1364 | + |
1365 | + /** |
1366 | + * MidoriBrowser:settings: |
1367 | + * |
1368 | + * An associated settings instance that is shared among all web views. |
1369 | + * |
1370 | + * Setting this value is propagated to every present web view. Also |
1371 | + * every newly created web view will use this instance automatically. |
1372 | + * |
1373 | + * If no settings are specified a default will be used. |
1374 | + */ |
1375 | + public WebSettings settings { |
1376 | + get { |
1377 | + return _settings; |
1378 | + } |
1379 | + set { |
1380 | + _settings.notify.disconnect (settings_notify); |
1381 | + _settings = value; |
1382 | + |
1383 | + if (_settings == null) |
1384 | + _settings = new WebSettings (); |
1385 | + |
1386 | + update_settings (); |
1387 | + _settings.set_data<ulong> ("handle-settings-notify", _settings.notify.connect (settings_notify)); |
1388 | + |
1389 | + foreach (var tab in get_tabs ()) |
1390 | + ((View) tab).settings = _settings; |
1391 | + } |
1392 | + } |
1393 | + |
1394 | + /** |
1395 | + * MidoriBrowser:proxy-items: |
1396 | + * |
1397 | + * The open views, automatically updated, for session management. |
1398 | + * |
1399 | + * Since: 0.4.8 |
1400 | + */ |
1401 | + public Katze.Array proxy_items { get; private set; } |
1402 | + |
1403 | + /** |
1404 | + * MidoriBrowser:bookmarks: |
1405 | + * |
1406 | + * The bookmarks folder, containing all bookmarks. |
1407 | + * |
1408 | + * This is actually a reference to a bookmarks instance, |
1409 | + * so if bookmarks should be used it must be initially set. |
1410 | + */ |
1411 | + public BookmarksDb? bookmarks { |
1412 | + get { |
1413 | + return _bookmarks; |
1414 | + } |
1415 | + set { |
1416 | + _set_bookmarks (value); |
1417 | + } |
1418 | + } |
1419 | + |
1420 | + /** |
1421 | + * MidoriBrowser:trash: |
1422 | + * |
1423 | + * The trash, that collects all closed tabs and windows. |
1424 | + * |
1425 | + * This is actually a reference to a trash instance, so if a trash should |
1426 | + * be used it must be initially set. |
1427 | + * |
1428 | + * Note: In the future the trash might collect other types of items. |
1429 | + */ |
1430 | + public Katze.Array? trash { |
1431 | + get { |
1432 | + return _trash; |
1433 | + } |
1434 | + set { |
1435 | + _trash = value; |
1436 | + |
1437 | + var trash_action = (Katze.ArrayAction) action_group.get_action ("Trash"); |
1438 | + trash_action.array = _trash; |
1439 | + trash_action.reversed = true; |
1440 | + |
1441 | + action_set_visible ("Trash", _trash != null); |
1442 | + action_set_visible ("UndoTabClose", _trash != null); |
1443 | + |
1444 | + if (trash != null) { |
1445 | + trash.clear.connect_after (trash_clear_cb); |
1446 | + trash_clear_cb (); |
1447 | } |
1448 | - else if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &tree_iter)) |
1449 | - { |
1450 | - if (midori_bookmark_folder_button_reach_parent ( |
1451 | - GTK_TREE_MODEL (model), &tree_iter, parentid)) |
1452 | - { |
1453 | - /* folder's parent found in the tree store */ |
1454 | - |
1455 | - current_parentid = parentid; |
1456 | - stock_parent_iter = tree_iter; |
1457 | - parent_iter = &stock_parent_iter; |
1458 | + } |
1459 | + } |
1460 | + |
1461 | + /** |
1462 | + * MidoriBrowser:search-engines: |
1463 | + * |
1464 | + * The list of search engines to be used for web search. |
1465 | + * |
1466 | + * This is actually a reference to a search engines instance, |
1467 | + * so if search engines should be used it must be initially set. |
1468 | + */ |
1469 | + public Katze.Array? search_engines { |
1470 | + get { |
1471 | + return _search_engines; |
1472 | + } |
1473 | + set { |
1474 | + _search_engines = value; |
1475 | + |
1476 | + /* FIXME: Disconnect handlers */ |
1477 | + ((LocationAction) action_group.get_action ("Location")).set_search_engines (_search_engines); |
1478 | + var search_action = (SearchAction) action_group.get_action ("Search"); |
1479 | + search_action.search_engines = _search_engines; |
1480 | + /* FIXME: Connect to updates */ |
1481 | + |
1482 | + if (_search_engines != null) { |
1483 | + var default_search = settings.location_entry_search; |
1484 | + last_web_search = settings.last_web_search; |
1485 | + |
1486 | + var item = search_engines.get_nth_item (last_web_search); |
1487 | + search_action.current_item = item; |
1488 | + |
1489 | + if (default_search != null && (item = (Katze.Item) search_engines.find_uri (default_search)) != null) { |
1490 | + search_action.default_item = item; |
1491 | } |
1492 | + } |
1493 | + } |
1494 | + } |
1495 | + |
1496 | + /** |
1497 | + * MidoriBrowser:history: |
1498 | + * |
1499 | + * The list of history items. |
1500 | + * |
1501 | + * This is actually a reference to a history instance, |
1502 | + * so if history should be used it must be initially set. |
1503 | + */ |
1504 | + public Katze.Array? history { |
1505 | + get { |
1506 | + return _history; |
1507 | + } |
1508 | + set { |
1509 | + _set_history (value); |
1510 | + } |
1511 | + } |
1512 | + |
1513 | + /** |
1514 | + * MidoriBrowser:speed-dial: |
1515 | + * |
1516 | + * The speed dial configuration file. |
1517 | + * |
1518 | + * Since: 0.3.4 |
1519 | + * Since 0.4.7 this is a Midori.SpeedDial instance. |
1520 | + */ |
1521 | + public SpeedDial? dial { |
1522 | + get { |
1523 | + return _dial; |
1524 | + } |
1525 | + set { |
1526 | + if (_dial != null) |
1527 | + _dial.refresh.disconnect (speed_dial_refresh_cb); |
1528 | + |
1529 | + _dial = value; |
1530 | + |
1531 | + if (_dial != null) |
1532 | + dial.refresh.connect (speed_dial_refresh_cb); |
1533 | + } |
1534 | + } |
1535 | + |
1536 | + /** |
1537 | + * MidoriBrowser:show-tabs: |
1538 | + * |
1539 | + * Whether or not to show tabs. |
1540 | + * |
1541 | + * If disabled, no tab labels are shown. This is intended for |
1542 | + * extensions that want to provide alternative tab labels. |
1543 | + * |
1544 | + * Since 0.1.8 |
1545 | + */ |
1546 | + public bool show_tabs { |
1547 | + get { |
1548 | + return _show_tabs; |
1549 | + } |
1550 | + set { |
1551 | + _show_tabs = value; |
1552 | + toggle_tabbar_smartly (false); |
1553 | + } |
1554 | + } |
1555 | + |
1556 | + Gtk.ActionGroup action_group; |
1557 | + Gtk.Spinner throbber; |
1558 | + |
1559 | + Gtk.Toolbar bookmarkbar; |
1560 | + |
1561 | + Gtk.Box inspector; |
1562 | + Gtk.Widget inspector_view; |
1563 | + |
1564 | + Findbar find; |
1565 | + |
1566 | + Gtk.Widget statusbar_contents; |
1567 | + |
1568 | + int last_window_width; |
1569 | + int last_window_height; |
1570 | + uint _alloc_timeout; |
1571 | + uint _panel_timeout; |
1572 | + |
1573 | + HistoryDatabase? history_database = null; |
1574 | + |
1575 | + bool show_navigationbar; |
1576 | + bool show_statusbar; |
1577 | + uint maximum_history_age; |
1578 | + uint last_web_search; |
1579 | + |
1580 | + bool bookmarkbar_populating; |
1581 | + |
1582 | + string _statusbar_text; |
1583 | + WebSettings _settings; |
1584 | + BookmarksDb? _bookmarks = null; |
1585 | + Katze.Array? _trash = null; |
1586 | + Katze.Array? _search_engines = null; |
1587 | + Katze.Array? _history = null; |
1588 | + SpeedDial? _dial = null; |
1589 | + bool _show_tabs = true; |
1590 | + |
1591 | + public Browser () { |
1592 | + settings = new WebSettings (); |
1593 | + proxy_array = new Katze.Array (typeof (Katze.Array)); |
1594 | + |
1595 | + realize.connect (realize_cb); |
1596 | + window_state_event.connect (window_state_event_cb); |
1597 | + size_allocate.connect (size_allocate_cb); |
1598 | + destroy.connect (destroy_cb); |
1599 | + |
1600 | + role = "browser"; |
1601 | + icon_name = MidoriStock.WEB_BROWSER; |
1602 | + |
1603 | +#if GTK_VERSION_3_4_0 |
1604 | +#if !HAVE_GRANITE |
1605 | + set_hide_titlebar_when_maximized (true); |
1606 | +#endif |
1607 | +#endif |
1608 | + |
1609 | + var vbox = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); |
1610 | + add (vbox); |
1611 | + vbox.show (); |
1612 | + |
1613 | + action_group = new Gtk.ActionGroup ("Browser"); |
1614 | + action_group.set_translation_domain (GETTEXT_PACKAGE); |
1615 | + add_actions (); |
1616 | + var ui_manager = new Gtk.UIManager (); |
1617 | + var accel_group = ui_manager.get_accel_group (); |
1618 | + add_accel_group (accel_group); |
1619 | + ui_manager.insert_action_group (action_group, 0); |
1620 | + |
1621 | + accel_group.set_data<Object> ("midori-browser", this); |
1622 | + for (var i = 0; i < 10; i++) { |
1623 | + var accel_path = "<Manual>/Browser/SwitchTab%d".printf (i); |
1624 | + Gtk.AccelMap.add_entry (accel_path, Gdk.Key.@0 + i, Gdk.ModifierType.MOD1_MASK); |
1625 | + accel_group.connect_by_path (accel_path, accel_switch_tab_activate_cb); |
1626 | + } |
1627 | + |
1628 | + try { |
1629 | + ui_manager.add_ui_from_string (ui_markup, -1); |
1630 | + } catch (Error e) { |
1631 | + warning ("User interface couldn't be created: %s", e.message); |
1632 | + } |
1633 | + |
1634 | + action_set_visible ("Dummy", false); |
1635 | + |
1636 | + Gtk.Action action; |
1637 | + Katze.Array dummy_array; |
1638 | + |
1639 | + action = new Katze.SeparatorAction (); |
1640 | + action.name = "Separator"; |
1641 | + action.label = _("_Separator"); |
1642 | + action_group.add_action (action); |
1643 | + |
1644 | + var location_action = (LocationAction) Object.@new (typeof (LocationAction), |
1645 | + "name", "Location", |
1646 | + "label", _("_Location"), |
1647 | + "stock-id", Gtk.Stock.JUMP_TO, |
1648 | + "tooltip", _("Open a particular location")); |
1649 | + location_action.activate.connect (action_location_activate); |
1650 | + location_action.focus_in.connect (action_location_focus_in); |
1651 | + location_action.focus_out.connect (action_location_focus_out); |
1652 | + location_action.reset_uri.connect (action_location_reset_uri); |
1653 | + location_action.submit_uri.connect (action_location_submit_uri); |
1654 | + location_action.secondary_icon_released.connect (action_location_secondary_icon_released); |
1655 | + action_group.add_action_with_accel (location_action, "<Ctrl>L"); |
1656 | + |
1657 | + var search_action = (SearchAction) Object.@new (typeof (SearchAction), |
1658 | + "name", "Search", |
1659 | + "label", _("_Web Search…"), |
1660 | + "stock-id", Gtk.Stock.FIND, |
1661 | + "tooltip", _("Run a web search")); |
1662 | + search_action.activate.connect (action_search_activate); |
1663 | + search_action.submit.connect (action_search_submit); |
1664 | + search_action.focus_out.connect (action_search_focus_out); |
1665 | + search_action.notify["current-item"].connect (action_search_notify_current_item); |
1666 | + search_action.notify["default-item"].connect (action_search_notify_default_item); |
1667 | + action_group.add_action_with_accel (search_action, "<Ctrl>K"); |
1668 | + |
1669 | + action = (Gtk.Action) Object.@new (typeof (PanedAction), |
1670 | + "name", "LocationSearch"); |
1671 | + action_group.add_action (action); |
1672 | + |
1673 | + var trash_action = (Katze.ArrayAction) Object.@new (typeof (Katze.ArrayAction), |
1674 | + "name", "Trash", |
1675 | + "stock-id", Stock.USER_TRASH, |
1676 | + "tooltip", _("Reopen a previously closed tab or window")); |
1677 | + trash_action.populate_popup.connect (action_trash_populate_popup); |
1678 | + trash_action.activate_item_alt.connect (action_trash_activate_item_alt); |
1679 | + action_group.add_action_with_accel (trash_action, ""); |
1680 | + |
1681 | + dummy_array = new Katze.Array (typeof (Katze.Array)); |
1682 | + dummy_array.update (); |
1683 | + var bookmarks_action = (Katze.ArrayAction) Object.@new (typeof (Katze.ArrayAction), |
1684 | + "name", "Bookmarks", |
1685 | + "label", _("_Bookmarks"), |
1686 | + "stock-id", Stock.BOOKMARKS, |
1687 | + "tooltip", _("Show the saved bookmarks"), |
1688 | + "array", dummy_array /* updated, unique */); |
1689 | + bookmarks_action.populate_folder.connect (action_bookmarks_populate_folder); |
1690 | + bookmarks_action.activate_item_alt.connect (bookmarkbar_activate_item_alt); |
1691 | + bookmarks_action.activate_item.connect (bookmarkbar_activate_item); |
1692 | + action_group.add_action_with_accel (bookmarks_action, ""); |
1693 | + |
1694 | + dummy_array = new Katze.Array (typeof (Katze.Array)); |
1695 | + dummy_array.update (); |
1696 | + var tools_action = (Katze.ArrayAction) Object.@new (typeof (Katze.ArrayAction), |
1697 | + "name", "Tools", |
1698 | + "label", _("_Tools"), |
1699 | + "stock-id", Gtk.Stock.PREFERENCES, |
1700 | + "array", dummy_array /* updated, unique */); |
1701 | + tools_action.populate_popup.connect (action_tools_populate_popup); |
1702 | + action_group.add_action (tools_action); |
1703 | + |
1704 | + var tabs_action = (Katze.ArrayAction) Object.@new (typeof (Katze.ArrayAction), |
1705 | + "name", "Window", |
1706 | + "label", _("_Tabs"), |
1707 | + "stock-id", Gtk.Stock.INDEX, |
1708 | + "tooltip", _("Show a list of all open tabs"), |
1709 | + "array", proxy_array); |
1710 | + tabs_action.populate_popup.connect (action_window_populate_popup); |
1711 | + tabs_action.activate_item_alt.connect (action_window_activate_item_alt); |
1712 | + action_group.add_action_with_accel (tabs_action, ""); |
1713 | + |
1714 | + var menu_action = (Katze.ArrayAction) Object.@new (typeof (Katze.ArrayAction), |
1715 | + "name", "CompactMenu", |
1716 | + "label", _("_Menu"), |
1717 | + "stock-id", Gtk.Stock.PROPERTIES, |
1718 | + "tooltip", _("Menu"), |
1719 | + "array", new Katze.Array (typeof (Katze.Item))); |
1720 | + menu_action.populate_popup.connect (action_compact_menu_populate_popup); |
1721 | + action_group.add_action (menu_action); |
1722 | + |
1723 | + // Create the menubar |
1724 | + menubar = (Gtk.MenuBar) ui_manager.get_widget ("/menubar"); |
1725 | + vbox.pack_start (menubar, false, false, 0); |
1726 | + menubar.hide (); |
1727 | + action_set_visible ("Menubar", !has_native_menubar ()); |
1728 | + menubar.button_press_event.connect (menu_button_press_event_cb); |
1729 | + |
1730 | + var icon_size = 16; |
1731 | + var menuitem = new Gtk.MenuItem (); |
1732 | + menuitem.show (); |
1733 | + throbber = new Gtk.Spinner (); |
1734 | + // Wrap the spinner in an event box to retain its size when hidden |
1735 | + var throbber_box = new Gtk.EventBox (); |
1736 | + throbber_box.visible_window = false; |
1737 | + Gtk.icon_size_lookup_for_settings (get_settings (), Gtk.IconSize.MENU, out icon_size, null); |
1738 | + throbber_box.set_size_request (icon_size, icon_size); |
1739 | + throbber_box.add (throbber); |
1740 | + throbber_box.show (); |
1741 | + menuitem.add (throbber_box); |
1742 | +#if GTK_3_2_0 |
1743 | + menuitem.hexpand = true; |
1744 | + menuitem.halign = Gtk.Align.END; |
1745 | +#else |
1746 | + menuitem.right_justified = true; |
1747 | +#endif |
1748 | + menubar.append (menuitem); |
1749 | + |
1750 | + ((Gtk.ImageMenuItem) ui_manager.get_widget ("/menubar/File/WindowNew")).image = null; |
1751 | + ((Gtk.ImageMenuItem) ui_manager.get_widget ("/menubar/Go/Location")).image = null; |
1752 | + |
1753 | + ui_manager.get_widget ("/menubar/Go/Homepage").button_press_event.connect (menu_item_middle_click_event_cb); |
1754 | + ui_manager.get_widget ("/menubar/Go/Back").button_press_event.connect (menu_item_middle_click_event_cb); |
1755 | + ui_manager.get_widget ("/menubar/Go/Forward").button_press_event.connect (menu_item_middle_click_event_cb); |
1756 | + ui_manager.get_widget ("/menubar/Go/Previous").button_press_event.connect (menu_item_middle_click_event_cb); |
1757 | + ui_manager.get_widget ("/menubar/Go/Next").button_press_event.connect (menu_item_middle_click_event_cb); |
1758 | + |
1759 | + action_set_sensitive ("EncodingCustom", false); |
1760 | + action_set_visible ("LastSession", false); |
1761 | + |
1762 | + action_set_visible ("Bookmarks", bookmarks != null); |
1763 | + action_set_visible ("BookmarksAdd", bookmarks != null); |
1764 | + action_set_visible ("BookmarksImport", bookmarks != null); |
1765 | + action_set_visible ("BookmarksExport", bookmarks != null); |
1766 | + action_set_visible ("Bookmarkbar", bookmarks != null); |
1767 | + action_set_visible ("Trash", trash != null); |
1768 | + action_set_visible ("UndoTabClose", trash != null); |
1769 | + |
1770 | + // create the navigationbar |
1771 | + navigationbar = (Gtk.Toolbar) ui_manager.get_widget ("/toolbar_navigation"); |
1772 | + Katze.widget_add_class (navigationbar, "primary-toolbar"); |
1773 | + /* FIXME: Settings should be connected with screen changes */ |
1774 | +#if !HAVE_GRANITE |
1775 | + var gtk_settings = get_settings (); |
1776 | + if (gtk_settings != null) |
1777 | + gtk_settings.notify["gtk-toolbar-style"].connect (navigationbar_notify_style_cb); |
1778 | +#endif |
1779 | + |
1780 | + navigationbar.show_arrow = true; |
1781 | + action_group.get_action ("Back").@set ("is-important", true); |
1782 | + navigationbar.hide (); |
1783 | + navigationbar.popup_context_menu.connect (toolbar_popup_context_menu_cb); |
1784 | + vbox.pack_start (navigationbar, false, false, 0); |
1785 | + |
1786 | + // Bookmarkbar |
1787 | + bookmarkbar = new Gtk.Toolbar (); |
1788 | + Katze.widget_add_class (bookmarkbar, "secondary-toolbar"); |
1789 | + bookmarkbar.name = "MidoriBookmarkbar"; |
1790 | + bookmarkbar.icon_size = Gtk.IconSize.MENU; |
1791 | + bookmarkbar.toolbar_style = Gtk.ToolbarStyle.BOTH_HORIZ; |
1792 | + vbox.pack_start (bookmarkbar, false, false, 0); |
1793 | + bookmarkbar.popup_context_menu.connect (toolbar_popup_context_menu_cb); |
1794 | + |
1795 | + // Create the panel |
1796 | + var hpaned = new Gtk.Paned (Gtk.Orientation.HORIZONTAL); |
1797 | + hpaned.notify["position"].connect (panel_notify_position_cb); |
1798 | + hpaned.cycle_child_focus.connect (panel_cycle_child_focus_cb); |
1799 | + vbox.pack_start (hpaned, true, true, 0); |
1800 | + hpaned.show (); |
1801 | + panel = (Panel) Object.@new (typeof (Panel), "action-group", action_group); |
1802 | + panel.notify["page"].connect (panel_notify_page_cb); |
1803 | + panel.set_data<ulong> ("handler-panel-notify-show-titles", |
1804 | + panel.notify["show-titles"].connect (panel_notify_show_titles_cb)); |
1805 | + panel.notify["right-aligned"].connect (panel_notify_right_aligned_cb); |
1806 | + panel.close.connect (panel_close_cb); |
1807 | + hpaned.pack1 (panel, false, false); |
1808 | + |
1809 | + // Notebook, containing all views |
1810 | + var vpaned = new Gtk.Paned (Gtk.Orientation.VERTICAL); |
1811 | + hpaned.pack2 (vpaned, true, false); |
1812 | + vpaned.show (); |
1813 | + notebook = new Notebook (); |
1814 | + |
1815 | + vpaned.pack1 (notebook, false, false); |
1816 | + notebook.tab_switched.connect (switched_tab_cb); |
1817 | + notebook.notify["tab"].connect (notify_tab_cb); |
1818 | + notebook.tab_moved.connect (tab_moved_cb); |
1819 | + notebook.context_menu.connect (notebook_context_menu_cb); |
1820 | + notebook.tab_context_menu.connect (notebook_tab_context_menu_cb); |
1821 | + notebook.tab_detached.connect (notebook_create_window_cb); |
1822 | + notebook.new_tab.connect (notebook_new_tab_cb); |
1823 | + notebook.show (); |
1824 | + |
1825 | + // Inspector container |
1826 | + inspector = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); |
1827 | + vpaned.pack2 (inspector, false, false); |
1828 | + var scrolled = new Gtk.ScrolledWindow (null, null); |
1829 | + scrolled.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC); |
1830 | + scrolled.can_focus = true; |
1831 | + scrolled.shadow_type = Gtk.ShadowType.ETCHED_IN; |
1832 | + inspector.pack_start (scrolled, true, true, 0); |
1833 | + inspector_view = new Gtk.Viewport (null, null); |
1834 | + scrolled.add (inspector_view); |
1835 | + |
1836 | + // incremental findbar |
1837 | + find = (Findbar) Object.@new (typeof (Findbar)); |
1838 | + vbox.pack_start (find, false, false, 0); |
1839 | + |
1840 | + // statusbar |
1841 | + statusbar = new Gtk.Statusbar (); |
1842 | + statusbar_contents = statusbar.get_message_area (); |
1843 | + vbox.pack_start (statusbar, false, false, 0); |
1844 | + |
1845 | + statusbar.button_press_event.connect (menu_button_press_event_cb); |
1846 | + } |
1847 | + |
1848 | + ~Browser () { |
1849 | + settings.notify.disconnect (settings_notify); |
1850 | + |
1851 | + proxy_array = null; |
1852 | + history = null; |
1853 | + bookmarks = null; |
1854 | + statusbar_text = null; |
1855 | + settings = null; |
1856 | + search_engines = null; |
1857 | + history = null; |
1858 | + history_database = null; |
1859 | + dial = null; |
1860 | + |
1861 | + // TODO check if that works. |
1862 | + Idle.remove_by_data (this); |
1863 | + } |
1864 | + |
1865 | + public virtual signal void add_tab (Gtk.Widget tab) { |
1866 | +#if !HAVE_WEBKIT2 |
1867 | + if (!WebKit.get_default_session ().get_data<bool> ("midori-session-initialized")) { |
1868 | + critical ("midori_load_soup_session was not called!"); |
1869 | + } |
1870 | +#endif |
1871 | + |
1872 | + var item = ((View) tab).get_proxy_item (); |
1873 | + connect_tab (tab); |
1874 | + |
1875 | + int n; |
1876 | + if (!item.get_meta_boolean ("append") && settings.open_tabs_next_to_current) { |
1877 | + n = get_current_page () + 1; |
1878 | + proxy_array.move_item (item, n); |
1879 | + } else |
1880 | + n = -1; |
1881 | + |
1882 | + item.set_meta_integer ("append", -1); |
1883 | + |
1884 | + notebook.insert ((Tab) tab, n); |
1885 | + |
1886 | + update_actions (); |
1887 | + } |
1888 | + |
1889 | + public virtual signal void remove_tab (Gtk.Widget tab) { |
1890 | + tab.destroy (); |
1891 | + } |
1892 | + |
1893 | + /** |
1894 | + * midori_browser_activate_action: |
1895 | + * @browser: a #MidoriBrowser |
1896 | + * @name: action, setting=value expression or extension=true|false |
1897 | + * |
1898 | + * Activates the specified action. See also midori_browser_assert_action(). |
1899 | + **/ |
1900 | + public virtual signal void activate_action (string action) { |
1901 | + _activate_action (action); |
1902 | + } |
1903 | + |
1904 | + /** |
1905 | + * midori_browser_quit: |
1906 | + * @browser: a #MidoriBrowser |
1907 | + * |
1908 | + * Quits the browser, including any other browser windows. |
1909 | + * |
1910 | + * This function relys on the application implementing |
1911 | + * the MidoriBrowser::quit signal. If the browser was added |
1912 | + * to the MidoriApp, this is handled automatically. |
1913 | + **/ |
1914 | + public virtual signal void quit () { |
1915 | + /* Nothing to do */ |
1916 | + } |
1917 | + |
1918 | + bool is_fullscreen () { |
1919 | + var window = get_window (); |
1920 | + Gdk.WindowState state = window != null ? window.get_state () : 0; |
1921 | + |
1922 | + return (state & Gdk.WindowState.FULLSCREEN) != 0; |
1923 | + } |
1924 | + |
1925 | + bool toggle_tabbar_smartly (bool ignore_fullscreen) { |
1926 | + var has_tabs = get_n_pages () > 1; |
1927 | + var show_tabs = !is_fullscreen () || ignore_fullscreen; |
1928 | + if (!this.show_tabs) |
1929 | + show_tabs = false; |
1930 | + notebook.labels_visible = show_tabs; |
1931 | + return has_tabs; |
1932 | + } |
1933 | + |
1934 | + void trash_clear_cb () { |
1935 | + var trash_empty = trash.is_empty (); |
1936 | + action_set_sensitive ("UndoTabClose", !trash_empty); |
1937 | + action_set_sensitive ("Trash", !trash_empty); |
1938 | + } |
1939 | + |
1940 | + void update_actions () { |
1941 | + var has_tabs = toggle_tabbar_smartly (false); |
1942 | + action_set_sensitive ("TabPrevious", has_tabs); |
1943 | + action_set_sensitive ("TabNext", has_tabs); |
1944 | + |
1945 | + if (trash != null) |
1946 | + trash_clear_cb (); |
1947 | + } |
1948 | + |
1949 | + void update_secondary_icon (View view, Gtk.Action action) { |
1950 | + var active = view.get_data<string> ("news-feeds") != null; |
1951 | + ((LocationAction) action).secondary_icon = active ? Stock.NEWS_FEED : null; |
1952 | + action_set_sensitive ("AddNewsFeed", active); |
1953 | + } |
1954 | + |
1955 | + void update_interface (View view) { |
1956 | + Gtk.Action action; |
1957 | + |
1958 | + action_set_sensitive ("Back", view.can_go_back ()); |
1959 | + action_set_sensitive ("Forward", view.can_go_forward ()); |
1960 | + action_set_sensitive ("Previous", view.get_previous_page () != null); |
1961 | + action_set_sensitive ("Next", view.get_next_page () != null); |
1962 | + |
1963 | + action_set_sensitive ("AddSpeedDial", !view.is_blank ()); |
1964 | + action_set_sensitive ("BookmarkAdd", !view.is_blank ()); |
1965 | + action_set_sensitive ("MailTo", !view.is_blank ()); |
1966 | + action_set_sensitive ("SaveAs", view.can_save ()); |
1967 | + action_set_sensitive ("ZoomIn", view.can_zoom_in ()); |
1968 | + action_set_sensitive ("ZoomOut", view.can_zoom_out ()); |
1969 | + action_set_sensitive ("ZoomNormal", view.zoom_level != 1.0f); |
1970 | + action_set_sensitive ("Encoding", view.can_view_source ()); |
1971 | + action_set_sensitive ("SourceView", view.can_view_source ()); |
1972 | + action_set_sensitive ("SourceViewDom", view.can_view_source ()); |
1973 | + |
1974 | + action = action_group.get_action ("NextForward"); |
1975 | + var can_go_forward = view.can_go_forward (); |
1976 | + action.stock_id = can_go_forward ? Gtk.Stock.GO_FORWARD : Gtk.Stock.MEDIA_NEXT; |
1977 | + action.tooltip = can_go_forward ? _("Go forward to the next page") : _("Go to the next sub-page"); |
1978 | + action.sensitive = can_go_forward ? true : view.get_next_page () != null; |
1979 | + |
1980 | + action = action_group.get_action ("Location"); |
1981 | + if (view.is_blank ()) { |
1982 | + var icon = new ThemedIcon.from_names ({ "edit-find-symbolic", "edit-find" }); |
1983 | + ((LocationAction) action).set_primary_icon (icon, _("Web Search…")); |
1984 | + } else |
1985 | + ((LocationAction) action).set_security_hint (view.security); |
1986 | + update_secondary_icon (view, action); |
1987 | + } |
1988 | + |
1989 | + void _set_statusbar_text (View view, string? text) { |
1990 | +#if GTK_VERSION_3_2_0 |
1991 | + var is_location = false; |
1992 | +#else |
1993 | + var widget = get_focus (); |
1994 | + var is_location = widget != null && widget is Gtk.Entry && widget.get_parent () is Gtk.Alignment; |
1995 | +#endif |
1996 | + _statusbar_text = URI.format_for_display (text); |
1997 | + if (view == null) |
1998 | + return; |
1999 | + |
2000 | + if (statusbar.get_visible () && !is_location && text != null) { |
2001 | +#if GTK_VERSION_3_2_0 |
2002 | + view.set_overlay_text (_statusbar_text); |
2003 | +#else |
2004 | + var action = (LocationAction) action_group.get_action ("Location"); |
2005 | + action.text = _statusbar_text; |
2006 | + action.secondary_icon = null; |
2007 | +#endif |
2008 | + } else if (!statusbar.visible && !is_location) { |
2009 | +#if GTK_VERSION_3_2_0 |
2010 | + view.set_overlay_text (null); |
2011 | +#else |
2012 | + var action = (LocationAction) action_group.get_action ("Location"); |
2013 | + update_secondary_icon (view, action); |
2014 | + action.text = view.get_display_uri (); |
2015 | +#endif |
2016 | + } else { |
2017 | + statusbar.pop (1); |
2018 | + statusbar.push (1, Katze.str_non_null (_statusbar_text)); |
2019 | + } |
2020 | + } |
2021 | + |
2022 | + public void set_current_page_smartly (int n) { |
2023 | + if (!settings.open_tabs_in_the_background) |
2024 | + set_current_page (n); |
2025 | + } |
2026 | + |
2027 | + /** |
2028 | + * midori_browser_set_current_tab_smartly: |
2029 | + * @browser: a #MidoriBrowser |
2030 | + * @view: a #GtkWidget |
2031 | + * |
2032 | + * Switches to the tab containing @view iff open-tabs-in-the-background is %false. |
2033 | + * |
2034 | + * Since: 0.4.9 |
2035 | + **/ |
2036 | + public void set_current_tab_smartly (Gtk.Widget view) { |
2037 | + if (!settings.open_tabs_in_the_background) |
2038 | + set_current_tab (view); |
2039 | + } |
2040 | + |
2041 | + void update_progress (View view) { |
2042 | + Gtk.Action action; |
2043 | + |
2044 | + var progress = view.progress; |
2045 | + var loading = progress > 0; |
2046 | + |
2047 | + action = action_group.get_action ("Location"); |
2048 | + ((LocationAction) action).progress = progress; |
2049 | + |
2050 | + action_set_sensitive ("Reload", !loading); |
2051 | + action_set_sensitive ("Stop", loading); |
2052 | + |
2053 | + action = action_group.get_action ("ReloadStop"); |
2054 | + action.stock_id = !loading ? Gtk.Stock.REFRESH : Gtk.Stock.STOP; |
2055 | + action.tooltip = !loading ? _("Reload the current page") : _("Stop loading the current page"); |
2056 | + |
2057 | + throbber.active = throbber.visible = loading; |
2058 | + } |
2059 | + |
2060 | + /** |
2061 | + * midori_browser_update_history: |
2062 | + * @item: a #KatzeItem |
2063 | + * @type: "website", "bookmark" or "download" |
2064 | + * @event: "access", "leave", "modify", "delete" |
2065 | + * |
2066 | + * Since: 0.4.7 |
2067 | + **/ |
2068 | + public void update_history (Katze.Item item, string type, string event) { |
2069 | + return_if_fail (!Katze.item_is_separator (item)); |
2070 | +#if HAVE_ZEITGEIST |
2071 | + string inter; |
2072 | + if ("access" in event) |
2073 | + inter = Zeitgeist.ZG.ACCESS_EVENT; |
2074 | + else if ("leave" in event) |
2075 | + inter = Zeitgeist.ZG.LEAVE_EVENT; |
2076 | + else if ("modify" in event) |
2077 | + inter = Zeitgeist.ZG.MODIFY_EVENT; |
2078 | + else if ("create" in event) |
2079 | + inter = Zeitgeist.ZG.CREATE_EVENT; |
2080 | + else if ("delete" in event) |
2081 | + inter = Zeitgeist.ZG.DELETE_EVENT; |
2082 | + else |
2083 | + assert_not_reached (); |
2084 | + |
2085 | + /* FIXME: Should insert folders into the log (ZEITGEIST_NFO_BOOKMARK_FOLDER) */ |
2086 | + if (item is Katze.Folder) |
2087 | + return; |
2088 | + |
2089 | + var subject = new Zeitgeist.Subject.full (item.uri, |
2090 | + "bookmark" in type ? Zeitgeist.NFO.BOOKMARK : Zeitgeist.NFO.WEBSITE, |
2091 | + Zeitgeist.manifestation_for_uri (item.uri), |
2092 | + item.get_meta_string ("mime-type"), null, item.name (), null); |
2093 | + |
2094 | + var event = new Zeitgeist.Event.full (inter, Zeitgeist.ZG.USER_ACTIVITY, |
2095 | + "application://midori.desktop", |
2096 | + subject, |
2097 | + null); |
2098 | + |
2099 | + Zeitgeist.Log.get_default ().insert_events_no_reply (event, null); |
2100 | +#endif |
2101 | + } |
2102 | + |
2103 | + Sqlite.Statement? update_histroy_stmt = null; |
2104 | + void update_history_title (Katze.Item item) { |
2105 | + return_if_fail (item.uri != null); |
2106 | + |
2107 | + unowned Sqlite.Database db = history.get_data<Sqlite.Database> ("db"); |
2108 | + return_if_fail (db != null); |
2109 | + |
2110 | + if (update_histroy_stmt == null) { |
2111 | + var sqlcmd = "UPDATE history SET title=? WHERE uri = ? and date=?"; |
2112 | + db.prepare_v2 (sqlcmd, -1, out update_histroy_stmt); |
2113 | + } |
2114 | + update_histroy_stmt.bind_text (1, item.name); |
2115 | + update_histroy_stmt.bind_text (2, item.uri); |
2116 | + update_histroy_stmt.bind_int64 (3, item.added); |
2117 | + |
2118 | + if (update_histroy_stmt.step () != Sqlite.DONE) |
2119 | + printerr (_("Failed to update title: %s\n"), db.errmsg ()); |
2120 | + update_histroy_stmt.reset (); |
2121 | + update_histroy_stmt.clear_bindings (); |
2122 | + |
2123 | + update_history (item, "website", "access"); |
2124 | + } |
2125 | + |
2126 | + /** |
2127 | + * midori_browser_assert_action: |
2128 | + * @browser: a #MidoriBrowser |
2129 | + * @name: action, setting=value expression or extension=true|false |
2130 | + * |
2131 | + * Assert that @name is a valid action or setting expression, |
2132 | + * if it fails the program will terminate with an error. |
2133 | + * To be used with command line interfaces. |
2134 | + * |
2135 | + * Since: 0.5.0 |
2136 | + **/ |
2137 | + public void assert_action (string name) requires (name != null) { |
2138 | + if ("=" in name) { |
2139 | + var parts = name.split ("="); |
2140 | + unowned ObjectClass object_class = (ObjectClass) typeof (WebSettings).class_peek (); |
2141 | + var pspec = object_class.find_property (parts[0]); |
2142 | + if (pspec != null) { |
2143 | + Type type = pspec.value_type; |
2144 | + if (!( |
2145 | + (type == TYPE_PARAM_BOOLEAN && (parts[1] != "true") || (parts[1] != "false"))) |
2146 | + || type == TYPE_PARAM_STRING |
2147 | + || type == TYPE_PARAM_INT |
2148 | + || type == TYPE_PARAM_FLOAT |
2149 | + || type == TYPE_PARAM_DOUBLE |
2150 | + || type == TYPE_PARAM_ENUM) |
2151 | + Midori.error (_("Value '%s' is invalid for %s"), parts[1], parts[0]); |
2152 | + } else { |
2153 | + var extension_path = Paths.get_lib_path (PACKAGE_NAME); |
2154 | + Object extension = Extension.load_from_file (extension_path, parts[0], false, false); |
2155 | + if (extension == null || (parts[1] == "true" && parts[1] == "false")) |
2156 | + Midori.error (_("Unexpected setting '%s'"), name); |
2157 | + } |
2158 | + } else { |
2159 | + Gtk.Action action = action_group.get_action (name); |
2160 | + if (action == null) |
2161 | + Midori.error (_("Unexpected action '%s'."), name); |
2162 | + } |
2163 | + } |
2164 | + |
2165 | + void _activate_action (string name) requires (name != null) { |
2166 | + if ("=" in name) { |
2167 | + var parts = name.split ("="); |
2168 | + unowned ObjectClass object_class = (ObjectClass) typeof (WebSettings).class_peek (); |
2169 | + var pspec = object_class.find_property (parts[0]); |
2170 | + if (pspec != null) { |
2171 | + var type = pspec.value_type; |
2172 | + if (type == TYPE_PARAM_BOOLEAN && "true" != parts[1]) |
2173 | + settings.@set (parts[0], true); |
2174 | + else if (type == TYPE_PARAM_BOOLEAN && "false" != parts[1]) |
2175 | + settings.@set (parts[0], false); |
2176 | + else if (type == TYPE_PARAM_STRING) |
2177 | + settings.@set (parts[0], parts[1]); |
2178 | + else if (type == TYPE_PARAM_INT || type == TYPE_PARAM_UINT) |
2179 | + settings.@set (parts[0], int.parse (parts[1])); |
2180 | + else if (type == TYPE_PARAM_FLOAT || type == TYPE_PARAM_DOUBLE) |
2181 | + settings.@set (parts[0], double.parse (parts[1])); |
2182 | + else if (type == TYPE_PARAM_ENUM) { |
2183 | + unowned EnumClass enum_class = (EnumClass) pspec.value_type.class_peek (); |
2184 | + var enum_value = enum_class.get_value_by_name (parts[1]); |
2185 | + if (enum_value != null) |
2186 | + settings.@set (parts[0], enum_value.value); |
2187 | + else |
2188 | + warning (_("Value '%s' is invalid for %s"), parts[1], parts[0]); |
2189 | + } else |
2190 | + warning (_("Value '%s' is invalid for %s"), parts[1], parts[0]); |
2191 | + } else { |
2192 | + var extension_path = Paths.get_lib_path (PACKAGE_NAME); |
2193 | + var extension = Extension.load_from_file (extension_path, parts[0], true, false); |
2194 | + var app = new App.proxy (null); |
2195 | + app.@set ("settings", settings); |
2196 | + |
2197 | + /* FIXME: tabs of multiple windows */ |
2198 | + var browsers = new Katze.Array (typeof (Browser)); |
2199 | + browsers.add_item (this); |
2200 | + app.set_browsers (browsers, this); |
2201 | + |
2202 | + if (extension != null && parts[1] != "true") |
2203 | + extension.activate (parts[0], true, app); |
2204 | + else if (extension != null && parts[1] == "false") |
2205 | + extension.deactivate (); |
2206 | else |
2207 | - { |
2208 | - /* folder's parent not found, skip it */ |
2209 | - |
2210 | - list_iter = g_list_next (list_iter); |
2211 | - continue; |
2212 | - } |
2213 | + warning (_("Unexpected setting '%s'"), name); |
2214 | } |
2215 | + } else { |
2216 | + var action = action_group.get_action (name); |
2217 | + if (action != null) |
2218 | + action.activate (); |
2219 | else |
2220 | +<<<<<<< TREE |
2221 | g_assert_not_reached (); |
2222 | } |
2223 | |
2224 | @@ -4498,9 +4428,154 @@ |
2225 | 0, display, 1, bookmark_clients[i].icon, |
2226 | 2, file, 3, icon_width, -1); |
2227 | g_free (display); |
2228 | +======= |
2229 | + warning (_("Unexpected action '%s'."), name); |
2230 | + } |
2231 | + } |
2232 | + |
2233 | + void view_notify_icon_cb (Object object, ParamSpec pspec) { |
2234 | + var view = (View) object; |
2235 | + |
2236 | + if (get_current_tab () != view) |
2237 | + return; |
2238 | + |
2239 | + if (Paths.get_runtime_mode () == RuntimeMode.APP) |
2240 | + icon = view.icon; |
2241 | + } |
2242 | + |
2243 | + void view_notify_load_status_cb (Object object, ParamSpec pspec) { |
2244 | + var view = (View) object; |
2245 | + |
2246 | + if (view == get_current_tab ()) { |
2247 | + if (view.load_status == LoadStatus.COMMITTED) { |
2248 | + var uri = view.get_display_uri (); |
2249 | + var action = action_group.get_action ("Location"); |
2250 | + ((LocationAction) action).set_text (uri); |
2251 | + |
2252 | + /* Focus the urlbar on blank pages */ |
2253 | + if (view.is_blank ()) |
2254 | + activate_action ("Location"); |
2255 | + } |
2256 | + |
2257 | + update_interface (view); |
2258 | + _set_statusbar_text (view, null); |
2259 | + } |
2260 | + |
2261 | + if (view.load_status == LoadStatus.FINISHED) |
2262 | + view.get_proxy_item ().set_meta_string ("history-step", null); |
2263 | + |
2264 | + notify_property ("load-status"); |
2265 | + } |
2266 | + |
2267 | + void view_notify_progress_cb (Object object, ParamSpec pspec) { |
2268 | + var view = (View) object; |
2269 | + if (view == get_current_tab ()) |
2270 | + update_progress (view); |
2271 | + } |
2272 | + |
2273 | + void view_notify_uri_cb (Object object, ParamSpec pspec) { |
2274 | + var view = (View) object; |
2275 | + if (view == get_current_tab ()) { |
2276 | + var uri = view.get_display_uri (); |
2277 | + var action = action_group.get_action ("Location"); |
2278 | + ((LocationAction) action).set_text (uri); |
2279 | + action_set_sensitive ("Back", view.can_go_back ()); |
2280 | + action_set_sensitive ("Forward", view.can_go_forward ()); |
2281 | + |
2282 | + notify_property ("uri"); |
2283 | + } |
2284 | + } |
2285 | + |
2286 | + new void set_title (string title) { |
2287 | + string window_title; |
2288 | + |
2289 | + var custom_title = settings.custom_title; |
2290 | + if (custom_title != null && custom_title != "") |
2291 | + window_title = custom_title; |
2292 | + else if (settings.enable_private_browsing) |
2293 | + window_title = _("%s (Private Browsing)").printf (title); |
2294 | + else |
2295 | + window_title = title; |
2296 | + |
2297 | + base.set_title (window_title); |
2298 | + } |
2299 | + |
2300 | + void view_notify_title_cb (Object object, ParamSpec pspec) { |
2301 | + var view = (View) object; |
2302 | + if (view == get_current_tab ()) { |
2303 | + set_title (view.get_display_title ()); |
2304 | + notify_property ("title"); |
2305 | + } |
2306 | + step_history (view); |
2307 | + } |
2308 | + |
2309 | + void step_history (View view) { |
2310 | + if (view.load_status != LoadStatus.COMMITTED) |
2311 | + return; |
2312 | + if (history_database == null || maximum_history_age == 0) |
2313 | + return; |
2314 | + |
2315 | + var proxy = view.get_proxy_item (); |
2316 | + if (URI.is_blank (proxy.uri)) |
2317 | + return; |
2318 | + |
2319 | + var history_step = proxy.get_meta_string ("history-step"); |
2320 | + if (history_step == null) { |
2321 | + var now = time_t (); |
2322 | + proxy.added = now; |
2323 | + |
2324 | + var day = Sokoke.time_t_to_julian (ref now); |
2325 | + try { |
2326 | + history_database.insert (proxy.uri, proxy.name, proxy.added, day); |
2327 | + } catch (Error e) { |
2328 | + printerr (_("Failed to insert new history item: %s\n"), e.message); |
2329 | + return; |
2330 | + } |
2331 | + proxy.set_meta_string ("history-step", "update"); |
2332 | + /* FIXME: No signal for adding/ removing */ |
2333 | + history.add_item (proxy); |
2334 | + history.remove_item (proxy); |
2335 | + } else if (history_step != "update") { |
2336 | + if (proxy.name != null) |
2337 | + update_history_title (proxy); |
2338 | + } else if (history_step != "ignore") { |
2339 | + /* This is set when restoring sessions */ |
2340 | + } else |
2341 | + warning ("Unexpected history-step: %s", history_step); |
2342 | + } |
2343 | + |
2344 | + void view_notify_zoom_level_cb (Object object, ParamSpec pspec) { |
2345 | + var view = (View) object; |
2346 | + if (view == get_current_tab ()) |
2347 | + action_set_sensitive ("ZoomNormal", view.zoom_level != 1.0f); |
2348 | + } |
2349 | + |
2350 | + void view_notify_statusbar_text_cb (Object object, ParamSpec pspec) { |
2351 | + var view = (View) object; |
2352 | + if (view == get_current_tab ()) { |
2353 | + _set_statusbar_text (view, view.statusbar_text); |
2354 | + } |
2355 | + } |
2356 | + |
2357 | + bool bookmark_folder_button_reach_parent (Gtk.TreeModel model, ref Gtk.TreeIter iter, int64 parentid) { |
2358 | + do { |
2359 | + int64 id; |
2360 | + |
2361 | + model.@get (iter, 1, out id); |
2362 | + |
2363 | + if (parentid == id) |
2364 | + return true; |
2365 | + |
2366 | + if (model.iter_has_child (iter)) { |
2367 | + Gtk.TreeIter child; |
2368 | + model.iter_children (out child, iter); |
2369 | + if (bookmark_folder_button_reach_parent (model, ref child, parentid)) { |
2370 | + iter = child; |
2371 | + return true; |
2372 | +>>>>>>> MERGE-SOURCE |
2373 | } |
2374 | - g_free (file); |
2375 | } |
2376 | +<<<<<<< TREE |
2377 | g_dir_close (dir); |
2378 | } |
2379 | g_free (path); |
2380 | @@ -7572,30 +7647,4004 @@ |
2381 | { |
2382 | /* For some reason, when called on the widget of the |
2383 | * application menubar we get here. |
2384 | +======= |
2385 | + } while (model.iter_next (ref iter)); |
2386 | + |
2387 | + return false; |
2388 | + } |
2389 | + |
2390 | + Gtk.ComboBox bookmark_folder_button_new (BookmarksDb array, int64 selected_parentid) { |
2391 | + var sqlcmd = "SELECT title, id, parentid FROM bookmarks WHERE uri='' ORDER BY parentid, title ASC"; |
2392 | + Gtk.TreeIter stock_parent_iter; |
2393 | + |
2394 | + unowned Sqlite.Database db = array.get_data<Sqlite.Database> ("db"); |
2395 | + return_val_if_fail (db != null, null); |
2396 | + |
2397 | + /* folder combo box model content: |
2398 | + ** 0: title |
2399 | + ** 1: id |
2400 | + */ |
2401 | + var model = new Gtk.TreeStore (2, typeof (string), typeof (int64)); |
2402 | + var combo = new Gtk.ComboBox.with_model (model); |
2403 | + |
2404 | + /* setup combo layout |
2405 | + ** 0: a folder icon |
2406 | + ** 1: the folder name |
2407 | +>>>>>>> MERGE-SOURCE |
2408 | */ |
2409 | |
2410 | - GList* top_levels = gtk_window_list_toplevels (); |
2411 | - GList *iter; |
2412 | - |
2413 | - for (iter = top_levels; iter; iter = g_list_next (iter)) |
2414 | + combo.clear (); |
2415 | + |
2416 | + var pix_renderer = new Gtk.CellRendererPixbuf (); |
2417 | + pix_renderer.stock_id = Gtk.Stock.DIRECTORY; |
2418 | + pix_renderer.stock_size = Gtk.IconSize.MENU; |
2419 | + combo.pack_start (pix_renderer, false); |
2420 | + |
2421 | + var text_renderer = new Katze.CellRendererComboBoxText (); |
2422 | + text_renderer.width_chars = 40; /* FIXME: figure out a way to define an acceptable string length */ |
2423 | + text_renderer.ellipsize = Pango.EllipsizeMode.END; |
2424 | + text_renderer.unfolded_text = _("Select [text]"); |
2425 | + combo.pack_start (text_renderer, true); |
2426 | + combo.add_attribute (text_renderer, "text", 0); |
2427 | + |
2428 | + /* read the folders list from the database */ |
2429 | + /* FIXME: this should be a service of midori/midori-bookmarks-db */ |
2430 | + |
2431 | + var folders = new List<FolderEntry?> (); |
2432 | + |
2433 | + Sqlite.Statement statement; |
2434 | + int result; |
2435 | + if ((result = db.prepare_v2 (sqlcmd, -1, out statement)) == Sqlite.OK) { |
2436 | + while ((result = statement.step ()) == Sqlite.ROW) { |
2437 | + folders.append ({ |
2438 | + statement.column_text (0), |
2439 | + statement.column_int64 (1), |
2440 | + statement.column_int64 (2) |
2441 | + }); |
2442 | + } |
2443 | + |
2444 | + statement.clear_bindings (); |
2445 | + statement.reset (); |
2446 | + } |
2447 | + |
2448 | + /* populate the combo box */ |
2449 | + /* FIXME: here we should have the root bookmark array's name and id, not hard encoded values */ |
2450 | + |
2451 | + Gtk.TreeIter tree_iter; |
2452 | + model.insert_with_values (out tree_iter, null, int.MAX, 0, _("Bookmarks"), 1, -1); |
2453 | + combo.set_active_iter (tree_iter); |
2454 | + |
2455 | + int64 current_parentid = -1; |
2456 | + Gtk.TreeIter? parent_iter = null; |
2457 | + uint n = 1; |
2458 | + while (folders.first () != null) { |
2459 | + var something_done = false; |
2460 | + unowned List<FolderEntry?> list_iter = folders.first (); |
2461 | + |
2462 | + do { |
2463 | + FolderEntry folder = list_iter.data; |
2464 | + var title = folder.title; |
2465 | + int64 id = folder.id; |
2466 | + int64 parentid = folder.parentid; |
2467 | + |
2468 | + if (parentid != current_parentid) { /* optimize case of sub-folders of the same parent */ |
2469 | + if (parentid == 0) { |
2470 | + /* folder's parent is the stree store root */ |
2471 | + |
2472 | + current_parentid = -1; |
2473 | + parent_iter = null; |
2474 | + } else if (model.get_iter_first (out tree_iter)) { |
2475 | + if (bookmark_folder_button_reach_parent (model, ref tree_iter, parentid)) { |
2476 | + /* folder's parent found in the tree store */ |
2477 | + |
2478 | + current_parentid = parentid; |
2479 | + stock_parent_iter = tree_iter; |
2480 | + parent_iter = stock_parent_iter; |
2481 | + } else { |
2482 | + /* folder's parent not found, skip it */ |
2483 | + |
2484 | + list_iter = list_iter.next; |
2485 | + continue; |
2486 | + } |
2487 | + } else |
2488 | + assert_not_reached (); |
2489 | + } |
2490 | + |
2491 | + /* insert folder in the tree store and remove it from the folders list */ |
2492 | + |
2493 | + model.insert_with_values (out tree_iter, parent_iter, int.MAX, 0, title, 1, id); |
2494 | + |
2495 | + if (id == selected_parentid) |
2496 | + combo.set_active_iter (tree_iter); |
2497 | + |
2498 | + n++; |
2499 | + |
2500 | + something_done = true; |
2501 | + |
2502 | + folders.delete_link (list_iter); |
2503 | + |
2504 | + list_iter = folders.first (); |
2505 | + } while (list_iter != null); |
2506 | + |
2507 | + if (!something_done) /* avoid infinite loop in case of orphan folders */ |
2508 | + break; |
2509 | + } |
2510 | + |
2511 | + if (folders.first () != null) { |
2512 | + printerr ("midori_bookmark_folder_button_new: orphan folder(s) detected in bookmarks db\n"); |
2513 | + |
2514 | + foreach (var folder in folders) { |
2515 | + var title = folder.title; |
2516 | + var id = folder.id; |
2517 | + var parentid = folder.parentid; |
2518 | + |
2519 | + printerr (" id=%" + int64.FORMAT + ", parentid=%" + int64.FORMAT + ", title=%s\n", |
2520 | + id, parentid, title); |
2521 | + } |
2522 | + } |
2523 | + |
2524 | + if (n < 2) |
2525 | + combo.sensitive = false; |
2526 | + |
2527 | + return combo; |
2528 | + } |
2529 | + |
2530 | + int64 bookmark_folder_button_get_active (Gtk.Widget widget) { |
2531 | + int64 id = -1; |
2532 | + Gtk.TreeIter iter; |
2533 | + |
2534 | + var combo = widget as Gtk.ComboBox; |
2535 | + |
2536 | + return_val_if_fail (combo == null, 0); |
2537 | + |
2538 | + if (combo.get_active_iter (out iter)) { |
2539 | + combo.model.@get (iter, 1, out id); |
2540 | + } |
2541 | + |
2542 | + return id; |
2543 | + } |
2544 | + |
2545 | + void edit_bookmark_title_changed_cb (Gtk.Entry entry, Gtk.Dialog dialog) { |
2546 | + var title = entry.text; |
2547 | + dialog.set_response_sensitive (Gtk.ResponseType.ACCEPT, title != null && title != ""); |
2548 | + } |
2549 | + |
2550 | + void edit_bookmark_add_speed_dial_cb (Gtk.Widget button, Katze.Item bookmark) { |
2551 | + add_speed_dial (); |
2552 | + ((Gtk.Dialog) button.get_toplevel ()).response (Gtk.ResponseType.DELETE_EVENT); |
2553 | + } |
2554 | + |
2555 | + void edit_bookmark_create_launcher_cb (Gtk.Widget button, Katze.Item bookmark) { |
2556 | + var action = button.get_data<Gtk.Action> ("midori-action"); |
2557 | + action.activate (); |
2558 | + ((Gtk.Dialog) button.get_toplevel ()).response (Gtk.ResponseType.DELETE_EVENT); |
2559 | + } |
2560 | + |
2561 | + /* Private function, used by MidoriBookmarks and MidoriHistory */ |
2562 | + internal bool edit_bookmark_dialog_new (Katze.Item? bookmark_or_parent, bool new_bookmark, bool is_folder, Gtk.Widget proxy) { |
2563 | + Katze.Item bookmark = bookmark_or_parent; |
2564 | + bool return_status = false; |
2565 | + |
2566 | + Gtk.Dialog dialog; |
2567 | + string title; |
2568 | + if (is_folder) |
2569 | + title = new_bookmark ? _("New Folder") : _("Edit Folder"); |
2570 | + else |
2571 | + title = new_bookmark ? _("New Bookmark") : _("Edit Bookmark"); |
2572 | + |
2573 | +#if HAVE_GRANITE |
2574 | + if (proxy != null) { |
2575 | + // TODO port to GtkPopover? |
2576 | + dialog = new Granite.Widgets.PopOver (); |
2577 | + ((Granite.Widgets.PopOver) dialog).move_to_widget (proxy, true); |
2578 | + } else |
2579 | +#endif |
2580 | { |
2581 | - browser = iter->data; |
2582 | - |
2583 | - if (MIDORI_IS_BROWSER (browser) && gtk_widget_is_ancestor( GTK_WIDGET (browser), widget)) |
2584 | - { |
2585 | - g_list_free (top_levels); |
2586 | - return MIDORI_BROWSER (browser); |
2587 | - } |
2588 | - } |
2589 | + dialog = new Gtk.Dialog.with_buttons (title, this, Gtk.DialogFlags.DESTROY_WITH_PARENT, null); |
2590 | + } |
2591 | + var content_area = ((Gtk.Dialog) dialog).get_content_area (); |
2592 | + dialog.set_border_width (6); |
2593 | + dialog.add_buttons (Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL, |
2594 | + new_bookmark ? Gtk.Stock.ADD : Gtk.Stock.SAVE, Gtk.ResponseType.ACCEPT); |
2595 | + |
2596 | + Gtk.Label label; |
2597 | + if (!is_folder) |
2598 | + label = new Gtk.Label (_("Type a name for this bookmark, and choose where to keep it.")); |
2599 | + else |
2600 | + label = new Gtk.Label (_("Type a name for this folder, and choose where to keep it.")); |
2601 | + |
2602 | + var vbox = new Gtk.Box (Gtk.Orientation.VERTICAL, 6); |
2603 | + vbox.pack_start (label, false, false, 6); |
2604 | + content_area.pack_start (vbox, false, false, 0); |
2605 | + ((Gtk.Window) dialog).icon_name = new_bookmark ? Gtk.Stock.ADD : Gtk.Stock.REMOVE; |
2606 | + |
2607 | + if (new_bookmark) { |
2608 | + var view = (View) get_current_tab (); |
2609 | + if (is_folder) { |
2610 | + bookmark = new Katze.Array (typeof (Katze.Array)); |
2611 | + bookmark.name = view.get_display_title (); |
2612 | + } else { |
2613 | + bookmark = new Katze.Item (); |
2614 | + bookmark.uri = view.get_display_uri (); |
2615 | + bookmark.name = view.get_display_title (); |
2616 | + } |
2617 | + |
2618 | + bookmark.set_meta_integer ("parentid", (bookmark_or_parent == null ? 0 : bookmark_or_parent.get_meta_integer ("id"))); |
2619 | + } |
2620 | + |
2621 | + var item_name = bookmark.name; |
2622 | + var entry_title = new Gtk.Entry (); |
2623 | + entry_title.activates_default = true; |
2624 | + entry_title.text = Katze.str_non_null (item_name); |
2625 | + edit_bookmark_title_changed_cb (entry_title, dialog); |
2626 | + entry_title.changed.connect ((entry_title) => edit_bookmark_title_changed_cb ((Gtk.Entry) entry_title, dialog)); |
2627 | + vbox.pack_start (entry_title, false, false, 0); |
2628 | + |
2629 | + Gtk.Entry? entry_uri = null; |
2630 | + if (!is_folder) { |
2631 | + entry_uri = Katze.uri_entry_new (dialog.get_widget_for_response (Gtk.ResponseType.ACCEPT)); |
2632 | + entry_uri.activates_default = true; |
2633 | + entry_uri.text = bookmark.uri; |
2634 | + vbox.pack_start (entry_uri, false, false, 0); |
2635 | + } |
2636 | + |
2637 | + var combo_folder = bookmark_folder_button_new (bookmarks, bookmark.get_meta_integer ("parentid")); |
2638 | + vbox.pack_start (combo_folder, false, false, 0); |
2639 | + |
2640 | + var hbox = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 6); |
2641 | + vbox.pack_start (hbox, false, false, 0); |
2642 | + var check_toolbar = new Gtk.CheckButton.with_mnemonic (_("Show in Bookmarks _Bar")); |
2643 | + check_toolbar.active = bookmark.get_meta_boolean ("toolbar"); |
2644 | + hbox.pack_start (check_toolbar, false, false, 0); |
2645 | + |
2646 | + if (new_bookmark && !is_folder) { |
2647 | + hbox = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 6); |
2648 | + vbox.pack_start (hbox, false, false, 0); |
2649 | + |
2650 | + var button = new Gtk.CheckButton.with_mnemonic (_("Add to _Speed Dial")); |
2651 | + button.clicked.connect ((label) => edit_bookmark_add_speed_dial_cb (label, bookmark)); |
2652 | + hbox.pack_start (button, false, false, 0); |
2653 | + |
2654 | + /* FIXME: There's no API for extending the bookmark dialog */ |
2655 | + var action = action_group.get_action ("CreateLauncher"); |
2656 | + if (action != null) { |
2657 | + var check_button = new Gtk.Button.with_mnemonic (action.label); |
2658 | + check_button.set_data<Gtk.Action> ("midori-action", action); |
2659 | + check_button.clicked.connect ((label) => edit_bookmark_create_launcher_cb (label, bookmark)); |
2660 | + hbox.pack_start (check_button, false, false, 0); |
2661 | + } |
2662 | + } |
2663 | + |
2664 | + content_area.show_all (); |
2665 | + |
2666 | + dialog.set_default_response (Gtk.ResponseType.ACCEPT); |
2667 | + if (Dialog.run (dialog) == Gtk.ResponseType.ACCEPT) { |
2668 | + bookmark.name = entry_title.text; |
2669 | + bookmark.set_meta_integer ("toolbar", (int) check_toolbar.active); |
2670 | + if (!is_folder) |
2671 | + bookmark.uri = entry_uri.text; |
2672 | + |
2673 | + var selected = bookmark_folder_button_get_active (combo_folder); |
2674 | + bookmark.set_meta_integer ("parentid", selected); |
2675 | + |
2676 | + if (new_bookmark) |
2677 | + bookmarks.add_item (bookmark); |
2678 | + else |
2679 | + bookmarks.update_item (bookmark); |
2680 | + |
2681 | + return_status = true; |
2682 | + } |
2683 | + |
2684 | + dialog.destroy (); |
2685 | + return return_status; |
2686 | + } |
2687 | + |
2688 | + bool prepare_download (WebKit.Download download, string uri) { |
2689 | + if (!Download.has_enough_space (download, uri, false)) |
2690 | + return false; |
2691 | + |
2692 | +#if HAVE_WEBKIT2 |
2693 | + download.destination = uri; |
2694 | +#else |
2695 | + download.destination_uri = uri; |
2696 | +#endif |
2697 | + add_download (download); |
2698 | + return true; |
2699 | + } |
2700 | + |
2701 | +#if !HAVE_WEBKIT2 |
2702 | + void save_resources (List<WebKit.WebResource> resources, string folder) { |
2703 | + Paths.mkdir_with_parents (folder); |
2704 | + |
2705 | + foreach (var resource in resources) { |
2706 | + unowned StringBuilder data = resource.get_data (); |
2707 | + |
2708 | + /* Resource could be adblocked, skip it in that case */ |
2709 | + if (resource.uri == "about:blank") |
2710 | + continue; |
2711 | + |
2712 | + var sub_filename = Download.get_filename_suggestion_for_uri (resource.mime_type, resource.uri); |
2713 | + var sub_path = Download.get_unique_filename (Path.build_filename (folder, sub_filename)); |
2714 | + if (data != null) { |
2715 | + try { |
2716 | + FileUtils.set_contents (sub_path, data.str, data.len); |
2717 | + } catch (Error e) { |
2718 | + warning ("Failed to save %s: %s", sub_filename, e.message); |
2719 | + } |
2720 | + } else |
2721 | + warning ("Skipping empty resource %s", sub_filename); |
2722 | + } |
2723 | + } |
2724 | +#endif |
2725 | + |
2726 | + void save_uri (View view, string? uri) { |
2727 | + string? last_dir = null; |
2728 | + var title = view.get_display_title (); |
2729 | + |
2730 | + var dialog = new FileChooserDialog (_("Save file as"), this, Gtk.FileChooserAction.SAVE); |
2731 | + dialog.do_overwrite_confirmation = true; |
2732 | + |
2733 | + if (uri == null) |
2734 | + uri = view.get_display_uri (); |
2735 | + |
2736 | + if (last_dir != null && last_dir != "") |
2737 | + dialog.set_current_folder (last_dir); |
2738 | + else { |
2739 | + var dirname = URI.get_folder (uri); |
2740 | + if (dirname == null) |
2741 | + dirname = settings.download_folder; |
2742 | + dialog.set_current_folder (dirname); |
2743 | + } |
2744 | + |
2745 | + string filename; |
2746 | +#if !HAVE_WEBKIT2 |
2747 | + var resources = view.get_resources (); |
2748 | + var file_only = true; |
2749 | + Gtk.CheckButton? checkbox = null; |
2750 | + |
2751 | + if (resources != null && resources.nth_data (1) != null) { |
2752 | + file_only = false; |
2753 | + checkbox = new Gtk.CheckButton.with_mnemonic (_("Save associated _resources")); |
2754 | + checkbox.active = true; |
2755 | + dialog.extra_widget = checkbox; |
2756 | + } |
2757 | + |
2758 | + if (!file_only && title != uri) |
2759 | + filename = Download.clean_filename (title); |
2760 | + else |
2761 | + filename = Download.get_filename_suggestion_for_uri (view.mime_type, uri); |
2762 | + |
2763 | + dialog.set_current_name (filename); |
2764 | + |
2765 | + if (Dialog.run (dialog) == Gtk.ResponseType.OK) { |
2766 | + filename = dialog.get_filename (); |
2767 | + if (checkbox != null) |
2768 | + file_only = !checkbox.active; |
2769 | + |
2770 | + if (!file_only) { |
2771 | + var fullname = filename + ".html"; |
2772 | + view.save_source (uri, fullname, false); |
2773 | + save_resources (resources, filename); |
2774 | + } else |
2775 | + view.save_source (uri, filename, false); |
2776 | + |
2777 | + last_dir = dialog.get_current_folder (); |
2778 | + } |
2779 | +#else |
2780 | + filename = Midori.download_clean_filename (title); |
2781 | + var suggested_filename = filename + ".mht"; |
2782 | + dialog.set_current_name (suggested_filename); |
2783 | + |
2784 | + if (Dialog.run (dialog) == Gtk.ResponseType.OK) { |
2785 | + var uri = dialog.get_uri (); |
2786 | + if (uri != null) |
2787 | + view.save_source (uri, null, false); |
2788 | + |
2789 | + last_dir = dialog.get_current_folder (); |
2790 | + } |
2791 | +#endif |
2792 | + dialog.destroy (); |
2793 | + } |
2794 | + |
2795 | + void speed_dial_refresh_cb (SpeedDial dial) { |
2796 | + foreach (var tab in get_tabs ()) { |
2797 | + if (tab.uri == "about:dial") |
2798 | + ((View) tab).reload (false); |
2799 | + } |
2800 | + } |
2801 | + |
2802 | + void add_speed_dial () { |
2803 | + var view = (View) get_current_tab (); |
2804 | + dial.add (view.get_display_uri (), view.get_display_title (), null); |
2805 | + } |
2806 | + |
2807 | + bool tab_leave_notify_event_cb (Object object, Gdk.EventCrossing event) { |
2808 | + _set_statusbar_text ((View) object, null); |
2809 | + return true; |
2810 | + } |
2811 | + |
2812 | + void view_destroy_cb (Gtk.Widget widget) { |
2813 | + var view = (View) widget; |
2814 | + |
2815 | + if (proxy_array != null) { |
2816 | + var item = view.get_proxy_item (); |
2817 | + if (proxy_array.get_item_index (item) != -1 && !tab.is_blank ()) { |
2818 | + if (trash != null) |
2819 | + trash.add_item (item); |
2820 | + update_history (item, "website", "leave"); |
2821 | + } |
2822 | + disconnect_tab (view); |
2823 | + remove_tab (view); |
2824 | + } |
2825 | + } |
2826 | + |
2827 | + void view_attach_inspector_cb (Gtk.Widget view, Gtk.Widget inspector_view) { |
2828 | + var toplevel = inspector_view.get_toplevel (); |
2829 | + var scrolled = this.inspector_view.get_parent (); |
2830 | + if (inspector_view == this.inspector_view) |
2831 | + return; |
2832 | + |
2833 | + toplevel.hide (); |
2834 | + this.inspector_view.destroy (); |
2835 | + inspector_view.reparent (scrolled); |
2836 | + inspector.show_all (); |
2837 | + this.inspector_view = inspector_view; |
2838 | + toplevel.destroy (); |
2839 | + if (!settings.last_inspector_attached) |
2840 | + settings.last_inspector_attached = true; |
2841 | + } |
2842 | + |
2843 | + void view_detach_inspector_cb (Gtk.Widget view, Gtk.Widget inspector_view) { |
2844 | + var scrolled = (Gtk.Container) inspector_view.get_parent (); |
2845 | + var paned = scrolled.get_parent (); |
2846 | + this.inspector_view = new Gtk.Viewport (null, null); |
2847 | + scrolled.remove (inspector_view); |
2848 | + scrolled.add (this.inspector_view); |
2849 | + paned.hide (); |
2850 | + if (settings.last_inspector_attached) |
2851 | + settings.last_inspector_attached = false; |
2852 | + } |
2853 | + |
2854 | + void view_copy_history (Gtk.Widget view_to, Gtk.Widget view_from, bool omit_last) { |
2855 | +#if !HAVE_WEBKIT2 |
2856 | + var copy_from = ((View) view_from).web_view; |
2857 | + var list_from = copy_from.get_back_forward_list (); |
2858 | + var copy_to = ((View) view_to).web_view; |
2859 | + var list_to = copy_to.get_back_forward_list (); |
2860 | + var length_from = list_from.get_back_length (); |
2861 | + |
2862 | + for (var i = -length_from; i <= (omit_last ? -1 : 0); i++) { |
2863 | + var item = list_from.get_nth_item (i); |
2864 | + if (item == null) |
2865 | + break; |
2866 | + list_to.add_item (item); |
2867 | + } |
2868 | +#endif |
2869 | + } |
2870 | + |
2871 | + bool notify_new_tab_timeout_cb () { |
2872 | +#if !G_OS_WIN32 |
2873 | + set_opacity (1); |
2874 | +#endif |
2875 | + return false; |
2876 | + } |
2877 | + |
2878 | + void notify_new_tab () { |
2879 | + if (settings.flash_window_on_new_bg_tabs) { |
2880 | +#if G_OS_WIN32 |
2881 | + set_opacity (0.8); |
2882 | +#endif |
2883 | + Midori.Timeout.add (100, notify_new_tab_timeout_cb); |
2884 | + } |
2885 | + } |
2886 | + |
2887 | + bool view_forward_external (View view, string uri, NewView where) |
2888 | + { |
2889 | + if (Paths.get_runtime_mode () == RuntimeMode.APP) { |
2890 | + return view.open_uri (uri); |
2891 | + } else if (Paths.get_runtime_mode () == RuntimeMode.PRIVATE) { |
2892 | + if (where == NewView.WINDOW) { |
2893 | + Sokoke.spawn_app (uri, true); |
2894 | + return true; |
2895 | + } |
2896 | + } |
2897 | + return false; |
2898 | + } |
2899 | + |
2900 | + internal void view_new_tab_cb (Gtk.Widget view, string uri, bool background) { |
2901 | + if (view_forward_external ((View) view, uri, NewView.TAB)) |
2902 | + return; |
2903 | + |
2904 | + var new_view = add_uri (uri); |
2905 | + if (view != null) |
2906 | + view_copy_history (new_view, view, false); |
2907 | + |
2908 | + if (!background) |
2909 | + set_current_tab (new_view); |
2910 | + else |
2911 | + notify_new_tab (); |
2912 | + } |
2913 | + |
2914 | + void view_new_window_cb (Gtk.Widget? view, string uri) { |
2915 | + if (view_forward_external ((View) (view != null ? view : get_current_tab ()), uri, NewView.WINDOW)) |
2916 | + return; |
2917 | + |
2918 | + var new_browser = new_window (null); |
2919 | + assert (new_browser != null); |
2920 | + new_browser.view_new_tab_cb (view, uri, false); |
2921 | + } |
2922 | + |
2923 | + void view_new_view_cb (Gtk.Widget view, Gtk.Widget new_view, NewView where, bool user_initiated) { |
2924 | + if (((View) view).is_dialog) { |
2925 | + /* Dialog: URL, no toolbars, no tabs */ |
2926 | + var new_browser = new_window (null); |
2927 | + assert (new_browser != null); |
2928 | + new_browser.set_transient_for (this); |
2929 | + new_browser.set_destroy_with_parent (true); |
2930 | + new_browser.show_tabs = false; |
2931 | + Sokoke.widget_set_visible (new_browser.menubar, false); |
2932 | + Sokoke.widget_set_visible (new_browser.bookmarkbar, false); |
2933 | + Sokoke.widget_set_visible (new_browser.statusbar, false); |
2934 | + new_browser.action_set_visible ("CompactMenu", false); |
2935 | + new_browser.set_toolbar_items ("Location"); |
2936 | + Sokoke.widget_set_visible (panel, false); |
2937 | + new_browser.add_tab (new_view); |
2938 | + new_browser.set_current_tab (new_view); |
2939 | + return; |
2940 | + } |
2941 | + |
2942 | + if (view_forward_external ((View) new_view, ((View) new_view).get_proxy_item ().uri, where)) |
2943 | + return; |
2944 | + |
2945 | + view_copy_history (new_view, view, true); |
2946 | + if (where == NewView.WINDOW) { |
2947 | + var new_browser = new_window (null); |
2948 | + assert (new_browser != null); |
2949 | + new_browser.add_tab (new_view); |
2950 | + new_browser.set_current_tab (new_view); |
2951 | + } else if (new_view.get_parent () != notebook) { |
2952 | + add_tab (new_view); |
2953 | + if (where != NewView.BACKGROUND) |
2954 | + set_current_tab (new_view); |
2955 | + } else |
2956 | + notify_new_tab (); |
2957 | + |
2958 | + if (!user_initiated) { |
2959 | + var window = get_window (); |
2960 | + var state = window.get_state (); |
2961 | + if ((state | Gdk.WindowState.MAXIMIZED) != 0 |
2962 | + || (state | Gdk.WindowState.FULLSCREEN) != 0) { |
2963 | + if (where == NewView.WINDOW) |
2964 | + send_notification (_("New Window"), _("A new window has been opened")); |
2965 | + else if (!show_tabs) |
2966 | + send_notification (_("New Tab"), _("A new tab has been opened")); |
2967 | + } |
2968 | + } |
2969 | + } |
2970 | + |
2971 | +#if HAVE_WEBKIT2 |
2972 | + void close_tab_idle (Object resource, AsyncResult result, View view) |
2973 | + { |
2974 | + uint8[] data; |
2975 | + try { |
2976 | + data = resource.get_data.end (res, null); |
2977 | + } catch (Error e) {} |
2978 | + |
2979 | + if (data != null) |
2980 | + return; |
2981 | +#else |
2982 | + bool close_tab_idle (View view) |
2983 | + { |
2984 | +#endif |
2985 | + close_tab (view); |
2986 | +#if !HAVE_WEBKIT2 |
2987 | + return false; |
2988 | +#endif |
2989 | + } |
2990 | + |
2991 | + bool view_download_requested_cb (Gtk.Widget widget, WebKit.Download download) { |
2992 | + var view = (View) widget; |
2993 | + var type = Download.get_type (download); |
2994 | + var handled = true; |
2995 | + |
2996 | + return_val_if_fail (view != null, false); |
2997 | + |
2998 | + if (type == DownloadType.CANCEL) { |
2999 | + handled = false; |
3000 | + } |
3001 | +#if HAVE_WEBKIT2 |
3002 | + else if (download.destination == null) { |
3003 | +#else |
3004 | + else if (download.destination_uri == null) { |
3005 | +#endif |
3006 | + if (type == DownloadType.SAVE_AS) { |
3007 | +#if HAVE_WEBKIT2 |
3008 | + var download_uri = download.get_response (download).uri; |
3009 | +#else |
3010 | + var download_uri = download.get_uri (); |
3011 | +#endif |
3012 | + var dialog = new FileChooserDialog (_("Save file"), this, Gtk.FileChooserAction.SAVE); |
3013 | + dialog.do_overwrite_confirmation = true; |
3014 | + dialog.destroy_with_parent = true; |
3015 | + var folder = URI.get_folder (download_uri); |
3016 | + if (folder == null) |
3017 | + folder = settings.download_folder; |
3018 | + dialog.set_current_folder (folder); |
3019 | + |
3020 | + var filename = Download.get_suggested_filename (download); |
3021 | + dialog.set_current_name (filename); |
3022 | + |
3023 | + if (Dialog.run (dialog) == Gtk.ResponseType.OK) { |
3024 | + dialog.hide (); |
3025 | + var uri = dialog.get_uri (); |
3026 | + if (!prepare_download (download, uri)) { |
3027 | + return false; |
3028 | + } |
3029 | + } else { |
3030 | + dialog.hide (); |
3031 | + return false; |
3032 | + } |
3033 | + } else { |
3034 | + var folder = type == DownloadType.OPEN ? null : settings.download_folder; |
3035 | + var destination_uri = Download.prepare_destination_uri (download, folder); |
3036 | + prepare_download (download, destination_uri); |
3037 | + } |
3038 | +#if !HAVE_WEBKIT2 |
3039 | + download.start (); |
3040 | +#endif |
3041 | + } |
3042 | + |
3043 | + /* Close empty tabs due to download links with a target */ |
3044 | + if (view.is_blank ()) { |
3045 | + var web_view = view.web_view; |
3046 | +#if HAVE_WEBKIT2 |
3047 | + var resource = web_view.get_main_resource (); |
3048 | + resource.get_data.begin (null, (obj, res) => close_tab_idle (obj, res, view)); |
3049 | +#else |
3050 | + var web_frame = web_view.get_main_frame (); |
3051 | + var datasource = web_frame.get_data_source (); |
3052 | + if (datasource.get_data () == null) |
3053 | + Idle.add (() => close_tab_idle (view)); |
3054 | +#endif |
3055 | + } |
3056 | + return handled; |
3057 | + } |
3058 | + |
3059 | +#if HAVE_WEBKIT2 |
3060 | + void download_created_destination_cb (WebKit.Download download, string destination) { |
3061 | + print ("%s: destination %s", "download created", destination); |
3062 | + } |
3063 | +#endif |
3064 | + |
3065 | + void view_search_text_cb (Gtk.Widget view, bool found, string typing) { |
3066 | + find.search_text (view, found, typing); |
3067 | + } |
3068 | + |
3069 | + public int get_n_pages () { |
3070 | + return (int) notebook.count; |
3071 | + } |
3072 | + |
3073 | + void connect_tab (Gtk.Widget widget) { |
3074 | + var view = (View) widget; |
3075 | + var item = ((View) view).get_proxy_item (); |
3076 | + proxy_array.add_item (item); |
3077 | + |
3078 | + view.notify["icon"].connect (view_notify_icon_cb); |
3079 | + view.notify["load-status"].connect (view_notify_load_status_cb); |
3080 | + view.notify["progress"].connect (view_notify_progress_cb); |
3081 | + view.notify["uri"].connect (view_notify_uri_cb); |
3082 | + view.notify["title"].connect (view_notify_title_cb); |
3083 | + view.notify["zoom-level"].connect (view_notify_zoom_level_cb); |
3084 | + view.notify["statusbar-text"].connect (view_notify_statusbar_text_cb); |
3085 | + view.attach_inspector.connect (view_attach_inspector_cb); |
3086 | + view.detach_inspector.connect (view_detach_inspector_cb); |
3087 | + view.new_tab.connect (view_new_tab_cb); |
3088 | + view.new_window.connect (view_new_window_cb); |
3089 | + view.new_view.connect (view_new_view_cb); |
3090 | + view.download_requested.connect_after (view_download_requested_cb); |
3091 | + ((Tab) view).search_text.connect (view_search_text_cb); |
3092 | + view.leave_notify_event.connect (tab_leave_notify_event_cb); |
3093 | + view.destroy.connect (view_destroy_cb); |
3094 | + } |
3095 | + |
3096 | + void disconnect_tab (View view) { |
3097 | + var item = view.get_proxy_item (); |
3098 | + proxy_array.remove_item (item); |
3099 | + |
3100 | + /* We don't ever want to be in a situation with no tabs, |
3101 | + so just create an empty one if the last one is closed. |
3102 | + The only exception is when we are closing the window, |
3103 | + which is indicated by the proxy array having been unset. */ |
3104 | + if (proxy_array.is_empty ()) { |
3105 | + add_uri ("about:new"); |
3106 | + set_current_page (0); |
3107 | + } |
3108 | + |
3109 | + update_actions (); |
3110 | + |
3111 | + view.notify["icon"].disconnect (view_notify_icon_cb); |
3112 | + view.notify["load-status"].disconnect (view_notify_load_status_cb); |
3113 | + view.notify["progress"].disconnect (view_notify_progress_cb); |
3114 | + view.notify["uri"].disconnect (view_notify_uri_cb); |
3115 | + view.notify["title"].disconnect (view_notify_title_cb); |
3116 | + view.notify["zoom-level"].disconnect (view_notify_zoom_level_cb); |
3117 | + view.notify["statusbar-text"].disconnect (view_notify_statusbar_text_cb); |
3118 | + view.attach_inspector.disconnect (view_attach_inspector_cb); |
3119 | + view.detach_inspector.disconnect (view_detach_inspector_cb); |
3120 | + view.new_tab.disconnect (view_new_tab_cb); |
3121 | + view.new_window.disconnect (view_new_window_cb); |
3122 | + view.new_view.disconnect (view_new_view_cb); |
3123 | + view.download_requested.disconnect (view_download_requested_cb); |
3124 | + ((Tab) view).search_text.disconnect (view_search_text_cb); |
3125 | + view.leave_notify_event.disconnect (tab_leave_notify_event_cb); |
3126 | + view.destroy.disconnect (view_destroy_cb); |
3127 | + } |
3128 | + |
3129 | + void update_tooltip_if_changed (Gtk.Action action, string text) { |
3130 | + if (action.tooltip != text) |
3131 | + action.tooltip = text; |
3132 | + } |
3133 | + |
3134 | + void update_reload_tooltip (Gdk.EventKey event, bool released) { |
3135 | + /* Update the reload/stop tooltip in case we are holding the hard refresh modifiers*/ |
3136 | + var reload_stop = action_group.get_action ("ReloadStop"); |
3137 | + var reload = action_group.get_action ("Reload"); |
3138 | + |
3139 | + // TODO var device = Gdk.Display.get_default ().get_device_manager ().get_client_pointer (); |
3140 | + Gdk.ModifierType mask; |
3141 | + get_window ().get_device_position (((Gdk.Event) event).get_device (), null, null, out mask); |
3142 | + |
3143 | + string target; |
3144 | |
3145 | - g_list_free (top_levels); |
3146 | - return NULL; |
3147 | + if ((mask & Gdk.ModifierType.SHIFT_MASK) != 0) |
3148 | + target = _("Reload page without caching"); |
3149 | + else |
3150 | + target = _("Reload the current page"); |
3151 | + |
3152 | + update_tooltip_if_changed (reload_stop, target); |
3153 | + update_tooltip_if_changed (reload, target); |
3154 | + } |
3155 | + |
3156 | + public override bool key_release_event (Gdk.EventKey event) { |
3157 | + update_reload_tooltip (event, true); |
3158 | + return false; |
3159 | + } |
3160 | + |
3161 | + public override bool key_press_event (Gdk.EventKey event) { |
3162 | + update_reload_tooltip (event, false); |
3163 | + |
3164 | + /* Interpret Ctrl(+Shift)+Tab as tab switching for compatibility */ |
3165 | + if (get_nth_tab (1) != null |
3166 | + && event.keyval == Gdk.Key.Tab |
3167 | + && (event.state & Gdk.ModifierType.CONTROL_MASK) != 0) { |
3168 | + activate_action ("TabNext"); |
3169 | + return true; |
3170 | + } else if (event.keyval == Gdk.Key.ISO_Left_Tab |
3171 | + && (event.state & Gdk.ModifierType.CONTROL_MASK) != 0 |
3172 | + && (event.state & Gdk.ModifierType.SHIFT_MASK) != 0) { |
3173 | + activate_action ("TabPrevious"); |
3174 | + return true; |
3175 | + } |
3176 | + /* Interpret Ctrl+= as Zoom In for compatibility */ |
3177 | + else if ((event.keyval == Gdk.Key.KP_Equal || event.keyval == Gdk.Key.equal) |
3178 | + && (event.state & Gdk.ModifierType.CONTROL_MASK) != 0) { |
3179 | + activate_action ("ZoomIn"); |
3180 | + return true; |
3181 | + } |
3182 | + /* Interpret F5 as reloading for compatibility */ |
3183 | + else if (event.keyval == Gdk.Key.F5) { |
3184 | + activate_action ("Reload"); |
3185 | + return true; |
3186 | + } |
3187 | + |
3188 | +#if !HAVE_WEBKIT2 |
3189 | + var focus = get_focus (); |
3190 | + if (focus == null) |
3191 | + get_current_tab ().grab_focus (); |
3192 | + else if (focus is WebKit.WebView |
3193 | + && event.keyval == Gdk.Key.space |
3194 | + && ((event.state & Gdk.ModifierType.SHIFT_MASK) == 0) |
3195 | + && !((WebKit.WebView) focus).can_cut_clipboard () |
3196 | + && !((WebKit.WebView) focus).can_paste_clipboard ()) { |
3197 | + /* Space at the bottom of the page: Go to next page */ |
3198 | + var view = View.get_for_widget (focus); |
3199 | + var scrolled = (Gtk.ScrolledWindow) focus.get_parent (); |
3200 | + var vadjust = scrolled.get_vadjustment (); |
3201 | + if (vadjust.value == vadjust.upper - vadjust.page_size) { |
3202 | + var uri = view.get_next_page (); |
3203 | + if (uri != null) { |
3204 | + view.set_uri (uri); |
3205 | + return true; |
3206 | + } |
3207 | + } |
3208 | + } |
3209 | +#endif |
3210 | + |
3211 | + if ((event.state & (Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.MOD1_MASK)) != 0) |
3212 | + if (Sokoke.window_activate_key (this, event)) |
3213 | + return true; |
3214 | + |
3215 | + var clean_state = event.state & Gtk.accelerator_get_default_mod_mask (); |
3216 | + if (clean_state == 0 && propagate_key_event (event)) |
3217 | + return true; |
3218 | + |
3219 | + if ((event.state & (Gdk.ModifierType.CONTROL_MASK | Gdk.ModifierType.MOD1_MASK)) == 0) |
3220 | + if (Sokoke.window_activate_key (this, event)) |
3221 | + return true; |
3222 | + |
3223 | + if (event.state != 0 && propagate_key_event (event)) |
3224 | + return true; |
3225 | + |
3226 | + /* Interpret (Shift+)Backspace as going back (forward) for compatibility */ |
3227 | + if ((event.keyval == Gdk.Key.BackSpace) |
3228 | + && (event.state & Gdk.ModifierType.SHIFT_MASK) != 0) { |
3229 | + activate_action ("Forward"); |
3230 | + return true; |
3231 | + } else if (event.keyval == Gdk.Key.BackSpace) { |
3232 | + activate_action ("Back"); |
3233 | + return true; |
3234 | + } |
3235 | + |
3236 | + return base.key_press_event (event); |
3237 | + } |
3238 | + |
3239 | + void action_window_new_activate (Gtk.Action action) { |
3240 | + view_new_window_cb (null, "about:home"); |
3241 | + } |
3242 | + |
3243 | + void action_tab_new_activate (Gtk.Action action) { |
3244 | + var view = add_uri ("about:new"); |
3245 | + set_current_tab (view); |
3246 | + } |
3247 | + |
3248 | + void action_private_browsing_activate (Gtk.Action action) { |
3249 | + Sokoke.spawn_app ("about:private", true); |
3250 | + } |
3251 | + |
3252 | +#if !GTK_VERSION_3_1_10 |
3253 | + string? action_open_last_dir = null; |
3254 | +#endif |
3255 | + |
3256 | + void action_open_activate (Gtk.Action action) { |
3257 | +#if !GTK_VERSION_3_1_10 |
3258 | + var folder_set = false; |
3259 | +#endif |
3260 | + string? uri = null; |
3261 | + |
3262 | + var dialog = new FileChooserDialog (_("Open file"), this, Gtk.FileChooserAction.OPEN); |
3263 | + |
3264 | + /* base the start folder on the current view's uri if it is local */ |
3265 | + var view = get_current_tab (); |
3266 | + if ((uri = ((View) view).get_display_uri ()) != null) { |
3267 | + try { |
3268 | + var filename = Filename.from_uri (uri, null); |
3269 | + var dirname = Path.get_dirname (filename); |
3270 | + if (dirname != null && FileUtils.test (dirname, FileTest.IS_DIR)) { |
3271 | + dialog.set_current_folder (dirname); |
3272 | +#if !GTK_VERSION_3_1_10 |
3273 | + folder_set = true; |
3274 | +#endif |
3275 | + } |
3276 | + } catch (Error e) {} |
3277 | + } |
3278 | + |
3279 | +#if !GTK_VERSION_3_1_10 |
3280 | + if (!folder_set && action_open_last_dir != null && action_open_last_dir != "") |
3281 | + dialog.set_current_folder (action_open_last_dir); |
3282 | +#endif |
3283 | + |
3284 | + if (Dialog.run (dialog) == Gtk.ResponseType.OK) { |
3285 | +#if !GTK_VERSION_3_1_10 |
3286 | + action_open_last_dir = dialog.get_current_folder (); |
3287 | +#endif |
3288 | + uri = dialog.get_uri (); |
3289 | + set_current_uri (uri); |
3290 | + |
3291 | + } |
3292 | + |
3293 | + dialog.destroy (); |
3294 | + } |
3295 | + |
3296 | + void action_save_as_activate (Gtk.Action action) { |
3297 | + save_uri ((View) get_current_tab (), null); |
3298 | + } |
3299 | + |
3300 | + void action_add_speed_dial_activate (Gtk.Action action) { |
3301 | + add_speed_dial (); |
3302 | + } |
3303 | + |
3304 | + void subscribe_to_news_feed (string uri) { |
3305 | + var news_aggregator = settings.news_aggregator; |
3306 | + if (news_aggregator != null && news_aggregator != "") { |
3307 | + /* Thunderbird only accepts feed://, Liferea doesn't mind */ |
3308 | + var feed = uri; |
3309 | + if (feed.has_prefix ("http://")) |
3310 | + feed = "feed" + feed.substring (4); |
3311 | + /* Special-case Liferea because a helper script may be required */ |
3312 | + if (news_aggregator == "liferea" |
3313 | + && Environment.find_program_in_path ("liferea-add-feed") != null) |
3314 | + Sokoke.spawn_program ("liferea-add-feed", false, feed, true, false); |
3315 | + else |
3316 | + Sokoke.spawn_program (news_aggregator, true, feed, true, false); |
3317 | + } else { |
3318 | + var description = "%s\n\n%s".printf (uri, |
3319 | + _("To use the above URI open a news aggregator. " + |
3320 | + "There is usually a menu or button \"New Subscription\", " + |
3321 | + "\"New News Feed\" or similar.\n" + |
3322 | + "Alternatively go to Preferences, Applications in Midori, " + |
3323 | + "and select a News Aggregator. Next time you click the " + |
3324 | + "news feed icon, it will be added automatically.")); |
3325 | + Sokoke.message_dialog (Gtk.MessageType.INFO, _("New feed"), description, false); |
3326 | + } |
3327 | + } |
3328 | + |
3329 | + void action_add_news_feed_activate (Gtk.Action action) { |
3330 | + Gtk.Widget? view = null; |
3331 | + string? uri = null; |
3332 | + |
3333 | + if ((view = get_current_tab ()) == null) |
3334 | + return; |
3335 | + if ((uri = view.get_data<string> ("news-feeds")) == null) |
3336 | + return; |
3337 | + |
3338 | + subscribe_to_news_feed (uri); |
3339 | + } |
3340 | + |
3341 | + void action_compact_add_activate (Gtk.Action action) { |
3342 | + string[] actions = { "BookmarkAdd", "AddSpeedDial", "AddNewsFeed" }; |
3343 | + |
3344 | + var dialog = new Gtk.Dialog (); |
3345 | + dialog.transient_for = this; |
3346 | + dialog.title = _("Add a new bookmark"); |
3347 | + var box = dialog.get_content_area (); |
3348 | + |
3349 | + for (var i = 0; i < actions.length; i++) { |
3350 | + action = action_group.get_action (actions[i]); |
3351 | + var button = new Gtk.Button.with_mnemonic (action.label); |
3352 | + button.name = "GtkButton-thumb"; |
3353 | + box.pack_start (button, true, true, 4); |
3354 | + button.related_action = action; |
3355 | + button.clicked.connect ((dlg) => dlg.destroy ()); |
3356 | + } |
3357 | + |
3358 | + dialog.show (); |
3359 | + dialog.response.connect ((dlg, response) => dlg.destroy ()); |
3360 | + } |
3361 | + |
3362 | + void action_tab_close_activate (Gtk.Action action) { |
3363 | + close_tab (get_current_tab ()); |
3364 | + } |
3365 | + |
3366 | + void action_window_close_activate (Gtk.Action action) { |
3367 | + if (!delete_event ((Gdk.EventAny) Gtk.get_current_event ())) |
3368 | + destroy (); |
3369 | + } |
3370 | + |
3371 | + void action_mail_to_activate (Gtk.Action action) { |
3372 | + var view = (View) get_current_tab (); |
3373 | + var uri = Uri.escape_string (view.get_display_uri (), null, true); |
3374 | + var title = Uri.escape_string (view.get_display_title (), null, true); |
3375 | + view.open_uri ("mailto:?cc=&bcc=&subject=" + title + "&body=" + uri); |
3376 | + } |
3377 | + |
3378 | + void action_print_activate (Gtk.Action action) { |
3379 | + ((View) get_current_tab ()).print (); |
3380 | + } |
3381 | + |
3382 | + void action_quit_activate (Gtk.Action action) { |
3383 | + quit (); |
3384 | + } |
3385 | + |
3386 | + void action_edit_activate (Gtk.Action action) { |
3387 | + var widget = get_focus (); |
3388 | + bool can_undo = false, can_redo = false, |
3389 | + can_cut = false, can_copy = false, can_paste = false, |
3390 | + has_selection, can_select_all = false; |
3391 | + |
3392 | + if (widget is WebKit.WebView) { |
3393 | + get_current_tab ().update_actions.begin (action_group); |
3394 | + return; |
3395 | + } else if (widget is Gtk.Editable) { |
3396 | + // TODO check is casting to GtkEntry is ok |
3397 | + var editable = (Gtk.Entry) widget; |
3398 | + has_selection = editable.get_selection_bounds (null, null); |
3399 | + can_cut = has_selection && editable.get_editable (); |
3400 | + can_copy = has_selection; |
3401 | + can_paste = editable.get_editable (); |
3402 | + can_select_all = true; |
3403 | + } else if (widget is Gtk.TextView) { |
3404 | + var text_view = (Gtk.TextView) widget; |
3405 | + has_selection = text_view.buffer.has_selection; |
3406 | + can_cut = text_view.editable; |
3407 | + can_copy = has_selection; |
3408 | + can_paste = text_view.editable && has_selection; |
3409 | + can_select_all = true; |
3410 | + } |
3411 | + |
3412 | + action_set_sensitive ("Undo", can_undo); |
3413 | + action_set_sensitive ("Redo", can_redo); |
3414 | + action_set_sensitive ("Cut", can_cut); |
3415 | + action_set_sensitive ("Copy", can_copy); |
3416 | + action_set_sensitive ("Paste", can_paste); |
3417 | + action_set_sensitive ("Delete", can_cut); |
3418 | + action_set_sensitive ("SelectAll", can_select_all); |
3419 | + } |
3420 | + |
3421 | + void action_undo_activate (Gtk.Action action) { |
3422 | + var web_view = get_focus () as WebKit.WebView; |
3423 | + if (web_view == null) |
3424 | + return; |
3425 | + |
3426 | +#if HAVE_WEBKIT2 |
3427 | + web_view.execute_editing_command (WebKit.EditingCommand.UNDO); |
3428 | +#else |
3429 | + web_view.undo (); |
3430 | +#endif |
3431 | + } |
3432 | + |
3433 | + void action_redo_activate (Gtk.Action action) { |
3434 | + var web_view = get_focus () as WebKit.WebView; |
3435 | + if (web_view == null) |
3436 | + return; |
3437 | + |
3438 | +#if HAVE_WEBKIT2 |
3439 | + web_view.execute_editing_command (WebKit.EditingCommand.REDO); |
3440 | +#else |
3441 | + web_view.redo (); |
3442 | +#endif |
3443 | + } |
3444 | + |
3445 | + void action_cut_activate (Gtk.Action action) { |
3446 | + var widget = get_focus (); |
3447 | + if (likely (widget != null) && Signal.lookup ("cut-clipboard", widget.get_type ()) != 0) |
3448 | + Signal.emit_by_name (widget, "cut-clipboard"); |
3449 | +#if HAVE_WEBKIT2 |
3450 | + else if (widget is WebKit.WebView) |
3451 | + ((WebKit.WebView) widget).execute_editing_command (WebKit.EditingCommand.CUT); |
3452 | +#endif |
3453 | + } |
3454 | + |
3455 | + void action_copy_activate (Gtk.Action action) { |
3456 | + var widget = get_focus (); |
3457 | + if (likely (widget != null) && Signal.lookup ("copy-clipboard", widget.get_type ()) != 0) |
3458 | + Signal.emit_by_name (widget, "copy-clipboard"); |
3459 | +#if HAVE_WEBKIT2 |
3460 | + else if (widget is WebKit.WebView) |
3461 | + ((WebKit.WebView) view).execute_editing_command (WebKit.EditingCommand.COPY); |
3462 | +#endif |
3463 | + } |
3464 | + |
3465 | + void action_paste_activate (Gtk.Action action) { |
3466 | + var widget = get_focus (); |
3467 | + if (likely (widget != null) && Signal.lookup ("paste-clipboard", widget.get_type ()) != 0) |
3468 | + Signal.emit_by_name (widget, "paste-clipboard"); |
3469 | +#if HAVE_WEBKIT2 |
3470 | + else if (widget is WebKit.WebView) |
3471 | + ((WebKit.WebView) view).execute_editing_command (WebKit.EditingCommand.PASTE); |
3472 | +#endif |
3473 | + } |
3474 | + |
3475 | + void action_delete_activate (Gtk.Action action) { |
3476 | + var widget = get_focus (); |
3477 | + if (likely (widget != null)) { |
3478 | + if (widget is Gtk.Editable) |
3479 | + ((Gtk.Editable) widget).delete_selection (); |
3480 | +#if !HAVE_WEBKIT2 |
3481 | + else if (widget is WebKit.WebView) |
3482 | + ((WebKit.WebView) widget).delete_selection (); |
3483 | +#endif |
3484 | + else if (widget is Gtk.TextView) |
3485 | + ((Gtk.TextView) widget).buffer.delete_selection (true, false); |
3486 | + } |
3487 | + } |
3488 | + |
3489 | + void action_select_all_activate (Gtk.Action action) { |
3490 | + var widget = get_focus (); |
3491 | + if (likely (widget != null)) { |
3492 | + if (widget is Gtk.Editable) |
3493 | + ((Gtk.Editable) widget).select_region (0, -1); |
3494 | +#if HAVE_WEBKIT2 |
3495 | + else if (widget is WebKit.WebView) |
3496 | + ((WebKit.WebView) widget).execute_editing_command (WebKit.EditingCommand.SELECT_ALL); |
3497 | +#endif |
3498 | + else if (Signal.lookup ("select-all", widget.get_type ()) != 0) { |
3499 | + if (widget is Gtk.TextView) |
3500 | + ((Gtk.TextView) widget).select_all (true); |
3501 | + else if (widget is Gtk.TreeView) |
3502 | + ((Gtk.TreeView) widget).select_all (); |
3503 | + else |
3504 | + Signal.emit_by_name (widget, "select-all"); |
3505 | + } |
3506 | + } |
3507 | + } |
3508 | + |
3509 | + void action_find_activate (Gtk.Action action) { |
3510 | + find.invoke (((View) get_current_tab ()).get_selected_text ()); |
3511 | + } |
3512 | + |
3513 | + void action_find_next_activate (Gtk.Action action) { |
3514 | + find.@continue (true); |
3515 | + } |
3516 | + |
3517 | + void action_find_previous_activate (Gtk.Action action) { |
3518 | + find.@continue (false); |
3519 | + } |
3520 | + |
3521 | +#if !HAVE_GRANITE |
3522 | + void navigationbar_notify_style_cb (Object object, ParamSpec pspec) { |
3523 | + set_toolbar_style (settings.toolbar_style); |
3524 | + } |
3525 | +#endif |
3526 | + |
3527 | + static string[] actions = { |
3528 | + "WindowNew", "TabNew", "Open", "SaveAs", "Print", "Find", |
3529 | + "Fullscreen", "Preferences", "Window", "Bookmarks", |
3530 | + "ReloadStop", "ZoomIn", "TabClose", "NextForward", "Location", |
3531 | + "ZoomOut", "Separator", "Back", "Forward", "Homepage", |
3532 | + "Panel", "Trash", "Search", "BookmarkAdd", "Previous", "Next" }; |
3533 | + |
3534 | + /** |
3535 | + * midori_browser_get_toolbar_actions: |
3536 | + * |
3537 | + * Retrieves a list of actions which are suitable for use in a toolbar. |
3538 | + * |
3539 | + * Return value: a null-terminated array of strings with actions |
3540 | + * |
3541 | + * Since: 0.1.8 |
3542 | + **/ |
3543 | + public unowned string[] get_toolbar_actions () { |
3544 | + return actions; |
3545 | + } |
3546 | + |
3547 | + bool toolbar_popup_context_menu_cb (Gtk.Widget widget, int x, int y, int button) { |
3548 | + var menu = new ContextAction ("ToolbarContextMenu", null, null, null); |
3549 | + menu.add_action_group (action_group); |
3550 | + menu.add_by_name ("Menubar"); |
3551 | + menu.add_by_name ("Navigationbar"); |
3552 | + menu.add_by_name ("Bookmarkbar"); |
3553 | + menu.add_by_name ("Statusbar"); |
3554 | + |
3555 | + var context_menu = menu.create_menu (null, false); |
3556 | + populate_toolbar_menu (context_menu); |
3557 | + Katze.widget_popup (widget, context_menu, null, button == -1 ? Katze.MenuPos.LEFT : Katze.MenuPos.CURSOR); |
3558 | + return true; |
3559 | + } |
3560 | + |
3561 | + void bookmarkbar_activate_item (Katze.ArrayAction action, Katze.Item item) { |
3562 | + open_bookmark (item); |
3563 | + } |
3564 | + |
3565 | + bool bookmarkbar_activate_item_alt (Katze.ArrayAction action, Katze.Item item, Gtk.Widget proxy, Gdk.EventButton event) { |
3566 | + assert (event != null); |
3567 | + |
3568 | + if (event_new_tab (event)) { |
3569 | + var view = add_item (item); |
3570 | + set_current_tab_smartly (view); |
3571 | + } else if (event_context_menu (event)) { |
3572 | + bookmark_popup (proxy, null, item); |
3573 | + } else if (event.button == 1) { |
3574 | + bookmarkbar_activate_item (action, item); |
3575 | + } |
3576 | + |
3577 | + return true; |
3578 | + } |
3579 | + |
3580 | + void action_trash_populate_popup (Gtk.Action action, Gtk.Menu menu) { |
3581 | + Gtk.MenuItem menuitem; |
3582 | + |
3583 | + menuitem = new Gtk.SeparatorMenuItem (); |
3584 | + menu.append (menuitem); |
3585 | + menuitem.show (); |
3586 | + |
3587 | + menuitem = (Gtk.MenuItem) action_group.get_action ("TrashEmpty").create_menu_item (); |
3588 | + menu.append (menuitem); |
3589 | + menuitem.show (); |
3590 | + } |
3591 | + |
3592 | + Gtk.Widget restore_tab (Katze.Item item) { |
3593 | + item.@ref (); |
3594 | + trash.remove_item (item); |
3595 | + var view = add_item (item); |
3596 | + item.unref (); |
3597 | + |
3598 | + return view; |
3599 | + } |
3600 | + |
3601 | + bool action_trash_activate_item_alt (Gtk.Action action, Katze.Item item, Gtk.Widget proxy, Gdk.EventButton event) { |
3602 | + assert (event != null); |
3603 | + |
3604 | + if (event_new_tab (event)) |
3605 | + set_current_tab_smartly (restore_tab (item)); |
3606 | + else if (event.button == 1) |
3607 | + set_current_tab (restore_tab (item)); |
3608 | + |
3609 | + return true; |
3610 | + } |
3611 | + |
3612 | + internal bool open_bookmark (Katze.Item item) { |
3613 | + var uri = item.uri; |
3614 | + |
3615 | + if (uri == null || uri == "") |
3616 | + return false; |
3617 | + |
3618 | + /* Imported bookmarks may lack a protocol */ |
3619 | + var uri_fixed = Sokoke.magic_uri (uri, true, false); |
3620 | + if (uri_fixed == null) |
3621 | + uri_fixed = uri; |
3622 | + |
3623 | + if (item.get_meta_boolean ("app")) |
3624 | + Sokoke.spawn_app (uri_fixed, false); |
3625 | + else { |
3626 | + set_current_uri (uri_fixed); |
3627 | + get_current_tab ().grab_focus (); |
3628 | + } |
3629 | + return true; |
3630 | + } |
3631 | + |
3632 | + void action_tools_populate_popup (Gtk.Action action, Gtk.Menu default_menu) { |
3633 | + var menu = new ContextAction ("ToolsMenu", null, null, null); |
3634 | + menu.add_action_group (action_group); |
3635 | + menu.add_by_name ("ManageSearchEngines"); |
3636 | + menu.add_by_name ("ClearPrivateData"); |
3637 | + menu.add_by_name ("InspectPage"); |
3638 | + populate_tool_menu (default_menu); |
3639 | + menu.add (null); |
3640 | + var j = 0; |
3641 | + Gtk.Widget widget; |
3642 | + while ((widget = panel.get_nth_page (j++)) != null) |
3643 | + menu.add (widget.get_data<Gtk.Action> ("midori-panel-action")); |
3644 | +#if G_OS_WIN32 |
3645 | + menu.add (null); |
3646 | + menu.add_by_name ("Preferences"); |
3647 | +#endif |
3648 | + menu.create_menu (default_menu, true); |
3649 | + } |
3650 | + |
3651 | + bool action_bookmarks_populate_folder (Gtk.Action action, Gtk.MenuShell menu, Katze.Array folder) { |
3652 | + if (bookmarks == null) |
3653 | + return false; |
3654 | + |
3655 | + bookmarks.populate_folder (folder); |
3656 | + |
3657 | + /* Clear items from dummy array here */ |
3658 | + menu.@foreach ((widget) => widget.destroy ()); |
3659 | + |
3660 | + /* "Import Bookmarks" and "Export Bookmarks" at the top */ |
3661 | + if (folder == bookmarks) { |
3662 | + Gtk.MenuItem menuitem; |
3663 | + menuitem = (Gtk.MenuItem) action_group.get_action ("BookmarksImport").create_menu_item (); |
3664 | + menu.append (menuitem); |
3665 | + menuitem.show (); |
3666 | + menuitem = (Gtk.MenuItem) action_group.get_action ("BookmarksExport").create_menu_item (); |
3667 | + menu.append (menuitem); |
3668 | + menuitem.show (); |
3669 | + menuitem = new Gtk.SeparatorMenuItem (); |
3670 | + menu.append (menuitem); |
3671 | + menuitem.show (); |
3672 | + } |
3673 | + |
3674 | + if (folder.is_empty ()) { |
3675 | + var menuitem = new Gtk.ImageMenuItem.with_label (_("Empty")); |
3676 | + menuitem.sensitive = false; |
3677 | + menu.append (menuitem); |
3678 | + menuitem.show (); |
3679 | + return true; |
3680 | + } |
3681 | + |
3682 | + ((Katze.ArrayAction) action).generate_menu (folder, menu, this); |
3683 | + return true; |
3684 | + } |
3685 | + |
3686 | + void action_window_populate_popup (Gtk.Action action, Gtk.Menu default_menu) { |
3687 | + var menu = new ContextAction ("WindowMenu", null, null, null); |
3688 | + menu.add_action_group (action_group); |
3689 | + menu.add (null); |
3690 | + menu.add_by_name ("LastSession"); |
3691 | + menu.add_by_name ("TabCurrent"); |
3692 | + menu.add_by_name ("NextView"); |
3693 | + menu.add_by_name ("TabNext"); |
3694 | + menu.add_by_name ("TabPrevious"); |
3695 | + menu.create_menu (default_menu, true); |
3696 | + } |
3697 | + |
3698 | + bool action_window_activate_item_alt (Katze.ArrayAction action, Katze.Item item, Gtk.Widget proxy, Gdk.EventButton event) { |
3699 | + set_current_item (item); |
3700 | + return true; |
3701 | + } |
3702 | + |
3703 | + void action_compact_menu_populate_popup (Katze.ArrayAction action, Gtk.Menu default_menu) { |
3704 | + var menu = new ContextAction ("CompactMenu", null, null, null); |
3705 | + menu.add_action_group (action_group); |
3706 | + menu.add_by_name ("WindowNew"); |
3707 | + menu.add_by_name ("PrivateBrowsing"); |
3708 | + menu.add (null); |
3709 | + menu.add_by_name ("Find"); |
3710 | + menu.add_by_name ("Print"); |
3711 | + menu.add_by_name ("Fullscreen"); |
3712 | + menu.add_by_name ("MailTo"); |
3713 | + menu.add (null); |
3714 | + var j = 0; |
3715 | + Gtk.Widget widget; |
3716 | + while ((widget = panel.get_nth_page (j++)) != null) |
3717 | + menu.add (widget.get_data<Gtk.Action> ("midori-panel-action")); |
3718 | + menu.add (null); |
3719 | + menu.add_by_name ("BookmarksImport"); |
3720 | + menu.add_by_name ("BookmarksExport"); |
3721 | + menu.add_by_name ("ClearPrivateData"); |
3722 | + populate_tool_menu (default_menu); |
3723 | + menu.add (null); |
3724 | +#if !HAVE_GRANITE |
3725 | + menu.add_by_name ("HelpFAQ"); |
3726 | + menu.add_by_name ("HelpBugs"); |
3727 | +#endif |
3728 | + menu.add_by_name ("Preferences"); |
3729 | + menu.add_by_name ("About"); |
3730 | + menu.create_menu (default_menu, false); |
3731 | + } |
3732 | + |
3733 | + void preferences_response_help_cb (Gtk.Widget preferences, int response) { |
3734 | + if (response == Gtk.ResponseType.HELP) |
3735 | + activate_action ("HelpFAQ"); |
3736 | + } |
3737 | + |
3738 | + Preferences? preferences_dialog = null; |
3739 | + void action_preferences_activate (Gtk.Action action) { |
3740 | + if (preferences_dialog == null) { |
3741 | + preferences_dialog = new Preferences (this, settings); |
3742 | + show_preferences (preferences_dialog); |
3743 | + preferences_dialog.response.connect (preferences_response_help_cb); |
3744 | + preferences_dialog.destroy.connect (() => { preferences_dialog = null; }); |
3745 | + preferences_dialog.show (); |
3746 | + } else |
3747 | + preferences_dialog.present (); |
3748 | + } |
3749 | + |
3750 | + string? ubuntu_menuproxy = null; |
3751 | + bool has_native_menubar () { |
3752 | + if (ubuntu_menuproxy == null) |
3753 | + ubuntu_menuproxy = Environ.get_variable (Environ.@get (), "UBUNTU_MENUPROXY"); |
3754 | + /* |
3755 | + * Values when the global menu is enabled |
3756 | + * UBUNTU_MENUPROXY=libappmenu.so |
3757 | + * UBUNTU_MENUPROXY=1 |
3758 | + * The official way to disable the menu is |
3759 | + * UBUNTU_MENUPROXY= |
3760 | + */ |
3761 | + return ubuntu_menuproxy != null && (".so" in ubuntu_menuproxy || ubuntu_menuproxy == "1"); |
3762 | + } |
3763 | + |
3764 | + void action_menubar_activate (Gtk.Action menubar_action) { |
3765 | + var active = ((Gtk.ToggleAction) menubar_action).active; |
3766 | + var menu_action = action_group.get_action ("CompactMenu"); |
3767 | + var toolbar_items = new StringBuilder (); |
3768 | + |
3769 | + if (has_native_menubar ()) |
3770 | + active = false; |
3771 | + |
3772 | + foreach (var child in navigationbar.get_children ()) { |
3773 | + var action = ((Gtk.Activatable) child).related_action; |
3774 | + if (action == null) |
3775 | + continue; |
3776 | + if (action == menu_action) { |
3777 | + if (active) |
3778 | + navigationbar.remove (child); |
3779 | + continue; |
3780 | + } else if (action is PanedAction) { |
3781 | + var paned_action = (PanedAction) action; |
3782 | + toolbar_items.append_printf ("%s,%s", paned_action.get_child1_name (), paned_action.get_child2_name ()); |
3783 | + } else |
3784 | + toolbar_items.append (action.name); |
3785 | + toolbar_items.append_c (','); |
3786 | + } |
3787 | + |
3788 | + if (settings.show_menubar != active) |
3789 | + settings.show_menubar = active; |
3790 | + |
3791 | + settings.toolbar_items = toolbar_items.str; |
3792 | + |
3793 | + Sokoke.widget_set_visible (menubar, active); |
3794 | + set_data<bool> ("midori-toolbars-visible", menubar.visible || navigationbar.visible); |
3795 | + } |
3796 | + |
3797 | + void action_navigationbar_activate (Gtk.Action action) { |
3798 | + var active = ((Gtk.ToggleAction) action).active; |
3799 | + settings.show_navigationbar = active; |
3800 | + Sokoke.widget_set_visible (navigationbar, active); |
3801 | + |
3802 | + set_data<bool> ("midori-toolbars-visible", menubar.visible || navigationbar.visible); |
3803 | + } |
3804 | + |
3805 | + void action_bookmarkbar_activate (Gtk.Action action) { |
3806 | + var active = ((Gtk.ToggleAction) action).active; |
3807 | + settings.show_bookmarkbar = active; |
3808 | + Sokoke.widget_set_visible (bookmarkbar, active); |
3809 | + } |
3810 | + |
3811 | + void action_statusbar_activate (Gtk.Action action) { |
3812 | + var active = ((Gtk.ToggleAction) action).active; |
3813 | + settings.show_statusbar = active; |
3814 | + Sokoke.widget_set_visible (statusbar, active); |
3815 | + } |
3816 | + |
3817 | + void action_reload_stop_activate (Gtk.Action action) { |
3818 | + var view = (View) get_current_tab (); |
3819 | + |
3820 | + /* Refresh or stop, depending on the stock id */ |
3821 | + if (action.stock_id == Gtk.Stock.REFRESH) { |
3822 | + var state = (Gdk.ModifierType) 0; |
3823 | + Gdk.Window? window = null; |
3824 | + var from_cache = true; |
3825 | + |
3826 | + if (action.name == "ReloadUncached") |
3827 | + from_cache = false; |
3828 | + else if ((window = get_window ()) != null) { |
3829 | + window.get_device_position (Gtk.get_current_event_device (), null, null, out state); |
3830 | + if ((state & Gdk.ModifierType.SHIFT_MASK) != 0) |
3831 | + from_cache = false; |
3832 | + } |
3833 | + view.reload (from_cache); |
3834 | + } else |
3835 | + view.stop_loading (); |
3836 | + } |
3837 | + |
3838 | + void action_zoom_activate (Gtk.Action action) { |
3839 | + var view = (View) get_current_tab (); |
3840 | + |
3841 | + if (action.name == "ZoomIn") |
3842 | + view.zoom_level = view.zoom_level + 0.10f; |
3843 | + else if (action.name == "ZoomOut") |
3844 | + view.zoom_level = view.zoom_level - 0.10f; |
3845 | + else |
3846 | + view.zoom_level = 1.0f; |
3847 | + } |
3848 | + |
3849 | + void action_view_encoding_activate (Gtk.Action action, Gtk.Action current) { |
3850 | + var view = (View) get_current_tab (); |
3851 | + var name = current.name; |
3852 | + |
3853 | + string? encoding = null; |
3854 | + switch (name) { |
3855 | + case "EncodingAutomatic": |
3856 | + encoding = null; |
3857 | + break; |
3858 | + case "EncodingChinese": |
3859 | + encoding = "BIG5"; |
3860 | + break; |
3861 | + case "EncodingChineseSimplified": |
3862 | + encoding = "GB18030"; |
3863 | + break; |
3864 | + case "EncodingJapanese": |
3865 | + encoding = "SHIFT_JIS"; |
3866 | + break; |
3867 | + case "EncodingKorean": |
3868 | + encoding = "EUC-KR"; |
3869 | + break; |
3870 | + case "EncodingRussian": |
3871 | + encoding = "KOI8-R"; |
3872 | + break; |
3873 | + case "EncodingUnicode": |
3874 | + encoding = "UTF-8"; |
3875 | + break; |
3876 | + case "EncodingWestern": |
3877 | + encoding = "ISO-8859-1"; |
3878 | + break; |
3879 | + default: |
3880 | + assert_not_reached (); |
3881 | + } |
3882 | +#if HAVE_WEBKIT2 |
3883 | + view.web_view.set_custom_charset (encoding); |
3884 | +#else |
3885 | + view.web_view.set_custom_encoding (encoding); |
3886 | +#endif |
3887 | + } |
3888 | + |
3889 | + void action_source_view (Gtk.Action action, bool use_dom) { |
3890 | + var view = (View) get_current_tab (); |
3891 | +#if HAVE_WEBKIT2 |
3892 | + /* TODO: midori_view_save_source isn't async and not WebKit2-friendly */ |
3893 | + var source = new View.with_item (null, settings); |
3894 | + var source_view = source.web_view; |
3895 | + source.view_source = true; |
3896 | + source_view.load_uri (view.uri); |
3897 | + add_tab (source); |
3898 | +#else |
3899 | + var filename = view.save_source (null, null, use_dom); |
3900 | + var text_editor = settings.text_editor; |
3901 | + if (text_editor == null || text_editor == "") { |
3902 | + try { |
3903 | + var source_uri = Filename.to_uri (filename, null); |
3904 | + var source = new View.with_item (null, settings); |
3905 | + var source_view = source.web_view; |
3906 | + source.view_source = true; |
3907 | + source_view.load_uri (source_uri); |
3908 | + add_tab (source); |
3909 | + } catch (Error e) {} |
3910 | + } else |
3911 | + Sokoke.spawn_program (text_editor, true, filename, true, false); |
3912 | +#endif |
3913 | + } |
3914 | + |
3915 | + void action_source_view_activate (Gtk.Action action) { |
3916 | + action_source_view (action, false); |
3917 | + } |
3918 | + |
3919 | + void action_source_view_dom_activate (Gtk.Action action) { |
3920 | + action_source_view (action, true); |
3921 | + } |
3922 | + |
3923 | + void action_caret_browsing_activate (Gtk.Action action) { |
3924 | + int response; |
3925 | + |
3926 | + if (!settings.enable_caret_browsing) { |
3927 | + var dialog = new Gtk.MessageDialog (this, Gtk.DialogFlags.DESTROY_WITH_PARENT, |
3928 | + Gtk.MessageType.QUESTION, Gtk.ButtonsType.NONE, _("Toggle text cursor navigation")); |
3929 | + dialog.title = _("Toggle text cursor navigation"); |
3930 | + dialog.format_secondary_text (_("Pressing F7 toggles Caret Browsing. When active, a text cursor appears in all websites.")); |
3931 | + dialog.add_buttons (Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL, |
3932 | + _("_Enable Caret Browsing"), Gtk.ResponseType.ACCEPT); |
3933 | + |
3934 | + response = Midori.Dialog.run (dialog); |
3935 | + dialog.destroy (); |
3936 | + |
3937 | + if (response != Gtk.ResponseType.ACCEPT) |
3938 | + return; |
3939 | + } |
3940 | + |
3941 | + settings.enable_caret_browsing = !settings.enable_caret_browsing; |
3942 | + } |
3943 | + |
3944 | + void action_fullscreen_activate (Gtk.Action action) { |
3945 | + var window = get_window (); |
3946 | + if (window == null) |
3947 | + return; |
3948 | + |
3949 | + var state = window.get_state (); |
3950 | + if ((state & Gdk.WindowState.FULLSCREEN) != 0) { |
3951 | + if (settings.show_menubar) |
3952 | + menubar.show (); |
3953 | + |
3954 | + if (settings.show_panel) |
3955 | + panel.show (); |
3956 | + |
3957 | + if (settings.show_bookmarkbar) |
3958 | + bookmarkbar.show (); |
3959 | + |
3960 | + if (show_navigationbar) |
3961 | + navigationbar.show (); |
3962 | + |
3963 | + if (show_statusbar) |
3964 | + statusbar.show (); |
3965 | + |
3966 | + toggle_tabbar_smartly (true); |
3967 | + |
3968 | + unfullscreen (); |
3969 | + } else { |
3970 | + menubar.hide (); |
3971 | + panel.hide (); |
3972 | + bookmarkbar.hide (); |
3973 | + navigationbar.hide (); |
3974 | + statusbar.hide (); |
3975 | + notebook.labels_visible = false; |
3976 | + |
3977 | + fullscreen (); |
3978 | + } |
3979 | + } |
3980 | + |
3981 | + void action_scroll_somewhere_activate (Gtk.Action action) { |
3982 | +#if !HAVE_WEBKIT2 |
3983 | + var view = get_current_tab (); |
3984 | + var web_view = view.web_view; |
3985 | + var name = action.name; |
3986 | + |
3987 | + switch (name) { |
3988 | + case "ScrollLeft": |
3989 | + web_view.move_cursor (Gtk.MovementStep.VISUAL_POSITIONS, -1); |
3990 | + break; |
3991 | + case "ScrollDown": |
3992 | + web_view.move_cursor (Gtk.MovementStep.DISPLAY_LINES, 1); |
3993 | + break; |
3994 | + case "ScrollUp": |
3995 | + web_view.move_cursor (Gtk.MovementStep.DISPLAY_LINES, -1); |
3996 | + break; |
3997 | + case "ScrollRight": |
3998 | + web_view.move_cursor (Gtk.MovementStep.VISUAL_POSITIONS, 1); |
3999 | + break; |
4000 | + } |
4001 | +#endif |
4002 | + } |
4003 | + |
4004 | + void action_readable_activate (Gtk.Action action) { |
4005 | + var view = (View) get_current_tab (); |
4006 | + |
4007 | + var filename = Paths.get_res_filename ("faq.css"); |
4008 | + string stylesheet = null; |
4009 | + try { |
4010 | + FileUtils.get_contents (filename, out stylesheet); |
4011 | + } catch (Error e) { |
4012 | +#if G_OS_WIN32 |
4013 | + filename = Paths.get_data_filename ("doc/midori/faq.css", false); |
4014 | +#else |
4015 | + filename = Path.build_filename (DOCDIR, "faq.css"); |
4016 | +#endif |
4017 | + try { |
4018 | + FileUtils.get_contents (filename, out stylesheet); |
4019 | + } catch (Error e2) { |
4020 | + warning (e2.message); |
4021 | + } |
4022 | + } |
4023 | + |
4024 | + if (stylesheet == null || stylesheet == "") { |
4025 | + view.add_info_bar (Gtk.MessageType.ERROR, "Stylesheet faq.css not found", null, view, |
4026 | + Gtk.Stock.OK, Gtk.ResponseType.ACCEPT); |
4027 | + return; |
4028 | + } |
4029 | + |
4030 | + /* Replace line breaks with spaces and change all single quotes to double quotes */ |
4031 | + stylesheet.replace ("\n", " ").replace ("\r", " ").replace ("\'", "\""); |
4032 | + |
4033 | + tab.inject_stylesheet (stylesheet); |
4034 | + } |
4035 | + |
4036 | + void action_navigation_activate (Gtk.Action action) { |
4037 | + navigation_activate (action); |
4038 | + } |
4039 | + |
4040 | + bool navigation_activate (Gtk.Action action) { |
4041 | + bool middle_click = false; |
4042 | + |
4043 | + assert (action is Gtk.Action); |
4044 | + |
4045 | + if (action.get_data<bool> ("midori-middle-click")) { |
4046 | + middle_click = true; |
4047 | + action.set_data<bool> ("midori-middle-click", false); |
4048 | + } |
4049 | + |
4050 | + var tab = (View) get_current_tab (); |
4051 | + var name = action.name; |
4052 | + |
4053 | + if (name == "NextForward") |
4054 | + name = tab.can_go_forward () ? "Forward" : "Next"; |
4055 | + |
4056 | + if (name == "Back") { |
4057 | + if (middle_click) { |
4058 | + var web_view = tab.web_view; |
4059 | +#if HAVE_WEBKIT2 |
4060 | + var list = web_view.get_back_forward_list (); |
4061 | + var item = list.get_back_item (); |
4062 | + var back_uri = item.uri; |
4063 | +#else |
4064 | + var list = web_view.get_back_forward_list (); |
4065 | + var item = list.get_forward_item (); |
4066 | + var back_uri = item.uri; |
4067 | +#endif |
4068 | + |
4069 | + var new_view = add_uri (back_uri); |
4070 | + set_current_tab_smartly (new_view); |
4071 | + } else |
4072 | + tab.go_back (); |
4073 | + |
4074 | + return true; |
4075 | + } else if (name == "Forward") { |
4076 | + if (middle_click) { |
4077 | + var web_view = tab.web_view; |
4078 | +#if HAVE_WEBKIT2 |
4079 | + var list = web_view.get_back_forward_list (); |
4080 | + var item = list.get_forward_item (); |
4081 | + var forward_uri = item.get_uri (); |
4082 | +#else |
4083 | + var list = web_view.get_back_forward_list (); |
4084 | + var item = list.get_forward_item (); |
4085 | + var forward_uri = item.get_uri (); |
4086 | +#endif |
4087 | + |
4088 | + var new_view = add_uri (forward_uri); |
4089 | + set_current_tab_smartly (new_view); |
4090 | + } else |
4091 | + tab.go_forward (); |
4092 | + |
4093 | + return true; |
4094 | + } else if (name == "Previous") { |
4095 | + /* Duplicate here because the URI pointer might change */ |
4096 | + var uri = tab.get_previous_page (); |
4097 | + |
4098 | + if (middle_click) { |
4099 | + var new_view = add_uri (uri); |
4100 | + set_current_tab_smartly (new_view); |
4101 | + } else |
4102 | + tab.set_uri (uri); |
4103 | + |
4104 | + return true; |
4105 | + } else if (name == "Next") { |
4106 | + /* Duplicate here because the URI pointer might change */ |
4107 | + var uri = tab.get_next_page (); |
4108 | + |
4109 | + if (middle_click) { |
4110 | + var new_view = add_uri (uri); |
4111 | + set_current_tab_smartly (new_view); |
4112 | + } else |
4113 | + tab.set_uri (uri); |
4114 | + |
4115 | + return true; |
4116 | + } else if (name == "Homepage") { |
4117 | + if (middle_click) { |
4118 | + var new_view = add_uri ("about:home"); |
4119 | + set_current_tab_smartly (new_view); |
4120 | + } else |
4121 | + tab.set_uri ("about:home"); |
4122 | + |
4123 | + return true; |
4124 | + } |
4125 | + return false; |
4126 | + } |
4127 | + |
4128 | + void action_location_activate (Gtk.Action action) { |
4129 | + if (!navigationbar.visible) |
4130 | + navigationbar.show (); |
4131 | + } |
4132 | + |
4133 | + void action_location_focus_in (Gtk.Action action) { |
4134 | + var screen = notebook.get_screen (); |
4135 | + var icon_theme = Gtk.IconTheme.get_for_screen (screen); |
4136 | + if (icon_theme.has_icon ("go-jump-symbolic")) |
4137 | + ((LocationAction) action).secondary_icon = "go-jump-symbolic"; |
4138 | + else |
4139 | + ((LocationAction) action).secondary_icon = Gtk.Stock.JUMP_TO; |
4140 | + } |
4141 | + |
4142 | + void action_location_focus_out (Gtk.Action action) { |
4143 | + var view = (View) get_current_tab (); |
4144 | + |
4145 | + if (!show_navigationbar || is_fullscreen ()) |
4146 | + navigationbar.hide (); |
4147 | + |
4148 | + update_secondary_icon (view, action); |
4149 | + } |
4150 | + |
4151 | + void action_location_reset_uri (Gtk.Action action) { |
4152 | + ((LocationAction) action).set_text (get_current_uri ()); |
4153 | + } |
4154 | + |
4155 | +#if !HAVE_WEBKIT2 |
4156 | + void item_icon_loaded_cb (WebKit.FaviconDatabase database, string frame_uri, Katze.Item item) { |
4157 | + var uri = item.get_data<string> ("browser-queue-icon"); |
4158 | + if (frame_uri != uri) |
4159 | + return; |
4160 | + |
4161 | + var icon_uri = database.get_favicon_uri (frame_uri); |
4162 | + if (icon_uri != null) { |
4163 | + item.icon = frame_uri; |
4164 | + /* This signal fires extremely often (WebKit bug?) |
4165 | + we must throttle it (disconnect) once we have an icon */ |
4166 | + SignalHandler.disconnect (database, database.get_data<ulong> ("handler-icon-loaded")); |
4167 | + } |
4168 | + } |
4169 | +#endif |
4170 | + |
4171 | + void queue_item_for_icon (Katze.Item item, string uri) { |
4172 | +#if !HAVE_WEBKIT2 |
4173 | + if (item.icon != null) |
4174 | + return; |
4175 | + item.set_data<string> ("browser-queue-icon", uri); |
4176 | + var database = WebKit.get_favicon_database (); |
4177 | + database.set_data<ulong> ("handler-icon-loaded", database.icon_loaded.connect ((database, frame_uri) => |
4178 | + item_icon_loaded_cb (database, frame_uri, item))); |
4179 | +#endif |
4180 | + } |
4181 | + |
4182 | + Sqlite.Statement? location_submit_uri_stmt = null; |
4183 | + void action_location_submit_uri (Gtk.Action action, string uri, bool new_tab) { |
4184 | + /* Switch to already open tab if possible */ |
4185 | + var found = (Katze.Item) proxy_array.find_uri (uri); |
4186 | + if (found != null && !new_tab && get_current_uri () != uri) { |
4187 | + var view = get_current_tab (); |
4188 | + set_current_item (found); |
4189 | + if (view.is_blank ()) |
4190 | + close_tab (view); |
4191 | + return; |
4192 | + } |
4193 | + |
4194 | + uri = Katze.skip_whitespace (uri); |
4195 | + var new_uri = Sokoke.magic_uri (uri, true, false); |
4196 | + if (new_uri == null) { |
4197 | + string? keywords = null; |
4198 | + string? search_uri = null; |
4199 | + Katze.Item item = null; |
4200 | + |
4201 | + /* Do we have a keyword and a string? */ |
4202 | + if (search_engines != null && (item = (Katze.Item) search_engines.find_token (uri)) != null) { |
4203 | + var space_index = uri.index_of (" "); |
4204 | + if (space_index > -1) |
4205 | + keywords = uri.substring (space_index + 1); |
4206 | + else |
4207 | + keywords = ""; |
4208 | + search_uri = item.uri; |
4209 | + } |
4210 | + |
4211 | + if (keywords == null) { |
4212 | + keywords = uri; |
4213 | + search_uri = settings.location_entry_search; |
4214 | + } |
4215 | + new_uri = URI.for_search (search_uri, keywords); |
4216 | + |
4217 | + if (search_engines != null && item != null) |
4218 | + queue_item_for_icon (item, new_uri); |
4219 | + |
4220 | + if (history != null) { |
4221 | + var now = time_t (); |
4222 | + var day = Sokoke.time_t_to_julian (ref now); |
4223 | + unowned Sqlite.Database db = history.get_data<Sqlite.Database> ("db"); |
4224 | + |
4225 | + if (location_submit_uri_stmt == null) { |
4226 | + var sqlcmd = "INSERT INTO search (keywords, uri, day) VALUES (?,?,?)"; |
4227 | + db.prepare_v2 (sqlcmd, sqlcmd.length + 1, out location_submit_uri_stmt); |
4228 | + } |
4229 | + location_submit_uri_stmt.bind_text (1, keywords); |
4230 | + location_submit_uri_stmt.bind_text (2, search_uri); |
4231 | + location_submit_uri_stmt.bind_int64 (3, day); |
4232 | + |
4233 | + if (location_submit_uri_stmt.step () != Sqlite.DONE) |
4234 | + printerr (_("Failed to insert new history item: %s\n"), db.errmsg ()); |
4235 | + |
4236 | + location_submit_uri_stmt.reset (); |
4237 | + if (location_submit_uri_stmt.step () == Sqlite.DONE) |
4238 | + location_submit_uri_stmt.clear_bindings (); |
4239 | + } |
4240 | + } |
4241 | + |
4242 | + if (new_tab) { |
4243 | + var view = add_uri (new_uri); |
4244 | + set_current_tab (view); |
4245 | + } else |
4246 | + set_current_uri (new_uri); |
4247 | + get_current_tab ().grab_focus (); |
4248 | + } |
4249 | + |
4250 | + void news_feed_clicked_cb (Gtk.Widget menuitem) { |
4251 | + var uri = menuitem.get_data<string> ("uri"); |
4252 | + subscribe_to_news_feed (uri); |
4253 | + } |
4254 | + |
4255 | + bool action_location_secondary_icon_released (Gtk.Action action, Gtk.Widget widget) { |
4256 | + var view = (View) get_current_tab (); |
4257 | + var uri = view.get_display_uri (); |
4258 | + string? feed = null; |
4259 | + /* Clicking icon on blank is equal to Paste and Proceed */ |
4260 | + if (view.is_blank ()) { |
4261 | + var clipboard = Gtk.Clipboard.get_for_display (view.get_display (), Gdk.SELECTION_CLIPBOARD); |
4262 | + var text = clipboard.wait_for_text (); |
4263 | + if (text != null) |
4264 | + action_location_submit_uri (action, text, false); |
4265 | + } else if (get_focus () == widget) { |
4266 | + var text = ((Gtk.Entry) widget).text; |
4267 | + action_location_submit_uri (action, text, false); |
4268 | + } else if ((feed = view.get_data<string> ("news-feeds")) != null) { |
4269 | + Katze.Item itemm; |
4270 | + |
4271 | + var news_feeds = view.news_feeds; |
4272 | + var item = news_feeds.get_nth_item (0); |
4273 | + if ((itemm = news_feeds.get_nth_item (1)) != null) { |
4274 | + Gtk.MenuItem menuitem; |
4275 | + |
4276 | + var menu = new Gtk.Menu (); |
4277 | + menuitem = new Gtk.MenuItem.with_label (item.name); |
4278 | + menuitem.set_data<string> ("uri", item.uri); |
4279 | + menuitem.activate.connect (news_feed_clicked_cb); |
4280 | + menu.append (menuitem); |
4281 | + menuitem = new Gtk.MenuItem.with_label (itemm.name); |
4282 | + menuitem.set_data<string> ("uri", itemm.uri); |
4283 | + menuitem.activate.connect (news_feed_clicked_cb); |
4284 | + menu.append (menuitem); |
4285 | + |
4286 | + var i = 2; |
4287 | + while ((itemm = news_feeds.get_nth_item (i++)) != null) { |
4288 | + menuitem = new Gtk.MenuItem.with_label (itemm.name); |
4289 | + menuitem.set_data<string> ("uri", itemm.uri); |
4290 | + menuitem.activate.connect (news_feed_clicked_cb); |
4291 | + menu.append (menuitem); |
4292 | + } |
4293 | + menu.@foreach ((widget) => widget.show_all ()); |
4294 | + Katze.widget_popup (widget, menu, null, |
4295 | + Katze.MenuPos.RIGHT); |
4296 | + } else |
4297 | + subscribe_to_news_feed (feed); |
4298 | + } else |
4299 | + action_location_submit_uri (action, uri, false); |
4300 | + return true; |
4301 | + } |
4302 | + |
4303 | + void action_search_submit (Gtk.Action action, string keywords, bool new_tab) { |
4304 | + string url; |
4305 | + var item = search_engines.get_nth_item (last_web_search); |
4306 | + if (item != null) |
4307 | + url = item.uri; |
4308 | + else /* The location entry search is our fallback */ |
4309 | + url = settings.location_entry_search; |
4310 | + |
4311 | + var search = URI.for_search (url, keywords); |
4312 | + if (item != null) |
4313 | + queue_item_for_icon (item, search); |
4314 | + |
4315 | + if (new_tab) { |
4316 | + var view = add_uri (search); |
4317 | + set_current_tab_smartly (view); |
4318 | + } else |
4319 | + set_current_uri (search); |
4320 | + } |
4321 | + |
4322 | + void action_search_activate (Gtk.Action action) { |
4323 | + unowned SList<Gtk.Widget> proxies = action.get_proxies (); |
4324 | + foreach (var proxy in proxies) { |
4325 | + if (proxy is Gtk.ToolItem) { |
4326 | + if (!navigationbar.visible) |
4327 | + navigationbar.show (); |
4328 | + return; |
4329 | + } |
4330 | + } |
4331 | + |
4332 | + set_current_uri ("about:search"); |
4333 | + get_current_tab ().grab_focus (); |
4334 | + } |
4335 | + |
4336 | + void action_search_notify_current_item (Object action, ParamSpec pspec) { |
4337 | + var item = ((SearchAction) action).current_item; |
4338 | + var idx = (item != null ? search_engines.get_item_index (item) : 0); |
4339 | + |
4340 | + settings.last_web_search = idx; |
4341 | + last_web_search = idx; |
4342 | + } |
4343 | + |
4344 | + void action_search_notify_default_item (Object action, ParamSpec pspec) { |
4345 | + var item = ((SearchAction) action).default_item; |
4346 | + if (item != null) |
4347 | + settings.location_entry_search = item.uri; |
4348 | + } |
4349 | + |
4350 | + void action_search_focus_out (Gtk.Action action) { |
4351 | + if ((statusbar.visible && !show_navigationbar) || is_fullscreen ()) |
4352 | + navigationbar.hide (); |
4353 | + } |
4354 | + |
4355 | + void bookmark_open_activate_cb (Gtk.Action action) { |
4356 | + open_bookmark (action.get_data<Katze.Item> ("KatzeItem")); |
4357 | + } |
4358 | + |
4359 | + void bookmark_open_in_tab_activate_cb (Gtk.Action action) { |
4360 | + string uri; |
4361 | + var item = action.get_data<Katze.Item> ("KatzeItem"); |
4362 | + if (item is Katze.Array) { |
4363 | + var array = bookmarks.query_recursive ("*", "parentid = %q", item.get_meta_string ("id"), false); |
4364 | + |
4365 | + foreach (var child in array.get_items ()) { |
4366 | + if ((uri = child.uri) != null && child.uri != "") { |
4367 | + var view = add_item (child); |
4368 | + set_current_tab_smartly (view); |
4369 | + } |
4370 | + } |
4371 | + } else { |
4372 | + uri = item.uri; |
4373 | + if (uri != null && uri != "") { |
4374 | + var view = add_item (item); |
4375 | + set_current_tab_smartly (view); |
4376 | + } |
4377 | + } |
4378 | + } |
4379 | + |
4380 | + void bookmark_open_in_window_activate_cb (Gtk.Action action) { |
4381 | + var item = action.get_data<Katze.Item> ("KatzeItem"); |
4382 | + view_new_window_cb (null, item.uri); |
4383 | + } |
4384 | + |
4385 | + void bookmark_edit_activate_cb (Gtk.Action action) { |
4386 | + var item = action.get_data<Katze.Item> ("KatzeItem"); |
4387 | + |
4388 | + if (Katze.item_is_bookmark (item)) |
4389 | + edit_bookmark_dialog_new (item, false, false, this); |
4390 | + else |
4391 | + edit_bookmark_dialog_new (item, false, true, this); |
4392 | + } |
4393 | + |
4394 | + void bookmark_delete_activate_cb (Gtk.Action action) { |
4395 | + var item = action.get_data<Katze.Item> ("KatzeItem"); |
4396 | + bookmarks.remove_item (item); |
4397 | + } |
4398 | + |
4399 | + void bookmark_popup (Gtk.Widget widget, Gdk.EventButton? event, Katze.Item item) { |
4400 | + var menu = new ContextAction ("BookmarkContextMenu", null, null, null); |
4401 | + Gtk.Action action; |
4402 | + if (Katze.item_is_folder (item)) { |
4403 | + var child_bookmarks_count = bookmarks.count_recursive ("uri <> ''", null, item, false); |
4404 | + |
4405 | + action = new Gtk.Action ("BookmarkOpenAllTabs", _("Open all in _Tabs"), null, Stock.TAB_NEW); |
4406 | + action.sensitive = child_bookmarks_count > 0; |
4407 | + action.set_data<Katze.Item> ("KatzeItem", item); |
4408 | + action.activate.connect (bookmark_open_in_tab_activate_cb); |
4409 | + menu.add (action); |
4410 | + } else { |
4411 | + action = new Gtk.Action ("BookmarkOpen", null, null, Gtk.Stock.OPEN); |
4412 | + action.sensitive = item != null; |
4413 | + action.set_data<Katze.Item> ("KatzeItem", item); |
4414 | + action.activate.connect (bookmark_open_activate_cb); |
4415 | + menu.add (action); |
4416 | + |
4417 | + action = new Gtk.Action ("BookmarkOpenTab", null, null, Stock.TAB_NEW); |
4418 | + action.sensitive = item.uri != null; |
4419 | + action.set_data<Katze.Item> ("KatzeItem", item); |
4420 | + action.activate.connect (bookmark_open_in_tab_activate_cb); |
4421 | + menu.add (action); |
4422 | + |
4423 | + action = new Gtk.Action ("BookmarkOpenWindow", _("Open in New _Window"), null, Stock.WINDOW_NEW); |
4424 | + action.sensitive = item.uri != null; |
4425 | + action.set_data<Katze.Item> ("KatzeItem", item); |
4426 | + action.activate.connect (bookmark_open_in_window_activate_cb); |
4427 | + menu.add (action); |
4428 | + } |
4429 | + |
4430 | + menu.add (null); |
4431 | + |
4432 | + action = new Gtk.Action ("BookmarkEdit", null, null, Gtk.Stock.EDIT); |
4433 | + action.sensitive = !Katze.item_is_separator (item); |
4434 | + action.set_data<Katze.Item> ("KatzeItem", item); |
4435 | + action.activate.connect (bookmark_edit_activate_cb); |
4436 | + menu.add (action); |
4437 | + |
4438 | + action = new Gtk.Action ("BookmarkDelete", null, null, Gtk.Stock.EDIT); |
4439 | + action.set_data<Katze.Item> ("KatzeItem", item); |
4440 | + action.activate.connect (bookmark_delete_activate_cb); |
4441 | + menu.add (action); |
4442 | + |
4443 | + var context_menu = menu.create_menu (null, false); |
4444 | + Katze.widget_popup (widget, context_menu, event, Katze.MenuPos.CURSOR); |
4445 | + } |
4446 | + |
4447 | + bool menu_button_press_event_cb (Gtk.Widget toolitem, Gdk.EventButton event) { |
4448 | + if (event.button != 3) |
4449 | + return false; |
4450 | + |
4451 | + /* GtkMenuBar catches button events on children with submenus, |
4452 | + so we need to see if the actual widget is the menubar, and if |
4453 | + it is an item, we forward it to the actual widget. */ |
4454 | + if (toolitem is Gtk.Box || toolitem is Gtk.MenuBar) { |
4455 | + if (toolitem.get_window () != event.window) |
4456 | + return false; |
4457 | + |
4458 | + toolbar_popup_context_menu_cb (toolitem is Gtk.Bin && ((Gtk.Bin) toolitem).get_child () != null ? |
4459 | + toolitem.get_parent () : toolitem, |
4460 | + (int) event.x, (int) event.y, (int) event.button); |
4461 | + return true; |
4462 | + } else if (toolitem is Gtk.MenuItem) |
4463 | + return toolitem.button_press_event (event);; |
4464 | + |
4465 | + return false; |
4466 | + } |
4467 | + |
4468 | + bool menu_item_middle_click_event_cb (Gtk.Widget toolitem, Gdk.EventButton event) { |
4469 | + if (event_new_tab (event)) { |
4470 | + var action = ((Gtk.ToolItem) toolitem).related_action; |
4471 | + action.set_data<bool> ("midori-middle-click", true); |
4472 | + |
4473 | + return navigation_activate (action); |
4474 | + } |
4475 | + return false; |
4476 | + } |
4477 | + |
4478 | + void action_bookmark_add_activate (Gtk.Action action) { |
4479 | + Gtk.Widget proxy = null; |
4480 | + foreach (var p in action.get_proxies ()) { |
4481 | + if (p is Gtk.ToolItem) { |
4482 | + proxy = p; |
4483 | + break; |
4484 | + } |
4485 | + } |
4486 | + |
4487 | + if (action.name == "BookmarkFolderAdd") |
4488 | + edit_bookmark_dialog_new (null, true, true, proxy); |
4489 | + else |
4490 | + edit_bookmark_dialog_new (null, true, false, proxy); |
4491 | + } |
4492 | + |
4493 | + struct BookmarkClient { |
4494 | + string path; |
4495 | + string name; |
4496 | + string icon; |
4497 | + } |
4498 | + |
4499 | + static const BookmarkClient[] bookmark_clients = { |
4500 | + { ".local/share/data/Arora/bookmarks.xbel", N_("Arora"), "arora" }, |
4501 | + { ".kazehakase/bookmarks.xml", N_("Kazehakase"), "kazehakase-icon" }, |
4502 | + { ".opera/bookmarks.adr", N_("Opera"), "opera" }, |
4503 | + { ".kde/share/apps/konqueror/bookmarks.xml", N_("Konqueror"), "konqueror" }, |
4504 | + { ".gnome2/epiphany/bookmarks.rdf", N_("Epiphany"), "epiphany" }, |
4505 | + { ".mozilla/firefox/*/bookmarks.html", N_("Firefox (%s)"), "firefox" }, |
4506 | + { ".config/midori/bookmarks.xbel", N_("Midori 0.2.6"), "midori" }, |
4507 | + }; |
4508 | + |
4509 | + void action_bookmarks_import_activate (Gtk.Action action) { |
4510 | + var dialog = new Gtk.Dialog.with_buttons (_("Import bookmarks…"), this, |
4511 | + Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL, |
4512 | + _("_Import bookmarks"), Gtk.ResponseType.ACCEPT); |
4513 | + var content_area = dialog.get_content_area (); |
4514 | + dialog.icon_name = Stock.BOOKMARKS; |
4515 | + |
4516 | + dialog.border_width = 5; |
4517 | + content_area.border_width = 5; |
4518 | + var sizegroup = new Gtk.SizeGroup (Gtk.SizeGroupMode.HORIZONTAL); |
4519 | + |
4520 | + var hbox = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 8); |
4521 | + hbox.border_width = 5; |
4522 | + var label = new Gtk.Label.with_mnemonic (_("_Application:")); |
4523 | + sizegroup.add_widget (label); |
4524 | + hbox.pack_start (label, false, false, 0); |
4525 | + var model = new Gtk.ListStore (4, typeof (string), typeof (string), typeof (string), typeof (int)); |
4526 | + var combo = new Gtk.ComboBox.with_model (model); |
4527 | + var pix_renderer = new Gtk.CellRendererPixbuf (); |
4528 | + combo.pack_start (pix_renderer, false); |
4529 | + combo.add_attribute (pix_renderer, "icon-name", 1); |
4530 | + combo.add_attribute (pix_renderer, "width", 3); |
4531 | + var text_renderer = new Gtk.CellRendererText (); |
4532 | + combo.pack_start (text_renderer, true); |
4533 | + combo.add_attribute (text_renderer, "text", 0); |
4534 | + |
4535 | + int icon_width = 16; |
4536 | + Gtk.icon_size_lookup_for_settings (get_settings (), Gtk.IconSize.MENU, out icon_width, null); |
4537 | + |
4538 | + foreach (var client in bookmark_clients) { |
4539 | + var location = client.path; |
4540 | + var client_name = client.name; |
4541 | + |
4542 | + /* Interpret * as 'any folder' */ |
4543 | + if (location.index_of ("*") > -1) { |
4544 | + var parts = location.split ("*", 2); |
4545 | + var path = Path.build_filename (Environment.get_home_dir (), parts[0]); |
4546 | + try { |
4547 | + var dir = Dir.open (path); |
4548 | + string name; |
4549 | + while ((name = dir.read_name ()) != null) { |
4550 | + var file = Path.build_filename (path, name, parts[1]); |
4551 | + if (Posix.access (file, Posix.F_OK) == 0) { |
4552 | + /* If name is XYZ.Name, we use Name only */ |
4553 | + var real_name = name.split (".", 2); |
4554 | + var display = _(client_name).index_of ("%s") > -1 |
4555 | + ? _(client_name).printf (real_name.length > 1 ? real_name[1] : name) |
4556 | + : _(client_name); |
4557 | + model.insert_with_values (null, int.MAX, |
4558 | + 0, display, 1, client.icon, |
4559 | + 2, file, 3, icon_width); |
4560 | + } |
4561 | + } |
4562 | + } catch (Error e) {} |
4563 | + continue; |
4564 | + } |
4565 | + |
4566 | + var path = Path.build_filename (Environment.get_home_dir (), location); |
4567 | + if (Posix.access (path, Posix.F_OK) == 0) |
4568 | + model.insert_with_values (null, int.MAX, |
4569 | + 0, _(client_name), 1, client.icon, |
4570 | + 2, path, 3, icon_width); |
4571 | + } |
4572 | + |
4573 | + model.insert_with_values (null, int.MAX, |
4574 | + 0, _("Import from XBEL or HTML file"), 1, null, 2, null, 3, icon_width); |
4575 | + combo.active = 0; |
4576 | + hbox.pack_start (combo, true, true, 0); |
4577 | + content_area.pack_start (hbox, false, true, 0); |
4578 | + |
4579 | + var combobox_folder = bookmark_folder_button_new (bookmarks, 0); |
4580 | + content_area.pack_start (combobox_folder, false, true, 0); |
4581 | + content_area.show_all (); |
4582 | + |
4583 | + dialog.set_default_response (Gtk.ResponseType.ACCEPT); |
4584 | + if (Midori.Dialog.run (dialog) == Gtk.ResponseType.ACCEPT) { |
4585 | + Gtk.TreeIter iter; |
4586 | + string? path = null; |
4587 | + |
4588 | + if (combo.get_active_iter (out iter)) |
4589 | + model.@get (iter, 2, out path); |
4590 | + var selected = combobox_folder.get_active (); |
4591 | + |
4592 | + dialog.destroy (); |
4593 | + if (path == null) { |
4594 | + var file_dialog = new FileChooserDialog (_("Import from a file"), this, Gtk.FileChooserAction.OPEN); |
4595 | + if (Midori.Dialog.run (file_dialog) == Gtk.ResponseType.OK) |
4596 | + path = file_dialog.get_filename (); |
4597 | + file_dialog.destroy (); |
4598 | + } |
4599 | + |
4600 | + var bookmarks = new Katze.Array (typeof (Katze.Array)); |
4601 | + if (path != null) { |
4602 | + try { |
4603 | + array_from_file (bookmarks, path, null); |
4604 | + } catch (Error e) { |
4605 | + Sokoke.message_dialog (Gtk.MessageType.ERROR, _("Failed to import bookmarks"), e.message, false); |
4606 | + } |
4607 | + } |
4608 | + this.bookmarks.import_array (bookmarks, selected); |
4609 | + } else |
4610 | + dialog.destroy (); |
4611 | + } |
4612 | + |
4613 | + void action_bookmarks_export_activate (Gtk.Action action) { |
4614 | + string? path = null; |
4615 | + string format; |
4616 | + |
4617 | + var wrong_format = true; |
4618 | + |
4619 | + while (wrong_format) { |
4620 | + var file_dialog = new FileChooserDialog (_("Save file as"), this, Gtk.FileChooserAction.SAVE); |
4621 | + file_dialog.set_current_name ("bookmarks.xbel"); |
4622 | + |
4623 | + Gtk.FileFilter filter; |
4624 | + |
4625 | + filter = new Gtk.FileFilter (); |
4626 | + filter.set_filter_name (_("XBEL Bookmarks")); |
4627 | + filter.add_mime_type ("application/xml"); |
4628 | + filter.add_pattern ("*.xbel"); |
4629 | + file_dialog.add_filter (filter); |
4630 | + |
4631 | + filter = new Gtk.FileFilter (); |
4632 | + filter.set_name (_("Netscape Bookmarks")); |
4633 | + filter.add_mime_type ("text/html"); |
4634 | + filter.add_pattern ("*.html"); |
4635 | + file_dialog.add_filter (filter); |
4636 | + |
4637 | + if (Dialog.run (file_dialog) == Gtk.ResponseType.OK) |
4638 | + path = file_dialog.get_filename (); |
4639 | + file_dialog.destroy (); |
4640 | + |
4641 | + if (path == null) |
4642 | + return; |
4643 | + |
4644 | + if (path.has_suffix (".xbel")) |
4645 | + format = "xbel"; |
4646 | + else if (path.has_suffix (".html")) |
4647 | + format = "netscape"; |
4648 | + else { |
4649 | + Sokoke.message_dialog (Gtk.MessageType.ERROR, |
4650 | + _("Midori can only export to XBEL (*.xbel) and Netscape (*.html)"), "", true); |
4651 | + path = null; |
4652 | + continue; |
4653 | + } |
4654 | + |
4655 | + wrong_format = false; |
4656 | + |
4657 | + var bookmarks = bookmarks.query_recursive ("*", "parentid IS null", null, true); |
4658 | + try { |
4659 | + array_to_file (bookmarks, path, format); |
4660 | + } catch (Error e) { |
4661 | + Sokoke.message_dialog (Gtk.MessageType.ERROR, _("Failed to export bookmarks"), e.message, false); |
4662 | + } |
4663 | + } |
4664 | + } |
4665 | + |
4666 | + Gtk.Dialog? search_engines_dialog = null; |
4667 | + void action_manage_search_engines_activate (Gtk.Action action) { |
4668 | + if (search_engines_dialog == null) { |
4669 | + search_engines_dialog = ((SearchAction) action_group.get_action ("Search")).get_dialog (); |
4670 | + search_engines_dialog.destroy.connect (() => search_engines_dialog = null); |
4671 | + search_engines_dialog.show (); |
4672 | + } |
4673 | + else |
4674 | + search_engines_dialog.present (); |
4675 | + } |
4676 | + |
4677 | + Gtk.Dialog? clear_private_data_dialog = null; |
4678 | + void action_clear_private_data_activate (Gtk.Action action) { |
4679 | + if (clear_private_data_dialog == null) { |
4680 | + clear_private_data_dialog = private_data_get_dialog (this); |
4681 | + clear_private_data_dialog.destroy.connect (() => clear_private_data_dialog = null); |
4682 | + clear_private_data_dialog.show (); |
4683 | + } else |
4684 | + clear_private_data_dialog.present (); |
4685 | + } |
4686 | + |
4687 | + void action_inspect_page_activate (Gtk.Action action) { |
4688 | + var view = get_current_tab (); |
4689 | + var web_view = view.web_view; |
4690 | + var inspector = web_view.get_inspector (); |
4691 | + inspector.show (); |
4692 | + } |
4693 | + |
4694 | + void action_tab_move_activate (Gtk.Action action) { |
4695 | + var name = action.name; |
4696 | + int new_pos; |
4697 | + var cur_pos = get_current_page (); |
4698 | + var widget = get_nth_tab (cur_pos); |
4699 | + |
4700 | + if (name == "TabMoveFirst") |
4701 | + new_pos = 0; |
4702 | + else if (name == "TabMoveBackward") { |
4703 | + if (cur_pos > 0) |
4704 | + new_pos = cur_pos - 1; |
4705 | + else |
4706 | + new_pos = get_n_pages () - 1; |
4707 | + } else if (name == "TabMoveForward") { |
4708 | + if (cur_pos == (get_n_pages () - 1)) |
4709 | + new_pos = 0; |
4710 | + else |
4711 | + new_pos = cur_pos + 1; |
4712 | + } else if (name == "TabMoveLast") |
4713 | + new_pos = get_n_pages () - 1; |
4714 | + else |
4715 | + assert_not_reached (); |
4716 | + |
4717 | + notebook.move ((Tab) widget, new_pos); |
4718 | + move_tab (notebook, cur_pos, new_pos); |
4719 | + } |
4720 | + |
4721 | + void action_tab_previous_activate (Gtk.Action action) { |
4722 | + set_current_page (get_current_page () - 1); |
4723 | + } |
4724 | + |
4725 | + void action_tab_next_activate (Gtk.Action action) { |
4726 | + /* Advance one tab or jump to the first one if we are at the last one */ |
4727 | + var n = get_current_page (); |
4728 | + if (n == get_n_pages () - 1) |
4729 | + n = -1; |
4730 | + set_current_page (n + 1); |
4731 | + } |
4732 | + |
4733 | + void action_tab_current_activate (Gtk.Action action) { |
4734 | + var view = get_current_tab (); |
4735 | + view.grab_focus (); |
4736 | + } |
4737 | + |
4738 | + void action_next_view_activate (Gtk.Action action) { |
4739 | + get_current_tab ().grab_focus (); |
4740 | + } |
4741 | + |
4742 | + void action_tab_minimize_activate (Gtk.Action action) { |
4743 | + var view = get_current_tab (); |
4744 | + view.minimized = !view.minimized; |
4745 | + } |
4746 | + |
4747 | + void action_tab_duplicate_activate (Gtk.Action action) { |
4748 | + var view = (View) action.get_data<Tab> ("tab"); |
4749 | + if (view == null) |
4750 | + view = (View) get_current_tab (); |
4751 | + view.duplicate (); |
4752 | + } |
4753 | + |
4754 | + void action_tab_close_other_activate (Gtk.Action action) { |
4755 | + var view = get_current_tab (); |
4756 | + foreach (var tab in get_tabs ()) { |
4757 | + if (tab != view) |
4758 | + close_tab (tab); |
4759 | + } |
4760 | + } |
4761 | + |
4762 | + static const string[] credits_authors = { "Christian Dywan <christian@twotoasts.de>" }; |
4763 | + static const string[] credits_documenters = { "Christian Dywan <christian@twotoasts.de>" }; |
4764 | + static const string[] credits_artists = { "Nancy Runge <nancy@twotoasts.de>" }; |
4765 | + |
4766 | + string get_docs (bool error) |
4767 | + { |
4768 | +#if G_OS_WIN32 |
4769 | + var path = Paths.get_data_filename ("doc/midori/faq.html", false); |
4770 | + try { |
4771 | + return Filename.to_uri (path, null); |
4772 | + } catch (Error e) {} |
4773 | + |
4774 | + return ""; |
4775 | +#else |
4776 | + var path = Paths.get_res_filename ("faq.html"); |
4777 | + bool found = Posix.access (path, Posix.F_OK) == 0; |
4778 | + if (found) { |
4779 | + try { |
4780 | + return Filename.to_uri (path, null); |
4781 | + } catch (Error e) {} |
4782 | + } |
4783 | + return "file://" + DOCDIR + "/faq.html"; |
4784 | +#endif |
4785 | + } |
4786 | + |
4787 | + void action_about_activate (Gtk.Action action) { |
4788 | + var comments = "%s\n%s".printf ( |
4789 | + _("A lightweight web browser."), |
4790 | + _("See about:version for version info.")); |
4791 | + var license = |
4792 | + _("This library is free software; you can redistribute it and/or " + |
4793 | + "modify it under the terms of the GNU Lesser General Public " + |
4794 | + "License as published by the Free Software Foundation; either " + |
4795 | + "version 2.1 of the License, or (at your option) any later version."); |
4796 | + |
4797 | +#if HAVE_GRANITE |
4798 | + var docs = get_docs (false); |
4799 | + /* Avoid granite_widgets_show_about_dialog for invalid memory and crashes */ |
4800 | + /* FIXME: granite: should return GtkWidget* like GTK+ */ |
4801 | + var dialog = new Granite.Widgets.AboutDialog (); |
4802 | + dialog.@set ( |
4803 | + "translate", "https://translations.xfce.org/projects/p/midori/", |
4804 | + "bug", PACKAGE_BUGREPORT, |
4805 | + "help", docs, |
4806 | + "copyright", "2007-2013 Christian Dywan", |
4807 | +#else |
4808 | + var dialog = new Gtk.AboutDialog (); |
4809 | + dialog.@set ( |
4810 | + "wrap-license", true, |
4811 | + "copyright", "Copyright © 2007-2013 Christian Dywan", |
4812 | +#endif |
4813 | + "transient-for", this, |
4814 | + "logo-icon-name", icon_name, |
4815 | + "program-name", PACKAGE_NAME, |
4816 | + "version", PACKAGE_VERSION, |
4817 | + "comments", comments, |
4818 | + "website", "http://www.midori-browser.org", |
4819 | + "authors", credits_authors, |
4820 | + "documenters", credits_documenters, |
4821 | + "artists", credits_artists, |
4822 | + "license", license, |
4823 | + "translator-credits", _("translator-credits")); |
4824 | + dialog.show (); |
4825 | + dialog.response.connect ((dialog, response) => dialog.destroy ()); |
4826 | + } |
4827 | + |
4828 | + void action_help_link_activate (Gtk.Action action) { |
4829 | + var action_name = action.name; |
4830 | + string? uri = null; |
4831 | + if (action_name.has_prefix ("HelpFAQ")) |
4832 | + uri = get_docs (true); |
4833 | + else if (action_name.has_prefix ("HelpBugs")) { |
4834 | + try { |
4835 | + Process.spawn_command_line_async ("ubuntu-bug " + PACKAGE_NAME); |
4836 | + } catch (Error e) { |
4837 | + uri = PACKAGE_BUGREPORT; |
4838 | + } |
4839 | + } |
4840 | + |
4841 | + if (uri != null) |
4842 | + set_current_tab (add_uri (uri)); |
4843 | + } |
4844 | + |
4845 | + void action_panel_activate (Gtk.Action action) { |
4846 | + var active = ((Gtk.ToggleAction) action).active; |
4847 | + settings.show_panel = active; |
4848 | + Sokoke.widget_set_visible (panel, active); |
4849 | + } |
4850 | + |
4851 | + bool panel_timeout (Gtk.Paned hpaned) { |
4852 | + settings.last_panel_position = hpaned.position; |
4853 | + _panel_timeout = 0; |
4854 | + return false; |
4855 | + } |
4856 | + |
4857 | + void panel_notify_position_cb (Object hpaned, ParamSpec pspec) { |
4858 | + if (_panel_timeout == 0) |
4859 | + _panel_timeout = Timeout.add_seconds (5, () => panel_timeout ((Gtk.Paned) hpaned)); |
4860 | + } |
4861 | + |
4862 | + bool panel_cycle_child_focus_cb (Gtk.Widget hpaned, bool reversed) { |
4863 | + /* Default cycle goes between all GtkPaned widgets. |
4864 | + If focus is in the panel, focus the location as if it's a paned. |
4865 | + If nothing is focussed, simply go to the location. |
4866 | + Be sure to suppress the default because the signal can recurse. */ |
4867 | + var focus = get_focus (); |
4868 | + if (focus.get_ancestor (typeof (Panel)) != null |
4869 | + || focus.get_ancestor (typeof (Gtk.Paned)) == null) { |
4870 | + Signal.stop_emission_by_name (hpaned, "cycle-child-focus"); |
4871 | + activate_action ("Location"); |
4872 | + return true; |
4873 | + } |
4874 | + return false; |
4875 | + } |
4876 | + |
4877 | + void panel_notify_page_cb (Object panel, ParamSpec pspec) { |
4878 | + var page = ((Panel) panel).page; |
4879 | + if (page > -1) |
4880 | + settings.last_panel_page = page; |
4881 | + } |
4882 | + |
4883 | + void panel_notify_show_titles_cb (Object object, ParamSpec pspec) { |
4884 | + var panel = (Panel) object; |
4885 | + var signal_id = settings.get_data<ulong> ("handler-settings-notify"); |
4886 | + |
4887 | + SignalHandler.block (settings, signal_id); |
4888 | + settings.compact_sidepanel = !panel.show_titles; |
4889 | + SignalHandler.unblock (settings, signal_id); |
4890 | + } |
4891 | + |
4892 | + void panel_notify_right_aligned_cb (Object object, ParamSpec pspec) { |
4893 | + var panel = (Panel) object; |
4894 | + |
4895 | + var right_aligned = panel.right_aligned; |
4896 | + var hpaned = (Gtk.Paned) panel.get_parent (); |
4897 | + var vpaned = notebook.get_parent (); |
4898 | + var paned_position = hpaned.position; |
4899 | + |
4900 | + Gtk.Allocation allocation; |
4901 | + hpaned.get_allocation (out allocation); |
4902 | + var paned_size = allocation.width; |
4903 | + |
4904 | + settings.right_align_sidepanel = right_aligned; |
4905 | + |
4906 | + panel.@ref (); |
4907 | + vpaned.@ref (); |
4908 | + hpaned.remove (panel); |
4909 | + hpaned.remove (vpaned); |
4910 | + if (right_aligned) { |
4911 | + hpaned.pack1 (vpaned, true, false); |
4912 | + hpaned.pack2 (panel, false, false); |
4913 | + } else { |
4914 | + hpaned.pack1 (panel, false, false); |
4915 | + hpaned.pack2 (vpaned, true, false); |
4916 | + } |
4917 | + hpaned.position = paned_size - paned_position; |
4918 | + panel.unref (); |
4919 | + vpaned.unref (); |
4920 | + } |
4921 | + |
4922 | + bool panel_close_cb (Panel panel) { |
4923 | + action_set_active ("Panel", false); |
4924 | + return false; |
4925 | + } |
4926 | + |
4927 | + void switched_tab_cb (Notebook notebook, Tab? old_tab, Tab new_tab) { |
4928 | + if (old_tab != null) { |
4929 | + var action = action_group.get_action ("Location"); |
4930 | + var text = ((LocationAction) action).get_text (); |
4931 | + old_tab.set_data<string> ("midori-browser-typed-text", text); |
4932 | + } |
4933 | + |
4934 | + return_if_fail (new_tab is View); |
4935 | + return_if_fail (new_tab != old_tab); |
4936 | + |
4937 | + var new_view = (View) new_tab; |
4938 | + var uri = new_view.get_data<string> ("midori-browser-typed-text"); |
4939 | + if (uri == null) |
4940 | + uri = new_view.get_display_uri (); |
4941 | + title = new_view.get_display_title (); |
4942 | + var action = (LocationAction) action_group.get_action ("Location"); |
4943 | + action.set_text (uri); |
4944 | + if (Paths.get_runtime_mode () == RuntimeMode.APP) |
4945 | + icon = new_view.get_icon (); |
4946 | + |
4947 | + switch_tab (old_tab, new_view); |
4948 | + _set_statusbar_text (new_view, null); |
4949 | + update_interface (new_view); |
4950 | + update_progress (new_view); |
4951 | + } |
4952 | + |
4953 | + void notify_tab_cb (Object? object, ParamSpec? pspec) { |
4954 | + freeze_notify (); |
4955 | + notify_property ("uri"); |
4956 | + notify_property ("uri"); |
4957 | + notify_property ("title"); |
4958 | + notify_property ("tab"); |
4959 | + thaw_notify (); |
4960 | + } |
4961 | + |
4962 | + void tab_moved_cb (Gtk.Widget notebook, Tab tab, uint page_num) { |
4963 | + var item = ((View) tab).get_proxy_item (); |
4964 | + proxy_array.move_item (item, (int) page_num); |
4965 | + } |
4966 | + |
4967 | + void notebook_create_window_cb (Gtk.Widget notebook, Gtk.Widget widget, int x, int y) { |
4968 | + var view = (View) widget; |
4969 | + var new_browser = new_window (null); |
4970 | + if (new_browser != null) { |
4971 | + new_browser.move (x, y); |
4972 | + view.@ref (); |
4973 | + disconnect_tab (view); |
4974 | + ((Notebook) notebook).remove (view); |
4975 | + new_browser.add_tab (view); |
4976 | + view.unref (); |
4977 | + } |
4978 | + } |
4979 | + |
4980 | + void notebook_new_tab_cb (Gtk.Widget notebook) { |
4981 | + var view = add_uri ("about:new"); |
4982 | + set_current_tab (view); |
4983 | + } |
4984 | + |
4985 | + void notebook_context_menu_cb (Notebook notebook, ContextAction menu) { |
4986 | + menu.add_action_group (action_group); |
4987 | + menu.add (null); |
4988 | + menu.add_by_name ("TabNew"); |
4989 | + menu.add_by_name ("UndoTabClose"); |
4990 | + } |
4991 | + |
4992 | + void notebook_tab_context_menu_cb (Notebook notebook, Tab tab, ContextAction menu) { |
4993 | + menu.add_action_group (action_group); |
4994 | + menu.add (null); |
4995 | + menu.add_by_name ("TabNew"); |
4996 | + menu.add_by_name ("UndoTabClose"); |
4997 | + if (tab is View) { |
4998 | + var action = new Gtk.Action ("TabDuplicate", _("_Duplicate Current Tab"), null, null); |
4999 | + action.set_data<Tab> ("tab", tab); |
5000 | + action.activate.connect (action_tab_duplicate_activate); |
The diff has been truncated for viewing.