30using namespace kiapi::common::commands;
53 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
54 return tl::unexpected( *busy );
61 e.set_status( ApiStatusCode::AS_UNHANDLED );
62 return tl::unexpected( e );
68 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
69 e.set_error_message( fmt::format(
"the client {} already has a commit in progress",
71 return tl::unexpected( e );
76 BeginCommitResponse response;
80 response.mutable_id()->set_value(
id.AsStdString() );
91 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
92 return tl::unexpected( *busy );
99 e.set_status( ApiStatusCode::AS_UNHANDLED );
100 return tl::unexpected( e );
106 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
107 e.set_error_message( fmt::format(
"the client {} does not has a commit in progress",
109 return tl::unexpected( e );
115 const KIID&
id = pair.first;
116 const std::unique_ptr<COMMIT>& commit = pair.second;
118 EndCommitResponse response;
121 switch( aCtx.
Request.action() )
123 case kiapi::common::commands::CMA_DROP:
131 case kiapi::common::commands::CMA_COMMIT:
133 if( aCtx.
Request.id().value().compare(
id.AsStdString() ) != 0 )
136 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
137 e.set_error_message( fmt::format(
"the id {} does not match the commit in progress",
139 return tl::unexpected( e );
162 return m_commits.at( aClientName ).second.get();
167 const wxString& aMessage )
183 return tl::unexpected( validation.error() );
190 const types::ItemHeader& aHeader )
192 if( !aHeader.has_document() || aHeader.document().type() !=
thisDocumentType() )
195 e.set_status( ApiStatusCode::AS_UNHANDLED );
197 return tl::unexpected( e );
202 if( !documentValidation )
203 return tl::unexpected( documentValidation.error() );
206 return tl::unexpected(
result.error() );
208 if( aHeader.has_container() )
210 return KIID( aHeader.container().value() );
223 if( !
m_frame->CanAcceptApiCommands() )
226 e.set_status( ApiStatusCode::AS_BUSY );
227 e.set_error_message(
"KiCad is busy and cannot respond to API requests right now" );
238 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
239 return tl::unexpected( *busy );
241 CreateItemsResponse response;
246 [&](
const ItemStatus& aStatus,
const google::protobuf::Any& aItem )
248 ItemCreationResult itemResult;
249 itemResult.mutable_status()->CopyFrom( aStatus );
250 itemResult.mutable_item()->CopyFrom( aItem );
251 response.mutable_created_items()->Add( std::move( itemResult ) );
255 return tl::unexpected(
result.error() );
257 response.set_status( *
result );
265 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
266 return tl::unexpected( *busy );
268 UpdateItemsResponse response;
273 [&](
const ItemStatus& aStatus,
const google::protobuf::Any& aItem )
275 ItemUpdateResult itemResult;
276 itemResult.mutable_status()->CopyFrom( aStatus );
277 itemResult.mutable_item()->CopyFrom( aItem );
278 response.mutable_updated_items()->Add( std::move( itemResult ) );
282 return tl::unexpected(
result.error() );
284 response.set_status( *
result );
292 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
293 return tl::unexpected( *busy );
299 e.set_status( ApiStatusCode::AS_UNHANDLED );
300 return tl::unexpected( e );
303 std::map<KIID, ItemDeletionStatus> itemsToDelete;
305 for(
const kiapi::common::types::KIID& kiidBuf : aCtx.
Request.item_ids() )
307 if( !kiidBuf.value().empty() )
309 KIID kiid( kiidBuf.value() );
310 itemsToDelete[kiid] = ItemDeletionStatus::IDS_NONEXISTENT;
314 if( itemsToDelete.empty() )
317 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
318 e.set_error_message(
"no valid items to delete were given" );
319 return tl::unexpected( e );
324 DeleteItemsResponse response;
326 for(
const auto& [
id, status] : itemsToDelete )
328 ItemDeletionResult*
result = response.add_deleted_items();
329 result->mutable_id()->set_value(
id.AsStdString() );
330 result->set_status( status );
333 response.set_status( kiapi::common::types::ItemRequestStatus::IRS_OK );
341 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
342 return tl::unexpected( *busy );
348 e.set_status( ApiStatusCode::AS_UNHANDLED );
349 return tl::unexpected( e );
352 HitTestResponse response;
360 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
361 e.set_error_message(
"the requested item ID is not present in the given document" );
362 return tl::unexpected( e );
367 int toleranceIu =
scale.NmToIU( aCtx.
Request.tolerance() );
369 if( ( *item )->HitTest( posIu, toleranceIu ) )
370 response.set_result( HitTestResult::HTR_HIT );
372 response.set_result( HitTestResult::HTR_NO_HIT );
382 return tl::unexpected( documentValidation.error() );
384 GetDocumentModifiedStateResponse response;
387 response.set_state(
m_frame->IsContentModified() ? DocumentModifiedState::DMS_MODIFIED
388 : DocumentModifiedState::DMS_UNMODIFIED );
395 std::vector<KICAD_T>
types;
397 for(
int typeRaw : aTypes )
399 auto typeMessage =
static_cast<types::KiCadObjectType
>( typeRaw );
402 types.emplace_back( type );
414 if( !documentValidation )
415 return tl::unexpected( documentValidation.error() );
422 e.set_status( AS_BAD_REQUEST );
423 e.set_error_message(
"this editor does not support a title block" );
424 return tl::unexpected( e );
429 types::TitleBlockInfo response;
431 response.set_title( block.
GetTitle().ToUTF8() );
432 response.set_date( block.
GetDate().ToUTF8() );
433 response.set_revision( block.
GetRevision().ToUTF8() );
434 response.set_company( block.
GetCompany().ToUTF8() );
435 response.set_comment1( block.
GetComment( 0 ).ToUTF8() );
436 response.set_comment2( block.
GetComment( 1 ).ToUTF8() );
437 response.set_comment3( block.
GetComment( 2 ).ToUTF8() );
438 response.set_comment4( block.
GetComment( 3 ).ToUTF8() );
439 response.set_comment5( block.
GetComment( 4 ).ToUTF8() );
440 response.set_comment6( block.
GetComment( 5 ).ToUTF8() );
441 response.set_comment7( block.
GetComment( 6 ).ToUTF8() );
442 response.set_comment8( block.
GetComment( 7 ).ToUTF8() );
443 response.set_comment9( block.
GetComment( 8 ).ToUTF8() );
454 if( !documentValidation )
455 return tl::unexpected( documentValidation.error() );
457 if( !aCtx.
Request.has_title_block() )
460 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
461 e.set_error_message(
"SetTitleBlockInfo requires title_block" );
462 return tl::unexpected( e );
470 e.set_status( AS_BAD_REQUEST );
471 e.set_error_message(
"this editor does not support a title block" );
472 return tl::unexpected( e );
477 const types::TitleBlockInfo& request = aCtx.
Request.title_block();
479 block.
SetTitle( wxString::FromUTF8( request.title() ) );
480 block.
SetDate( wxString::FromUTF8( request.date() ) );
481 block.
SetRevision( wxString::FromUTF8( request.revision() ) );
482 block.
SetCompany( wxString::FromUTF8( request.company() ) );
483 block.
SetComment( 0, wxString::FromUTF8( request.comment1() ) );
484 block.
SetComment( 1, wxString::FromUTF8( request.comment2() ) );
485 block.
SetComment( 2, wxString::FromUTF8( request.comment3() ) );
486 block.
SetComment( 3, wxString::FromUTF8( request.comment4() ) );
487 block.
SetComment( 4, wxString::FromUTF8( request.comment5() ) );
488 block.
SetComment( 5, wxString::FromUTF8( request.comment6() ) );
489 block.
SetComment( 6, wxString::FromUTF8( request.comment7() ) );
490 block.
SetComment( 7, wxString::FromUTF8( request.comment8() ) );
491 block.
SetComment( 8, wxString::FromUTF8( request.comment9() ) );
495 return google::protobuf::Empty();
504 if( !documentValidation )
505 return tl::unexpected( documentValidation.error() );
512 e.set_status( AS_BAD_REQUEST );
513 e.set_error_message(
"this editor does not support page settings" );
514 return tl::unexpected( e );
519 types::PageSettings response;
525 response.set_orientation( pageInfo.
IsPortrait() ? types::PageOrientation::PO_PORTRAIT
526 : types::PageOrientation::PO_LANDSCAPE );
538 if( !documentValidation )
539 return tl::unexpected( documentValidation.error() );
541 if( !aCtx.
Request.has_page_settings() )
544 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
545 e.set_error_message(
"SetPageSettings requires page_settings" );
546 return tl::unexpected( e );
554 e.set_status( AS_BAD_REQUEST );
555 e.set_error_message(
"this editor does not support page settings" );
556 return tl::unexpected( e );
559 const types::PageSettings& request = aCtx.
Request.page_settings();
566 if( !request.has_user_page_size() )
569 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
570 e.set_error_message(
"custom page size requires user_page_size" );
571 return tl::unexpected( e );
582 bool portrait = ( request.orientation() == types::PageOrientation::PO_PORTRAIT );
583 pageInfo.
SetType( pageSizeType, portrait );
589 e.set_status( AS_BAD_REQUEST );
590 e.set_error_message(
"this editor does not support page settings" );
591 return tl::unexpected( e );
594 wxString drawingSheet( wxString::FromUTF8( request.drawing_sheet() ) );
599 types::PageSettings response;
605 response.set_orientation( pageInfo.
IsPortrait() ? types::PageOrientation::PO_PORTRAIT
606 : types::PageOrientation::PO_LANDSCAPE );
KICOMMON_API types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICOMMON_API KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
tl::expected< T, ApiResponseStatus > HANDLER_RESULT
constexpr EDA_IU_SCALE pcbIUScale
virtual std::unique_ptr< COMMIT > createCommit()=0
Override this to create an appropriate COMMIT subclass for the frame in question.
virtual bool setPageSettings(const DocumentSpecifier &aDocument, const PAGE_INFO &aPageInfo)
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)
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)
virtual std::optional< PAGE_INFO > getPageSettings(const DocumentSpecifier &aDocument)
virtual HANDLER_RESULT< commands::GetDocumentModifiedStateResponse > handleGetDocumentModifiedState(const HANDLER_CONTEXT< commands::GetDocumentModifiedState > &aCtx)
virtual std::optional< TITLE_BLOCK * > getTitleBlock(const DocumentSpecifier &aDocument)
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
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