67
67
public abstract class Session : GLib.Object, ISession {
68
protected GLib.SList<double?> tab_sorting;
70
public Midori.Browser browser { get; protected set; }
68
72
public abstract void add_item (Katze.Item item);
69
73
public abstract void uri_changed (Midori.View view, string uri);
70
74
public abstract void data_changed (Midori.View view);
71
75
public abstract void tab_added (Midori.Browser browser, Midori.View view);
72
76
public abstract void tab_removed (Midori.Browser browser, Midori.View view);
73
public abstract void close ();
77
public abstract void tab_switched (Midori.View? old_view, Midori.View? new_view);
74
79
public abstract Katze.Array get_tabs ();
76
81
public void attach (Midori.Browser browser) {
77
browser.add_tab.connect (this.tab_added);
82
this.browser = browser;
84
browser.add_tab.connect_after (this.tab_added);
78
85
browser.add_tab.connect (this.helper_data_changed);
79
87
browser.remove_tab.connect (this.tab_removed);
88
browser.switch_tab.connect (this.tab_switched);
89
browser.delete_event.connect_after(this.delete_event);
81
91
foreach (Midori.View view in browser.get_tabs ()) {
82
92
this.tab_added (browser, view);
93
105
tabs.add_item (item);
96
browser.add_tab.connect (this.tab_added);
108
browser.add_tab.connect_after (this.tab_added);
97
109
browser.add_tab.connect (this.helper_data_changed);
98
111
browser.remove_tab.connect (this.tab_removed);
112
browser.switch_tab.connect (this.tab_switched);
113
browser.delete_event.connect_after(this.delete_event);
100
115
GLib.List<unowned Katze.Item> items = tabs.get_items ();
101
116
unowned GLib.List<unowned Katze.Item> u_items = items;
105
120
GLib.Idle.add (() => {
106
121
/* Note: we need to use `items` for something to maintain a valid reference */
122
GLib.PtrArray new_tabs = new GLib.PtrArray ();
107
123
if (items.length () > 0) {
108
124
for (int i = 0; i < 3; i++) {
125
if (u_items == null) {
126
this.helper_reorder_tabs (new_tabs);
112
130
Katze.Item t_item = u_items.data<Katze.Item>;
132
t_item.set_meta_integer ("append", 1);
115
135
t_item.set_meta_integer ("delay", Midori.Delay.DELAYED);
119
browser.add_item (t_item);
139
unowned Gtk.Widget tab = browser.add_item (t_item);
121
142
u_items = u_items.next;
144
this.helper_reorder_tabs (new_tabs);
124
146
return u_items != null;
150
public virtual void close () {
151
this.browser.add_tab.disconnect (this.tab_added);
152
this.browser.add_tab.disconnect (this.helper_data_changed);
153
this.browser.remove_tab.disconnect (this.tab_removed);
154
this.browser.switch_tab.disconnect (this.tab_switched);
155
this.browser.delete_event.disconnect (this.delete_event);
159
protected bool delete_event (Gtk.Widget widget, Gdk.EventAny event) {
161
protected bool delete_event (Gtk.Widget widget, Gdk.Event event) {
169
protected double? get_tab_sorting (Midori.View view) {
170
int this_pos = this.browser.notebook.page_num (view);
171
Midori.View prev_view = this.browser.notebook.get_nth_page (this_pos - 1) as Midori.View;
172
Midori.View next_view = this.browser.notebook.get_nth_page (this_pos + 1) as Midori.View;
174
string? prev_meta_sorting = null;
175
string? next_meta_sorting = null;
176
double? prev_sorting, next_sorting, this_sorting;
178
if (prev_view != null) {
179
unowned Katze.Item prev_item = prev_view.get_proxy_item ();
180
prev_meta_sorting = prev_item.get_meta_string ("sorting");
183
if (prev_meta_sorting == null)
184
prev_sorting = double.parse ("0");
186
prev_sorting = double.parse (prev_meta_sorting);
188
if (next_view != null) {
189
unowned Katze.Item next_item = next_view.get_proxy_item ();
190
next_meta_sorting = next_item.get_meta_string ("sorting");
193
if (next_meta_sorting == null)
194
next_sorting = prev_sorting + 2048;
196
next_sorting = double.parse (next_meta_sorting);
198
this_sorting = prev_sorting + (next_sorting - prev_sorting) / 2;
128
203
private void helper_data_changed (Midori.Browser browser, Midori.View view) {
129
204
ulong sig_id = 0;
130
205
sig_id = view.web_view.load_started.connect (() => {
222
private void helper_reorder_tabs (GLib.PtrArray new_tabs) {
223
CompareDataFunc<double?> helper_compare_data = (a, b) => {
231
GLib.CompareFunc<double?> helper_compare_func = (a,b) => {
232
return a == b ? 0 : -1;
235
for(var i = 0; i < new_tabs.len; i++) {
236
Midori.View tab = new_tabs.index(i) as Midori.View;
238
unowned Katze.Item item = tab.get_proxy_item ();
241
string? sorting_string = item.get_meta_string ("sorting");
242
if (sorting_string != null) { /* we have to use a seperate if condition to avoid a `possibly unassigned local variable` error */
243
if (double.try_parse (item.get_meta_string ("sorting"), out sorting)) {
244
this.tab_sorting.insert_sorted_with_data (sorting, helper_compare_data);
246
int index = this.tab_sorting.position (this.tab_sorting.find_custom (sorting, helper_compare_func));
248
this.browser.notebook.reorder_child (tab, index);
255
this.tab_sorting = new GLib.SList<double?> ();
155
266
public override void add_item (Katze.Item item) {
156
267
GLib.DateTime time = new DateTime.now_local ();
157
string sqlcmd = "INSERT INTO `tabs` (`crdate`, `tstamp`, `session_id`, `uri`, `title`) VALUES (:tstamp, :tstamp, :session_id, :uri, :title);";
268
string? sorting = item.get_meta_string ("sorting");
269
string sqlcmd = "INSERT INTO `tabs` (`crdate`, `tstamp`, `session_id`, `uri`, `title`, `sorting`) VALUES (:tstamp, :tstamp, :session_id, :uri, :title, :sorting);";
158
270
Sqlite.Statement stmt;
159
271
if (this.db.prepare_v2 (sqlcmd, -1, out stmt, null) != Sqlite.OK)
160
272
critical (_("Failed to update database: %s"), db.errmsg);
162
274
stmt.bind_int64 (stmt.bind_parameter_index (":session_id"), this.id);
163
275
stmt.bind_text (stmt.bind_parameter_index (":uri"), item.uri);
164
276
stmt.bind_text (stmt.bind_parameter_index (":title"), item.name);
278
stmt.bind_double (stmt.bind_parameter_index (":sorting"), double.parse ("1"));
280
stmt.bind_double (stmt.bind_parameter_index (":sorting"), double.parse (sorting));
165
282
if (stmt.step () != Sqlite.DONE)
166
283
critical (_("Failed to update database: %s"), db.errmsg);
220
339
critical (_("Failed to update database: %s"), db.errmsg ());
342
protected override void tab_switched (Midori.View? old_view, Midori.View? new_view) {
343
GLib.DateTime time = new DateTime.now_local ();
344
unowned Katze.Item item = new_view.get_proxy_item ();
345
int64 tab_id = item.get_meta_integer ("tabby-id");
346
string sqlcmd = "UPDATE `tabs` SET tstamp = :tstamp WHERE session_id = :session_id AND id = :tab_id;";
347
Sqlite.Statement stmt;
348
if (this.db.prepare_v2 (sqlcmd, -1, out stmt, null) != Sqlite.OK)
349
critical (_("Failed to update database: %s"), db.errmsg ());
350
stmt.bind_int64 (stmt.bind_parameter_index (":session_id"), this.id);
351
stmt.bind_int64 (stmt.bind_parameter_index (":tab_id"), tab_id);
352
stmt.bind_int64 (stmt.bind_parameter_index (":tstamp"), time.to_unix ());
353
if (stmt.step () != Sqlite.DONE)
354
critical (_("Failed to update database: %s"), db.errmsg ());
223
357
public override void close() {
224
360
if (Session.open_sessions == 1)
239
375
public override Katze.Array get_tabs() {
240
376
Katze.Array tabs = new Katze.Array (typeof (Katze.Item));
242
string sqlcmd = "SELECT id, uri, title FROM tabs WHERE session_id = :session_id";
378
string sqlcmd = "SELECT id, uri, title, sorting FROM tabs WHERE session_id = :session_id ORDER BY tstamp DESC";
243
379
Sqlite.Statement stmt;
244
380
if (this.db.prepare_v2 (sqlcmd, -1, out stmt, null) != Sqlite.OK)
245
381
critical (_("Failed to select from database: %s"), db.errmsg ());