BUG-148 - Shared Files directory tree node stuck expanded after collapse and cannot re-expand¶
Summary¶
In the main-window Shared Files directory tree (CSharedDirsTreeCtrl, the
"All Directories" file-system browse tree), expanding a folder and then
collapsing it leaves the expand glyph stuck at -. The control treats the node
as still expanded, so the next click is consumed as a phantom collapse and the
folder can no longer be expanded.
This is a regression from stock/community eMule behavior, not a stock defect.
Root Cause¶
CSharedDirsTreeCtrl::OnTvnItemexpanding (in srchybrid/SharedDirsTreeCtrl.cpp)
handles TVN_ITEMEXPANDING, which fires before the expand/collapse completes.
Commit ec9e1d52 (BUG-022) added a bCollapse branch that, on collapse, calls
DeleteChildItems(pExpanded) to free the subtree but does not re-add it:
- The node is still flagged
TVIS_EXPANDEDand still owns its children when the notification fires. - Deleting every child mid-collapse makes the tree-view auto-clear the expanded
state, then the control runs its own collapse toggle on an already-cleared
node. The result is a desynced
TVIS_EXPANDED: glyph shows-, node is logically collapsed, and the next click is eaten as a collapse.
Stock/community eMule never branches on collapse - it unconditionally re-adds the immediate subdirectories, so the node always retains children and the control's collapse toggle runs cleanly.
Why The Fix Choice Matters At Scale¶
The tree holds directory nodes only (files live in CSharedFilesCtrl), populated
lazily one level per expand via FileSystemTreeAddSubdirectories (a live
directory enumeration). Three correct fixes were considered against 50k+ shared
libraries:
- Restore stock (always re-add on collapse): correct, but re-enumerates the immediate subdirs on every collapse - redundant disk I/O that makes collapsing a large folder as slow as expanding it.
- No-op collapse: instant, but retains the entire previously-expanded subtree in memory until the next expand - worst memory retention on deep trees.
- Free children in
TVN_ITEMEXPANDED(chosen): collapse does no enumeration, frees the whole subtree (the memory win BUG-022 intended), and is correct because deletion runs after the collapse has settled.
Fix¶
OnTvnItemexpandingnow handles only the expand direction (returns early onTVE_COLLAPSE/TVE_COLLAPSERESET); it populates children before the node draws expanded.- New
OnTvnItemexpanded(TVN_ITEMEXPANDED, post-action) frees the now-hidden subtree on collapse viaDeleteChildItemsand keepscChildren = 1so the+glyph remains and the folder can be expanded again. - Both the
SDI_UNSHAREDDIRECTORYfolders and theSDI_FILESYSTEMPARENTroot node use the same corrected ordering. WHY:comments at both sites record the expanded-state desync and the post-collapse free.
Representative Sites¶
srchybrid/SharedDirsTreeCtrl.cpp:OnTvnItemexpanding, newOnTvnItemexpanded, message mapTVN_ITEMEXPANDEDreflect entry.srchybrid/SharedDirsTreeCtrl.h:OnTvnItemexpandeddeclaration.
Acceptance Criteria¶
- [ ] Expand, then collapse, then expand again toggles the
+/-glyph correctly and re-expands every time, for folders and the root node. - [ ] Collapsing a large folder performs no directory re-enumeration.
- [ ] Collapsed nodes free their materialized subtree (bounded memory on huge shared trees) and repopulate lazily on the next expand.
- [x] Debug and Release x64 app builds pass before implementation commit.
- [x] Diagnostics Release x64 build passes before implementation commit.
Resolution¶
Implemented and shipped in 0.7.3-rc.2. Fix commit 8acda717 ("BUG-148 fix
shared dirs tree collapse re-expand") is an ancestor of the rc.2 app head
38827709 (tag emulebb-v0.7.3-rc.2). The expand-only OnTvnItemexpanding /
post-collapse OnTvnItemexpanded split in srchybrid/SharedDirsTreeCtrl.cpp
restores correct +/- glyph toggling and re-expansion while freeing the hidden
subtree after the collapse settles. Build gates (x64 Debug/Release + diagnostics
Release) passed before the commit. Closed DONE on 2026-06-13.