30using namespace kiapi::common::commands;
51 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
52 return tl::unexpected( *busy );
59 e.set_status( ApiStatusCode::AS_UNHANDLED );
60 return tl::unexpected( e );
66 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
67 e.set_error_message( fmt::format(
"the client {} already has a commit in progress",
69 return tl::unexpected( e );
74 BeginCommitResponse response;
78 response.mutable_id()->set_value(
id.AsStdString() );
89 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
90 return tl::unexpected( *busy );
97 e.set_status( ApiStatusCode::AS_UNHANDLED );
98 return tl::unexpected( e );
104 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
105 e.set_error_message( fmt::format(
"the client {} does not has a commit in progress",
107 return tl::unexpected( e );
113 const KIID&
id = pair.first;
114 const std::unique_ptr<COMMIT>& commit = pair.second;
116 EndCommitResponse response;
119 switch( aCtx.
Request.action() )
121 case kiapi::common::commands::CMA_DROP:
129 case kiapi::common::commands::CMA_COMMIT:
131 if( aCtx.
Request.id().value().compare(
id.AsStdString() ) != 0 )
134 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
135 e.set_error_message( fmt::format(
"the id {} does not match the commit in progress",
137 return tl::unexpected( e );
160 return m_commits.at( aClientName ).second.get();
165 const wxString& aMessage )
183 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
184 e.set_error_message( fmt::format(
"the requested document {} is not open",
185 aDocument.board_filename() ) );
186 return tl::unexpected( e );
194 const types::ItemHeader& aHeader )
196 if( !aHeader.has_document() || aHeader.document().type() !=
thisDocumentType() )
199 e.set_status( ApiStatusCode::AS_UNHANDLED );
201 return tl::unexpected( e );
206 if( !documentValidation )
207 return tl::unexpected( documentValidation.error() );
210 return tl::unexpected(
result.error() );
212 if( aHeader.has_container() )
214 return KIID( aHeader.container().value() );
227 if( !
m_frame->CanAcceptApiCommands() )
230 e.set_status( ApiStatusCode::AS_BUSY );
231 e.set_error_message(
"KiCad is busy and cannot respond to API requests right now" );
242 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
243 return tl::unexpected( *busy );
245 CreateItemsResponse response;
250 [&](
const ItemStatus& aStatus,
const google::protobuf::Any& aItem )
252 ItemCreationResult itemResult;
253 itemResult.mutable_status()->CopyFrom( aStatus );
254 itemResult.mutable_item()->CopyFrom( aItem );
255 response.mutable_created_items()->Add( std::move( itemResult ) );
259 return tl::unexpected(
result.error() );
261 response.set_status( *
result );
269 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
270 return tl::unexpected( *busy );
272 UpdateItemsResponse response;
277 [&](
const ItemStatus& aStatus,
const google::protobuf::Any& aItem )
279 ItemUpdateResult itemResult;
280 itemResult.mutable_status()->CopyFrom( aStatus );
281 itemResult.mutable_item()->CopyFrom( aItem );
282 response.mutable_updated_items()->Add( std::move( itemResult ) );
286 return tl::unexpected(
result.error() );
288 response.set_status( *
result );
296 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
297 return tl::unexpected( *busy );
303 e.set_status( ApiStatusCode::AS_UNHANDLED );
304 return tl::unexpected( e );
307 std::map<KIID, ItemDeletionStatus> itemsToDelete;
309 for(
const kiapi::common::types::KIID& kiidBuf : aCtx.
Request.item_ids() )
311 if( !kiidBuf.value().empty() )
313 KIID kiid( kiidBuf.value() );
314 itemsToDelete[kiid] = ItemDeletionStatus::IDS_NONEXISTENT;
318 if( itemsToDelete.empty() )
321 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
322 e.set_error_message(
"no valid items to delete were given" );
323 return tl::unexpected( e );
328 DeleteItemsResponse response;
330 for(
const auto& [
id, status] : itemsToDelete )
332 ItemDeletionResult
result;
333 result.mutable_id()->set_value(
id.AsStdString() );
334 result.set_status( status );
337 response.set_status( kiapi::common::types::ItemRequestStatus::IRS_OK );
345 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
346 return tl::unexpected( *busy );
352 e.set_status( ApiStatusCode::AS_UNHANDLED );
353 return tl::unexpected( e );
356 HitTestResponse response;
364 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
365 e.set_error_message(
"the requested item ID is not present in the given document" );
366 return tl::unexpected( e );
371 int toleranceIu =
scale.NmToIU( aCtx.
Request.tolerance() );
373 if( ( *item )->HitTest( posIu, toleranceIu ) )
374 response.set_result( HitTestResult::HTR_HIT );
376 response.set_result( HitTestResult::HTR_NO_HIT );
384 std::vector<KICAD_T> types;
386 for(
int typeRaw : aTypes )
388 auto typeMessage =
static_cast<types::KiCadObjectType
>( typeRaw );
391 types.emplace_back( type );
403 if( !documentValidation )
404 return tl::unexpected( documentValidation.error() );
411 e.set_status( AS_BAD_REQUEST );
412 e.set_error_message(
"this editor does not support a title block" );
413 return tl::unexpected( e );
418 types::TitleBlockInfo response;
420 response.set_title( block.
GetTitle().ToUTF8() );
421 response.set_date( block.
GetDate().ToUTF8() );
422 response.set_revision( block.
GetRevision().ToUTF8() );
423 response.set_company( block.
GetCompany().ToUTF8() );
424 response.set_comment1( block.
GetComment( 0 ).ToUTF8() );
425 response.set_comment2( block.
GetComment( 1 ).ToUTF8() );
426 response.set_comment3( block.
GetComment( 2 ).ToUTF8() );
427 response.set_comment4( block.
GetComment( 3 ).ToUTF8() );
428 response.set_comment5( block.
GetComment( 4 ).ToUTF8() );
429 response.set_comment6( block.
GetComment( 5 ).ToUTF8() );
430 response.set_comment7( block.
GetComment( 6 ).ToUTF8() );
431 response.set_comment8( block.
GetComment( 7 ).ToUTF8() );
432 response.set_comment9( block.
GetComment( 8 ).ToUTF8() );
443 if( !documentValidation )
444 return tl::unexpected( documentValidation.error() );
446 if( !aCtx.
Request.has_title_block() )
449 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
450 e.set_error_message(
"SetTitleBlockInfo requires title_block" );
451 return tl::unexpected( e );
459 e.set_status( AS_BAD_REQUEST );
460 e.set_error_message(
"this editor does not support a title block" );
461 return tl::unexpected( e );
466 const types::TitleBlockInfo& request = aCtx.
Request.title_block();
468 block.
SetTitle( wxString::FromUTF8( request.title() ) );
469 block.
SetDate( wxString::FromUTF8( request.date() ) );
470 block.
SetRevision( wxString::FromUTF8( request.revision() ) );
471 block.
SetCompany( wxString::FromUTF8( request.company() ) );
472 block.
SetComment( 0, wxString::FromUTF8( request.comment1() ) );
473 block.
SetComment( 1, wxString::FromUTF8( request.comment2() ) );
474 block.
SetComment( 2, wxString::FromUTF8( request.comment3() ) );
475 block.
SetComment( 3, wxString::FromUTF8( request.comment4() ) );
476 block.
SetComment( 4, wxString::FromUTF8( request.comment5() ) );
477 block.
SetComment( 5, wxString::FromUTF8( request.comment6() ) );
478 block.
SetComment( 6, wxString::FromUTF8( request.comment7() ) );
479 block.
SetComment( 7, wxString::FromUTF8( request.comment8() ) );
480 block.
SetComment( 8, wxString::FromUTF8( request.comment9() ) );
484 return google::protobuf::Empty();
493 if( !documentValidation )
494 return tl::unexpected( documentValidation.error() );
501 e.set_status( AS_BAD_REQUEST );
502 e.set_error_message(
"this editor does not support page settings" );
503 return tl::unexpected( e );
508 types::PageSettings response;
514 response.set_orientation( pageInfo.
IsPortrait() ? types::PageOrientation::PO_PORTRAIT
515 : types::PageOrientation::PO_LANDSCAPE );
527 if( !documentValidation )
528 return tl::unexpected( documentValidation.error() );
530 if( !aCtx.
Request.has_page_settings() )
533 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
534 e.set_error_message(
"SetPageSettings requires page_settings" );
535 return tl::unexpected( e );
543 e.set_status( AS_BAD_REQUEST );
544 e.set_error_message(
"this editor does not support page settings" );
545 return tl::unexpected( e );
548 const types::PageSettings& request = aCtx.
Request.page_settings();
555 if( !request.has_user_page_size() )
558 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
559 e.set_error_message(
"custom page size requires user_page_size" );
560 return tl::unexpected( e );
571 bool portrait = ( request.orientation() == types::PageOrientation::PO_PORTRAIT );
572 pageInfo.
SetType( pageSizeType, portrait );
578 e.set_status( AS_BAD_REQUEST );
579 e.set_error_message(
"this editor does not support page settings" );
580 return tl::unexpected( e );
583 wxString drawingSheet( wxString::FromUTF8( request.drawing_sheet() ) );
588 types::PageSettings response;
594 response.set_orientation( pageInfo.
IsPortrait() ? types::PageOrientation::PO_PORTRAIT
595 : types::PageOrientation::PO_LANDSCAPE );
types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
tl::expected< T, ApiResponseStatus > HANDLER_RESULT
constexpr EDA_IU_SCALE pcbIUScale
virtual std::optional< PAGE_INFO > getPageSettings()
virtual std::unique_ptr< COMMIT > createCommit()=0
Override this to create an appropriate COMMIT subclass for the frame in question.
HANDLER_RESULT< bool > validateDocument(const DocumentSpecifier &aDocument)
HANDLER_RESULT< commands::DeleteItemsResponse > handleDeleteItems(const HANDLER_CONTEXT< commands::DeleteItems > &aCtx)
HANDLER_RESULT< types::PageSettings > handleSetPageSettings(const HANDLER_CONTEXT< commands::SetPageSettings > &aCtx)
virtual const EDA_IU_SCALE & getIuScale() const
Returns the internal-unit scale that the concrete editor uses.
virtual std::optional< EDA_ITEM * > getItemFromDocument(const DocumentSpecifier &aDocument, const KIID &aId)=0
HANDLER_RESULT< std::optional< KIID > > validateItemHeaderDocument(const kiapi::common::types::ItemHeader &aHeader)
If the header is valid, returns the item container.
virtual void setDrawingSheetFileName(const wxString &aFileName)
HANDLER_RESULT< types::PageSettings > handleGetPageSettings(const HANDLER_CONTEXT< commands::GetPageSettings > &aCtx)
virtual std::optional< TITLE_BLOCK * > getTitleBlock()
HANDLER_RESULT< commands::EndCommitResponse > handleEndCommit(const HANDLER_CONTEXT< commands::EndCommit > &aCtx)
virtual tl::expected< bool, ApiResponseStatus > validateDocumentInternal(const DocumentSpecifier &aDocument) const =0
API_HANDLER_EDITOR(EDA_BASE_FRAME *aFrame=nullptr)
static std::vector< KICAD_T > parseRequestedItemTypes(const google::protobuf::RepeatedField< int > &aTypes)
HANDLER_RESULT< commands::CreateItemsResponse > handleCreateItems(const HANDLER_CONTEXT< commands::CreateItems > &aCtx)
COMMIT * getCurrentCommit(const std::string &aClientName)
virtual void pushCurrentCommit(const std::string &aClientName, const wxString &aMessage)
virtual HANDLER_RESULT< ItemRequestStatus > handleCreateUpdateItemsInternal(bool aCreate, const std::string &aClientName, const types::ItemHeader &aHeader, const google::protobuf::RepeatedPtrField< google::protobuf::Any > &aItems, std::function< void(commands::ItemStatus, google::protobuf::Any)> aItemHandler)=0
std::set< std::string > m_activeClients
std::map< std::string, std::pair< KIID, std::unique_ptr< COMMIT > > > m_commits
virtual bool setPageSettings(const PAGE_INFO &aPageInfo)
HANDLER_RESULT< commands::UpdateItemsResponse > handleUpdateItems(const HANDLER_CONTEXT< commands::UpdateItems > &aCtx)
virtual void deleteItemsInternal(std::map< KIID, ItemDeletionStatus > &aItemsToDelete, const std::string &aClientName)=0
virtual wxString getDrawingSheetFileName()
virtual std::optional< ApiResponseStatus > checkForBusy()
Checks if the editor can accept commands.
HANDLER_RESULT< types::TitleBlockInfo > handleGetTitleBlockInfo(const HANDLER_CONTEXT< commands::GetTitleBlockInfo > &aCtx)
virtual types::DocumentType thisDocumentType() const =0
Override this to specify which document type this editor handles.
HANDLER_RESULT< google::protobuf::Empty > handleSetTitleBlockInfo(const HANDLER_CONTEXT< commands::SetTitleBlockInfo > &aCtx)
HANDLER_RESULT< commands::BeginCommitResponse > handleBeginCommit(const HANDLER_CONTEXT< commands::BeginCommit > &aCtx)
virtual void onModified()
HANDLER_RESULT< commands::HitTestResponse > handleHitTest(const HANDLER_CONTEXT< commands::HitTest > &aCtx)
static const wxString m_defaultCommitMessage
void registerHandler(HANDLER_RESULT< ResponseType >(HandlerType::*aHandler)(const HANDLER_CONTEXT< RequestType > &))
Registers an API command handler for the given message types.
Represent a set of changes (additions, deletions or modifications) of a data model (e....
The base frame for deriving all KiCad main window classes.
Describe the page size and margins of a paper page on which to eventually print or plot.
bool SetType(PAGE_SIZE_TYPE aPageSize, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
static void SetCustomWidthMils(double aWidthInMils)
Set the width of Custom page in mils for any custom page constructed or made via SetType() after maki...
const VECTOR2D GetSizeIU(double aIUScale) const
Gets the page size in internal units.
static void SetCustomHeightMils(double aHeightInMils)
Set the height of Custom page in mils for any custom page constructed or made via SetType() after mak...
const PAGE_SIZE_TYPE & GetType() const
Hold the information shown in the lower right corner of a plot, printout, or editing view.
const wxString & GetCompany() const
void SetRevision(const wxString &aRevision)
void SetComment(int aIdx, const wxString &aComment)
const wxString & GetRevision() const
void SetTitle(const wxString &aTitle)
const wxString & GetDate() const
const wxString & GetComment(int aIdx) const
void SetCompany(const wxString &aCompany)
const wxString & GetTitle() const
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
Base window classes and related definitions.
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput, const EDA_IU_SCALE &aScale)
RequestMessageType Request
wxString result
Test unit parsing edge cases and error handling.
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D