Merge lp:~jeremywootten/pantheon-files/reload-icon-in-pathbar into lp:~elementary-apps/pantheon-files/trunk

Proposed by Jeremy Wootten
Status: Merged
Approved by: Cody Garver
Approved revision: 1689
Merged at revision: 1730
Proposed branch: lp:~jeremywootten/pantheon-files/reload-icon-in-pathbar
Merge into: lp:~elementary-apps/pantheon-files/trunk
Diff against target: 532 lines (+148/-80)
6 files modified
libcore/gof-directory-async.vala (+32/-15)
libcore/tests/marlincore-tests-file.c (+3/-3)
libwidgets/LocationBar.vala (+88/-41)
src/View/LocationBar.vala (+12/-13)
src/View/ViewContainer.vala (+5/-1)
src/View/Window.vala (+8/-7)
To merge this branch: bzr merge lp:~jeremywootten/pantheon-files/reload-icon-in-pathbar
Reviewer Review Type Date Requested Status
Danielle Foré Approve
PerfectCarl (community) Needs Fixing
Cody Garver (community) Needs Fixing
Review via email: mp+246055@code.launchpad.net

Commit message

Add a refresh icon to the pathbar

Description of the change

This branch places a refresh icon at the right hand end of the pathbar while in browsing mode. Clicking on the icon refreshes the current view.

To test:

FOR FUNCTION
1) Click on the refresh icon (either button) at the right-hand end of the pathbar. The current view refreshes (reloads). In Miller view, the active slot refreshes.

2) Hover over the icon - a tooltip appears (review wording).

3) Enter edit mode - the icon changes to the Navigate to icon.

4) Enter search mode - the icon disappears

FOR POSSIBLE REGRESSIONS
1) All pathbar functions work as normal.

2) All other ways of refreshing the view work as normal

3) Nothing bad happens if the icon is clicked when the view is not displaying a normal accessible folder.

To post a comment you must log in.
Revision history for this message
Cody Garver (codygarver) wrote :

Icon should probably be view-refresh-symbolic

String should probably be "Reload the current folder" if we want to match the wording of Midori's reload tooltip

Revision history for this message
Cody Garver (codygarver) wrote :

UX Team confirms that the icon should be "view-refresh-symbolic"

And the tooltip should be "Reload this folder"

review: Needs Fixing
1683. By Jeremy Wootten

Use 'view-refresh-symblic' icon and amend tooltip to 'Reload this folder'

1684. By Jeremy Wootten

Correct spelling mistake

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

The icon is now "view-refresh-symbolic" and the tooltip is "Reload this folder".

Revision history for this message
Danielle Foré (danrabbit) wrote :

Okay so if you do this:

this.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, "go-jump-symbolic");

Instead of this:

secondary_icon_pixbuf = arrow_img;

It doesn't get that weird screwed up hover effect

1685. By Jeremy Wootten

Do not use pixbufs for secondary icon, fix disappearing tooltip on secondary icon

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

Thanks Dan, I have implemented your fix for both secondary icons and removed unused code. Also fixed a bug I noticed where the tooltip on the secondary icon did not appear if you first hovered over the blank part of the pathbar. It appears calling set_tooltip_text ("") has the effect of turning off ALL the tooltips. Not sure if this is expected or a Gtk.Entry bug.

Revision history for this message
Danielle Foré (danrabbit) wrote :

* We shouldn't offer reload while the directory is currently reloading.

* There is a minor regression where the "go" arrow shows immediately instead of only after you've made a change to the path

review: Needs Fixing
1686. By Jeremy Wootten

Fix enter key press, hide reload icon if path unchanged, fix keyboard reload while in edit mode, fix regression in completion

1687. By Jeremy Wootten

Fix error message re atk_object, remove unneeded entry icon code

Revision history for this message
PerfectCarl (name-is-carl) wrote :

Is this branch related/touching code pertaining to https://code.launchpad.net/~jeremywootten/pantheon-files/fix-enter-in-pathbar ?

