Merge lp:~jeremywootten/pantheon-files/refactor-location-bar-preparation into lp:~elementary-apps/pantheon-files/trunk

Proposed by Jeremy Wootten
Status: Merged
Approved by: Cody Garver
Approved revision: 1958
Merged at revision: 1981
Proposed branch: lp:~jeremywootten/pantheon-files/refactor-location-bar-preparation
Merge into: lp:~elementary-apps/pantheon-files/trunk
Diff against target: 1080 lines (+435/-101)
21 files modified
filechooser-module/CMakeLists.txt (+2/-2)
libcore/AbstractSlot.vala (+1/-0)
libcore/CMakeLists.txt (+5/-0)
libcore/DndHandler.vala (+2/-2)
libcore/Enums.vala (+7/-0)
libwidgets/CMakeLists.txt (+17/-3)
libwidgets/Chrome/TopMenu.vala (+27/-13)
libwidgets/Chrome/ViewSwicher.vala (+0/-3)
libwidgets/Chrome/ViewWindowInterface.vala (+35/-0)
libwidgets/Chrome/Viewable.vala (+32/-0)
libwidgets/Dialogs/ChooseAppDialog.vala (+62/-0)
libwidgets/FileUtils.vala (+149/-0)
libwidgets/LocationBar.vala (+16/-18)
libwidgets/SearchResults.vala (+4/-9)
src/CMakeLists.txt (+1/-24)
src/View/AbstractDirectoryView.vala (+13/-19)
src/View/Miller.vala (+4/-0)
src/View/Sidebar.vala (+1/-1)
src/View/Slot.vala (+5/-0)
src/View/ViewContainer.vala (+8/-3)
src/View/Window.vala (+44/-4)
To merge this branch: bzr merge lp:~jeremywootten/pantheon-files/refactor-location-bar-preparation
Reviewer Review Type Date Requested Status
elementary Apps team Pending
Review via email: mp+273316@code.launchpad.net

Commit message

Move TopMenu widgets into libwidgets and some supporting classes into libcore

Description of the change

This branch is the first of a series aimed at refactoring the location bar in particular and the topmenu in general. The intention is to make these widgets self-contained and testable with defined interfaces. See lp:~jeremywootten/pantheon-files/experimental-refactor-fix-1461060-browser-like-search for the (almost) final version. The refactored location bar will have a more browser-like search behaviour. A separate LocationBarChooser widget will not be needed.

This branch moves the existing topmenu widgets into libwidgets but does not changes their behaviour. Consequential changes are made so that they still work.

