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
=== modified file 'midori/midori-historycompletion.vala'
--- midori/midori-historycompletion.vala 2013-07-14 16:31:30 +0000
+++ midori/midori-historycompletion.vala 2013-07-24 17:43:25 +0000
@@ -11,22 +11,19 @@
1111
12namespace Midori {12namespace Midori {
13 public class HistoryCompletion : Completion {13 public class HistoryCompletion : Completion {
14 unowned Sqlite.Database db;14 HistoryDatabase? database = null;
1515
16 public HistoryCompletion () {16 public HistoryCompletion () {
17 GLib.Object (description: _("Bookmarks and History"));17 GLib.Object (description: _("Bookmarks and History"));
18 }18 }
1919
20 public override void prepare (GLib.Object app) {20 public override void prepare (GLib.Object app) {
21 GLib.Object history;21 database = new HistoryDatabase (app);
22 app.get ("history", out history);22 return_if_fail (database != null);
23 return_if_fail (history != null);
24 db = history.get_data<Sqlite.Database?> ("db");
25 return_if_fail (db != null);
26 }23 }
2724
28 public override bool can_complete (string text) {25 public override bool can_complete (string text) {
29 return db != null;26 return database != null;
30 }27 }
3128
32 public override bool can_action (string action) {29 public override bool can_action (string action) {
@@ -34,71 +31,26 @@
34 }31 }
3532
36 public override async List<Suggestion>? complete (string text, string? action, Cancellable cancellable) {33 public override async List<Suggestion>? complete (string text, string? action, Cancellable cancellable) {
37 return_val_if_fail (db != null, null);34 return_val_if_fail (database != null, null);
3835
39 Sqlite.Statement stmt;36 List<HistoryItem> items = yield database.list_by_count_with_bookmarks (text, max_items, cancellable);
40 unowned string sqlcmd = """37 if (items == null)
41 SELECT type, uri, title FROM (38 return null;
42 SELECT 1 AS type, uri, title, count() AS ct FROM history
43 WHERE uri LIKE ?1 OR title LIKE ?1 GROUP BY uri
44 UNION ALL
45 SELECT 2 AS type, replace(uri, '%s', keywords) AS uri,
46 keywords AS title, count() AS ct FROM search
47 WHERE uri LIKE ?1 OR title LIKE ?1 GROUP BY uri
48 UNION ALL
49 SELECT 1 AS type, uri, title, 50 AS ct FROM bookmarks
50 WHERE title LIKE ?1 OR uri LIKE ?1 AND uri !='' AND uri NOT LIKE 'javascript:%'
51 ) GROUP BY uri ORDER BY ct DESC LIMIT ?2
52 """;
53 if (db.prepare_v2 (sqlcmd, -1, out stmt, null) != Sqlite.OK) {
54 critical (_("Failed to initialize history: %s"), db.errmsg ());
55 return null;
56 }
57
58 string query = "%" + text.replace (" ", "%") + "%";
59 stmt.bind_text (1, query);
60 stmt.bind_int64 (2, max_items);
61
62 int result = stmt.step ();
63 if (result != Sqlite.ROW) {
64 if (result == Sqlite.ERROR)
65 critical (_("Failed to select from history: %s"), db.errmsg ());
66 return null;
67 }
6839
69 var suggestions = new List<Suggestion> ();40 var suggestions = new List<Suggestion> ();
70 while (result == Sqlite.ROW) {41 foreach (var item in items) {
71 int64 type = stmt.column_int64 (0);42 if (item is Midori.HistoryWebsite) {
72 unowned string uri = stmt.column_text (1);43 var website = item as Midori.HistoryWebsite;
73 unowned string title = stmt.column_text (2);44 suggestions.append (new Suggestion (website.uri, website.title,
74 Gdk.Pixbuf? icon = Midori.Paths.get_icon (uri, null);45 false, null, Midori.Paths.get_icon (website.uri, null)));
75 Suggestion suggestion;46 }
7647 else if (item is Midori.HistorySearch) {
77 switch (type) {48 var search = item as Midori.HistorySearch;
78 case 1: /* history_view */49 suggestions.append (new Suggestion (search.uri, search.title + "\n" + search.uri,
79 suggestion = new Suggestion (uri, title, false, null, icon);50 false, "gray", Midori.Paths.get_icon (search.uri, null)));
80 suggestions.append (suggestion);51 }
81 break;52 else
82 case 2: /* search_view */53 warn_if_reached ();
83 string desc = _("Search for %s").printf (title) + "\n" + uri;
84 /* FIXME: Theming? Win32? */
85 string background = "gray";
86 suggestion = new Suggestion (uri, desc, false, background, icon);
87 suggestions.append (suggestion);
88 break;
89 default:
90 warn_if_reached ();
91 break;
92 }
93
94 uint src = Idle.add (complete.callback);
95 yield;
96 Source.remove (src);
97
98 if (cancellable.is_cancelled ())
99 return null;
100
101 result = stmt.step ();
102 }54 }
10355
104 if (cancellable.is_cancelled ())56 if (cancellable.is_cancelled ())
10557
=== added file 'midori/midori-historydatabase.vala'
--- midori/midori-historydatabase.vala 1970-01-01 00:00:00 +0000
+++ midori/midori-historydatabase.vala 2013-07-24 17:43:25 +0000
@@ -0,0 +1,128 @@
1/*
2 Copyright (C) 2013 Christian Dywan <christian@twotoats.de>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 See the file COPYING for the full license text.
10*/
11
12namespace Midori {
13 public class HistoryWebsite : HistoryItem {
14 public string uri { get; set; }
15 public HistoryWebsite (string uri, string? title, int64 date) {
16 GLib.Object (uri: uri,
17 title: title,
18 date: date);
19 }
20 }
21
22 public class HistorySearch : HistoryItem {
23 public string uri { get; set; }
24 public string keywords { get; set; }
25 public HistorySearch (string uri, string keywords, int64 date) {
26 GLib.Object (uri: uri,
27 keywords: keywords,
28 title: _("Search for %s").printf (keywords),
29 date: date);
30 }
31 }
32
33 public class HistoryItem : GLib.Object {
34 public string? title { get; set; }
35 public int64 date { get; set; }
36 }
37
38 public class HistoryDatabase : GLib.Object {
39 unowned Sqlite.Database db = null;
40
41 public HistoryDatabase (GLib.Object app) {
42 GLib.Object history;
43 app.get ("history", out history);
44 return_val_if_fail (history != null, null);
45 db = history.get_data<Sqlite.Database?> ("db");
46 return_val_if_fail (db != null, null);
47 }
48
49 public async List<HistoryItem>? query (string sqlcmd, string? filter, int day, int max_items, Cancellable cancellable) {
50 return_val_if_fail (db != null, null);
51
52 Sqlite.Statement stmt;
53 int result;
54
55 result = db.prepare_v2 (sqlcmd, -1, out stmt, null);
56 if (result != Sqlite.OK) {
57 critical (_("Failed to select from history: %s"), db.errmsg ());
58 return null;
59 }
60
61 if (":filter" in sqlcmd) {
62 string real_filter = "%" + filter.replace (" ", "%") + "%";
63 stmt.bind_text (stmt.bind_parameter_index (":filter"), real_filter);
64 }
65 if (":day" in sqlcmd)
66 stmt.bind_int64 (stmt.bind_parameter_index (":day"), day);
67 if (":limit" in sqlcmd)
68 stmt.bind_int64 (stmt.bind_parameter_index (":limit"), max_items);
69
70 result = stmt.step ();
71 if (!(result == Sqlite.DONE || result == Sqlite.ROW)) {
72 critical (_("Failed to select from history: %s"), db.errmsg ());
73 return null;
74 }
75
76 var items = new List<HistoryItem> ();
77 while (result == Sqlite.ROW) {
78 int64 type = stmt.column_int64 (0);
79 int64 date = stmt.column_int64 (1);
80 switch (type) {
81 case 1:
82 string uri = stmt.column_text (2);
83 string title = stmt.column_text (3);
84 items.append (new HistoryWebsite (uri, title, date));
85 break;
86 case 2:
87 string uri = stmt.column_text (2);
88 string title = stmt.column_text (3);
89 items.append (new HistorySearch (uri, title, date));
90 break;
91 default:
92 warn_if_reached ();
93 break;
94 }
95
96 uint src = Idle.add (query.callback);
97 yield;
98 Source.remove (src);
99
100 if (cancellable.is_cancelled ())
101 return null;
102
103 result = stmt.step ();
104 }
105
106 if (cancellable.is_cancelled ())
107 return null;
108 return items;
109 }
110
111 public async List<HistoryItem>? list_by_count_with_bookmarks (string? filter, int max_items, Cancellable cancellable) {
112 unowned string sqlcmd = """
113 SELECT type, date, uri, title FROM (
114 SELECT 1 AS type, date, uri, title, count() AS ct FROM history
115 WHERE uri LIKE :filter OR title LIKE :filter GROUP BY uri
116 UNION ALL
117 SELECT 2 AS type, day AS date, replace(uri, '%s', keywords) AS uri,
118 keywords AS title, count() AS ct FROM search
119 WHERE uri LIKE :filter OR title LIKE :filter GROUP BY uri
120 UNION ALL
121 SELECT 1 AS type, last_visit AS date, uri, title, 50 AS ct FROM bookmarks
122 WHERE title LIKE :filter OR uri LIKE :filter AND uri !='' AND uri NOT LIKE 'javascript:%'
123 ) GROUP BY uri ORDER BY ct DESC LIMIT :limit
124 """;
125 return yield query (sqlcmd, filter, 0, max_items, cancellable);
126 }
127 }
128}

Subscribers

People subscribed via source and target branches

to all changes: