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() );
514 commit->
Remove( boardItem );
515 item->Serialize( newItem );
516 commit->
Add( item.release() );
520 commit->
Modify( boardItem );
526 aItemHandler( status, newItem );
532 :
_(
"Modified items via API" ) );
536 return ItemRequestStatus::IRS_OK;
542 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
543 return tl::unexpected( *busy );
549 e.set_status( ApiStatusCode::AS_UNHANDLED );
550 return tl::unexpected( e );
553 GetItemsResponse response;
556 std::vector<BOARD_ITEM*> items;
557 std::set<KICAD_T> typesRequested, typesInserted;
558 bool handledAnything =
false;
560 for(
int typeRaw : aCtx.
Request.types() )
562 auto typeMessage =
static_cast<common::types::KiCadObjectType
>( typeRaw );
568 typesRequested.emplace( type );
570 if( typesInserted.count( type ) )
578 handledAnything =
true;
579 std::copy(
board->Tracks().begin(),
board->Tracks().end(),
580 std::back_inserter( items ) );
586 handledAnything =
true;
590 std::copy( fp->Pads().begin(), fp->Pads().end(),
591 std::back_inserter( items ) );
600 handledAnything =
true;
602 std::copy(
board->Footprints().begin(),
board->Footprints().end(),
603 std::back_inserter( items ) );
614 handledAnything =
true;
615 bool inserted =
false;
619 if( item->Type() == type )
621 items.emplace_back( item );
627 typesInserted.insert( type );
634 handledAnything =
true;
636 std::copy(
board->Zones().begin(),
board->Zones().end(),
637 std::back_inserter( items ) );
645 handledAnything =
true;
647 std::copy(
board->Groups().begin(),
board->Groups().end(),
648 std::back_inserter( items ) );
658 if( !handledAnything )
661 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
662 e.set_error_message(
"none of the requested types are valid for a Board object" );
663 return tl::unexpected( e );
668 if( !typesRequested.count( item->Type() ) )
671 google::protobuf::Any itemBuf;
672 item->Serialize( itemBuf );
673 response.mutable_items()->Add( std::move( itemBuf ) );
676 response.set_status( ItemRequestStatus::IRS_OK );
684 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
685 return tl::unexpected( *busy );
690 e.set_status( ApiStatusCode::AS_UNHANDLED );
691 return tl::unexpected( e );
694 GetItemsResponse response;
696 std::vector<BOARD_ITEM*> items;
698 for(
const kiapi::common::types::KIID&
id : aCtx.
Request.items() )
700 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
701 items.emplace_back( *item );
707 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
708 e.set_error_message(
"none of the requested IDs were found or valid" );
709 return tl::unexpected( e );
714 google::protobuf::Any itemBuf;
715 item->Serialize( itemBuf );
716 response.mutable_items()->Add( std::move( itemBuf ) );
719 response.set_status( ItemRequestStatus::IRS_OK );
724 const std::string& aClientName )
727 std::vector<BOARD_ITEM*> validatedItems;
729 for( std::pair<const KIID, ItemDeletionStatus> pair : aItemsToDelete )
733 validatedItems.push_back( item );
734 aItemsToDelete[pair.first] = ItemDeletionStatus::IDS_OK;
768 e.set_status( ApiStatusCode::AS_UNHANDLED );
769 return tl::unexpected( e );
774 for(
int typeRaw : aCtx.
Request.types() )
776 auto typeMessage =
static_cast<types::KiCadObjectType
>( typeRaw );
788 SelectionResponse response;
793 item->Serialize( *response.add_items() );
803 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
804 return tl::unexpected( *busy );
810 e.set_status( ApiStatusCode::AS_UNHANDLED );
811 return tl::unexpected( e );
825 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
826 return tl::unexpected( *busy );
832 e.set_status( ApiStatusCode::AS_UNHANDLED );
833 return tl::unexpected( e );
839 std::vector<EDA_ITEM*> toAdd;
841 for(
const types::KIID&
id : aCtx.
Request.items() )
843 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
844 toAdd.emplace_back( *item );
850 SelectionResponse response;
853 item->Serialize( *response.add_items() );
862 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
863 return tl::unexpected( *busy );
869 e.set_status( ApiStatusCode::AS_UNHANDLED );
870 return tl::unexpected( e );
876 std::vector<EDA_ITEM*> toRemove;
878 for(
const types::KIID&
id : aCtx.
Request.items() )
880 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
881 toRemove.emplace_back( *item );
887 SelectionResponse response;
890 item->Serialize( *response.add_items() );
901 if( !documentValidation )
902 return tl::unexpected( documentValidation.error() );
904 BoardStackupResponse response;
905 google::protobuf::Any
any;
909 any.UnpackTo( response.mutable_stackup() );
912 for( board::BoardStackupLayer& layer : *response.mutable_stackup()->mutable_layers() )
914 if( layer.type() == board::BoardStackupLayerType::BSLT_DIELECTRIC )
920 layer.set_user_name(
frame()->
GetBoard()->GetLayerName(
id ) );
932 if( !documentValidation )
933 return tl::unexpected( documentValidation.error() );
935 BoardEnabledLayersResponse response;
938 int copperLayerCount =
board->GetCopperLayerCount();
940 response.set_copper_layer_count( copperLayerCount );
942 LSET enabled =
board->GetEnabledLayers();
961 if( !documentValidation )
962 return tl::unexpected( documentValidation.error() );
964 if( aCtx.
Request.copper_layer_count() % 2 != 0 )
967 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
968 e.set_error_message(
"copper_layer_count must be an even number" );
969 return tl::unexpected( e );
975 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
976 e.set_error_message( fmt::format(
"copper_layer_count must be below %d",
MAX_CU_LAYERS ) );
977 return tl::unexpected( e );
980 int copperLayerCount =
static_cast<int>( aCtx.
Request.copper_layer_count() );
985 enabled &=
~LSET::AllCuMask();
990 LSET previousEnabled =
board->GetEnabledLayers();
991 LSET changedLayers = enabled ^ previousEnabled;
993 board->SetEnabledLayers( enabled );
994 board->SetVisibleLayers(
board->GetVisibleLayers() | changedLayers );
1000 if( !enabled[layer_id] &&
board->HasItemsOnLayer( layer_id ) )
1001 removedLayers.push_back( layer_id );
1004 bool modified =
false;
1006 if( !removedLayers.empty() )
1011 modified |=
board->RemoveAllItemsOnLayer( layer_id );
1014 if( enabled != previousEnabled )
1020 BoardEnabledLayersResponse response;
1022 response.set_copper_layer_count( copperLayerCount );
1034 if( !documentValidation )
1035 return tl::unexpected( documentValidation.error() );
1038 GraphicsDefaultsResponse response;
1041 constexpr std::array<kiapi::board::BoardLayerClass, LAYER_CLASS_COUNT> classOrder = {
1042 kiapi::board::BLC_SILKSCREEN,
1043 kiapi::board::BLC_COPPER,
1044 kiapi::board::BLC_EDGES,
1045 kiapi::board::BLC_COURTYARD,
1046 kiapi::board::BLC_FABRICATION,
1047 kiapi::board::BLC_OTHER
1052 kiapi::board::BoardLayerGraphicsDefaults* l = response.mutable_defaults()->add_layers();
1054 l->set_layer( classOrder[i] );
1057 kiapi::common::types::TextAttributes*
text = l->mutable_text();
1073 !documentValidation )
1075 return tl::unexpected( documentValidation.error() );
1094 ApiResponseStatus e;
1095 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1096 e.set_error_message(
"Unexpected origin type" );
1097 return tl::unexpected( e );
1101 types::Vector2 reply;
1109 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1110 return tl::unexpected( *busy );
1113 !documentValidation )
1115 return tl::unexpected( documentValidation.error() );
1126 frame()->CallAfter( [f, origin]()
1141 frame()->CallAfter( [f, origin]()
1153 ApiResponseStatus e;
1154 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1155 e.set_error_message(
"Unexpected origin type" );
1156 return tl::unexpected( e );
1167 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1168 return tl::unexpected( *busy );
1172 ApiResponseStatus e;
1174 e.set_status( ApiStatusCode::AS_UNHANDLED );
1175 return tl::unexpected( e );
1178 GetBoundingBoxResponse response;
1179 bool includeText = aCtx.
Request.mode() == BoundingBoxMode::BBM_ITEM_AND_CHILD_TEXT;
1181 for(
const types::KIID& idMsg : aCtx.
Request.items() )
1183 KIID id( idMsg.value() );
1184 std::optional<BOARD_ITEM*> optItem =
getItemById(
id );
1193 bbox =
static_cast<FOOTPRINT*
>( item )->GetBoundingBox( includeText );
1197 response.add_items()->set_value( idMsg.value() );
1198 PackBox2( *response.add_boxes(), bbox );
1209 !documentValidation )
1211 return tl::unexpected( documentValidation.error() );
1214 PadShapeAsPolygonResponse response;
1217 for(
const types::KIID& padRequest : aCtx.
Request.pads() )
1219 KIID id( padRequest.value() );
1220 std::optional<BOARD_ITEM*> optPad =
getItemById(
id );
1222 if( !optPad || ( *optPad )->Type() !=
PCB_PAD_T )
1225 response.add_pads()->set_value( padRequest.value() );
1227 PAD*
pad =
static_cast<PAD*
>( *optPad );
1229 pad->TransformShapeToPolygon( poly,
pad->Padstack().EffectiveLayerFor( layer ), 0,
1232 types::PolygonWithHoles* polyMsg = response.mutable_polygons()->Add();
1243 using board::types::BoardLayer;
1246 !documentValidation )
1248 return tl::unexpected( documentValidation.error() );
1251 PadstackPresenceResponse response;
1255 for(
const int layer : aCtx.
Request.layers() )
1258 for(
const types::KIID& padRequest : aCtx.
Request.items() )
1260 KIID id( padRequest.value() );
1261 std::optional<BOARD_ITEM*> optItem =
getItemById(
id );
1266 switch( ( *optItem )->Type() )
1270 PAD*
pad =
static_cast<PAD*
>( *optItem );
1274 PadstackPresenceEntry* entry = response.add_entries();
1275 entry->mutable_item()->set_value(
pad->m_Uuid.AsStdString() );
1277 entry->set_presence(
pad->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT );
1289 PadstackPresenceEntry* entry = response.add_entries();
1290 entry->mutable_item()->set_value(
via->m_Uuid.AsStdString() );
1292 entry->set_presence(
via->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT );
1312 if( !documentValidation )
1313 return tl::unexpected( documentValidation.error() );
1318 types::TitleBlockInfo response;
1320 response.set_title( block.
GetTitle().ToUTF8() );
1321 response.set_date( block.
GetDate().ToUTF8() );
1322 response.set_revision( block.
GetRevision().ToUTF8() );
1323 response.set_company( block.
GetCompany().ToUTF8() );
1324 response.set_comment1( block.
GetComment( 0 ).ToUTF8() );
1325 response.set_comment2( block.
GetComment( 1 ).ToUTF8() );
1326 response.set_comment3( block.
GetComment( 2 ).ToUTF8() );
1327 response.set_comment4( block.
GetComment( 3 ).ToUTF8() );
1328 response.set_comment5( block.
GetComment( 4 ).ToUTF8() );
1329 response.set_comment6( block.
GetComment( 5 ).ToUTF8() );
1330 response.set_comment7( block.
GetComment( 6 ).ToUTF8() );
1331 response.set_comment8( block.
GetComment( 7 ).ToUTF8() );
1332 response.set_comment9( block.
GetComment( 8 ).ToUTF8() );
1343 if( !documentValidation )
1344 return tl::unexpected( documentValidation.error() );
1346 ExpandTextVariablesResponse reply;
1349 std::function<bool( wxString* )> textResolver =
1350 [&]( wxString* token ) ->
bool
1353 return board->ResolveTextVar( token, 0 );
1356 for(
const std::string& textMsg : aCtx.
Request.text() )
1359 reply.add_text(
text.ToUTF8() );
1369 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1370 return tl::unexpected( *busy );
1374 if( !documentValidation )
1375 return tl::unexpected( documentValidation.error() );
1378 std::vector<EDA_ITEM*> toSelect;
1380 for(
const kiapi::common::types::KIID&
id : aCtx.
Request.items() )
1382 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
1383 toSelect.emplace_back(
static_cast<EDA_ITEM*
>( *item ) );
1386 if( toSelect.empty() )
1388 ApiResponseStatus e;
1389 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1390 e.set_error_message( fmt::format(
"None of the given items exist on the board",
1391 aCtx.
Request.board().board_filename() ) );
1392 return tl::unexpected( e );
1412 if( !documentValidation )
1413 return tl::unexpected( documentValidation.error() );
1415 NetsResponse response;
1418 std::set<wxString> netclassFilter;
1420 for(
const std::string& nc : aCtx.
Request.netclass_filter() )
1421 netclassFilter.insert( wxString( nc.c_str(), wxConvUTF8 ) );
1427 if( !netclassFilter.empty() && nc && !netclassFilter.count( nc->
GetName() ) )
1430 board::types::Net* netProto = response.add_nets();
1431 netProto->set_name( net->GetNetname() );
1432 netProto->mutable_code()->set_value( net->GetNetCode() );
1442 NetClassForNetsResponse response;
1446 google::protobuf::Any
any;
1448 for(
const board::types::Net& net : aCtx.
Request.net() )
1456 auto [pair, rc] = response.mutable_classes()->insert( { net.name(), {} } );
1457 any.UnpackTo( &pair->second );
1466 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1467 return tl::unexpected( *busy );
1471 if( !documentValidation )
1472 return tl::unexpected( documentValidation.error() );
1474 if( aCtx.
Request.zones().empty() )
1477 frame()->CallAfter( [mgr]()
1485 ApiResponseStatus e;
1486 e.set_status( ApiStatusCode::AS_UNIMPLEMENTED );
1487 return tl::unexpected( e );
1499 if( !documentValidation )
1500 return tl::unexpected( documentValidation.error() );
1502 SavedDocumentResponse response;
1503 response.mutable_document()->CopyFrom( aCtx.
Request.document() );
1507 [&](
const wxString& aData )
1509 response.set_contents( aData.ToUTF8() );
1521 SavedSelectionResponse response;
1529 [&](
const wxString& aData )
1531 response.set_contents( aData.ToUTF8() );
1544 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1545 return tl::unexpected( *busy );
1549 if( !documentValidation )
1550 return tl::unexpected( documentValidation.error() );
1552 CreateItemsResponse response;
1562 if( !documentValidation )
1563 return tl::unexpected( documentValidation.error() );
1565 BoardLayers response;
1577 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1578 return tl::unexpected( *busy );
1582 if( !documentValidation )
1583 return tl::unexpected( documentValidation.error() );
1588 for(
int layerIdx : aCtx.
Request.layers() )
1594 visible.
set( layer );
1610 if( !documentValidation )
1611 return tl::unexpected( documentValidation.error() );
1613 BoardLayerResponse response;
1624 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1625 return tl::unexpected( *busy );
1629 if( !documentValidation )
1630 return tl::unexpected( documentValidation.error() );
1634 if( !
frame()->
GetBoard()->GetEnabledLayers().Contains( layer ) )
1636 ApiResponseStatus err;
1637 err.set_status( ApiStatusCode::AS_BAD_REQUEST );
1638 err.set_error_message( fmt::format(
"Layer {} is not a valid layer for the given board",
1639 magic_enum::enum_name( layer ) ) );
1640 return tl::unexpected( err );
1651 BoardEditorAppearanceSettings reply;
1659 reply.set_net_color_display(
1662 reply.set_board_flip(
frame()->GetCanvas()->GetView()->IsMirroredX()
1663 ? BoardFlipMode::BFM_FLIPPED_X
1664 : BoardFlipMode::BFM_NORMAL );
1678 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1679 return tl::unexpected( *busy );
1684 const BoardEditorAppearanceSettings& newSettings = aCtx.
Request.settings();
1691 bool flip = newSettings.board_flip() == BoardFlipMode::BFM_FLIPPED_X;
1713 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1714 return tl::unexpected( *busy );
1718 if( !documentValidation )
1719 return tl::unexpected( documentValidation.error() );
1727 drcItem->SetErrorMessage( wxString::FromUTF8( aCtx.
Request.message() ) );
1731 for(
const auto&
id : aCtx.
Request.items() )
1732 ids.emplace_back(
KIID(
id.value() ) );
1735 drcItem->SetItems( ids );
1737 const auto& pos = aCtx.
Request.position();
1738 VECTOR2I position(
static_cast<int>( pos.x_nm() ),
static_cast<int>( pos.y_nm() ) );
1743 commit->
Add( marker );
1744 commit->
Push( wxS(
"API injected DRC marker" ) );
1746 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