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() );
210 if( !
m_frame->CanAcceptApiCommands() )
213 e.set_status( ApiStatusCode::AS_BUSY );
214 e.set_error_message(
"KiCad is busy and cannot respond to API requests right now" );
225 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
226 return tl::unexpected( *busy );
228 CreateItemsResponse response;
233 [&](
const ItemStatus& aStatus,
const google::protobuf::Any& aItem )
235 ItemCreationResult itemResult;
236 itemResult.mutable_status()->CopyFrom( aStatus );
237 itemResult.mutable_item()->CopyFrom( aItem );
238 response.mutable_created_items()->Add( std::move( itemResult ) );
242 return tl::unexpected(
result.error() );
244 response.set_status( *
result );
252 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
253 return tl::unexpected( *busy );
255 UpdateItemsResponse response;
260 [&](
const ItemStatus& aStatus,
const google::protobuf::Any& aItem )
262 ItemUpdateResult itemResult;
263 itemResult.mutable_status()->CopyFrom( aStatus );
264 itemResult.mutable_item()->CopyFrom( aItem );
265 response.mutable_updated_items()->Add( std::move( itemResult ) );
269 return tl::unexpected(
result.error() );
271 response.set_status( *
result );
279 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
280 return tl::unexpected( *busy );
286 e.set_status( ApiStatusCode::AS_UNHANDLED );
287 return tl::unexpected( e );
290 std::map<KIID, ItemDeletionStatus> itemsToDelete;
292 for(
const kiapi::common::types::KIID& kiidBuf : aCtx.
Request.item_ids() )
294 if( !kiidBuf.value().empty() )
296 KIID kiid( kiidBuf.value() );
297 itemsToDelete[kiid] = ItemDeletionStatus::IDS_NONEXISTENT;
301 if( itemsToDelete.empty() )
304 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
305 e.set_error_message(
"no valid items to delete were given" );
306 return tl::unexpected( e );
311 DeleteItemsResponse response;
313 for(
const auto& [
id, status] : itemsToDelete )
315 ItemDeletionResult
result;
316 result.mutable_id()->set_value(
id.AsStdString() );
317 result.set_status( status );
320 response.set_status( kiapi::common::types::ItemRequestStatus::IRS_OK );
328 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
329 return tl::unexpected( *busy );
335 e.set_status( ApiStatusCode::AS_UNHANDLED );
336 return tl::unexpected( e );
339 HitTestResponse response;
347 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
348 e.set_error_message(
"the requested item ID is not present in the given document" );
349 return tl::unexpected( e );
353 response.set_result( HitTestResult::HTR_HIT );
355 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.