27using namespace kiapi::common::commands;
46 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
47 return tl::unexpected( *busy );
52 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
53 e.set_error_message( fmt::format(
"the client {} already has a commit in progress",
55 return tl::unexpected( e );
60 BeginCommitResponse response;
64 response.mutable_id()->set_value(
id.AsStdString() );
75 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
76 return tl::unexpected( *busy );
81 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
82 e.set_error_message( fmt::format(
"the client {} does not has a commit in progress",
84 return tl::unexpected( e );
90 const KIID&
id = pair.first;
91 const std::unique_ptr<COMMIT>& commit = pair.second;
93 EndCommitResponse response;
98 case kiapi::common::commands::CMA_DROP:
106 case kiapi::common::commands::CMA_COMMIT:
108 if( aCtx.
Request.id().value().compare(
id.AsStdString() ) != 0 )
111 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
112 e.set_error_message( fmt::format(
"the id {} does not match the commit in progress",
114 return tl::unexpected( e );
137 return m_commits.at( aClientName ).second.get();
142 const wxString& aMessage )
160 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
161 e.set_error_message( fmt::format(
"the requested document {} is not open",
162 aDocument.board_filename() ) );
163 return tl::unexpected( e );
171 const types::ItemHeader& aHeader )
173 if( !aHeader.has_document() || aHeader.document().type() !=
thisDocumentType() )
176 e.set_status( ApiStatusCode::AS_UNHANDLED );
178 return tl::unexpected( e );
183 if( !documentValidation )
184 return tl::unexpected( documentValidation.error() );
189 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
190 e.set_error_message( fmt::format(
"the requested document {} is not open",
191 aHeader.document().board_filename() ) );
192 return tl::unexpected( e );
195 if( aHeader.has_container() )
197 return KIID( aHeader.container().value() );
207 if( !
m_frame->CanAcceptApiCommands() )
210 e.set_status( ApiStatusCode::AS_BUSY );
211 e.set_error_message(
"KiCad is busy and cannot respond to API requests right now" );
222 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
223 return tl::unexpected( *busy );
225 CreateItemsResponse response;
230 [&](
const ItemStatus& aStatus,
const google::protobuf::Any& aItem )
232 ItemCreationResult itemResult;
233 itemResult.mutable_status()->CopyFrom( aStatus );
234 itemResult.mutable_item()->CopyFrom( aItem );
235 response.mutable_created_items()->Add( std::move( itemResult ) );
239 return tl::unexpected(
result.error() );
241 response.set_status( *
result );
249 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
250 return tl::unexpected( *busy );
252 UpdateItemsResponse response;
257 [&](
const ItemStatus& aStatus,
const google::protobuf::Any& aItem )
259 ItemUpdateResult itemResult;
260 itemResult.mutable_status()->CopyFrom( aStatus );
261 itemResult.mutable_item()->CopyFrom( aItem );
262 response.mutable_updated_items()->Add( std::move( itemResult ) );
266 return tl::unexpected(
result.error() );
268 response.set_status( *
result );
276 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
277 return tl::unexpected( *busy );
283 e.set_status( ApiStatusCode::AS_UNHANDLED );
284 return tl::unexpected( e );
287 std::map<KIID, ItemDeletionStatus> itemsToDelete;
289 for(
const kiapi::common::types::KIID& kiidBuf : aCtx.
Request.item_ids() )
291 if( !kiidBuf.value().empty() )
293 KIID kiid( kiidBuf.value() );
294 itemsToDelete[kiid] = ItemDeletionStatus::IDS_NONEXISTENT;
298 if( itemsToDelete.empty() )
301 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
302 e.set_error_message(
"no valid items to delete were given" );
303 return tl::unexpected( e );
308 DeleteItemsResponse response;
310 for(
const auto& [
id, status] : itemsToDelete )
312 ItemDeletionResult
result;
313 result.mutable_id()->set_value(
id.AsStdString() );
314 result.set_status( status );
317 response.set_status( kiapi::common::types::ItemRequestStatus::IRS_OK );
325 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
326 return tl::unexpected( *busy );
332 e.set_status( ApiStatusCode::AS_UNHANDLED );
333 return tl::unexpected( e );
336 HitTestResponse response;
344 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
345 e.set_error_message(
"the requested item ID is not present in the given document" );
346 return tl::unexpected( e );
350 response.set_result( HitTestResult::HTR_HIT );
352 response.set_result( HitTestResult::HTR_NO_HIT );
tl::expected< T, ApiResponseStatus > HANDLER_RESULT
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)
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.
HANDLER_RESULT< commands::EndCommitResponse > handleEndCommit(const HANDLER_CONTEXT< commands::EndCommit > &aCtx)
API_HANDLER_EDITOR(EDA_BASE_FRAME *aFrame=nullptr)
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 std::optional< ApiResponseStatus > checkForBusy()
Checks if the editor can accept commands.
virtual types::DocumentType thisDocumentType() const =0
Override this to specify which document type this editor handles.
HANDLER_RESULT< commands::BeginCommitResponse > handleBeginCommit(const HANDLER_CONTEXT< commands::BeginCommit > &aCtx)
HANDLER_RESULT< commands::HitTestResponse > handleHitTest(const HANDLER_CONTEXT< commands::HitTest > &aCtx)
virtual bool validateDocumentInternal(const DocumentSpecifier &aDocument) const =0
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.
Base window classes and related definitions.
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput)
RequestMessageType Request
wxString result
Test unit parsing edge cases and error handling.