1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
/*
Copyright (C) 2012-2018 Christian Dywan <christian@twotoasts.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
See the file COPYING for the full license text.
*/
namespace Midori {
public class SuggestionItem : DatabaseItem {
public string? search { get; protected set; }
SuggestionItem (string uri, string? title) {
base (uri, title, 0);
}
public SuggestionItem.for_input (string uri, string? title) {
base (uri, title, 0);
this.search = uri;
}
}
public interface CompletionActivatable : Peas.ExtensionBase {
public abstract Completion completion { owned get; set; }
public abstract void activate ();
}
public class Completion : Object, ListModel {
List<ListModel> models = new List<ListModel> ();
public bool incognito { get; construct set; default = false; }
public string? key { get; set; default = null; }
construct {
var model = new ListStore (typeof (DatabaseItem));
var settings = CoreSettings.get_default ();
model.append (new SuggestionItem.for_input (settings.location_entry_search, _("_Search the Web")));
models.append (model);
try {
add (HistoryDatabase.get_default (incognito));
} catch (DatabaseError error) {
debug ("Failed to initialize completion model: %s", error.message);
}
var extensions = Plugins.get_default ().plug<CompletionActivatable> ("completion", this);
extensions.extension_added.connect ((info, extension) => ((CompletionActivatable)extension).activate ());
extensions.foreach ((extensions, info, extension) => { extensions.extension_added (info, extension); });
}
public Completion (bool incognito) {
Object (incognito: incognito);
}
/*
* Add a model to complete from. Items need to be based on DatabaseItem
* and filtered by key if set.
*/
public void add (ListModel model) {
if (model is Database) {
bind_property ("key", model, "key");
}
model.items_changed.connect (model_changed);
models.append (model);
}
void model_changed (ListModel model, uint position, uint removed, uint added) {
uint index = 0;
foreach (var other in models) {
if (model == other) {
items_changed (position + index, removed, added);
break;
}
index += other.get_n_items ();
}
}
public Type get_item_type () {
return typeof (DatabaseItem);
}
public Object? get_item (uint position) {
uint index = 0;
foreach (var model in models) {
uint count = model.get_n_items ();
if (position < index + count) {
return model.get_item (position - index);
}
index += count;
}
return null;
}
public uint get_n_items () {
uint count = 0;
foreach (var model in models) {
count += model.get_n_items ();
}
return count;
}
}
}
|