Also there is MERGE strings in the code: bzr merge failed it seems.

Please add a comment when hiding inherited methods (instead of overriding) as it is unusual and could be viewed as an error.

review: Needs Fixing
1688. By Jeremy Wootten

Merge trunk to rev 1723

1689. By Jeremy Wootten

Avoid hiding Gtk.Widget.key_press_event

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

1) Trunk merged and conflict resolved
2) Code refactored to avoid hiding Gtk Widget method.

Revision history for this message
Danielle Foré (danrabbit) :
review: Approve

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 2014-12-26 12:01:20 +0000
3+++ libcore/gof-directory-async.vala 2015-01-26 10:59:47 +0000
4@@ -129,7 +129,16 @@
5 state = State.NOT_LOADED;
6 }
7
8- public void load () {
9+ public delegate void GOFFileLoadedFunc (GOF.File file);
10+
11+ /** Views call the following function with null parameter - file_loaded and done_loading
12+ * signals are emitted and cause the view and view container to update.
13+ *
14+ * LocationBar calls this function, with a callback, on its own Async instances in order
15+ * to perform filename completion.- Emitting a done_loaded signal in that case would cause
16+ * the premature ending of text entry.
17+ **/
18+ public void load (GOFFileLoadedFunc? file_loaded_func = null) {
19 cancellable.reset ();
20 longest_file_name = "";
21
22@@ -141,15 +150,17 @@
23 if (state == State.LOADING)
24 clear_directory_info ();
25
26- list_directory.begin ();
27+ list_directory.begin (file_loaded_func);
28
29- try {
30- monitor = location.monitor_directory (0);
31- monitor.rate_limit = 100;
32- monitor.changed.connect (directory_changed);
33- } catch (IOError e) {
34- if (!(e is IOError.NOT_MOUNTED)) {
35- warning ("directory monitor failed: %s %s", e.message, file.uri);
36+ if (file_loaded_func == null) {
37+ try {
38+ monitor = location.monitor_directory (0);
39+ monitor.rate_limit = 100;
40+ monitor.changed.connect (directory_changed);
41+ } catch (IOError e) {
42+ if (!(e is IOError.NOT_MOUNTED)) {
43+ warning ("directory monitor failed: %s %s", e.message, file.uri);
44+ }
45 }
46 }
47 } else {
48@@ -164,12 +175,15 @@
49 if (track_longest_name)
50 update_longest_file_name (gof);
51
52- file_loaded (gof);
53+ if (file_loaded_func == null)
54+ file_loaded (gof);
55+ else
56+ file_loaded_func (gof);
57 }
58 }
59 }
60
61- if (!cancellable.is_cancelled ())
62+ if (file_loaded_func == null && !cancellable.is_cancelled ())
63 done_loading ();
64 }
65 }
66@@ -234,7 +248,7 @@
67 yield query_info_async (file, file_info_available);
68 }
69
70- private async void list_directory () {
71+ private async void list_directory (GOFFileLoadedFunc? file_loaded_func = null) {
72 file.exists = true;
73 files_count = 0;
74 state = State.LOADING;
75@@ -267,12 +281,16 @@
76 if (track_longest_name)
77 update_longest_file_name (gof);
78
79- file_loaded (gof);
80+ if (file_loaded_func == null)
81+ file_loaded (gof);
82+ else
83+ file_loaded_func (gof);
84 }
85
86 files_count++;
87 }
88 }
89+
90 if (state == State.LOADING) {
91 file.exists = true;
92 state = State.LOADED;
93@@ -293,8 +311,7 @@
94 else if (err is IOError.NOT_MOUNTED)
95 file.is_mounted = false;
96 }
97-
98- if (!cancellable.is_cancelled ())
99+ if (file_loaded_func == null && !cancellable.is_cancelled ())
100 done_loading ();
101 }
102
103
104=== modified file 'libcore/tests/marlincore-tests-file.c'
105--- libcore/tests/marlincore-tests-file.c 2014-08-05 22:40:12 +0000
106+++ libcore/tests/marlincore-tests-file.c 2015-01-26 10:59:47 +0000
107@@ -89,7 +89,7 @@
108 GOFDirectoryAsync *dir2;
109 dir2 = gof_directory_async_from_file(dir->file);
110 g_signal_connect(dir2, "done_loading", (GCallback) second_load_done, NULL);
111- gof_directory_async_load(dir2);
112+ gof_directory_async_load(dir2, NULL, NULL);
113
114 /* free previously allocated dir */
115 g_object_unref (dir);
116@@ -107,11 +107,11 @@
117
118 dir = gof_directory_async_from_gfile(g_file_new_for_path("/tmp/marlin-test"));
119 g_signal_connect(dir, "done_loading", (GCallback) first_load_done, NULL);
120- gof_directory_async_load(dir);
121+ gof_directory_async_load(dir, NULL, NULL);
122
123 /*dir2 = gof_directory_async_from_gfile(g_file_new_for_path("/tmp/marlin-test"));
124 g_signal_connect(dir2, "done_loading", (GCallback) second_load_done, NULL);
125- gof_directory_async_load(dir2);*/
126+ gof_directory_async_load(dir2, NULL, NULL);*/
127
128 //GOFFile *f1 = gof_file_get (g_file_new_for_path("/tmp/marlin-test/a"));
129
130
131=== modified file 'libwidgets/LocationBar.vala'
132--- libwidgets/LocationBar.vala 2014-11-21 10:02:45 +0000
133+++ libwidgets/LocationBar.vala 2015-01-26 10:59:47 +0000
134@@ -57,7 +57,11 @@
135
136 _search_mode = value;
137
138- primary_icon_name = _search_mode ? "edit-find-symbolic" : null;
139+ if (_search_mode) {
140+ primary_icon_name = "edit-find-symbolic";
141+ show_refresh_icon (false);
142+ } else
143+ primary_icon_name = null;
144
145 grab_focus ();
146 }
147@@ -66,10 +70,8 @@
148 protected string text_completion = "";
149 protected bool multiple_completions = false;
150 protected bool text_changed = false;
151- protected bool arrow_hovered = false;
152 protected bool ignore_focus_in = false;
153 protected bool ignore_change = false;
154- private Gdk.Pixbuf arrow_img;
155
156 /* if we must display the BreadcrumbsElement which are in newbreads. */
157 bool view_old = false;
158@@ -97,10 +99,12 @@
159 public signal void path_changed (File file);
160 public signal void need_completion ();
161 public signal void search_changed (string text);
162+ public signal void reload ();
163
164 List<IconDirectory?> icons;
165
166 string current_path = "";
167+ string refresh_tip = _("Reload this folder");
168
169 int selected = -1;
170 int space_breads = 12;
171@@ -123,13 +127,6 @@
172 construct {
173 icon_factory = Granite.Services.IconFactory.get_default ();
174 icons = new List<IconDirectory?> ();
175-
176- /* Load arrow image */
177- try {
178- arrow_img = Gtk.IconTheme.get_default ().load_icon ("go-jump-symbolic", 16, Gtk.IconLookupFlags.GENERIC_FALLBACK);
179- } catch (Error err) {
180- stderr.printf ("Unable to load home icon: %s", err.message);
181- }
182
183 button_context = get_style_context ();
184 button_context.add_class ("button");
185@@ -155,8 +152,10 @@
186 secondary_icon_sensitive = true;
187 truncate_multiline = true;
188 activate.connect (on_activate);
189- icon_press.connect (on_activate);
190- motion_notify_event.connect (on_motion_notify);
191+ button_press_event.connect (on_button_press_event);
192+ button_release_event.connect (on_button_release_event);
193+ icon_press.connect (on_icon_press);
194+ motion_notify_event.connect_after (after_motion_notify);
195 focus_in_event.connect (on_focus_in);
196 focus_out_event.connect (on_focus_out);
197 grab_focus.connect_after (on_grab_focus);
198@@ -170,8 +169,8 @@
199 drag_data_received.connect (on_drag_data_received);
200 drag_drop.connect (on_drag_drop);
201 }
202-
203- public override bool key_press_event (Gdk.EventKey event) {
204+
205+ public bool on_key_press_event (Gdk.EventKey event) {
206 switch (event.keyval) {
207 case Gdk.Key.KP_Tab:
208 case Gdk.Key.Tab:
209@@ -195,7 +194,12 @@
210 return base.key_press_event (event);
211 }
212
213- public override bool button_press_event (Gdk.EventButton event) {
214+ public bool on_button_press_event (Gdk.EventButton event) {
215+ /* We need to distinguish whether the event comes from one of the icons.
216+ * There doesn't seem to be a way of doing this directly so we check the window width */
217+ if (event.window.get_width () < 24)
218+ return false;
219+
220 if (is_focus)
221 return base.button_press_event (event);
222
223@@ -233,7 +237,12 @@
224 return true;
225 }
226
227- public override bool button_release_event (Gdk.EventButton event) {
228+ public bool on_button_release_event (Gdk.EventButton event) {
229+ /* We need to distinguish whether the event comes from one of the icons.
230+ * There doesn't seem to be a way of doing this directly so we check the window width */
231+ if (event.window.get_width () < 24)
232+ return false;
233+
234 reset_elements_states ();
235
236 if (timeout != -1) {
237@@ -244,6 +253,7 @@
238 if (is_focus)
239 return base.button_release_event (event);
240
241+
242 if (event.button == 1) {
243 var el = get_element_from_coordinates ((int) event.x, (int) event.y);
244 if (el != null) {
245@@ -256,7 +266,16 @@
246
247 return base.button_release_event (event);
248 }
249-
250+
251+ public void on_icon_press (Gtk.EntryIconPosition pos, Gdk.Event event) {
252+ if (pos == Gtk.EntryIconPosition.SECONDARY) {
253+ if (is_focus)
254+ on_activate ();
255+ else
256+ reload ();
257+ }
258+ }
259+
260 void on_change () {
261 if (search_mode) {
262 search_changed (text);
263@@ -268,19 +287,24 @@
264 return;
265 }
266
267- set_entry_icon (true, (text.length > 0) ? "Navigate to: " + text : "");
268+ show_navigate_icon ();
269 text_completion = "";
270 need_completion ();
271 }
272
273- bool on_motion_notify (Gdk.EventMotion event) {
274+ bool after_motion_notify (Gdk.EventMotion event) {
275+
276+ if (is_focus)
277+ return false;
278+
279 int x = (int) event.x;
280 double x_render = 0;
281 double x_previous = -10;
282 set_tooltip_text ("");
283-
284- if (is_focus)
285- return base.motion_notify_event (event);
286+ /* We must reset the icon tooltip as the above line turns all tooltips off */
287+ set_icon_tooltip_text (Gtk.EntryIconPosition.SECONDARY, refresh_tip);
288+
289+
290
291 foreach (BreadcrumbsElement element in elements) {
292 if (element.display) {
293@@ -299,22 +323,25 @@
294 set_entry_cursor (new Gdk.Cursor (Gdk.CursorType.ARROW));
295 else
296 set_entry_cursor (null);
297-
298- return base.motion_notify_event (event);
299+
300+ return false;
301 }
302
303 bool on_focus_out (Gdk.EventFocus event) {
304- if (is_focus) {
305+ if (is_focus)
306 ignore_focus_in = true;
307- return base.focus_out_event (event);
308+ else {
309+ reset ();
310+ show_refresh_icon (true);
311 }
312-
313+
314+ return base.focus_out_event (event);
315+ }
316+
317+ void reset () {
318 ignore_focus_in = false;
319- set_entry_icon (false);
320 set_entry_text ("");
321 search_mode = false;
322-
323- return base.focus_out_event (event);
324 }
325
326 bool on_focus_in (Gdk.EventFocus event) {
327@@ -323,10 +350,11 @@
328
329 if (search_mode)
330 set_entry_text ("");
331- else
332- set_entry_text (sanitise_path (GLib.Uri.unescape_string (get_elements_path ())));
333-
334-
335+ else {
336+ current_path = sanitise_path (GLib.Uri.unescape_string (get_elements_path ()));
337+ set_entry_text (current_path);
338+ show_navigate_icon ();
339+ }
340 return base.focus_in_event (event);
341 }
342
343@@ -343,10 +371,25 @@
344 }
345
346 void on_activate () {
347- path_changed (get_file_for_path (text + text_completion));
348+ string path = text + text_completion;
349+ path_changed (get_file_for_path (path));
350 text_completion = "";
351 }
352
353+ public void show_refresh_icon (bool show = true) {
354+ /* Cancel any editing or search if refresh icon is to be shown */
355+ if (show) {
356+ reset ();
357+ escape ();
358+ }
359+
360+ set_entry_secondary_icon (false, show);
361+ }
362+
363+ public void show_navigate_icon (bool show = true) {
364+ set_entry_secondary_icon (true, show && text != current_path);
365+ }
366+
367 protected abstract void on_drag_leave (Gdk.DragContext drag_context, uint time);
368
369 protected abstract void on_drag_data_received (Gdk.DragContext context,
370@@ -406,12 +449,16 @@
371 get_window ().get_children ().nth_data (13).set_cursor (cursor ?? new Gdk.Cursor (Gdk.CursorType.XTERM));
372 }
373
374- public void set_entry_icon (bool active, string? tooltip = null) {
375- if (!active)
376+ public void set_entry_secondary_icon (bool active, bool visible) {
377+ if (!visible)
378 secondary_icon_pixbuf = null;
379- else {
380- secondary_icon_pixbuf = arrow_img;
381- secondary_icon_tooltip_text = tooltip;
382+ else if (!active) {
383+ set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, "view-refresh-symbolic");
384+ set_icon_tooltip_text (Gtk.EntryIconPosition.SECONDARY, refresh_tip);
385+ } else {
386+ set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, "go-jump-symbolic");
387+ var tooltip = (text.length > 0) ? (_("Navigate to %s")).printf (text) : "";
388+ set_icon_tooltip_text (Gtk.EntryIconPosition.SECONDARY, tooltip);
389 }
390 }
391
392@@ -809,7 +856,7 @@
393 Pango.cairo_show_layout (cr, layout);
394 }
395 }
396-
397+
398 return true;
399 }
400
401
402=== modified file 'src/View/LocationBar.vala'
403--- src/View/LocationBar.vala 2014-12-01 12:20:37 +0000
404+++ src/View/LocationBar.vala 2015-01-26 10:59:47 +0000
405@@ -62,8 +62,12 @@
406 this.win = win;
407 bread = new Breadcrumbs (win);
408 bread.escape.connect (() => { escape(); });
409-
410 bread.path_changed.connect (on_path_changed);
411+
412+ bread.reload.connect (() => {
413+ win.win_actions.activate_action ("refresh", null);
414+ });
415+
416 bread.activate_alternate.connect ((file) => { activate_alternate(file); });
417 bread.notify["search-mode"].connect (() => {
418 if (!bread.search_mode) {
419@@ -78,6 +82,7 @@
420 margin_bottom = 4;
421 margin_left = 3;
422
423+ bread.set_entry_secondary_icon (false, true);
424 pack_start (bread, true, true, 0);
425 }
426
427@@ -331,17 +336,10 @@
428 file = file.get_parent ();
429 else
430 return;
431-
432- var directory = file;
433- var files_cache = files;
434
435- files = GOF.Directory.Async.from_gfile (directory);
436+ files = GOF.Directory.Async.from_gfile (file);
437 if (files.file.exists) {
438- /* Verify that we got a new instance of files so we do not double up events */
439- if (files_cache != files)
440- files.file_loaded.connect (on_file_loaded);
441-
442- files.load ();
443+ files.load (on_file_loaded);
444 }
445 }
446
447@@ -406,7 +404,6 @@
448 menu_open_with.set_submenu (submenu_open_with);
449 menu.append (new Gtk.SeparatorMenuItem ());
450
451-
452 unowned List<GOF.File>? sorted_dirs = files_menu.get_sorted_dirs ();
453 foreach (var gof in sorted_dirs) {
454 var menuitem = new Gtk.MenuItem.with_label(gof.get_display_name ());
455@@ -418,6 +415,9 @@
456 });
457 }
458 menu.show_all ();
459+ /* Release the Async directory as soon as possible */
460+ files_menu.done_loading.disconnect (on_files_loaded_menu);
461+ files_menu = null;
462 }
463
464 private void launch_uri_with_app (AppInfo app, string uri) {
465@@ -437,9 +437,8 @@
466 menu = new Gtk.Menu ();
467 menu.cancel.connect (() => { reset_elements_states (); });
468 menu.deactivate.connect (() => { reset_elements_states (); });
469+ /* current_right_click_root is parent of the directory named on the breadcrumb. */
470 var directory = File.new_for_uri (current_right_click_root);
471- if (files_menu != null)
472- files_menu.done_loading.disconnect (on_files_loaded_menu);
473 files_menu = GOF.Directory.Async.from_gfile (directory);
474 files_menu.done_loading.connect (on_files_loaded_menu);
475 files_menu.load ();
476
477=== modified file 'src/View/ViewContainer.vala'
478--- src/View/ViewContainer.vala 2014-12-28 09:23:52 +0000
479+++ src/View/ViewContainer.vala 2015-01-26 10:59:47 +0000
480@@ -331,6 +331,10 @@
481 if (file == null || location.equal (file))
482 return;
483
484+ var filetype = file.query_file_type (0);
485+ if (filetype == FileType.UNKNOWN)
486+ return;
487+
488 GLib.File? loc = null;
489 File? parent = file.get_parent ();
490 if (parent != null && location.equal (file.get_parent ())) {
491@@ -341,7 +345,7 @@
492 } else
493 loc = file;
494 } else if (!select_in_current_only) {
495- if (file.query_file_type (0) == FileType.DIRECTORY)
496+ if (filetype == FileType.DIRECTORY)
497 loc = file;
498 else if (parent != null) {
499 loc = parent;
500
501=== modified file 'src/View/Window.vala'
502--- src/View/Window.vala 2015-01-17 18:42:21 +0000
503+++ src/View/Window.vala 2015-01-26 10:59:47 +0000
504@@ -214,13 +214,6 @@
505
506 undo_manager.request_menu_update.connect (undo_redo_menu_update_callback);
507
508- key_press_event.connect ((event) => {
509- if (top_menu.location_bar.bread.is_focus)
510- return top_menu.location_bar.bread.key_press_event (event);
511-
512- return false;
513- });
514-
515 button_press_event.connect (on_button_press_event);
516
517 window_state_event.connect ((event) => {
518@@ -375,6 +368,14 @@
519
520 content.loading.connect ((is_loading) => {
521 tab.working = is_loading;
522+ top_menu.location_bar.bread.show_refresh_icon (!is_loading);
523+ });
524+
525+ key_press_event.connect ((event) => {
526+ if (top_menu.location_bar.bread.is_focus)
527+ return top_menu.location_bar.bread.on_key_press_event (event);
528+
529+ return false;
530 });
531
532 change_tab ((int)tabs.insert_tab (tab, -1));

Subscribers

People subscribed via source and target branches

to all changes: