Merge lp:~jeremywootten/pantheon-files/fix-1518692-right-click-samba-breadcrumb into lp:~elementary-apps/pantheon-files/trunk

Proposed by Jeremy Wootten
Status: Merged
Approved by: Cody Garver
Approved revision: 1990
Merged at revision: 1994
Proposed branch: lp:~jeremywootten/pantheon-files/fix-1518692-right-click-samba-breadcrumb
Merge into: lp:~elementary-apps/pantheon-files/trunk
Diff against target: 316 lines (+86/-65)
4 files modified
libcore/gof-directory-async.vala (+2/-1)
libwidgets/FileUtils.vala (+33/-17)
libwidgets/MimeActions.vala (+13/-16)
libwidgets/View/BreadcrumbsEntry.vala (+38/-31)
To merge this branch: bzr merge lp:~jeremywootten/pantheon-files/fix-1518692-right-click-samba-breadcrumb
Reviewer Review Type Date Requested Status
elementary Apps team Pending
Review via email: mp+278265@code.launchpad.net

Commit message

Fix breadcrumb context menu for uri schemes other than file:// (lp:1518692)

Description of the change

This branch fixes a number of issues relating to right-clicking on breadcrumbs representing remote shares, servers or protocols, including possible crashes.

TO TEST:
Navigate to shares and subfolders for the following protocols:
smb://
ftp://
sftp://
afp://
webdav://
webdavs://
trash://
mtp://
recent://

