Repository: spyder-ide/spyder

Issue:
Outline pane, clicking on file name should move to start of file
## Feature Suggestion  Description

Clicking on a leaf node in the outline pane tree takes you to the start of the relevant bit of code, but clicking on the root node (the filename) does nothing. It would be better if it took you to the start of the file.

This would be a useful feature for when one realizes halfway through adding some code that some extra modules need to be imported at the start of the file - being able to quickly get there using the outline view would be handy. It would also make the root node behave in a more consistent fashion to the leaf nodes.

## Package Versions

* Spyder version: 3.2.8 
* Python version: 3.6.4
* Qt version: 5.6.2
* PyQt5 version: 5.6
* Operating system: Linux 4.13.0-43-generic




Discussion:
Thanks for the suggestion. It seems simple enough that we could implement it in our next release.
I'm currently using the outliner with "show all files" and clicking back and forth on the files in the list to switch files like switching between tabs. In this work flow, putting the cursor to the top when I switch between files would be less than ideal.

Changing the cursor to the file start if you click on the file name could work if it only brought you to the top of the file when that file is in focus.

Another idea would be to always have a "File Start" top level item at the start of the file tree. This would be a little strange to see but it would be more obvious what will happen when you click on it.
@bcolsen, thanks for your input. What if a double-click takes you to the top of the file?
That would work for me but I don't think it's very discoverable.

I was going to submit the idea that the outliner position should follow the current cursor position. Placing the cursor at the file start before the first tag tag was one of the corner cases for what should be highlighted. Having a "start tag" would help with that.
So  when you double click leaf nodes they expand or contract - for UI consistency I'd expect the root file nodes to do the same rather than move the cursor - the fact that currently it does neither is possibly an orthogonal problem!
I don;t normally use the all-files option, but I did notice that when you clicks on a new filename, the old file node is collapsed and the new file node is expanded  - so only the current file is expanded. This made me think that you could get both the switch and move to top of the file behaviors  by looking at whether the file node is expanded or not.
If the file node is not expanded, switch the editor tab, expand the outline view, but don't move the cursor
If the file node is expanded, then move the cursor (and switch editor tabs if necessary).

I don't think that is overloading the UI too much and it seems to my mind consistent with how the outline pane works in other respects. The special 'top-of-file' entry is also possible, but it's a bit VB-esque with a [declarations] section heading....
> So when you double click leaf nodes they expand or contract - for UI consistency I'd expect the root file nodes to do the same rather than move the cursor - the fact that currently it does neither is possibly an orthogonal problem!

Yes this is what double clicking should do. It actually does do this currently when you click on a file name but since that file becomes the active file then the tree is automatically expended because it is the active file. I don't think this needs to be fixed.

>If the file node is not expanded, switch the editor tab, expand the outline view, but don't move the cursor
>If the file node is expanded, then move the cursor (and switch editor tabs if necessary).

This is a fine idea. I don't think that I'll accidentally click on the file twice.





>  It actually does do this currently when you click on a file name but since that file becomes the active file then the tree is automatically expended because it is the active file. I don't think this needs to be fixed.

This is somewhat orthogonal, but I'd personally rather it be fixed and *not* be expanded on a single click. I'd like to use it as a "vertical tab bar" like @bcolsen suggested, and love the similar functionality in Notepad++ and have switched to it as my primary navigation mechanism when I'm switching between too many files for Alt-Tab or the normal tab bar. However, it is much more difficult to do so when it autoexpands on each file, making it much harder to consistently navigate in this fashion. 

Furthermore, double-clicking a top-level file to minimize it again currently does nothing, even though the "triangle" expand-contract toggle still works, as does the expand/contract all button up top. For UI consistancy, there is no reason this shouldn't work normally as it does at all other levels with this keystroke. 

That, then, leaves the issue of jumping to the top. Double-clicking to go to the top of the file was the natural suggestion that popped into my head for that as well, but would be inconsistant and possibly confusing Ux compared to what it does at all other levels, and would prevent the above from being implemented. This currently can still be accomplished by other quick means, like Ctrl-PageUp or Ctrl-Home. 

However, what would be really nice and a meaningful addition, especially for the usage scenario the @gb119 described which I often face as well (jumping to the top to modify some imports, etc), is a way to quickly jump to the top of the file, then jump *back* down to the previous position—at least in my workflow, it's that latter part that takes way more time and effort then just jumping to the top in the first place, and which this wouldn't really solve. But that's probably out of scope, and with double-clicking (should be) already taken for expanding/contracting outline elements there isn't an obvious UI for it.

Resolving patch:
diff --git a/spyder/plugins/outlineexplorer/widgets.py b/spyder/plugins/outlineexplorer/widgets.py
--- a/spyder/plugins/outlineexplorer/widgets.py
+++ b/spyder/plugins/outlineexplorer/widgets.py
@@ -475,13 +475,14 @@ def populate_branch(self, editor, root_item, tree_cache=None):
 
     def root_item_selected(self, item):
         """Root item has been selected: expanding it and collapsing others"""
-        for index in range(self.topLevelItemCount()):
-            root_item = self.topLevelItem(index)
+        if self.show_all_files:
+            return
+        for root_item in self.get_top_level_items():
             if root_item is item:
                 self.expandItem(root_item)
             else:
                 self.collapseItem(root_item)
-                
+
     def restore(self):
         """Reimplemented OneColumnTree method"""
         if self.current_editor is not None:
@@ -512,16 +513,22 @@ def get_visible_items(self):
 
     def activated(self, item):
         """Double-click event"""
+        editor_item = self.editor_items.get(
+            self.editor_ids.get(self.current_editor))
         line = 0
-        if isinstance(item, TreeItem):
+        if item == editor_item:
+            line = 1
+        elif isinstance(item, TreeItem):
             line = item.line
-        root_item = self.get_root_item(item)
+
         self.freeze = True
+        root_item = self.get_root_item(item)
         if line:
             self.parent().edit_goto.emit(root_item.path, line, item.text(0))
         else:
             self.parent().edit.emit(root_item.path)
         self.freeze = False
+
         parent = self.current_editor.parent()
         for editor_id, i_item in list(self.editor_items.items()):
             if i_item is root_item:


Test patch:
diff --git a/spyder/plugins/editor/widgets/tests/test_editor_and_outline.py b/spyder/plugins/editor/widgets/tests/test_editor_and_outline.py
--- a/spyder/plugins/editor/widgets/tests/test_editor_and_outline.py
+++ b/spyder/plugins/editor/widgets/tests/test_editor_and_outline.py
@@ -97,7 +97,7 @@ def test_load_files(empty_editor_bot, python_files):
     editorstack.tabs.currentIndex() == 0
 
     results = [item.text(0) for item in treewidget.get_visible_items()]
-    assert results == ['foo1.py', 'foo']
+    assert results == ['foo1.py']
 
     # Load the second file and assert the content of the outline explorer tree.
     editorstack.load(python_files[1])
@@ -105,7 +105,7 @@ def test_load_files(empty_editor_bot, python_files):
     editorstack.tabs.currentIndex() == 1
 
     results = [item.text(0) for item in treewidget.get_visible_items()]
-    assert results == ['foo1.py', 'foo2.py', '---- a comment']
+    assert results == ['foo1.py', 'foo2.py']
 
 
 def test_close_editor(editor_bot):
@@ -138,7 +138,7 @@ def test_close_a_file(editor_bot):
     # tree has been updated.
     editorstack.close_file(index=1)
     results = [item.text(0) for item in treewidget.get_visible_items()]
-    assert results == ['foo1.py', 'foo']
+    assert results == ['foo1.py']
 
 
 if __name__ == "__main__":