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;
487 item->Serialize( newItem );
488 commit->
Add( item.release() );
502 commit->
Remove( boardItem );
503 item->Serialize( newItem );
504 commit->
Add( item.release() );
508 commit->
Modify( boardItem );
514 aItemHandler( status, newItem );
520 :
_(
"Modified items via API" ) );
524 return ItemRequestStatus::IRS_OK;
530 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
531 return tl::unexpected( *busy );
537 e.set_status( ApiStatusCode::AS_UNHANDLED );
538 return tl::unexpected( e );
541 GetItemsResponse response;
544 std::vector<BOARD_ITEM*> items;
545 std::set<KICAD_T> typesRequested, typesInserted;
546 bool handledAnything =
false;
548 for(
int typeRaw : aCtx.
Request.types() )
550 auto typeMessage =
static_cast<common::types::KiCadObjectType
>( typeRaw );
556 typesRequested.emplace( type );
558 if( typesInserted.count( type ) )
566 handledAnything =
true;
567 std::copy(
board->Tracks().begin(),
board->Tracks().end(),
568 std::back_inserter( items ) );
574 handledAnything =
true;
578 std::copy( fp->Pads().begin(), fp->Pads().end(),
579 std::back_inserter( items ) );
588 handledAnything =
true;
590 std::copy(
board->Footprints().begin(),
board->Footprints().end(),
591 std::back_inserter( items ) );
602 handledAnything =
true;
603 bool inserted =
false;
607 if( item->Type() == type )
609 items.emplace_back( item );
615 typesInserted.insert( type );
622 handledAnything =
true;
624 std::copy(
board->Zones().begin(),
board->Zones().end(),
625 std::back_inserter( items ) );
633 handledAnything =
true;
635 std::copy(
board->Groups().begin(),
board->Groups().end(),
636 std::back_inserter( items ) );
646 if( !handledAnything )
649 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
650 e.set_error_message(
"none of the requested types are valid for a Board object" );
651 return tl::unexpected( e );
656 if( !typesRequested.count( item->Type() ) )
659 google::protobuf::Any itemBuf;
660 item->Serialize( itemBuf );
661 response.mutable_items()->Add( std::move( itemBuf ) );
664 response.set_status( ItemRequestStatus::IRS_OK );
672 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
673 return tl::unexpected( *busy );
678 e.set_status( ApiStatusCode::AS_UNHANDLED );
679 return tl::unexpected( e );
682 GetItemsResponse response;
684 std::vector<BOARD_ITEM*> items;
686 for(
const kiapi::common::types::KIID&
id : aCtx.
Request.items() )
688 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
689 items.emplace_back( *item );
695 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
696 e.set_error_message(
"none of the requested IDs were found or valid" );
697 return tl::unexpected( e );
702 google::protobuf::Any itemBuf;
703 item->Serialize( itemBuf );
704 response.mutable_items()->Add( std::move( itemBuf ) );
707 response.set_status( ItemRequestStatus::IRS_OK );
712 const std::string& aClientName )
715 std::vector<BOARD_ITEM*> validatedItems;
717 for( std::pair<const KIID, ItemDeletionStatus> pair : aItemsToDelete )
721 validatedItems.push_back( item );
722 aItemsToDelete[pair.first] = ItemDeletionStatus::IDS_OK;
756 e.set_status( ApiStatusCode::AS_UNHANDLED );
757 return tl::unexpected( e );
762 for(
int typeRaw : aCtx.
Request.types() )
764 auto typeMessage =
static_cast<types::KiCadObjectType
>( typeRaw );
776 SelectionResponse response;
781 item->Serialize( *response.add_items() );
791 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
792 return tl::unexpected( *busy );
798 e.set_status( ApiStatusCode::AS_UNHANDLED );
799 return tl::unexpected( e );
813 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
814 return tl::unexpected( *busy );
820 e.set_status( ApiStatusCode::AS_UNHANDLED );
821 return tl::unexpected( e );
827 std::vector<EDA_ITEM*> toAdd;
829 for(
const types::KIID&
id : aCtx.
Request.items() )
831 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
832 toAdd.emplace_back( *item );
838 SelectionResponse response;
841 item->Serialize( *response.add_items() );
850 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
851 return tl::unexpected( *busy );
857 e.set_status( ApiStatusCode::AS_UNHANDLED );
858 return tl::unexpected( e );
864 std::vector<EDA_ITEM*> toRemove;
866 for(
const types::KIID&
id : aCtx.
Request.items() )
868 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
869 toRemove.emplace_back( *item );
875 SelectionResponse response;
878 item->Serialize( *response.add_items() );
889 if( !documentValidation )
890 return tl::unexpected( documentValidation.error() );
892 BoardStackupResponse response;
893 google::protobuf::Any
any;
897 any.UnpackTo( response.mutable_stackup() );
900 for( board::BoardStackupLayer& layer : *response.mutable_stackup()->mutable_layers() )
902 if( layer.type() == board::BoardStackupLayerType::BSLT_DIELECTRIC )
908 layer.set_user_name(
frame()->
GetBoard()->GetLayerName(
id ) );
920 if( !documentValidation )
921 return tl::unexpected( documentValidation.error() );
923 BoardEnabledLayersResponse response;
926 int copperLayerCount =
board->GetCopperLayerCount();
928 response.set_copper_layer_count( copperLayerCount );
930 LSET enabled =
board->GetEnabledLayers();
949 if( !documentValidation )
950 return tl::unexpected( documentValidation.error() );
952 if( aCtx.
Request.copper_layer_count() % 2 != 0 )
955 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
956 e.set_error_message(
"copper_layer_count must be an even number" );
957 return tl::unexpected( e );
963 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
964 e.set_error_message( fmt::format(
"copper_layer_count must be below %d",
MAX_CU_LAYERS ) );
965 return tl::unexpected( e );
968 int copperLayerCount =
static_cast<int>( aCtx.
Request.copper_layer_count() );
973 enabled &=
~LSET::AllCuMask();
978 LSET previousEnabled =
board->GetEnabledLayers();
979 LSET changedLayers = enabled ^ previousEnabled;
981 board->SetEnabledLayers( enabled );
982 board->SetVisibleLayers(
board->GetVisibleLayers() | changedLayers );
988 if( !enabled[layer_id] &&
board->HasItemsOnLayer( layer_id ) )
989 removedLayers.push_back( layer_id );
992 bool modified =
false;
994 if( !removedLayers.empty() )
999 modified |=
board->RemoveAllItemsOnLayer( layer_id );
1002 if( enabled != previousEnabled )
1008 BoardEnabledLayersResponse response;
1010 response.set_copper_layer_count( copperLayerCount );
1022 if( !documentValidation )
1023 return tl::unexpected( documentValidation.error() );
1026 GraphicsDefaultsResponse response;
1029 constexpr std::array<kiapi::board::BoardLayerClass, LAYER_CLASS_COUNT> classOrder = {
1030 kiapi::board::BLC_SILKSCREEN,
1031 kiapi::board::BLC_COPPER,
1032 kiapi::board::BLC_EDGES,
1033 kiapi::board::BLC_COURTYARD,
1034 kiapi::board::BLC_FABRICATION,
1035 kiapi::board::BLC_OTHER
1040 kiapi::board::BoardLayerGraphicsDefaults* l = response.mutable_defaults()->add_layers();
1042 l->set_layer( classOrder[i] );
1045 kiapi::common::types::TextAttributes*
text = l->mutable_text();
1061 !documentValidation )
1063 return tl::unexpected( documentValidation.error() );
1082 ApiResponseStatus e;
1083 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1084 e.set_error_message(
"Unexpected origin type" );
1085 return tl::unexpected( e );
1089 types::Vector2 reply;
1097 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1098 return tl::unexpected( *busy );
1101 !documentValidation )
1103 return tl::unexpected( documentValidation.error() );
1114 frame()->CallAfter( [f, origin]()
1129 frame()->CallAfter( [f, origin]()
1141 ApiResponseStatus e;
1142 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1143 e.set_error_message(
"Unexpected origin type" );
1144 return tl::unexpected( e );
1155 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1156 return tl::unexpected( *busy );
1160 ApiResponseStatus e;
1162 e.set_status( ApiStatusCode::AS_UNHANDLED );
1163 return tl::unexpected( e );
1166 GetBoundingBoxResponse response;
1167 bool includeText = aCtx.
Request.mode() == BoundingBoxMode::BBM_ITEM_AND_CHILD_TEXT;
1169 for(
const types::KIID& idMsg : aCtx.
Request.items() )
1171 KIID id( idMsg.value() );
1172 std::optional<BOARD_ITEM*> optItem =
getItemById(
id );
1181 bbox =
static_cast<FOOTPRINT*
>( item )->GetBoundingBox( includeText );
1185 response.add_items()->set_value( idMsg.value() );
1186 PackBox2( *response.add_boxes(), bbox );
1197 !documentValidation )
1199 return tl::unexpected( documentValidation.error() );
1202 PadShapeAsPolygonResponse response;
1205 for(
const types::KIID& padRequest : aCtx.
Request.pads() )
1207 KIID id( padRequest.value() );
1208 std::optional<BOARD_ITEM*> optPad =
getItemById(
id );
1210 if( !optPad || ( *optPad )->Type() !=
PCB_PAD_T )
1213 response.add_pads()->set_value( padRequest.value() );
1215 PAD*
pad =
static_cast<PAD*
>( *optPad );
1217 pad->TransformShapeToPolygon( poly,
pad->Padstack().EffectiveLayerFor( layer ), 0,
1220 types::PolygonWithHoles* polyMsg = response.mutable_polygons()->Add();
1231 using board::types::BoardLayer;
1234 !documentValidation )
1236 return tl::unexpected( documentValidation.error() );
1239 PadstackPresenceResponse response;
1243 for(
const int layer : aCtx.
Request.layers() )
1246 for(
const types::KIID& padRequest : aCtx.
Request.items() )
1248 KIID id( padRequest.value() );
1249 std::optional<BOARD_ITEM*> optItem =
getItemById(
id );
1254 switch( ( *optItem )->Type() )
1258 PAD*
pad =
static_cast<PAD*
>( *optItem );
1262 PadstackPresenceEntry* entry = response.add_entries();
1263 entry->mutable_item()->set_value(
pad->m_Uuid.AsStdString() );
1265 entry->set_presence(
pad->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT );
1277 PadstackPresenceEntry* entry = response.add_entries();
1278 entry->mutable_item()->set_value(
via->m_Uuid.AsStdString() );
1280 entry->set_presence(
via->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT );
1300 if( !documentValidation )
1301 return tl::unexpected( documentValidation.error() );
1306 types::TitleBlockInfo response;
1308 response.set_title( block.
GetTitle().ToUTF8() );
1309 response.set_date( block.
GetDate().ToUTF8() );
1310 response.set_revision( block.
GetRevision().ToUTF8() );
1311 response.set_company( block.
GetCompany().ToUTF8() );
1312 response.set_comment1( block.
GetComment( 0 ).ToUTF8() );
1313 response.set_comment2( block.
GetComment( 1 ).ToUTF8() );
1314 response.set_comment3( block.
GetComment( 2 ).ToUTF8() );
1315 response.set_comment4( block.
GetComment( 3 ).ToUTF8() );
1316 response.set_comment5( block.
GetComment( 4 ).ToUTF8() );
1317 response.set_comment6( block.
GetComment( 5 ).ToUTF8() );
1318 response.set_comment7( block.
GetComment( 6 ).ToUTF8() );
1319 response.set_comment8( block.
GetComment( 7 ).ToUTF8() );
1320 response.set_comment9( block.
GetComment( 8 ).ToUTF8() );
1331 if( !documentValidation )
1332 return tl::unexpected( documentValidation.error() );
1334 ExpandTextVariablesResponse reply;
1337 std::function<bool( wxString* )> textResolver =
1338 [&]( wxString* token ) ->
bool
1341 return board->ResolveTextVar( token, 0 );
1344 for(
const std::string& textMsg : aCtx.
Request.text() )
1347 reply.add_text(
text.ToUTF8() );
1357 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1358 return tl::unexpected( *busy );
1362 if( !documentValidation )
1363 return tl::unexpected( documentValidation.error() );
1366 std::vector<EDA_ITEM*> toSelect;
1368 for(
const kiapi::common::types::KIID&
id : aCtx.
Request.items() )
1370 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
1371 toSelect.emplace_back(
static_cast<EDA_ITEM*
>( *item ) );
1374 if( toSelect.empty() )
1376 ApiResponseStatus e;
1377 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1378 e.set_error_message( fmt::format(
"None of the given items exist on the board",
1379 aCtx.
Request.board().board_filename() ) );
1380 return tl::unexpected( e );
1400 if( !documentValidation )
1401 return tl::unexpected( documentValidation.error() );
1403 NetsResponse response;
1406 std::set<wxString> netclassFilter;
1408 for(
const std::string& nc : aCtx.
Request.netclass_filter() )
1409 netclassFilter.insert( wxString( nc.c_str(), wxConvUTF8 ) );
1415 if( !netclassFilter.empty() && nc && !netclassFilter.count( nc->
GetName() ) )
1418 board::types::Net* netProto = response.add_nets();
1419 netProto->set_name( net->GetNetname() );
1420 netProto->mutable_code()->set_value( net->GetNetCode() );
1430 NetClassForNetsResponse response;
1434 google::protobuf::Any
any;
1436 for(
const board::types::Net& net : aCtx.
Request.net() )
1444 auto [pair, rc] = response.mutable_classes()->insert( { net.name(), {} } );
1445 any.UnpackTo( &pair->second );
1454 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1455 return tl::unexpected( *busy );
1459 if( !documentValidation )
1460 return tl::unexpected( documentValidation.error() );
1462 if( aCtx.
Request.zones().empty() )
1465 frame()->CallAfter( [mgr]()
1473 ApiResponseStatus e;
1474 e.set_status( ApiStatusCode::AS_UNIMPLEMENTED );
1475 return tl::unexpected( e );
1487 if( !documentValidation )
1488 return tl::unexpected( documentValidation.error() );
1490 SavedDocumentResponse response;
1491 response.mutable_document()->CopyFrom( aCtx.
Request.document() );
1495 [&](
const wxString& aData )
1497 response.set_contents( aData.ToUTF8() );
1509 SavedSelectionResponse response;
1517 [&](
const wxString& aData )
1519 response.set_contents( aData.ToUTF8() );
1532 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1533 return tl::unexpected( *busy );
1537 if( !documentValidation )
1538 return tl::unexpected( documentValidation.error() );
1540 CreateItemsResponse response;
1550 if( !documentValidation )
1551 return tl::unexpected( documentValidation.error() );
1553 BoardLayers response;
1565 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1566 return tl::unexpected( *busy );
1570 if( !documentValidation )
1571 return tl::unexpected( documentValidation.error() );
1576 for(
int layerIdx : aCtx.
Request.layers() )
1582 visible.
set( layer );
1598 if( !documentValidation )
1599 return tl::unexpected( documentValidation.error() );
1601 BoardLayerResponse response;
1612 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1613 return tl::unexpected( *busy );
1617 if( !documentValidation )
1618 return tl::unexpected( documentValidation.error() );
1622 if( !
frame()->
GetBoard()->GetEnabledLayers().Contains( layer ) )
1624 ApiResponseStatus err;
1625 err.set_status( ApiStatusCode::AS_BAD_REQUEST );
1626 err.set_error_message( fmt::format(
"Layer {} is not a valid layer for the given board",
1627 magic_enum::enum_name( layer ) ) );
1628 return tl::unexpected( err );
1639 BoardEditorAppearanceSettings reply;
1647 reply.set_net_color_display(
1650 reply.set_board_flip(
frame()->GetCanvas()->GetView()->IsMirroredX()
1651 ? BoardFlipMode::BFM_FLIPPED_X
1652 : BoardFlipMode::BFM_NORMAL );
1666 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1667 return tl::unexpected( *busy );
1672 const BoardEditorAppearanceSettings& newSettings = aCtx.
Request.settings();
1679 bool flip = newSettings.board_flip() == BoardFlipMode::BFM_FLIPPED_X;
1701 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1702 return tl::unexpected( *busy );
1706 if( !documentValidation )
1707 return tl::unexpected( documentValidation.error() );
1715 drcItem->SetErrorMessage( wxString::FromUTF8( aCtx.
Request.message() ) );
1719 for(
const auto&
id : aCtx.
Request.items() )
1720 ids.emplace_back(
KIID(
id.value() ) );
1723 drcItem->SetItems( ids );
1725 const auto& pos = aCtx.
Request.position();
1726 VECTOR2I position(
static_cast<int>( pos.x_nm() ),
static_cast<int>( pos.y_nm() ) );
1731 commit->
Add( marker );
1732 commit->
Push( wxS(
"API injected DRC marker" ) );
1734 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
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.
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.
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