Merge lp:~mefrio-g/pantheon-files/split-view into lp:~elementary-apps/pantheon-files/trunk

Proposed by Mario Guerriero
Status: Rejected
Rejected by: Jeremy Wootten
Proposed branch: lp:~mefrio-g/pantheon-files/split-view
Merge into: lp:~elementary-apps/pantheon-files/trunk
Diff against target: 463 lines (+227/-71)
8 files modified
src/CMakeLists.txt (+2/-0)
src/View/Chrome/TopMenu.vala (+3/-2)
src/View/FilesView.vala (+67/-0)
src/View/LocationBar.vala (+1/-1)
src/View/SplitView.vala (+108/-0)
src/View/ViewContainer.vala (+1/-0)
src/View/Window.vala (+44/-68)
src/pantheon-files-ui.xml (+1/-0)
To merge this branch: bzr merge lp:~mefrio-g/pantheon-files/split-view
Reviewer Review Type Date Requested Status
Danielle Foré Needs Fixing
Cody Garver (community) Needs Fixing
Julián Unrrein Pending
Review via email: mp+169690@code.launchpad.net

Commit message

Implement Split View which can be accessed by hitting F3 key fix bug #1078973.

Description of the change

This branch contains an implementation of a Split View which can be used by hitting F3 key.

To post a comment you must log in.
Revision history for this message
Julián Unrrein (junrrein) wrote :

Wow Mario! This is a great contribution!

The Split View isn't added when I hit F3. Nothing happens.

Notice that, since Files doesn't have an appmenu anymore, it would be necessary to also use the F3 key to close the current view. Skimming through you changes, that doesn't seem to be implemented.

Revision history for this message
Julián Unrrein (junrrein) wrote :

Wow Mario! This is a great contribution!

The Split View isn't added when I hit F3. Nothing happens.

Notice that, since Files doesn't have an appmenu anymore, it would be necessary to also use the F3 key to close the current view. Skimming through you changes, that doesn't seem to be implemented.

Revision history for this message
Julián Unrrein (junrrein) wrote :
Revision history for this message
Julián Unrrein (junrrein) wrote :

Disregard my last comment. I haven't tested that branch before submitting for merging, and it didn't work. A slip up.

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

Design team Approves this new feature.

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

When the code is deemed ready, this will be merged AFTER final Luna release of Files, to avoid any bugs it could introduce.

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

Changing to Needs Fixing because I stupidly thought Launchpad would report me as clicking the design team's review link...

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

I have a few issues:

* View switching seems to only work for the right pane
* There's a duplicate overlay statusbar
* Should we use ThinPane here?
* Close the last tab on the left view then hit F3 again: crash.
* Source List affects the right pane instead of last selected pane
* Select an item inside each pane and copy, then cd. pasting doesn't seem to work correctly.
* Hitting F3 again creates a new tab instead of closing the right pane

review: Needs Fixing
Revision history for this message
Mario Guerriero (mefrio-g) wrote :

Julian you have to install this branch so that you will install the pantheon-files.xml file containing the F3 action.

Hey Daniel I think ThinPaned is not necessary there. It's better to be able to re-size the views. SourceList affects the last used pane e.g. the last pane which switched folder. I don't think that hitting F3 again should close the right pane as it would be a contradiction that F3 creates and destroys a pane. The rest are bugs :)

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

Hey Mario, you know that thin pane has an invisible resize area that's the same size as hpane right? :p

Revision history for this message
Mario Guerriero (mefrio-g) wrote :

Yes but in hpane it is more visible :)

Revision history for this message
Julián Unrrein (junrrein) wrote :

When closing the split view and hovering over items in the view that is left, console output throws this http://pastebin.com/D4TLzAuv every time you hover over an item.

This can devolve in a crash: http://pastebin.com/9T48hGs8. I got this crash when hovering over an item, but none in particular. I can't reproduce this with a definite series of steps, but if I flail the mouse some time (not much) I can get it to crash.

Revision history for this message
Julián Unrrein (junrrein) wrote :

The sidebar (which is not a SourceList by the way, it is just styled as one) should really affect the last focused view. You can even open some files or view the properties in the other view (the one that didn't change its directory last) and still the sidebar will affect the last changed view. I don't think this is desirable.

Revision history for this message
Julián Unrrein (junrrein) wrote :

After opening the split view, right clicking on items in the left view works erratically. Most of the times options pertaining to the item don't show up or are disabled (contracts, open, cut/copy/paste). Sometimes it works correctly. Sometimes a menu doesn't show up.

Console output when pressing right-click: http://pastebin.com/d1RpQbu6.

Revision history for this message
Julián Unrrein (junrrein) wrote :

Related to right-click: Right-clicking on blank space in the left panel works. However, the action is executed on the active tab in the right view.

Revision history for this message
Julián Unrrein (junrrein) wrote :

Window.vala has a member called current_tab that holds the current active tab. It seems that we need this variable to hold the current active ViewContainer, but its valued is never updated on your branch (only when creating a new tab).

My understanding of how that works is limited though, so you may want to ask Victor about it.

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

This branch is now incompatible with Files so will have to be rejected. Sorry.

Unmerged revisions

1226. By Mario Guerriero

SplitView works fine

1225. By Mario Guerriero

pushed missing files

1224. By Mario Guerriero

press F3 to have a split view, set a minimum size for the path bar

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/CMakeLists.txt'
2--- src/CMakeLists.txt 2013-06-01 19:39:36 +0000
3+++ src/CMakeLists.txt 2013-06-16 14:19:28 +0000
4@@ -47,6 +47,8 @@
5 View/Browser.vala
6 View/ViewMode.vala
7 View/LocationBar.vala
8+ View/SplitView.vala
9+ View/FilesView.vala
10 View/Chrome/TopMenu.vala
11 View/Chrome/ViewSwicher.vala
12 View/Chrome/ColorWidget.vala
13
14=== modified file 'src/View/Chrome/TopMenu.vala'
15--- src/View/Chrome/TopMenu.vala 2013-06-14 02:10:41 +0000
16+++ src/View/Chrome/TopMenu.vala 2013-06-16 14:19:28 +0000
17@@ -65,11 +65,12 @@
18 if (name == "LocationEntry")
19 {
20 location_bar = new LocationBar (win.ui, win);
21+ location_bar.set_size_request (13, 26);
22 location_bar.halign = Gtk.Align.FILL;
23 location_bar.valign = Gtk.Align.FILL;
24 location_bar.margin_left = 6;
25 location_bar.margin_right = 12;
26-
27+
28 /* init the path if we got a curent tab with a valid slot
29 and a valid directory loaded */
30 if (win.current_tab != null && win.current_tab.slot != null
31@@ -85,7 +86,7 @@
32 win.current_tab.slot.view_box.grab_focus ();
33 });
34 location_bar.activate.connect(() => { win.current_tab.path_changed(File.new_for_commandline_arg(location_bar.path)); });
35- location_bar.activate_alternate.connect((a) => { win.add_tab(File.new_for_commandline_arg(a)); });
36+ location_bar.activate_alternate.connect((a) => { win.get_current_view ().add_tab(File.new_for_commandline_arg(a)); });
37 location_bar.show_all();
38 insert(location_bar, -1);
39 continue;
40
41=== added file 'src/View/FilesView.vala'
42--- src/View/FilesView.vala 1970-01-01 00:00:00 +0000
43+++ src/View/FilesView.vala 2013-06-16 14:19:28 +0000
44@@ -0,0 +1,67 @@
45+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
46+/***
47+ BEGIN LICENSE
48+
49+ Copyright (C) 2013 Mario Guerriero <mario@elementaryos.org>
50+ This program is free software: you can redistribute it and/or modify it
51+ under the terms of the GNU Lesser General Public License version 3, as published
52+ by the Free Software Foundation.
53+
54+ This program is distributed in the hope that it will be useful, but
55+ WITHOUT ANY WARRANTY; without even the implied warranties of
56+ MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
57+ PURPOSE. See the GNU General Public License for more details.
58+
59+ You should have received a copy of the GNU General Public License along
60+ with this program. If not, see <http://www.gnu.org/licenses/>
61+
62+ END LICENSE
63+***/
64+
65+using Gtk;
66+using Granite.Widgets;
67+
68+namespace Marlin.View {
69+ public class FilesView : DynamicNotebook {
70+ public FilesView () {
71+ // Connect to some signals
72+ this.tab_added.connect ((tab) => {
73+ if (tab != null)
74+ this.remove_tab (tab);
75+ add_tab ();
76+ });
77+
78+ this.tab_removed.connect ((tab) => {
79+ //if (this.n_tabs == 1)
80+ // add_tab ();
81+ return true;
82+ });
83+ }
84+
85+ public void add_tab (File location = File.new_for_commandline_arg (Environment.get_home_dir ())) {
86+ var toplevel = this.get_toplevel () as Marlin.View.Window;
87+ ViewContainer content = new View.ViewContainer(toplevel, location,
88+ toplevel.current_tab != null ? toplevel.current_tab.view_mode : Preferences.settings.get_enum("default-viewmode"));
89+
90+ var new_tab = new Granite.Widgets.Tab (content.tab_name, null, content);
91+
92+ content.tab_name_changed.connect ((tab_name) => {
93+ toplevel.current_tab = content;
94+ new_tab.label = tab_name;
95+ content.content.grab_focus ();
96+ });
97+ content.path_changed.connect (() => {
98+ toplevel.current_tab = content;
99+ content.content.grab_focus ();
100+ content.refresh_slot_info ();
101+ });
102+
103+ this.insert_tab (new_tab, -1);
104+
105+ this.current = new_tab;
106+ toplevel.current_tab = content;
107+ content.refresh_slot_info ();
108+ content.content.grab_focus ();
109+ }
110+ }
111+}
112
113=== modified file 'src/View/LocationBar.vala'
114--- src/View/LocationBar.vala 2013-06-08 23:27:45 +0000
115+++ src/View/LocationBar.vala 2013-06-16 14:19:28 +0000
116@@ -302,7 +302,7 @@
117 var menuitem_newtab = new Gtk.MenuItem.with_label (_("Open in New Tab"));
118 menu.append (menuitem_newtab);
119 menuitem_newtab.activate.connect (() => {
120- win.add_tab (File.new_for_uri (current_right_click_path));
121+ win.get_current_view ().add_tab (File.new_for_uri (current_right_click_path));
122 });
123
124 menu.append (new Gtk.SeparatorMenuItem ());
125
126=== added file 'src/View/SplitView.vala'
127--- src/View/SplitView.vala 1970-01-01 00:00:00 +0000
128+++ src/View/SplitView.vala 2013-06-16 14:19:28 +0000
129@@ -0,0 +1,108 @@
130+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
131+/***
132+ BEGIN LICENSE
133+
134+ Copyright (C) 2013 Mario Guerriero <mario@elementaryos.org>
135+ This program is free software: you can redistribute it and/or modify it
136+ under the terms of the GNU Lesser General Public License version 3, as published
137+ by the Free Software Foundation.
138+
139+ This program is distributed in the hope that it will be useful, but
140+ WITHOUT ANY WARRANTY; without even the implied warranties of
141+ MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
142+ PURPOSE. See the GNU General Public License for more details.
143+
144+ You should have received a copy of the GNU General Public License along
145+ with this program. If not, see <http://www.gnu.org/licenses/>
146+
147+ END LICENSE
148+***/
149+
150+using Gtk;
151+using Granite.Widgets;
152+
153+namespace Marlin.View {
154+
155+ public class SplitView : CollapsiblePaned {
156+
157+ public FilesView? current_view = null;
158+ public GLib.List<FilesView> views;
159+
160+ // Signals
161+ public signal void view_added (FilesView view);
162+
163+ public SplitView () {
164+ base (Gtk.Orientation.HORIZONTAL);
165+
166+ views = new GLib.List<FilesView> ();
167+ }
168+
169+ public FilesView? add_view () {
170+ if (views.length () >= 2) {
171+ warning ("Maximum view number was already reached!");
172+ return null;
173+ }
174+
175+ var view = new FilesView ();
176+ view.tab_removed.connect (() => {
177+ if (view.n_tabs == 1)
178+ if (views.length () >= 2)
179+ remove_view (view);
180+ else
181+ view.add_tab ();
182+ return true;
183+ });
184+
185+ if (views.length () < 1)
186+ this.pack1 (view, true, true);
187+ else
188+ this.pack2 (view, true, true);
189+
190+ view.show_all ();
191+
192+ views.append (view);
193+ this.current_view = view;
194+ debug ("View added succefully");
195+
196+ this.show_all ();
197+
198+ this.view_added (view);
199+
200+ return view;
201+ }
202+
203+ public void remove_view (FilesView? view = null) {
204+ // If no specific view is required to be removed, just remove the current one
205+ if (view == null)
206+ view = get_focus_child () as FilesView;
207+ if (view == null) {
208+ warning ("The is no focused view to remove!");
209+ return;
210+ }
211+
212+ this.remove (view);
213+ this.views.remove (view);
214+ view.destroy ();
215+ debug ("View removed succefully");
216+
217+ // Move the focus on the other view
218+ if (views.nth_data (0) != null) {
219+ views.nth_data (0).current.grab_focus ();
220+ }
221+ }
222+
223+ public FilesView? get_current_view () {
224+ views.foreach ((v) => {
225+ if (v.current.has_focus)
226+ current_view = v;
227+ });
228+
229+ return current_view;
230+ }
231+
232+ public bool is_empty () {
233+ return (views.length () == 0);
234+ }
235+
236+ }
237+}
238
239=== modified file 'src/View/ViewContainer.vala'
240--- src/View/ViewContainer.vala 2013-06-14 23:37:29 +0000
241+++ src/View/ViewContainer.vala 2013-06-16 14:19:28 +0000
242@@ -159,6 +159,7 @@
243 /* update window title */
244 if (window.current_tab == this) {
245 window.set_title (tab_name);
246+ //print("\n\n\n");
247 if (window.top_menu.location_bar != null)
248 window.top_menu.location_bar.path = aslot.directory.file.location.get_parse_name ();
249 }
250
251=== modified file 'src/View/Window.vala'
252--- src/View/Window.vala 2013-06-14 02:10:41 +0000
253+++ src/View/Window.vala 2013-06-16 14:19:28 +0000
254@@ -36,7 +36,8 @@
255 public Gtk.InfoBar info_bar;
256 public Granite.Widgets.DynamicNotebook tabs;
257 public Marlin.Places.Sidebar sidebar;
258-
259+
260+ public SplitView split_view;
261 public ViewContainer? current_tab;
262
263 public Gtk.ActionGroup main_actions;
264@@ -152,10 +153,8 @@
265 show_infobar (!is_marlin_mydefault_fm ());
266
267 /* Contents */
268- tabs = new Granite.Widgets.DynamicNotebook ();
269- tabs.show_tabs = true;
270- tabs.show ();
271-
272+ split_view = new SplitView ();
273+
274 /* Sidebar */
275 sidebar = new Marlin.Places.Sidebar (this);
276 Preferences.settings.bind("sidebar-zoom-level", sidebar, "zoom-level", SettingsBindFlags.DEFAULT);
277@@ -164,7 +163,7 @@
278 lside_pane.show();
279
280 lside_pane.pack1(sidebar, false, false);
281- lside_pane.pack2(tabs, true, true);
282+ lside_pane.pack2(split_view, true, true);
283
284 sidebar.show ();
285
286@@ -221,23 +220,12 @@
287 return false;
288 });
289
290- tabs.tab_added.connect ((tab) => {
291- if (tab != null)
292- tabs.remove_tab (tab);
293- add_tab ();
294- });
295-
296- tabs.tab_removed.connect ((tab) => {
297- if (tabs.n_tabs == 1) {
298- add_tab ();
299- }
300- return true;
301- });
302-
303- tabs.tab_switched.connect ((old_tab, new_tab) => {
304- change_tab (tabs.get_tab_position (new_tab));
305- });
306-
307+ this.split_view.view_added.connect ((view) => {
308+ view.tab_switched.connect ((old_tab, new_tab) => {
309+ change_tab (view.get_tab_position (new_tab));
310+ });
311+ });
312+
313 Gtk.Allocation win_alloc;
314 get_allocation (out win_alloc);
315
316@@ -252,7 +240,9 @@
317 undo_manager = Marlin.UndoManager.instance ();
318 undo_manager.request_menu_update.connect (undo_redo_menu_update_callback);
319 undo_actions_set_insensitive ();
320-
321+
322+ // Add a view
323+ split_view.add_view ();
324 }
325
326 private void show_infobar (bool val) {
327@@ -290,7 +280,7 @@
328
329 public void change_tab (int offset) {
330 ViewContainer old_tab = current_tab;
331- current_tab = (tabs.get_tab_by_index (offset)).page as ViewContainer;
332+ current_tab = (get_current_view ().get_tab_by_index (offset)).page as ViewContainer;
333 if (old_tab == current_tab) {
334 return;
335 }
336@@ -317,26 +307,13 @@
337 }
338
339 public void add_tab (File location = File.new_for_commandline_arg (Environment.get_home_dir ())) {
340-
341- ViewContainer content = new View.ViewContainer(this, location,
342- current_tab != null ? current_tab.view_mode : Preferences.settings.get_enum("default-viewmode"));
343-
344- var new_tab = new Granite.Widgets.Tab ("", null, content);
345-
346- content.tab_name_changed.connect ((tab_name) => {
347- new_tab.label = tab_name;
348- });
349-
350- tabs.insert_tab (new_tab, -1);
351-
352- tabs.current = new_tab;
353- //current_tab = content;
354+ this.get_current_view ().add_tab (location);
355 }
356
357 public void remove_tab (ViewContainer view_container){
358- var tab = tabs.get_tab_by_widget (view_container as Gtk.Widget);
359+ var tab = get_current_view ().get_tab_by_widget (view_container as Gtk.Widget);
360 if (tab != null)
361- tabs.remove_tab (tab);
362+ get_current_view ().remove_tab (tab);
363 }
364
365 public void add_window(File location){
366@@ -386,11 +363,11 @@
367 }
368
369 private void action_new_tab (Gtk.Action action) {
370- add_tab ();
371+ get_current_view ().add_tab ();
372 }
373
374 private void action_remove_tab (Gtk.Action action) {
375- tabs.remove_tab (tabs.current);
376+ get_current_view ().remove_tab (get_current_view ().current);
377 }
378
379 private void save_geometries () {
380@@ -438,26 +415,17 @@
381 return false;
382 }
383
384- private bool is_close_first () {
385- string path = "/apps/metacity/general/button_layout";
386- GConf.Client cl = GConf.Client.get_default ();
387- string key;
388-
389- try {
390- if (cl.get (path) != null)
391- key = cl.get_string (path);
392- else
393- return false;
394- } catch (GLib.Error err) {
395- warning ("Unable to read metacity settings: %s", err.message);
396+ // Get current view
397+ public FilesView? get_current_view () {
398+ FilesView? view = null;
399+
400+ view = split_view.get_current_view ();
401+
402+ if (view == null && !split_view.is_empty ()) {
403+ view = (split_view.get_child2 () ?? split_view.get_child2 ()) as FilesView;
404 }
405
406- string[] keys = key.split (":");
407- if ("close" in keys[0])
408- return true;
409- else
410- return false;
411-
412+ return view;
413 }
414
415 private bool is_marlin_mydefault_fm ()
416@@ -529,13 +497,17 @@
417
418 void action_next_tab ()
419 {
420- tabs.next_page ();
421- }
422- void action_previous_tab ()
423- {
424- tabs.previous_page ();
425- }
426-
427+ get_current_view ().next_page ();
428+ }
429+ void action_previous_tab () {
430+ get_current_view ().previous_page ();
431+ }
432+
433+ void action_new_view () {
434+ this.split_view.add_view ();
435+ get_current_view ().add_tab ();
436+ }
437+
438 private void action_zoom_normal_callback (Gtk.Action action) {
439 if (current_tab != null && current_tab.slot != null)
440 ((FM.Directory.View) current_tab.slot.view_box).zoom_normal ();
441@@ -665,6 +637,10 @@
442 /* label, accelerator */ N_("Previous Tab"), "<control>Page_Up",
443 /* tooltip */ "",
444 action_previous_tab },
445+ /* name, stock id */ { "New View", null,
446+ /* label, accelerator */ N_("New View"), "F3",
447+ /* tooltip */ "",
448+ action_new_view },
449 /* name, stock id */ { "Connect to Server", null,
450 /* label, accelerator */ N_("Connect to _Server..."), null,
451 /* tooltip */ N_("Connect to a remote computer or shared disk"),
452
453=== modified file 'src/pantheon-files-ui.xml'
454--- src/pantheon-files-ui.xml 2013-05-28 08:04:18 +0000
455+++ src/pantheon-files-ui.xml 2013-06-16 14:19:28 +0000
456@@ -7,6 +7,7 @@
457 <menubar name="MenuBar">
458 <menu action="File">
459 <placeholder name="New Items Placeholder">
460+ <menuitem name="New View" action="New View"/>
461 <menuitem name="New Tab" action="New Tab"/>
462 <menuitem name="New Window" action="New Window"/>
463 </placeholder>

Subscribers

People subscribed via source and target branches

to all changes: