# How to collapse a folder by code?

**URL:** https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082
**Category:** Support
**Created:** [October 9, 2021, 11:00am UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082 "2021-10-09T11:00:35Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![apparrilla](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/apparrilla/32/9230_2.png) [@apparrilla](https://discourse.slicer.org/u/apparrilla)
#### Post date: [October 9, 2021, 11:00am UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/1 "2021-10-09T11:00:35Z")

</div>

Hi everyone!!  
Order all new nodes maked by a process is wonderfull !!!.. Every thing in a human comprensive tree of elements… But I don´t find the way to collapse by code all made folders… Is it possible?

Thanks in advance!!!

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [October 10, 2021, 12:51pm UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/2 "2021-10-10T12:51:09Z")

</div>

You can use [SetItemExpanded method](http://apidocs.slicer.org/master/classvtkMRMLSubjectHierarchyNode.html#aff3cba573e67923da6f60d5300263e5a) of the subject hierarchy node.

---

<div class="post-metadata">

### Author: ![apparrilla](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/apparrilla/32/9230_2.png) [@apparrilla](https://discourse.slicer.org/u/apparrilla)
#### Post date: [October 10, 2021, 1:42pm UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/3 "2021-10-10T13:42:37Z")

</div>

It also works for collapsing segmentations on Data Tree. Some code to copy/paste:

```auto
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)

sceneItemID = shNode.GetSceneItemID()
folderID = shNode.GetItemChildWithName(sceneItemID,"folder_name")
shNode.SetItemExpanded(folderID , False)

SegmentationNode = slicer.mrmlScene.GetFirstNodeByName("segmentationNode_name")
segmentationNodeID = shNode.GetItemByDataNode(SegmentationNode)
shNode.SetItemExpanded(segmentationNodeID , False)

```

Wonderfull!

Thanks a lot!

---

<div class="post-metadata">

### Author: ![apparrilla](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/apparrilla/32/9230_2.png) [@apparrilla](https://discourse.slicer.org/u/apparrilla)
#### Post date: [October 17, 2021, 6:43pm UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/4 "2021-10-17T18:43:23Z")

</div>

A bit more complex but in the same line…  
Is it possible to reorder items position in the tree? I mean, to put simillar folders one over the other, not following the creation orden…

Thanks in advance!!

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [October 17, 2021, 8:26pm UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/5 "2021-10-17T20:26:31Z")

</div>

You can reorder items using the [MoveItem](http://apidocs.slicer.org/master/classvtkMRMLSubjectHierarchyNode.html#a9b23e40db6c1988e8de1a033e8fcaf72) method.

---

<div class="post-metadata">

### Author: ![apparrilla](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/apparrilla/32/9230_2.png) [@apparrilla](https://discourse.slicer.org/u/apparrilla)
#### Post date: [November 3, 2021, 12:23am UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/6 "2021-11-03T00:23:15Z")

</div>

I have some problem with MoveItem.  
I´ve check both itemIDs and they are right but they don´t move with the function. There is no error message either… I´ve aldo tried to invert items order, but anything happends.  
I don´t know what i´m doing wrong.

Thanks

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [November 3, 2021, 3:30am UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/7 "2021-11-03T03:30:00Z")

</div>

C++ methods cannot log error on the console, so check out the application log for errors or warnings. If there are no messages or you cannot figure out what goes wrong then share your scene (save as .mrb file, upload some, and copy the link here) and the script that does not work as you expect.

---

<div class="post-metadata">

### Author: ![apparrilla](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/apparrilla/32/9230_2.png) [@apparrilla](https://discourse.slicer.org/u/apparrilla)
#### Post date: [November 3, 2021, 5:31pm UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/8 "2021-11-03T17:31:00Z")

</div>

There is no error message in slicer log either.

I´ve made a simple example scene with an empty segmentation and 2 folders:

 ![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/6/8/687498f15a7b446891a0a526c75262bd9c2de594.png)

```auto
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
sceneItemID = shNode.GetSceneItemID()
folderItemID = shNode.GetItemChildWithName(sceneItemID,'NewFolder')
otherFolderItemID = shNode.GetItemChildWithName(sceneItemID,'OtherFolder')
segmentationItemID = shNode.GetItemChildWithName(sceneItemID,'Segmentation')

```

I tried:

```auto
shNode.MoveItem(otherFolderItemID,segmentationItemID)
shNode.MoveItem(folderItemID,segmentationItemID)

```

Both send me a “True” but there is no change in Subject Hierarchy order of items…

I´m sure I´m doing something wrong but I can´t find it out.

Thanks and sorry…

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [November 9, 2021, 4:16am UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/9 "2021-11-09T04:16:14Z")

</div>

I was able to reproduce this update issue. A workaround is to force an update by temporarily switching to scene import state:

```python
slicer.mrmlScene.StartState(slicer.vtkMRMLScene.ImportState)
slicer.mrmlScene.EndState(slicer.vtkMRMLScene.ImportState)

```

I’ve filed a bug report here:

> <https://github.com/Slicer/Slicer/issues/6006>
>
> vtkMRMLSubjectHierarchyNode::MoveItem method has no immediate visible effect.
> 
> …
> See more details here: https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/8
> 
> \## Steps to reproduce
> 
> Create scene like this:
> 
> !\[image\](https://user-images.githubusercontent.com/307929/140860773-e960c719-4711-4e38-9efb-da151c4dd180.png)
> 
> Run this code snipped:
> 
> \`\`\`python
> shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
> sceneItemID = shNode.GetSceneItemID()
> segmentationItemID = shNode.GetItemChildWithName(sceneItemID,'Segmentation')
> folderItemID = shNode.GetItemChildWithName(sceneItemID,'NewFolder')
> folder1ItemID = shNode.GetItemChildWithName(sceneItemID,'NewFolder\_1')
> shNode.MoveItem(folder1ItemID,segmentationItemID)
> \`\`\`
> 
> Nothing changes in the subject hierarchy tree in Data module.
> 
> \## Expected behavior
> 
> NewFolder\_1 should appear above Segmentation.
> 
> \## Environment
> \- Slicer version: Slicer-4.13.0-2021-11-08
> \- Operating system: Windows 10
> 
> \## Workaround
> 
> Force subject hierarchy tree rebuild by temporarily switching to scene import mode:
> 
> \`\`\`python
> slicer.mrmlScene.StartState(slicer.vtkMRMLScene.ImportState)
> slicer.mrmlScene.EndState(slicer.vtkMRMLScene.ImportState)
> \`\`\`

---

<div class="post-metadata">

### Author: ![apparrilla](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/apparrilla/32/9230_2.png) [@apparrilla](https://discourse.slicer.org/u/apparrilla)
#### Post date: [December 9, 2021, 10:03pm UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/10 "2021-12-09T22:03:41Z")

</div>

Any solution in the next future?

---

<div class="post-metadata">

### Author: ![Luca](https://avatars.discourse-cdn.com/v4/letter/l/51bf81/32.png) [@Luca](https://discourse.slicer.org/u/Luca)
#### Post date: [March 11, 2022, 11:48am UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/11 "2022-03-11T11:48:22Z")

</div>

Hi!

I reached this post because I want to create a folder, put many nodes inside it, and then collapse it using a pyhton script run by prompt with --python-script.

I’m using the code below (from this discussion) to collapse it

> [@apparrilla](#):
>
> ```auto
> shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
> 
> sceneItemID = shNode.GetSceneItemID()
> folderID = shNode.GetItemChildWithName(sceneItemID,"folder_name")
> shNode.SetItemExpanded(folderID , False)
> 
> ```

but it doesn’t do anything. However when the script ended, if I type the same code in the python interactor it works. Could it be a problem related to the way I use the script? Otherwise, am I missing any lines?

Thanks in advance!!

---

<div class="post-metadata">

### Author: ![ebrahim](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/ebrahim/32/13403_2.png) [@ebrahim](https://discourse.slicer.org/u/ebrahim)
#### Post date: [March 11, 2022, 2:09pm UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/12 "2022-03-11T14:09:45Z")

</div>

Hmm maybe it will work if you connect your code to the `slicer.util.mainWindow().initialWindowShown` signal? I don’t know if the `--python-script` option already waits for this signal to execute your script. Or maybe you could connect to a `qt.QTimer.singleShot` with 0 or very small timeout in order to allow other events to process that might be expanding the folder at startup.

I recently ran into a situation where I wanted my script to make some changes to widgets at startup, but it had to happen after everything was sufficiently loaded that it wouldn’t revert my change. Here are the two lines that ended up working for my project:

- [lungair-desktop-application/Home.py at 1cf6deb7d6cce0f63944aefdd463ea6053211428 · KitwareMedical/lungair-desktop-application · GitHub](https://github.com/KitwareMedical/lungair-desktop-application/blob/1cf6deb7d6cce0f63944aefdd463ea6053211428/Modules/Scripted/Home/Home.py#L138)
- [lungair-desktop-application/Home.py at 1cf6deb7d6cce0f63944aefdd463ea6053211428 · KitwareMedical/lungair-desktop-application · GitHub](https://github.com/KitwareMedical/lungair-desktop-application/blob/1cf6deb7d6cce0f63944aefdd463ea6053211428/Modules/Scripted/Home/Home.py#L152)

---

<div class="post-metadata">

### Author: ![Arenhart](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/arenhart/32/15650_2.png) [@Arenhart](https://discourse.slicer.org/u/Arenhart)
#### Post date: [January 13, 2023, 7:41pm UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/13 "2023-01-13T19:41:08Z")

</div>

I’ve been using .SetItemExpanded() and it works both in script and in the console, except for the Scene folder.  
I tested the following code, both in a script and directly in the Python console:

```auto
folder_tree = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
scene_id = folder_tree.GetSceneItemID()
folder_tree.SetItemExpanded(scene_id, True)

```

Runing the code,` folder_tree.GetItemExpanded(scene_id)` will return True, but no change will occur in the data widget, the Scene folder will remain collapsed. Using a children folder ID instead of scene\_id will work, imediatelly expanding or collapsing the correct folder.

I have also tried qt.QTimer.singleShot(0, lambda : folder\_tree.SetItemExpanded(scene\_id, True)) following Ebrahim’s comment.

Is there any solution for this situation?

---

<div class="post-metadata">

### Author: ![cpinter](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/cpinter/32/7995_2.png) [@cpinter](https://discourse.slicer.org/u/cpinter)
#### Post date: [January 16, 2023, 10:59am UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/14 "2023-01-16T10:59:09Z")

</div>

The problem is that the scene does not have an item (thus it is not a folder either), so the SH model does not know about the collapsed state of the scene.

My only idea at the moment is trying `shTreeView.expandToDepth(0)`. Or a higher number, depending on what you want. If you need to conserve the expanded states of specific items then it may require some extra work.

Update: Maybe we could make `qMRMLSubjectHierarchyModel::subjectHierarchySceneIndex` callable from Python (`Q_INVOKABLE`) and call `shTreeView.expand(sceneItemModelIndex)`.

---

<div class="post-metadata">

### Author: ![Arenhart](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/arenhart/32/15650_2.png) [@Arenhart](https://discourse.slicer.org/u/Arenhart)
#### Post date: [January 16, 2023, 11:30am UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/15 "2023-01-16T11:30:25Z")

</div>

Unfortunatelly, we do need to conserve the expanded states. We even removed the multiple `shTreeView.expandToDepth(4)` in the code to avoid losing them. It is much better now, since after manually expanding the Scene, our folder pattern is displayed, so it is just a minor inconvenience currently, but on I believe we must fix. EDIT: I tried to programatically expand and collapsed the scene folder in the official 5.3 Slicer too, with the same results.

Ok, so I haven’t worked much with the Slicer source code, but what I understood is that we should include a function like QModelIndex qMRMLSortFilterSubjectHierarchyProxyModel::subjectHierarchySceneIndex()const in `qMRMLSubjectHierarchyModel` and then use it in the Python console with a new `shTreeView.expand(sceneItemModelIndex)` function.

I have two questions:  
One: Won’t the subjectHierarchySceneIndex be the same as folder\_tree.GetSceneItemID()  
Second: shTreeView.expand(sceneItemModelIndex) should be different from SetExpanded ?

---

<div class="post-metadata">

### Author: ![cpinter](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/cpinter/32/7995_2.png) [@cpinter](https://discourse.slicer.org/u/cpinter)
#### Post date: [January 17, 2023, 12:48pm UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/16 "2023-01-17T12:48:43Z")

</div>

> [@Arenhart](#):
>
> Won’t the subjectHierarchySceneIndex be the same as folder\_tree.GetSceneItemID()

No. One is an SH ID, the other a Qt Model Index

> [@Arenhart](#):
>
> shTreeView.expand(sceneItemModelIndex) should be different from SetExpanded

These are two different things, yes. One sets it by SH ID (that the scene doesn’t have), the other by QModelIndex (that the scene has). Hence the whole thing I suggested

---

<div class="post-metadata">

### Author: ![Arenhart](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/arenhart/32/15650_2.png) [@Arenhart](https://discourse.slicer.org/u/Arenhart)
#### Post date: [January 26, 2023, 6:12pm UTC](https://discourse.slicer.org/t/how-to-collapse-a-folder-by-code/20082/17 "2023-01-26T18:12:23Z")

</div>

I found a workaround, if anyone else faces the same problem. Using the qMRMLSubjectHierarchyTreeView instance instead of vtkMRMLSubjectHierarchyNode to expand the folder worked, using the same scene Item ID.

This is the code I used:

```auto
        folder_tree = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
        scene_id = folder_tree.GetSceneItemID()
        dataWidget = slicer.modules.data.widgetRepresentation()
        shTreeView = slicer.util.findChild(dataWidget, name="SubjectHierarchyTreeView")
        shTreeView.expandItem(scene_id)

```

Can also be used to collapse the folder with shTreeView.collapseItem(scene\_id)
