mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 02:03:12 +02:00
Store hierarchy expansion/collapse state
Defaults to fully expanded but stores the names for nodes that are collapsed in project local settings. Because project local settings are generally changed by modifying views or selection filters, these should be saved on close rather than only when the project is saved Fixes https://gitlab.com/kicad/code/kicad/-/issues/19276
This commit is contained in:
parent
b67b467483
commit
e379e91081
@ -354,6 +354,9 @@ PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( PROJECT* aProject, const wxStrin
|
|||||||
{ "otherItems", true }
|
{ "otherItems", true }
|
||||||
} ) );
|
} ) );
|
||||||
|
|
||||||
|
m_params.emplace_back( new PARAM_LIST<wxString>( "schematic.hierarchy_collapsed",
|
||||||
|
&m_SchHierarchyCollapsed, {} ) );
|
||||||
|
|
||||||
registerMigration( 1, 2,
|
registerMigration( 1, 2,
|
||||||
[&]()
|
[&]()
|
||||||
{
|
{
|
||||||
|
@ -156,9 +156,10 @@ void SETTINGS_MANAGER::Save()
|
|||||||
if( dynamic_cast<COLOR_SETTINGS*>( settings.get() ) )
|
if( dynamic_cast<COLOR_SETTINGS*>( settings.get() ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Never automatically save project settings, caller should use SaveProject or UnloadProject
|
// Never automatically save project file, caller should use SaveProject or UnloadProject
|
||||||
if( dynamic_cast<PROJECT_FILE*>( settings.get() )
|
// We do want to save the project local settings, though because they are generally view
|
||||||
|| dynamic_cast<PROJECT_LOCAL_SETTINGS*>( settings.get() ) )
|
// settings that should persist even if the project is not saved
|
||||||
|
if( dynamic_cast<PROJECT_FILE*>( settings.get() ) )
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -246,6 +246,7 @@ void SCH_EDIT_FRAME::SaveProjectLocalSettings()
|
|||||||
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
|
SCH_SELECTION_TOOL* selTool = GetToolManager()->GetTool<SCH_SELECTION_TOOL>();
|
||||||
|
|
||||||
localSettings.m_SchSelectionFilter = selTool->GetFilter();
|
localSettings.m_SchSelectionFilter = selTool->GetFilter();
|
||||||
|
localSettings.m_SchHierarchyCollapsed = m_hierarchy->GetCollapsedPaths();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include <tool/tool_manager.h>
|
#include <tool/tool_manager.h>
|
||||||
#include <tools/sch_actions.h>
|
#include <tools/sch_actions.h>
|
||||||
#include <hierarchy_pane.h>
|
#include <hierarchy_pane.h>
|
||||||
|
#include <project/project_local_settings.h>
|
||||||
#include <kiface_base.h>
|
#include <kiface_base.h>
|
||||||
#include <wx/object.h>
|
#include <wx/object.h>
|
||||||
#include <wx/generic/textdlgg.h>
|
#include <wx/generic/textdlgg.h>
|
||||||
@ -95,6 +96,11 @@ HIERARCHY_PANE::HIERARCHY_PANE( SCH_EDIT_FRAME* aParent ) :
|
|||||||
|
|
||||||
m_events_bound = false;
|
m_events_bound = false;
|
||||||
|
|
||||||
|
PROJECT_LOCAL_SETTINGS& localSettings = m_frame->Prj().GetLocalSettings();
|
||||||
|
|
||||||
|
for( const wxString& path : localSettings.m_SchHierarchyCollapsed )
|
||||||
|
m_collapsedPaths.insert( path );
|
||||||
|
|
||||||
UpdateHierarchyTree();
|
UpdateHierarchyTree();
|
||||||
|
|
||||||
// Enable selection events
|
// Enable selection events
|
||||||
@ -220,32 +226,39 @@ void HIERARCHY_PANE::UpdateHierarchyTree( bool aClear )
|
|||||||
}
|
}
|
||||||
|
|
||||||
SCH_SHEET_LIST hierarchy = m_frame->Schematic().Hierarchy();
|
SCH_SHEET_LIST hierarchy = m_frame->Schematic().Hierarchy();
|
||||||
std::set<SCH_SHEET_PATH> expandedNodes;
|
std::set<wxString> collapsedNodes = m_collapsedPaths;
|
||||||
|
|
||||||
std::function<void( const wxTreeItemId& )> getExpandedNodes =
|
std::function<void( const wxTreeItemId& )> getCollapsedNodes =
|
||||||
[&]( const wxTreeItemId& id )
|
[&]( const wxTreeItemId& id )
|
||||||
{
|
{
|
||||||
wxCHECK_RET( id.IsOk(), wxT( "Invalid tree item" ) );
|
wxCHECK_RET( id.IsOk(), wxT( "Invalid tree item" ) );
|
||||||
|
|
||||||
TREE_ITEM_DATA* itemData = static_cast<TREE_ITEM_DATA*>( m_tree->GetItemData( id ) );
|
TREE_ITEM_DATA* itemData = static_cast<TREE_ITEM_DATA*>( m_tree->GetItemData( id ) );
|
||||||
|
|
||||||
if( m_tree->IsExpanded( id ) && hierarchy.HasPath( itemData->m_SheetPath.Path() ) )
|
if( m_tree->ItemHasChildren( id ) && !m_tree->IsExpanded( id )
|
||||||
expandedNodes.emplace( itemData->m_SheetPath );
|
&& hierarchy.HasPath( itemData->m_SheetPath.Path() ) )
|
||||||
|
{
|
||||||
|
collapsedNodes.emplace( itemData->m_SheetPath.PathAsString() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wxTreeItemIdValue cookie;
|
wxTreeItemIdValue cookie;
|
||||||
wxTreeItemId child = m_tree->GetFirstChild( id, cookie );
|
wxTreeItemId child = m_tree->GetFirstChild( id, cookie );
|
||||||
|
|
||||||
while( child.IsOk() )
|
while( child.IsOk() )
|
||||||
{
|
{
|
||||||
getExpandedNodes( child );
|
getCollapsedNodes( child );
|
||||||
child = m_tree->GetNextChild( id, cookie );
|
child = m_tree->GetNextChild( id, cookie );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// If we are clearing the tree, don't try to get expanded nodes as they
|
// If we are clearing the tree, don't try to get collapsed nodes as they
|
||||||
// might be deleted
|
// might be deleted
|
||||||
if( !aClear && !m_tree->IsEmpty() )
|
if( !aClear && !m_tree->IsEmpty() )
|
||||||
getExpandedNodes( m_tree->GetRootItem() );
|
{
|
||||||
|
collapsedNodes.clear();
|
||||||
|
getCollapsedNodes( m_tree->GetRootItem() );
|
||||||
|
}
|
||||||
|
|
||||||
m_list.clear();
|
m_list.clear();
|
||||||
m_list.push_back( &m_frame->Schematic().Root() );
|
m_list.push_back( &m_frame->Schematic().Root() );
|
||||||
@ -258,35 +271,35 @@ void HIERARCHY_PANE::UpdateHierarchyTree( bool aClear )
|
|||||||
buildHierarchyTree( &m_list, root );
|
buildHierarchyTree( &m_list, root );
|
||||||
UpdateHierarchySelection();
|
UpdateHierarchySelection();
|
||||||
|
|
||||||
if( !expandedNodes.empty() )
|
m_tree->ExpandAll();
|
||||||
{
|
|
||||||
std::function<void( const wxTreeItemId& )> expandNodes =
|
std::function<void( const wxTreeItemId& )> collapseNodes =
|
||||||
[&]( const wxTreeItemId& id )
|
[&]( const wxTreeItemId& id )
|
||||||
|
{
|
||||||
|
wxCHECK_RET( id.IsOk(), wxT( "Invalid tree item" ) );
|
||||||
|
|
||||||
|
TREE_ITEM_DATA* itemData =
|
||||||
|
static_cast<TREE_ITEM_DATA*>( m_tree->GetItemData( id ) );
|
||||||
|
|
||||||
|
if( id != root &&
|
||||||
|
collapsedNodes.find( itemData->m_SheetPath.PathAsString() ) != collapsedNodes.end() )
|
||||||
{
|
{
|
||||||
wxCHECK_RET( id.IsOk(), wxT( "Invalid tree item" ) );
|
m_tree->Collapse( id );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
TREE_ITEM_DATA* itemData =
|
wxTreeItemIdValue cookie;
|
||||||
static_cast<TREE_ITEM_DATA*>( m_tree->GetItemData( id ) );
|
wxTreeItemId child = m_tree->GetFirstChild( id, cookie );
|
||||||
|
|
||||||
if( expandedNodes.find( itemData->m_SheetPath ) != expandedNodes.end() )
|
while( child.IsOk() )
|
||||||
m_tree->Expand( id );
|
{
|
||||||
|
collapseNodes( child );
|
||||||
|
child = m_tree->GetNextChild( id, cookie );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
wxTreeItemIdValue cookie;
|
collapseNodes( root );
|
||||||
wxTreeItemId child = m_tree->GetFirstChild( id, cookie );
|
m_collapsedPaths = std::move( collapsedNodes );
|
||||||
|
|
||||||
while( child.IsOk() )
|
|
||||||
{
|
|
||||||
expandNodes( child );
|
|
||||||
child = m_tree->GetNextChild( id, cookie );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
expandNodes( m_tree->GetRootItem() );
|
|
||||||
}
|
|
||||||
else if( m_tree->ItemHasChildren( root ) )
|
|
||||||
{
|
|
||||||
m_tree->Expand( root );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( eventsWereBound )
|
if( eventsWereBound )
|
||||||
{
|
{
|
||||||
@ -359,6 +372,42 @@ void HIERARCHY_PANE::UpdateLabelsHierarchyTree()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<wxString> HIERARCHY_PANE::GetCollapsedPaths() const
|
||||||
|
{
|
||||||
|
std::vector<wxString> collapsed;
|
||||||
|
|
||||||
|
if( m_tree->IsEmpty() )
|
||||||
|
return collapsed;
|
||||||
|
|
||||||
|
std::function<void( const wxTreeItemId& )> collect =
|
||||||
|
[&]( const wxTreeItemId& id )
|
||||||
|
{
|
||||||
|
wxCHECK_RET( id.IsOk(), wxT( "Invalid tree item" ) );
|
||||||
|
|
||||||
|
TREE_ITEM_DATA* itemData = static_cast<TREE_ITEM_DATA*>( m_tree->GetItemData( id ) );
|
||||||
|
|
||||||
|
if( id != m_tree->GetRootItem() && m_tree->ItemHasChildren( id )
|
||||||
|
&& !m_tree->IsExpanded( id ) )
|
||||||
|
{
|
||||||
|
collapsed.push_back( itemData->m_SheetPath.PathAsString() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxTreeItemIdValue cookie;
|
||||||
|
wxTreeItemId child = m_tree->GetFirstChild( id, cookie );
|
||||||
|
|
||||||
|
while( child.IsOk() )
|
||||||
|
{
|
||||||
|
collect( child );
|
||||||
|
child = m_tree->GetNextChild( id, cookie );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
collect( m_tree->GetRootItem() );
|
||||||
|
return collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void HIERARCHY_PANE::onTreeItemRightClick( wxTreeEvent& aEvent )
|
void HIERARCHY_PANE::onTreeItemRightClick( wxTreeEvent& aEvent )
|
||||||
{
|
{
|
||||||
onRightClick( aEvent.GetItem() );
|
onRightClick( aEvent.GetItem() );
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
#include <wx/imaglist.h>
|
#include <wx/imaglist.h>
|
||||||
#include <wx/object.h> // wxRTTI macros
|
#include <wx/object.h> // wxRTTI macros
|
||||||
#include <wx/treectrl.h>
|
#include <wx/treectrl.h>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
#include "widgets/wx_panel.h"
|
#include "widgets/wx_panel.h"
|
||||||
|
|
||||||
|
|
||||||
@ -98,6 +100,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
void UpdateLabelsHierarchyTree();
|
void UpdateLabelsHierarchyTree();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of sheet paths for nodes that are currently collapsed.
|
||||||
|
*/
|
||||||
|
std::vector<wxString> GetCollapsedPaths() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Create the hierarchical tree of the schematic.
|
* Create the hierarchical tree of the schematic.
|
||||||
@ -149,6 +156,7 @@ private:
|
|||||||
HIERARCHY_TREE* m_tree;
|
HIERARCHY_TREE* m_tree;
|
||||||
|
|
||||||
bool m_events_bound;
|
bool m_events_bound;
|
||||||
|
std::set<wxString> m_collapsedPaths;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HIERARCHY_PANE_H
|
#endif // HIERARCHY_PANE_H
|
||||||
|
@ -151,6 +151,9 @@ public:
|
|||||||
PCB_SELECTION_FILTER_OPTIONS m_PcbSelectionFilter;
|
PCB_SELECTION_FILTER_OPTIONS m_PcbSelectionFilter;
|
||||||
SCH_SELECTION_FILTER_OPTIONS m_SchSelectionFilter;
|
SCH_SELECTION_FILTER_OPTIONS m_SchSelectionFilter;
|
||||||
|
|
||||||
|
/// Collapsed nodes in the schematic hierarchy navigator
|
||||||
|
std::vector<wxString> m_SchHierarchyCollapsed;
|
||||||
|
|
||||||
// Upstream git repo info
|
// Upstream git repo info
|
||||||
wxString m_GitRepoUsername;
|
wxString m_GitRepoUsername;
|
||||||
wxString m_GitRepoType;
|
wxString m_GitRepoType;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user