Right-click on breadcrumbs. There should be no crashes and at least the base context menu should appear and function normally and in most cases a 'folder' list is produced.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'libcore/gof-directory-async.vala'
2--- libcore/gof-directory-async.vala 2015-10-30 12:45:44 +0000
3+++ libcore/gof-directory-async.vala 2015-11-22 18:20:03 +0000
4@@ -874,8 +874,9 @@
5 return sorted_dirs;
6
7 foreach (var gof in file_hash.get_values()) {
8- if (!gof.is_hidden && gof.is_folder ())
9+ if (!gof.is_hidden && (gof.is_folder () || gof.is_smb_server ())) {
10 sorted_dirs.prepend (gof);
11+ }
12 }
13
14 sorted_dirs.sort (GOF.File.compare_by_display_name);
15
16=== modified file 'libwidgets/FileUtils.vala'
17--- libwidgets/FileUtils.vala 2015-10-09 11:12:36 +0000
18+++ libwidgets/FileUtils.vala 2015-11-22 18:20:03 +0000
19@@ -31,23 +31,20 @@
20 }
21
22 public string get_parent_path_from_path (string path) {
23- File? file = File.new_for_commandline_arg (path);
24- string parent_path = path;
25- if (file != null) {
26- File? parent = file.get_parent ();
27- if (parent != null) {
28- parent_path = parent.get_path ();
29- } else {
30- parent_path = construct_parent_path (path);
31- }
32- }
33+ /* We construct the parent path rather than use File.get_parent () as the latter gives odd
34+ * results for some gvfs files.
35+ */
36+ string parent_path = construct_parent_path (path);
37 if (parent_path == Marlin.FTP_URI ||
38- parent_path == Marlin.MTP_URI ||
39 parent_path == Marlin.SFTP_URI) {
40
41 parent_path = path;
42 }
43
44+ if (parent_path.has_prefix (Marlin.MTP_URI) && !valid_mtp_uri (parent_path)) {
45+ parent_path = path;
46+ }
47+
48 if (parent_path == Marlin.SMB_URI) {
49 parent_path = parent_path + Path.DIR_SEPARATOR_S;
50 }
51@@ -68,7 +65,7 @@
52 }
53 sb.erase (last_separator, -1);
54 string parent_path = sb.str + Path.DIR_SEPARATOR_S;
55- return parent_path;
56+ return sanitize_path (parent_path);
57 }
58
59 public bool path_has_parent (string new_path) {
60@@ -145,7 +142,7 @@
61 **/
62 public void split_protocol_from_path (string path, out string protocol, out string new_path) {
63 protocol = "";
64- new_path = path;
65+ new_path = path.dup ();
66
67 string[] explode_protocol = new_path.split ("://");
68 if (explode_protocol.length > 2) {
69@@ -155,12 +152,18 @@
70 if (explode_protocol.length > 1) {
71 if (explode_protocol[0] == "mtp") {
72 string[] explode_path = explode_protocol[1].split ("]", 2);
73- protocol = (explode_protocol[0] + "://" + explode_path[0] + "]").replace ("///", "//");
74- /* If path is being manually edited there may not be "]" so explode_path[1] may be null*/
75- new_path = explode_path [1] ?? "";
76+ if (explode_path[0] != null && explode_path[0].has_prefix ("[")) {
77+ protocol = (explode_protocol[0] + "://" + explode_path[0] + "]").replace ("///", "//");
78+ /* If path is being manually edited there may not be "]" so explode_path[1] may be null*/
79+ new_path = explode_path [1] ?? "";
80+ } else {
81+ warning ("Invalid mtp path");
82+ protocol = new_path.dup ();
83+ new_path = "/";
84+ }
85 } else {
86 protocol = explode_protocol[0] + "://";
87- new_path = explode_protocol[1];
88+ new_path = explode_protocol[1] ?? "";
89 }
90 } else {
91 protocol = Marlin.ROOT_FS_URI;
92@@ -173,4 +176,17 @@
93 new_path = Path.DIR_SEPARATOR_S + new_path;
94 }
95 }
96+
97+ private bool valid_mtp_uri (string uri) {
98+ if (!uri.contains (Marlin.MTP_URI)) {
99+ return false;
100+ }
101+ string[] explode_protocol = uri.split ("://",2);
102+ if (explode_protocol.length != 2 ||
103+ !explode_protocol[1].has_prefix ("[") ||
104+ !explode_protocol[1].contains ("]")) {
105+ return false;
106+ }
107+ return true;
108+ }
109 }
110
111=== modified file 'libwidgets/MimeActions.vala'
112--- libwidgets/MimeActions.vala 2015-10-09 11:12:36 +0000
113+++ libwidgets/MimeActions.vala 2015-11-22 18:20:03 +0000
114@@ -75,12 +75,13 @@
115 return app;
116 }
117
118- public static List<AppInfo>? get_applications_for_file (GOF.File file) {
119+ public static List<AppInfo> get_applications_for_file (GOF.File file) {
120+ List<AppInfo> result = null;
121 string? type = file.get_ftype ();
122 if (type == null)
123- return null;
124+ return result;
125
126- List<AppInfo> result = AppInfo.get_all_for_type (type);
127+ result = AppInfo.get_all_for_type (type);
128 string uri_scheme = file.location.get_uri_scheme ();
129
130 if (uri_scheme != null) {
131@@ -98,7 +99,7 @@
132 return result;
133 }
134
135- public static List<AppInfo>? get_applications_for_folder (GOF.File file) {
136+ public static List<AppInfo> get_applications_for_folder (GOF.File file) {
137 List<AppInfo> result = AppInfo.get_all_for_type (ContentType.get_mime_type ("inode/directory"));
138 string uri_scheme = file.location.get_uri_scheme ();
139
140@@ -110,10 +111,9 @@
141 }
142
143 if (!file_has_local_path (file))
144- filter_non_uri_apps (result);
145+ result = filter_non_uri_apps (result);
146
147 result.sort (application_compare_by_name);
148-
149 return result;
150 }
151
152@@ -189,17 +189,14 @@
153 return strcmp (a.get_id (), b.get_id ());
154 }
155
156- private static void filter_non_uri_apps (List<AppInfo> apps) {
157- List<AppInfo> non_uri_apps = null;
158-
159+ private static List<AppInfo> filter_non_uri_apps (List<AppInfo> apps) {
160+ List<AppInfo> uri_apps = null;
161 foreach (var app in apps) {
162- if (!app.supports_uris ())
163- non_uri_apps.append (app);
164- }
165-
166- foreach (var app in non_uri_apps) {
167- apps.remove (app);
168- }
169+ if (app.supports_uris ()) {
170+ uri_apps.append (app);
171+ }
172+ }
173+ return uri_apps;
174 }
175
176 private static List<AppInfo> intersect_application_lists (List<AppInfo> a, List<AppInfo> b) {
177
178=== modified file 'libwidgets/View/BreadcrumbsEntry.vala'
179--- libwidgets/View/BreadcrumbsEntry.vala 2015-11-15 17:46:29 +0000
180+++ libwidgets/View/BreadcrumbsEntry.vala 2015-11-22 18:20:03 +0000
181@@ -20,8 +20,11 @@
182
183 namespace Marlin.View.Chrome {
184 public class BreadcrumbsEntry : BasicBreadcrumbsEntry {
185+ /** Breadcrumb context menu support **/
186+ ulong files_menu_dir_handler_id = 0;
187+ Gtk.Menu menu;
188+
189 /** Completion support **/
190- ulong files_menu_handler_id = 0;
191 GOF.Directory.Async? current_completion_dir = null;
192 string completion_text = "";
193 bool autocompleted = false;
194@@ -360,8 +363,9 @@
195 /****************************/
196 private void load_right_click_menu (Gdk.EventButton event, BreadcrumbElement clicked_element) {
197 string path = get_path_from_element (clicked_element);
198- GLib.File loc = File.new_for_commandline_arg (path);
199- GLib.File? root = loc.get_parent ();
200+ GLib.File loc = PF.FileUtils.get_file_for_path (path);
201+ string parent_path = PF.FileUtils.get_parent_path_from_path (path);
202+ GLib.File? root = PF.FileUtils.get_file_for_path (parent_path);
203
204 var style_context = get_style_context ();
205 var padding = style_context.get_padding (style_context.get_state ());
206@@ -371,29 +375,34 @@
207 menu_x_root = event.x_root - event.x + clicked_element.x - BREAD_SPACING;
208
209 menu_y_root = event.y_root - event.y + get_allocated_height () - padding.bottom - padding.top;
210- var menu = new Gtk.Menu ();
211- menu.cancel.connect (() => { reset_elements_states (); });
212- menu.deactivate.connect (() => { reset_elements_states (); });
213+
214+ menu = new Gtk.Menu ();
215+ menu.cancel.connect (() => {reset_elements_states ();});
216+ menu.deactivate.connect (() => {reset_elements_states ();});
217+
218 build_base_menu (menu, loc);
219-
220 if (root != null) {
221- var files_menu = GOF.Directory.Async.from_gfile (root);
222- files_menu_handler_id = files_menu.done_loading.connect (() => {
223- append_subdirectories (menu, files_menu);
224+ var files_menu_dir = GOF.Directory.Async.from_gfile (root);
225+ files_menu_dir_handler_id = files_menu_dir.done_loading.connect (() => {
226+ append_subdirectories (menu, files_menu_dir);
227+ files_menu_dir.disconnect (files_menu_dir_handler_id);
228 });
229- files_menu.load ();
230+ files_menu_dir.load ();
231+ } else {
232+ warning ("Root directory null for %s", path);
233 }
234
235+ menu.show_all ();
236 menu.popup (null,
237 null,
238 right_click_menu_position_func,
239 0,
240- Gtk.get_current_event_time ());
241+ event.time);
242 }
243
244 private void build_base_menu (Gtk.Menu menu, GLib.File loc) {
245 /* First the "Open in new tab" menuitem is added to the menu. */
246- var path = loc.get_path ();
247+ var path = loc.get_uri ();
248 var menuitem_newtab = new Gtk.MenuItem.with_label (_("Open in New Tab"));
249 menu.append (menuitem_newtab);
250 menuitem_newtab.activate.connect (() => {
251@@ -409,17 +418,12 @@
252
253 menu.append (new Gtk.SeparatorMenuItem ());
254
255- /* Then the "Open with" menuitem is added to the menu. */
256- var menu_open_with = new Gtk.MenuItem.with_label (_("Open with"));
257- menu.append (menu_open_with);
258 var submenu_open_with = new Gtk.Menu ();
259- menu_open_with.set_submenu (submenu_open_with);
260-
261 var root = GOF.File.get (loc);
262 var app_info_list = Marlin.MimeActions.get_applications_for_folder (root);
263 bool at_least_one = false;
264 foreach (AppInfo app_info in app_info_list) {
265- if (app_info.get_executable () != Environment.get_application_name ()) {
266+ if (app_info != null && app_info.get_executable () != Environment.get_application_name ()) {
267 at_least_one = true;
268 var menu_item = new Gtk.ImageMenuItem.with_label (app_info.get_name ());
269 menu_item.set_data ("appinfo", app_info);
270@@ -436,8 +440,11 @@
271 submenu_open_with.append (menu_item);
272 }
273 }
274-
275 if (at_least_one) {
276+ /* Then the "Open with" menuitem is added to the menu. */
277+ var menu_open_with = new Gtk.MenuItem.with_label (_("Open with"));
278+ menu.append (menu_open_with);
279+ menu_open_with.set_submenu (submenu_open_with);
280 submenu_open_with.append (new Gtk.SeparatorMenuItem ());
281 }
282
283@@ -451,22 +458,22 @@
284 }
285
286 private void append_subdirectories (Gtk.Menu menu, GOF.Directory.Async dir) {
287- menu.append (new Gtk.SeparatorMenuItem ());
288-
289 /* Append list of directories at the same level */
290 unowned List<GOF.File>? sorted_dirs = dir.get_sorted_dirs ();
291- foreach (var gof in sorted_dirs) {
292- var menuitem = new Gtk.MenuItem.with_label(gof.get_display_name ());
293- menuitem.set_data ("location", gof.uri);
294- menu.append (menuitem);
295- menuitem.activate.connect (() => {
296- text = menu.get_active ().get_data ("location");
297- activate ();
298- });
299+ if (sorted_dirs.length () > 0) {
300+ menu.append (new Gtk.SeparatorMenuItem ());
301+ foreach (var gof in sorted_dirs) {
302+ var menuitem = new Gtk.MenuItem.with_label(gof.get_display_name ());
303+ menuitem.set_data ("location", gof.uri);
304+ menu.append (menuitem);
305+ menuitem.activate.connect (() => {
306+ text = menu.get_active ().get_data ("location");
307+ activate ();
308+ });
309+ }
310 }
311 menu.show_all ();
312 /* Release the Async directory as soon as possible */
313- dir.disconnect (files_menu_handler_id);
314 dir.cancel ();
315 dir = null;
316 }

Subscribers

People subscribed via source and target branches

to all changes: