Add a new option to change behavior when closing a tab
This commit is contained in:
parent
fa970c076b
commit
b49de2ab26
1 changed files with 461 additions and 314 deletions
|
@ -14,21 +14,35 @@ using Gdk;
|
||||||
using WebKit;
|
using WebKit;
|
||||||
using Midori;
|
using Midori;
|
||||||
|
|
||||||
enum TabTreeCells {
|
namespace HistoryList {
|
||||||
|
enum TabTreeCells {
|
||||||
TREE_CELL_PIXBUF,
|
TREE_CELL_PIXBUF,
|
||||||
TREE_CELL_STRING,
|
TREE_CELL_STRING,
|
||||||
TREE_CELL_POINTER,
|
TREE_CELL_POINTER,
|
||||||
TREE_CELL_COUNT
|
TREE_CELL_COUNT
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract class HistoryWindow : Gtk.Window {
|
enum TabClosingBehavior {
|
||||||
|
NONE,
|
||||||
|
LAST,
|
||||||
|
NEW
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TabClosingBehaviorModel {
|
||||||
|
TEXT,
|
||||||
|
VALUE
|
||||||
|
}
|
||||||
|
|
||||||
|
private abstract class HistoryWindow : Gtk.Window {
|
||||||
public Midori.Browser browser { get; construct set; }
|
public Midori.Browser browser { get; construct set; }
|
||||||
protected Gtk.TreeView? treeview = null;
|
protected Gtk.TreeView? treeview = null;
|
||||||
|
|
||||||
public HistoryWindow (Midori.Browser browser) {
|
public HistoryWindow (Midori.Browser browser) {
|
||||||
GLib.Object (type: Gtk.WindowType.POPUP,
|
GLib.Object (type: Gtk.WindowType.POPUP,
|
||||||
window_position: Gtk.WindowPosition.CENTER,
|
window_position: Gtk.WindowPosition.CENTER,
|
||||||
browser: browser);
|
browser: browser);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void walk (int step) {
|
public virtual void walk (int step) {
|
||||||
Gtk.TreePath? path;
|
Gtk.TreePath? path;
|
||||||
Gtk.TreeViewColumn? column;
|
Gtk.TreeViewColumn? column;
|
||||||
|
@ -46,12 +60,14 @@ private abstract class HistoryWindow : Gtk.Window {
|
||||||
path = new Gtk.TreePath.from_indices (new_index);
|
path = new Gtk.TreePath.from_indices (new_index);
|
||||||
this.treeview.set_cursor (path, column, false);
|
this.treeview.set_cursor (path, column, false);
|
||||||
}
|
}
|
||||||
public abstract void make_update ();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class TabWindow : HistoryWindow {
|
public abstract void make_update ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TabWindow : HistoryWindow {
|
||||||
protected Gtk.HBox? hbox;
|
protected Gtk.HBox? hbox;
|
||||||
protected Gtk.VBox? vbox;
|
protected Gtk.VBox? vbox;
|
||||||
|
|
||||||
protected void store_append_row (GLib.PtrArray list, Gtk.ListStore store, out Gtk.TreeIter iter) {
|
protected void store_append_row (GLib.PtrArray list, Gtk.ListStore store, out Gtk.TreeIter iter) {
|
||||||
for (var i = list.len; i > 0; i--) {
|
for (var i = list.len; i > 0; i--) {
|
||||||
Midori.View view = list.index (i - 1) as Midori.View;
|
Midori.View view = list.index (i - 1) as Midori.View;
|
||||||
|
@ -67,6 +83,7 @@ private class TabWindow : HistoryWindow {
|
||||||
TabTreeCells.TREE_CELL_POINTER, view);
|
TabTreeCells.TREE_CELL_POINTER, view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void insert_rows (Gtk.ListStore store) {
|
protected virtual void insert_rows (Gtk.ListStore store) {
|
||||||
Gtk.TreeIter iter;
|
Gtk.TreeIter iter;
|
||||||
unowned GLib.PtrArray list = this.browser.get_data<GLib.PtrArray> ("history-list-tab-history");
|
unowned GLib.PtrArray list = this.browser.get_data<GLib.PtrArray> ("history-list-tab-history");
|
||||||
|
@ -74,6 +91,7 @@ private class TabWindow : HistoryWindow {
|
||||||
store_append_row (list, store, out iter);
|
store_append_row (list, store, out iter);
|
||||||
store_append_row (list_new, store, out iter);
|
store_append_row (list_new, store, out iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TabWindow (Midori.Browser browser) {
|
public TabWindow (Midori.Browser browser) {
|
||||||
base (browser);
|
base (browser);
|
||||||
|
|
||||||
|
@ -121,6 +139,7 @@ private class TabWindow : HistoryWindow {
|
||||||
|
|
||||||
this.show_all ();
|
this.show_all ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void make_update () {
|
public override void make_update () {
|
||||||
Gtk.TreePath? path;
|
Gtk.TreePath? path;
|
||||||
Gtk.TreeViewColumn? column;
|
Gtk.TreeViewColumn? column;
|
||||||
|
@ -136,10 +155,11 @@ private class TabWindow : HistoryWindow {
|
||||||
model.get (iter, TabTreeCells.TREE_CELL_POINTER, out view);
|
model.get (iter, TabTreeCells.TREE_CELL_POINTER, out view);
|
||||||
this.browser.set ("tab", view);
|
this.browser.set ("tab", view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class NewTabWindow : TabWindow {
|
private class NewTabWindow : TabWindow {
|
||||||
protected bool first_step = true;
|
protected bool first_step = true;
|
||||||
|
|
||||||
protected override void insert_rows (Gtk.ListStore store) {
|
protected override void insert_rows (Gtk.ListStore store) {
|
||||||
Gtk.TreeIter iter;
|
Gtk.TreeIter iter;
|
||||||
unowned GLib.PtrArray list = this.browser.get_data<GLib.PtrArray> ("history-list-tab-history-new");
|
unowned GLib.PtrArray list = this.browser.get_data<GLib.PtrArray> ("history-list-tab-history-new");
|
||||||
|
@ -152,28 +172,126 @@ private class NewTabWindow : TabWindow {
|
||||||
store_append_row (list_old, store, out iter);
|
store_append_row (list_old, store, out iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void walk (int step) {
|
public override void walk (int step) {
|
||||||
if (this.first_step == false || step != 1) {
|
if (this.first_step == false || step != 1) {
|
||||||
base.walk (step);
|
base.walk (step);
|
||||||
}
|
}
|
||||||
this.first_step = false;
|
this.first_step = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NewTabWindow (Midori.Browser browser) {
|
public NewTabWindow (Midori.Browser browser) {
|
||||||
base (browser);
|
base (browser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class PreferencesDialog : Dialog {
|
||||||
|
protected Manager hl_manager;
|
||||||
|
protected ComboBox closing_behavior;
|
||||||
|
|
||||||
|
public PreferencesDialog (Manager manager) {
|
||||||
|
this.hl_manager = manager;
|
||||||
|
|
||||||
|
this.title = _("Preferences for %s").printf( _("History-List"));
|
||||||
|
this.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 (Dialog source, int response_id) {
|
||||||
|
switch (response_id) {
|
||||||
|
case ResponseType.APPLY:
|
||||||
|
int value;
|
||||||
|
TreeIter iter;
|
||||||
|
|
||||||
|
this.closing_behavior.get_active_iter (out iter);
|
||||||
|
var model = this.closing_behavior.get_model ();
|
||||||
|
model.get (iter, TabClosingBehaviorModel.VALUE, out value);
|
||||||
|
|
||||||
|
this.hl_manager.set_integer ("TabClosingBehavior", value);
|
||||||
|
this.hl_manager.preferences_changed ();
|
||||||
|
|
||||||
|
this.destroy ();
|
||||||
|
break;
|
||||||
|
case ResponseType.CANCEL:
|
||||||
|
this.destroy ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void create_widgets () {
|
||||||
|
ListStore model;
|
||||||
|
TreeIter iter;
|
||||||
|
TreeIter? active_iter = null;
|
||||||
|
|
||||||
|
var table = new Table (1, 2, true);
|
||||||
|
var renderer = new CellRendererText ();
|
||||||
|
|
||||||
|
var label = new Label ( _("Tab closing behavior"));
|
||||||
|
table.attach_defaults (label, 0, 1, 0, 1);
|
||||||
|
|
||||||
|
var tab_closing_behavior = this.hl_manager.get_integer ("TabClosingBehavior");
|
||||||
|
|
||||||
|
model = new ListStore (2, typeof (string), typeof (int));
|
||||||
|
|
||||||
|
model.append (out iter);
|
||||||
|
model.set (iter, TabClosingBehaviorModel.TEXT, _("Do nothing"),
|
||||||
|
TabClosingBehaviorModel.VALUE, TabClosingBehavior.NONE);
|
||||||
|
if (TabClosingBehavior.NONE == tab_closing_behavior)
|
||||||
|
active_iter = iter;
|
||||||
|
|
||||||
|
model.append (out iter);
|
||||||
|
model.set (iter, TabClosingBehaviorModel.TEXT, _("Switch to last view tab"),
|
||||||
|
TabClosingBehaviorModel.VALUE, TabClosingBehavior.LAST);
|
||||||
|
if (TabClosingBehavior.LAST == tab_closing_behavior)
|
||||||
|
active_iter = iter;
|
||||||
|
|
||||||
|
model.append (out iter);
|
||||||
|
model.set (iter, TabClosingBehaviorModel.TEXT, _("Switch to newest tab"),
|
||||||
|
TabClosingBehaviorModel.VALUE, TabClosingBehavior.NEW);
|
||||||
|
if (TabClosingBehavior.NEW == tab_closing_behavior)
|
||||||
|
active_iter = iter;
|
||||||
|
|
||||||
|
this.closing_behavior = new ComboBox.with_model (model);
|
||||||
|
this.closing_behavior.set_active_iter (active_iter);
|
||||||
|
this.closing_behavior.pack_start (renderer, true);
|
||||||
|
this.closing_behavior.set_attributes (renderer, "text", 0);
|
||||||
|
|
||||||
|
table.attach_defaults (this.closing_behavior, 1, 2, 0, 1);
|
||||||
|
|
||||||
|
this.vbox.pack_start (table, false, true, 0);
|
||||||
|
|
||||||
|
this.add_button (Gtk.STOCK_CANCEL, ResponseType.CANCEL);
|
||||||
|
this.add_button (Gtk.STOCK_APPLY, ResponseType.APPLY);
|
||||||
|
|
||||||
|
this.show_all ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Manager : Midori.Extension {
|
||||||
|
public signal void preferences_changed ();
|
||||||
|
|
||||||
private class HistoryList : Midori.Extension {
|
|
||||||
protected uint escKeyval;
|
protected uint escKeyval;
|
||||||
protected uint modifier_count;
|
protected uint modifier_count;
|
||||||
|
protected int closing_behavior;
|
||||||
protected HistoryWindow? history_window;
|
protected HistoryWindow? history_window;
|
||||||
protected ulong[] tmp_sig_ids = new ulong[2];
|
protected ulong[] tmp_sig_ids = new ulong[2];
|
||||||
|
|
||||||
|
public void preferences_changed_cb () {
|
||||||
|
this.closing_behavior = this.get_integer ("TabClosingBehavior");
|
||||||
|
}
|
||||||
|
|
||||||
public bool key_press (Gdk.EventKey event_key) {
|
public bool key_press (Gdk.EventKey event_key) {
|
||||||
if (event_key.is_modifier > 0) {
|
if (event_key.is_modifier > 0) {
|
||||||
this.modifier_count++;
|
this.modifier_count++;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool key_release (Gdk.EventKey event_key, Browser browser) {
|
public bool key_release (Gdk.EventKey event_key, Browser browser) {
|
||||||
if (event_key.is_modifier > 0) {
|
if (event_key.is_modifier > 0) {
|
||||||
this.modifier_count--;
|
this.modifier_count--;
|
||||||
|
@ -191,6 +309,7 @@ private class HistoryList : Midori.Extension {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void walk (Gtk.Action action, Browser browser, Type type, int step) {
|
public void walk (Gtk.Action action, Browser browser, Type type, int step) {
|
||||||
Midori.View? view = null;
|
Midori.View? view = null;
|
||||||
view = browser.get_data<Midori.View?> ("history-list-last-change");
|
view = browser.get_data<Midori.View?> ("history-list-last-change");
|
||||||
|
@ -225,6 +344,7 @@ private class HistoryList : Midori.Extension {
|
||||||
var hw = this.history_window as HistoryWindow;
|
var hw = this.history_window as HistoryWindow;
|
||||||
hw.walk (step);
|
hw.walk (step);
|
||||||
}
|
}
|
||||||
|
|
||||||
void browser_added (Midori.Browser browser) {
|
void browser_added (Midori.Browser browser) {
|
||||||
ulong sidTabNext, sidTabPrevious;
|
ulong sidTabNext, sidTabPrevious;
|
||||||
var acg = new Gtk.AccelGroup ();
|
var acg = new Gtk.AccelGroup ();
|
||||||
|
@ -280,6 +400,7 @@ private class HistoryList : Midori.Extension {
|
||||||
browser.remove_tab.connect (tab_removed);
|
browser.remove_tab.connect (tab_removed);
|
||||||
browser.notify["tab"].connect (this.tab_changed);
|
browser.notify["tab"].connect (this.tab_changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void browser_removed (Midori.Browser browser) {
|
void browser_removed (Midori.Browser browser) {
|
||||||
string[] callbacks = { "HistoryListNextNewTab", "HistoryListPreviousNewTab" };
|
string[] callbacks = { "HistoryListNextNewTab", "HistoryListPreviousNewTab" };
|
||||||
ulong sidTabNext, sidTabPrevious;
|
ulong sidTabNext, sidTabPrevious;
|
||||||
|
@ -307,23 +428,33 @@ private class HistoryList : Midori.Extension {
|
||||||
browser.remove_tab.disconnect (tab_removed);
|
browser.remove_tab.disconnect (tab_removed);
|
||||||
browser.notify["tab"].disconnect (this.tab_changed);
|
browser.notify["tab"].disconnect (this.tab_changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tab_added (Midori.Browser browser, Midori.View view) {
|
void tab_added (Midori.Browser browser, Midori.View view) {
|
||||||
unowned GLib.PtrArray list = browser.get_data<GLib.PtrArray> ("history-list-tab-history-new");
|
unowned GLib.PtrArray list = browser.get_data<GLib.PtrArray> ("history-list-tab-history-new");
|
||||||
list.add (view);
|
list.add (view);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tab_removed (Midori.Browser browser, Midori.View view) {
|
void tab_removed (Midori.Browser browser, Midori.View view) {
|
||||||
unowned GLib.PtrArray list = browser.get_data<GLib.PtrArray> ("history-list-tab-history");
|
unowned GLib.PtrArray list = browser.get_data<GLib.PtrArray> ("history-list-tab-history");
|
||||||
unowned GLib.PtrArray list_new = browser.get_data<GLib.PtrArray> ("history-list-tab-history-new");
|
unowned GLib.PtrArray list_new = browser.get_data<GLib.PtrArray> ("history-list-tab-history-new");
|
||||||
list.remove (view);
|
list.remove (view);
|
||||||
list_new.remove (view);
|
list_new.remove (view);
|
||||||
|
|
||||||
|
if (this.closing_behavior == TabClosingBehavior.LAST || this.closing_behavior == TabClosingBehavior.NEW) {
|
||||||
browser.set_data<Midori.View?> ("history-list-last-change", null);
|
browser.set_data<Midori.View?> ("history-list-last-change", null);
|
||||||
|
|
||||||
if ((int) list.len > 0 || (int) list_new.len > 0) {
|
if ((int) list.len > 0 || (int) list_new.len > 0) {
|
||||||
var hw = new TabWindow (browser);
|
TabWindow hw;
|
||||||
|
if (this.closing_behavior == TabClosingBehavior.LAST)
|
||||||
|
hw = new TabWindow (browser);
|
||||||
|
else
|
||||||
|
hw = new NewTabWindow (browser);
|
||||||
hw.make_update ();
|
hw.make_update ();
|
||||||
hw.destroy ();
|
hw.destroy ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void tab_changed (GLib.Object window, GLib.ParamSpec pspec) {
|
void tab_changed (GLib.Object window, GLib.ParamSpec pspec) {
|
||||||
Midori.Browser browser = window as Midori.Browser;
|
Midori.Browser browser = window as Midori.Browser;
|
||||||
Midori.View view = null;
|
Midori.View view = null;
|
||||||
|
@ -337,6 +468,7 @@ private class HistoryList : Midori.Extension {
|
||||||
}
|
}
|
||||||
browser.set_data<Midori.View?> ("history-list-last-change", view);
|
browser.set_data<Midori.View?> ("history-list-last-change", view);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tab_list_resort (Midori.Browser browser, Midori.View view) {
|
void tab_list_resort (Midori.Browser browser, Midori.View view) {
|
||||||
unowned GLib.PtrArray list = browser.get_data<GLib.PtrArray> ("history-list-tab-history");
|
unowned GLib.PtrArray list = browser.get_data<GLib.PtrArray> ("history-list-tab-history");
|
||||||
unowned GLib.PtrArray list_new = browser.get_data<GLib.PtrArray> ("history-list-tab-history-new");
|
unowned GLib.PtrArray list_new = browser.get_data<GLib.PtrArray> ("history-list-tab-history-new");
|
||||||
|
@ -344,31 +476,46 @@ private class HistoryList : Midori.Extension {
|
||||||
list_new.remove (view);
|
list_new.remove (view);
|
||||||
list.add (view);
|
list.add (view);
|
||||||
}
|
}
|
||||||
|
|
||||||
void activated (Midori.App app) {
|
void activated (Midori.App app) {
|
||||||
|
this.preferences_changed ();
|
||||||
foreach (var browser in app.get_browsers ())
|
foreach (var browser in app.get_browsers ())
|
||||||
browser_added (browser);
|
browser_added (browser);
|
||||||
app.add_browser.connect (browser_added);
|
app.add_browser.connect (browser_added);
|
||||||
}
|
}
|
||||||
|
|
||||||
void deactivated () {
|
void deactivated () {
|
||||||
var app = get_app ();
|
var app = get_app ();
|
||||||
foreach (var browser in app.get_browsers ())
|
foreach (var browser in app.get_browsers ())
|
||||||
browser_removed (browser);
|
browser_removed (browser);
|
||||||
app.add_browser.disconnect (browser_added);
|
app.add_browser.disconnect (browser_added);
|
||||||
}
|
}
|
||||||
internal HistoryList () {
|
|
||||||
|
void show_preferences () {
|
||||||
|
var dialog = new PreferencesDialog (this);
|
||||||
|
dialog.show ();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Manager () {
|
||||||
GLib.Object (name: _("History List"),
|
GLib.Object (name: _("History List"),
|
||||||
description: _("Switch tabs with Ctrl+Tab sorted by last usage"),
|
description: _("Move to the last used tab when switching or closing tabs"),
|
||||||
version: "0.3",
|
version: "0.4",
|
||||||
authors: "André Stösel <andre@stoesel.de>");
|
authors: "André Stösel <andre@stoesel.de>");
|
||||||
activate.connect (activated);
|
|
||||||
deactivate.connect (deactivated);
|
this.install_integer ("TabClosingBehavior", TabClosingBehavior.LAST);
|
||||||
|
|
||||||
|
this.activate.connect (activated);
|
||||||
|
this.deactivate.connect (deactivated);
|
||||||
|
this.open_preferences.connect (show_preferences);
|
||||||
|
this.preferences_changed.connect (preferences_changed_cb);
|
||||||
}
|
}
|
||||||
construct {
|
construct {
|
||||||
this.escKeyval = Gdk.keyval_from_name ("Escape");
|
this.escKeyval = Gdk.keyval_from_name ("Escape");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Midori.Extension extension_init () {
|
public Midori.Extension extension_init () {
|
||||||
return new HistoryList ();
|
return new HistoryList.Manager ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue