21#include <magic_enum.hpp>
34#include <api/common/commands/library_commands.pb.h>
95#include <api/common/types/base_types.pb.h>
96#include <api/board/board_rules.pb.h>
98#include <google/protobuf/util/json_util.h>
107using namespace kiapi::common::commands;
108using namespace kiapi::board::commands;
109using types::CommandStatus;
110using types::DocumentType;
111using types::ItemRequestStatus;
227 if( aCtx.
Request.type() != DocumentType::DOCTYPE_PCB )
231 e.set_status( ApiStatusCode::AS_UNHANDLED );
232 return tl::unexpected( e );
235 GetOpenDocumentsResponse response;
236 common::types::DocumentSpecifier doc;
238 wxFileName fn(
pcbContext()->GetCurrentFileName() );
240 doc.set_type( DocumentType::DOCTYPE_PCB );
241 doc.set_board_filename( fn.GetFullName() );
246 response.mutable_documents()->Add( std::move( doc ) );
255 return tl::unexpected( documentValidation.error() );
257 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
258 return tl::unexpected( *busy );
260 if(
board()->GetFileName().IsEmpty() )
263 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
264 e.set_error_message(
"the board is untitled; use SaveDocumentAs to save it to a new file" );
265 return tl::unexpected( e );
271 e.set_status( ApiStatusCode::AS_INTERNAL_ERROR );
272 e.set_error_message(
"board could not be saved" );
273 return tl::unexpected( e );
285 e.set_status( ApiStatusCode::AS_UNIMPLEMENTED );
286 e.set_error_message(
"SaveDocumentAs is not available in GUI mode" );
287 return tl::unexpected( e );
291 return tl::unexpected( documentValidation.error() );
293 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
294 return tl::unexpected( *busy );
296 wxString pathStr = wxString::FromUTF8( aCtx.
Request.path() );
298 if( pathStr.IsEmpty() )
301 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
302 e.set_error_message(
"path is required" );
303 return tl::unexpected( e );
306 wxFileName oldBoardFile(
pcbContext()->GetCurrentFileName() );
311 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
312 e.set_error_message( fmt::format(
"failed to save board to '{}'", pathStr.ToStdString() ) );
313 return tl::unexpected( e );
318 wxFileName newBoardFile( pathStr );
321 server->NotifyDocumentRenamed(
thisDocumentType(), oldBoardFile.GetFullPath(), newBoardFile.GetFullPath() );
332 return tl::unexpected( documentValidation.error() );
334 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
335 return tl::unexpected( *busy );
337 wxFileName boardPath(
project().AbsolutePath( wxString::FromUTF8( aCtx.
Request.path() ) ) );
339 if( !boardPath.IsOk() || !boardPath.IsDirWritable() )
342 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
343 e.set_error_message( fmt::format(
"save path '{}' could not be opened",
344 boardPath.GetFullPath().ToStdString() ) );
345 return tl::unexpected( e );
348 if( boardPath.FileExists()
349 && ( !boardPath.IsFileWritable() || !aCtx.
Request.options().overwrite() ) )
352 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
353 e.set_error_message( fmt::format(
"save path '{}' exists and cannot be overwritten",
354 boardPath.GetFullPath().ToStdString() ) );
355 return tl::unexpected( e );
361 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
362 e.set_error_message( fmt::format(
"save path '{}' must have a kicad_pcb extension",
363 boardPath.GetFullPath().ToStdString() ) );
364 return tl::unexpected( e );
369 if( board->
GetFileName().Matches( boardPath.GetFullPath() ) )
374 e.set_status( ApiStatusCode::AS_INTERNAL_ERROR );
375 e.set_error_message(
"board could not be saved" );
376 return tl::unexpected( e );
382 bool includeProject =
true;
384 if( aCtx.
Request.has_options() )
385 includeProject = aCtx.
Request.options().include_project();
387 if( !
pcbContext()->SavePcbCopy( boardPath.GetFullPath(), includeProject,
true ) )
390 e.set_status( ApiStatusCode::AS_INTERNAL_ERROR );
391 e.set_error_message( fmt::format(
"board could not be saved to '{}'",
392 boardPath.GetFullPath().ToStdString() ) );
393 return tl::unexpected( e );
405 return tl::unexpected( documentValidation.error() );
412 e.set_status( ApiStatusCode::AS_BUSY );
413 e.set_error_message(
"cannot revert while a commit is open" );
414 return tl::unexpected( e );
417 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
418 return tl::unexpected( *busy );
423 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
424 e.set_error_message(
"could not revert: there is no saved file on disk to revert to" );
425 return tl::unexpected( e );
434 if( aDocument.type() != DocumentType::DOCTYPE_PCB )
437 e.set_status( ApiStatusCode::AS_UNHANDLED );
438 return tl::unexpected( e );
441 wxFileName fn(
pcbContext()->GetCurrentFileName() );
443 if( aDocument.board_filename().compare( fn.GetFullName() ) != 0 )
446 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
447 e.set_error_message( fmt::format(
"the requested document {} is not open",
448 aDocument.board_filename() ) );
449 return tl::unexpected( e );
485 e.set_status( ApiStatusCode::AS_UNHANDLED );
486 return tl::unexpected( e );
489 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
490 return tl::unexpected( *busy );
492 GetItemsResponse response;
495 std::vector<BOARD_ITEM*> items;
496 std::set<KICAD_T> typesRequested, typesInserted;
497 bool handledAnything =
false;
501 if( aCtx.
Request.types().empty() )
504 for(
KICAD_T type : requestedTypes )
506 typesRequested.emplace( type );
508 if( typesInserted.count( type ) )
516 handledAnything =
true;
517 std::copy(
board->Tracks().begin(),
board->Tracks().end(),
518 std::back_inserter( items ) );
524 handledAnything =
true;
528 std::copy( fp->Pads().begin(), fp->Pads().end(),
529 std::back_inserter( items ) );
538 handledAnything =
true;
540 std::copy(
board->Footprints().begin(),
board->Footprints().end(),
541 std::back_inserter( items ) );
555 handledAnything =
true;
556 bool inserted =
false;
560 if( item->Type() == type )
562 items.emplace_back( item );
568 typesInserted.insert( type );
575 handledAnything =
true;
576 bool inserted =
false;
580 switch (item->Type()) {
586 items.emplace_back( item );
604 handledAnything =
true;
606 std::copy(
board->Zones().begin(),
board->Zones().end(),
607 std::back_inserter( items ) );
615 handledAnything =
true;
617 std::copy(
board->Groups().begin(),
board->Groups().end(),
618 std::back_inserter( items ) );
626 handledAnything =
true;
627 std::copy(
board->Points().begin(),
board->Points().end(), std::back_inserter( items ) );
634 handledAnything =
true;
635 std::ranges::copy(
board->Generators(), std::back_inserter( items ) );
642 handledAnything =
true;
644 std::copy(
board->Constraints().begin(),
board->Constraints().end(),
645 std::back_inserter( items ) );
656 if( !handledAnything )
659 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
660 e.set_error_message(
"none of the requested types are valid for a Board object" );
661 return tl::unexpected( e );
666 if( !typesRequested.count( item->Type() ) )
669 google::protobuf::Any itemBuf;
670 item->Serialize( itemBuf );
671 response.mutable_items()->Add( std::move( itemBuf ) );
674 response.set_status( ItemRequestStatus::IRS_OK );
683 return tl::unexpected( documentValidation.error() );
685 if( aCtx.
Request.copper_layer_count() < 2 || aCtx.
Request.copper_layer_count() % 2 != 0 )
688 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
689 e.set_error_message(
"copper_layer_count must be an even number of at least 2" );
690 return tl::unexpected( e );
696 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
697 e.set_error_message( fmt::format(
"copper_layer_count must be below %d",
MAX_CU_LAYERS ) );
698 return tl::unexpected( e );
701 int copperLayerCount =
static_cast<int>( aCtx.
Request.copper_layer_count() );
706 enabled &=
~LSET::AllCuMask();
711 LSET previousEnabled =
board->GetEnabledLayers();
712 LSET changedLayers = enabled ^ previousEnabled;
714 board->SetEnabledLayers( enabled );
715 board->SetVisibleLayers(
board->GetVisibleLayers() | changedLayers );
721 if( !enabled[layer_id] &&
board->HasItemsOnLayer( layer_id ) )
722 removedLayers.push_back( layer_id );
725 bool modified =
false;
727 if( !removedLayers.empty() )
732 modified |=
board->RemoveAllItemsOnLayer( layer_id );
735 if( enabled != previousEnabled || modified )
738 BoardEnabledLayersResponse response;
740 response.set_copper_layer_count( copperLayerCount );
751 return tl::unexpected( documentValidation.error() );
753 common::types::EmbeddedFiles response;
764 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
765 e.set_error_message(
"embedded file validation failed" );
766 return tl::unexpected( e );
776 return tl::unexpected( documentValidation.error() );
778 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
779 return tl::unexpected( *busy );
789 for(
const std::shared_ptr<EMBEDDED_FILES::EMBEDDED_FILE>& file : files.
EmbeddedFileMap() | std::views::values )
791 auto copy = std::make_shared<EMBEDDED_FILES::EMBEDDED_FILE>( *file );
803 return tl::unexpected( documentValidation.error() );
805 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
806 return tl::unexpected( *busy );
824 if( !documentValidation )
825 return tl::unexpected( documentValidation.error() );
828 BoardDesignRulesResponse response;
829 kiapi::board::BoardDesignRules* rules = response.mutable_rules();
831 kiapi::board::MinimumConstraints* constraints = rules->mutable_constraints();
833 constraints->mutable_min_clearance()->set_value_nm( bds.
m_MinClearance );
834 constraints->mutable_min_groove_width()->set_value_nm( bds.
m_MinGrooveWidth );
835 constraints->mutable_min_connection_width()->set_value_nm( bds.
m_MinConn );
836 constraints->mutable_min_track_width()->set_value_nm( bds.
m_TrackMinWidth );
838 constraints->mutable_min_via_size()->set_value_nm( bds.
m_ViasMinSize );
843 constraints->mutable_hole_clearance()->set_value_nm( bds.
m_HoleClearance );
844 constraints->mutable_hole_to_hole_min()->set_value_nm( bds.
m_HoleToHoleMin );
845 constraints->mutable_silk_clearance()->set_value_nm( bds.
m_SilkClearance );
850 kiapi::board::PredefinedSizes* sizes = rules->mutable_predefined_sizes();
853 sizes->add_tracks()->mutable_width()->set_value_nm( bds.
m_TrackWidthList[ii] );
857 kiapi::board::PresetViaDimension*
via = sizes->add_vias();
864 kiapi::board::PresetDiffPairDimension* pair = sizes->add_diff_pairs();
870 kiapi::board::SolderMaskPasteDefaults* maskPaste = rules->mutable_solder_mask_paste();
879 kiapi::board::TeardropDefaults* teardrops = rules->mutable_teardrops();
892 kiapi::board::TeardropTargetEntry* entry = teardrops->add_target_params();
896 entry->mutable_params()->set_enabled( params->
m_Enabled );
897 entry->mutable_params()->mutable_max_length()->set_value_nm( params->
m_TdMaxLen );
898 entry->mutable_params()->mutable_max_width()->set_value_nm( params->
m_TdMaxWidth );
902 entry->mutable_params()->set_curved_edges( params->
m_CurvedEdges );
907 kiapi::board::ViaProtectionDefaults* viaProtection = rules->mutable_via_protection();
920 board::DrcSeveritySetting* setting = rules->add_severities();
921 setting->set_rule_type(
927 rules->add_exclusions()->CopyFrom( exclusion.
ToProto() );
929 response.set_custom_rules_status( CRS_NONE );
933 if( !rulesPath.IsEmpty() && wxFileName::IsFileReadable( rulesPath ) )
935 wxFFile file( rulesPath,
"r" );
937 std::vector<std::shared_ptr<DRC_RULE>> parsedRules;
939 if( !file.IsOpened() )
941 response.set_custom_rules_status( CRS_INVALID );
945 file.ReadAll( &content );
951 parser.
Parse( parsedRules,
nullptr );
952 response.set_custom_rules_status( CRS_VALID );
956 response.set_custom_rules_status( CRS_INVALID );
969 if( !documentValidation )
970 return tl::unexpected( documentValidation.error() );
973 const kiapi::board::BoardDesignRules& rules = aCtx.
Request.rules();
975 if( rules.has_constraints() )
977 const kiapi::board::MinimumConstraints& constraints = rules.constraints();
979 newSettings.
m_MinClearance = constraints.min_clearance().value_nm();
981 newSettings.
m_MinConn = constraints.min_connection_width().value_nm();
982 newSettings.
m_TrackMinWidth = constraints.min_track_width().value_nm();
984 newSettings.
m_ViasMinSize = constraints.min_via_size().value_nm();
990 newSettings.
m_HoleToHoleMin = constraints.hole_to_hole_min().value_nm();
997 if( rules.has_predefined_sizes() )
1002 for(
const kiapi::board::PresetTrackWidth& track : rules.predefined_sizes().tracks() )
1008 for(
const kiapi::board::PresetViaDimension&
via : rules.predefined_sizes().vias() )
1011 static_cast<int>(
via.drill().value_nm() ) );
1017 for(
const kiapi::board::PresetDiffPairDimension& pair : rules.predefined_sizes().diff_pairs() )
1020 static_cast<int>( pair.width().value_nm() ),
1021 static_cast<int>( pair.gap().value_nm() ),
1022 static_cast<int>( pair.via_gap().value_nm() ) );
1026 if( rules.has_solder_mask_paste() )
1028 const kiapi::board::SolderMaskPasteDefaults& maskPaste = rules.solder_mask_paste();
1036 maskPaste.allow_soldermask_bridges_in_footprints();
1039 if( rules.has_teardrops() )
1041 const kiapi::board::TeardropDefaults& teardrops = rules.teardrops();
1049 for(
const kiapi::board::TeardropTargetEntry& entry : teardrops.target_params() )
1051 if( entry.target() == kiapi::board::TeardropTarget::TDT_UNKNOWN )
1059 ApiResponseStatus e;
1060 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1061 e.set_error_message(
"unknown teardrop target" );
1062 return tl::unexpected( e );
1067 params->
m_Enabled = entry.params().enabled();
1068 params->
m_TdMaxLen = entry.params().max_length().value_nm();
1069 params->
m_TdMaxWidth = entry.params().max_width().value_nm();
1079 if( rules.has_via_protection() )
1081 const kiapi::board::ViaProtectionDefaults& viaProtection = rules.via_protection();
1089 newSettings.
m_CapVias = viaProtection.cap();
1090 newSettings.
m_FillVias = viaProtection.fill();
1093 if( rules.severities_size() > 0 )
1097 for(
const kiapi::board::DrcSeveritySetting& severitySetting : rules.severities() )
1105 if( !permitted.contains( setting ) )
1107 ApiResponseStatus e;
1108 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1109 e.set_error_message( fmt::format(
"DRC severity must be error, warning, or ignore" ) );
1110 return tl::unexpected( e );
1117 if( rules.exclusions_size() > 0 )
1121 for(
const kiapi::board::DrcExclusion& exclusion : rules.exclusions() )
1125 std::vector<BOARD_DESIGN_SETTINGS::VALIDATION_ERROR> errors = newSettings.
ValidateDesignRules();
1127 if( !errors.empty() )
1131 ApiResponseStatus e;
1132 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1133 e.set_error_message( fmt::format(
"Invalid board design rules: {}: {}",
1136 return tl::unexpected( e );
1155 if( !documentValidation )
1156 return tl::unexpected( documentValidation.error() );
1158 CustomRulesResponse response;
1159 response.set_status( CRS_NONE );
1163 if( rulesPath.IsEmpty() || !wxFileName::IsFileReadable( rulesPath ) )
1166 wxFFile file( rulesPath,
"r" );
1168 if( !file.IsOpened() )
1170 response.set_status( CRS_INVALID );
1171 response.set_error_text(
"Failed to open custom rules file" );
1176 file.ReadAll( &content );
1179 std::vector<std::shared_ptr<DRC_RULE>> parsedRules;
1184 parser.
Parse( parsedRules,
nullptr );
1188 response.set_status( CRS_INVALID );
1189 response.set_error_text( ioe.
What().ToStdString() );
1193 for(
const std::shared_ptr<DRC_RULE>& rule : parsedRules )
1200 kiapi::board::CustomRule* customRule = response.add_rules();
1202 if( rule->m_Condition )
1203 customRule->set_condition( rule->m_Condition->GetExpression().ToUTF8() );
1207 board::CustomRuleConstraint* constraintProto = customRule->add_constraints();
1208 constraint.
ToProto( *constraintProto );
1212 customRule->set_name( rule->m_Name.ToUTF8() );
1214 if( rule->m_LayerSource.CmpNoCase( wxS(
"outer" ) ) == 0 )
1216 customRule->set_layer_mode( kiapi::board::CRLM_OUTER );
1218 else if( rule->m_LayerSource.CmpNoCase( wxS(
"inner" ) ) == 0 )
1220 customRule->set_layer_mode( kiapi::board::CRLM_INNER );
1222 else if( !rule->m_LayerSource.IsEmpty() )
1228 customRule->set_single_layer(
1233 if( !comment.IsEmpty() )
1234 customRule->set_comments( comment );
1237 response.set_status( CRS_VALID );
1247 if( !documentValidation )
1248 return tl::unexpected( documentValidation.error() );
1252 if( aCtx.
Request.rules_size() == 0 )
1254 if( wxFileName::FileExists( rulesPath ) )
1256 if( !wxRemoveFile( rulesPath ) )
1258 CustomRulesResponse response;
1259 response.set_status( CRS_INVALID );
1260 response.set_error_text(
"Failed to remove custom rules file" );
1265 CustomRulesResponse response;
1266 response.set_status( CRS_NONE );
1271 rulesText <<
"(version 2)\n";
1273 for(
const board::CustomRule& rule : aCtx.
Request.rules() )
1275 wxString serializationError;
1278 if( serializedRule.IsEmpty() )
1280 CustomRulesResponse response;
1281 response.set_status( CRS_INVALID );
1283 if( serializationError.IsEmpty() )
1284 response.set_error_text(
"Failed to serialize custom rule" );
1286 response.set_error_text( serializationError.ToUTF8() );
1291 rulesText <<
"\n" << serializedRule;
1297 std::vector<std::shared_ptr<DRC_RULE>> parsedRules;
1299 parser.
Parse( parsedRules,
nullptr );
1303 CustomRulesResponse response;
1304 response.set_status( CRS_INVALID );
1305 response.set_error_text( ioe.
What().ToStdString() );
1309 wxFFile file( rulesPath,
"w" );
1311 if( !file.IsOpened() )
1313 CustomRulesResponse response;
1314 response.set_status( CRS_INVALID );
1315 response.set_error_text(
"Failed to open custom rules file for writing" );
1319 if( !file.Write( rulesText ) )
1323 CustomRulesResponse response;
1324 response.set_status( CRS_INVALID );
1325 response.set_error_text(
"Failed to write custom rules file" );
1341 !documentValidation )
1343 return tl::unexpected( documentValidation.error() );
1362 ApiResponseStatus e;
1363 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1364 e.set_error_message(
"Unexpected origin type" );
1365 return tl::unexpected( e );
1369 types::Vector2 reply;
1378 return tl::unexpected( documentValidation.error() );
1380 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1381 return tl::unexpected( *busy );
1438 ApiResponseStatus e;
1439 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1440 e.set_error_message(
"Unexpected origin type" );
1441 return tl::unexpected( e );
1453 !documentValidation )
1455 return tl::unexpected( documentValidation.error() );
1458 BoardLayerNameResponse response;
1462 response.set_name(
board()->GetLayerName(
id ) );
1472 !documentValidation )
1474 return tl::unexpected( documentValidation.error() );
1477 BoardLayerResponse response;
1536 brd->SynchronizeNetsAndNetClasses(
false );
1554 return tl::unexpected( documentValidation.error() );
1556 GetDocumentModifiedStateResponse response;
1557 response.set_state(
pcbContext()->IsContentModified() ? DocumentModifiedState::DMS_MODIFIED
1558 : DocumentModifiedState::DMS_UNMODIFIED );
1566 return tl::unexpected( documentValidation.error() );
1568 NetsResponse response;
1571 std::set<wxString> netclassFilter;
1573 for(
const std::string& nc : aCtx.
Request.netclass_filter() )
1574 netclassFilter.insert( wxString( nc.c_str(), wxConvUTF8 ) );
1580 if( !netclassFilter.empty() && nc )
1582 bool inClass =
false;
1584 for(
const wxString&
filter : netclassFilter )
1597 board::types::Net* netProto = response.add_nets();
1598 netProto->set_name( net->GetNetname() );
1599 netProto->mutable_code()->set_value( net->GetNetCode() );
1611 ApiResponseStatus e;
1612 e.set_status( ApiStatusCode::AS_UNHANDLED );
1613 return tl::unexpected( e );
1616 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1617 return tl::unexpected( *busy );
1620 const bool filterByType = aCtx.
Request.types_size() > 0;
1622 if( filterByType &&
types.empty() )
1624 ApiResponseStatus e;
1625 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1626 e.set_error_message(
"none of the requested types are valid for a Board object" );
1627 return tl::unexpected( e );
1630 std::set<KICAD_T> typeFilter(
types.begin(),
types.end() );
1631 std::vector<BOARD_CONNECTED_ITEM*> sourceItems;
1633 for(
const types::KIID&
id : aCtx.
Request.items() )
1635 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
1638 sourceItems.emplace_back( connected );
1642 if( sourceItems.empty() )
1644 ApiResponseStatus e;
1645 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1646 e.set_error_message(
"none of the requested IDs were found or valid connected items" );
1647 return tl::unexpected( e );
1650 GetItemsResponse response;
1652 std::set<KIID> insertedItems;
1658 if( filterByType && !typeFilter.contains( connected->Type() ) )
1661 if( !insertedItems.insert( connected->m_Uuid ).second )
1664 connected->Serialize( *response.add_items() );
1668 response.set_status( ItemRequestStatus::IRS_OK );
1678 ApiResponseStatus e;
1679 e.set_status( ApiStatusCode::AS_UNHANDLED );
1680 return tl::unexpected( e );
1683 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1684 return tl::unexpected( *busy );
1687 const bool filterByType = aCtx.
Request.types_size() > 0;
1689 if( filterByType &&
types.empty() )
1691 ApiResponseStatus e;
1692 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1693 e.set_error_message(
"none of the requested types are valid for a Board object" );
1694 return tl::unexpected( e );
1700 GetItemsResponse response;
1702 std::shared_ptr<CONNECTIVITY_DATA> conn =
board->GetConnectivity();
1703 std::set<KIID> insertedItems;
1707 for(
const board::types::Net& net : aCtx.
Request.nets() )
1716 if( !insertedItems.insert( item->m_Uuid ).second )
1719 item->Serialize( *response.add_items() );
1723 response.set_status( ItemRequestStatus::IRS_OK );
1733 ApiResponseStatus e;
1734 e.set_status( ApiStatusCode::AS_UNHANDLED );
1735 return tl::unexpected( e );
1738 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1739 return tl::unexpected( *busy );
1742 const bool filterByType = aCtx.
Request.types_size() > 0;
1744 if( filterByType &&
types.empty() )
1746 ApiResponseStatus e;
1747 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1748 e.set_error_message(
"none of the requested types are valid for a Board object" );
1749 return tl::unexpected( e );
1755 std::set<wxString> requestedClasses;
1757 for(
const std::string& netClass : aCtx.
Request.net_classes() )
1758 requestedClasses.insert( wxString( netClass.c_str(), wxConvUTF8 ) );
1760 GetItemsResponse response;
1762 std::shared_ptr<CONNECTIVITY_DATA> conn =
board->GetConnectivity();
1763 std::set<KIID> insertedItems;
1772 if( !requestedClasses.empty() )
1777 bool inClass =
false;
1779 for(
const wxString&
filter : requestedClasses )
1794 if( !insertedItems.insert( item->m_Uuid ).second )
1797 item->Serialize( *response.add_items() );
1801 response.set_status( ItemRequestStatus::IRS_OK );
1809 NetClassForNetsResponse response;
1814 for(
const board::types::Net& net : aCtx.
Request.net() )
1821 auto [pair, rc] = response.mutable_classes()->insert( { net.name(), {} } );
1832 return tl::unexpected( documentValidation.error() );
1834 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1835 return tl::unexpected( *busy );
1844 if( aCtx.
Request.zones().empty() )
1848 frame()->CallAfter( [mgr]()
1862 std::vector<ZONE*> toFill;
1864 for(
const types::KIID&
id : aCtx.
Request.zones() )
1868 if( !item || ( *item )->Type() !=
PCB_ZONE_T )
1870 ApiResponseStatus e;
1871 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1872 e.set_error_message( fmt::format(
"zone with ID {} not found on the board",
id.value() ) );
1873 return tl::unexpected( e );
1876 ZONE* zone =
static_cast<ZONE*
>( *item );
1881 ApiResponseStatus e;
1882 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1883 e.set_error_message( fmt::format(
"zone with ID {} is a rule area and cannot be filled",
1885 return tl::unexpected( e );
1890 toFill.push_back( zone );
1896 if( !filler.
Fill( toFill ) )
1900 ApiResponseStatus e;
1901 e.set_status( ApiStatusCode::AS_UNKNOWN );
1902 e.set_error_message(
"zone fill failed" );
1903 return tl::unexpected( e );
1920 if( !documentValidation )
1921 return tl::unexpected( documentValidation.error() );
1923 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1924 return tl::unexpected( *busy );
1926 wxFileName netlistPath(
project().AbsolutePath( wxString::FromUTF8( aCtx.
Request.netlist_path() ) ) );
1928 if( !netlistPath.IsOk() || !netlistPath.FileExists() )
1930 ApiResponseStatus e;
1931 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1932 e.set_error_message(
1933 fmt::format(
"netlist file '{}' could not be opened", netlistPath.GetFullPath().ToStdString() ) );
1934 return tl::unexpected( e );
1940 const bool lookupByTimestamp = aCtx.
Request.match_mode() != NetlistMatchMode::NMM_REFERENCE;
1943 netlist.SetFindByTimeStamp( lookupByTimestamp );
1944 netlist.SetReplaceFootprints( aCtx.
Request.update_footprints() );
1948 ApiResponseStatus e;
1949 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1950 e.set_error_message( fmt::format(
"unable to handle netlist file '{}': {}",
1951 netlistPath.GetFullPath().ToStdString(),
1952 reporter.GetMessages().ToStdString() ) );
1953 return tl::unexpected( e );
1959 updater->SetIsDryRun( aCtx.
Request.dry_run() );
1960 updater->SetLookupByTimestamp( lookupByTimestamp );
1961 updater->SetDeleteUnusedFootprints( aCtx.
Request.delete_extra_footprints() );
1962 updater->SetReplaceFootprints( aCtx.
Request.update_footprints() );
1963 updater->SetTransferGroups( aCtx.
Request.transfer_groups() );
1964 updater->SetOverrideLocks( aCtx.
Request.override_locks() );
1965 updater->SetUpdateFields(
true );
1967 const bool success = updater->UpdateNetlist(
netlist );
1969 if( !aCtx.
Request.dry_run() && success )
1972 ImportNetlistResponse response;
1973 response.set_report(
reporter.GetMessages().ToUTF8() );
1974 response.set_error_count( updater->GetErrorCount() );
1975 response.set_warning_count( updater->GetWarningCount() );
1976 response.set_new_footprint_count( updater->GetNewFootprintCount() );
1984 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"GetBoardEditorAppearanceSettings" ) )
1985 return tl::unexpected( *headless );
1987 BoardEditorAppearanceSettings reply;
1995 reply.set_net_color_display(
1998 reply.set_board_flip(
frame()->GetCanvas()->GetView()->IsMirroredX()
1999 ? BoardFlipMode::BFM_FLIPPED_X
2000 : BoardFlipMode::BFM_NORMAL );
2014 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"SetBoardEditorAppearanceSettings" ) )
2015 return tl::unexpected( *headless );
2017 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2018 return tl::unexpected( *busy );
2022 const BoardEditorAppearanceSettings& newSettings = aCtx.
Request.settings();
2028 options.
m_FlipBoardView = newSettings.board_flip() == BoardFlipMode::BFM_FLIPPED_X;
2045 return tl::unexpected( documentValidation.error() );
2049 BoardPlotSettingsResponse response;
2050 BoardPlotSettings* settings = response.mutable_plot_settings();
2057 settings->set_mirror( plotOpts.
GetMirror() );
2060 settings->set_scale( plotOpts.
GetScale() );
2067 settings->set_plot_footprint_values( plotOpts.
GetPlotValue() );
2083 return tl::unexpected( documentValidation.error() );
2085 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2086 return tl::unexpected( *busy );
2088 const BoardPlotSettings& settings = aCtx.
Request.plot_settings();
2095 for(
int layer : settings.common_layers() )
2102 ApiResponseStatus e;
2103 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2104 e.set_error_message( fmt::format(
"SetBoardPlotSettings contains an invalid layer {}",
2105 magic_enum::enum_name( layerId ) ) );
2106 return tl::unexpected( e );
2109 commonLayers.push_back( layerId );
2114 plotOpts.
SetMirror( settings.mirror() );
2117 plotOpts.
SetScale( settings.scale() );
2124 plotOpts.
SetPlotValue( settings.plot_footprint_values() );
2146 return tl::unexpected( documentValidation.error() );
2148 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2149 return tl::unexpected( *busy );
2157 drcItem->SetErrorMessage( wxString::FromUTF8( aCtx.
Request.message() ) );
2161 for(
const auto&
id : aCtx.
Request.items() )
2162 ids.emplace_back(
KIID(
id.value() ) );
2165 drcItem->SetItems( ids );
2167 const auto& pos = aCtx.
Request.position();
2168 VECTOR2I position(
static_cast<int>( pos.x_nm() ),
static_cast<int>( pos.y_nm() ) );
2173 commit->
Add( marker );
2178 InjectDrcErrorResponse response;
2186 const std::string& aCommandName )
2188 if( aUnits == types::Units::U_INCH || aUnits == types::Units::U_MM
2189 || aUnits == types::Units::U_UNKNOWN )
2191 return std::nullopt;
2194 ApiResponseStatus e;
2195 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2196 e.set_error_message( fmt::format(
"{} supports only inch and mm units", aCommandName ) );
2201std::optional<ApiResponseStatus>
2203 const std::string& aCommandName )
2205 if( aMode == kiapi::board::jobs::BoardJobPaginationMode::BJPM_UNKNOWN
2206 || aMode == kiapi::board::jobs::BoardJobPaginationMode::BJPM_ALL_LAYERS_ONE_PAGE
2207 || aMode == kiapi::board::jobs::BoardJobPaginationMode::BJPM_EACH_LAYER_OWN_FILE )
2209 return std::nullopt;
2212 ApiResponseStatus e;
2213 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2214 e.set_error_message( fmt::format(
"{} does not support EACH_LAYER_OWN_PAGE pagination mode",
2223 for(
int layer : aSettings.layers() )
2226 static_cast<board::types::BoardLayer
>( layer ) );
2228 if( !
IsPcbLayer(
static_cast<int>( layerId ) ) )
2230 ApiResponseStatus e;
2231 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2232 e.set_error_message(
"Board plot settings contain an invalid layer" );
2239 for(
int layer : aSettings.common_layers() )
2242 static_cast<board::types::BoardLayer
>( layer ) );
2244 if( !
IsPcbLayer(
static_cast<int>( layerId ) ) )
2246 ApiResponseStatus e;
2247 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2248 e.set_error_message(
"Board plot settings contain an invalid common layer" );
2255 aJob.
m_colorTheme = wxString::FromUTF8( aSettings.color_theme() );
2256 aJob.
m_drawingSheet = wxString::FromUTF8( aSettings.drawing_sheet() );
2257 aJob.
m_variant = wxString::FromUTF8( aSettings.variant() );
2259 aJob.
m_mirror = aSettings.mirror();
2262 aJob.
m_scale = aSettings.scale();
2270 aJob.
m_plotRefDes = aSettings.plot_reference_designators();
2280 return std::nullopt;
2286 types::RunJobResponse response;
2289 if( !aContext || !aContext->
GetKiway() )
2291 response.set_status( types::JobStatus::JS_ERROR );
2292 response.set_message(
"Internal error" );
2293 wxCHECK_MSG(
false, response,
"context missing valid kiway in ExecuteBoardJob?" );
2300 response.add_output_path( output.m_outputPath.ToUTF8() );
2304 response.set_status( types::JobStatus::JS_SUCCESS );
2308 response.set_status( types::JobStatus::JS_ERROR );
2309 response.set_message( fmt::format(
"Board export job '{}' failed with exit code {}: {}",
2311 reporter.GetMessages().ToStdString() ) );
2320 return tl::unexpected( validation.error() );
2322 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2323 return tl::unexpected( *busy );
2377 return tl::unexpected( validation.error() );
2379 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2380 return tl::unexpected( *busy );
2423 return tl::unexpected( validation.error() );
2425 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2426 return tl::unexpected( *busy );
2433 return tl::unexpected( *err );
2438 if( std::optional<ApiResponseStatus> paginationError =
2440 "RunBoardJobExportSvg" ) )
2442 return tl::unexpected( *paginationError );
2455 return tl::unexpected( validation.error() );
2457 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2458 return tl::unexpected( *busy );
2465 return tl::unexpected( *err );
2470 if( std::optional<ApiResponseStatus> unitError =
2473 return tl::unexpected( *unitError );
2478 if( std::optional<ApiResponseStatus> paginationError =
2480 "RunBoardJobExportDxf" ) )
2482 return tl::unexpected( *paginationError );
2495 return tl::unexpected( validation.error() );
2497 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2498 return tl::unexpected( *busy );
2505 return tl::unexpected( *err );
2523 return tl::unexpected( validation.error() );
2525 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2526 return tl::unexpected( *busy );
2533 return tl::unexpected( *err );
2535 if( std::optional<ApiResponseStatus> paginationError =
2537 "RunBoardJobExportPs" ) )
2539 return tl::unexpected( *paginationError );
2558 return tl::unexpected( validation.error() );
2560 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2561 return tl::unexpected( *busy );
2568 return tl::unexpected( *err );
2570 if( std::optional<ApiResponseStatus> paginationError =
2573 return tl::unexpected( *paginationError );
2584 ApiResponseStatus status;
2585 status.set_status( ApiStatusCode::AS_BAD_REQUEST );
2587 return tl::unexpected( status );
2605 return tl::unexpected( validation.error() );
2607 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2608 return tl::unexpected( *busy );
2619 return tl::unexpected( *err );
2628 switch( aCtx.
Request.precision() )
2631 case GerberPrecision::GP_5: job.
m_precision = 5;
break;
2632 case GerberPrecision::GP_6: job.
m_precision = 6;
break;
2643 return tl::unexpected( validation.error() );
2645 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2646 return tl::unexpected( *busy );
2654 if( std::optional<ApiResponseStatus> unitError =
2657 return tl::unexpected( *unitError );
2664 if( aCtx.
Request.has_excellon() )
2666 const ExcellonFormatOptions& excellonOptions = aCtx.
Request.excellon();
2668 if( excellonOptions.has_mirror_y() )
2671 if( excellonOptions.has_minimal_header() )
2674 if( excellonOptions.has_combine_pth_npth() )
2677 if( excellonOptions.has_route_oval_holes() )
2681 if( aCtx.
Request.map_format() != DrillMapFormat::DMF_UNKNOWN )
2689 if( aCtx.
Request.has_gerber_generate_tenting() )
2692 if( aCtx.
Request.report_format() != DrillReportFormat::DRF_UNKNOWN )
2696 if( aCtx.
Request.has_report_filename() )
2708 return tl::unexpected( validation.error() );
2710 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2711 return tl::unexpected( *busy );
2717 if( aCtx.
Request.has_use_drill_place_file_origin() )
2727 if( aCtx.
Request.has_include_board_edge_for_gerber() )
2734 if( std::optional<ApiResponseStatus> unitError =
2737 return tl::unexpected( *unitError );
2751 return tl::unexpected( validation.error() );
2753 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2754 return tl::unexpected( *busy );
2774 return tl::unexpected( validation.error() );
2776 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2777 return tl::unexpected( *busy );
2784 if( !aCtx.
Request.variant().empty() )
2789 if( aCtx.
Request.has_precision() )
2794 job.
m_colMfgPn = wxString::FromUTF8( aCtx.
Request.manufacturer_part_number_column() );
2795 job.
m_colMfg = wxString::FromUTF8( aCtx.
Request.manufacturer_column() );
2796 job.
m_colDistPn = wxString::FromUTF8( aCtx.
Request.distributor_part_number_column() );
2800 if( std::optional<ApiResponseStatus> unitError =
2803 return tl::unexpected( *unitError );
2820 return tl::unexpected( validation.error() );
2822 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2823 return tl::unexpected( *busy );
2836 aJob.
m_sections = aContent.sections().empty()
2838 : std::optional<wxString>( wxString::FromUTF8( aContent.sections() ) );
2845 aJob.
m_drawingSheet = wxString::FromUTF8( aRequest.drawing_sheet() );
2847 if( aRequest.variant_names_size() > 0 )
2849 for(
const std::string&
name : aRequest.variant_names() )
2852 else if( !aRequest.variant().empty() )
2854 aJob.
m_variantNames.push_back( wxString::FromUTF8( aRequest.variant() ) );
2858 aRequest.variant_packaging() );
2860 if( aRequest.has_precision() )
2866 aJob.
m_colMfgPn = wxString::FromUTF8( aRequest.manufacturer_part_number_column() );
2868 aJob.
m_productName = wxString::FromUTF8( aRequest.product_name() );
2877 return tl::unexpected( validation.error() );
2879 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2880 return tl::unexpected( *busy );
2886 if( std::optional<ApiResponseStatus> unitError =
2889 return tl::unexpected( *unitError );
2902 return tl::unexpected( validation.error() );
2904 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2905 return tl::unexpected( *busy );
2913 if( std::optional<ApiResponseStatus> unitError =
2916 return tl::unexpected( *unitError );
2933 return tl::unexpected( valid.error() );
2935 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2936 return tl::unexpected( *busy );
2938 switch( aCtx.
Request.units() )
2940 case types::Units::U_UNKNOWN:
2941 case types::Units::U_MM:
2942 case types::Units::U_MILS:
2947 ApiResponseStatus e;
2948 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2949 e.set_error_message(
"RunBoardJobExportIdf supports only mm and mils units" );
2950 return tl::unexpected( e );
2961 if( aCtx.
Request.origin_mode() == IdfOriginMode::IOM_USER )
2972 if( aCtx.
Request.has_part_number_field() )
2984 wxLogTrace(
traceApi,
"Received announce from frame %d at %s",
2990 CrossProbeAnnounceResponse response;
2991 response.set_status( CPS_OK );
2998 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"SyncSelection" ) )
2999 return tl::unexpected( *headless );
3001 SyncSelectionResponse response;
3005 if( !settings.
on_selection && aCtx.
Request.context() != SyncSelectionContext::SSC_EXPLICIT )
3007 response.set_status( CPS_DISABLED );
3008 response.set_message(
"implicit selection sync disabled by user" );
3012 std::vector<BOARD_ITEM*> items =
3017 if( aCtx.
Request.mode() == SyncSelectionMode::SSM_ITEMS_AND_NETS )
3029 wxLogTrace(
traceCrossProbeFlash,
"MAIL_SELECTION(_FORCE) PCB: flash enabled, items=%zu", items.size() );
3036 std::vector<BOARD_ITEM*> boardItems;
3037 std::copy( items.begin(), items.end(), std::back_inserter( boardItems ) );
3046 response.set_status( CPS_OK );
3054 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"HighlightNets" ) )
3055 return tl::unexpected( *headless );
3057 HighlightNetsResponse response;
3065 response.set_status( CPS_DISABLED );
3066 response.set_message(
"net highlight cross-probing disabled by user" );
3071 std::vector<wxString> nets;
3073 for(
const std::string&
name : aCtx.
Request.net_name() )
3074 nets.emplace_back( wxString::FromUTF8(
name ) );
3078 response.set_status( CPS_OK );
3086 return tl::unexpected( documentValidation.error() );
3088 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3089 return tl::unexpected( *busy );
3092 VariantsResponse response;
3096 for(
const wxString&
name :
board->GetVariantNames() )
3098 types::DesignVariant* var = response.add_variants();
3099 var->set_name(
name.ToUTF8() );
3100 var->set_description(
board->GetVariantDescription(
name ).ToUTF8() );
3110 return tl::unexpected( documentValidation.error() );
3112 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3113 return tl::unexpected( *busy );
3117 wxString
name = wxString::FromUTF8( aCtx.
Request.name() );
3121 ApiResponseStatus e;
3122 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3123 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.name() ) );
3124 return tl::unexpected( e );
3129 ApiResponseStatus e;
3130 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3131 e.set_error_message( fmt::format(
"a variant named '{}' already exists", aCtx.
Request.name() ) );
3132 return tl::unexpected( e );
3137 if( aCtx.
Request.has_description() )
3138 board->SetVariantDescription(
name, wxString::FromUTF8( aCtx.
Request.description() ) );
3152 return tl::unexpected( documentValidation.error() );
3154 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3155 return tl::unexpected( *busy );
3159 wxString
name = wxString::FromUTF8( aCtx.
Request.name() );
3163 ApiResponseStatus e;
3164 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3165 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.name() ) );
3166 return tl::unexpected( e );
3171 ApiResponseStatus e;
3172 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3173 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.name() ) );
3174 return tl::unexpected( e );
3191 return tl::unexpected( documentValidation.error() );
3193 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3194 return tl::unexpected( *busy );
3198 wxString oldName = wxString::FromUTF8( aCtx.
Request.old_name() );
3199 wxString newName = wxString::FromUTF8( aCtx.
Request.new_name() );
3203 ApiResponseStatus e;
3204 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3205 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.old_name() ) );
3206 return tl::unexpected( e );
3211 ApiResponseStatus e;
3212 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3213 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.new_name() ) );
3214 return tl::unexpected( e );
3217 if( !
board->HasVariant( oldName ) )
3219 ApiResponseStatus e;
3220 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3221 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.old_name() ) );
3222 return tl::unexpected( e );
3225 if(
board->HasVariant( newName ) )
3227 ApiResponseStatus e;
3228 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3229 e.set_error_message( fmt::format(
"a variant named '{}' already exists", aCtx.
Request.new_name() ) );
3230 return tl::unexpected( e );
3233 board->RenameVariant( oldName, newName );
3247 return tl::unexpected( documentValidation.error() );
3249 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3250 return tl::unexpected( *busy );
3254 wxString oldName = wxString::FromUTF8( aCtx.
Request.old_name() );
3255 wxString newName = wxString::FromUTF8( aCtx.
Request.new_name() );
3259 ApiResponseStatus e;
3260 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3261 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.old_name() ) );
3262 return tl::unexpected( e );
3267 ApiResponseStatus e;
3268 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3269 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.new_name() ) );
3270 return tl::unexpected( e );
3273 if( !
board->HasVariant( oldName ) )
3275 ApiResponseStatus e;
3276 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3277 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.old_name() ) );
3278 return tl::unexpected( e );
3281 if(
board->HasVariant( newName ) )
3283 ApiResponseStatus e;
3284 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3285 e.set_error_message( fmt::format(
"a variant named '{}' already exists", aCtx.
Request.new_name() ) );
3286 return tl::unexpected( e );
3289 board->CopyVariant( oldName, newName,
3290 aCtx.
Request.has_new_description() ? wxString::FromUTF8( aCtx.
Request.new_description() )
3305 return tl::unexpected( documentValidation.error() );
3307 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3308 return tl::unexpected( *busy );
3312 wxString
name = wxString::FromUTF8( aCtx.
Request.name() );
3316 ApiResponseStatus e;
3317 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3318 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.name() ) );
3319 return tl::unexpected( e );
3322 board->SetVariantDescription(
name, wxString::FromUTF8( aCtx.
Request.description() ) );
3333 return tl::unexpected( documentValidation.error() );
3335 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3336 return tl::unexpected( *busy );
3344 ApiResponseStatus e;
3345 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3346 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.name() ) );
3347 return tl::unexpected( e );
3351 wxString varName = aCtx.
Request.has_name() ? wxString::FromUTF8( aCtx.
Request.name() ) : wxString();
3356 board->SetCurrentVariant( varName );
3366 return tl::unexpected( documentValidation.error() );
3368 CurrentVariantResponse response;
3370 if( wxString current =
pcbContext()->GetBoard()->GetCurrentVariant(); !current.IsEmpty() )
3371 response.set_name( current.ToUTF8() );
3382 ApiResponseStatus e;
3383 e.set_status( ApiStatusCode::AS_UNHANDLED );
3384 return tl::unexpected( e );
3387 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3388 return tl::unexpected( *busy );
3394 ApiResponseStatus e;
3395 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3396 e.set_error_message(
"lib_id must specify both a library nickname and an entry name" );
3397 return tl::unexpected( e );
3405 ApiResponseStatus e;
3406 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3407 e.set_error_message(
"layer must be F_Cu or B_Cu" );
3408 return tl::unexpected( e );
3415 ApiResponseStatus e;
3416 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3417 e.set_error_message( fmt::format(
"footprint '{}' not found", libId.
Format().
wx_str() ) );
3418 return tl::unexpected( e );
3421 footprint->SetUuid(
KIID() );
3422 footprint->RunOnChildren(
3429 footprint->SetParent(
board() );
3433 if( aCtx.
Request.has_orientation() )
3434 footprint->SetOrientationDegrees( aCtx.
Request.orientation().value_degrees() );
3436 footprint->SetLayerAndFlip( layer );
3439 FOOTPRINT* placed = footprint.release();
3440 commit->
Add( placed );
3445 PlaceFromLibraryResponse response;
3446 response.mutable_header()->CopyFrom( aCtx.
Request.header() );
3447 placed->
Serialize( *response.mutable_item() );
KICOMMON_API types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICOMMON_API 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)
HANDLER_RESULT< Empty > unpackEmbeddedFiles(EMBEDDED_FILES &aOutput, const common::types::EmbeddedFiles &aProto)
void ApplyOdbJobRequest(const RunBoardJobExportODB &aRequest, JOB_EXPORT_PCB_ODB &aJob)
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(PCB_CONTEXT *aContext, JOB &aJob)
void ApplyFabExportContent(const FabExportContent &aContent, JOB_EXPORT_PCB_FAB &aJob)
static const std::vector< KICAD_T > s_allowedBoardTypes
void ApplyOdbJobRequest(const kiapi::board::jobs::RunBoardJobExportODB &aRequest, JOB_EXPORT_PCB_ODB &aJob)
void ApplyFabExportContent(const kiapi::board::jobs::FabExportContent &aContent, JOB_EXPORT_PCB_FAB &aJob)
BASE_SCREEN class implementation.
constexpr EDA_IU_SCALE pcbIUScale
static TOOL_ACTION selectionClear
Clear the current selection.
static TOOL_ACTION gridSetOrigin
API_HANDLER_BOARD(std::shared_ptr< BOARD_CONTEXT > aContext, EDA_BASE_FRAME *aFrame=nullptr)
std::unique_ptr< COMMIT > createCommit() override
Override this to create an appropriate COMMIT subclass for the frame in question.
TOOL_MANAGER * toolManager() const
std::vector< KICAD_T > parseRequestedItemTypes(const google::protobuf::RepeatedField< int > &aTypes)
PROJECT & project() const
void pushCurrentCommit(const std::string &aClientName, const wxString &aMessage) override
BOARD_CONTEXT * context() const
std::optional< ApiResponseStatus > checkForHeadless(const std::string &aCommandName) const
std::optional< BOARD_ITEM * > getItemById(const KIID &aId) const
HANDLER_RESULT< bool > validateDocument(const DocumentSpecifier &aDocument)
HANDLER_RESULT< types::PageSettings > handleSetPageSettings(const HANDLER_CONTEXT< commands::SetPageSettings > &aCtx)
HANDLER_RESULT< std::optional< KIID > > validateItemHeaderDocument(const kiapi::common::types::ItemHeader &aHeader)
If the header is valid, returns the item container.
HANDLER_RESULT< types::PageSettings > handleGetPageSettings(const HANDLER_CONTEXT< commands::GetPageSettings > &aCtx)
COMMIT * getCurrentCommit(const std::string &aClientName)
std::set< std::string > m_activeClients
std::map< std::string, std::pair< KIID, std::unique_ptr< COMMIT > > > m_commits
virtual std::optional< ApiResponseStatus > checkForBusy()
Checks if the editor can accept commands.
HANDLER_RESULT< ImportNetlistResponse > handleImportNetlist(const HANDLER_CONTEXT< ImportNetlist > &aCtx)
HANDLER_RESULT< BoardPlotSettingsResponse > handleGetBoardPlotSettings(const HANDLER_CONTEXT< GetBoardPlotSettings > &aCtx)
HANDLER_RESULT< Empty > handleDeleteVariant(const HANDLER_CONTEXT< commands::DeleteVariant > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportPdf(const HANDLER_CONTEXT< RunBoardJobExportPdf > &aCtx)
HANDLER_RESULT< google::protobuf::Empty > handleSetEmbeddedFiles(const HANDLER_CONTEXT< SetEmbeddedFiles > &aCtx)
HANDLER_RESULT< commands::CurrentVariantResponse > handleGetCurrentVariant(const HANDLER_CONTEXT< commands::GetCurrentVariant > &aCtx)
HANDLER_RESULT< BoardDesignRulesResponse > handleSetBoardDesignRules(const HANDLER_CONTEXT< SetBoardDesignRules > &aCtx)
API_HANDLER_PCB(PCB_EDIT_FRAME *aFrame)
HANDLER_RESULT< Empty > handleAddVariant(const HANDLER_CONTEXT< commands::AddVariant > &aCtx)
HANDLER_RESULT< commands::GetItemsResponse > handleGetConnectedItems(const HANDLER_CONTEXT< GetConnectedItems > &aCtx)
HANDLER_RESULT< commands::VariantsResponse > handleGetVariants(const HANDLER_CONTEXT< commands::GetVariants > &aCtx)
HANDLER_RESULT< types::Vector2 > handleGetBoardOrigin(const HANDLER_CONTEXT< GetBoardOrigin > &aCtx)
HANDLER_RESULT< commands::GetItemsResponse > handleGetItemsByNetClass(const HANDLER_CONTEXT< GetItemsByNetClass > &aCtx)
HANDLER_RESULT< Empty > handleSaveDocumentAs(const HANDLER_CONTEXT< commands::SaveDocumentAs > &aCtx)
HANDLER_RESULT< NetClassForNetsResponse > handleGetNetClassForNets(const HANDLER_CONTEXT< GetNetClassForNets > &aCtx)
HANDLER_RESULT< commands::CrossProbeAnnounceResponse > handleCrossProbeAnnounce(const HANDLER_CONTEXT< commands::CrossProbeAnnounce > &aCtx)
HANDLER_RESULT< Empty > handleCopyVariant(const HANDLER_CONTEXT< commands::CopyVariant > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportIpcD356(const HANDLER_CONTEXT< RunBoardJobExportIpcD356 > &aCtx)
PCB_CONTEXT * pcbContext() const
HANDLER_RESULT< BoardDesignRulesResponse > handleGetBoardDesignRules(const HANDLER_CONTEXT< GetBoardDesignRules > &aCtx)
HANDLER_RESULT< commands::GetDocumentModifiedStateResponse > handleGetDocumentModifiedState(const HANDLER_CONTEXT< commands::GetDocumentModifiedState > &aCtx) override
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< types::RunJobResponse > handleRunBoardJobExport3D(const HANDLER_CONTEXT< RunBoardJobExport3D > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportPng(const HANDLER_CONTEXT< RunBoardJobExportPng > &aCtx)
HANDLER_RESULT< Empty > handleSetCurrentVariant(const HANDLER_CONTEXT< commands::SetCurrentVariant > &aCtx)
void setDrawingSheetFileName(const wxString &aFileName) override
HANDLER_RESULT< commands::GetItemsResponse > handleGetItemsByNet(const HANDLER_CONTEXT< GetItemsByNet > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportIpc2581(const HANDLER_CONTEXT< RunBoardJobExportIpc2581 > &aCtx)
std::optional< TITLE_BLOCK * > getTitleBlock(const DocumentSpecifier &aDocument) override
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportPosition(const HANDLER_CONTEXT< RunBoardJobExportPosition > &aCtx)
HANDLER_RESULT< Empty > handleSetBoardOrigin(const HANDLER_CONTEXT< SetBoardOrigin > &aCtx)
HANDLER_RESULT< Empty > handleSetBoardPlotSettings(const HANDLER_CONTEXT< SetBoardPlotSettings > &aCtx)
HANDLER_RESULT< BoardLayerNameResponse > handleGetBoardLayerName(const HANDLER_CONTEXT< GetBoardLayerName > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportStats(const HANDLER_CONTEXT< RunBoardJobExportStats > &aCtx)
void onModified() override
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportPs(const HANDLER_CONTEXT< RunBoardJobExportPs > &aCtx)
HANDLER_RESULT< CustomRulesResponse > handleGetCustomDesignRules(const HANDLER_CONTEXT< GetCustomDesignRules > &aCtx)
bool setPageSettings(const DocumentSpecifier &aDocument, const PAGE_INFO &aPageInfo) override
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportSvg(const HANDLER_CONTEXT< RunBoardJobExportSvg > &aCtx)
kiapi::common::types::DocumentType thisDocumentType() const override
Override this to specify which document type this editor handles.
HANDLER_RESULT< commands::GetOpenDocumentsResponse > handleGetOpenDocuments(const HANDLER_CONTEXT< commands::GetOpenDocuments > &aCtx)
HANDLER_RESULT< commands::SyncSelectionResponse > handleSyncSelection(const HANDLER_CONTEXT< commands::SyncSelection > &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< Empty > handleSetVariantDescription(const HANDLER_CONTEXT< commands::SetVariantDescription > &aCtx)
HANDLER_RESULT< Empty > handleSaveDocument(const HANDLER_CONTEXT< commands::SaveDocument > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportDrill(const HANDLER_CONTEXT< RunBoardJobExportDrill > &aCtx)
HANDLER_RESULT< commands::GetItemsResponse > handleGetItems(const HANDLER_CONTEXT< commands::GetItems > &aCtx)
HANDLER_RESULT< kiapi::common::commands::PlaceFromLibraryResponse > handlePlaceFootprintFromLibrary(const HANDLER_CONTEXT< kiapi::board::commands::PlaceFootprintFromLibrary > &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 > handleRenameVariant(const HANDLER_CONTEXT< commands::RenameVariant > &aCtx)
std::optional< PAGE_INFO > getPageSettings(const DocumentSpecifier &aDocument) override
HANDLER_RESULT< Empty > handleSetBoardEditorAppearanceSettings(const HANDLER_CONTEXT< SetBoardEditorAppearanceSettings > &aCtx)
tl::expected< bool, ApiResponseStatus > validateDocumentInternal(const DocumentSpecifier &aDocument) const override
HANDLER_RESULT< Empty > handleRefillZones(const HANDLER_CONTEXT< RefillZones > &aCtx)
HANDLER_RESULT< commands::HighlightNetsResponse > handleHighlightNets(const HANDLER_CONTEXT< commands::HighlightNets > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunBoardJobExportIdf(const HANDLER_CONTEXT< RunBoardJobExportIdf > &aCtx)
HANDLER_RESULT< google::protobuf::Empty > handleAddEmbeddedFiles(const HANDLER_CONTEXT< AddEmbeddedFiles > &aCtx)
HANDLER_RESULT< common::types::EmbeddedFiles > handleGetEmbeddedFiles(const HANDLER_CONTEXT< GetEmbeddedFiles > &aCtx)
HANDLER_RESULT< BoardLayerResponse > handleGetBoardLayerByName(const HANDLER_CONTEXT< GetBoardLayerByName > &aCtx)
HANDLER_RESULT< Empty > handleRevertDocument(const HANDLER_CONTEXT< commands::RevertDocument > &aCtx)
HANDLER_RESULT< CustomRulesResponse > handleSetCustomDesignRules(const HANDLER_CONTEXT< SetCustomDesignRules > &aCtx)
void onNetSettingsChanged() override
Called on all registered handlers after project net settings (netclasses or netclass assignments) hav...
wxString getDrawingSheetFileName() override
KICAD_API_SERVER * apiServer() const
void registerHandler(HANDLER_RESULT< ResponseType >(HandlerType::*aHandler)(const HANDLER_CONTEXT< RequestType > &))
Registers an API command handler for the given message types.
CROSS_PROBING_SETTINGS m_CrossProbing
static wxString m_DrawingSheetFileName
the name of the drawing sheet file, or empty to use the default drawing sheet
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual KIWAY * GetKiway() const =0
virtual BOARD * GetBoard() const =0
Container for design settings for a BOARD object.
int m_CopperEdgeClearance
std::map< int, SEVERITY > m_DRCSeverities
void SetGridOrigin(const VECTOR2I &aOrigin)
int m_MinSilkTextThickness
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
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).
void SetAuxOrigin(const VECTOR2I &aOrigin)
const VECTOR2I & GetAuxOrigin() const
int m_SolderMaskExpansion
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.
double m_SolderPasteMarginRatio
std::vector< VIA_DIMENSION > m_ViasDimensionsList
int m_ViasMinAnnularWidth
std::set< DRC_EXCLUSION, DRC_EXCLUSION_COMPARE > m_DrcExclusions
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)
Information pertinent to a Pcbnew printed circuit board.
void SetPlotOptions(const PCB_PLOT_PARAMS &aOptions)
EMBEDDED_FILES * GetEmbeddedFiles() override
const PAGE_INFO & GetPageSettings() const
void SetDesignSettings(const BOARD_DESIGN_SETTINGS &aSettings)
TITLE_BLOCK & GetTitleBlock()
PCB_LAYER_ID GetLayerID(const wxString &aLayerName) const
Return the ID of a layer.
void SetPageSettings(const PAGE_INFO &aPageSettings)
const wxString & GetFileName() const
const PCB_PLOT_PARAMS & GetPlotOptions() const
wxString GetDesignRulesPath() const
Return the absolute path to the design rules file for this board.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Represent a set of changes (additions, deletions or modifications) of a data model (e....
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
static void RegisterPeer(FRAME_T aFrameType, const std::string &aSocketPath)
void ToProto(kiapi::board::CustomRuleConstraint &aProto) const
Container for an DRC exclusion, which is a PCB_MARKER plus an optional comment.
static DRC_EXCLUSION FromProto(const kiapi::board::DrcExclusion &aMessage)
const kiapi::board::DrcExclusion & ToProto() 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)
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
EMBEDDED_FILE * AddFile(const wxFileName &aName, bool aOverwrite)
Load a file from disk and adds it to the collection.
const std::map< wxString, std::shared_ptr< EMBEDDED_FILE > > & EmbeddedFileMap() const
Provide an iterable view of the file collection.
static const TOOL_EVENT SelectedItemsModified
Selected item had a property changed (except movement)
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
std::optional< wxString > m_sections
Section key that replaces the optional sections of the data set Unset lets the data set select them a...
std::vector< wxString > m_variantNames
bool m_checkZonesBeforeExport
bool m_useIndividualShapes
bool m_useBoardPlotParams
bool m_useProtelFileExtension
bool m_includeNetlistAttributes
bool m_disableApertureMacros
IDF_SETTINGS::COORD_ORIGIN m_originMode
bool m_calculateHeightFromModels
VECTOR2D m_userOrigin
In whatever units the user specified in m_units.
wxString m_partNumberField
IDF_SETTINGS::UNITS m_units
bool m_includeUnspecified
IPC2581_VERSION m_version
VARIANT_PACKAGING m_variantPackaging
ODB_COMPRESSION m_compressionMode
bool m_pdfFrontFPPropertyPopups
wxString m_pdfBackgroundColor
The background color specified in a hex string.
bool m_pdfBackFPPropertyPopups
GEN_MODE m_pdfGenMode
uused by the cli, will be removed when the other behavior is deprecated
bool m_sketchDNPFPsOnFabLayers
bool m_useDrillOrigin
Used by SVG/DXF/PDF/Gerbers.
bool m_plotFootprintValues
LSEQ m_plotOnAllLayersSequence
Layers to include on all individual layer prints.
bool m_checkZonesBeforePlot
bool m_sketchPadsOnFabLayers
DRILL_MARKS m_drillShapeOption
Used by SVG & PDF.
bool m_crossoutDNPFPsOnFabLayers
bool m_hideDNPFPsOnFabLayers
bool m_mirror
Common Options.
bool m_subtractSolderMaskFromSilk
bool m_useBackgroundColor
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 UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
std::string AsStdString() const
int ProcessJob(KIWAY::FACE_T aFace, JOB *aJob, REPORTER *aReporter=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr)
A logical library item identifier and consists of various portions much like a URI.
bool IsValid() const
Check if this LID_ID is valid.
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.
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
Store information read from a netlist along with the flags used to update the NETLIST in the BOARD.
Describe the page size and margins of a paper page on which to eventually print or plot.
DISPLAY_OPTIONS m_Display
static TOOL_ACTION zoneFillAll
static TOOL_ACTION syncSelection
Sets selection to specified items, zooms to fit, if enabled.
static TOOL_ACTION drillSetOrigin
static TOOL_ACTION syncSelectionWithNets
Sets selection to specified items with connected nets, zooms to fit, if enabled.
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.
void SetDisplayOptions(const PCB_DISPLAY_OPTIONS &aOptions, bool aRefresh=true)
Update the current display options.
virtual void Update3DView(bool aMarkDirty, bool aRefresh, const wxString *aTitle=nullptr)
Update the 3D view, if the viewer is opened by this frame.
PCB-editor-specific context; extends BOARD_CONTEXT with save/filename operations.
virtual wxString GetCurrentFileName() const =0
virtual void OnNetlistChanged(BOARD_NETLIST_UPDATER &aUpdater)=0
Post-import board sync (nets, classes, DRC, ratsnest, new footprint placement).
virtual bool ReadNetlistFromFile(const wxString &aFilename, NETLIST &aNetlist, REPORTER &aReporter)=0
Read a netlist file and preload component footprints.
virtual void SetContentModified(bool aModified=true)=0
virtual std::unique_ptr< BOARD_NETLIST_UPDATER > MakeNetlistUpdater()=0
Create a netlist updater bound to this context's board.
bool m_FlipBoardView
true if the board is flipped to show the mirrored view
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 KIGFX::VIEW instance used in the panel.
The main frame for Pcbnew.
void LoadDrawingSheet()
Load the drawing sheet file.
void OnModify() override
Must be called after a board change to set the modified flag.
void StartCrossProbeFlash(const std::vector< BOARD_ITEM * > &aItems)
void UpdateVariantSelectionCtrl()
Update the variant selection dropdown with the current board's variant names.
void SetCurrentVariant(const wxString &aVariantName)
Set the current variant on the board and update the drawing sheet's cached variant name and descripti...
void UpdateUserInterface()
Update the layer manager and other widgets from the board setup (layer and items visibility,...
void HandleRemoteNetHighlight(const std::vector< wxString > &aNetNames)
const KIID GetUUID() const override
Parameters and options when plotting/printing a board.
void SetDrillMarksType(DRILL_MARKS aVal)
bool GetUseAuxOrigin() const
LSEQ GetPlotOnAllLayersSequence() const
bool GetHideDNPFPsOnFabLayers() const
void SetLayerSelection(const LSET &aSelection)
void SetPlotReference(bool aFlag)
void SetSketchPadsOnFabLayers(bool aFlag)
bool GetCrossoutDNPFPsOnFabLayers() const
bool GetSketchDNPFPsOnFabLayers() const
void SetPlotOnAllLayersSequence(LSEQ aSeq)
void SetPlotFrameRef(bool aFlag)
void SetSketchDNPFPsOnFabLayers(bool aFlag)
void SetPlotPadNumbers(bool aFlag)
LSET GetLayerSelection() const
bool GetPlotReference() const
void SetScale(double aVal)
void SetMirror(bool aFlag)
void SetBlackAndWhite(bool blackAndWhite)
void SetSubtractMaskFromSilk(bool aSubtract)
bool GetSketchPadsOnFabLayers() const
void SetHideDNPFPsOnFabLayers(bool aFlag)
bool GetSubtractMaskFromSilk() const
void SetPlotValue(bool aFlag)
bool GetPlotPadNumbers() const
DRILL_MARKS GetDrillMarksType() const
bool GetPlotValue() const
void SetNegative(bool aFlag)
bool GetBlackAndWhite() const
void SetUseAuxOrigin(bool aAux)
bool GetPlotFrameRef() const
void SetCrossoutDNPFPsOnFabLayers(bool aFlag)
std::vector< KIID > KIIDS
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.
A wrapper for reporting to a wxString object.
bool Fill(const std::vector< ZONE * > &aZones, bool aCheck=false, wxWindow *aParent=nullptr)
Fills the given list of zones.
Handle a list of polygons defining a copper zone.
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
static std::string ToStdString(const wxString &aStr)
FRAME_T
The set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
static const std::string KiCadPcbFileExtension
const wxChar *const traceCrossProbeFlash
Flag to enable debug output for cross-probe flash operations.
const wxChar *const traceApi
Flag to enable debug output related to the IPC API and its plugin system.
bool IsPcbLayer(int aLayer)
Test whether a layer is a valid layer for Pcbnew.
@ LAYER_DRC_WARNING
Layer for DRC markers with RPT_SEVERITY_WARNING.
@ LAYER_DRC_ERROR
Layer for DRC markers with RPT_SEVERITY_ERROR.
bool IsExternalCopperLayer(int aLayerId)
Test whether a layer is an external (F_Cu or B_Cu) copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
void PackLayerSet(google::protobuf::RepeatedField< int > &aOutput, const LSET &aLayerSet)
void PackEmbeddedFiles(common::types::EmbeddedFiles &aOutput, const EMBEDDED_FILES &aFiles)
bool UnpackEmbeddedFiles(EMBEDDED_FILES &aOutput, const common::types::EmbeddedFiles &aProto)
LSET UnpackLayerSet(const google::protobuf::RepeatedField< int > &aProtoLayerSet)
std::vector< BOARD_ITEM * > FindItemsFromSyncSelection(const BOARD *aBoard, const google::protobuf::RepeatedPtrField< kiapi::common::commands::SelectionSpec > &aItems)
Resolve a cross-probe selection request against a board.
KICOMMON_API VECTOR3D UnpackVector3D(const types::Vector3D &aInput)
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API LIB_ID UnpackLibId(const types::LibraryIdentifier &aId)
const KICOMMON_API std::string KiwayClientName
const KICOMMON_API std::string StandaloneCrossProbeClientName
std::shared_ptr< PCB_CONTEXT > CreatePcbFrameContext(PCB_EDIT_FRAME *aFrame)
Class to handle a set of BOARD_ITEMs.
FOOTPRINT * LoadFootprintFromProject(BOARD *aBoard, const LIB_ID &aFootprintId, bool aKeepUuid)
Load a footprint from the project library table and apply board default settings.
PGM_BASE & Pgm()
The global program "get" accessor.
constexpr int MIN_PNG_DPI
constexpr int MAX_PNG_DPI
#define SKIP_CONNECTIVITY
wxString GetDefaultVariantName()
bool flash_selection
Flash newly cross-probed selection (visual attention aid).
bool on_selection
Synchronize the selection for multiple items too.
bool auto_highlight
Automatically turn on highlight mode in the target frame.
RequestMessageType Request
RATSNEST_MODE m_RatsnestMode
IbisParser parser & reporter
wxString result
Test unit parsing edge cases and error handling.
wxLogTrace helper definitions.
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
@ PCB_CONSTRAINT_T
a geometric constraint between board items
@ 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_GENERATOR_T
class PCB_GENERATOR, generator on a layer
@ 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_GRID_ITEM_T
a subgrid placed on a board
@ 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_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
@ PCB_POINT_T
class PCB_POINT, a 0-dimensional point
@ 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