37#include <api/common/types/base_types.pb.h>
39using namespace kiapi::common::commands;
40using types::CommandStatus;
41using types::DocumentType;
42using types::ItemRequestStatus;
76 if( aDocument.type() != DocumentType::DOCTYPE_FOOTPRINT )
79 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
80 e.set_error_message(
"the requested document is not a footprint" );
81 return tl::unexpected( e );
87 if( 0 != aDocument.lib_id().library_nickname().compare( actual_lib ) )
90 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
91 e.set_error_message( fmt::format(
"the requested library is {} but the actual library is {}",
92 aDocument.lib_id().library_nickname(), actual_lib ) );
93 return tl::unexpected( e );
96 if( 0 != aDocument.lib_id().entry_name().compare( actual_name ) )
99 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
100 e.set_error_message( fmt::format(
"the requested footprint name is {} but the actual name is {}",
101 aDocument.lib_id().entry_name(), actual_name ) );
102 return tl::unexpected( e );
109 const DocumentSpecifier& aDocument )
111 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
112 return tl::unexpected( *busy );
116 if( !documentValidation )
117 return tl::unexpected( documentValidation.error() );
121 if( !editorFootprint )
124 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
125 e.set_error_message(
"no footprint is currently loaded" );
126 return tl::unexpected( e );
129 return editorFootprint;
135 if( aCtx.
Request.type() != DocumentType::DOCTYPE_FOOTPRINT )
138 e.set_status( ApiStatusCode::AS_UNHANDLED );
139 return tl::unexpected( e );
144 wxString libraryName = aCtx.
Request.identifier().library_nickname();
145 wxString fpName = aCtx.
Request.identifier().entry_name();
147 LIB_ID fpid( libraryName, fpName );
151 std::unique_ptr<FOOTPRINT> footprint(
157 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
158 e.set_error_message(
"could not open footprint" );
159 return tl::unexpected( e );
165 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
166 e.set_error_message( fmt::format(
"could not open footprint due to IO error {}",
167 err.
Problem().ToStdString() ) );
168 return tl::unexpected( e );
178 if( aCtx.
Request.type() != DocumentType::DOCTYPE_FOOTPRINT )
181 e.set_status( ApiStatusCode::AS_UNHANDLED );
182 return tl::unexpected( e );
185 GetOpenDocumentsResponse response;
186 common::types::DocumentSpecifier doc;
190 doc.set_type( DocumentType::DOCTYPE_FOOTPRINT );
194 if( !
project().IsNullProject() )
196 doc.mutable_project()->set_name(
project().GetProjectName().ToStdString() );
197 doc.mutable_project()->set_path(
project().GetProjectDirectory().ToStdString() );
200 response.mutable_documents()->Add( std::move( doc ) );
211 return tl::unexpected( footprint.error() );
216 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
217 e.set_error_message(
"failed to save footprint" );
218 return tl::unexpected( e );
231 return tl::unexpected( footprint.error() );
233 wxString pathStr = wxString::FromUTF8( aCtx.
Request.path() );
235 if( pathStr.IsEmpty() )
238 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
239 e.set_error_message(
"path must contain the new footprint name, "
240 "optionally prefixed with a library nickname (e.g. \"lib:name\")" );
241 return tl::unexpected( e );
246 targetId.
Parse( pathStr );
250 if( libraryName.IsEmpty() )
256 std::unique_ptr<FOOTPRINT>
copy(
static_cast<FOOTPRINT*
>( ( *footprint )->Clone() ) );
257 copy->SetFPID(
LIB_ID( libraryName, newName ) );
262 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
263 e.set_error_message( fmt::format(
"failed to save footprint copy '{}' to library '{}'",
264 newName.ToStdString(),
265 libraryName.ToStdString() ) );
266 return tl::unexpected( e );
276 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
277 return tl::unexpected( *busy );
281 if( !documentValidation )
282 return tl::unexpected( documentValidation.error() );
294 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
295 return tl::unexpected( *busy );
301 e.set_status( ApiStatusCode::AS_UNHANDLED );
302 return tl::unexpected( e );
305 GetItemsResponse response;
308 std::vector<BOARD_ITEM*> items;
309 std::set<KICAD_T> typesRequested, typesInserted;
310 bool handledAnything =
false;
312 for(
int typeRaw : aCtx.
Request.types() )
314 auto typeMessage =
static_cast<common::types::KiCadObjectType
>( typeRaw );
320 typesRequested.emplace( type );
322 if( typesInserted.count( type ) )
329 handledAnything =
true;
331 std::copy( footprint->
Pads().begin(), footprint->
Pads().end(),
332 std::back_inserter( items ) );
343 handledAnything =
true;
344 bool inserted =
false;
348 if( item->Type() == type )
350 items.emplace_back( item );
356 typesInserted.insert( type );
363 handledAnything =
true;
364 bool inserted =
false;
368 switch( item->Type() )
375 items.emplace_back( item );
398 handledAnything =
true;
400 std::copy( footprint->
Zones().begin(), footprint->
Zones().end(),
401 std::back_inserter( items ) );
409 handledAnything =
true;
411 std::copy( footprint->
Groups().begin(), footprint->
Groups().end(),
412 std::back_inserter( items ) );
423 if( !handledAnything )
426 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
427 e.set_error_message(
"none of the requested types are valid for a Footprint object" );
428 return tl::unexpected( e );
433 if( !typesRequested.count( item->Type() ) )
436 google::protobuf::Any itemBuf;
437 item->Serialize( itemBuf );
438 response.mutable_items()->Add( std::move( itemBuf ) );
441 response.set_status( ItemRequestStatus::IRS_OK );
KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
tl::expected< T, ApiResponseStatus > HANDLER_RESULT
API_HANDLER_BOARD(std::shared_ptr< BOARD_CONTEXT > aContext, EDA_BASE_FRAME *aFrame=nullptr)
PROJECT & project() const
HANDLER_RESULT< bool > validateDocument(const DocumentSpecifier &aDocument)
HANDLER_RESULT< std::optional< KIID > > validateItemHeaderDocument(const kiapi::common::types::ItemHeader &aHeader)
If the header is valid, returns the item container.
virtual std::optional< ApiResponseStatus > checkForBusy()
Checks if the editor can accept commands.
void registerHandler(HANDLER_RESULT< ResponseType >(HandlerType::*aHandler)(const HANDLER_CONTEXT< RequestType > &))
Registers an API command handler for the given message types.
void SetContentModified(bool aModified=true)
Abstract interface for BOARD_ITEMs capable of storing other items inside.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString Problem() const
what was the problem?
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
const wxString GetUniStringLibItemName() const
Get strings for display messages in dialogs.
const wxString GetUniStringLibNickname() const
const UTF8 & GetLibItemName() const
const UTF8 & GetLibNickname() const
Return the logical library name portion of a LIB_ID.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
static FOOTPRINT_LIBRARY_ADAPTER * FootprintLibAdapter(PROJECT *aProject)
Class to handle a set of BOARD_ITEMs.
RequestMessageType Request
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
@ PCB_ZONE_T
class ZONE, a copper pour area
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension