Port to Seed to support (only) the WebKit version of Epiphany
[ephy-keyword-searches.git] / bookmark-shortcuts.js
1 // bookmark shortcuts v1.1.1
2 // shortcuts for smart bookmark searches, shared with Deskbar Applet
3
4 // Original extension for the Mozilla-based Epiphany:
5 // (c) 2006-10-17 by Nigel Tao <nigeltao@gnome.org>, GPL licensed.
6 // Port to Seed and GIO, and add an entry to the Edit menu:
7 // Copyright © 2009 Iain Nicol <iainn@src.gnome.org>
8
9 // This program is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 2 of the License, or
12 // (at your option) any later version.
13
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18
19 // You should have received a copy of the GNU General Public License
20 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21
22 Gio = imports.gi.Gio;
23 Gdk = imports.gi.Gdk;
24
25 var shortcut_to_bookmark_map = {};
26 var shortcuts_file_name = GLib.get_user_config_dir() +
27 "/deskbar-applet/search-bookmarks-shortcuts.txt";
28 var shortcuts_file_monitor;
29
30 var get_map_from_file = function (file) {
31 var map = {};
32
33 try {
34 var data_in_stream = new Gio.DataInputStream.c_new(file.read());
35
36 while ((line = data_in_stream.read_line(null)) !== null) {
37 line = line.trim();
38
39 var sep_location = line.search(/ |\t/);
40 if (sep_location > 0) {
41 var url = line.substring(0, sep_location);
42 var shortcut = line.substring(sep_location + 1).trim();
43
44 map[shortcut] = url;
45 }
46 }
47 } catch (e) {
48 // Maybe the file doesn't exist, etc. Ignore.
49 printerr(e);
50 }
51
52 return map;
53 };
54
55 var shortcuts_changed_cb = function (file_monitor, file, other_file,
56 event_type, user_data) {
57 if (event_type === Gio.FileMonitorEvent.CHANGES_DONE_HINT) {
58 shortcut_to_bookmark_map = get_map_from_file(file);
59 }
60 };
61
62 var edit_bookmark_shortcuts_cb = function (action, window) {
63 // Comment out the code to spawn programs on the correct screen
64 // because as of the end of 2009, missing annotations in GDK will
65 // cause a crash.
66 //
67 var screen = null; // window.get_screen();
68 var deskbar_extn = Gio.file_new_for_path(
69 "/usr/lib/deskbar-applet/modules-2.20-compatible/epiphany.py");
70
71 if (deskbar_extn.query_exists()) {
72 // launch Deskbar's editor
73 var python_commands =
74 "import sys\n" +
75 "sys.path.insert(0," +
76 " '/usr/lib/deskbar-applet/modules-2.20-compatible')\n" +
77 "import epiphany\n" +
78 "e = epiphany.EpiphanySearchHandler()\n" +
79 "e.initialize()\n" +
80 "e.show_config(None)\n";
81
82 // Gdk.spawn_on_screen(screen, null, ["python", "-c", python_commands],
83 // null, GLib.SpawnFlags.SEARCH_PATH, null, null,
84 // null);
85 GLib.spawn_async(null, ["python", "-c", python_commands],
86 null, GLib.SpawnFlags.SEARCH_PATH, null, null,
87 null);
88 } else {
89 var dialog = new Gtk.MessageDialog({
90 text: "The file format is a series of lines, each of the form:\n" +
91 "\n" +
92 "url shortcut\n" +
93 "\n" +
94 "Each “url” should contain “%s” in the position the search " +
95 "terms should go."});
96 dialog.add_button(Gtk.STOCK_CANCEL,
97 Gtk.ResponseType.CANCEL);
98 dialog.add_button("Open Editor", Gtk.ResponseType.OK).grab_focus();
99
100 var response = dialog.run();
101 dialog.destroy();
102
103 if (response !== Gtk.ResponseType.OK) {
104 return;
105 }
106
107 var shortcuts_file = Gio.file_new_for_path(shortcuts_file_name);
108 try {
109 shortcuts_file.create();
110 } catch (e) {
111 }
112 Gtk.show_uri(screen, shortcuts_file.get_uri(), Gdk.CURRENT_TIME);
113 }
114 };
115
116 var resolve_address_cb = function (bookmarks, address, content) {
117 address = address.trim();
118 var n = address.indexOf(" ");
119 var shortcut;
120 var args;
121
122 if (n === -1) {
123 shortcut = address;
124 args = "";
125 } else {
126 shortcut = address.substring(0, n);
127 args = address.substring(n+1);
128 }
129
130 bookmark = shortcut_to_bookmark_map[shortcut];
131 if (bookmark === undefined) {
132 return null;
133 } else {
134 return bookmark.replace("%s", args);
135 }
136 };
137
138 var initialize_extension = function () {
139 bookmarks = Epiphany.EphyShell.get_default().get_bookmarks();
140 bookmarks._bookmark_shortcuts_signal = bookmarks.signal.
141 resolve_address.connect(resolve_address_cb);
142
143 var file = Gio.file_new_for_path(shortcuts_file_name);
144 try {
145 shortcuts_file_monitor = file.monitor();
146 shortcuts_file_monitor.signal.changed.connect(shortcuts_changed_cb);
147 shortcut_to_bookmark_map = get_map_from_file(file);
148 } catch (e) {
149 }
150 };
151
152 var finalize_extension = function () {
153 bookmarks = Epiphany.EphyShell.get_default().get_bookmarks();
154 bookmarks.signal.disconnect(bookmarks._bookmark_shortcuts_signal);
155 delete bookmarks._bookmark_shortcuts_signal;
156 shortcuts_file_monitor = null;
157 };
158
159 var attached_window_count = 0;
160
161 var attach_window = function (window) {
162 // No race condition below because this extension is always called
163 // in the one GUI thread. Hopefully.
164 if (attached_window_count === 0) {
165 initialize_extension();
166 }
167 attached_window_count++;
168
169 // Add Edit -> Bookmark Shortcuts to this window's menu.
170
171 // Object to hold onto the Edit menu entry, etc., for the window's
172 // lifetime.
173 window._bookmark_shortcuts = {};
174 var wbs = window._bookmark_shortcuts;
175
176 wbs.action = new Gtk.Action({
177 name: "EditBookmarkShortcuts",
178 label: "_Bookmark Shortcuts",
179 tooltip: "Configure shortcuts for your bookmark searches",
180 stock_id: null});
181 wbs.sig_id = wbs.action.signal.activate.connect(edit_bookmark_shortcuts_cb,
182 window);
183 wbs.action_group = new Gtk.ActionGroup({
184 name: "EditBookmarkShortcutsActionGroup"});
185 wbs.action_group.add_action(wbs.action);
186
187 // Unfortunately the following line can trigger:
188 // Gtk-CRITICAL **: gtk_container_foreach: assertion
189 // `GTK_IS_CONTAINER (container)' failed
190 // when we close the window. This isn't our fault, though.
191 wbs.manager = window.get_ui_manager();
192
193 wbs.manager.insert_action_group(wbs.action_group, 0);
194 wbs.merge_id = wbs.manager.new_merge_id();
195 wbs.manager.add_ui(wbs.merge_id, "/menubar/EditMenu/EditPrefsMenu",
196 "EditBookmarkShortcutsMenu", "EditBookmarkShortcuts",
197 Gtk.UIManagerItemType.MENUITEM, true);
198 };
199
200 var detach_window = function (window) {
201 // Remove our Edit menu entry.
202 // Is this necessary? Well, it doesn't hurt /too/ much, at least.
203 var wbs = window._bookmark_shortcuts;
204
205 wbs.manager.remove_ui(wbs.merge_id);
206 wbs.manager.remove_action_group(wbs.action_group);
207 wbs.action_group.remove_action(wbs.action);
208 wbs.action.signal.disconnect(wbs.sig_id);
209 delete window._bookmark_shortcuts;
210
211 // Cleanup the rest of the extension if necessary.
212 attached_window_count--;
213 if (attached_window_count === 0) {
214 finalize_extension();
215 }
216 };
217
218 extension = {
219 attach_window: attach_window,
220 detach_window: detach_window
221 };