The linked bug is fixed in passing.

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 'filechooser-module/CMakeLists.txt'
2--- filechooser-module/CMakeLists.txt 2015-10-01 08:43:51 +0000
3+++ filechooser-module/CMakeLists.txt 2015-11-14 13:22:20 +0000
4@@ -9,8 +9,8 @@
5
6 vala_precompile (VALA_C ${MODULE_NAME}
7 ${CMAKE_SOURCE_DIR}/libwidgets/Resources.vala
8- ${CMAKE_SOURCE_DIR}/libwidgets/LocationBar.vala
9- ${CMAKE_SOURCE_DIR}/libwidgets/BreadcrumbsElements.vala
10+ ${CMAKE_SOURCE_DIR}/libwidgets/Chrome/LocationBar.vala
11+ ${CMAKE_SOURCE_DIR}/libwidgets/Chrome/BreadcrumbsElements.vala
12 LocationBarChooser.vala
13 FileChooserDialog.vala
14 Plugin.vala
15
16=== modified file 'libcore/AbstractSlot.vala'
17--- libcore/AbstractSlot.vala 2015-07-24 08:01:21 +0000
18+++ libcore/AbstractSlot.vala 2015-11-14 13:22:20 +0000
19@@ -65,6 +65,7 @@
20
21 public abstract unowned GLib.List<unowned GOF.File>? get_selected_files ();
22 public abstract void set_active_state (bool set_active);
23+ public abstract void set_frozen_state (bool is_frozen);
24 public abstract unowned AbstractSlot? get_current_slot ();
25 public abstract void reload (bool non_local_only = false);
26 public abstract void grab_focus ();
27
28=== renamed file 'src/Bookmark.vala' => 'libcore/Bookmark.vala'
29=== renamed file 'src/BookmarkList.vala' => 'libcore/BookmarkList.vala'
30=== modified file 'libcore/CMakeLists.txt'
31--- libcore/CMakeLists.txt 2015-05-03 06:44:42 +0000
32+++ libcore/CMakeLists.txt 2015-11-14 13:22:20 +0000
33@@ -16,6 +16,11 @@
34 vala_precompile(VALA_C ${PKGNAME}
35 AbstractSidebar.vala
36 AbstractSlot.vala
37+ Bookmark.vala
38+ BookmarkList.vala
39+ DndHandler.vala
40+ Enums.vala
41+ MimeActions.vala
42 gof-callwhenready.vala
43 gof-directory-async.vala
44 gof-preferences.vala
45
46=== renamed file 'src/DndHandler.vala' => 'libcore/DndHandler.vala'
47--- src/DndHandler.vala 2015-07-03 13:48:11 +0000
48+++ libcore/DndHandler.vala 2015-11-14 13:22:20 +0000
49@@ -19,7 +19,7 @@
50 Authors: Jeremy Wootten <jeremy@elementaryos.org>
51 ***/
52
53-namespace FM {
54+namespace Marlin {
55 public class DndHandler : GLib.Object {
56 Gdk.DragAction chosen = Gdk.DragAction.DEFAULT;
57
58@@ -249,7 +249,7 @@
59 public bool selection_data_is_uri_list (Gtk.SelectionData selection_data, uint info, out string? text) {
60 text = null;
61
62- if (info == AbstractDirectoryView.TargetType.TEXT_URI_LIST &&
63+ if (info == Marlin.TargetType.TEXT_URI_LIST &&
64 selection_data.get_format () == 8 &&
65 selection_data.get_length () > 0) {
66
67
68=== renamed file 'src/Enums.vala' => 'libcore/Enums.vala'
69--- src/Enums.vala 2015-08-17 08:16:55 +0000
70+++ libcore/Enums.vala 2015-11-14 13:22:20 +0000
71@@ -142,4 +142,11 @@
72 assert_not_reached ();
73 }
74 }
75+
76+ public enum TargetType {
77+ STRING,
78+ TEXT_URI_LIST,
79+ XDND_DIRECT_SAVE0,
80+ NETSCAPE_URL
81+ }
82 }
83
84=== renamed file 'src/MimeActions.vala' => 'libcore/MimeActions.vala'
85=== added directory 'libwidgets/Animations'
86=== renamed file 'libwidgets/Animations.vala' => 'libwidgets/Animations/Animations.vala'
87=== modified file 'libwidgets/CMakeLists.txt'
88--- libwidgets/CMakeLists.txt 2015-11-05 11:26:27 +0000
89+++ libwidgets/CMakeLists.txt 2015-11-14 13:22:20 +0000
90@@ -33,25 +33,39 @@
91 )
92 link_directories(${LIB_PATHS})
93
94+include_directories (${CMAKE_CURRENT_SOURCE_DIR}/../libcore/)
95+include_directories (${CMAKE_CURRENT_BINARY_DIR}/../libcore/)
96 include_directories (${CMAKE_CURRENT_BINARY_DIR})
97 include_directories (${CMAKE_BINARY_DIR})
98
99 vala_precompile(VALA_C ${PKGNAME}
100+ FileUtils.vala
101 Resources.vala
102- Animations.vala
103 LocationBar.vala
104- BreadcrumbsElements.vala
105+ SearchResults.vala
106+ Animations/Animations.vala
107+ Chrome/LocationBar.vala
108+ Chrome/BreadcrumbsElements.vala
109+ Chrome/TopMenu.vala
110+ Chrome/ButtonWithMenu.vala
111+ Chrome/ViewSwicher.vala
112+ Chrome/XsEntry.vala
113+ Chrome/ImgEventBox.vala
114+ Chrome/Viewable.vala
115+ Dialogs/ChooseAppDialog.vala
116 Welcome.vala
117 PACKAGES
118 gtk+-3.0
119 granite
120 gee-0.8
121 posix
122+ zeitgeist-2.0
123 pantheon-files-core
124 pantheon-files-core-C
125 OPTIONS
126 --vapidir=${CMAKE_SOURCE_DIR}/libcore
127 --vapidir=${CMAKE_BINARY_DIR}/libcore
128+ --target-glib=2.32 # Needed for new thread API
129 --thread
130 GENERATE_VAPI
131 pantheon-files-widgets
132@@ -66,4 +80,4 @@
133 SOVERSION ${PANTHEON_FILES_WIDGETS_SOVERSION})
134
135 install (TARGETS ${PKGNAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/)
136-target_link_libraries(${PKGNAME} ${DEPS_LIBRARIES})
137+target_link_libraries(${PKGNAME} pantheon-files-core ${DEPS_LIBRARIES})
138
139=== added directory 'libwidgets/Chrome'
140=== renamed file 'libwidgets/BreadcrumbsElements.vala' => 'libwidgets/Chrome/BreadcrumbsElements.vala'
141=== renamed file 'src/View/Chrome/ButtonWithMenu.vala' => 'libwidgets/Chrome/ButtonWithMenu.vala'
142=== renamed file 'src/View/Chrome/ImgEventBox.vala' => 'libwidgets/Chrome/ImgEventBox.vala'
143=== renamed file 'libwidgets/LocationBar.vala' => 'libwidgets/Chrome/LocationBar.vala'
144=== renamed file 'src/View/Chrome/TopMenu.vala' => 'libwidgets/Chrome/TopMenu.vala'
145--- src/View/Chrome/TopMenu.vala 2015-05-03 06:44:42 +0000
146+++ libwidgets/Chrome/TopMenu.vala 2015-11-14 13:22:20 +0000
147@@ -26,7 +26,7 @@
148 public class TopMenu : Gtk.HeaderBar {
149 public ViewSwitcher? view_switcher;
150 public LocationBar? location_bar;
151- public Marlin.View.Window win;
152+ public Marlin.Viewable win;
153 public Chrome.ButtonWithMenu button_forward;
154 public Chrome.ButtonWithMenu button_back;
155
156@@ -40,7 +40,12 @@
157 button_forward.set_sensitive (can);
158 }
159
160- public TopMenu (Marlin.View.Window window) {
161+ public signal void focus_location_request (GLib.File? location);
162+ public signal void path_change_request (string path, Marlin.OpenFlag flag);
163+ public signal void escape ();
164+ public signal void reload_request ();
165+
166+ public TopMenu (ViewSwitcher switcher, Marlin.Viewable window) {
167 win = window;
168
169 button_back = new Marlin.View.Chrome.ButtonWithMenu.from_icon_name ("go-previous-symbolic", Gtk.IconSize.LARGE_TOOLBAR);
170@@ -62,27 +67,36 @@
171 back (1);
172 });
173
174-
175- view_switcher = new ViewSwitcher (win.win_actions.lookup_action ("view_mode") as GLib.SimpleAction);
176-
177+ view_switcher = switcher;
178+ view_switcher.margin_right = 20;
179 view_switcher.show_all ();
180 pack_start (view_switcher);
181
182 location_bar = new LocationBar (win);
183+ connect_location_bar_signals ();
184+ location_bar.show_all ();
185+ pack_start (location_bar);
186+
187+ show ();
188+ }
189+
190+ private void connect_location_bar_signals () {
191 location_bar.escape.connect (win.grab_focus);
192 location_bar.activate.connect (win.file_path_change_request);
193 location_bar.activate_alternate.connect ((file) => {
194 win.add_tab (file, Marlin.ViewMode.CURRENT);
195 });
196-
197-
198- location_bar.show_all ();
199- view_switcher.margin_right = 20;
200- pack_start (location_bar);
201-
202- show ();
203+ location_bar.reload_request.connect (() => {
204+ reload_request ();
205+ });
206+ location_bar.focus_in_event.connect ((event) => {
207+ return focus_in_event (event);
208+ });
209+ location_bar.focus_out_event.connect ((event) => {
210+ return focus_out_event (event);
211+ });
212 }
213-
214+
215 public void set_back_menu (Gee.List<string> path_list) {
216 /* Clear the back menu and re-add the correct entries. */
217 var back_menu = new Gtk.Menu ();
218
219=== renamed file 'src/View/Chrome/ViewSwicher.vala' => 'libwidgets/Chrome/ViewSwicher.vala'
220--- src/View/Chrome/ViewSwicher.vala 2015-05-03 06:44:42 +0000
221+++ libwidgets/Chrome/ViewSwicher.vala 2015-11-14 13:22:20 +0000
222@@ -48,7 +48,6 @@
223 break;
224 }
225
226- Preferences.settings.set_enum ("default-viewmode", value);
227 freeze_update = true;
228 switcher.set_active (active_index);
229 freeze_update = false;
230@@ -92,8 +91,6 @@
231 switcher.append (miller);
232 miller_sv = new GLib.Variant.string ("MILLER");
233
234- mode = (Marlin.ViewMode) Preferences.settings.get_enum("default-viewmode");
235-
236 switcher.mode_changed.connect ((image) => {
237 if (freeze_update) {
238 return;
239
240=== added file 'libwidgets/Chrome/ViewWindowInterface.vala'
241--- libwidgets/Chrome/ViewWindowInterface.vala 1970-01-01 00:00:00 +0000
242+++ libwidgets/Chrome/ViewWindowInterface.vala 2015-11-14 13:22:20 +0000
243@@ -0,0 +1,35 @@
244+/*
245+ * ViewWindowInterface.vala
246+ *
247+ * Copyright 2015 jeremy <jeremy@jeremy-W54-55SU1-SUW>
248+ *
249+ * This program is free software; you can redistribute it and/or modify
250+ * it under the terms of the GNU General Public License as published by
251+ * the Free Software Foundation; either version 2 of the License, or
252+ * (at your option) any later version.
253+ *
254+ * This program is distributed in the hope that it will be useful,
255+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
256+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
257+ * GNU General Public License for more details.
258+ *
259+ * You should have received a copy of the GNU General Public License
260+ * along with this program; if not, write to the Free Software
261+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
262+ * MA 02110-1301, USA.
263+ *
264+ *
265+ */
266+
267+
268+public interface Marlin.Viewable : Gtk.ApplicationWindow {
269+ public abstract new void grab_focus ();
270+ public abstract void file_path_change_request (GLib.File file);
271+ public abstract void focus_location_request (GLib.File loc);
272+ public abstract void add_tab (GLib.File location = GLib.File.new_for_commandline_arg (GLib.Environment.get_home_dir ()),
273+ Marlin.ViewMode mode = Marlin.ViewMode.PREFERRED);
274+ public abstract GLib.File get_current_location ();
275+ public abstract bool get_frozen ();
276+ public abstract void refresh_view ();
277+ public abstract void go_to_parent ();
278+}
279
280=== added file 'libwidgets/Chrome/Viewable.vala'
281--- libwidgets/Chrome/Viewable.vala 1970-01-01 00:00:00 +0000
282+++ libwidgets/Chrome/Viewable.vala 2015-11-14 13:22:20 +0000
283@@ -0,0 +1,32 @@
284+/***
285+ Copyright (C) 2015 elementary Developers
286+
287+ This program is free software: you can redistribute it and/or modify it
288+ under the terms of the GNU Lesser General Public License version 3, as published
289+ by the Free Software Foundation.
290+
291+ This program is distributed in the hope that it will be useful, but
292+ WITHOUT ANY WARRANTY; without even the implied warranties of
293+ MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
294+ PURPOSE. See the GNU General Public License for more details.
295+
296+ You should have received a copy of the GNU General Public License along
297+ with this program. If not, see <http://www.gnu.org/licenses/>.
298+
299+ Authors : Jeremy Wootten <jeremy@elementaryos.org>
300+***/
301+
302+
303+public interface Marlin.Viewable : Gtk.ApplicationWindow {
304+ public abstract new void grab_focus ();
305+ public abstract void file_path_change_request (GLib.File file);
306+ public abstract void focus_location_request (GLib.File? loc,
307+ bool select_in_current_only = false,
308+ bool unselect_others = false);
309+ public abstract void add_tab (GLib.File location = GLib.File.new_for_commandline_arg (GLib.Environment.get_home_dir ()),
310+ Marlin.ViewMode mode = Marlin.ViewMode.PREFERRED);
311+ public abstract GLib.File get_current_location ();
312+ public abstract bool get_frozen ();
313+ public abstract void refresh_view ();
314+ public abstract void go_to_parent ();
315+}
316
317=== renamed file 'src/View/Chrome/XsEntry.vala' => 'libwidgets/Chrome/XsEntry.vala'
318=== added directory 'libwidgets/Dialogs'
319=== added file 'libwidgets/Dialogs/ChooseAppDialog.vala'
320--- libwidgets/Dialogs/ChooseAppDialog.vala 1970-01-01 00:00:00 +0000
321+++ libwidgets/Dialogs/ChooseAppDialog.vala 2015-11-14 13:22:20 +0000
322@@ -0,0 +1,62 @@
323+/***
324+ Copyright (C) 2015 elementary Developers
325+
326+ This program is free software: you can redistribute it and/or modify it
327+ under the terms of the GNU Lesser General Public License version 3, as published
328+ by the Free Software Foundation.
329+
330+ This program is distributed in the hope that it will be useful, but
331+ WITHOUT ANY WARRANTY; without even the implied warranties of
332+ MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
333+ PURPOSE. See the GNU General Public License for more details.
334+
335+ You should have received a copy of the GNU General Public License along
336+ with this program. If not, see <http://www.gnu.org/licenses/>.
337+
338+ Authors : Jeremy Wootten <jeremy@elementaryos.org>
339+***/
340+
341+namespace PF {
342+ class ChooseAppDialog {
343+ Gtk.AppChooserDialog dialog;
344+ Gtk.CheckButton check_default;
345+ GLib.File file_to_open;
346+ public ChooseAppDialog (Gtk.Window parent, GLib.File file) {
347+ file_to_open = file;
348+ dialog = new Gtk.AppChooserDialog (parent,
349+ Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
350+ file_to_open);
351+
352+ dialog.set_deletable (false);
353+ var app_chooser = dialog.get_widget () as Gtk.AppChooserWidget;
354+ app_chooser.set_show_recommended (true);
355+ check_default = new Gtk.CheckButton.with_label (_("Set as default"));
356+ check_default.set_active (true);
357+ check_default.show ();
358+ var action_area = dialog.get_action_area () as Gtk.ButtonBox;
359+ action_area.add (check_default);
360+ action_area.set_child_secondary (check_default, true);
361+ dialog.show ();
362+ }
363+
364+ public AppInfo? get_app_info () {
365+ AppInfo? app = null;
366+ int response = dialog.run ();
367+ if (response == Gtk.ResponseType.OK) {
368+ app = dialog.get_app_info ();
369+ if (check_default.get_active ()) {
370+ try {
371+ var info = file_to_open.query_info (FileAttribute.STANDARD_CONTENT_TYPE,
372+ FileQueryInfoFlags.NONE, null);
373+ app.set_as_default_for_type (info.get_content_type ());
374+ }
375+ catch (GLib.Error error) {
376+ critical ("Could not set as default: %s", error.message);
377+ }
378+ }
379+ }
380+ dialog.destroy ();
381+ return app;
382+ }
383+ }
384+}
385
386=== added file 'libwidgets/FileUtils.vala'
387--- libwidgets/FileUtils.vala 1970-01-01 00:00:00 +0000
388+++ libwidgets/FileUtils.vala 2015-11-14 13:22:20 +0000
389@@ -0,0 +1,149 @@
390+namespace PF.FileUtils {
391+ const string reserved_chars = (GLib.Uri.RESERVED_CHARS_GENERIC_DELIMITERS + GLib.Uri.RESERVED_CHARS_SUBCOMPONENT_DELIMITERS + " ");
392+
393+ /**
394+ * Gets a properly escaped GLib.File for the given path
395+ **/
396+ public File? get_file_for_path (string? path) {
397+ File? file = null;
398+ string new_path = sanitize_path (path);
399+ if (path.length > 0) {
400+ file = File.new_for_commandline_arg (new_path);
401+ }
402+ return file;
403+ }
404+
405+ public string get_parent_path_from_path (string path) {
406+ File? file = File.new_for_commandline_arg (path);
407+ string parent_path = path;
408+ if (file != null) {
409+ File? parent = file.get_parent ();
410+ if (parent != null) {
411+ parent_path = parent.get_path ();
412+ } else {
413+ parent_path = construct_parent_path (path);
414+ }
415+ }
416+ return parent_path;
417+ }
418+
419+ private string construct_parent_path (string path) {
420+ if (path.length < 2) {
421+ return Path.DIR_SEPARATOR_S;
422+ }
423+ StringBuilder sb = new StringBuilder (path);
424+ if (path.has_suffix (Path.DIR_SEPARATOR_S)) {
425+ sb.erase (sb.str.length - 1,-1);
426+ }
427+ int last_separator = sb.str.last_index_of (Path.DIR_SEPARATOR_S);
428+ if (last_separator < 0) {
429+ last_separator = 0;
430+ }
431+ sb.erase (last_separator, -1);
432+ string parent_path = sb.str + Path.DIR_SEPARATOR_S;
433+ return parent_path;
434+ }
435+
436+ public bool path_has_parent (string new_path) {
437+ var file = File.new_for_commandline_arg (new_path);
438+ return file.get_parent () != null;
439+ }
440+
441+ public string? escape_uri (string uri, bool allow_utf8 = true) {
442+ reserved_chars.replace("#", "");
443+ return Uri.escape_string ((Uri.unescape_string (uri) ?? uri), reserved_chars, allow_utf8);
444+ }
445+
446+ /** Produce a valid unescaped path **/
447+ public string sanitize_path (string? p, string? cp = null) {
448+ string path = "";
449+ string scheme = "";
450+ string? current_path = null;
451+ string? current_scheme = null;
452+
453+ if (p == null || p == "") {
454+ return cp ?? "";
455+ }
456+ string? unescaped_p = Uri.unescape_string (p, null);
457+ if (unescaped_p == null) {
458+ unescaped_p = p;
459+ }
460+
461+ split_protocol_from_path (unescaped_p, out scheme, out path);
462+ path = path.strip ().replace ("//", "/");
463+ StringBuilder sb = new StringBuilder (path);
464+ if (cp != null) {
465+ split_protocol_from_path (cp, out current_scheme, out current_path);
466+ /* current_path is assumed already sanitized */
467+ if (scheme == "" && path.has_prefix ("/./")) {
468+ sb.erase (0, 2);
469+ sb.prepend (cp);
470+ split_protocol_from_path (sb.str , out scheme, out path);
471+ sb.assign (path);
472+ } else if (path.has_prefix ("/../")) {
473+ sb.erase (0, 3);
474+ sb.prepend (get_parent_path_from_path (current_path));
475+ sb.prepend (current_scheme);
476+ split_protocol_from_path (sb.str , out scheme, out path);
477+ sb.assign (path);
478+ }
479+ }
480+
481+ if (path.length > 0) {
482+ if (scheme == "" && path.has_prefix ("/~/")) {
483+ sb.erase (0, 2);
484+ sb.prepend (Environment.get_home_dir ());
485+ }
486+ }
487+
488+ path = sb.str;
489+ do {
490+ path = path.replace ("//", "/");
491+ } while (path.contains ("//"));
492+
493+ string new_path = (scheme + path).replace("////", "///");
494+
495+ if (new_path.length > 0) {
496+ if (scheme != Marlin.ROOT_FS_URI && path != "/") {
497+ new_path = new_path.replace ("///", "//");
498+ }
499+ new_path = new_path.replace("ssh:", "sftp:");
500+ }
501+
502+ return new_path;
503+ }
504+
505+ /** Splits the path into a protocol ending in '://" (unless it is file:// which is replaced by "")
506+ * and a path beginning "/".
507+ **/
508+ public void split_protocol_from_path (string path, out string protocol, out string new_path) {
509+ protocol = "";
510+ new_path = path;
511+
512+ string[] explode_protocol = new_path.split ("://");
513+ if (explode_protocol.length > 2) {
514+ new_path = "";
515+ return;
516+ }
517+ if (explode_protocol.length > 1) {
518+ if (explode_protocol[0] == "mtp") {
519+ string[] explode_path = explode_protocol[1].split ("]", 2);
520+ protocol = (explode_protocol[0] + "://" + explode_path[0] + "]").replace ("///", "//");
521+ /* If path is being manually edited there may not be "]" so explode_path[1] may be null*/
522+ new_path = explode_path [1] ?? "";
523+ } else {
524+ protocol = explode_protocol[0] + "://";
525+ new_path = explode_protocol[1];
526+ }
527+ } else {
528+ protocol = Marlin.ROOT_FS_URI;
529+ }
530+
531+ if (Marlin.ROOT_FS_URI.has_prefix (protocol)) {
532+ protocol = "";
533+ }
534+ if (!new_path.has_prefix (Path.DIR_SEPARATOR_S)) {
535+ new_path = Path.DIR_SEPARATOR_S + new_path;
536+ }
537+ }
538+}
539\ No newline at end of file
540
541=== renamed file 'src/View/LocationBar.vala' => 'libwidgets/LocationBar.vala'
542--- src/View/LocationBar.vala 2015-11-13 18:58:58 +0000
543+++ libwidgets/LocationBar.vala 2015-11-14 13:22:20 +0000
544@@ -31,7 +31,7 @@
545 if (new_path != null) {
546 _path = new_path;
547
548- if (!bread.is_focus && !win.freeze_view_changes) {
549+ if (!bread.is_focus && !win.get_frozen ()) {
550 bread.text = "";
551 bread.change_breadcrumbs (new_path);
552 }
553@@ -45,26 +45,26 @@
554 }
555 }
556
557- Marlin.View.Window win;
558+ Marlin.Viewable win;
559
560 public new signal void activate (GLib.File file);
561 public signal void activate_alternate (GLib.File file);
562 public signal void escape ();
563 public signal void search_mode_left ();
564-
565+ public signal void reload_request ();
566 public override void get_preferred_width (out int minimum_width, out int natural_width) {
567 minimum_width = -1;
568 natural_width = 3000;
569 }
570
571- public LocationBar (Marlin.View.Window win) {
572+ public LocationBar (Marlin.Viewable win) {
573 this.win = win;
574 bread = new Breadcrumbs (win);
575 bread.escape.connect (() => { escape(); });
576 bread.path_changed.connect (on_path_changed);
577
578 bread.reload.connect (() => {
579- win.win_actions.activate_action ("refresh", null);
580+ win.refresh_view ();
581 });
582
583 bread.activate_alternate.connect ((file) => { activate_alternate(file); });
584@@ -92,7 +92,8 @@
585 }
586
587 private void on_path_changed (File? file) {
588- if (file == null || win.freeze_view_changes)
589+ if (file == null || win.get_frozen ())
590+ if (file == null)
591 return;
592
593 win.grab_focus ();
594@@ -116,7 +117,7 @@
595
596 bool autocompleted = false;
597
598- Marlin.View.Window win;
599+ Marlin.Viewable win;
600
601 double menu_x_root;
602 double menu_y_root;
603@@ -124,14 +125,14 @@
604 private bool drop_data_ready = false; /* whether the drop data was received already */
605 private bool drop_occurred = false; /* whether the data was dropped */
606 private GLib.List<GLib.File> drop_file_list = null; /* the list of URIs in the drop data */
607- protected static FM.DndHandler dnd_handler = new FM.DndHandler ();
608+ protected static Marlin.DndHandler dnd_handler = new Marlin.DndHandler ();
609
610 Gdk.DragAction current_suggested_action = 0; /* No action */
611 Gdk.DragAction current_actions = 0; /* No action */
612
613 GOF.File? drop_target_file = null;
614
615- public Breadcrumbs (Marlin.View.Window win)
616+ public Breadcrumbs (Marlin.Viewable win)
617 {
618 this.win = win;
619 /* FIXME the string split of the path url is kinda too basic, we should use the Gile to split our uris and determine the protocol (if any) with g_uri_parse_scheme or g_file_get_uri_scheme */
620@@ -230,7 +231,7 @@
621 if (parent != null && file.get_uri () != parent.get_uri ())
622 change_breadcrumbs (parent.get_uri ());
623
624- win.go_up ();
625+ win.go_to_parent ();
626 grab_focus ();
627 });
628
629@@ -262,18 +263,15 @@
630
631 search_results.file_selected.connect ((file) => {
632 win.grab_focus ();
633- win.current_tab.focus_location (file);
634-
635- search_mode = false;
636- escape ();
637+ win.focus_location_request (file, false, true);
638 });
639
640 search_results.cursor_changed.connect ((file) => {
641- win.current_tab.focus_location_if_in_current_directory (file, true);
642+ win.focus_location_request (file, true, true);
643 });
644
645 search_results.first_match_found.connect ((file) => {
646- win.current_tab.focus_location_if_in_current_directory (file, true);
647+ win.focus_location_request (file, true, true);
648 });
649
650 search_results.hide.connect (() => {
651@@ -281,7 +279,7 @@
652 });
653
654 search_changed.connect ((text) => {
655- search_results.search (text, win.current_tab.location);
656+ search_results.search (text, win.get_current_location ());
657 });
658 }
659
660@@ -372,7 +370,7 @@
661
662 bool at_least_one = false;
663 foreach (AppInfo app_info in app_info_list) {
664- if (app_info.get_executable () != APP_NAME) {
665+ if (app_info.get_executable () != Environment.get_application_name ()) {
666 at_least_one = true;
667 var menu_item = new Gtk.ImageMenuItem.with_label (app_info.get_name ());
668 menu_item.set_data ("appinfo", app_info);
669
670=== renamed file 'src/View/SearchResults.vala' => 'libwidgets/SearchResults.vala'
671--- src/View/SearchResults.vala 2015-05-03 06:44:42 +0000
672+++ libwidgets/SearchResults.vala 2015-11-14 13:22:20 +0000
673@@ -101,8 +101,6 @@
674 Gtk.TreeModelFilter filter;
675 Gtk.ScrolledWindow scroll;
676
677- ulong cursor_changed_handler_id;
678-
679 public SearchResults (Gtk.Entry entry)
680 {
681 Object (entry: entry,
682@@ -210,7 +208,6 @@
683 Gtk.TreePath path;
684 Gtk.TreeIter iter;
685
686- SignalHandler.block (view, cursor_changed_handler_id);
687 view.get_path_at_pos ((int) e.x, (int) e.y, out path, null, null, null);
688
689 if (path != null) {
690@@ -218,12 +215,9 @@
691 filter.convert_iter_to_child_iter (out iter, iter);
692 accept (iter);
693 }
694- SignalHandler.unblock (view, cursor_changed_handler_id);
695 return true;
696 });
697
698- cursor_changed_handler_id = view.cursor_changed.connect (on_cursor_changed);
699-
700 key_release_event.connect (key_event);
701 key_press_event.connect (key_event);
702
703@@ -504,6 +498,7 @@
704 || is_grabbing)
705 return;
706
707+ view.cursor_changed.connect (on_cursor_changed);
708 resize_popup ();
709
710 var toplevel = entry.get_toplevel ();
711@@ -527,6 +522,7 @@
712
713 void popdown ()
714 {
715+ view.cursor_changed.disconnect (on_cursor_changed);
716 entry.reset_im_context ();
717
718 if (is_grabbing && device != null) {
719@@ -644,10 +640,9 @@
720 Gdk.beep ();
721 return;
722 }
723-
724+ /* The order of these two lines is critical to prevent unwanted cursor-changed signals */
725+ popdown ();
726 file_selected (file);
727-
728- popdown ();
729 }
730
731 File? get_file_at_iter (Gtk.TreeIter? iter)
732
733=== modified file 'src/CMakeLists.txt'
734--- src/CMakeLists.txt 2015-11-03 15:58:50 +0000
735+++ src/CMakeLists.txt 2015-11-14 13:22:20 +0000
736@@ -51,17 +51,12 @@
737 IF (WITH_UNITY AND UNITY_FOUND)
738 vala_precompile (VALA_C pantheon-files
739 Application.vala
740- Bookmark.vala
741- BookmarkList.vala
742 ConnectServerOperation.vala
743- DndHandler.vala
744- Enums.vala
745 AbstractEditableLabel.vala
746 SingleLineEditableLabel.vala
747 MultiLineEditableLabel.vala
748 main.vala
749 marlin-deep-count.vala
750- MimeActions.vala
751 ProgressInfoWidget.vala
752 ProgressUIHandler.vala
753 TextRenderer.vala
754@@ -75,21 +70,15 @@
755 View/IconSpinnerRenderer.vala
756 View/DirectoryNotFound.vala
757 View/AbstractDirectoryView.vala
758- View/SearchResults.vala
759 View/Window.vala
760 View/ViewContainer.vala
761 View/OverlayBar.vala
762 View/PropertiesWindow.vala
763 View/Browser.vala
764- View/LocationBar.vala
765 View/Sidebar.vala
766 View/Slot.vala
767 View/Miller.vala
768- View/Chrome/TopMenu.vala
769- View/Chrome/ButtonWithMenu.vala
770- View/Chrome/ViewSwicher.vala
771- View/Chrome/XsEntry.vala
772- View/Chrome/ImgEventBox.vala
773+
774 PACKAGES
775 gtk+-3.0
776 gio-2.0
777@@ -118,17 +107,12 @@
778 ELSE (WITH_UNITY AND UNITY_FOUND)
779 vala_precompile (VALA_C pantheon-files
780 Application.vala
781- Bookmark.vala
782- BookmarkList.vala
783 ConnectServerOperation.vala
784- DndHandler.vala
785- Enums.vala
786 AbstractEditableLabel.vala
787 SingleLineEditableLabel.vala
788 MultiLineEditableLabel.vala
789 main.vala
790 marlin-deep-count.vala
791- MimeActions.vala
792 ProgressInfoWidget.vala
793 ProgressUIHandler.vala
794 TextRenderer.vala
795@@ -137,7 +121,6 @@
796 View/IconView.vala
797 View/ListView.vala
798 ZeitgeistManager.vala
799- View/SearchResults.vala
800 View/DiskRenderer.vala
801 View/DirectoryNotFound.vala
802 View/AbstractDirectoryView.vala
803@@ -147,15 +130,9 @@
804 View/OverlayBar.vala
805 View/PropertiesWindow.vala
806 View/Browser.vala
807- View/LocationBar.vala
808 View/Sidebar.vala
809 View/Slot.vala
810 View/Miller.vala
811- View/Chrome/TopMenu.vala
812- View/Chrome/ButtonWithMenu.vala
813- View/Chrome/ViewSwicher.vala
814- View/Chrome/XsEntry.vala
815- View/Chrome/ImgEventBox.vala
816 PACKAGES
817 gtk+-3.0
818 gio-2.0
819
820=== modified file 'src/View/AbstractDirectoryView.vala'
821--- src/View/AbstractDirectoryView.vala 2015-09-21 13:50:55 +0000
822+++ src/View/AbstractDirectoryView.vala 2015-11-14 13:22:20 +0000
823@@ -25,13 +25,6 @@
824 namespace FM {
825 public abstract class AbstractDirectoryView : Gtk.ScrolledWindow {
826
827- public enum TargetType {
828- STRING,
829- TEXT_URI_LIST,
830- XDND_DIRECT_SAVE0,
831- NETSCAPE_URL
832- }
833-
834 protected enum ClickZone {
835 EXPANDER,
836 HELPER,
837@@ -46,15 +39,15 @@
838 const int MAX_TEMPLATES = 32;
839
840 const Gtk.TargetEntry [] drag_targets = {
841- {"text/plain", Gtk.TargetFlags.SAME_APP, TargetType.STRING},
842- {"text/uri-list", Gtk.TargetFlags.SAME_APP, TargetType.TEXT_URI_LIST}
843+ {"text/plain", Gtk.TargetFlags.SAME_APP, Marlin.TargetType.STRING},
844+ {"text/uri-list", Gtk.TargetFlags.SAME_APP, Marlin.TargetType.TEXT_URI_LIST}
845 };
846
847 const Gtk.TargetEntry [] drop_targets = {
848- {"text/uri-list", Gtk.TargetFlags.SAME_APP, TargetType.TEXT_URI_LIST},
849- {"text/uri-list", Gtk.TargetFlags.OTHER_APP, TargetType.TEXT_URI_LIST},
850- {"XdndDirectSave0", Gtk.TargetFlags.OTHER_APP, TargetType.XDND_DIRECT_SAVE0},
851- {"_NETSCAPE_URL", Gtk.TargetFlags.OTHER_APP, TargetType.NETSCAPE_URL}
852+ {"text/uri-list", Gtk.TargetFlags.SAME_APP, Marlin.TargetType.TEXT_URI_LIST},
853+ {"text/uri-list", Gtk.TargetFlags.OTHER_APP, Marlin.TargetType.TEXT_URI_LIST},
854+ {"XdndDirectSave0", Gtk.TargetFlags.OTHER_APP, Marlin.TargetType.XDND_DIRECT_SAVE0},
855+ {"_NETSCAPE_URL", Gtk.TargetFlags.OTHER_APP, Marlin.TargetType.NETSCAPE_URL}
856 };
857
858 const Gdk.DragAction file_drag_actions = (Gdk.DragAction.COPY | Gdk.DragAction.MOVE | Gdk.DragAction.LINK);
859@@ -235,7 +228,7 @@
860 protected Marlin.IconRenderer icon_renderer;
861 protected unowned Marlin.View.Slot slot;
862 protected unowned Marlin.View.Window window; /*For convenience - this can be derived from slot */
863- protected static DndHandler dnd_handler = new FM.DndHandler ();
864+ protected static Marlin.DndHandler dnd_handler = new Marlin.DndHandler ();
865
866 protected unowned Gtk.RecentManager recent;
867
868@@ -394,9 +387,10 @@
869 Gtk.TreePath path = model.get_path (iter);
870 if (path != null) {
871 select_path (path);
872- if (focus_location != null && focus_location.equal (file.location))
873+ if (focus_location != null && focus_location.equal (file.location)) {
874 /* set cursor and scroll to focus location*/
875- set_cursor (path, false, false, true);
876+ set_cursor (path, false, false, true);
877+ }
878 }
879 }
880 });
881@@ -1536,19 +1530,19 @@
882 slot.reload (true); /* non-local only */
883
884 switch (info) {
885- case TargetType.XDND_DIRECT_SAVE0:
886+ case Marlin.TargetType.XDND_DIRECT_SAVE0:
887 success = dnd_handler.handle_xdnddirectsave (context,
888 drop_target_file,
889 selection_data);
890 break;
891
892- case TargetType.NETSCAPE_URL:
893+ case Marlin.TargetType.NETSCAPE_URL:
894 success = dnd_handler.handle_netscape_url (context,
895 drop_target_file,
896 selection_data);
897 break;
898
899- case TargetType.TEXT_URI_LIST:
900+ case Marlin.TargetType.TEXT_URI_LIST:
901 if ((current_actions & file_drag_actions) != 0) {
902 if (selected_files != null)
903 unselect_all ();
904
905=== modified file 'src/View/Miller.vala'
906--- src/View/Miller.vala 2015-07-24 08:01:21 +0000
907+++ src/View/Miller.vala 2015-11-14 13:22:20 +0000
908@@ -428,5 +428,9 @@
909 public override bool set_all_selected (bool all) {
910 return ((Marlin.View.Slot)(current_slot)).set_all_selected (all);
911 }
912+
913+ public override void set_frozen_state (bool freeze) {
914+ current_slot.set_frozen_state (freeze);
915+ }
916 }
917 }
918
919=== modified file 'src/View/Sidebar.vala'
920--- src/View/Sidebar.vala 2015-11-03 15:58:50 +0000
921+++ src/View/Sidebar.vala 2015-11-14 13:22:20 +0000
922@@ -37,7 +37,7 @@
923 private const int ICON_XPAD = 6 + ROOT_INDENTATION_XPAD;
924 private const int PROP_0 = 0;
925
926- private static FM.DndHandler dnd_handler = new FM.DndHandler ();
927+ private static Marlin.DndHandler dnd_handler = new Marlin.DndHandler ();
928
929 Gtk.TreeView tree_view;
930 Gtk.CellRenderer indent_renderer;
931
932=== modified file 'src/View/Slot.vala'
933--- src/View/Slot.vala 2015-09-12 09:33:43 +0000
934+++ src/View/Slot.vala 2015-11-14 13:22:20 +0000
935@@ -351,5 +351,10 @@
936 directory.update_files ();
937 }
938 }
939+
940+ public override void set_frozen_state (bool freeze) {
941+ set_view_updates_frozen (freeze);
942+ frozen_changed (freeze);
943+ }
944 }
945 }
946
947=== modified file 'src/View/ViewContainer.vala'
948--- src/View/ViewContainer.vala 2015-11-05 11:26:27 +0000
949+++ src/View/ViewContainer.vala 2015-11-14 13:22:20 +0000
950@@ -396,11 +396,16 @@
951 if (aslot != null)
952 aslot.set_active_state (is_active);
953 }
954-
955+
956+ public void set_frozen_state (bool is_frozen) {
957+ var aslot = get_current_slot ();
958+ if (aslot != null)
959+ aslot.set_frozen_state (is_frozen);
960+ }
961+
962 public void focus_location (GLib.File? file,
963 bool select_in_current_only = false,
964 bool unselect_others = false) {
965-
966 if (unselect_others || file == null) {
967 get_current_slot ().set_all_selected (false);
968 selected_locations = null;
969@@ -417,7 +422,7 @@
970 File? parent = file.get_parent ();
971 if (parent != null && location.equal (file.get_parent ())) {
972 if (select_in_current_only || file.query_file_type (0) != FileType.DIRECTORY) {
973- var list = new List<File> ();
974+ var list = new List<File> ();
975 list.prepend (file);
976 get_current_slot ().select_glib_files (list, file);
977 } else
978
979=== modified file 'src/View/Window.vala'
980--- src/View/Window.vala 2015-08-17 14:25:36 +0000
981+++ src/View/Window.vala 2015-11-14 13:22:20 +0000
982@@ -23,7 +23,7 @@
983
984 namespace Marlin.View {
985
986- public class Window : Gtk.ApplicationWindow
987+ public class Window : Gtk.ApplicationWindow, Marlin.Viewable
988 {
989 static const GLib.ActionEntry [] win_entries = {
990 {"new_window", action_new_window},
991@@ -54,6 +54,7 @@
992 public Gtk.Builder ui;
993 private unowned UndoManager undo_manager;
994 public Chrome.TopMenu top_menu;
995+ public Chrome.ViewSwitcher view_switcher;
996 public Gtk.InfoBar info_bar;
997 public Granite.Widgets.DynamicNotebook tabs;
998 public Marlin.Places.Sidebar sidebar;
999@@ -167,11 +168,13 @@
1000 }
1001
1002 private void construct_top_menu () {
1003- top_menu = new Chrome.TopMenu(this);
1004+ view_switcher = new Chrome.ViewSwitcher (win_actions.lookup_action ("view_mode") as SimpleAction);
1005+ view_switcher.mode = Preferences.settings.get_enum("default-viewmode");
1006+ top_menu = new Chrome.TopMenu(view_switcher, this as Marlin.Viewable);
1007 top_menu.set_show_close_button (true);
1008 top_menu.set_custom_title (new Gtk.Label (null));
1009 }
1010-
1011+
1012 private void construct_info_bar () {
1013 info_bar = new Gtk.InfoBar ();
1014
1015@@ -210,6 +213,20 @@
1016
1017 top_menu.forward.connect (on_go_forward);
1018 top_menu.back.connect (on_go_back);
1019+ top_menu.focus_in_event.connect (() => {
1020+ current_tab.set_frozen_state (true);
1021+ return false;
1022+ });
1023+ top_menu.focus_out_event.connect (() => {
1024+ current_tab.set_frozen_state (false);
1025+ grab_focus ();
1026+ return true;
1027+ });
1028+ top_menu.escape.connect (() => {
1029+ current_tab.set_frozen_state (false);
1030+ grab_focus ();
1031+ });
1032+ top_menu.reload_request.connect (action_reload);
1033
1034 undo_manager.request_menu_update.connect (undo_redo_menu_update_callback);
1035
1036@@ -461,7 +478,7 @@
1037 (application as Marlin.Application).quit ();
1038 }
1039
1040- private void action_reload (GLib.SimpleAction action, GLib.Variant? param) {
1041+ private void action_reload () {
1042 /* avoid spawning reload when key kept pressed */
1043 if (tabs.current.working || !current_tab.ready)
1044 return;
1045@@ -928,6 +945,7 @@
1046 top_menu.set_back_menu (current_tab.get_go_back_path_list ());
1047 top_menu.set_forward_menu (current_tab.get_go_forward_path_list ());
1048 top_menu.view_switcher.mode = current_tab.view_mode;
1049+ Preferences.settings.set_enum ("default-viewmode", (int)(current_tab.view_mode));
1050 }
1051 }
1052
1053@@ -997,5 +1015,27 @@
1054 application.set_accels_for_action ("win.info::HELP", {"F1"});
1055 application.set_accels_for_action ("win.info::ABOUT", {"F3"});
1056 }
1057+
1058+ public bool get_frozen () {
1059+ return freeze_view_changes;
1060+ }
1061+
1062+ public GLib.File get_current_location () {
1063+ return current_tab.location;
1064+ }
1065+
1066+ public void refresh_view () {
1067+ action_reload ();
1068+ }
1069+
1070+ public void focus_location_request (GLib.File? loc,
1071+ bool select_in_current_only = false,
1072+ bool unselect_others = false) {
1073+ current_tab.focus_location (loc, select_in_current_only, unselect_others);
1074+ }
1075+
1076+ public void go_to_parent () {
1077+ go_up ();
1078+ }
1079 }
1080 }

Subscribers

People subscribed via source and target branches

to all changes: