← Back to team overview

kicad-developers team mailing list archive

Re: Selection tool that selects components and local connections

 

Updated the patch to fit on current master.


On 2017-02-08 21:14, Kristoffer Ödmark wrote:
I tried reverting back to master and found the same strange bugs on
windows, so i do not think my patch causes them.

example of bug:
https://snag.gy/EesP2n.jpg

On 2017-02-08 19:17, Kristoffer Ödmark wrote:
Hello again!

Since my groupselection required changes to the file format to be
useful. I have now created a selection tool that selects all footprints
belonging on the same sheet or "deeper".

It also finds all nets that only have connections between components on
the same or deeper sheet and selects them.

It gives some functionality of the group selection idea and does not
break file format or any previous workflow.

Tested on linux, saw some strange right-click meny errors on windows,
but the functionality works there as well when using the shortcut key 'P'

Attaching patch

Video:
https://www.youtube.com/watch?v=DUskyc7t_HA&feature=youtu.be

- Kristoffer


>From dc0c15e81f22d5fefe1fabbf6993d2cb5c61b5bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kristoffer=20=C3=96dmark?= <kristoffer.odmark90@xxxxxxxxx>
Date: Wed, 8 Feb 2017 17:32:41 +0100
Subject: [PATCH] Enables selection of components and tracks on same sheet.

Modifies the selection menu to be adaptive and disable selection options
that are not possible.

Adds a new selection option that is only available when selecting
modules, this tool will select all footprints on the same sheet level or
belonging to subsheets. It will also search for nets that are only
connecting between modules on the same sheet or lower and select every
segment and via belonging to it.

	modified:   tools/common_actions.cpp
	modified:   tools/common_actions.h
	modified:   tools/selection_tool.cpp
	modified:   tools/selection_tool.h
---
 pcbnew/tools/common_actions.cpp |   4 ++
 pcbnew/tools/common_actions.h   |   2 +
 pcbnew/tools/selection_tool.cpp | 132 +++++++++++++++++++++++++++++++++++++++-
 pcbnew/tools/selection_tool.h   |   3 +
 4 files changed, 139 insertions(+), 2 deletions(-)

diff --git a/pcbnew/tools/common_actions.cpp b/pcbnew/tools/common_actions.cpp
index cbb95b10d..7041c1bee 100644
--- a/pcbnew/tools/common_actions.cpp
+++ b/pcbnew/tools/common_actions.cpp
@@ -66,6 +66,10 @@ TOOL_ACTION COMMON_ACTIONS::selectNet( "pcbnew.InteractiveSelection.SelectNet",
         AS_GLOBAL, 0,
         _( "Whole Net" ), _( "Selects all tracks & vias belonging to the same net." ) );
 
+TOOL_ACTION COMMON_ACTIONS::selectSameSheet( "pcbnew.InteractiveSelection.SelectSameSheet",
+        AS_GLOBAL,  'P',
+        _( "Same Sheet" ), _( "Selects all modules and tracks in the same schematic sheet" ) );
+
 TOOL_ACTION COMMON_ACTIONS::find( "pcbnew.InteractiveSelection.Find",
         AS_GLOBAL, 0, //TOOL_ACTION::LegacyHotKey( HK_FIND_ITEM ), // handled by wxWidgets
         _( "Find Item" ), _( "Searches the document for an item" ), find_xpm );
diff --git a/pcbnew/tools/common_actions.h b/pcbnew/tools/common_actions.h
index 72cdb449e..7865581c4 100644
--- a/pcbnew/tools/common_actions.h
+++ b/pcbnew/tools/common_actions.h
@@ -66,6 +66,8 @@ public:
     /// Selects all connections belonging to a single net.
     static TOOL_ACTION selectNet;
 
+    /// Selects all components on the same sheet.
+    static TOOL_ACTION selectSameSheet;
     // Edit Tool
     /// Activation of the edit tool
     static TOOL_ACTION editActivate;
diff --git a/pcbnew/tools/selection_tool.cpp b/pcbnew/tools/selection_tool.cpp
index 97d901ed7..f972504d9 100644
--- a/pcbnew/tools/selection_tool.cpp
+++ b/pcbnew/tools/selection_tool.cpp
@@ -62,9 +62,28 @@ public:
         Add( COMMON_ACTIONS::selectConnection );
         Add( COMMON_ACTIONS::selectCopper );
         Add( COMMON_ACTIONS::selectNet );
+        Add( COMMON_ACTIONS::selectSameSheet );
     }
 
 private:
+
+    void update() override
+    {
+        SELECTION_TOOL* selTool = getToolManager()->GetTool<SELECTION_TOOL>();
+
+        // lines like this make me really think about a better name for SELECTION_CONDITIONS class
+        bool selEnabled =  ( SELECTION_CONDITIONS::OnlyType( PCB_VIA_T )
+                || SELECTION_CONDITIONS::OnlyType( PCB_TRACE_T ) )
+                              ( selTool->GetSelection() );
+
+        bool sheetSelEnabled = ( SELECTION_CONDITIONS::OnlyType( PCB_MODULE_T ) )
+                              ( selTool->GetSelection() );
+
+        Enable( getMenuId( COMMON_ACTIONS::selectNet ), selEnabled );
+        Enable( getMenuId( COMMON_ACTIONS::selectCopper ), selEnabled );
+        Enable( getMenuId( COMMON_ACTIONS::selectConnection ), selEnabled );
+        Enable( getMenuId( COMMON_ACTIONS::selectSameSheet ), sheetSelEnabled );
+    }
     CONTEXT_MENU* create() const override
     {
         return new SELECT_MENU();
@@ -92,8 +111,10 @@ bool SELECTION_TOOL::Init()
 {
     using S_C = SELECTION_CONDITIONS;
 
-    auto showSelectMenuFunctor = ( S_C::OnlyType( PCB_VIA_T ) || S_C::OnlyType( PCB_TRACE_T ) )
-                                    && S_C::Count( 1 );
+    auto showSelectMenuFunctor = ( S_C::OnlyType( PCB_VIA_T ) ||
+            S_C::OnlyType( PCB_TRACE_T ) ||
+            S_C::OnlyType( PCB_MODULE_T ) ) &&
+            S_C::Count( 1 );
 
     auto selectMenu = std::make_shared<SELECT_MENU>();
     selectMenu->SetTool( this );
@@ -457,6 +478,7 @@ void SELECTION_TOOL::SetTransitions()
     Go( &SELECTION_TOOL::selectConnection, COMMON_ACTIONS::selectConnection.MakeEvent() );
     Go( &SELECTION_TOOL::selectCopper, COMMON_ACTIONS::selectCopper.MakeEvent() );
     Go( &SELECTION_TOOL::selectNet, COMMON_ACTIONS::selectNet.MakeEvent() );
+    Go( &SELECTION_TOOL::selectSameSheet, COMMON_ACTIONS::selectSameSheet.MakeEvent() );
 }
 
 
@@ -654,6 +676,112 @@ int SELECTION_TOOL::selectNet( const TOOL_EVENT& aEvent )
     return 0;
 }
 
+int SELECTION_TOOL::selectSameSheet( const TOOL_EVENT& aEvent )
+{
+    if( !selectCursor( true ) )
+        return 0;
+
+    // this function currently only supports modules since they are only
+    // on one sheet.
+    auto item = m_selection.Front();
+    if( item->Type() != PCB_MODULE_T )
+        return 0;
+    if( !item )
+        return 0;
+    auto mod = dynamic_cast<MODULE*>( item );
+
+    clearSelection();
+
+    // get the lowest subsheet name for this.
+    wxString sheetPath = mod->GetPath();
+    sheetPath = sheetPath.BeforeLast( '/' );
+    sheetPath = sheetPath.AfterLast( '/' );
+
+    auto modules = board()->m_Modules.GetFirst();
+    std::list<MODULE*> modList;
+
+    // store all modules that are on that sheet
+    for( MODULE* item = modules; item; item = item->Next() )
+    {
+        if ( item != NULL && item->GetPath().Contains( sheetPath ) )
+        {
+            modList.push_back( item );
+        }
+    }
+
+    //Generate a list of all pads, and of all nets they belong to.
+    std::list<int> netcodeList;
+    for( MODULE* mod : modList )
+    {
+        for( D_PAD* pad = mod->Pads().GetFirst(); pad; pad = pad->Next() )
+        {
+            if( pad->IsConnected() )
+            {
+                netcodeList.push_back( pad->GetNetCode() );
+            }
+        }
+    }
+
+    // remove all duplicates
+    netcodeList.sort();
+    netcodeList.unique();
+
+    // now we need to find all modules that are connected to each of these nets
+    // then we need to determine if these modules are in the list of modules
+    // belonging to this sheet ( modList )
+    RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest();
+    std::list<int> removeCodeList;
+    for( int netCode : netcodeList )
+    {
+        std::list<BOARD_CONNECTED_ITEM*> netPads;
+        ratsnest->GetNetItems( netCode, netPads, (RN_ITEM_TYPE)( RN_PADS ) );
+        for( BOARD_CONNECTED_ITEM* item : netPads )
+        {
+            bool found = ( std::find( modList.begin(), modList.end(), item->GetParent() ) != modList.end() );
+            if( !found )
+            {
+                // if we cannot find the module of the pad in the modList
+                // then we can assume that that module is not located in the same
+                // schematic, therefore invalidate this netcode.
+                removeCodeList.push_back( netCode );
+                break;
+            }
+        }
+    }
+
+    // remove all duplicates
+    removeCodeList.sort();
+    removeCodeList.unique();
+
+    for( int removeCode : removeCodeList )
+    {
+        netcodeList.remove( removeCode );
+    }
+
+    std::list<BOARD_CONNECTED_ITEM*> localConnectionList;
+    for( int netCode : netcodeList )
+    {
+        ratsnest->GetNetItems( netCode, localConnectionList, (RN_ITEM_TYPE)( RN_TRACKS | RN_VIAS ) );
+    }
+
+    for( BOARD_ITEM* i : modList )
+    {
+        if( i != NULL )
+            select( i );
+    }
+    for( BOARD_CONNECTED_ITEM* i : localConnectionList )
+    {
+        if( i != NULL )
+            select( i );
+    }
+
+    // Inform other potentially interested tools
+    if( m_selection.Size() > 0 )
+        m_toolMgr->ProcessEvent( SelectedEvent );
+
+    return 0;
+}
+
 
 void SELECTION_TOOL::findCallback( BOARD_ITEM* aItem )
 {
diff --git a/pcbnew/tools/selection_tool.h b/pcbnew/tools/selection_tool.h
index d6d194362..f4947a20a 100644
--- a/pcbnew/tools/selection_tool.h
+++ b/pcbnew/tools/selection_tool.h
@@ -263,6 +263,9 @@ private:
     ///> Selects all copper connections belonging to a single net.
     int selectNet( const TOOL_EVENT& aEvent );
 
+    ///> Selects all modules belonging to same sheet.
+    int selectSameSheet( const TOOL_EVENT& aEvent );
+
     ///> Find dialog callback.
     void findCallback( BOARD_ITEM* aItem );
 
-- 
2.11.0


Follow ups

References