/* Copyright (C) 2012-2013 André Stösel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See the file COPYING for the full license text. */ using Gtk; using Katze; using Midori; namespace DelayedLoad { private class PreferencesDialog : Gtk.Dialog { protected Manager dl_manager; protected Scale slider; public PreferencesDialog (Manager manager) { this.dl_manager = manager; this.title = _("Preferences for %s").printf ( _("Delayed load")); if (this.get_class ().find_property ("has-separator") != null) this.set ("has-separator", false); this.border_width = 5; this.set_modal (true); this.set_default_size (350, 100); this.create_widgets (); this.response.connect (response_cb); } private void response_cb (Gtk.Dialog source, int response_id) { switch (response_id) { case ResponseType.APPLY: this.dl_manager.set_integer ("delay", (int) (this.slider.get_value () * 1000)); this.dl_manager.preferences_changed (); this.destroy (); break; case ResponseType.CANCEL: this.destroy (); break; } } private void create_widgets () { Label text = new Label (_("Delay in seconds until loading the page:")); #if HAVE_GTK3 this.slider = new Scale.with_range (Orientation.HORIZONTAL, 0, 15, 0.1); #else this.slider = new HScale.with_range (0, 15, 0.1); #endif int delay = this.dl_manager.get_integer ("delay"); if (delay > 0) this.slider.set_value ((float)delay / 1000); #if HAVE_GTK3 Gtk.Box vbox = get_content_area () as Gtk.Box; vbox.pack_start (text, false, false, 0); vbox.pack_start (this.slider, false, true, 0); #else this.vbox.pack_start (text, false, false, 0); this.vbox.pack_start (this.slider, false, true, 0); #endif this.add_button (Gtk.STOCK_CANCEL, ResponseType.CANCEL); this.add_button (Gtk.STOCK_APPLY, ResponseType.APPLY); this.show_all (); } } private class TabShaker : GLib.Object { public unowned Midori.Browser browser; public GLib.PtrArray tasks; public bool reload_tab () { if (tasks.len == 1) { Midori.View? view = browser.tab as Midori.View; Midori.View scheduled_view = tasks.index (0) as Midori.View; if (scheduled_view == view) { Katze.Item item = view.get_proxy_item (); item.ref(); int64 delay = item.get_meta_integer ("delay"); if (delay == Midori.Delay.PENDING_UNDELAY) { view.reload (true); } } } tasks.remove_index (0); return false; } public TabShaker (Midori.Browser browser) { this.browser = browser; } construct { this.tasks = new GLib.PtrArray (); } } private class Manager : Midori.Extension { private int timeout = 0; private bool initialized = false; private HashTable tasks; public signal void preferences_changed (); private void preferences_changed_cb () { this.timeout = get_integer ("delay"); } private void show_preferences () { PreferencesDialog dialog = new PreferencesDialog (this); dialog.show (); } private void schedule_reload (Midori.Browser browser, Midori.View view) { if (this.timeout == 0) view.reload (true); else { unowned TabShaker shaker = tasks.get (browser); if (shaker != null) { shaker.tasks.add (view); Midori.Timeout.add (this.timeout, shaker.reload_tab); } } } private void tab_changed (Midori.View? old_view, Midori.View? new_view) { if (new_view != null) { Midori.App app = get_app (); Midori.Browser browser = app.browser; Katze.Item item = new_view.get_proxy_item (); item.ref(); int64 delay = item.get_meta_integer ("delay"); if (delay == Midori.Delay.PENDING_UNDELAY && new_view.progress < 1.0 && this.initialized) { this.schedule_reload (browser, new_view); } } } private bool reload_first_tab () { Midori.App app = get_app (); Midori.Browser? browser = app.browser; Midori.View? view = browser.tab as Midori.View; if (view != null) { this.initialized = true; Katze.Item item = view.get_proxy_item (); item.ref(); int64 delay = item.get_meta_integer ("delay"); if (delay != Midori.Delay.DELAYED) { if (view.load_status == Midori.LoadStatus.FINISHED) { if (this.timeout != 0) this.tasks.set (browser, new TabShaker (browser)); if (view.progress < 1.0) this.schedule_reload (browser, view); return false; } } } return true; } private void browser_added (Midori.Browser browser) { browser.switch_tab.connect_after (this.tab_changed); } private void browser_removed (Midori.Browser browser) { browser.switch_tab.disconnect (this.tab_changed); } public void activated (Midori.App app) { /* FIXME: override behavior without changing the preference */ app.settings.load_on_startup = MidoriStartup.DELAYED_PAGES; this.preferences_changed (); Midori.Browser? focused_browser = app.browser; if (focused_browser == null) Midori.Timeout.add (50, this.reload_first_tab); else this.initialized = true; foreach (Midori.Browser browser in app.get_browsers ()) { browser_added (browser); } app.add_browser.connect (browser_added); } public void deactivated () { Midori.App app = get_app (); foreach (Midori.Browser browser in app.get_browsers ()) { browser_removed (browser); } app.add_browser.disconnect (browser_added); } internal Manager () { GLib.Object (name: _("Delayed load"), description: _("Delay page load until you actually use the tab."), version: "0.1", authors: "André Stösel "); install_integer ("delay", 0); activate.connect (this.activated); deactivate.connect (this.deactivated); open_preferences.connect (show_preferences); preferences_changed.connect (preferences_changed_cb); this.tasks = new HashTable (GLib.direct_hash, GLib.direct_equal); } } } public Midori.Extension extension_init () { return new DelayedLoad.Manager (); }