Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Paweł Forysiuk | ||||
Approved revision: | 6587 | ||||
Merged at revision: | 6569 | ||||
Proposed branch: | lp:~midori/midori/openWith | ||||
Merge into: | lp:midori | ||||
Diff against target: |
1725 lines (+904/-475) 19 files modified
extensions/addons.c (+5/-4) extensions/open-with.vala (+802/-0) extensions/transfers.vala (+2/-7) katze/katze-utils.c (+1/-211) katze/katze.vapi (+7/-0) katze/midori-uri.vala (+17/-0) midori/midori-app.c (+1/-1) midori/midori-browser.c (+5/-44) midori/midori-dialog.vala (+14/-0) midori/midori-download.vala (+7/-4) midori/midori-extension.c (+2/-0) midori/midori-frontend.c (+2/-1) midori/midori-preferences.c (+0/-12) midori/midori-tab.vala (+2/-0) midori/midori-view.c (+13/-31) midori/midori.vapi (+1/-0) midori/sokoke.c (+22/-143) midori/sokoke.h (+0/-17) po/POTFILES.in (+1/-0) |
||||
To merge this branch: | bzr merge lp:~midori/midori/openWith | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Paweł Forysiuk | Approve | ||
Review via email: mp+207737@code.launchpad.net |
Commit message
Implement Open With extension dealing with file types
Description of the change
To post a comment you must log in.
lp:~midori/midori/openWith
updated
- 6583. By Paweł Forysiuk
-
Don't bother fetching hicon if path to executable is null, update code style a bit
- 6584. By Paweł Forysiuk
-
Merge lp:midori
- 6585. By Paweł Forysiuk
-
Add some sanity checks when feching hIcon
- 6586. By Cris Dywan
-
Implement Customize… menu item in Chooser
- 6587. By Cris Dywan
-
Add tooltip about customization to treeview
Revision history for this message
Paweł Forysiuk (tuxator) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'extensions/addons.c' |
2 | --- extensions/addons.c 2013-06-21 23:18:01 +0000 |
3 | +++ extensions/addons.c 2014-02-25 19:27:20 +0000 |
4 | @@ -485,8 +485,8 @@ |
5 | else |
6 | { |
7 | gchar* element_uri = g_filename_to_uri (element->fullpath, NULL, NULL); |
8 | - sokoke_show_uri (NULL, element_uri, |
9 | - gtk_get_current_event_time (), NULL); |
10 | + gboolean handled = FALSE; |
11 | + g_signal_emit_by_name (midori_browser_get_current_tab (browser), "open-uri", element_uri, &handled); |
12 | g_free (element_uri); |
13 | } |
14 | |
15 | @@ -522,8 +522,9 @@ |
16 | folder_uri = g_filename_to_uri (folder, NULL, NULL); |
17 | g_free (folder); |
18 | |
19 | - sokoke_show_uri (gtk_widget_get_screen (GTK_WIDGET (addons->treeview)), |
20 | - folder_uri, gtk_get_current_event_time (), NULL); |
21 | + MidoriBrowser* browser = midori_browser_get_for_widget (addons->treeview); |
22 | + gboolean handled = FALSE; |
23 | + g_signal_emit_by_name (midori_browser_get_current_tab (browser), "open-uri", folder_uri, &handled); |
24 | g_free (folder_uri); |
25 | } |
26 | |
27 | |
28 | === added file 'extensions/open-with.vala' |
29 | --- extensions/open-with.vala 1970-01-01 00:00:00 +0000 |
30 | +++ extensions/open-with.vala 2014-02-25 19:27:20 +0000 |
31 | @@ -0,0 +1,802 @@ |
32 | +/* |
33 | + Copyright (C) 2014 Christian Dywan <christian@twotoasts.de> |
34 | + |
35 | + This library is free software; you can redistribute it and/or |
36 | + modify it under the terms of the GNU Lesser General Public |
37 | + License as published by the Free Software Foundation; either |
38 | + version 2.1 of the License, or (at your option) any later version. |
39 | + |
40 | + See the file COPYING for the full license text. |
41 | +*/ |
42 | + |
43 | +#if HAVE_WIN32 |
44 | +namespace Sokoke { |
45 | + extern static Gdk.Pixbuf get_gdk_pixbuf_from_win32_executable (string path); |
46 | +} |
47 | +#endif |
48 | + |
49 | +namespace ExternalApplications { |
50 | + bool open_app_info (AppInfo app_info, string uri, string content_type) { |
51 | + Midori.URI.recursive_fork_protection (uri, true); |
52 | + |
53 | + try { |
54 | + var uris = new List<File> (); |
55 | + uris.append (File.new_for_uri (uri)); |
56 | + app_info.launch (uris, null); |
57 | + new Associations ().remember (content_type, app_info); |
58 | + return true; |
59 | + } catch (Error error) { |
60 | + warning ("Failed to open \"%s\": %s", uri, error.message); |
61 | + return false; |
62 | + } |
63 | + } |
64 | + |
65 | + class Associations : Object { |
66 | +#if HAVE_WIN32 |
67 | + string config_dir; |
68 | + string filename; |
69 | + KeyFile keyfile; |
70 | + |
71 | + public Associations () { |
72 | + config_dir = Midori.Paths.get_extension_config_dir ("open-with"); |
73 | + filename = Path.build_filename (config_dir, "config"); |
74 | + keyfile = new KeyFile (); |
75 | + |
76 | + try { |
77 | + keyfile.load_from_file (filename, KeyFileFlags.NONE); |
78 | + } catch (FileError.NOENT exist_error) { |
79 | + /* It's no error if no config file exists */ |
80 | + } catch (Error error) { |
81 | + warning ("Failed to load associations: %s", error.message); |
82 | + } |
83 | + } |
84 | + |
85 | + public bool open (string content_type, string uri) { |
86 | + Midori.URI.recursive_fork_protection (uri, true); |
87 | + try { |
88 | + string commandline = keyfile.get_string ("mimes", content_type); |
89 | + if ("%u" in commandline) |
90 | + commandline = commandline.replace ("%u", Shell.quote (uri)); |
91 | + else if ("%F" in commandline) |
92 | + commandline = commandline.replace ("%F", Shell.quote (Filename.from_uri (uri))); |
93 | + return Process.spawn_command_line_async (commandline); |
94 | + } catch (KeyFileError error) { |
95 | + /* Not remembered before */ |
96 | + return false; |
97 | + } catch (Error error) { |
98 | + warning ("Failed to open \"%s\": %s", uri, error.message); |
99 | + return false; |
100 | + } |
101 | + } |
102 | + |
103 | + public void remember (string content_type, AppInfo app_info) throws Error { |
104 | + keyfile.set_string ("mimes", content_type, get_commandline (app_info)); |
105 | + FileUtils.set_contents (filename, keyfile.to_data ()); |
106 | + } |
107 | + |
108 | + public void custom (string content_type, string commandline, string name, string uri) { |
109 | + keyfile.set_string ("mimes", content_type, commandline); |
110 | + try { |
111 | + FileUtils.set_contents (filename, keyfile.to_data ()); |
112 | + } catch (Error error) { |
113 | + warning ("Failed to add remember custom command line for \"%s\": %s", uri, error.message); |
114 | + } |
115 | + open (content_type, uri); |
116 | + } |
117 | + } |
118 | +#else |
119 | + public Associations () { |
120 | + } |
121 | + |
122 | + public bool open (string content_type, string uri) { |
123 | + var app_info = AppInfo.get_default_for_type (content_type, false); |
124 | + if (app_info == null) |
125 | + return false; |
126 | + return open_app_info (app_info, uri, content_type); |
127 | + } |
128 | + |
129 | + public void remember (string content_type, AppInfo app_info) throws Error { |
130 | + app_info.set_as_last_used_for_type (content_type); |
131 | + app_info.set_as_default_for_type (content_type); |
132 | + } |
133 | + |
134 | + public void custom (string content_type, string commandline, string name, string uri) { |
135 | + try { |
136 | + var app_info = AppInfo.create_from_commandline (commandline, name, |
137 | + "%u" in commandline ? AppInfoCreateFlags.SUPPORTS_URIS : AppInfoCreateFlags.NONE); |
138 | + open_app_info (app_info, uri, content_type); |
139 | + } catch (Error error) { |
140 | + warning ("Failed to add custom command line for \"%s\": %s", uri, error.message); |
141 | + } |
142 | + } |
143 | + } |
144 | +#endif |
145 | + |
146 | + static string get_commandline (AppInfo app_info) { |
147 | + return app_info.get_commandline () ?? app_info.get_executable (); |
148 | + } |
149 | + |
150 | + static string describe_app_info (AppInfo app_info) { |
151 | + string name = app_info.get_display_name () ?? (Path.get_basename (app_info.get_executable ())); |
152 | + string desc = app_info.get_description () ?? get_commandline (app_info); |
153 | + return Markup.printf_escaped ("<b>%s</b>\n%s", name, desc); |
154 | + } |
155 | + |
156 | + static Icon? app_info_get_icon (AppInfo app_info) { |
157 | + #if HAVE_WIN32 |
158 | + return Sokoke.get_gdk_pixbuf_from_win32_executable (app_info.get_executable ()); |
159 | + #else |
160 | + return app_info.get_icon (); |
161 | + #endif |
162 | + } |
163 | + |
164 | + class CustomizerDialog : Gtk.Dialog { |
165 | + public Gtk.Entry name_entry; |
166 | + public Gtk.Entry commandline_entry; |
167 | + |
168 | + public CustomizerDialog (AppInfo app_info, Gtk.Widget widget) { |
169 | + var browser = Midori.Browser.get_for_widget (widget); |
170 | + transient_for = browser; |
171 | + |
172 | + title = _("Custom…"); |
173 | +#if !HAVE_GTK3 |
174 | + has_separator = false; |
175 | +#endif |
176 | + destroy_with_parent = true; |
177 | + set_icon_name (Gtk.STOCK_OPEN); |
178 | + resizable = false; |
179 | + add_buttons (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, |
180 | + Gtk.STOCK_SAVE, Gtk.ResponseType.ACCEPT); |
181 | + |
182 | + var vbox = new Gtk.VBox (false, 8); |
183 | + vbox.border_width = 8; |
184 | + (get_content_area () as Gtk.Box).pack_start (vbox, true, true, 8); |
185 | + |
186 | + var sizegroup = new Gtk.SizeGroup (Gtk.SizeGroupMode.HORIZONTAL); |
187 | + var label = new Gtk.Label (_("Name:")); |
188 | + sizegroup.add_widget (label); |
189 | + label.set_alignment (0.0f, 0.5f); |
190 | + vbox.pack_start (label, false, false, 0); |
191 | + name_entry = new Gtk.Entry (); |
192 | + name_entry.activates_default = true; |
193 | + sizegroup.add_widget (name_entry); |
194 | + vbox.pack_start (name_entry, true, true, 0); |
195 | + |
196 | + label = new Gtk.Label (_("Command Line:")); |
197 | + sizegroup.add_widget (label); |
198 | + label.set_alignment (0.0f, 0.5f); |
199 | + vbox.pack_start (label, false, false, 0); |
200 | + commandline_entry = new Gtk.Entry (); |
201 | + commandline_entry.activates_default = true; |
202 | + sizegroup.add_widget (name_entry); |
203 | + sizegroup.add_widget (commandline_entry); |
204 | + vbox.pack_start (commandline_entry, true, true, 0); |
205 | + get_content_area ().show_all (); |
206 | + set_default_response (Gtk.ResponseType.ACCEPT); |
207 | + |
208 | + name_entry.text = app_info.get_name (); |
209 | + commandline_entry.text = get_commandline (app_info); |
210 | + } |
211 | + } |
212 | + |
213 | + private class Chooser : Gtk.VBox { |
214 | + Gtk.ListStore store = new Gtk.ListStore (1, typeof (AppInfo)); |
215 | + Gtk.TreeView treeview; |
216 | + List<AppInfo> available; |
217 | + string content_type; |
218 | + string uri; |
219 | + |
220 | + public Chooser (string uri, string content_type) { |
221 | + this.content_type = content_type; |
222 | + this.uri = uri; |
223 | + |
224 | + Gtk.TreeViewColumn column; |
225 | + |
226 | + treeview = new Gtk.TreeView.with_model (store); |
227 | + treeview.headers_visible = false; |
228 | + |
229 | + store.set_sort_column_id (0, Gtk.SortType.ASCENDING); |
230 | + store.set_sort_func (0, tree_sort_func); |
231 | + |
232 | + column = new Gtk.TreeViewColumn (); |
233 | + Gtk.CellRendererPixbuf renderer_icon = new Gtk.CellRendererPixbuf (); |
234 | + column.pack_start (renderer_icon, false); |
235 | + column.set_cell_data_func (renderer_icon, on_render_icon); |
236 | + treeview.append_column (column); |
237 | + |
238 | + column = new Gtk.TreeViewColumn (); |
239 | + column.set_sizing (Gtk.TreeViewColumnSizing.AUTOSIZE); |
240 | + Gtk.CellRendererText renderer_text = new Gtk.CellRendererText (); |
241 | + column.pack_start (renderer_text, true); |
242 | + column.set_expand (true); |
243 | + column.set_cell_data_func (renderer_text, on_render_text); |
244 | + treeview.append_column (column); |
245 | + |
246 | + treeview.row_activated.connect (row_activated); |
247 | + treeview.show (); |
248 | + var scrolled = new Gtk.ScrolledWindow (null, null); |
249 | + scrolled.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC); |
250 | + scrolled.add (treeview); |
251 | + pack_start (scrolled); |
252 | + int height; |
253 | + treeview.create_pango_layout ("a\nb").get_pixel_size (null, out height); |
254 | + scrolled.set_size_request (-1, height * 5); |
255 | + treeview.button_release_event.connect (button_released); |
256 | + treeview.tooltip_text = _("Right-click a suggestion to customize it"); |
257 | + |
258 | + available = new List<AppInfo> (); |
259 | + foreach (var app_info in AppInfo.get_all_for_type (content_type)) |
260 | + launcher_added (app_info, uri); |
261 | + |
262 | + if (store.iter_n_children (null) < 1) { |
263 | + foreach (var app_info in AppInfo.get_all ()) |
264 | + launcher_added (app_info, uri); |
265 | + } |
266 | + } |
267 | + |
268 | + bool button_released (Gdk.EventButton event) { |
269 | + if (event.button == 3) |
270 | + return show_popup_menu (event); |
271 | + return false; |
272 | + } |
273 | + |
274 | + bool show_popup_menu (Gdk.EventButton? event) { |
275 | + Gtk.TreeIter iter; |
276 | + if (treeview.get_selection ().get_selected (null, out iter)) { |
277 | + AppInfo app_info; |
278 | + store.get (iter, 0, out app_info); |
279 | + |
280 | + var menu = new Gtk.Menu (); |
281 | + var menuitem = new Gtk.ImageMenuItem.with_mnemonic (_("Custom…")); |
282 | + menuitem.image = new Gtk.Image.from_stock (Gtk.STOCK_EDIT, Gtk.IconSize.MENU); |
283 | + menuitem.activate.connect (() => { |
284 | + customize_app_info (app_info, content_type, uri); |
285 | + }); |
286 | + menu.append (menuitem); |
287 | + menu.show_all (); |
288 | + Katze.widget_popup (treeview, menu, null, Katze.MenuPos.CURSOR); |
289 | + |
290 | + return true; |
291 | + } |
292 | + return false; |
293 | + } |
294 | + |
295 | + void customize_app_info (AppInfo app_info, string content_type, string uri) { |
296 | + var dialog = new CustomizerDialog (app_info, this); |
297 | + bool accept = dialog.run () == Gtk.ResponseType.ACCEPT; |
298 | + if (accept) { |
299 | + string name = dialog.name_entry.text; |
300 | + string commandline = dialog.commandline_entry.text; |
301 | + new Associations ().custom (content_type, commandline, name, uri); |
302 | + customized (app_info, content_type, uri); |
303 | + } |
304 | + dialog.destroy (); |
305 | + } |
306 | + |
307 | + public List<AppInfo> get_available () { |
308 | + return available.copy (); |
309 | + } |
310 | + |
311 | + public AppInfo get_app_info () { |
312 | + Gtk.TreeIter iter; |
313 | + if (treeview.get_selection ().get_selected (null, out iter)) { |
314 | + AppInfo app_info; |
315 | + store.get (iter, 0, out app_info); |
316 | + return app_info; |
317 | + } |
318 | + assert_not_reached (); |
319 | + } |
320 | + |
321 | + void on_render_icon (Gtk.CellLayout column, Gtk.CellRenderer renderer, |
322 | + Gtk.TreeModel model, Gtk.TreeIter iter) { |
323 | + |
324 | + AppInfo app_info; |
325 | + model.get (iter, 0, out app_info); |
326 | + |
327 | + renderer.set ("gicon", app_info_get_icon (app_info), |
328 | + "stock-size", Gtk.IconSize.DIALOG, |
329 | + "xpad", 4); |
330 | + } |
331 | + |
332 | + void on_render_text (Gtk.CellLayout column, Gtk.CellRenderer renderer, |
333 | + Gtk.TreeModel model, Gtk.TreeIter iter) { |
334 | + |
335 | + AppInfo app_info; |
336 | + model.get (iter, 0, out app_info); |
337 | + renderer.set ("markup", describe_app_info (app_info), |
338 | + "ellipsize", Pango.EllipsizeMode.END); |
339 | + } |
340 | + |
341 | + void launcher_added (AppInfo app_info, string uri) { |
342 | + if (!app_info.should_show ()) |
343 | + return; |
344 | + |
345 | + Gtk.TreeIter iter; |
346 | + store.append (out iter); |
347 | + store.set (iter, 0, app_info); |
348 | + |
349 | + available.append (app_info); |
350 | + } |
351 | + |
352 | + int tree_sort_func (Gtk.TreeModel model, Gtk.TreeIter a, Gtk.TreeIter b) { |
353 | + AppInfo app_info1, app_info2; |
354 | + model.get (a, 0, out app_info1); |
355 | + model.get (b, 0, out app_info2); |
356 | + return strcmp (app_info1.get_display_name (), app_info2.get_display_name ()); |
357 | + } |
358 | + |
359 | + void row_activated (Gtk.TreePath path, Gtk.TreeViewColumn column) { |
360 | + Gtk.TreeIter iter; |
361 | + if (store.get_iter (out iter, path)) { |
362 | + AppInfo app_info; |
363 | + store.get (iter, 0, out app_info); |
364 | + selected (app_info); |
365 | + } |
366 | + } |
367 | + |
368 | + public signal void selected (AppInfo app_info); |
369 | + public signal void customized (AppInfo app_info, string content_type, string uri); |
370 | + } |
371 | + |
372 | + class ChooserDialog : Gtk.Dialog { |
373 | + public Chooser chooser { get; private set; } |
374 | + |
375 | + public ChooserDialog (string uri, string content_type, Gtk.Widget widget) { |
376 | + string filename; |
377 | + if (uri.has_prefix ("file://")) |
378 | + filename = Midori.Download.get_basename_for_display (uri); |
379 | + else |
380 | + filename = uri; |
381 | + |
382 | + var browser = Midori.Browser.get_for_widget (widget); |
383 | + transient_for = browser; |
384 | + |
385 | + title = _("Choose application"); |
386 | +#if !HAVE_GTK3 |
387 | + has_separator = false; |
388 | +#endif |
389 | + destroy_with_parent = true; |
390 | + set_icon_name (Gtk.STOCK_OPEN); |
391 | + resizable = false; |
392 | + add_buttons (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, |
393 | + Gtk.STOCK_OPEN, Gtk.ResponseType.ACCEPT); |
394 | + |
395 | + var vbox = new Gtk.VBox (false, 8); |
396 | + vbox.border_width = 8; |
397 | + (get_content_area () as Gtk.Box).pack_start (vbox, true, true, 8); |
398 | + var label = new Gtk.Label (_("Select an application to open \"%s\"".printf (filename))); |
399 | + label.ellipsize = Pango.EllipsizeMode.MIDDLE; |
400 | + vbox.pack_start (label, false, false, 0); |
401 | + if (uri == "") |
402 | + label.no_show_all = true; |
403 | + chooser = new Chooser (uri, content_type); |
404 | + vbox.pack_start (chooser, true, true, 0); |
405 | + |
406 | + get_content_area ().show_all (); |
407 | + set_default_response (Gtk.ResponseType.ACCEPT); |
408 | + chooser.selected.connect ((app_info) => { |
409 | + response (Gtk.ResponseType.ACCEPT); |
410 | + }); |
411 | + chooser.customized.connect ((app_info, content_type, uri) => { |
412 | + response (Gtk.ResponseType.CANCEL); |
413 | + }); |
414 | + } |
415 | + |
416 | + public AppInfo? open_with () { |
417 | + show (); |
418 | + bool accept = run () == Gtk.ResponseType.ACCEPT; |
419 | + hide (); |
420 | + |
421 | + if (!accept) |
422 | + return null; |
423 | + return chooser.get_app_info (); |
424 | + } |
425 | + } |
426 | + |
427 | + class ChooserButton : Gtk.Button { |
428 | + public AppInfo? app_info { get; set; } |
429 | + public string? commandline { get; set; } |
430 | + ChooserDialog dialog; |
431 | + Gtk.Label app_name; |
432 | + Gtk.Image icon; |
433 | + |
434 | + public ChooserButton (string mime_type, string? commandline) { |
435 | + string content_type = ContentType.from_mime_type (mime_type); |
436 | + dialog = new ChooserDialog ("", content_type, this); |
437 | + app_info = null; |
438 | + foreach (var candidate in dialog.chooser.get_available ()) { |
439 | + if (get_commandline (candidate) == commandline) |
440 | + app_info = candidate; |
441 | + } |
442 | + |
443 | + var hbox = new Gtk.HBox (false, 4); |
444 | + icon = new Gtk.Image (); |
445 | + hbox.pack_start (icon, false, false, 0); |
446 | + app_name = new Gtk.Label (null); |
447 | + app_name.use_markup = true; |
448 | + app_name.ellipsize = Pango.EllipsizeMode.END; |
449 | + hbox.pack_start (app_name, true, true, 0); |
450 | + add (hbox); |
451 | + show_all (); |
452 | + update_label (); |
453 | + |
454 | + clicked.connect (() => { |
455 | + app_info = dialog.open_with (); |
456 | + string new_commandline = app_info != null ? get_commandline (app_info) : null; |
457 | + commandline = new_commandline; |
458 | + selected (new_commandline); |
459 | + update_label (); |
460 | + }); |
461 | + } |
462 | + |
463 | + void update_label () { |
464 | + app_name.label = app_info != null ? describe_app_info (app_info).replace ("\n", " ") : _("None"); |
465 | + icon.set_from_gicon (app_info != null ? app_info_get_icon (app_info) : null, Gtk.IconSize.BUTTON); |
466 | + } |
467 | + |
468 | + public signal void selected (string? commandline); |
469 | + } |
470 | + |
471 | + class Types : Gtk.VBox { |
472 | + public Gtk.ListStore store = new Gtk.ListStore (2, typeof (string), typeof (AppInfo)); |
473 | + Gtk.TreeView treeview; |
474 | + |
475 | + public Types () { |
476 | + Gtk.TreeViewColumn column; |
477 | + |
478 | + treeview = new Gtk.TreeView.with_model (store); |
479 | + treeview.headers_visible = false; |
480 | + |
481 | + store.set_sort_column_id (0, Gtk.SortType.ASCENDING); |
482 | + store.set_sort_func (0, tree_sort_func); |
483 | + |
484 | + column = new Gtk.TreeViewColumn (); |
485 | + column.set_sizing (Gtk.TreeViewColumnSizing.AUTOSIZE); |
486 | + Gtk.CellRendererPixbuf renderer_type_icon = new Gtk.CellRendererPixbuf (); |
487 | + column.pack_start (renderer_type_icon, false); |
488 | + column.set_cell_data_func (renderer_type_icon, on_render_type_icon); |
489 | + treeview.append_column (column); |
490 | + |
491 | + column = new Gtk.TreeViewColumn (); |
492 | + column.set_sizing (Gtk.TreeViewColumnSizing.AUTOSIZE); |
493 | + Gtk.CellRendererText renderer_type_text = new Gtk.CellRendererText (); |
494 | + column.pack_start (renderer_type_text, true); |
495 | + column.set_cell_data_func (renderer_type_text, on_render_type_text); |
496 | + treeview.append_column (column); |
497 | + |
498 | + column = new Gtk.TreeViewColumn (); |
499 | + column.set_sizing (Gtk.TreeViewColumnSizing.AUTOSIZE); |
500 | + Gtk.CellRendererPixbuf renderer_icon = new Gtk.CellRendererPixbuf (); |
501 | + column.pack_start (renderer_icon, false); |
502 | + column.set_cell_data_func (renderer_icon, on_render_icon); |
503 | + treeview.append_column (column); |
504 | + |
505 | + column = new Gtk.TreeViewColumn (); |
506 | + column.set_sizing (Gtk.TreeViewColumnSizing.AUTOSIZE); |
507 | + Gtk.CellRendererText renderer_text = new Gtk.CellRendererText (); |
508 | + column.pack_start (renderer_text, true); |
509 | + column.set_expand (true); |
510 | + column.set_cell_data_func (renderer_text, on_render_text); |
511 | + treeview.append_column (column); |
512 | + |
513 | + treeview.row_activated.connect (row_activated); |
514 | + treeview.show (); |
515 | + var scrolled = new Gtk.ScrolledWindow (null, null); |
516 | + scrolled.set_policy (Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC); |
517 | + scrolled.add (treeview); |
518 | + pack_start (scrolled); |
519 | + int height; |
520 | + treeview.create_pango_layout ("a\nb").get_pixel_size (null, out height); |
521 | + scrolled.set_size_request (-1, height * 5); |
522 | + |
523 | + foreach (string content_type in ContentType.list_registered ()) |
524 | + launcher_added (content_type); |
525 | + foreach (string scheme in Vfs.get_default ().get_supported_uri_schemes ()) |
526 | + launcher_added ("x-scheme-handler/" + scheme); |
527 | + |
528 | + treeview.size_allocate.connect_after ((allocation) => { |
529 | + treeview.columns_autosize (); |
530 | + }); |
531 | + } |
532 | + |
533 | + void on_render_type_icon (Gtk.CellLayout column, Gtk.CellRenderer renderer, |
534 | + Gtk.TreeModel model, Gtk.TreeIter iter) { |
535 | + |
536 | + string content_type; |
537 | + store.get (iter, 0, out content_type); |
538 | + |
539 | + renderer.set ("gicon", ContentType.get_icon (content_type), |
540 | + "stock-size", Gtk.IconSize.BUTTON, |
541 | + "xpad", 4); |
542 | + } |
543 | + |
544 | + void on_render_type_text (Gtk.CellLayout column, Gtk.CellRenderer renderer, |
545 | + Gtk.TreeModel model, Gtk.TreeIter iter) { |
546 | + |
547 | + string content_type; |
548 | + AppInfo app_info; |
549 | + store.get (iter, 0, out content_type, 1, out app_info); |
550 | + |
551 | + string desc, mime_type; |
552 | + if (content_type.has_prefix ("x-scheme-handler/")) { |
553 | + desc = content_type.split ("/")[1] + "://"; |
554 | + mime_type = ""; |
555 | + } else { |
556 | + desc = ContentType.get_description (content_type); |
557 | + mime_type = ContentType.get_mime_type (content_type); |
558 | + } |
559 | + |
560 | + renderer.set ("markup", |
561 | + Markup.printf_escaped ("<b>%s</b>\n%s", |
562 | + desc, mime_type), |
563 | +#if HAVE_GTK3 |
564 | + "max-width-chars", 30, |
565 | +#else |
566 | + "width-chars", 30, |
567 | +#endif |
568 | + "ellipsize", Pango.EllipsizeMode.END); |
569 | + } |
570 | + |
571 | + void on_render_icon (Gtk.CellLayout column, Gtk.CellRenderer renderer, |
572 | + Gtk.TreeModel model, Gtk.TreeIter iter) { |
573 | + |
574 | + AppInfo app_info; |
575 | + model.get (iter, 1, out app_info); |
576 | + |
577 | + renderer.set ("gicon", app_info_get_icon (app_info), |
578 | + "stock-size", Gtk.IconSize.MENU, |
579 | + "xpad", 4); |
580 | + } |
581 | + |
582 | + void on_render_text (Gtk.CellLayout column, Gtk.CellRenderer renderer, |
583 | + Gtk.TreeModel model, Gtk.TreeIter iter) { |
584 | + |
585 | + AppInfo app_info; |
586 | + model.get (iter, 1, out app_info); |
587 | + renderer.set ("markup", describe_app_info (app_info), |
588 | + "ellipsize", Pango.EllipsizeMode.END); |
589 | + } |
590 | + |
591 | + void launcher_added (string content_type) { |
592 | + var app_info = AppInfo.get_default_for_type (content_type, false); |
593 | + if (app_info == null) |
594 | + return; |
595 | + |
596 | + Gtk.TreeIter iter; |
597 | + store.append (out iter); |
598 | + store.set (iter, 0, content_type, 1, app_info); |
599 | + } |
600 | + |
601 | + int tree_sort_func (Gtk.TreeModel model, Gtk.TreeIter a, Gtk.TreeIter b) { |
602 | + string content_type1, content_type2; |
603 | + model.get (a, 0, out content_type1); |
604 | + model.get (b, 0, out content_type2); |
605 | + return strcmp (content_type1, content_type2); |
606 | + } |
607 | + |
608 | + void row_activated (Gtk.TreePath path, Gtk.TreeViewColumn column) { |
609 | + Gtk.TreeIter iter; |
610 | + if (store.get_iter (out iter, path)) { |
611 | + string content_type; |
612 | + store.get (iter, 0, out content_type); |
613 | + selected (content_type, iter); |
614 | + } |
615 | + } |
616 | + |
617 | + public signal void selected (string content_type, Gtk.TreeIter iter); |
618 | + } |
619 | + |
620 | + |
621 | + private class Manager : Midori.Extension { |
622 | + enum NextStep { |
623 | + TRY_OPEN, |
624 | + OPEN_WITH |
625 | + } |
626 | + |
627 | + bool open_uri (Midori.Tab tab, string uri) { |
628 | + return open_with_type (uri, get_content_type (uri, null), tab, NextStep.TRY_OPEN); |
629 | + } |
630 | + |
631 | + bool navigation_requested (WebKit.WebView web_view, WebKit.WebFrame frame, WebKit.NetworkRequest request, |
632 | + WebKit.WebNavigationAction action, WebKit.WebPolicyDecision decision) { |
633 | + |
634 | + string uri = request.uri; |
635 | + if (Midori.URI.is_http (uri) || Midori.URI.is_blank (uri)) |
636 | + return false; |
637 | + |
638 | + decision.ignore (); |
639 | + |
640 | + string content_type = get_content_type (uri, null); |
641 | + open_with_type (uri, content_type, web_view, NextStep.TRY_OPEN); |
642 | + return true; |
643 | + } |
644 | + |
645 | + string get_content_type (string uri, string? mime_type) { |
646 | + if (!uri.has_prefix ("file://") && !Midori.URI.is_http (uri)) { |
647 | + string protocol = uri.split(":", 2)[0]; |
648 | + return "x-scheme-handler/" + protocol; |
649 | + } else if (mime_type == null) { |
650 | + string filename; |
651 | + bool uncertain; |
652 | + try { |
653 | + filename = Filename.from_uri (uri); |
654 | + } catch (Error error) { |
655 | + filename = uri; |
656 | + } |
657 | + return ContentType.guess (filename, null, out uncertain); |
658 | + } |
659 | + return ContentType.from_mime_type (mime_type); |
660 | + } |
661 | + |
662 | + bool open_with_type (string uri, string content_type, Gtk.Widget widget, NextStep next_step) { |
663 | + #if HAVE_WEBKIT2 |
664 | + return open_now (uri, content_type, widget, next_step); |
665 | + #else |
666 | + if (!Midori.URI.is_http (uri)) |
667 | + return open_now (uri, content_type, widget, next_step); |
668 | + |
669 | + var download = new WebKit.Download (new WebKit.NetworkRequest (uri)); |
670 | + download.destination_uri = Midori.Download.prepare_destination_uri (download, null); |
671 | + if (!Midori.Download.has_enough_space (download, download.destination_uri)) |
672 | + return false; |
673 | + |
674 | + download.notify["status"].connect ((pspec) => { |
675 | + if (download.status == WebKit.DownloadStatus.FINISHED) { |
676 | + open_now (download.destination_uri, content_type, widget, next_step); |
677 | + } |
678 | + else if (download.status == WebKit.DownloadStatus.ERROR) |
679 | + Midori.show_message_dialog (Gtk.MessageType.ERROR, |
680 | + _("Error downloading the image!"), |
681 | + _("Can not download selected image."), false); |
682 | + }); |
683 | + download.start (); |
684 | + return true; |
685 | + #endif |
686 | + } |
687 | + |
688 | + bool open_now (string uri, string content_type, Gtk.Widget widget, NextStep next_step) { |
689 | + if (next_step == NextStep.TRY_OPEN && (new Associations ()).open (content_type, uri)) |
690 | + return true; |
691 | + if (open_with (uri, content_type, widget) != null) |
692 | + return true; |
693 | + return false; |
694 | + } |
695 | + |
696 | + AppInfo? open_with (string uri, string content_type, Gtk.Widget widget) { |
697 | + var dialog = new ChooserDialog (uri, content_type, widget); |
698 | + |
699 | + var app_info = dialog.open_with (); |
700 | + dialog.destroy (); |
701 | + |
702 | + if (uri == "") |
703 | + return app_info; |
704 | + |
705 | + if (app_info == null) |
706 | + return app_info; |
707 | + |
708 | + return open_app_info (app_info, uri, content_type) ? app_info : null; |
709 | + } |
710 | + |
711 | + void context_menu (Midori.Tab tab, WebKit.HitTestResult hit_test_result, Midori.ContextAction menu) { |
712 | + if ((hit_test_result.context & WebKit.HitTestResultContext.LINK) != 0) { |
713 | + string uri = hit_test_result.link_uri; |
714 | + var action = new Gtk.Action ("OpenWith", _("Open _with…"), null, null); |
715 | + action.activate.connect ((action) => { |
716 | + open_with_type (uri, get_content_type (uri, null), tab, NextStep.OPEN_WITH); |
717 | + }); |
718 | + menu.add (action); |
719 | + } |
720 | +#if !HAVE_WEBKIT2 |
721 | + if ((hit_test_result.context & WebKit.HitTestResultContext.IMAGE) != 0) { |
722 | + string uri = hit_test_result.image_uri; |
723 | + var action = new Gtk.Action ("OpenImageInViewer", _("Open in Image _Viewer"), null, null); |
724 | + action.activate.connect ((action) => { |
725 | + open_with_type (uri, get_content_type (uri, null), tab, NextStep.TRY_OPEN); |
726 | + }); |
727 | + menu.add (action); |
728 | + } |
729 | +#endif |
730 | + } |
731 | + |
732 | + void show_preferences (Katze.Preferences preferences) { |
733 | + var settings = get_app ().settings; |
734 | + var category = preferences.add_category (_("File Types"), Gtk.STOCK_FILE); |
735 | + preferences.add_group (null); |
736 | + |
737 | + var sizegroup = new Gtk.SizeGroup (Gtk.SizeGroupMode.HORIZONTAL); |
738 | + var label = new Gtk.Label (_("Text Editor")); |
739 | + sizegroup.add_widget (label); |
740 | + label.set_alignment (0.0f, 0.5f); |
741 | + preferences.add_widget (label, "indented"); |
742 | + var entry = new ChooserButton ("text/plain", settings.text_editor); |
743 | + sizegroup.add_widget (entry); |
744 | + entry.selected.connect ((commandline) => { |
745 | + settings.text_editor = commandline; |
746 | + }); |
747 | + preferences.add_widget (entry, "spanned"); |
748 | + |
749 | + label = new Gtk.Label (_("News Aggregator")); |
750 | + sizegroup.add_widget (label); |
751 | + label.set_alignment (0.0f, 0.5f); |
752 | + preferences.add_widget (label, "indented"); |
753 | + entry = new ChooserButton ("application/rss+xml", settings.news_aggregator); |
754 | + sizegroup.add_widget (entry); |
755 | + entry.selected.connect ((commandline) => { |
756 | + settings.news_aggregator = commandline; |
757 | + }); |
758 | + preferences.add_widget (entry, "spanned"); |
759 | + |
760 | + var types = new Types (); |
761 | + types.selected.connect ((content_type, iter) => { |
762 | + var app_info = open_with ("", content_type, preferences); |
763 | + if (app_info == null) |
764 | + return; |
765 | + try { |
766 | + app_info.set_as_default_for_type (content_type); |
767 | + types.store.set (iter, 1, app_info); |
768 | + } catch (Error error) { |
769 | + warning ("Failed to select default for \"%s\": %s", content_type, error.message); |
770 | + } |
771 | + }); |
772 | + category.pack_start (types, true, true, 0); |
773 | + types.show_all (); |
774 | + } |
775 | + |
776 | + public void tab_added (Midori.Browser browser, Midori.View view) { |
777 | + view.web_view.navigation_policy_decision_requested.connect (navigation_requested); |
778 | + view.open_uri.connect (open_uri); |
779 | + view.context_menu.connect (context_menu); |
780 | + } |
781 | + |
782 | + public void tab_removed (Midori.Browser browser, Midori.View view) { |
783 | + view.web_view.navigation_policy_decision_requested.disconnect (navigation_requested); |
784 | + view.open_uri.disconnect (open_uri); |
785 | + view.context_menu.disconnect (context_menu); |
786 | + } |
787 | + |
788 | + void browser_added (Midori.Browser browser) { |
789 | + foreach (var tab in browser.get_tabs ()) |
790 | + tab_added (browser, tab); |
791 | + browser.add_tab.connect (tab_added); |
792 | + browser.remove_tab.connect (tab_removed); |
793 | + browser.show_preferences.connect (show_preferences); |
794 | + } |
795 | + |
796 | + void activated (Midori.App app) { |
797 | + foreach (var browser in app.get_browsers ()) |
798 | + browser_added (browser); |
799 | + app.add_browser.connect (browser_added); |
800 | + } |
801 | + |
802 | + void browser_removed (Midori.Browser browser) { |
803 | + foreach (var tab in browser.get_tabs ()) |
804 | + tab_removed (browser, tab); |
805 | + browser.add_tab.disconnect (tab_added); |
806 | + browser.remove_tab.disconnect (tab_removed); |
807 | + browser.show_preferences.disconnect (show_preferences); |
808 | + } |
809 | + |
810 | + void deactivated () { |
811 | + var app = get_app (); |
812 | + foreach (var browser in app.get_browsers ()) |
813 | + browser_removed (browser); |
814 | + app.add_browser.disconnect (browser_added); |
815 | + |
816 | + } |
817 | + |
818 | + internal Manager () { |
819 | + GLib.Object (name: "External Applications", |
820 | + description: "Choose what to open unknown file types with", |
821 | + version: "0.1" + Midori.VERSION_SUFFIX, |
822 | + authors: "Christian Dywan <christian@twotoasts.de>"); |
823 | + |
824 | + this.activate.connect (activated); |
825 | + this.deactivate.connect (deactivated); |
826 | + } |
827 | + } |
828 | +} |
829 | + |
830 | +public Midori.Extension extension_init () { |
831 | + return new ExternalApplications.Manager (); |
832 | +} |
833 | + |
834 | |
835 | === modified file 'extensions/transfers.vala' |
836 | --- extensions/transfers.vala 2014-01-06 21:51:09 +0000 |
837 | +++ extensions/transfers.vala 2014-02-25 19:27:20 +0000 |
838 | @@ -14,7 +14,6 @@ |
839 | } |
840 | |
841 | namespace Sokoke { |
842 | - extern static bool show_uri (Gdk.Screen screen, string uri, uint32 timestamp) throws Error; |
843 | extern static void widget_get_text_size (Gtk.Widget widget, string sample, out int width, out int height); |
844 | } |
845 | |
846 | @@ -214,12 +213,8 @@ |
847 | menuitem = new Gtk.ImageMenuItem.with_mnemonic (_("Open Destination _Folder")); |
848 | menuitem.image = new Gtk.Image.from_stock (Gtk.STOCK_DIRECTORY, Gtk.IconSize.MENU); |
849 | menuitem.activate.connect (() => { |
850 | - try { |
851 | - var folder = GLib.File.new_for_uri (transfer.destination); |
852 | - Sokoke.show_uri (get_screen (), folder.get_parent ().get_uri (), 0); |
853 | - } catch (Error error_folder) { |
854 | - GLib.warning (_("Failed to open download: %s"), error_folder.message); |
855 | - } |
856 | + var folder = GLib.File.new_for_uri (transfer.destination); |
857 | + (Midori.Browser.get_for_widget (this).tab as Midori.Tab).open_uri (folder.get_parent ().get_uri ()); |
858 | }); |
859 | menu.append (menuitem); |
860 | menuitem = new Gtk.ImageMenuItem.with_mnemonic (_("Copy Link Loc_ation")); |
861 | |
862 | === modified file 'katze/katze-utils.c' |
863 | --- katze/katze-utils.c 2013-11-05 21:51:18 +0000 |
864 | +++ katze/katze-utils.c 2014-02-25 19:27:20 +0000 |
865 | @@ -101,78 +101,12 @@ |
866 | } |
867 | #endif |
868 | |
869 | -static const gchar* |
870 | -katze_app_info_get_commandline (GAppInfo* info) |
871 | -{ |
872 | - const gchar* exe; |
873 | - |
874 | - exe = g_app_info_get_commandline (info); |
875 | - if (!exe) |
876 | - exe = g_app_info_get_executable (info); |
877 | - if (!exe) |
878 | - exe = g_app_info_get_name (info); |
879 | - return exe; |
880 | -} |
881 | - |
882 | static gboolean |
883 | proxy_entry_focus_out_event_cb (GtkEntry* entry, |
884 | GdkEventFocus* event, |
885 | GObject* object); |
886 | |
887 | static void |
888 | -proxy_combo_box_apps_changed_cb (GtkComboBox* button, |
889 | - GObject* object) |
890 | -{ |
891 | - guint active = gtk_combo_box_get_active (button); |
892 | - GtkTreeModel* model = gtk_combo_box_get_model (button); |
893 | - GtkTreeIter iter; |
894 | - |
895 | - if (gtk_tree_model_iter_nth_child (model, &iter, NULL, active)) |
896 | - { |
897 | - GAppInfo* info; |
898 | - gboolean use_entry; |
899 | - GtkWidget* child; |
900 | - const gchar* exe; |
901 | - const gchar* property = g_object_get_data (G_OBJECT (button), "property"); |
902 | - |
903 | - gtk_tree_model_get (model, &iter, 0, &info, -1); |
904 | - |
905 | - use_entry = info && !g_app_info_get_icon (info); |
906 | - child = gtk_bin_get_child (GTK_BIN (button)); |
907 | - if (use_entry && GTK_IS_CELL_VIEW (child)) |
908 | - { |
909 | - GtkWidget* entry = gtk_entry_new (); |
910 | - exe = g_app_info_get_executable (info); |
911 | - if (exe && *exe && strcmp (exe, "%f")) |
912 | - gtk_entry_set_text (GTK_ENTRY (entry), exe); |
913 | - gtk_widget_show (entry); |
914 | - gtk_container_add (GTK_CONTAINER (button), entry); |
915 | - gtk_widget_grab_focus (entry); |
916 | - g_signal_connect (entry, "focus-out-event", |
917 | - G_CALLBACK (proxy_entry_focus_out_event_cb), object); |
918 | - g_object_set_data_full (G_OBJECT (entry), "property", |
919 | - g_strdup (property), g_free); |
920 | - } |
921 | - else if (!use_entry && GTK_IS_ENTRY (child)) |
922 | - { |
923 | - /* Force the combo to change the item again */ |
924 | - gtk_widget_destroy (child); |
925 | - gtk_combo_box_set_active (button, 0); |
926 | - gtk_combo_box_set_active_iter (button, &iter); |
927 | - } |
928 | - |
929 | - if (info) |
930 | - { |
931 | - exe = katze_app_info_get_commandline (info); |
932 | - g_object_set (object, property, exe, NULL); |
933 | - g_object_unref (info); |
934 | - } |
935 | - else |
936 | - g_object_set (object, property, "", NULL); |
937 | - } |
938 | -} |
939 | - |
940 | -static void |
941 | proxy_entry_activate_cb (GtkEntry* entry, |
942 | GObject* object) |
943 | { |
944 | @@ -326,130 +260,6 @@ |
945 | proxy_object_notify_string_cb, proxy); |
946 | } |
947 | |
948 | -static GList* |
949 | -katze_app_info_get_all_for_category (const gchar* category) |
950 | -{ |
951 | - #ifdef _WIN32 |
952 | - /* FIXME: Real filtering by category would be better */ |
953 | - const gchar* content_type = g_content_type_from_mime_type (category); |
954 | - GList* all_apps = g_app_info_get_all_for_type (content_type); |
955 | - #else |
956 | - GList* all_apps = g_app_info_get_all (); |
957 | - #endif |
958 | - GList* apps = NULL; |
959 | - GList* app; |
960 | - for (app = apps; app; app = g_list_next (app)) |
961 | - { |
962 | - GAppInfo* info = app->data; |
963 | - #ifdef GDK_WINDOWING_X11 |
964 | - gchar* filename = g_strconcat ("applications/", g_app_info_get_id (info), NULL); |
965 | - GKeyFile* file = g_key_file_new (); |
966 | - |
967 | - if (g_key_file_load_from_data_dirs (file, filename, NULL, G_KEY_FILE_NONE, NULL)) |
968 | - { |
969 | - gchar* cat = g_key_file_get_string (file, "Desktop Entry", |
970 | - "Categories", NULL); |
971 | - if (cat && g_strrstr (cat, category)) |
972 | - apps = g_list_append (apps, info); |
973 | - |
974 | - g_free (cat); |
975 | - } |
976 | - g_key_file_free (file); |
977 | - g_free (filename); |
978 | - #else |
979 | - apps = g_list_append (apps, info); |
980 | - #endif |
981 | - } |
982 | - g_list_free (all_apps); |
983 | - return apps; |
984 | -} |
985 | - |
986 | -static gboolean |
987 | -proxy_populate_apps (GtkWidget* widget) |
988 | -{ |
989 | - const gchar* property = g_object_get_data (G_OBJECT (widget), "property"); |
990 | - GObject* object = g_object_get_data (G_OBJECT (widget), "object"); |
991 | - gchar* string = katze_object_get_string (object, property); |
992 | - if (!g_strcmp0 (string, "")) |
993 | - katze_assign (string, NULL); |
994 | - GtkSettings* settings = gtk_widget_get_settings (widget); |
995 | - gint icon_width = 16; |
996 | - if (settings == NULL) |
997 | - settings = gtk_settings_get_for_screen (gdk_screen_get_default ()); |
998 | - gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU, |
999 | - &icon_width, NULL); |
1000 | - |
1001 | - GtkComboBox* combo = GTK_COMBO_BOX (widget); |
1002 | - GtkListStore* model = GTK_LIST_STORE (gtk_combo_box_get_model (combo)); |
1003 | - GtkTreeIter iter_none; |
1004 | - gtk_list_store_insert_with_values (model, &iter_none, 0, |
1005 | - 0, NULL, 1, NULL, 2, _("None"), 3, icon_width, -1); |
1006 | - |
1007 | - const gchar* app_type = g_object_get_data (G_OBJECT (widget), "app-type"); |
1008 | - GList* apps = g_app_info_get_all_for_type (app_type); |
1009 | - GAppInfo* info; |
1010 | - if (!apps) |
1011 | - apps = katze_app_info_get_all_for_category (app_type); |
1012 | - if (apps != NULL) |
1013 | - { |
1014 | - GList* app; |
1015 | - for (app = apps; app; app = g_list_next (app)) |
1016 | - { |
1017 | - info = app->data; |
1018 | - const gchar* name = g_app_info_get_name (info); |
1019 | - GIcon* icon = g_app_info_get_icon (info); |
1020 | - gchar* icon_name; |
1021 | - GtkTreeIter iter; |
1022 | - |
1023 | - if (!g_app_info_should_show (info)) |
1024 | - continue; |
1025 | - |
1026 | - icon_name = icon ? g_icon_to_string (icon) : NULL; |
1027 | - gtk_list_store_insert_with_values (model, &iter, G_MAXINT, |
1028 | - 0, info, 1, icon_name, 2, name, 3, icon_width, -1); |
1029 | - if (string && !strcmp (katze_app_info_get_commandline (info), string)) |
1030 | - gtk_combo_box_set_active_iter (combo, &iter); |
1031 | - |
1032 | - g_free (icon_name); |
1033 | - } |
1034 | - g_list_free (apps); |
1035 | - } |
1036 | - |
1037 | - info = g_app_info_create_from_commandline ("", |
1038 | - "", G_APP_INFO_CREATE_NONE, NULL); |
1039 | - gtk_list_store_insert_with_values (model, NULL, G_MAXINT, |
1040 | - 0, info, 1, NULL, 2, _("Custom…"), 3, icon_width, -1); |
1041 | - g_object_unref (info); |
1042 | - |
1043 | - if (gtk_combo_box_get_active (combo) == -1) |
1044 | - { |
1045 | - if (string) |
1046 | - { |
1047 | - GtkWidget* entry; |
1048 | - const gchar* exe; |
1049 | - |
1050 | - info = g_app_info_create_from_commandline (string, |
1051 | - NULL, G_APP_INFO_CREATE_NONE, NULL); |
1052 | - entry = gtk_entry_new (); |
1053 | - exe = g_app_info_get_executable (info); |
1054 | - if (exe && *exe && strcmp (exe, "%f")) |
1055 | - gtk_entry_set_text (GTK_ENTRY (entry), string); |
1056 | - gtk_widget_show (entry); |
1057 | - gtk_container_add (GTK_CONTAINER (combo), entry); |
1058 | - g_object_unref (info); |
1059 | - g_signal_connect (entry, "focus-out-event", |
1060 | - G_CALLBACK (proxy_entry_focus_out_event_cb), object); |
1061 | - g_object_set_data_full (G_OBJECT (entry), "property", |
1062 | - g_strdup (property), g_free); |
1063 | - } |
1064 | - else |
1065 | - gtk_combo_box_set_active_iter (combo, &iter_none); |
1066 | - } |
1067 | - g_signal_connect (widget, "changed", |
1068 | - G_CALLBACK (proxy_combo_box_apps_changed_cb), object); |
1069 | - return G_SOURCE_REMOVE; |
1070 | -} |
1071 | - |
1072 | /** |
1073 | * katze_property_proxy: |
1074 | * @object: a #GObject |
1075 | @@ -483,6 +293,7 @@ |
1076 | * for choosing an application to open TYPE files, ie. "text/plain". |
1077 | * "application-CATEGORY": the widget created will be particularly suitable |
1078 | * for choosing an application to open CATEGORY files, ie. "Network". |
1079 | + * Since 0.5.8 the CATEGORY hint is no longer supported. |
1080 | * "custom-PROPERTY": the last value of an enumeration will be the "custom" |
1081 | * value, where the user may enter text freely, which then updates |
1082 | * the property PROPERTY instead. This applies only to enumerations. |
1083 | @@ -652,27 +463,6 @@ |
1084 | g_free (families); |
1085 | #endif |
1086 | } |
1087 | - else if (type == G_TYPE_PARAM_STRING && hint && g_str_has_prefix (hint, "application-")) |
1088 | - { |
1089 | - GtkListStore* model; |
1090 | - GtkCellRenderer* renderer; |
1091 | - const gchar* app_type = &hint[12]; |
1092 | - |
1093 | - model = gtk_list_store_new (4, G_TYPE_APP_INFO, G_TYPE_STRING, |
1094 | - G_TYPE_STRING, G_TYPE_INT); |
1095 | - widget = gtk_combo_box_new_with_model (GTK_TREE_MODEL (model)); |
1096 | - renderer = gtk_cell_renderer_pixbuf_new (); |
1097 | - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), renderer, FALSE); |
1098 | - gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (widget), renderer, "icon-name", 1); |
1099 | - gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (widget), renderer, "width", 3); |
1100 | - renderer = gtk_cell_renderer_text_new (); |
1101 | - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), renderer, TRUE); |
1102 | - gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (widget), renderer, "text", 2); |
1103 | - |
1104 | - g_object_set_data_full (G_OBJECT (widget), "app-type", g_strdup (app_type), g_free); |
1105 | - g_object_set_data_full (G_OBJECT (widget), "object", g_object_ref (object), g_object_unref); |
1106 | - g_idle_add_full (G_PRIORITY_LOW, (GSourceFunc)proxy_populate_apps, widget, NULL); |
1107 | - } |
1108 | else if (type == G_TYPE_PARAM_STRING) |
1109 | { |
1110 | gchar* notify_property; |
1111 | |
1112 | === modified file 'katze/katze.vapi' |
1113 | --- katze/katze.vapi 2013-09-22 16:22:10 +0000 |
1114 | +++ katze/katze.vapi 2014-02-25 19:27:20 +0000 |
1115 | @@ -36,5 +36,12 @@ |
1116 | public unowned string? get_meta_string (string key); |
1117 | public void set_meta_string (string key, string value); |
1118 | } |
1119 | + |
1120 | + [CCode (cheader_filename = "katze/katze.h")] |
1121 | + public class Preferences : Gtk.Dialog { |
1122 | + public unowned Gtk.Box add_category (string label, string icon); |
1123 | + public void add_group (string? label); |
1124 | + public void add_widget (Gtk.Widget widget, string type); |
1125 | + } |
1126 | } |
1127 | |
1128 | |
1129 | === modified file 'katze/midori-uri.vala' |
1130 | --- katze/midori-uri.vala 2014-01-06 21:51:09 +0000 |
1131 | +++ katze/midori-uri.vala 2014-02-25 19:27:20 +0000 |
1132 | @@ -16,6 +16,8 @@ |
1133 | |
1134 | namespace Midori { |
1135 | public class URI : Object { |
1136 | + static string? fork_uri = null; |
1137 | + |
1138 | public static string? parse_hostname (string? uri, out string path) { |
1139 | path = null; |
1140 | if (uri == null) |
1141 | @@ -205,5 +207,20 @@ |
1142 | label = display; |
1143 | return type; |
1144 | } |
1145 | + |
1146 | + /* |
1147 | + Protects against recursive invokations of Midori with the same URI. |
1148 | + Consider a tel:// URI opened via Tab.open_uri, being handed off to GIO, |
1149 | + which in turns calls exo-open, which in turn can't open tel:// and falls |
1150 | + back to the browser ie. Midori. |
1151 | + So: code opening URIs calls this function with %true, #Midori.App passes %false. |
1152 | + |
1153 | + Since: 0.5.8 |
1154 | + */ |
1155 | + public static bool recursive_fork_protection (string uri, bool set_uri) { |
1156 | + if (set_uri) |
1157 | + fork_uri = uri; |
1158 | + return fork_uri != uri; |
1159 | + } |
1160 | } |
1161 | } |
1162 | |
1163 | === modified file 'midori/midori-app.c' |
1164 | --- midori/midori-app.c 2014-02-24 11:33:50 +0000 |
1165 | +++ midori/midori-app.c 2014-02-25 19:27:20 +0000 |
1166 | @@ -535,7 +535,7 @@ |
1167 | for (i = 0; i < n_files; i++) |
1168 | { |
1169 | gchar* uri = g_file_get_uri (files[i]); |
1170 | - if (sokoke_recursive_fork_protection (uri, FALSE)) |
1171 | + if (midori_uri_recursive_fork_protection (uri, FALSE)) |
1172 | { |
1173 | if (first) |
1174 | { |
1175 | |
1176 | === modified file 'midori/midori-browser.c' |
1177 | --- midori/midori-browser.c 2014-02-12 22:56:28 +0000 |
1178 | +++ midori/midori-browser.c 2014-02-25 19:27:20 +0000 |
1179 | @@ -1496,7 +1496,11 @@ |
1180 | MidoriNewView where) |
1181 | { |
1182 | if (midori_paths_get_runtime_mode () == MIDORI_RUNTIME_MODE_APP) |
1183 | - return sokoke_show_uri (gtk_widget_get_screen (view), uri, 0, NULL); |
1184 | + { |
1185 | + gboolean handled = FALSE; |
1186 | + g_signal_emit_by_name (view, "open-uri", uri, &handled); |
1187 | + return handled; |
1188 | + } |
1189 | else if (midori_paths_get_runtime_mode () == MIDORI_RUNTIME_MODE_PRIVATE) |
1190 | { |
1191 | if (where == MIDORI_NEW_VIEW_WINDOW) |
1192 | @@ -1613,37 +1617,6 @@ |
1193 | } |
1194 | } |
1195 | |
1196 | -static void |
1197 | -midori_browser_download_status_cb (WebKitDownload* download, |
1198 | - GParamSpec* pspec, |
1199 | - GtkWidget* widget) |
1200 | -{ |
1201 | -#ifndef HAVE_WEBKIT2 |
1202 | - const gchar* uri = webkit_download_get_destination_uri (download); |
1203 | - switch (webkit_download_get_status (download)) |
1204 | - { |
1205 | - case WEBKIT_DOWNLOAD_STATUS_FINISHED: |
1206 | - if (!sokoke_show_uri (gtk_widget_get_screen (widget), uri, 0, NULL)) |
1207 | - { |
1208 | - sokoke_message_dialog (GTK_MESSAGE_ERROR, |
1209 | - _("Error opening the image!"), |
1210 | - _("Can not open selected image in a default viewer."), FALSE); |
1211 | - } |
1212 | - break; |
1213 | - case WEBKIT_DOWNLOAD_STATUS_ERROR: |
1214 | - webkit_download_cancel (download); |
1215 | - sokoke_message_dialog (GTK_MESSAGE_ERROR, |
1216 | - _("Error downloading the image!"), |
1217 | - _("Can not download selected image."), FALSE); |
1218 | - break; |
1219 | - case WEBKIT_DOWNLOAD_STATUS_CREATED: |
1220 | - case WEBKIT_DOWNLOAD_STATUS_STARTED: |
1221 | - case WEBKIT_DOWNLOAD_STATUS_CANCELLED: |
1222 | - break; |
1223 | - } |
1224 | -#endif |
1225 | -} |
1226 | - |
1227 | #ifdef HAVE_WEBKIT2 |
1228 | static void |
1229 | midori_browser_close_tab_idle (GObject* resource, |
1230 | @@ -1679,18 +1652,6 @@ |
1231 | { |
1232 | handled = FALSE; |
1233 | } |
1234 | - else if (type == MIDORI_DOWNLOAD_OPEN_IN_VIEWER) |
1235 | - { |
1236 | - gchar* destination_uri = |
1237 | - midori_download_prepare_destination_uri (download, NULL); |
1238 | - midori_browser_prepare_download (browser, download, destination_uri); |
1239 | - g_signal_connect (download, "notify::status", |
1240 | - G_CALLBACK (midori_browser_download_status_cb), GTK_WIDGET (browser)); |
1241 | - g_free (destination_uri); |
1242 | - #ifndef HAVE_WEBKIT2 |
1243 | - webkit_download_start (download); |
1244 | - #endif |
1245 | - } |
1246 | #ifdef HAVE_WEBKIT2 |
1247 | else if (!webkit_download_get_destination (download)) |
1248 | #else |
1249 | |
1250 | === modified file 'midori/midori-dialog.vala' |
1251 | --- midori/midori-dialog.vala 2014-01-25 21:04:57 +0000 |
1252 | +++ midori/midori-dialog.vala 2014-02-25 19:27:20 +0000 |
1253 | @@ -103,6 +103,20 @@ |
1254 | } |
1255 | } |
1256 | |
1257 | + public static void show_message_dialog (Gtk.MessageType type, string short, string detailed, bool modal) { |
1258 | + var dialog = new Gtk.MessageDialog (null, 0, type, Gtk.ButtonsType.OK, "%s", short); |
1259 | + dialog.format_secondary_text ("%s", detailed); |
1260 | + if (modal) { |
1261 | + dialog.run (); |
1262 | + dialog.destroy (); |
1263 | + } else { |
1264 | + dialog.response.connect ((response) => { |
1265 | + dialog.destroy (); |
1266 | + }); |
1267 | + dialog.show (); |
1268 | + } |
1269 | + } |
1270 | + |
1271 | public class FileChooserDialog : Gtk.FileChooserDialog { |
1272 | public FileChooserDialog (string title, Gtk.Window? window, Gtk.FileChooserAction action) { |
1273 | /* Creates a new file chooser dialog to Open or Save and Cancel. |
1274 | |
1275 | === modified file 'midori/midori-download.vala' |
1276 | --- midori/midori-download.vala 2014-01-06 21:51:09 +0000 |
1277 | +++ midori/midori-download.vala 2014-02-25 19:27:20 +0000 |
1278 | @@ -11,7 +11,6 @@ |
1279 | |
1280 | namespace Sokoke { |
1281 | #if !HAVE_WEBKIT2 |
1282 | - extern static bool show_uri (Gdk.Screen screen, string uri, uint32 timestamp) throws Error; |
1283 | extern static bool message_dialog (Gtk.MessageType type, string short, string detailed, bool modal); |
1284 | #endif |
1285 | } |
1286 | @@ -212,9 +211,13 @@ |
1287 | |
1288 | public static bool open (WebKit.Download download, Gtk.Widget widget) throws Error { |
1289 | #if !HAVE_WEBKIT2 |
1290 | - if (!has_wrong_checksum (download)) |
1291 | - return Sokoke.show_uri (widget.get_screen (), |
1292 | - download.destination_uri, Gtk.get_current_event_time ()); |
1293 | + if (!has_wrong_checksum (download)) { |
1294 | + var browser = widget.get_toplevel (); |
1295 | + Tab? tab = null; |
1296 | + browser.get ("tab", tab); |
1297 | + if (tab != null) |
1298 | + tab.open_uri (download.destination_uri); |
1299 | + } |
1300 | |
1301 | Sokoke.message_dialog (Gtk.MessageType.WARNING, |
1302 | _("The downloaded file is erroneous."), |
1303 | |
1304 | === modified file 'midori/midori-extension.c' |
1305 | --- midori/midori-extension.c 2013-12-09 19:49:15 +0000 |
1306 | +++ midori/midori-extension.c 2014-02-25 19:27:20 +0000 |
1307 | @@ -563,6 +563,7 @@ |
1308 | g_assert (midori_extension_activate_gracefully (app, extension_path, "libapps." G_MODULE_SUFFIX, activate)); |
1309 | g_assert (midori_extension_activate_gracefully (app, extension_path, "libdelayed-load." G_MODULE_SUFFIX, activate)); |
1310 | g_assert (midori_extension_activate_gracefully (app, extension_path, "libtabby." G_MODULE_SUFFIX, activate)); |
1311 | + g_assert (midori_extension_activate_gracefully (app, extension_path, "libopen-with." G_MODULE_SUFFIX, activate)); |
1312 | g_assert (midori_extension_activate_gracefully (app, extension_path, "libflummi." G_MODULE_SUFFIX, activate)); |
1313 | } |
1314 | else |
1315 | @@ -679,6 +680,7 @@ |
1316 | && strcmp (filename, "libapps." G_MODULE_SUFFIX) |
1317 | && strcmp (filename, "libdelayed-load." G_MODULE_SUFFIX) |
1318 | && strcmp (filename, "libtabby." G_MODULE_SUFFIX) |
1319 | + && strcmp (filename, "libopen-with." G_MODULE_SUFFIX) |
1320 | && strcmp (filename, "libflummi." G_MODULE_SUFFIX)) |
1321 | katze_array_add_item (extensions, extension); |
1322 | |
1323 | |
1324 | === modified file 'midori/midori-frontend.c' |
1325 | --- midori/midori-frontend.c 2013-11-29 16:29:02 +0000 |
1326 | +++ midori/midori-frontend.c 2014-02-25 19:27:20 +0000 |
1327 | @@ -239,6 +239,7 @@ |
1328 | |
1329 | /* FIXME need proper stock extension mechanism */ |
1330 | midori_browser_activate_action (browser, "libtransfers." G_MODULE_SUFFIX "=true"); |
1331 | + midori_browser_activate_action (browser, "libopen-with." G_MODULE_SUFFIX "=true"); |
1332 | g_assert (g_module_error () == NULL); |
1333 | |
1334 | return browser; |
1335 | @@ -301,7 +302,7 @@ |
1336 | gchar* crash_log) |
1337 | { |
1338 | GError* error = NULL; |
1339 | - if (!sokoke_show_uri (gtk_widget_get_screen (button), crash_log, 0, &error)) |
1340 | + if (!gtk_show_uri (gtk_widget_get_screen (button), crash_log, 0, &error)) |
1341 | { |
1342 | sokoke_message_dialog (GTK_MESSAGE_ERROR, |
1343 | _("Could not run external program."), |
1344 | |
1345 | === modified file 'midori/midori-preferences.c' |
1346 | --- midori/midori-preferences.c 2013-12-09 11:40:39 +0000 |
1347 | +++ midori/midori-preferences.c 2014-02-25 19:27:20 +0000 |
1348 | @@ -490,18 +490,6 @@ |
1349 | gtk_button_set_label (GTK_BUTTON (button), _("Open tabs in the background")); |
1350 | SPANNED_ADD (button); |
1351 | |
1352 | - INDENTED_ADD (gtk_label_new (NULL)); |
1353 | - label = gtk_label_new (_("Text Editor")); |
1354 | - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); |
1355 | - INDENTED_ADD (label); |
1356 | - entry = katze_property_proxy (settings, "text-editor", "application-text/plain"); |
1357 | - SPANNED_ADD (entry); |
1358 | - label = gtk_label_new (_("News Aggregator")); |
1359 | - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); |
1360 | - INDENTED_ADD (label); |
1361 | - entry = katze_property_proxy (settings, "news-aggregator", "application-News"); |
1362 | - SPANNED_ADD (entry); |
1363 | - |
1364 | /* Page "Network" */ |
1365 | PAGE_NEW (GTK_STOCK_NETWORK, _("Network")); |
1366 | FRAME_NEW (NULL); |
1367 | |
1368 | === modified file 'midori/midori-tab.vala' |
1369 | --- midori/midori-tab.vala 2013-12-09 20:23:03 +0000 |
1370 | +++ midori/midori-tab.vala 2014-02-25 19:27:20 +0000 |
1371 | @@ -88,6 +88,8 @@ |
1372 | } |
1373 | } |
1374 | |
1375 | + /* Since: 0.5.8 */ |
1376 | + public signal bool open_uri (string uri); |
1377 | public signal void console_message (string message, int line, string source_id); |
1378 | public signal void attach_inspector (WebKit.WebView inspector_view); |
1379 | /* Emitted when an open inspector that was previously |
1380 | |
1381 | === modified file 'midori/midori-view.c' |
1382 | --- midori/midori-view.c 2013-12-09 20:23:03 +0000 |
1383 | +++ midori/midori-view.c 2014-02-25 19:27:20 +0000 |
1384 | @@ -558,19 +558,6 @@ |
1385 | g_free (new_uri); |
1386 | return TRUE; |
1387 | } |
1388 | - else if (sokoke_external_uri (uri)) |
1389 | - { |
1390 | - if (sokoke_show_uri (gtk_widget_get_screen (GTK_WIDGET (web_view)), |
1391 | - uri, GDK_CURRENT_TIME, NULL)) |
1392 | - { |
1393 | - #ifdef HAVE_WEBKIT2 |
1394 | - webkit_policy_decision_ignore (decision); |
1395 | - #else |
1396 | - webkit_web_policy_decision_ignore (decision); |
1397 | - #endif |
1398 | - return TRUE; |
1399 | - } |
1400 | - } |
1401 | else if (g_str_has_prefix (uri, "data:image/")) |
1402 | { |
1403 | /* For security reasons, main content served as data: is limited to images |
1404 | @@ -2109,16 +2096,6 @@ |
1405 | } |
1406 | |
1407 | static void |
1408 | -midori_web_view_open_in_viewer_cb (GtkAction* action, |
1409 | - gpointer user_data) |
1410 | -{ |
1411 | - MidoriView* view = user_data; |
1412 | - gchar* uri = katze_object_get_string (view->hit_test, "image-uri"); |
1413 | - midori_view_download_uri (view, MIDORI_DOWNLOAD_OPEN_IN_VIEWER, uri); |
1414 | - g_free (uri); |
1415 | -} |
1416 | - |
1417 | -static void |
1418 | midori_web_view_menu_video_copy_activate_cb (GtkAction* action, |
1419 | gpointer user_data) |
1420 | { |
1421 | @@ -2146,8 +2123,8 @@ |
1422 | MidoriView* view = user_data; |
1423 | gchar* data = (gchar*)g_object_get_data (G_OBJECT (action), "uri"); |
1424 | gchar* uri = g_strconcat ("mailto:", data, NULL); |
1425 | - sokoke_show_uri (gtk_widget_get_screen (view->web_view), |
1426 | - uri, GDK_CURRENT_TIME, NULL); |
1427 | + gboolean handled = FALSE; |
1428 | + g_signal_emit_by_name (view, "open-uri", uri, &handled); |
1429 | g_free (uri); |
1430 | } |
1431 | #endif |
1432 | @@ -2358,8 +2335,6 @@ |
1433 | midori_web_view_menu_image_copy_activate_cb, view); |
1434 | midori_context_action_add_simple (menu, "SaveImage", _("Save I_mage"), NULL, GTK_STOCK_SAVE, |
1435 | midori_web_view_menu_image_save_activate_cb, view); |
1436 | - midori_context_action_add_simple (menu, "OpenImageInViewer", _("Open in Image _Viewer"), NULL, GTK_STOCK_OPEN, |
1437 | - midori_web_view_open_in_viewer_cb, view); |
1438 | } |
1439 | |
1440 | if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_MEDIA) |
1441 | @@ -4013,12 +3988,19 @@ |
1442 | g_free (exception); |
1443 | } |
1444 | } |
1445 | - else if (sokoke_external_uri (uri)) |
1446 | - { |
1447 | - sokoke_show_uri (NULL, uri, GDK_CURRENT_TIME, NULL); |
1448 | - } |
1449 | else |
1450 | { |
1451 | + if (sokoke_external_uri (uri)) |
1452 | + { |
1453 | + gboolean handled = FALSE; |
1454 | + g_signal_emit_by_name (view, "open-uri", uri, &handled); |
1455 | + if (handled) |
1456 | + { |
1457 | + g_free (temporary_uri); |
1458 | + return; |
1459 | + } |
1460 | + } |
1461 | + |
1462 | midori_tab_set_uri (MIDORI_TAB (view), uri); |
1463 | katze_item_set_uri (view->item, midori_tab_get_uri (MIDORI_TAB (view))); |
1464 | katze_assign (view->title, NULL); |
1465 | |
1466 | === modified file 'midori/midori.vapi' |
1467 | --- midori/midori.vapi 2014-01-30 21:43:31 +0000 |
1468 | +++ midori/midori.vapi 2014-02-25 19:27:20 +0000 |
1469 | @@ -118,6 +118,7 @@ |
1470 | public signal void quit (); |
1471 | public signal void send_notification (string title, string message); |
1472 | public static void update_history (Katze.Item item, string type, string event); |
1473 | + public signal void show_preferences (Katze.Preferences preferences); |
1474 | } |
1475 | |
1476 | [CCode (cheader_filename = "midori/midori.h")] |
1477 | |
1478 | === modified file 'midori/sokoke.c' |
1479 | --- midori/sokoke.c 2013-10-28 23:36:29 +0000 |
1480 | +++ midori/sokoke.c 2014-02-25 19:27:20 +0000 |
1481 | @@ -37,6 +37,7 @@ |
1482 | #ifdef G_OS_WIN32 |
1483 | #include <windows.h> |
1484 | #include <shlobj.h> |
1485 | +#include <gdk/gdkwin32.h> |
1486 | #endif |
1487 | |
1488 | static gchar* |
1489 | @@ -109,39 +110,8 @@ |
1490 | const gchar* detailed_message, |
1491 | gboolean modal) |
1492 | { |
1493 | - GtkWidget* dialog = gtk_message_dialog_new ( |
1494 | - NULL, 0, message_type, GTK_BUTTONS_OK, "%s", short_message); |
1495 | - gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), |
1496 | - "%s", detailed_message); |
1497 | - if (modal) |
1498 | - { |
1499 | - gtk_dialog_run (GTK_DIALOG (dialog)); |
1500 | - gtk_widget_destroy (dialog); |
1501 | - } |
1502 | - else |
1503 | - { |
1504 | - g_signal_connect_swapped (dialog, "response", |
1505 | - G_CALLBACK (gtk_widget_destroy), dialog); |
1506 | - gtk_widget_show (dialog); |
1507 | - } |
1508 | - |
1509 | -} |
1510 | - |
1511 | -#ifndef G_OS_WIN32 |
1512 | -static void |
1513 | -sokoke_open_with_response_cb (GtkWidget* dialog, |
1514 | - gint response, |
1515 | - GtkEntry* entry) |
1516 | -{ |
1517 | - if (response == GTK_RESPONSE_ACCEPT) |
1518 | - { |
1519 | - const gchar* command = gtk_entry_get_text (entry); |
1520 | - const gchar* uri = g_object_get_data (G_OBJECT (dialog), "uri"); |
1521 | - sokoke_spawn_program (command, FALSE, uri, TRUE, FALSE); |
1522 | - } |
1523 | - gtk_widget_destroy (dialog); |
1524 | -} |
1525 | -#endif |
1526 | + midori_show_message_dialog (message_type, short_message, detailed_message, modal); |
1527 | +} |
1528 | |
1529 | GAppInfo* |
1530 | sokoke_default_for_uri (const gchar* uri, |
1531 | @@ -164,86 +134,6 @@ |
1532 | } |
1533 | |
1534 | /** |
1535 | - * sokoke_show_uri: |
1536 | - * @screen: a #GdkScreen, or %NULL |
1537 | - * @uri: the URI to show |
1538 | - * @timestamp: the timestamp of the event |
1539 | - * @error: the location of a #GError, or %NULL |
1540 | - * |
1541 | - * Shows the specified URI with an application or xdg-open. |
1542 | - * x-scheme-handler is supported for GLib < 2.28 as of 0.3.3. |
1543 | - * |
1544 | - * Return value: %TRUE on success, %FALSE if an error occurred |
1545 | - **/ |
1546 | -gboolean |
1547 | -sokoke_show_uri (GdkScreen* screen, |
1548 | - const gchar* uri, |
1549 | - guint32 timestamp, |
1550 | - GError** error) |
1551 | -{ |
1552 | - #ifdef G_OS_WIN32 |
1553 | - CoInitializeEx (NULL, COINIT_APARTMENTTHREADED); |
1554 | - SHELLEXECUTEINFO info = { sizeof (info) }; |
1555 | - info.nShow = SW_SHOWNORMAL; |
1556 | - info.lpFile = uri; |
1557 | - |
1558 | - return ShellExecuteEx (&info); |
1559 | - #else |
1560 | - |
1561 | - GtkWidget* dialog; |
1562 | - GtkWidget* box; |
1563 | - gchar* filename; |
1564 | - gchar* ms; |
1565 | - GtkWidget* entry; |
1566 | - |
1567 | - g_return_val_if_fail (GDK_IS_SCREEN (screen) || !screen, FALSE); |
1568 | - g_return_val_if_fail (uri != NULL, FALSE); |
1569 | - g_return_val_if_fail (!error || !*error, FALSE); |
1570 | - |
1571 | - sokoke_recursive_fork_protection (uri, TRUE); |
1572 | - |
1573 | - /* g_app_info_launch_default_for_uri, gdk_display_get_app_launch_context */ |
1574 | - if (gtk_show_uri (screen, uri, timestamp, error)) |
1575 | - return TRUE; |
1576 | - |
1577 | - { |
1578 | - gchar* command = g_strconcat ("xdg-open ", uri, NULL); |
1579 | - gboolean result = g_spawn_command_line_async (command, error); |
1580 | - g_free (command); |
1581 | - if (result) |
1582 | - return TRUE; |
1583 | - if (error) |
1584 | - *error = NULL; |
1585 | - } |
1586 | - |
1587 | - dialog = gtk_dialog_new_with_buttons (_("Open with"), NULL, 0, |
1588 | - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
1589 | - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); |
1590 | - box = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); |
1591 | - if (g_str_has_prefix (uri, "file:///")) |
1592 | - filename = g_filename_from_uri (uri, NULL, NULL); |
1593 | - else |
1594 | - filename = g_strdup (uri); |
1595 | - ms = g_strdup_printf (_("Choose an application or command to open \"%s\":"), |
1596 | - filename); |
1597 | - gtk_box_pack_start (GTK_BOX (box), gtk_label_new (ms), TRUE, FALSE, 4); |
1598 | - g_free (ms); |
1599 | - entry = gtk_entry_new (); |
1600 | - gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); |
1601 | - gtk_box_pack_start (GTK_BOX (box), entry, TRUE, FALSE, 4); |
1602 | - g_signal_connect (dialog, "response", |
1603 | - G_CALLBACK (sokoke_open_with_response_cb), entry); |
1604 | - g_object_set_data_full (G_OBJECT (dialog), "uri", |
1605 | - filename, (GDestroyNotify)g_free); |
1606 | - gtk_widget_show_all (dialog); |
1607 | - gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT); |
1608 | - gtk_widget_grab_focus (entry); |
1609 | - |
1610 | - return TRUE; |
1611 | - #endif |
1612 | -} |
1613 | - |
1614 | -/** |
1615 | * sokoke_prepare_command: |
1616 | * @command: the command, properly quoted |
1617 | * @argument: any arguments, properly quoted |
1618 | @@ -919,36 +809,6 @@ |
1619 | #endif |
1620 | } |
1621 | |
1622 | -/** |
1623 | - * sokoke_recursive_fork_protection |
1624 | - * @uri: the URI to check |
1625 | - * @set_uri: if TRUE the URI will be saved |
1626 | - * |
1627 | - * Protects against recursive invokations of the Midori executable |
1628 | - * with the same URI. |
1629 | - * |
1630 | - * As an example, consider having an URI starting with 'tel://'. You |
1631 | - * could attempt to open it with sokoke_show_uri. In turn, 'exo-open' |
1632 | - * might be called. Now quite possibly 'exo-open' is unable to handle |
1633 | - * 'tel://' and might well fall back to 'midori' as default browser. |
1634 | - * |
1635 | - * To protect against this scenario, call this function with the |
1636 | - * URI and %TRUE before calling any external tool. |
1637 | - * #MidoriApp calls sokoke_recursive_fork_protection() with %FALSE |
1638 | - * and bails out if %FALSE is returned. |
1639 | - * |
1640 | - * Return value: %TRUE if @uri is new, %FALSE on recursion |
1641 | - **/ |
1642 | -gboolean |
1643 | -sokoke_recursive_fork_protection (const gchar* uri, |
1644 | - gboolean set_uri) |
1645 | -{ |
1646 | - static gchar* fork_uri = NULL; |
1647 | - if (set_uri) |
1648 | - katze_assign (fork_uri, g_strdup (uri)); |
1649 | - return g_strcmp0 (fork_uri, uri) == 0 ? FALSE : TRUE; |
1650 | -} |
1651 | - |
1652 | static void |
1653 | sokoke_widget_clipboard_owner_clear_func (GtkClipboard* clipboard, |
1654 | gpointer user_data) |
1655 | @@ -1121,4 +981,23 @@ |
1656 | g_free (lnk_path); |
1657 | g_free (launcher_type); |
1658 | } |
1659 | + |
1660 | +GdkPixbuf* |
1661 | +sokoke_get_gdk_pixbuf_from_win32_executable (gchar* path) |
1662 | +{ |
1663 | + if (path == NULL) |
1664 | + return NULL; |
1665 | + |
1666 | + GdkPixbuf* pixbuf = NULL; |
1667 | + HICON hIcon = NULL; |
1668 | + HINSTANCE hInstance = NULL; |
1669 | + hIcon = ExtractIcon (hInstance, (LPCSTR)path, 0); |
1670 | + if (hIcon == NULL) |
1671 | + return NULL; |
1672 | + |
1673 | + pixbuf = gdk_win32_icon_to_pixbuf_libgtk_only (hIcon, NULL, NULL); |
1674 | + DestroyIcon (hIcon); |
1675 | + |
1676 | + return pixbuf; |
1677 | +} |
1678 | #endif |
1679 | |
1680 | === modified file 'midori/sokoke.h' |
1681 | --- midori/sokoke.h 2013-08-02 16:40:27 +0000 |
1682 | +++ midori/sokoke.h 2014-02-25 19:27:20 +0000 |
1683 | @@ -29,19 +29,6 @@ |
1684 | const gchar* detailed_message, |
1685 | gboolean modal); |
1686 | |
1687 | -gboolean |
1688 | -sokoke_show_uri_with_mime_type (GdkScreen* screen, |
1689 | - const gchar* uri, |
1690 | - const gchar* mime_type, |
1691 | - guint32 timestamp, |
1692 | - GError** error); |
1693 | - |
1694 | -gboolean |
1695 | -sokoke_show_uri (GdkScreen* screen, |
1696 | - const gchar* uri, |
1697 | - guint32 timestamp, |
1698 | - GError** error); |
1699 | - |
1700 | gchar* |
1701 | sokoke_prepare_command (const gchar* command, |
1702 | gboolean quote_command, |
1703 | @@ -112,10 +99,6 @@ |
1704 | gboolean |
1705 | sokoke_resolve_hostname (const gchar* hostname); |
1706 | |
1707 | -gboolean |
1708 | -sokoke_recursive_fork_protection (const gchar* uri, |
1709 | - gboolean set_uri); |
1710 | - |
1711 | void |
1712 | sokoke_widget_copy_clipboard (GtkWidget* widget, |
1713 | const gchar* text, |
1714 | |
1715 | === modified file 'po/POTFILES.in' |
1716 | --- po/POTFILES.in 2014-02-20 20:30:42 +0000 |
1717 | +++ po/POTFILES.in 2014-02-25 19:27:20 +0000 |
1718 | @@ -45,6 +45,7 @@ |
1719 | extensions/delayed-load.vala |
1720 | extensions/devpet.vala |
1721 | extensions/external-download-manager.vala |
1722 | +extensions/open-with.vala |
1723 | extensions/feed-panel/feed-atom.c |
1724 | extensions/feed-panel/feed-panel.c |
1725 | extensions/feed-panel/feed-parse.c |