21#include <magic_enum.hpp>
50#include <api/common/types/base_types.pb.h>
54using namespace kiapi::common::commands;
55using types::CommandStatus;
56using types::DocumentType;
57using types::ItemRequestStatus;
133 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
134 return tl::unexpected( *busy );
136 RunActionResponse response;
138 if(
frame()->GetToolManager()->RunAction( aCtx.
Request.action(),
true ) )
139 response.set_status( RunActionStatus::RAS_OK );
141 response.set_status( RunActionStatus::RAS_INVALID );
150 if( aCtx.
Request.type() != DocumentType::DOCTYPE_PCB )
154 e.set_status( ApiStatusCode::AS_UNHANDLED );
155 return tl::unexpected( e );
158 GetOpenDocumentsResponse response;
159 common::types::DocumentSpecifier doc;
161 wxFileName fn(
frame()->GetCurrentFileName() );
163 doc.set_type( DocumentType::DOCTYPE_PCB );
164 doc.set_board_filename( fn.GetFullName() );
166 doc.mutable_project()->set_name(
frame()->
Prj().GetProjectName().ToStdString() );
167 doc.mutable_project()->set_path(
frame()->
Prj().GetProjectDirectory().ToStdString() );
169 response.mutable_documents()->Add( std::move( doc ) );
177 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
178 return tl::unexpected( *busy );
182 if( !documentValidation )
183 return tl::unexpected( documentValidation.error() );
193 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
194 return tl::unexpected( *busy );
198 if( !documentValidation )
199 return tl::unexpected( documentValidation.error() );
201 wxFileName boardPath(
frame()->
Prj().AbsolutePath( wxString::FromUTF8( aCtx.
Request.path() ) ) );
203 if( !boardPath.IsOk() || !boardPath.IsDirWritable() )
206 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
207 e.set_error_message( fmt::format(
"save path '{}' could not be opened",
208 boardPath.GetFullPath().ToStdString() ) );
209 return tl::unexpected( e );
212 if( boardPath.FileExists()
213 && ( !boardPath.IsFileWritable() || !aCtx.
Request.options().overwrite() ) )
216 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
217 e.set_error_message( fmt::format(
"save path '{}' exists and cannot be overwritten",
218 boardPath.GetFullPath().ToStdString() ) );
219 return tl::unexpected( e );
225 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
226 e.set_error_message( fmt::format(
"save path '{}' must have a kicad_pcb extension",
227 boardPath.GetFullPath().ToStdString() ) );
228 return tl::unexpected( e );
233 if(
board->GetFileName().Matches( boardPath.GetFullPath() ) )
239 bool includeProject =
true;
241 if( aCtx.
Request.has_options() )
242 includeProject = aCtx.
Request.options().include_project();
253 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
254 return tl::unexpected( *busy );
258 if( !documentValidation )
259 return tl::unexpected( documentValidation.error() );
280 return std::make_unique<BOARD_COMMIT>(
frame() );
297 if( aDocument.type() != DocumentType::DOCTYPE_PCB )
300 wxFileName fn(
frame()->GetCurrentFileName() );
301 return 0 == aDocument.board_filename().compare( fn.GetFullName() );
311 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
312 e.set_error_message(
"Tried to create an item in a null container" );
313 return tl::unexpected( e );
319 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
320 e.set_error_message( fmt::format(
"Tried to create a pad in {}, which is not a footprint",
322 return tl::unexpected( e );
327 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
328 e.set_error_message( fmt::format(
"Tried to create a footprint in {}, which is not a board",
330 return tl::unexpected( e );
338 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
339 e.set_error_message( fmt::format(
"Tried to create an item of type {}, which is unhandled",
340 magic_enum::enum_name( aType ) ) );
341 return tl::unexpected( e );
349 const std::string& aClientName,
350 const types::ItemHeader &aHeader,
351 const google::protobuf::RepeatedPtrField<google::protobuf::Any>& aItems,
352 std::function<
void( ItemStatus, google::protobuf::Any )> aItemHandler )
358 if( !containerResult && containerResult.error().status() == ApiStatusCode::AS_UNHANDLED )
361 e.set_status( ApiStatusCode::AS_UNHANDLED );
362 return tl::unexpected( e );
364 else if( !containerResult )
366 e.CopyFrom( containerResult.error() );
367 return tl::unexpected( e );
373 if( containerResult->has_value() )
375 const KIID& containerId = **containerResult;
376 std::optional<BOARD_ITEM*> optItem =
getItemById( containerId );
384 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
385 e.set_error_message( fmt::format(
386 "The requested container {} is not a valid board item container",
388 return tl::unexpected( e );
393 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
394 e.set_error_message( fmt::format(
395 "The requested container {} does not exist in this document",
397 return tl::unexpected( e );
403 for(
const google::protobuf::Any& anyItem : aItems )
410 status.set_code( ItemStatusCode::ISC_INVALID_TYPE );
411 status.set_error_message( fmt::format(
"Could not decode a valid type from {}",
412 anyItem.type_url() ) );
413 aItemHandler( status, anyItem );
419 board::types::Dimension dimension;
420 anyItem.UnpackTo( &dimension );
422 switch( dimension.dimension_style_case() )
429 case board::types::Dimension::DIMENSION_STYLE_NOT_SET:
break;
436 if( !creationResult )
438 status.set_code( ItemStatusCode::ISC_INVALID_TYPE );
439 status.set_error_message( creationResult.error().error_message() );
440 aItemHandler( status, anyItem );
444 std::unique_ptr<BOARD_ITEM> item( std::move( *creationResult ) );
446 if( !item->Deserialize( anyItem ) )
448 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
449 e.set_error_message( fmt::format(
"could not unpack {} from request",
450 item->GetClass().ToStdString() ) );
451 return tl::unexpected( e );
454 std::optional<BOARD_ITEM*> optItem =
getItemById( item->m_Uuid );
456 if( aCreate && optItem )
458 status.set_code( ItemStatusCode::ISC_EXISTING );
459 status.set_error_message( fmt::format(
"an item with UUID {} already exists",
460 item->m_Uuid.AsStdString() ) );
461 aItemHandler( status, anyItem );
464 else if( !aCreate && !optItem )
466 status.set_code( ItemStatusCode::ISC_NONEXISTENT );
467 status.set_error_message( fmt::format(
"an item with UUID {} does not exist",
468 item->m_Uuid.AsStdString() ) );
469 aItemHandler( status, anyItem );
473 if( aCreate && !(
board->GetEnabledLayers() & item->GetLayerSet() ).any() )
475 status.set_code( ItemStatusCode::ISC_INVALID_DATA );
476 status.set_error_message(
477 "attempted to add item with no overlapping layers with the board" );
478 aItemHandler( status, anyItem );
482 status.set_code( ItemStatusCode::ISC_OK );
483 google::protobuf::Any newItem;
499 item->Serialize( newItem );
500 commit->
Add( item.release() );
517 commit->
Remove( boardItem );
518 item->Serialize( newItem );
521 commit->
Add( newBoardItem );
525 parentGroup->
AddItem( newBoardItem );
529 commit->
Modify( boardItem );
535 aItemHandler( status, newItem );
541 :
_(
"Modified items via API" ) );
545 return ItemRequestStatus::IRS_OK;
551 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
552 return tl::unexpected( *busy );
558 e.set_status( ApiStatusCode::AS_UNHANDLED );
559 return tl::unexpected( e );
562 GetItemsResponse response;
565 std::vector<BOARD_ITEM*> items;
566 std::set<KICAD_T> typesRequested, typesInserted;
567 bool handledAnything =
false;
569 for(
int typeRaw : aCtx.
Request.types() )
571 auto typeMessage =
static_cast<common::types::KiCadObjectType
>( typeRaw );
577 typesRequested.emplace( type );
579 if( typesInserted.count( type ) )
587 handledAnything =
true;
588 std::copy(
board->Tracks().begin(),
board->Tracks().end(),
589 std::back_inserter( items ) );
595 handledAnything =
true;
599 std::copy( fp->Pads().begin(), fp->Pads().end(),
600 std::back_inserter( items ) );
609 handledAnything =
true;
611 std::copy(
board->Footprints().begin(),
board->Footprints().end(),
612 std::back_inserter( items ) );
623 handledAnything =
true;
624 bool inserted =
false;
628 if( item->Type() == type )
630 items.emplace_back( item );
636 typesInserted.insert( type );
643 handledAnything =
true;
645 std::copy(
board->Zones().begin(),
board->Zones().end(),
646 std::back_inserter( items ) );
654 handledAnything =
true;
656 std::copy(
board->Groups().begin(),
board->Groups().end(),
657 std::back_inserter( items ) );
667 if( !handledAnything )
670 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
671 e.set_error_message(
"none of the requested types are valid for a Board object" );
672 return tl::unexpected( e );
677 if( !typesRequested.count( item->Type() ) )
680 google::protobuf::Any itemBuf;
681 item->Serialize( itemBuf );
682 response.mutable_items()->Add( std::move( itemBuf ) );
685 response.set_status( ItemRequestStatus::IRS_OK );
693 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
694 return tl::unexpected( *busy );
699 e.set_status( ApiStatusCode::AS_UNHANDLED );
700 return tl::unexpected( e );
703 GetItemsResponse response;
705 std::vector<BOARD_ITEM*> items;
707 for(
const kiapi::common::types::KIID&
id : aCtx.
Request.items() )
709 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
710 items.emplace_back( *item );
716 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
717 e.set_error_message(
"none of the requested IDs were found or valid" );
718 return tl::unexpected( e );
723 google::protobuf::Any itemBuf;
724 item->Serialize( itemBuf );
725 response.mutable_items()->Add( std::move( itemBuf ) );
728 response.set_status( ItemRequestStatus::IRS_OK );
733 const std::string& aClientName )
736 std::vector<BOARD_ITEM*> validatedItems;
738 for( std::pair<const KIID, ItemDeletionStatus> pair : aItemsToDelete )
742 validatedItems.push_back( item );
743 aItemsToDelete[pair.first] = ItemDeletionStatus::IDS_OK;
777 e.set_status( ApiStatusCode::AS_UNHANDLED );
778 return tl::unexpected( e );
783 for(
int typeRaw : aCtx.
Request.types() )
785 auto typeMessage =
static_cast<types::KiCadObjectType
>( typeRaw );
797 SelectionResponse response;
802 item->Serialize( *response.add_items() );
812 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
813 return tl::unexpected( *busy );
819 e.set_status( ApiStatusCode::AS_UNHANDLED );
820 return tl::unexpected( e );
834 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
835 return tl::unexpected( *busy );
841 e.set_status( ApiStatusCode::AS_UNHANDLED );
842 return tl::unexpected( e );
848 std::vector<EDA_ITEM*> toAdd;
850 for(
const types::KIID&
id : aCtx.
Request.items() )
852 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
853 toAdd.emplace_back( *item );
859 SelectionResponse response;
862 item->Serialize( *response.add_items() );
871 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
872 return tl::unexpected( *busy );
878 e.set_status( ApiStatusCode::AS_UNHANDLED );
879 return tl::unexpected( e );
885 std::vector<EDA_ITEM*> toRemove;
887 for(
const types::KIID&
id : aCtx.
Request.items() )
889 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
890 toRemove.emplace_back( *item );
896 SelectionResponse response;
899 item->Serialize( *response.add_items() );
910 if( !documentValidation )
911 return tl::unexpected( documentValidation.error() );
913 BoardStackupResponse response;
914 google::protobuf::Any
any;
918 any.UnpackTo( response.mutable_stackup() );
921 for( board::BoardStackupLayer& layer : *response.mutable_stackup()->mutable_layers() )
923 if( layer.type() == board::BoardStackupLayerType::BSLT_DIELECTRIC )
929 layer.set_user_name(
frame()->
GetBoard()->GetLayerName(
id ) );
941 if( !documentValidation )
942 return tl::unexpected( documentValidation.error() );
944 BoardEnabledLayersResponse response;
947 int copperLayerCount =
board->GetCopperLayerCount();
949 response.set_copper_layer_count( copperLayerCount );
951 LSET enabled =
board->GetEnabledLayers();
970 if( !documentValidation )
971 return tl::unexpected( documentValidation.error() );
973 if( aCtx.
Request.copper_layer_count() % 2 != 0 )
976 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
977 e.set_error_message(
"copper_layer_count must be an even number" );
978 return tl::unexpected( e );
984 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
985 e.set_error_message( fmt::format(
"copper_layer_count must be below %d",
MAX_CU_LAYERS ) );
986 return tl::unexpected( e );
989 int copperLayerCount =
static_cast<int>( aCtx.
Request.copper_layer_count() );
994 enabled &=
~LSET::AllCuMask();
999 LSET previousEnabled =
board->GetEnabledLayers();
1000 LSET changedLayers = enabled ^ previousEnabled;
1002 board->SetEnabledLayers( enabled );
1003 board->SetVisibleLayers(
board->GetVisibleLayers() | changedLayers );
1009 if( !enabled[layer_id] &&
board->HasItemsOnLayer( layer_id ) )
1010 removedLayers.push_back( layer_id );
1013 bool modified =
false;
1015 if( !removedLayers.empty() )
1020 modified |=
board->RemoveAllItemsOnLayer( layer_id );
1023 if( enabled != previousEnabled )
1029 BoardEnabledLayersResponse response;
1031 response.set_copper_layer_count( copperLayerCount );
1043 if( !documentValidation )
1044 return tl::unexpected( documentValidation.error() );
1047 GraphicsDefaultsResponse response;
1050 constexpr std::array<kiapi::board::BoardLayerClass, LAYER_CLASS_COUNT> classOrder = {
1051 kiapi::board::BLC_SILKSCREEN,
1052 kiapi::board::BLC_COPPER,
1053 kiapi::board::BLC_EDGES,
1054 kiapi::board::BLC_COURTYARD,
1055 kiapi::board::BLC_FABRICATION,
1056 kiapi::board::BLC_OTHER
1061 kiapi::board::BoardLayerGraphicsDefaults* l = response.mutable_defaults()->add_layers();
1063 l->set_layer( classOrder[i] );
1066 kiapi::common::types::TextAttributes*
text = l->mutable_text();
1082 !documentValidation )
1084 return tl::unexpected( documentValidation.error() );
1103 ApiResponseStatus e;
1104 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1105 e.set_error_message(
"Unexpected origin type" );
1106 return tl::unexpected( e );
1110 types::Vector2 reply;
1118 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1119 return tl::unexpected( *busy );
1122 !documentValidation )
1124 return tl::unexpected( documentValidation.error() );
1135 frame()->CallAfter( [f, origin]()
1150 frame()->CallAfter( [f, origin]()
1162 ApiResponseStatus e;
1163 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1164 e.set_error_message(
"Unexpected origin type" );
1165 return tl::unexpected( e );
1176 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1177 return tl::unexpected( *busy );
1181 ApiResponseStatus e;
1183 e.set_status( ApiStatusCode::AS_UNHANDLED );
1184 return tl::unexpected( e );
1187 GetBoundingBoxResponse response;
1188 bool includeText = aCtx.
Request.mode() == BoundingBoxMode::BBM_ITEM_AND_CHILD_TEXT;
1190 for(
const types::KIID& idMsg : aCtx.
Request.items() )
1192 KIID id( idMsg.value() );
1193 std::optional<BOARD_ITEM*> optItem =
getItemById(
id );
1202 bbox =
static_cast<FOOTPRINT*
>( item )->GetBoundingBox( includeText );
1206 response.add_items()->set_value( idMsg.value() );
1207 PackBox2( *response.add_boxes(), bbox );
1218 !documentValidation )
1220 return tl::unexpected( documentValidation.error() );
1223 PadShapeAsPolygonResponse response;
1226 for(
const types::KIID& padRequest : aCtx.
Request.pads() )
1228 KIID id( padRequest.value() );
1229 std::optional<BOARD_ITEM*> optPad =
getItemById(
id );
1231 if( !optPad || ( *optPad )->Type() !=
PCB_PAD_T )
1234 response.add_pads()->set_value( padRequest.value() );
1236 PAD*
pad =
static_cast<PAD*
>( *optPad );
1238 pad->TransformShapeToPolygon( poly,
pad->Padstack().EffectiveLayerFor( layer ), 0,
1241 types::PolygonWithHoles* polyMsg = response.mutable_polygons()->Add();
1252 using board::types::BoardLayer;
1255 !documentValidation )
1257 return tl::unexpected( documentValidation.error() );
1260 PadstackPresenceResponse response;
1264 for(
const int layer : aCtx.
Request.layers() )
1267 for(
const types::KIID& padRequest : aCtx.
Request.items() )
1269 KIID id( padRequest.value() );
1270 std::optional<BOARD_ITEM*> optItem =
getItemById(
id );
1275 switch( ( *optItem )->Type() )
1279 PAD*
pad =
static_cast<PAD*
>( *optItem );
1283 PadstackPresenceEntry* entry = response.add_entries();
1284 entry->mutable_item()->set_value(
pad->m_Uuid.AsStdString() );
1286 entry->set_presence(
pad->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT );
1298 PadstackPresenceEntry* entry = response.add_entries();
1299 entry->mutable_item()->set_value(
via->m_Uuid.AsStdString() );
1301 entry->set_presence(
via->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT );
1321 if( !documentValidation )
1322 return tl::unexpected( documentValidation.error() );
1327 types::TitleBlockInfo response;
1329 response.set_title( block.
GetTitle().ToUTF8() );
1330 response.set_date( block.
GetDate().ToUTF8() );
1331 response.set_revision( block.
GetRevision().ToUTF8() );
1332 response.set_company( block.
GetCompany().ToUTF8() );
1333 response.set_comment1( block.
GetComment( 0 ).ToUTF8() );
1334 response.set_comment2( block.
GetComment( 1 ).ToUTF8() );
1335 response.set_comment3( block.
GetComment( 2 ).ToUTF8() );
1336 response.set_comment4( block.
GetComment( 3 ).ToUTF8() );
1337 response.set_comment5( block.
GetComment( 4 ).ToUTF8() );
1338 response.set_comment6( block.
GetComment( 5 ).ToUTF8() );
1339 response.set_comment7( block.
GetComment( 6 ).ToUTF8() );
1340 response.set_comment8( block.
GetComment( 7 ).ToUTF8() );
1341 response.set_comment9( block.
GetComment( 8 ).ToUTF8() );
1352 if( !documentValidation )
1353 return tl::unexpected( documentValidation.error() );
1355 ExpandTextVariablesResponse reply;
1358 std::function<bool( wxString* )> textResolver =
1359 [&]( wxString* token ) ->
bool
1362 return board->ResolveTextVar( token, 0 );
1365 for(
const std::string& textMsg : aCtx.
Request.text() )
1368 reply.add_text(
text.ToUTF8() );
1378 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1379 return tl::unexpected( *busy );
1383 if( !documentValidation )
1384 return tl::unexpected( documentValidation.error() );
1387 std::vector<EDA_ITEM*> toSelect;
1389 for(
const kiapi::common::types::KIID&
id : aCtx.
Request.items() )
1391 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
1392 toSelect.emplace_back(
static_cast<EDA_ITEM*
>( *item ) );
1395 if( toSelect.empty() )
1397 ApiResponseStatus e;
1398 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1399 e.set_error_message( fmt::format(
"None of the given items exist on the board",
1400 aCtx.
Request.board().board_filename() ) );
1401 return tl::unexpected( e );
1421 if( !documentValidation )
1422 return tl::unexpected( documentValidation.error() );
1424 NetsResponse response;
1427 std::set<wxString> netclassFilter;
1429 for(
const std::string& nc : aCtx.
Request.netclass_filter() )
1430 netclassFilter.insert( wxString( nc.c_str(), wxConvUTF8 ) );
1436 if( !netclassFilter.empty() && nc && !netclassFilter.count( nc->
GetName() ) )
1439 board::types::Net* netProto = response.add_nets();
1440 netProto->set_name( net->GetNetname() );
1441 netProto->mutable_code()->set_value( net->GetNetCode() );
1451 NetClassForNetsResponse response;
1455 google::protobuf::Any
any;
1457 for(
const board::types::Net& net : aCtx.
Request.net() )
1465 auto [pair, rc] = response.mutable_classes()->insert( { net.name(), {} } );
1466 any.UnpackTo( &pair->second );
1475 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1476 return tl::unexpected( *busy );
1480 if( !documentValidation )
1481 return tl::unexpected( documentValidation.error() );
1483 if( aCtx.
Request.zones().empty() )
1486 frame()->CallAfter( [mgr]()
1494 ApiResponseStatus e;
1495 e.set_status( ApiStatusCode::AS_UNIMPLEMENTED );
1496 return tl::unexpected( e );
1508 if( !documentValidation )
1509 return tl::unexpected( documentValidation.error() );
1511 SavedDocumentResponse response;
1512 response.mutable_document()->CopyFrom( aCtx.
Request.document() );
1516 [&](
const wxString& aData )
1518 response.set_contents( aData.ToUTF8() );
1530 SavedSelectionResponse response;
1538 [&](
const wxString& aData )
1540 response.set_contents( aData.ToUTF8() );
1553 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1554 return tl::unexpected( *busy );
1558 if( !documentValidation )
1559 return tl::unexpected( documentValidation.error() );
1561 CreateItemsResponse response;
1571 if( !documentValidation )
1572 return tl::unexpected( documentValidation.error() );
1574 BoardLayers response;
1586 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1587 return tl::unexpected( *busy );
1591 if( !documentValidation )
1592 return tl::unexpected( documentValidation.error() );
1597 for(
int layerIdx : aCtx.
Request.layers() )
1603 visible.
set( layer );
1619 if( !documentValidation )
1620 return tl::unexpected( documentValidation.error() );
1622 BoardLayerResponse response;
1633 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1634 return tl::unexpected( *busy );
1638 if( !documentValidation )
1639 return tl::unexpected( documentValidation.error() );
1643 if( !
frame()->
GetBoard()->GetEnabledLayers().Contains( layer ) )
1645 ApiResponseStatus err;
1646 err.set_status( ApiStatusCode::AS_BAD_REQUEST );
1647 err.set_error_message( fmt::format(
"Layer {} is not a valid layer for the given board",
1648 magic_enum::enum_name( layer ) ) );
1649 return tl::unexpected( err );
1660 BoardEditorAppearanceSettings reply;
1668 reply.set_net_color_display(
1671 reply.set_board_flip(
frame()->GetCanvas()->GetView()->IsMirroredX()
1672 ? BoardFlipMode::BFM_FLIPPED_X
1673 : BoardFlipMode::BFM_NORMAL );
1687 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1688 return tl::unexpected( *busy );
1693 const BoardEditorAppearanceSettings& newSettings = aCtx.
Request.settings();
1700 bool flip = newSettings.board_flip() == BoardFlipMode::BFM_FLIPPED_X;
1722 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1723 return tl::unexpected( *busy );
1727 if( !documentValidation )
1728 return tl::unexpected( documentValidation.error() );
1736 drcItem->SetErrorMessage( wxString::FromUTF8( aCtx.
Request.message() ) );
1740 for(
const auto&
id : aCtx.
Request.items() )
1741 ids.emplace_back(
KIID(
id.value() ) );
1744 drcItem->SetItems( ids );
1746 const auto& pos = aCtx.
Request.position();
1747 VECTOR2I position(
static_cast<int>( pos.x_nm() ),
static_cast<int>( pos.y_nm() ) );
1752 commit->
Add( marker );
1753 commit->
Push( wxS(
"API injected DRC marker" ) );
1755 InjectDrcErrorResponse response;
types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
tl::expected< T, ApiResponseStatus > HANDLER_RESULT
std::unique_ptr< EDA_ITEM > CreateItemForType(KICAD_T aType, EDA_ITEM *aContainer)
static TOOL_ACTION selectionClear
Clear the current selection.
static TOOL_ACTION gridSetOrigin
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
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.
API_HANDLER_EDITOR(EDA_BASE_FRAME *aFrame=nullptr)
COMMIT * getCurrentCommit(const std::string &aClientName)
virtual void pushCurrentCommit(const std::string &aClientName, const wxString &aMessage)
std::set< std::string > m_activeClients
virtual std::optional< ApiResponseStatus > checkForBusy()
Checks if the editor can accept commands.
HANDLER_RESULT< commands::SelectionResponse > handleAddToSelection(const HANDLER_CONTEXT< commands::AddToSelection > &aCtx)
HANDLER_RESULT< commands::CreateItemsResponse > handleParseAndCreateItemsFromString(const HANDLER_CONTEXT< commands::ParseAndCreateItemsFromString > &aCtx)
HANDLER_RESULT< Empty > handleInteractiveMoveItems(const HANDLER_CONTEXT< InteractiveMoveItems > &aCtx)
bool validateDocumentInternal(const DocumentSpecifier &aDocument) const override
HANDLER_RESULT< Empty > handleSetActiveLayer(const HANDLER_CONTEXT< SetActiveLayer > &aCtx)
API_HANDLER_PCB(PCB_EDIT_FRAME *aFrame)
static HANDLER_RESULT< std::unique_ptr< BOARD_ITEM > > createItemForType(KICAD_T aType, BOARD_ITEM_CONTAINER *aContainer)
std::optional< BOARD_ITEM * > getItemById(const KIID &aId) const
HANDLER_RESULT< types::Vector2 > handleGetBoardOrigin(const HANDLER_CONTEXT< GetBoardOrigin > &aCtx)
std::unique_ptr< COMMIT > createCommit() override
Override this to create an appropriate COMMIT subclass for the frame in question.
HANDLER_RESULT< BoardStackupResponse > handleGetStackup(const HANDLER_CONTEXT< GetBoardStackup > &aCtx)
HANDLER_RESULT< types::TitleBlockInfo > handleGetTitleBlockInfo(const HANDLER_CONTEXT< commands::GetTitleBlockInfo > &aCtx)
HANDLER_RESULT< commands::SelectionResponse > handleGetSelection(const HANDLER_CONTEXT< commands::GetSelection > &aCtx)
HANDLER_RESULT< NetClassForNetsResponse > handleGetNetClassForNets(const HANDLER_CONTEXT< GetNetClassForNets > &aCtx)
std::optional< EDA_ITEM * > getItemFromDocument(const DocumentSpecifier &aDocument, const KIID &aId) override
HANDLER_RESULT< commands::ExpandTextVariablesResponse > handleExpandTextVariables(const HANDLER_CONTEXT< commands::ExpandTextVariables > &aCtx)
HANDLER_RESULT< Empty > handleSetVisibleLayers(const HANDLER_CONTEXT< SetVisibleLayers > &aCtx)
HANDLER_RESULT< Empty > handleSaveCopyOfDocument(const HANDLER_CONTEXT< commands::SaveCopyOfDocument > &aCtx)
HANDLER_RESULT< GraphicsDefaultsResponse > handleGetGraphicsDefaults(const HANDLER_CONTEXT< GetGraphicsDefaults > &aCtx)
HANDLER_RESULT< commands::GetItemsResponse > handleGetItemsById(const HANDLER_CONTEXT< commands::GetItemsById > &aCtx)
HANDLER_RESULT< Empty > handleSetBoardOrigin(const HANDLER_CONTEXT< SetBoardOrigin > &aCtx)
HANDLER_RESULT< Empty > handleClearSelection(const HANDLER_CONTEXT< commands::ClearSelection > &aCtx)
HANDLER_RESULT< commands::RunActionResponse > handleRunAction(const HANDLER_CONTEXT< commands::RunAction > &aCtx)
HANDLER_RESULT< BoardLayers > handleGetVisibleLayers(const HANDLER_CONTEXT< GetVisibleLayers > &aCtx)
HANDLER_RESULT< PadstackPresenceResponse > handleCheckPadstackPresenceOnLayers(const HANDLER_CONTEXT< CheckPadstackPresenceOnLayers > &aCtx)
HANDLER_RESULT< commands::SelectionResponse > handleRemoveFromSelection(const HANDLER_CONTEXT< commands::RemoveFromSelection > &aCtx)
HANDLER_RESULT< commands::GetOpenDocumentsResponse > handleGetOpenDocuments(const HANDLER_CONTEXT< commands::GetOpenDocuments > &aCtx)
HANDLER_RESULT< BoardEditorAppearanceSettings > handleGetBoardEditorAppearanceSettings(const HANDLER_CONTEXT< GetBoardEditorAppearanceSettings > &aCtx)
HANDLER_RESULT< NetsResponse > handleGetNets(const HANDLER_CONTEXT< GetNets > &aCtx)
HANDLER_RESULT< commands::SavedDocumentResponse > handleSaveDocumentToString(const HANDLER_CONTEXT< commands::SaveDocumentToString > &aCtx)
HANDLER_RESULT< commands::GetBoundingBoxResponse > handleGetBoundingBox(const HANDLER_CONTEXT< commands::GetBoundingBox > &aCtx)
HANDLER_RESULT< Empty > handleSaveDocument(const HANDLER_CONTEXT< commands::SaveDocument > &aCtx)
void deleteItemsInternal(std::map< KIID, ItemDeletionStatus > &aItemsToDelete, const std::string &aClientName) override
HANDLER_RESULT< BoardEnabledLayersResponse > handleGetBoardEnabledLayers(const HANDLER_CONTEXT< GetBoardEnabledLayers > &aCtx)
HANDLER_RESULT< commands::GetItemsResponse > handleGetItems(const HANDLER_CONTEXT< commands::GetItems > &aCtx)
HANDLER_RESULT< PadShapeAsPolygonResponse > handleGetPadShapeAsPolygon(const HANDLER_CONTEXT< GetPadShapeAsPolygon > &aCtx)
HANDLER_RESULT< InjectDrcErrorResponse > handleInjectDrcError(const HANDLER_CONTEXT< InjectDrcError > &aCtx)
PCB_EDIT_FRAME * frame() const
HANDLER_RESULT< BoardEnabledLayersResponse > handleSetBoardEnabledLayers(const HANDLER_CONTEXT< SetBoardEnabledLayers > &aCtx)
HANDLER_RESULT< Empty > handleSetBoardEditorAppearanceSettings(const HANDLER_CONTEXT< SetBoardEditorAppearanceSettings > &aCtx)
HANDLER_RESULT< Empty > handleRefillZones(const HANDLER_CONTEXT< RefillZones > &aCtx)
HANDLER_RESULT< types::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) override
HANDLER_RESULT< BoardLayerResponse > handleGetActiveLayer(const HANDLER_CONTEXT< GetActiveLayer > &aCtx)
HANDLER_RESULT< Empty > handleRevertDocument(const HANDLER_CONTEXT< commands::RevertDocument > &aCtx)
HANDLER_RESULT< commands::SavedSelectionResponse > handleSaveSelectionToString(const HANDLER_CONTEXT< commands::SaveSelectionToString > &aCtx)
void pushCurrentCommit(const std::string &aClientName, const wxString &aMessage) override
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)
BASE_SET & reset(size_t pos)
BASE_SET & set(size_t pos)
Container for design settings for a BOARD object.
bool m_TextUpright[LAYER_CLASS_COUNT]
const VECTOR2I & GetGridOrigin() const
const VECTOR2I & GetAuxOrigin() const
int m_TextThickness[LAYER_CLASS_COUNT]
int m_LineThickness[LAYER_CLASS_COUNT]
VECTOR2I m_TextSize[LAYER_CLASS_COUNT]
bool m_TextItalic[LAYER_CLASS_COUNT]
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...
virtual void CopyFrom(const BOARD_ITEM *aOther)
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Information pertinent to a Pcbnew printed circuit board.
BOARD_STACKUP GetStackupOrDefault() const
void SetVisibleLayers(const LSET &aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings changes the bit-mask of vis...
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
BOARD_ITEM * ResolveItem(const KIID &aID, bool aAllowNullptrReturn=false) const
void SaveSelection(const PCB_SELECTION &selected, bool isFootprintEditor)
void SetWriter(std::function< void(const wxString &)> aWriter)
void SaveBoard(const wxString &aFileName, BOARD *aBoard, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aBoard to a storage file in a format that this PCB_IO implementation knows about or it can be u...
void SetBoard(BOARD *aBoard)
Represent a set of changes (additions, deletions or modifications) of a data model (e....
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
virtual void Push(const wxString &aMessage=wxT("A commit"), int aFlags=0)=0
Execute the changes.
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
void ReleaseFile()
Release the current file marked in use.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
void AddItem(EDA_ITEM *aItem)
Add item to group.
A base class for most all the KiCad significant classes used in schematics and boards.
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
virtual EDA_GROUP * GetParentGroup() const
KICAD_T Type() const
Returns the type of object.
virtual wxString GetFriendlyName() const
void SetMirror(bool aMirrorX, bool aMirrorY)
Control the mirroring of the VIEW.
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
bool IsMirroredX() const
Return true if view is flipped across the X axis.
void RecacheAllItems()
Rebuild GAL display lists.
bool IsMirroredY() const
Return true if view is flipped across the Y axis.
std::string AsStdString() const
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
LSET is a set of PCB_LAYER_IDs.
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
A collection of nets and the parameters used to route or test these nets.
const wxString GetName() const
Gets the name of this (maybe aggregate) netclass in a format for internal usage or for export to exte...
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Handle the data for a net.
Container for NETINFO_ITEM elements, which are the nets.
NETINFO_ITEM * GetNetItem(int aNetCode) const
DISPLAY_OPTIONS m_Display
static TOOL_ACTION zoneFillAll
static TOOL_ACTION move
move or drag an item
static TOOL_ACTION drillSetOrigin
APPEARANCE_CONTROLS * GetAppearancePanel()
const PCB_DISPLAY_OPTIONS & GetDisplayOptions() const
Display options control the way tracks, vias, outlines and other things are shown (for instance solid...
PCBNEW_SETTINGS * GetPcbNewSettings() const
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
void SetDisplayOptions(const PCB_DISPLAY_OPTIONS &aOptions, bool aRefresh=true)
Update the current display options.
HIGH_CONTRAST_MODE m_ContrastModeDisplay
How inactive layers are displayed.
NET_COLOR_MODE m_NetColorMode
How to use color overrides on specific nets and netclasses.
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
void SyncLayersVisibility(const BOARD *aBoard)
Update "visibility" property of each layer of a given BOARD.
The main frame for Pcbnew.
void SetActiveLayer(PCB_LAYER_ID aLayer) override
Change the currently active layer to aLayer and also update the APPEARANCE_CONTROLS.
void OnModify() override
Must be called after a board change to set the modified flag.
bool SaveBoard(bool aSaveAs=false, bool aSaveCopy=false)
bool OpenProjectFiles(const std::vector< wxString > &aFileSet, int aCtl=0) override
Load a KiCad board (.kicad_pcb) from aFileName.
void UpdateUserInterface()
Update the layer manager and other widgets from the board setup (layer and items visibility,...
bool SavePcbCopy(const wxString &aFileName, bool aCreateProject=false, bool aHeadless=false)
Write the board data structures to aFileName.
A set of BOARD_ITEMs (i.e., without duplicates).
const KIID GetUUID() const override
virtual const wxString AbsolutePath(const wxString &aFileName) const
Fix up aFileName if it is relative to the project's directory to be an absolute path and filename.
std::vector< KIID > KIIDS
void SetReferencePoint(const VECTOR2I &aP)
virtual void Serialize(google::protobuf::Any &aContainer) const
Serializes this object to the given Any message.
Represent a set of closed polygons.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Hold the information shown in the lower right corner of a plot, printout, or editing view.
const wxString & GetCompany() const
const wxString & GetRevision() const
const wxString & GetDate() const
const wxString & GetComment(int aIdx) const
const wxString & GetTitle() const
A type-safe container of any type.
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
std::vector< EDA_ITEM * > EDA_ITEMS
Define list of drawing items for screens.
static const std::string KiCadPcbFileExtension
#define KICTL_REVERT
reverting to a previously-saved (KiCad) file.
@ LAYER_DRC_WARNING
Layer for DRC markers with #SEVERITY_WARNING.
@ LAYER_DRC_ERROR
Layer for DRC markers with #SEVERITY_ERROR.
PCB_LAYER_ID
A quick note on layer IDs:
void PackLayerSet(google::protobuf::RepeatedField< int > &aOutput, const LSET &aLayerSet)
LSET UnpackLayerSet(const google::protobuf::RepeatedField< int > &aProtoLayerSet)
KICOMMON_API void PackBox2(types::Box2 &aOutput, const BOX2I &aInput)
KICOMMON_API std::optional< KICAD_T > TypeNameFromAny(const google::protobuf::Any &aMessage)
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput)
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput)
KICOMMON_API void PackPolyLine(types::PolyLine &aOutput, const SHAPE_LINE_CHAIN &aSlc)
Class to handle a set of BOARD_ITEMs.
RequestMessageType Request
RATSNEST_MODE m_RatsnestMode
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_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ 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_FOOTPRINT_T
class FOOTPRINT, a footprint
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D