~midori/midori/trunk

« back to all changes in this revision

Viewing changes to extensions/tabby.vala

  • Committer: Tarmac
  • Author(s): André Stösel
  • Date: 2013-10-04 07:40:34 UTC
  • mfrom: (6394.3.13 tabby-tab-order)
  • Revision ID: tarmac-20131004074034-0vuak2y6mrtrol3h
add tab sorting

Show diffs side-by-side

added added

removed removed

Lines of Context:
65
65
        }
66
66
 
67
67
        public abstract class Session : GLib.Object, ISession {
 
68
            protected GLib.SList<double?> tab_sorting;
 
69
 
 
70
            public Midori.Browser browser { get; protected set; }
 
71
 
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);
 
78
 
74
79
            public abstract Katze.Array get_tabs ();
75
80
 
76
81
            public void attach (Midori.Browser browser) {
77
 
                browser.add_tab.connect (this.tab_added);
 
82
                this.browser = browser;
 
83
 
 
84
                browser.add_tab.connect_after (this.tab_added);
78
85
                browser.add_tab.connect (this.helper_data_changed);
 
86
 
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);
80
90
 
81
91
                foreach (Midori.View view in browser.get_tabs ()) {
82
92
                    this.tab_added (browser, view);
85
95
            }
86
96
 
87
97
            public void restore (Midori.Browser browser) {
 
98
                this.browser = browser;
 
99
 
88
100
                Katze.Array tabs = this.get_tabs ();
89
101
 
90
102
                if(tabs.is_empty ()) {
93
105
                    tabs.add_item (item);
94
106
                }
95
107
 
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);
 
110
 
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);
99
114
 
100
115
                GLib.List<unowned Katze.Item> items = tabs.get_items ();
101
116
                unowned GLib.List<unowned Katze.Item> u_items = items;
104
119
 
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++) {
109
 
                            if (u_items == null)
 
125
                            if (u_items == null) {
 
126
                                this.helper_reorder_tabs (new_tabs);
110
127
                                return false;
 
128
                            }
111
129
 
112
130
                            Katze.Item t_item = u_items.data<Katze.Item>;
113
131
 
 
132
                            t_item.set_meta_integer ("append", 1);
 
133
 
114
134
                            if (delay)
115
135
                                t_item.set_meta_integer ("delay", Midori.Delay.DELAYED);
116
136
                            else
117
137
                                delay = true;
118
138
 
119
 
                            browser.add_item (t_item);
 
139
                            unowned Gtk.Widget tab = browser.add_item (t_item);
 
140
                            new_tabs.add (tab);
120
141
 
121
142
                            u_items = u_items.next;
122
143
                        }
 
144
                        this.helper_reorder_tabs (new_tabs);
123
145
                    }
124
146
                    return u_items != null;
125
147
                });
126
148
            }
127
149
 
 
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);
 
156
            }
 
157
 
 
158
#if HAVE_GTK3
 
159
            protected bool delete_event (Gtk.Widget widget, Gdk.EventAny event) {
 
160
#else
 
161
            protected bool delete_event (Gtk.Widget widget, Gdk.Event event) {
 
162
#endif
 
163
 
 
164
                this.close();
 
165
                return false;
 
166
 
 
167
            }
 
168
 
 
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;
 
173
 
 
174
                string? prev_meta_sorting = null;
 
175
                string? next_meta_sorting = null;
 
176
                double? prev_sorting, next_sorting, this_sorting;
 
177
 
 
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");
 
181
                }
 
182
 
 
183
                if (prev_meta_sorting == null)
 
184
                    prev_sorting = double.parse ("0");
 
185
                else
 
186
                    prev_sorting = double.parse (prev_meta_sorting);
 
187
 
 
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");
 
191
                }
 
192
 
 
193
                if (next_meta_sorting == null)
 
194
                    next_sorting = prev_sorting + 2048;
 
195
                else
 
196
                    next_sorting = double.parse (next_meta_sorting);
 
197
 
 
198
                this_sorting = prev_sorting + (next_sorting - prev_sorting) / 2;
 
199
 
 
200
                return this_sorting;
 
201
            }
 
202
 
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 (() => {
143
218
                    }
144
219
                });
145
220
            }
 
221
 
 
222
            private void helper_reorder_tabs (GLib.PtrArray new_tabs) {
 
223
                CompareDataFunc<double?> helper_compare_data = (a, b) => {
 
224
                    if (a > b)
 
225
                        return 1;
 
226
                    else if(a < b)
 
227
                        return -1;
 
228
                    return 0;
 
229
                };
 
230
 
 
231
                GLib.CompareFunc<double?> helper_compare_func = (a,b) => {
 
232
                    return a == b ? 0 : -1;
 
233
                };
 
234
 
 
235
                for(var i = 0; i < new_tabs.len; i++) {
 
236
                    Midori.View tab = new_tabs.index(i) as Midori.View;
 
237
 
 
238
                    unowned Katze.Item item = tab.get_proxy_item ();
 
239
 
 
240
                    double? sorting;
 
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);
 
245
 
 
246
                            int index = this.tab_sorting.position (this.tab_sorting.find_custom (sorting, helper_compare_func));
 
247
 
 
248
                            this.browser.notebook.reorder_child (tab, index);
 
249
                        }
 
250
                    }
 
251
                }
 
252
            }
 
253
 
 
254
            construct {
 
255
                this.tab_sorting = new GLib.SList<double?> ();
 
256
            }
146
257
        }
147
258
    }
148
259
 
154
265
 
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);
 
277
                if (sorting == null)
 
278
                    stmt.bind_double (stmt.bind_parameter_index (":sorting"), double.parse ("1"));
 
279
                else
 
280
                    stmt.bind_double (stmt.bind_parameter_index (":sorting"), double.parse (sorting));
 
281
 
165
282
                if (stmt.step () != Sqlite.DONE)
166
283
                    critical (_("Failed to update database: %s"), db.errmsg);
167
284
                else {
202
319
                unowned Katze.Item item = view.get_proxy_item ();
203
320
                int64 tab_id = item.get_meta_integer ("tabby-id");
204
321
                if (tab_id < 1) {
 
322
                    double? sorting = this.get_tab_sorting (view);
 
323
                    item.set_meta_string ("sorting", sorting.to_string ());
205
324
                    this.add_item (item);
206
325
                }
207
326
           }
220
339
                    critical (_("Failed to update database: %s"), db.errmsg ());
221
340
            }
222
341
 
 
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 ());
 
355
            }
 
356
 
223
357
            public override void close() {
 
358
                base.close ();
 
359
 
224
360
                if (Session.open_sessions == 1)
225
361
                    return;
226
362
 
239
375
            public override Katze.Array get_tabs() {
240
376
                Katze.Array tabs = new Katze.Array (typeof (Katze.Item));
241
377
 
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 ());
258
394
                    item.uri = uri;
259
395
                    item.name = title;
260
396
                    item.set_meta_integer ("tabby-id", id);
 
397
                    item.set_meta_string ("sorting", stmt.column_double (3).to_string ());
261
398
                    tabs.add_item (item);
262
399
                    result = stmt.step ();
263
400
                 }