diff --git a/api/proto/board/board_types.proto b/api/proto/board/board_types.proto index 65732e103c..6fd2371aab 100644 --- a/api/proto/board/board_types.proto +++ b/api/proto/board/board_types.proto @@ -841,7 +841,9 @@ message ReferenceImage message Group { - // TODO + kiapi.common.types.KIID id = 1; + string name = 2; + repeated kiapi.common.types.KIID items = 3; } message FieldId diff --git a/api/proto/common/commands/editor_commands.proto b/api/proto/common/commands/editor_commands.proto index 9551e01b7d..04a2c38e59 100644 --- a/api/proto/common/commands/editor_commands.proto +++ b/api/proto/common/commands/editor_commands.proto @@ -222,6 +222,14 @@ message GetItems repeated kiapi.common.types.KiCadObjectType types = 2; } +message GetItemsById +{ + // Specifies which document to query, which fields to return, etc. + kiapi.common.types.ItemHeader header = 1; + + repeated kiapi.common.types.KIID items = 2; +} + message GetItemsResponse { // Specifies which document was modified, which fields are included in items, etc. diff --git a/pcbnew/api/api_handler_pcb.cpp b/pcbnew/api/api_handler_pcb.cpp index b8f5b8fd38..29be3a273a 100644 --- a/pcbnew/api/api_handler_pcb.cpp +++ b/pcbnew/api/api_handler_pcb.cpp @@ -64,6 +64,7 @@ API_HANDLER_PCB::API_HANDLER_PCB( PCB_EDIT_FRAME* aFrame ) : registerHandler( &API_HANDLER_PCB::handleRevertDocument ); registerHandler( &API_HANDLER_PCB::handleGetItems ); + registerHandler( &API_HANDLER_PCB::handleGetItemsById ); registerHandler( &API_HANDLER_PCB::handleGetSelection ); registerHandler( &API_HANDLER_PCB::handleClearSelection ); @@ -484,7 +485,9 @@ HANDLER_RESULT API_HANDLER_PCB::handleCreateUpdateItemsIntern // doesn't currently know what to do with a footprint that has had its children // replaced with other children; which results in things like the view not having its // cached geometry for footprint children updated when you move a footprint around. - if( boardItem->Type() == PCB_FOOTPRINT_T ) + // And also, groups are special because they can contain any item type, so we + // can't use CopyFrom on them either. + if( boardItem->Type() == PCB_FOOTPRINT_T || boardItem->Type() == PCB_GROUP_T ) { commit->Remove( boardItem ); item->Serialize( newItem ); @@ -615,6 +618,16 @@ HANDLER_RESULT API_HANDLER_PCB::handleGetItems( break; } + case PCB_GROUP_T: + { + handledAnything = true; + + std::copy( board->Groups().begin(), board->Groups().end(), + std::back_inserter( items ) ); + + typesInserted.insert( PCB_GROUP_T ); + break; + } default: break; } @@ -643,6 +656,47 @@ HANDLER_RESULT API_HANDLER_PCB::handleGetItems( } +HANDLER_RESULT API_HANDLER_PCB::handleGetItemsById( + const HANDLER_CONTEXT& aCtx ) +{ + if( std::optional busy = checkForBusy() ) + return tl::unexpected( *busy ); + + if( !validateItemHeaderDocument( aCtx.Request.header() ) ) + { + ApiResponseStatus e; + e.set_status( ApiStatusCode::AS_UNHANDLED ); + return tl::unexpected( e ); + } + + GetItemsResponse response; + + std::vector items; + for( const kiapi::common::types::KIID& id : aCtx.Request.items() ) + { + if( std::optional item = getItemById( KIID( id.value() ) ) ) + items.emplace_back( *item ); + } + + if( items.empty() ) + { + ApiResponseStatus e; + e.set_status( ApiStatusCode::AS_BAD_REQUEST ); + e.set_error_message( "none of the requested IDs were found or valid" ); + return tl::unexpected( e ); + } + + for( const BOARD_ITEM* item : items ) + { + google::protobuf::Any itemBuf; + item->Serialize( itemBuf ); + response.mutable_items()->Add( std::move( itemBuf ) ); + } + + response.set_status( ItemRequestStatus::IRS_OK ); + return response; +} + void API_HANDLER_PCB::deleteItemsInternal( std::map& aItemsToDelete, const std::string& aClientName ) { diff --git a/pcbnew/api/api_handler_pcb.h b/pcbnew/api/api_handler_pcb.h index c44b0a0a36..c08c3c1237 100644 --- a/pcbnew/api/api_handler_pcb.h +++ b/pcbnew/api/api_handler_pcb.h @@ -74,6 +74,9 @@ private: HANDLER_RESULT handleGetItems( const HANDLER_CONTEXT& aCtx ); + HANDLER_RESULT handleGetItemsById( + const HANDLER_CONTEXT& aCtx ); + HANDLER_RESULT handleGetSelection( const HANDLER_CONTEXT& aCtx ); diff --git a/pcbnew/pcb_group.cpp b/pcbnew/pcb_group.cpp index 075f7896a8..b511f3de52 100644 --- a/pcbnew/pcb_group.cpp +++ b/pcbnew/pcb_group.cpp @@ -32,6 +32,11 @@ #include #include #include +#include +#include +#include +#include +#include #include @@ -46,6 +51,53 @@ PCB_GROUP::PCB_GROUP( BOARD_ITEM* aParent, KICAD_T idtype, PCB_LAYER_ID aLayer ) { } +void PCB_GROUP::Serialize( google::protobuf::Any &aContainer ) const +{ + using namespace kiapi::board::types; + Group group; + + group.mutable_id()->set_value( m_Uuid.AsStdString() ); + group.set_name( GetName().ToUTF8() ); + + for( EDA_ITEM* item : GetItems() ) + { + kiapi::common::types::KIID* itemId = group.add_items(); + itemId->set_value( item->m_Uuid.AsStdString() ); + } + + aContainer.PackFrom( group ); +} + + +bool PCB_GROUP::Deserialize( const google::protobuf::Any &aContainer ) +{ + kiapi::board::types::Group group; + + if( !aContainer.UnpackTo( &group ) ) + return false; + + const_cast( m_Uuid ) = KIID( group.id().value() ); + SetName( wxString( group.name().c_str(), wxConvUTF8 ) ); + + + BOARD* board = GetBoard(); + if( !board ) + return false; + + for ( const kiapi::common::types::KIID& itemId : group.items() ) + { + + KIID id( itemId.value() ); + BOARD_ITEM* item = board->ResolveItem( id, true ); + + if( item ) + { + AddItem( item ); + } + } + + return true; +} std::unordered_set PCB_GROUP::GetBoardItems() const { diff --git a/pcbnew/pcb_group.h b/pcbnew/pcb_group.h index 8820ab184b..8c8f0247bf 100644 --- a/pcbnew/pcb_group.h +++ b/pcbnew/pcb_group.h @@ -54,6 +54,10 @@ class PCB_GROUP : public BOARD_ITEM, public EDA_GROUP public: PCB_GROUP( BOARD_ITEM* aParent ); + void Serialize( google::protobuf::Any &aContainer ) const override; + bool Deserialize( const google::protobuf::Any &aContainer ) override; + + EDA_ITEM* AsEdaItem() override { return this; } static inline bool ClassOf( const EDA_ITEM* aItem )