21#include <magic_enum.hpp>
70#include <api/common/types/base_types.pb.h>
78#include <wx/filename.h>
80using namespace kiapi::common::commands;
81using types::CommandStatus;
82using types::DocumentType;
83using types::ItemRequestStatus;
209 e.set_status( ApiStatusCode::AS_UNIMPLEMENTED );
210 e.set_error_message( fmt::format(
"{} is not available in headless mode", aCommandName ) );
218 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"RunAction" ) )
219 return tl::unexpected( *headless );
221 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
222 return tl::unexpected( *busy );
224 RunActionResponse response;
227 response.set_status( RunActionStatus::RAS_OK );
229 response.set_status( RunActionStatus::RAS_INVALID );
238 if( aCtx.
Request.type() != DocumentType::DOCTYPE_PCB )
242 e.set_status( ApiStatusCode::AS_UNHANDLED );
243 return tl::unexpected( e );
246 GetOpenDocumentsResponse response;
247 common::types::DocumentSpecifier doc;
249 wxFileName fn(
context()->GetCurrentFileName() );
251 doc.set_type( DocumentType::DOCTYPE_PCB );
252 doc.set_board_filename( fn.GetFullName() );
254 doc.mutable_project()->set_name(
project().GetProjectName().ToStdString() );
255 doc.mutable_project()->set_path(
project().GetProjectDirectory().ToStdString() );
257 response.mutable_documents()->Add( std::move( doc ) );
265 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
266 return tl::unexpected( *busy );
270 if( !documentValidation )
271 return tl::unexpected( documentValidation.error() );
281 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
282 return tl::unexpected( *busy );
286 if( !documentValidation )
287 return tl::unexpected( documentValidation.error() );
289 wxFileName boardPath(
project().AbsolutePath( wxString::FromUTF8( aCtx.
Request.path() ) ) );
291 if( !boardPath.IsOk() || !boardPath.IsDirWritable() )
294 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
295 e.set_error_message( fmt::format(
"save path '{}' could not be opened",
296 boardPath.GetFullPath().ToStdString() ) );
297 return tl::unexpected( e );
300 if( boardPath.FileExists()
301 && ( !boardPath.IsFileWritable() || !aCtx.
Request.options().overwrite() ) )
304 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
305 e.set_error_message( fmt::format(
"save path '{}' exists and cannot be overwritten",
306 boardPath.GetFullPath().ToStdString() ) );
307 return tl::unexpected( e );
313 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
314 e.set_error_message( fmt::format(
"save path '{}' must have a kicad_pcb extension",
315 boardPath.GetFullPath().ToStdString() ) );
316 return tl::unexpected( e );
321 if( board->
GetFileName().Matches( boardPath.GetFullPath() ) )
327 bool includeProject =
true;
329 if( aCtx.
Request.has_options() )
330 includeProject = aCtx.
Request.options().include_project();
341 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"RevertDocument" ) )
342 return tl::unexpected( *headless );
344 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
345 return tl::unexpected( *busy );
349 if( !documentValidation )
350 return tl::unexpected( documentValidation.error() );
374 return std::make_unique<BOARD_COMMIT>(
frame() );
376 return std::make_unique<BOARD_COMMIT>(
toolManager(),
true,
false );
393 if( aDocument.type() != DocumentType::DOCTYPE_PCB )
396 wxFileName fn(
context()->GetCurrentFileName() );
397 return 0 == aDocument.board_filename().compare( fn.GetFullName() );
407 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
408 e.set_error_message(
"Tried to create an item in a null container" );
409 return tl::unexpected( e );
415 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
416 e.set_error_message( fmt::format(
"Tried to create a pad in {}, which is not a footprint",
418 return tl::unexpected( e );
423 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
424 e.set_error_message( fmt::format(
"Tried to create a footprint in {}, which is not a board",
426 return tl::unexpected( e );
434 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
435 e.set_error_message( fmt::format(
"Tried to create an item of type {}, which is unhandled",
436 magic_enum::enum_name( aType ) ) );
437 return tl::unexpected( e );
445 const std::string& aClientName,
446 const types::ItemHeader &aHeader,
447 const google::protobuf::RepeatedPtrField<google::protobuf::Any>& aItems,
448 std::function<
void( ItemStatus, google::protobuf::Any )> aItemHandler )
454 if( !containerResult && containerResult.error().status() == ApiStatusCode::AS_UNHANDLED )
457 e.set_status( ApiStatusCode::AS_UNHANDLED );
458 return tl::unexpected( e );
460 else if( !containerResult )
462 e.CopyFrom( containerResult.error() );
463 return tl::unexpected( e );
469 if( containerResult->has_value() )
471 const KIID& containerId = **containerResult;
472 std::optional<BOARD_ITEM*> optItem =
getItemById( containerId );
480 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
481 e.set_error_message( fmt::format(
482 "The requested container {} is not a valid board item container",
484 return tl::unexpected( e );
489 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
490 e.set_error_message( fmt::format(
491 "The requested container {} does not exist in this document",
493 return tl::unexpected( e );
499 for(
const google::protobuf::Any& anyItem : aItems )
506 status.set_code( ItemStatusCode::ISC_INVALID_TYPE );
507 status.set_error_message( fmt::format(
"Could not decode a valid type from {}",
508 anyItem.type_url() ) );
509 aItemHandler( status, anyItem );
515 board::types::Dimension dimension;
516 anyItem.UnpackTo( &dimension );
518 switch( dimension.dimension_style_case() )
525 case board::types::Dimension::DIMENSION_STYLE_NOT_SET:
break;
532 if( !creationResult )
534 status.set_code( ItemStatusCode::ISC_INVALID_TYPE );
535 status.set_error_message( creationResult.error().error_message() );
536 aItemHandler( status, anyItem );
540 std::unique_ptr<BOARD_ITEM> item( std::move( *creationResult ) );
542 if( !item->Deserialize( anyItem ) )
544 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
545 e.set_error_message( fmt::format(
"could not unpack {} from request",
546 item->GetClass().ToStdString() ) );
547 return tl::unexpected( e );
550 std::optional<BOARD_ITEM*> optItem =
getItemById( item->m_Uuid );
552 if( aCreate && optItem )
554 status.set_code( ItemStatusCode::ISC_EXISTING );
555 status.set_error_message( fmt::format(
"an item with UUID {} already exists",
556 item->m_Uuid.AsStdString() ) );
557 aItemHandler( status, anyItem );
560 else if( !aCreate && !optItem )
562 status.set_code( ItemStatusCode::ISC_NONEXISTENT );
563 status.set_error_message( fmt::format(
"an item with UUID {} does not exist",
564 item->m_Uuid.AsStdString() ) );
565 aItemHandler( status, anyItem );
569 if( aCreate && !(
board->GetEnabledLayers() & item->GetLayerSet() ).any() )
571 status.set_code( ItemStatusCode::ISC_INVALID_DATA );
572 status.set_error_message(
573 "attempted to add item with no overlapping layers with the board" );
574 aItemHandler( status, anyItem );
578 status.set_code( ItemStatusCode::ISC_OK );
579 google::protobuf::Any newItem;
595 item->Serialize( newItem );
596 commit->
Add( item.release() );
613 commit->
Remove( boardItem );
614 item->Serialize( newItem );
617 commit->
Add( newBoardItem );
621 parentGroup->
AddItem( newBoardItem );
625 commit->
Modify( boardItem );
631 aItemHandler( status, newItem );
637 :
_(
"Modified items via API" ) );
641 return ItemRequestStatus::IRS_OK;
647 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
648 return tl::unexpected( *busy );
654 e.set_status( ApiStatusCode::AS_UNHANDLED );
655 return tl::unexpected( e );
658 GetItemsResponse response;
661 std::vector<BOARD_ITEM*> items;
662 std::set<KICAD_T> typesRequested, typesInserted;
663 bool handledAnything =
false;
667 typesRequested.emplace( type );
669 if( typesInserted.count( type ) )
677 handledAnything =
true;
678 std::copy(
board->Tracks().begin(),
board->Tracks().end(),
679 std::back_inserter( items ) );
685 handledAnything =
true;
689 std::copy( fp->Pads().begin(), fp->Pads().end(),
690 std::back_inserter( items ) );
699 handledAnything =
true;
701 std::copy(
board->Footprints().begin(),
board->Footprints().end(),
702 std::back_inserter( items ) );
714 handledAnything =
true;
715 bool inserted =
false;
719 if( item->Type() == type )
721 items.emplace_back( item );
727 typesInserted.insert( type );
734 handledAnything =
true;
735 bool inserted =
false;
739 switch (item->Type()) {
745 items.emplace_back( item );
763 handledAnything =
true;
765 std::copy(
board->Zones().begin(),
board->Zones().end(),
766 std::back_inserter( items ) );
774 handledAnything =
true;
776 std::copy(
board->Groups().begin(),
board->Groups().end(),
777 std::back_inserter( items ) );
787 if( !handledAnything )
790 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
791 e.set_error_message(
"none of the requested types are valid for a Board object" );
792 return tl::unexpected( e );
797 if( !typesRequested.count( item->Type() ) )
800 google::protobuf::Any itemBuf;
801 item->Serialize( itemBuf );
802 response.mutable_items()->Add( std::move( itemBuf ) );
805 response.set_status( ItemRequestStatus::IRS_OK );
813 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
814 return tl::unexpected( *busy );
819 e.set_status( ApiStatusCode::AS_UNHANDLED );
820 return tl::unexpected( e );
823 GetItemsResponse response;
825 std::vector<BOARD_ITEM*> items;
827 for(
const kiapi::common::types::KIID&
id : aCtx.
Request.items() )
829 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
830 items.emplace_back( *item );
836 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
837 e.set_error_message(
"none of the requested IDs were found or valid" );
838 return tl::unexpected( e );
843 google::protobuf::Any itemBuf;
844 item->Serialize( itemBuf );
845 response.mutable_items()->Add( std::move( itemBuf ) );
848 response.set_status( ItemRequestStatus::IRS_OK );
853 const std::string& aClientName )
856 std::vector<BOARD_ITEM*> validatedItems;
858 for( std::pair<const KIID, ItemDeletionStatus> pair : aItemsToDelete )
862 validatedItems.push_back( item );
863 aItemsToDelete[pair.first] = ItemDeletionStatus::IDS_OK;
893 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"GetSelection" ) )
894 return tl::unexpected( *headless );
900 e.set_status( ApiStatusCode::AS_UNHANDLED );
901 return tl::unexpected( e );
912 SelectionResponse response;
917 item->Serialize( *response.add_items() );
927 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"ClearSelection" ) )
928 return tl::unexpected( *headless );
930 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
931 return tl::unexpected( *busy );
937 e.set_status( ApiStatusCode::AS_UNHANDLED );
938 return tl::unexpected( e );
952 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"AddToSelection" ) )
953 return tl::unexpected( *headless );
955 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
956 return tl::unexpected( *busy );
962 e.set_status( ApiStatusCode::AS_UNHANDLED );
963 return tl::unexpected( e );
969 std::vector<EDA_ITEM*> toAdd;
971 for(
const types::KIID&
id : aCtx.
Request.items() )
973 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
974 toAdd.emplace_back( *item );
980 SelectionResponse response;
983 item->Serialize( *response.add_items() );
992 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"RemoveFromSelection" ) )
993 return tl::unexpected( *headless );
995 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
996 return tl::unexpected( *busy );
1000 ApiResponseStatus e;
1002 e.set_status( ApiStatusCode::AS_UNHANDLED );
1003 return tl::unexpected( e );
1009 std::vector<EDA_ITEM*> toRemove;
1011 for(
const types::KIID&
id : aCtx.
Request.items() )
1013 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
1014 toRemove.emplace_back( *item );
1020 SelectionResponse response;
1023 item->Serialize( *response.add_items() );
1034 if( !documentValidation )
1035 return tl::unexpected( documentValidation.error() );
1037 BoardStackupResponse response;
1038 google::protobuf::Any
any;
1042 any.UnpackTo( response.mutable_stackup() );
1045 for( board::BoardStackupLayer& layer : *response.mutable_stackup()->mutable_layers() )
1047 if( layer.type() == board::BoardStackupLayerType::BSLT_DIELECTRIC )
1053 layer.set_user_name(
board()->GetLayerName(
id ) );
1065 if( !documentValidation )
1066 return tl::unexpected( documentValidation.error() );
1068 BoardEnabledLayersResponse response;
1071 int copperLayerCount =
board->GetCopperLayerCount();
1073 response.set_copper_layer_count( copperLayerCount );
1075 LSET enabled =
board->GetEnabledLayers();
1094 if( !documentValidation )
1095 return tl::unexpected( documentValidation.error() );
1097 if( aCtx.
Request.copper_layer_count() % 2 != 0 )
1099 ApiResponseStatus e;
1100 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1101 e.set_error_message(
"copper_layer_count must be an even number" );
1102 return tl::unexpected( e );
1107 ApiResponseStatus e;
1108 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1109 e.set_error_message( fmt::format(
"copper_layer_count must be below %d",
MAX_CU_LAYERS ) );
1110 return tl::unexpected( e );
1113 int copperLayerCount =
static_cast<int>( aCtx.
Request.copper_layer_count() );
1118 enabled &=
~LSET::AllCuMask();
1123 LSET previousEnabled =
board->GetEnabledLayers();
1124 LSET changedLayers = enabled ^ previousEnabled;
1126 board->SetEnabledLayers( enabled );
1127 board->SetVisibleLayers(
board->GetVisibleLayers() | changedLayers );
1133 if( !enabled[layer_id] &&
board->HasItemsOnLayer( layer_id ) )
1134 removedLayers.push_back( layer_id );
1137 bool modified =
false;
1139 if( !removedLayers.empty() )
1144 modified |=
board->RemoveAllItemsOnLayer( layer_id );
1147 if( enabled != previousEnabled )
1153 BoardEnabledLayersResponse response;
1155 response.set_copper_layer_count( copperLayerCount );
1167 if( !documentValidation )
1168 return tl::unexpected( documentValidation.error() );
1171 GraphicsDefaultsResponse response;
1174 constexpr std::array<kiapi::board::BoardLayerClass, LAYER_CLASS_COUNT> classOrder = {
1175 kiapi::board::BLC_SILKSCREEN,
1176 kiapi::board::BLC_COPPER,
1177 kiapi::board::BLC_EDGES,
1178 kiapi::board::BLC_COURTYARD,
1179 kiapi::board::BLC_FABRICATION,
1180 kiapi::board::BLC_OTHER
1185 kiapi::board::BoardLayerGraphicsDefaults* l = response.mutable_defaults()->add_layers();
1187 l->set_layer( classOrder[i] );
1190 kiapi::common::types::TextAttributes*
text = l->mutable_text();
1207 if( !documentValidation )
1208 return tl::unexpected( documentValidation.error() );
1211 BoardDesignRulesResponse response;
1212 kiapi::board::BoardDesignRules* rules = response.mutable_rules();
1214 kiapi::board::MinimumConstraints* constraints = rules->mutable_constraints();
1216 constraints->mutable_min_clearance()->set_value_nm( bds.
m_MinClearance );
1217 constraints->mutable_min_groove_width()->set_value_nm( bds.
m_MinGrooveWidth );
1218 constraints->mutable_min_connection_width()->set_value_nm( bds.
m_MinConn );
1219 constraints->mutable_min_track_width()->set_value_nm( bds.
m_TrackMinWidth );
1221 constraints->mutable_min_via_size()->set_value_nm( bds.
m_ViasMinSize );
1222 constraints->mutable_min_through_drill()->set_value_nm( bds.
m_MinThroughDrill );
1226 constraints->mutable_hole_clearance()->set_value_nm( bds.
m_HoleClearance );
1227 constraints->mutable_hole_to_hole_min()->set_value_nm( bds.
m_HoleToHoleMin );
1228 constraints->mutable_silk_clearance()->set_value_nm( bds.
m_SilkClearance );
1233 kiapi::board::PredefinedSizes* sizes = rules->mutable_predefined_sizes();
1236 sizes->add_tracks()->mutable_width()->set_value_nm( bds.
m_TrackWidthList[ii] );
1240 kiapi::board::PresetViaDimension*
via = sizes->add_vias();
1247 kiapi::board::PresetDiffPairDimension* pair = sizes->add_diff_pairs();
1253 kiapi::board::SolderMaskPasteDefaults* maskPaste = rules->mutable_solder_mask_paste();
1262 kiapi::board::TeardropDefaults* teardrops = rules->mutable_teardrops();
1275 kiapi::board::TeardropTargetEntry* entry = teardrops->add_target_params();
1279 entry->mutable_params()->set_enabled( params->
m_Enabled );
1280 entry->mutable_params()->mutable_max_length()->set_value_nm( params->
m_TdMaxLen );
1281 entry->mutable_params()->mutable_max_width()->set_value_nm( params->
m_TdMaxWidth );
1285 entry->mutable_params()->set_curved_edges( params->
m_CurvedEdges );
1290 kiapi::board::ViaProtectionDefaults* viaProtection = rules->mutable_via_protection();
1298 viaProtection->set_cap( bds.
m_CapVias );
1303 board::DrcSeveritySetting* setting = rules->add_severities();
1304 setting->set_rule_type(
1311 kiapi::board::DrcExclusion* exclusion = rules->add_exclusions();
1312 exclusion->mutable_marker()->mutable_id()->set_opaque_id( serialized.ToStdString() );
1317 exclusion->set_comment( it->second.ToStdString() );
1320 response.set_custom_rules_status( CRS_NONE );
1326 if( !rulesPath.IsEmpty() && wxFileName::IsFileReadable( rulesPath ) )
1328 wxFFile file( rulesPath,
"r" );
1330 std::vector<std::shared_ptr<DRC_RULE>> parsedRules;
1332 if( !file.IsOpened() )
1334 response.set_custom_rules_status( CRS_INVALID );
1338 file.ReadAll( &content );
1344 parser.
Parse( parsedRules,
nullptr );
1345 response.set_custom_rules_status( CRS_VALID );
1349 response.set_custom_rules_status( CRS_INVALID );
1362 if( !documentValidation )
1363 return tl::unexpected( documentValidation.error() );
1366 const kiapi::board::BoardDesignRules& rules = aCtx.
Request.rules();
1368 if( rules.has_constraints() )
1370 const kiapi::board::MinimumConstraints& constraints = rules.constraints();
1372 newSettings.
m_MinClearance = constraints.min_clearance().value_nm();
1374 newSettings.
m_MinConn = constraints.min_connection_width().value_nm();
1375 newSettings.
m_TrackMinWidth = constraints.min_track_width().value_nm();
1377 newSettings.
m_ViasMinSize = constraints.min_via_size().value_nm();
1382 newSettings.
m_HoleClearance = constraints.hole_clearance().value_nm();
1383 newSettings.
m_HoleToHoleMin = constraints.hole_to_hole_min().value_nm();
1384 newSettings.
m_SilkClearance = constraints.silk_clearance().value_nm();
1390 if( rules.has_predefined_sizes() )
1395 for(
const kiapi::board::PresetTrackWidth& track : rules.predefined_sizes().tracks() )
1401 for(
const kiapi::board::PresetViaDimension&
via : rules.predefined_sizes().vias() )
1404 static_cast<int>(
via.drill().value_nm() ) );
1410 for(
const kiapi::board::PresetDiffPairDimension& pair : rules.predefined_sizes().diff_pairs() )
1413 static_cast<int>( pair.width().value_nm() ),
1414 static_cast<int>( pair.gap().value_nm() ),
1415 static_cast<int>( pair.via_gap().value_nm() ) );
1419 if( rules.has_solder_mask_paste() )
1421 const kiapi::board::SolderMaskPasteDefaults& maskPaste = rules.solder_mask_paste();
1429 maskPaste.allow_soldermask_bridges_in_footprints();
1432 if( rules.has_teardrops() )
1434 const kiapi::board::TeardropDefaults& teardrops = rules.teardrops();
1442 for(
const kiapi::board::TeardropTargetEntry& entry : teardrops.target_params() )
1444 if( entry.target() == kiapi::board::TeardropTarget::TDT_UNKNOWN )
1452 params->
m_Enabled = entry.params().enabled();
1453 params->
m_TdMaxLen = entry.params().max_length().value_nm();
1454 params->
m_TdMaxWidth = entry.params().max_width().value_nm();
1464 if( rules.has_via_protection() )
1466 const kiapi::board::ViaProtectionDefaults& viaProtection = rules.via_protection();
1474 newSettings.
m_CapVias = viaProtection.cap();
1475 newSettings.
m_FillVias = viaProtection.fill();
1478 if( rules.severities_size() > 0 )
1482 for(
const kiapi::board::DrcSeveritySetting& severitySetting : rules.severities() )
1490 if( !permitted.contains( setting ) )
1492 ApiResponseStatus e;
1493 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1494 e.set_error_message( fmt::format(
"DRC severity must be error, warning, or ignore" ) );
1495 return tl::unexpected( e );
1502 if( rules.exclusions_size() > 0 )
1507 for(
const kiapi::board::DrcExclusion& exclusion : rules.exclusions() )
1509 wxString serialized = wxString::FromUTF8( exclusion.marker().id().opaque_id() );
1511 if( serialized.IsEmpty() )
1513 ApiResponseStatus e;
1514 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1515 e.set_error_message(
"DrcExclusion marker id must not be empty" );
1516 return tl::unexpected( e );
1524 std::vector<BOARD_DESIGN_SETTINGS::VALIDATION_ERROR> errors = newSettings.
ValidateDesignRules();
1526 if( !errors.empty() )
1530 ApiResponseStatus e;
1531 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1532 e.set_error_message( fmt::format(
"Invalid board design rules: {}: {}",
1535 return tl::unexpected( e );
1558 if( !documentValidation )
1559 return tl::unexpected( documentValidation.error() );
1561 CustomRulesResponse response;
1562 response.set_status( CRS_NONE );
1568 if( rulesPath.IsEmpty() || !wxFileName::IsFileReadable( rulesPath ) )
1571 wxFFile file( rulesPath,
"r" );
1573 if( !file.IsOpened() )
1575 response.set_status( CRS_INVALID );
1576 response.set_error_text(
"Failed to open custom rules file" );
1581 file.ReadAll( &content );
1584 std::vector<std::shared_ptr<DRC_RULE>> parsedRules;
1589 parser.
Parse( parsedRules,
nullptr );
1593 response.set_status( CRS_INVALID );
1594 response.set_error_text( ioe.
What().ToStdString() );
1598 for(
const std::shared_ptr<DRC_RULE>& rule : parsedRules )
1605 kiapi::board::CustomRule* customRule = response.add_rules();
1607 if( rule->m_Condition )
1608 customRule->set_condition( rule->m_Condition->GetExpression().ToUTF8() );
1612 board::CustomRuleConstraint* constraintProto = customRule->add_constraints();
1613 constraint.
ToProto( *constraintProto );
1617 customRule->set_name( rule->m_Name.ToUTF8() );
1619 if( rule->m_LayerSource.CmpNoCase( wxS(
"outer" ) ) == 0 )
1621 customRule->set_layer_mode( kiapi::board::CRLM_OUTER );
1623 else if( rule->m_LayerSource.CmpNoCase( wxS(
"inner" ) ) == 0 )
1625 customRule->set_layer_mode( kiapi::board::CRLM_INNER );
1627 else if( !rule->m_LayerSource.IsEmpty() )
1633 customRule->set_single_layer(
1638 if( !comment.IsEmpty() )
1639 customRule->set_comments( comment );
1642 response.set_status( CRS_VALID );
1652 if( !documentValidation )
1653 return tl::unexpected( documentValidation.error() );
1659 if( aCtx.
Request.rules_size() == 0 )
1661 if( wxFileName::FileExists( rulesPath ) )
1663 if( !wxRemoveFile( rulesPath ) )
1665 CustomRulesResponse response;
1666 response.set_status( CRS_INVALID );
1667 response.set_error_text(
"Failed to remove custom rules file" );
1672 CustomRulesResponse response;
1673 response.set_status( CRS_NONE );
1678 rulesText <<
"(version 1)\n";
1680 for(
const board::CustomRule& rule : aCtx.
Request.rules() )
1682 wxString serializationError;
1685 if( serializedRule.IsEmpty() )
1687 CustomRulesResponse response;
1688 response.set_status( CRS_INVALID );
1690 if( serializationError.IsEmpty() )
1691 response.set_error_text(
"Failed to serialize custom rule" );
1693 response.set_error_text( serializationError.ToUTF8() );
1698 rulesText <<
"\n" << serializedRule;
1704 std::vector<std::shared_ptr<DRC_RULE>> parsedRules;
1706 parser.
Parse( parsedRules,
nullptr );
1710 CustomRulesResponse response;
1711 response.set_status( CRS_INVALID );
1712 response.set_error_text( ioe.
What().ToStdString() );
1716 wxFFile file( rulesPath,
"w" );
1718 if( !file.IsOpened() )
1720 CustomRulesResponse response;
1721 response.set_status( CRS_INVALID );
1722 response.set_error_text(
"Failed to open custom rules file for writing" );
1726 if( !file.Write( rulesText ) )
1730 CustomRulesResponse response;
1731 response.set_status( CRS_INVALID );
1732 response.set_error_text(
"Failed to write custom rules file" );
1748 !documentValidation )
1750 return tl::unexpected( documentValidation.error() );
1769 ApiResponseStatus e;
1770 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1771 e.set_error_message(
"Unexpected origin type" );
1772 return tl::unexpected( e );
1776 types::Vector2 reply;
1784 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1785 return tl::unexpected( *busy );
1788 !documentValidation )
1790 return tl::unexpected( documentValidation.error() );
1801 frame()->CallAfter( [f, origin]()
1816 frame()->CallAfter( [f, origin]()
1828 ApiResponseStatus e;
1829 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1830 e.set_error_message(
"Unexpected origin type" );
1831 return tl::unexpected( e );
1843 !documentValidation )
1845 return tl::unexpected( documentValidation.error() );
1848 BoardLayerNameResponse response;
1852 response.set_name(
board()->GetLayerName(
id ) );
1861 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1862 return tl::unexpected( *busy );
1866 ApiResponseStatus e;
1868 e.set_status( ApiStatusCode::AS_UNHANDLED );
1869 return tl::unexpected( e );
1872 GetBoundingBoxResponse response;
1873 bool includeText = aCtx.
Request.mode() == BoundingBoxMode::BBM_ITEM_AND_CHILD_TEXT;
1875 for(
const types::KIID& idMsg : aCtx.
Request.items() )
1877 KIID id( idMsg.value() );
1878 std::optional<BOARD_ITEM*> optItem =
getItemById(
id );
1887 bbox =
static_cast<FOOTPRINT*
>( item )->GetBoundingBox( includeText );
1891 response.add_items()->set_value( idMsg.value() );
1892 PackBox2( *response.add_boxes(), bbox );
1903 !documentValidation )
1905 return tl::unexpected( documentValidation.error() );
1908 PadShapeAsPolygonResponse response;
1911 for(
const types::KIID& padRequest : aCtx.
Request.pads() )
1913 KIID id( padRequest.value() );
1914 std::optional<BOARD_ITEM*> optPad =
getItemById(
id );
1916 if( !optPad || ( *optPad )->Type() !=
PCB_PAD_T )
1919 response.add_pads()->set_value( padRequest.value() );
1921 PAD*
pad =
static_cast<PAD*
>( *optPad );
1923 pad->TransformShapeToPolygon( poly,
pad->Padstack().EffectiveLayerFor( layer ), 0,
1926 types::PolygonWithHoles* polyMsg = response.mutable_polygons()->Add();
1937 using board::types::BoardLayer;
1940 !documentValidation )
1942 return tl::unexpected( documentValidation.error() );
1945 PadstackPresenceResponse response;
1949 for(
const int layer : aCtx.
Request.layers() )
1952 for(
const types::KIID& padRequest : aCtx.
Request.items() )
1954 KIID id( padRequest.value() );
1955 std::optional<BOARD_ITEM*> optItem =
getItemById(
id );
1960 switch( ( *optItem )->Type() )
1964 PAD*
pad =
static_cast<PAD*
>( *optItem );
1968 PadstackPresenceEntry* entry = response.add_entries();
1969 entry->mutable_item()->set_value(
pad->m_Uuid.AsStdString() );
1971 entry->set_presence(
pad->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT );
1983 PadstackPresenceEntry* entry = response.add_entries();
1984 entry->mutable_item()->set_value(
via->m_Uuid.AsStdString() );
1986 entry->set_presence(
via->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT );
2006 if( !documentValidation )
2007 return tl::unexpected( documentValidation.error() );
2011 types::TitleBlockInfo response;
2013 response.set_title( block.
GetTitle().ToUTF8() );
2014 response.set_date( block.
GetDate().ToUTF8() );
2015 response.set_revision( block.
GetRevision().ToUTF8() );
2016 response.set_company( block.
GetCompany().ToUTF8() );
2017 response.set_comment1( block.
GetComment( 0 ).ToUTF8() );
2018 response.set_comment2( block.
GetComment( 1 ).ToUTF8() );
2019 response.set_comment3( block.
GetComment( 2 ).ToUTF8() );
2020 response.set_comment4( block.
GetComment( 3 ).ToUTF8() );
2021 response.set_comment5( block.
GetComment( 4 ).ToUTF8() );
2022 response.set_comment6( block.
GetComment( 5 ).ToUTF8() );
2023 response.set_comment7( block.
GetComment( 6 ).ToUTF8() );
2024 response.set_comment8( block.
GetComment( 7 ).ToUTF8() );
2025 response.set_comment9( block.
GetComment( 8 ).ToUTF8() );
2035 if( !documentValidation )
2036 return tl::unexpected( documentValidation.error() );
2038 if( !aCtx.
Request.has_title_block() )
2040 ApiResponseStatus e;
2041 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2042 e.set_error_message(
"SetTitleBlockInfo requires title_block" );
2043 return tl::unexpected( e );
2048 const types::TitleBlockInfo& request = aCtx.
Request.title_block();
2050 block.
SetTitle( wxString::FromUTF8( request.title() ) );
2051 block.
SetDate( wxString::FromUTF8( request.date() ) );
2052 block.
SetRevision( wxString::FromUTF8( request.revision() ) );
2053 block.
SetCompany( wxString::FromUTF8( request.company() ) );
2054 block.
SetComment( 0, wxString::FromUTF8( request.comment1() ) );
2055 block.
SetComment( 1, wxString::FromUTF8( request.comment2() ) );
2056 block.
SetComment( 2, wxString::FromUTF8( request.comment3() ) );
2057 block.
SetComment( 3, wxString::FromUTF8( request.comment4() ) );
2058 block.
SetComment( 4, wxString::FromUTF8( request.comment5() ) );
2059 block.
SetComment( 5, wxString::FromUTF8( request.comment6() ) );
2060 block.
SetComment( 6, wxString::FromUTF8( request.comment7() ) );
2061 block.
SetComment( 7, wxString::FromUTF8( request.comment8() ) );
2062 block.
SetComment( 8, wxString::FromUTF8( request.comment9() ) );
2079 if( !documentValidation )
2080 return tl::unexpected( documentValidation.error() );
2082 ExpandTextVariablesResponse reply;
2085 std::function<bool( wxString* )> textResolver =
2086 [&]( wxString* token ) ->
bool
2089 return board->ResolveTextVar( token, 0 );
2092 for(
const std::string& textMsg : aCtx.
Request.text() )
2095 reply.add_text(
text.ToUTF8() );
2105 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"InteractiveMoveItems" ) )
2106 return tl::unexpected( *headless );
2108 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2109 return tl::unexpected( *busy );
2113 if( !documentValidation )
2114 return tl::unexpected( documentValidation.error() );
2117 std::vector<EDA_ITEM*> toSelect;
2119 for(
const kiapi::common::types::KIID&
id : aCtx.
Request.items() )
2121 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
2122 toSelect.emplace_back(
static_cast<EDA_ITEM*
>( *item ) );
2125 if( toSelect.empty() )
2127 ApiResponseStatus e;
2128 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2129 e.set_error_message( fmt::format(
"None of the given items exist on the board",
2130 aCtx.
Request.board().board_filename() ) );
2131 return tl::unexpected( e );
2151 if( !documentValidation )
2152 return tl::unexpected( documentValidation.error() );
2154 NetsResponse response;
2157 std::set<wxString> netclassFilter;
2159 for(
const std::string& nc : aCtx.
Request.netclass_filter() )
2160 netclassFilter.insert( wxString( nc.c_str(), wxConvUTF8 ) );
2166 if( !netclassFilter.empty() && nc )
2168 bool inClass =
false;
2170 for(
const wxString&
filter : netclassFilter )
2183 board::types::Net* netProto = response.add_nets();
2184 netProto->set_name( net->GetNetname() );
2185 netProto->mutable_code()->set_value( net->GetNetCode() );
2195 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2196 return tl::unexpected( *busy );
2200 ApiResponseStatus e;
2201 e.set_status( ApiStatusCode::AS_UNHANDLED );
2202 return tl::unexpected( e );
2206 const bool filterByType = aCtx.
Request.types_size() > 0;
2208 if( filterByType && types.empty() )
2210 ApiResponseStatus e;
2211 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2212 e.set_error_message(
"none of the requested types are valid for a Board object" );
2213 return tl::unexpected( e );
2216 std::set<KICAD_T> typeFilter( types.begin(), types.end() );
2217 std::vector<BOARD_CONNECTED_ITEM*> sourceItems;
2219 for(
const types::KIID&
id : aCtx.
Request.items() )
2221 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
2224 sourceItems.emplace_back( connected );
2228 if( sourceItems.empty() )
2230 ApiResponseStatus e;
2231 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2232 e.set_error_message(
"none of the requested IDs were found or valid connected items" );
2233 return tl::unexpected( e );
2236 GetItemsResponse response;
2238 std::set<KIID> insertedItems;
2244 if( filterByType && !typeFilter.contains( connected->Type() ) )
2247 if( !insertedItems.insert( connected->m_Uuid ).second )
2250 connected->Serialize( *response.add_items() );
2254 response.set_status( ItemRequestStatus::IRS_OK );
2261 std::vector<KICAD_T> types;
2263 for(
int typeRaw : aTypes )
2265 auto typeMessage =
static_cast<common::types::KiCadObjectType
>( typeRaw );
2269 types.emplace_back( type );
2279 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2280 return tl::unexpected( *busy );
2284 ApiResponseStatus e;
2285 e.set_status( ApiStatusCode::AS_UNHANDLED );
2286 return tl::unexpected( e );
2290 const bool filterByType = aCtx.
Request.types_size() > 0;
2292 if( filterByType && types.empty() )
2294 ApiResponseStatus e;
2295 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2296 e.set_error_message(
"none of the requested types are valid for a Board object" );
2297 return tl::unexpected( e );
2303 GetItemsResponse response;
2305 std::shared_ptr<CONNECTIVITY_DATA> conn =
board->GetConnectivity();
2306 std::set<KIID> insertedItems;
2310 for(
const board::types::Net& net : aCtx.
Request.nets() )
2319 if( !insertedItems.insert( item->m_Uuid ).second )
2322 item->Serialize( *response.add_items() );
2326 response.set_status( ItemRequestStatus::IRS_OK );
2334 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2335 return tl::unexpected( *busy );
2339 ApiResponseStatus e;
2340 e.set_status( ApiStatusCode::AS_UNHANDLED );
2341 return tl::unexpected( e );
2345 const bool filterByType = aCtx.
Request.types_size() > 0;
2347 if( filterByType && types.empty() )
2349 ApiResponseStatus e;
2350 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2351 e.set_error_message(
"none of the requested types are valid for a Board object" );
2352 return tl::unexpected( e );
2358 std::set<wxString> requestedClasses;
2360 for(
const std::string& netClass : aCtx.
Request.net_classes() )
2361 requestedClasses.insert( wxString( netClass.c_str(), wxConvUTF8 ) );
2363 GetItemsResponse response;
2365 std::shared_ptr<CONNECTIVITY_DATA> conn =
board->GetConnectivity();
2366 std::set<KIID> insertedItems;
2375 if( !requestedClasses.empty() )
2380 bool inClass =
false;
2382 for(
const wxString&
filter : requestedClasses )
2397 if( !insertedItems.insert( item->m_Uuid ).second )
2400 item->Serialize( *response.add_items() );
2404 response.set_status( ItemRequestStatus::IRS_OK );
2412 NetClassForNetsResponse response;
2416 google::protobuf::Any
any;
2418 for(
const board::types::Net& net : aCtx.
Request.net() )
2426 auto [pair, rc] = response.mutable_classes()->insert( { net.name(), {} } );
2427 any.UnpackTo( &pair->second );
2436 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2437 return tl::unexpected( *busy );
2441 if( !documentValidation )
2442 return tl::unexpected( documentValidation.error() );
2444 if( aCtx.
Request.zones().empty() )
2447 frame()->CallAfter( [mgr]()
2455 ApiResponseStatus e;
2456 e.set_status( ApiStatusCode::AS_UNIMPLEMENTED );
2457 return tl::unexpected( e );
2469 if( !documentValidation )
2470 return tl::unexpected( documentValidation.error() );
2472 SavedDocumentResponse response;
2473 response.mutable_document()->CopyFrom( aCtx.
Request.document() );
2477 [&](
const wxString& aData )
2479 response.set_contents( aData.ToUTF8() );
2491 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"SaveSelectionToString" ) )
2492 return tl::unexpected( *headless );
2494 SavedSelectionResponse response;
2502 [&](
const wxString& aData )
2504 response.set_contents( aData.ToUTF8() );
2517 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2518 return tl::unexpected( *busy );
2522 if( !documentValidation )
2523 return tl::unexpected( documentValidation.error() );
2525 CreateItemsResponse response;
2533 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"GetVisibleLayers" ) )
2534 return tl::unexpected( *headless );
2538 if( !documentValidation )
2539 return tl::unexpected( documentValidation.error() );
2541 BoardLayers response;
2553 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"SetVisibleLayers" ) )
2554 return tl::unexpected( *headless );
2556 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2557 return tl::unexpected( *busy );
2561 if( !documentValidation )
2562 return tl::unexpected( documentValidation.error() );
2567 for(
int layerIdx : aCtx.
Request.layers() )
2573 visible.
set( layer );
2587 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"GetActiveLayer" ) )
2588 return tl::unexpected( *headless );
2592 if( !documentValidation )
2593 return tl::unexpected( documentValidation.error() );
2595 BoardLayerResponse response;
2606 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"SetActiveLayer" ) )
2607 return tl::unexpected( *headless );
2609 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2610 return tl::unexpected( *busy );
2614 if( !documentValidation )
2615 return tl::unexpected( documentValidation.error() );
2619 if( !
board()->GetEnabledLayers().Contains( layer ) )
2621 ApiResponseStatus err;
2622 err.set_status( ApiStatusCode::AS_BAD_REQUEST );
2623 err.set_error_message( fmt::format(
"Layer {} is not a valid layer for the given board",
2624 magic_enum::enum_name( layer ) ) );
2625 return tl::unexpected( err );
2636 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"GetBoardEditorAppearanceSettings" ) )
2637 return tl::unexpected( *headless );
2639 BoardEditorAppearanceSettings reply;
2647 reply.set_net_color_display(
2650 reply.set_board_flip(
frame()->GetCanvas()->GetView()->IsMirroredX()
2651 ? BoardFlipMode::BFM_FLIPPED_X
2652 : BoardFlipMode::BFM_NORMAL );
2666 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"SetBoardEditorAppearanceSettings" ) )
2667 return tl::unexpected( *headless );
2669 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2670 return tl::unexpected( *busy );
2675 const BoardEditorAppearanceSettings& newSettings = aCtx.
Request.settings();
2682 bool flip = newSettings.board_flip() == BoardFlipMode::BFM_FLIPPED_X;
2704 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2705 return tl::unexpected( *busy );
2709 if( !documentValidation )
2710 return tl::unexpected( documentValidation.error() );
2718 drcItem->SetErrorMessage( wxString::FromUTF8( aCtx.
Request.message() ) );
2722 for(
const auto&
id : aCtx.
Request.items() )
2723 ids.emplace_back(
KIID(
id.value() ) );
2726 drcItem->SetItems( ids );
2728 const auto& pos = aCtx.
Request.position();
2729 VECTOR2I position(
static_cast<int>( pos.x_nm() ),
static_cast<int>( pos.y_nm() ) );
2734 commit->
Add( marker );
2735 commit->
Push( wxS(
"API injected DRC marker" ) );
2737 InjectDrcErrorResponse response;
2745 const std::string& aCommandName )
2747 if( aUnits == types::Units::U_INCH || aUnits == types::Units::U_MM
2748 || aUnits == types::Units::U_UNKNOWN )
2750 return std::nullopt;
2753 ApiResponseStatus e;
2754 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2755 e.set_error_message( fmt::format(
"{} supports only inch and mm units", aCommandName ) );
2760std::optional<ApiResponseStatus>
2762 const std::string& aCommandName )
2764 if( aMode == kiapi::board::jobs::BoardJobPaginationMode::BJPM_UNKNOWN
2765 || aMode == kiapi::board::jobs::BoardJobPaginationMode::BJPM_ALL_LAYERS_ONE_PAGE
2766 || aMode == kiapi::board::jobs::BoardJobPaginationMode::BJPM_EACH_LAYER_OWN_FILE )
2768 return std::nullopt;
2771 ApiResponseStatus e;
2772 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2773 e.set_error_message( fmt::format(
"{} does not support EACH_LAYER_OWN_PAGE pagination mode",
2782 for(
int layer : aSettings.layers() )
2785 static_cast<board::types::BoardLayer
>( layer ) );
2789 ApiResponseStatus e;
2790 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2791 e.set_error_message(
"Board plot settings contain an invalid layer" );
2798 for(
int layer : aSettings.common_layers() )
2801 static_cast<board::types::BoardLayer
>( layer ) );
2805 ApiResponseStatus e;
2806 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2807 e.set_error_message(
"Board plot settings contain an invalid common layer" );
2814 aJob.
m_colorTheme = wxString::FromUTF8( aSettings.color_theme() );
2815 aJob.
m_drawingSheet = wxString::FromUTF8( aSettings.drawing_sheet() );
2816 aJob.
m_variant = wxString::FromUTF8( aSettings.variant() );
2818 aJob.
m_mirror = aSettings.mirror();
2821 aJob.
m_scale = aSettings.scale();
2829 aJob.
m_plotRefDes = aSettings.plot_reference_designators();
2839 return std::nullopt;
2845 types::RunJobResponse response;
2848 if( !aContext || !aContext->
GetKiway() )
2850 response.set_status( types::JobStatus::JS_ERROR );
2851 response.set_message(
"Internal error" );
2853 wxCHECK_MSG(
false, response,
"context missing valid kiway in ExecuteBoardJob?" );
2859 response.add_output_path(
output.m_outputPath.ToUTF8() );
2863 response.set_status( types::JobStatus::JS_SUCCESS );
2867 response.set_status( types::JobStatus::JS_ERROR );
2868 response.set_message( fmt::format(
"Board export job '{}' failed with exit code {}: {}",
2878 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2879 return tl::unexpected( *busy );
2883 if( !documentValidation )
2884 return tl::unexpected( documentValidation.error() );
2937 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2938 return tl::unexpected( *busy );
2942 if( !documentValidation )
2943 return tl::unexpected( documentValidation.error() );
2985 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2986 return tl::unexpected( *busy );
2990 if( !documentValidation )
2991 return tl::unexpected( documentValidation.error() );
2998 return tl::unexpected( *err );
3003 if( std::optional<ApiResponseStatus> paginationError =
3005 "RunBoardJobExportSvg" ) )
3007 return tl::unexpected( *paginationError );
3019 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3020 return tl::unexpected( *busy );
3024 if( !documentValidation )
3025 return tl::unexpected( documentValidation.error() );
3032 return tl::unexpected( *err );
3037 if( std::optional<ApiResponseStatus> unitError =
3040 return tl::unexpected( *unitError );
3045 if( std::optional<ApiResponseStatus> paginationError =
3047 "RunBoardJobExportDxf" ) )
3049 return tl::unexpected( *paginationError );
3061 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3062 return tl::unexpected( *busy );
3066 if( !documentValidation )
3067 return tl::unexpected( documentValidation.error() );
3074 return tl::unexpected( *err );
3091 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3092 return tl::unexpected( *busy );
3096 if( !documentValidation )
3097 return tl::unexpected( documentValidation.error() );
3104 return tl::unexpected( *err );
3106 if( std::optional<ApiResponseStatus> paginationError =
3108 "RunBoardJobExportPs" ) )
3110 return tl::unexpected( *paginationError );
3128 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3129 return tl::unexpected( *busy );
3133 if( !documentValidation )
3134 return tl::unexpected( documentValidation.error() );
3136 if( aCtx.
Request.layers().empty() )
3138 ApiResponseStatus e;
3139 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3140 e.set_error_message(
"RunBoardJobExportGerbers requires at least one layer" );
3141 return tl::unexpected( e );
3148 for(
int layer : aCtx.
Request.layers() )
3152 static_cast<board::types::BoardLayer
>( layer ) );
3156 ApiResponseStatus e;
3157 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3158 e.set_error_message(
"RunBoardJobExportGerbers contains an invalid layer" );
3159 return tl::unexpected( e );
3172 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3173 return tl::unexpected( *busy );
3177 if( !documentValidation )
3178 return tl::unexpected( documentValidation.error() );
3186 if( std::optional<ApiResponseStatus> unitError =
3189 return tl::unexpected( *unitError );
3196 if( aCtx.
Request.has_excellon() )
3198 const ExcellonFormatOptions& excellonOptions = aCtx.
Request.excellon();
3200 if( excellonOptions.has_mirror_y() )
3203 if( excellonOptions.has_minimal_header() )
3206 if( excellonOptions.has_combine_pth_npth() )
3209 if( excellonOptions.has_route_oval_holes() )
3213 if( aCtx.
Request.map_format() != DrillMapFormat::DMF_UNKNOWN )
3221 if( aCtx.
Request.has_gerber_generate_tenting() )
3224 if( aCtx.
Request.report_format() != DrillReportFormat::DRF_UNKNOWN )
3228 if( aCtx.
Request.has_report_filename() )
3239 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3240 return tl::unexpected( *busy );
3244 if( !documentValidation )
3245 return tl::unexpected( documentValidation.error() );
3251 if( aCtx.
Request.has_use_drill_place_file_origin() )
3261 if( aCtx.
Request.has_include_board_edge_for_gerber() )
3268 if( std::optional<ApiResponseStatus> unitError =
3271 return tl::unexpected( *unitError );
3284 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3285 return tl::unexpected( *busy );
3289 if( !documentValidation )
3290 return tl::unexpected( documentValidation.error() );
3309 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3310 return tl::unexpected( *busy );
3314 if( !documentValidation )
3315 return tl::unexpected( documentValidation.error() );
3323 if( aCtx.
Request.has_precision() )
3328 job.
m_colMfgPn = wxString::FromUTF8( aCtx.
Request.manufacturer_part_number_column() );
3329 job.
m_colMfg = wxString::FromUTF8( aCtx.
Request.manufacturer_column() );
3330 job.
m_colDistPn = wxString::FromUTF8( aCtx.
Request.distributor_part_number_column() );
3334 if( std::optional<ApiResponseStatus> unitError =
3337 return tl::unexpected( *unitError );
3350 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3351 return tl::unexpected( *busy );
3355 if( !documentValidation )
3356 return tl::unexpected( documentValidation.error() );
3369 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3370 return tl::unexpected( *busy );
3374 if( !documentValidation )
3375 return tl::unexpected( documentValidation.error() );
3383 if( aCtx.
Request.has_precision() )
3386 if( std::optional<ApiResponseStatus> unitError =
3389 return tl::unexpected( *unitError );
3402 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3403 return tl::unexpected( *busy );
3407 if( !documentValidation )
3408 return tl::unexpected( documentValidation.error() );
3416 if( std::optional<ApiResponseStatus> unitError =
3419 return tl::unexpected( *unitError );
types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
tl::expected< T, ApiResponseStatus > HANDLER_RESULT
std::optional< ApiResponseStatus > ValidatePaginationModeForSingleOrPerFile(kiapi::board::jobs::BoardJobPaginationMode aMode, const std::string &aCommandName)
std::optional< ApiResponseStatus > ApplyBoardPlotSettings(const BoardPlotSettings &aSettings, JOB_EXPORT_PCB_PLOT &aJob)
std::optional< ApiResponseStatus > ValidateUnitsInchMm(types::Units aUnits, const std::string &aCommandName)
HANDLER_RESULT< types::RunJobResponse > ExecuteBoardJob(BOARD_CONTEXT *aContext, JOB &aJob)
std::unique_ptr< EDA_ITEM > CreateItemForType(KICAD_T aType, EDA_ITEM *aContainer)
std::shared_ptr< BOARD_CONTEXT > CreatePcbFrameContext(PCB_EDIT_FRAME *aFrame)
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)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportPdf(const HANDLER_CONTEXT< RunBoardJobExportPdf > &aCtx)
HANDLER_RESULT< BoardDesignRulesResponse > handleSetBoardDesignRules(const HANDLER_CONTEXT< SetBoardDesignRules > &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< commands::GetItemsResponse > handleGetConnectedItems(const HANDLER_CONTEXT< GetConnectedItems > &aCtx)
HANDLER_RESULT< types::Vector2 > handleGetBoardOrigin(const HANDLER_CONTEXT< GetBoardOrigin > &aCtx)
std::shared_ptr< BOARD_CONTEXT > m_context
HANDLER_RESULT< commands::GetItemsResponse > handleGetItemsByNetClass(const HANDLER_CONTEXT< GetItemsByNetClass > &aCtx)
std::unique_ptr< COMMIT > createCommit() override
Override this to create an appropriate COMMIT subclass for the frame in question.
BOARD_CONTEXT * context() const
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)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportIpcD356(const HANDLER_CONTEXT< RunBoardJobExportIpcD356 > &aCtx)
HANDLER_RESULT< BoardDesignRulesResponse > handleGetBoardDesignRules(const HANDLER_CONTEXT< GetBoardDesignRules > &aCtx)
std::optional< EDA_ITEM * > getItemFromDocument(const DocumentSpecifier &aDocument, const KIID &aId) override
HANDLER_RESULT< commands::ExpandTextVariablesResponse > handleExpandTextVariables(const HANDLER_CONTEXT< commands::ExpandTextVariables > &aCtx)
std::optional< ApiResponseStatus > checkForHeadless(const std::string &aCommandName) const
HANDLER_RESULT< Empty > handleSetVisibleLayers(const HANDLER_CONTEXT< SetVisibleLayers > &aCtx)
HANDLER_RESULT< Empty > handleSetTitleBlockInfo(const HANDLER_CONTEXT< commands::SetTitleBlockInfo > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportGerbers(const HANDLER_CONTEXT< RunBoardJobExportGerbers > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportODB(const HANDLER_CONTEXT< RunBoardJobExportODB > &aCtx)
HANDLER_RESULT< Empty > handleSaveCopyOfDocument(const HANDLER_CONTEXT< commands::SaveCopyOfDocument > &aCtx)
HANDLER_RESULT< GraphicsDefaultsResponse > handleGetGraphicsDefaults(const HANDLER_CONTEXT< GetGraphicsDefaults > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExport3D(const HANDLER_CONTEXT< RunBoardJobExport3D > &aCtx)
TOOL_MANAGER * toolManager() const
HANDLER_RESULT< commands::GetItemsResponse > handleGetItemsById(const HANDLER_CONTEXT< commands::GetItemsById > &aCtx)
HANDLER_RESULT< commands::GetItemsResponse > handleGetItemsByNet(const HANDLER_CONTEXT< GetItemsByNet > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportIpc2581(const HANDLER_CONTEXT< RunBoardJobExportIpc2581 > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportPosition(const HANDLER_CONTEXT< RunBoardJobExportPosition > &aCtx)
HANDLER_RESULT< Empty > handleSetBoardOrigin(const HANDLER_CONTEXT< SetBoardOrigin > &aCtx)
HANDLER_RESULT< BoardLayerNameResponse > handleGetBoardLayerName(const HANDLER_CONTEXT< GetBoardLayerName > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportStats(const HANDLER_CONTEXT< RunBoardJobExportStats > &aCtx)
HANDLER_RESULT< Empty > handleClearSelection(const HANDLER_CONTEXT< commands::ClearSelection > &aCtx)
HANDLER_RESULT< commands::RunActionResponse > handleRunAction(const HANDLER_CONTEXT< commands::RunAction > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportPs(const HANDLER_CONTEXT< RunBoardJobExportPs > &aCtx)
HANDLER_RESULT< CustomRulesResponse > handleGetCustomDesignRules(const HANDLER_CONTEXT< GetCustomDesignRules > &aCtx)
HANDLER_RESULT< BoardLayers > handleGetVisibleLayers(const HANDLER_CONTEXT< GetVisibleLayers > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportSvg(const HANDLER_CONTEXT< RunBoardJobExportSvg > &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< types::RunJobResponse > handleRunBoardJobExportDxf(const HANDLER_CONTEXT< RunBoardJobExportDxf > &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
PROJECT & project() const
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportDrill(const HANDLER_CONTEXT< RunBoardJobExportDrill > &aCtx)
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)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportRender(const HANDLER_CONTEXT< RunBoardJobExportRender > &aCtx)
PCB_EDIT_FRAME * frame() const
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportGencad(const HANDLER_CONTEXT< RunBoardJobExportGencad > &aCtx)
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
HANDLER_RESULT< CustomRulesResponse > handleSetCustomDesignRules(const HANDLER_CONTEXT< SetCustomDesignRules > &aCtx)
std::vector< KICAD_T > parseRequestedItemTypes(const google::protobuf::RepeatedField< int > &aTypes)
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)
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
An interface for the frame surface that the API handlers need; to enable headless mode.
virtual bool SaveBoard()=0
virtual bool SavePcbCopy(const wxString &aFileName, bool aCreateProject, bool aHeadless)=0
virtual KIWAY * GetKiway() const =0
virtual BOARD * GetBoard() const =0
virtual PROJECT & Prj() const =0
virtual wxString GetCurrentFileName() const =0
Container for design settings for a BOARD object.
std::map< wxString, wxString > m_DrcExclusionComments
int m_CopperEdgeClearance
std::map< int, SEVERITY > m_DRCSeverities
bool m_TextUpright[LAYER_CLASS_COUNT]
int m_MinSilkTextThickness
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
std::set< wxString > m_DrcExclusions
int m_SolderMaskToCopperClearance
const VECTOR2I & GetGridOrigin() const
bool m_AllowSoldermaskBridgesInFPs
TEARDROP_PARAMETERS_LIST m_TeardropParamsList
The parameters of teardrops for the different teardrop targets (via/pad, track end).
const VECTOR2I & GetAuxOrigin() const
int m_SolderMaskExpansion
int m_TextThickness[LAYER_CLASS_COUNT]
std::vector< int > m_TrackWidthList
std::vector< VALIDATION_ERROR > ValidateDesignRules(std::optional< EDA_UNITS > aUnits=std::nullopt) const
Validate design settings values and return per-field errors.
int m_LineThickness[LAYER_CLASS_COUNT]
double m_SolderPasteMarginRatio
VECTOR2I m_TextSize[LAYER_CLASS_COUNT]
bool m_TextItalic[LAYER_CLASS_COUNT]
std::vector< VIA_DIMENSION > m_ViasDimensionsList
int m_ViasMinAnnularWidth
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...
void SetDesignSettings(const BOARD_DESIGN_SETTINGS &aSettings)
TITLE_BLOCK & GetTitleBlock()
const wxString & GetFileName() const
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
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
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.
void ToProto(kiapi::board::CustomRuleConstraint &aProto) const
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
void Parse(std::vector< std::shared_ptr< DRC_RULE > > &aRules, REPORTER *aReporter)
static wxString ExtractRuleComment(const wxString &aOriginalText)
Extract comment lines from a rule.
static wxString ExtractRuleText(const wxString &aContent, const wxString &aRuleName)
Extract the complete original text of a rule from file content.
static wxString FormatRuleFromProto(const kiapi::board::CustomRule &aRule, wxString *aErrorText=nullptr)
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
double m_BoardOutlinesChainingEpsilon
bool m_IncludeUnspecified
wxString m_ComponentFilter
bool m_UsePcbCenterOrigin
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
JOB_EXPORT_PCB_3D::FORMAT m_format
EXPORTER_STEP_PARAMS m_3dparams
Despite the name; also used for other formats.
ZEROS_FORMAT m_zeroFormat
bool m_excellonOvalDrillRoute
DRILL_ORIGIN m_drillOrigin
bool m_excellonCombinePTHNPTH
bool m_excellonMinimalHeader
bool m_plotGraphicItemsUsingContours
bool m_useIndividualShapes
IPC2581_VERSION m_version
ODB_COMPRESSION m_compressionMode
bool m_pdfFrontFPPropertyPopups
wxString m_pdfBackgroundColor
bool m_pdfSingle
This is a hack to deal with cli having the wrong behavior We will deprecate out the wrong behavior,...
bool m_pdfBackFPPropertyPopups
GEN_MODE m_pdfGenMode
The background color specified in a hex string.
bool m_sketchDNPFPsOnFabLayers
bool m_plotFootprintValues
LSEQ m_plotOnAllLayersSequence
Used by SVG & PDF.
bool m_checkZonesBeforePlot
bool m_sketchPadsOnFabLayers
DRILL_MARKS m_drillShapeOption
Used by SVG/DXF/PDF/Gerbers.
bool m_crossoutDNPFPsOnFabLayers
bool m_hideDNPFPsOnFabLayers
bool m_mirror
Common Options.
bool m_subtractSolderMaskFromSilk
LSEQ m_plotLayerSequence
Layers to include on all individual layer prints.
wxString m_variant
Variant name for variant-aware filtering.
bool m_useDrillPlaceFileOrigin
bool m_excludeFootprintsWithTh
double m_trackWidthCorrection
bool m_subtractHolesFromBoardArea
bool m_excludeFootprintsWithoutPads
bool m_subtractHolesFromCopperAreas
VECTOR3D m_lightBottomIntensity
VECTOR3D m_lightTopIntensity
VECTOR3D m_lightCameraIntensity
bool m_proceduralTextures
bool m_useBoardStackupColors
VECTOR3D m_lightSideIntensity
std::string m_appearancePreset
An simple container class that lets us dispatch output jobs to kifaces.
void SetConfiguredOutputPath(const wxString &aPath)
Sets the configured output path for the job, this path is always saved to file.
const std::vector< JOB_OUTPUT > & GetOutputs()
const std::string & GetType() 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
int ProcessJob(KIWAY::FACE_T aFace, JOB *aJob, REPORTER *aReporter=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
LSET is a set of PCB_LAYER_IDs.
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
static int NameToLayer(wxString &aName)
Return the layer number from a layer name.
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.
bool ContainsNetclassWithName(const wxString &netclass) const
Determines if the given netclass name is a constituent of this (maybe aggregate) netclass.
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 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,...
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
TEARDROP_PARAMETERS_LIST is a helper class to handle the list of TEARDROP_PARAMETERS needed to build ...
bool m_UseRoundShapesOnly
True to create teardrops for round shapes only.
bool m_TargetVias
True to create teardrops for vias.
bool m_TargetPTHPads
True to create teardrops for pads with holes.
bool m_TargetTrack2Track
True to create teardrops at the end of a track connected to the end of another track having a differe...
TEARDROP_PARAMETERS * GetParameters(TARGET_TD aTdType)
bool m_TargetSMDPads
True to create teardrops for pads SMD, edge connectors,.
TEARDROP_PARAMETARS is a helper class to handle parameters needed to build teardrops for a board thes...
double m_BestWidthRatio
The height of a teardrop as ratio between height and size of pad/via.
int m_TdMaxLen
max allowed length for teardrops in IU. <= 0 to disable
bool m_AllowUseTwoTracks
True to create teardrops using 2 track segments if the first in too small.
int m_TdMaxWidth
max allowed height for teardrops in IU. <= 0 to disable
double m_BestLengthRatio
The length of a teardrop as ratio between length and size of pad/via.
double m_WidthtoSizeFilterRatio
The ratio (H/D) between the via/pad size and the track width max value to create a teardrop 1....
bool m_TdOnPadsInZones
A filter to exclude pads inside zone fills.
bool m_Enabled
Flag to enable teardrops.
bool m_CurvedEdges
True if the teardrop should be curved.
Hold the information shown in the lower right corner of a plot, printout, or editing view.
const wxString & GetCompany() const
void SetRevision(const wxString &aRevision)
void SetComment(int aIdx, const wxString &aComment)
const wxString & GetRevision() const
void SetTitle(const wxString &aTitle)
const wxString & GetDate() const
const wxString & GetComment(int aIdx) const
void SetCompany(const wxString &aCompany)
const wxString & GetTitle() const
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
A wrapper for reporting to a wxString object.
const wxString & GetMessages() const
A type-safe container of any type.
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
static const std::string DesignRulesFileExtension
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 VECTOR3D UnpackVector3D(const types::Vector3D &aInput)
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.
std::vector< EDA_ITEM * > EDA_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_REFERENCE_IMAGE_T
class PCB_REFERENCE_IMAGE, bitmap 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