Merge lp:~kalikiana/midori/historydb into lp:midori

Proposed by Cris Dywan
Status: Merged
Approved by: Paweł Forysiuk
Approved revision: 6277
Merged at revision: 6283
Proposed branch: lp:~kalikiana/midori/historydb
Merge into: lp:midori
Diff against target: 253 lines (+150/-70)
2 files modified
midori/midori-historycompletion.vala (+22/-70)
midori/midori-historydatabase.vala (+128/-0)
To merge this branch: bzr merge lp:~kalikiana/midori/historydb
Reviewer Review Type Date Requested Status
Paweł Forysiuk Approve
Review via email: mp+176301@code.launchpad.net

Commit message

Introduce object oriented API for access to History Database

Description of the change

Goals include: introduce object-oriented API, hide SQL internals, allow HistoryDatabase in memory for testing or private browsing, all async (panel specifically), find a way to integrate downloads with history
Note that this will only cover the initial API and autocompletion; to keep review manageable separate branches will deal with speed dial, panel, etc

To post a comment you must log in.
Revision history for this message
Paweł Forysiuk (tuxator) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'midori/midori-historycompletion.vala'
2--- midori/midori-historycompletion.vala 2013-07-14 16:31:30 +0000
3+++ midori/midori-historycompletion.vala 2013-07-24 17:43:25 +0000
4@@ -11,22 +11,19 @@
5
6 namespace Midori {
7 public class HistoryCompletion : Completion {
8- unowned Sqlite.Database db;
9+ HistoryDatabase? database = null;
10
11 public HistoryCompletion () {
12 GLib.Object (description: _("Bookmarks and History"));
13 }
14
15 public override void prepare (GLib.Object app) {
16- GLib.Object history;
17- app.get ("history", out history);
18- return_if_fail (history != null);
19- db = history.get_data<Sqlite.Database?> ("db");
20- return_if_fail (db != null);
21+ database = new HistoryDatabase (app);
22+ return_if_fail (database != null);
23 }
24
25 public override bool can_complete (string text) {
26- return db != null;
27+ return database != null;
28 }
29
30 public override bool can_action (string action) {
31@@ -34,71 +31,26 @@
32 }
33
34 public override async List<Suggestion>? complete (string text, string? action, Cancellable cancellable) {
35- return_val_if_fail (db != null, null);
36-
37- Sqlite.Statement stmt;
38- unowned string sqlcmd = """
39- SELECT type, uri, title FROM (
40- SELECT 1 AS type, uri, title, count() AS ct FROM history
41- WHERE uri LIKE ?1 OR title LIKE ?1 GROUP BY uri
42- UNION ALL
43- SELECT 2 AS type, replace(uri, '%s', keywords) AS uri,
44- keywords AS title, count() AS ct FROM search
45- WHERE uri LIKE ?1 OR title LIKE ?1 GROUP BY uri
46- UNION ALL
47- SELECT 1 AS type, uri, title, 50 AS ct FROM bookmarks
48- WHERE title LIKE ?1 OR uri LIKE ?1 AND uri !='' AND uri NOT LIKE 'javascript:%'
49- ) GROUP BY uri ORDER BY ct DESC LIMIT ?2
50- """;
51- if (db.prepare_v2 (sqlcmd, -1, out stmt, null) != Sqlite.OK) {
52- critical (_("Failed to initialize history: %s"), db.errmsg ());
53- return null;
54- }
55-
56- string query = "%" + text.replace (" ", "%") + "%";
57- stmt.bind_text (1, query);
58- stmt.bind_int64 (2, max_items);
59-
60- int result = stmt.step ();
61- if (result != Sqlite.ROW) {
62- if (result == Sqlite.ERROR)
63- critical (_("Failed to select from history: %s"), db.errmsg ());
64- return null;
65- }
66+ return_val_if_fail (database != null, null);
67+
68+ List<HistoryItem> items = yield database.list_by_count_with_bookmarks (text, max_items, cancellable);
69+ if (items == null)
70+ return null;
71
72 var suggestions = new List<Suggestion> ();
73- while (result == Sqlite.ROW) {
74- int64 type = stmt.column_int64 (0);
75- unowned string uri = stmt.column_text (1);
76- unowned string title = stmt.column_text (2);
77- Gdk.Pixbuf? icon = Midori.Paths.get_icon (uri, null);
78- Suggestion suggestion;
79-
80- switch (type) {
81- case 1: /* history_view */
82- suggestion = new Suggestion (uri, title, false, null, icon);
83- suggestions.append (suggestion);
84- break;
85- case 2: /* search_view */
86- string desc = _("Search for %s").printf (title) + "\n" + uri;
87- /* FIXME: Theming? Win32? */
88- string background = "gray";
89- suggestion = new Suggestion (uri, desc, false, background, icon);
90- suggestions.append (suggestion);
91- break;
92- default:
93- warn_if_reached ();
94- break;
95- }
96-
97- uint src = Idle.add (complete.callback);
98- yield;
99- Source.remove (src);
100-
101- if (cancellable.is_cancelled ())
102- return null;
103-
104- result = stmt.step ();
105+ foreach (var item in items) {
106+ if (item is Midori.HistoryWebsite) {
107+ var website = item as Midori.HistoryWebsite;
108+ suggestions.append (new Suggestion (website.uri, website.title,
109+ false, null, Midori.Paths.get_icon (website.uri, null)));
110+ }
111+ else if (item is Midori.HistorySearch) {
112+ var search = item as Midori.HistorySearch;
113+ suggestions.append (new Suggestion (search.uri, search.title + "\n" + search.uri,
114+ false, "gray", Midori.Paths.get_icon (search.uri, null)));
115+ }
116+ else
117+ warn_if_reached ();
118 }
119
120 if (cancellable.is_cancelled ())
121
122=== added file 'midori/midori-historydatabase.vala'
123--- midori/midori-historydatabase.vala 1970-01-01 00:00:00 +0000
124+++ midori/midori-historydatabase.vala 2013-07-24 17:43:25 +0000
125@@ -0,0 +1,128 @@
126+/*
127+ Copyright (C) 2013 Christian Dywan <christian@twotoats.de>
128+
129+ This library is free software; you can redistribute it and/or
130+ modify it under the terms of the GNU Lesser General Public
131+ License as published by the Free Software Foundation; either
132+ version 2.1 of the License, or (at your option) any later version.
133+
134+ See the file COPYING for the full license text.
135+*/
136+
137+namespace Midori {
138+ public class HistoryWebsite : HistoryItem {
139+ public string uri { get; set; }
140+ public HistoryWebsite (string uri, string? title, int64 date) {
141+ GLib.Object (uri: uri,
142+ title: title,
143+ date: date);
144+ }
145+ }
146+
147+ public class HistorySearch : HistoryItem {
148+ public string uri { get; set; }
149+ public string keywords { get; set; }
150+ public HistorySearch (string uri, string keywords, int64 date) {
151+ GLib.Object (uri: uri,
152+ keywords: keywords,
153+ title: _("Search for %s").printf (keywords),
154+ date: date);
155+ }
156+ }
157+
158+ public class HistoryItem : GLib.Object {
159+ public string? title { get; set; }
160+ public int64 date { get; set; }
161+ }
162+
163+ public class HistoryDatabase : GLib.Object {
164+ unowned Sqlite.Database db = null;
165+
166+ public HistoryDatabase (GLib.Object app) {
167+ GLib.Object history;
168+ app.get ("history", out history);
169+ return_val_if_fail (history != null, null);
170+ db = history.get_data<Sqlite.Database?> ("db");
171+ return_val_if_fail (db != null, null);
172+ }
173+
174+ public async List<HistoryItem>? query (string sqlcmd, string? filter, int day, int max_items, Cancellable cancellable) {
175+ return_val_if_fail (db != null, null);
176+
177+ Sqlite.Statement stmt;
178+ int result;
179+
180+ result = db.prepare_v2 (sqlcmd, -1, out stmt, null);
181+ if (result != Sqlite.OK) {
182+ critical (_("Failed to select from history: %s"), db.errmsg ());
183+ return null;
184+ }
185+
186+ if (":filter" in sqlcmd) {
187+ string real_filter = "%" + filter.replace (" ", "%") + "%";
188+ stmt.bind_text (stmt.bind_parameter_index (":filter"), real_filter);
189+ }
190+ if (":day" in sqlcmd)
191+ stmt.bind_int64 (stmt.bind_parameter_index (":day"), day);
192+ if (":limit" in sqlcmd)
193+ stmt.bind_int64 (stmt.bind_parameter_index (":limit"), max_items);
194+
195+ result = stmt.step ();
196+ if (!(result == Sqlite.DONE || result == Sqlite.ROW)) {
197+ critical (_("Failed to select from history: %s"), db.errmsg ());
198+ return null;
199+ }
200+
201+ var items = new List<HistoryItem> ();
202+ while (result == Sqlite.ROW) {
203+ int64 type = stmt.column_int64 (0);
204+ int64 date = stmt.column_int64 (1);
205+ switch (type) {
206+ case 1:
207+ string uri = stmt.column_text (2);
208+ string title = stmt.column_text (3);
209+ items.append (new HistoryWebsite (uri, title, date));
210+ break;
211+ case 2:
212+ string uri = stmt.column_text (2);
213+ string title = stmt.column_text (3);
214+ items.append (new HistorySearch (uri, title, date));
215+ break;
216+ default:
217+ warn_if_reached ();
218+ break;
219+ }
220+
221+ uint src = Idle.add (query.callback);
222+ yield;
223+ Source.remove (src);
224+
225+ if (cancellable.is_cancelled ())
226+ return null;
227+
228+ result = stmt.step ();
229+ }
230+
231+ if (cancellable.is_cancelled ())
232+ return null;
233+ return items;
234+ }
235+
236+ public async List<HistoryItem>? list_by_count_with_bookmarks (string? filter, int max_items, Cancellable cancellable) {
237+ unowned string sqlcmd = """
238+ SELECT type, date, uri, title FROM (
239+ SELECT 1 AS type, date, uri, title, count() AS ct FROM history
240+ WHERE uri LIKE :filter OR title LIKE :filter GROUP BY uri
241+ UNION ALL
242+ SELECT 2 AS type, day AS date, replace(uri, '%s', keywords) AS uri,
243+ keywords AS title, count() AS ct FROM search
244+ WHERE uri LIKE :filter OR title LIKE :filter GROUP BY uri
245+ UNION ALL
246+ SELECT 1 AS type, last_visit AS date, uri, title, 50 AS ct FROM bookmarks
247+ WHERE title LIKE :filter OR uri LIKE :filter AND uri !='' AND uri NOT LIKE 'javascript:%'
248+ ) GROUP BY uri ORDER BY ct DESC LIMIT :limit
249+ """;
250+ return yield query (sqlcmd, filter, 0, max_items, cancellable);
251+ }
252+ }
253+}

Subscribers

People subscribed via source and target branches

to all changes: