21#include <magic_enum.hpp>
34#include <api/common/commands/library_commands.pb.h>
98#include <api/common/types/base_types.pb.h>
102#include <api/board/board_rules.pb.h>
104#include <google/protobuf/util/json_util.h>
113using namespace kiapi::common::commands;
114using namespace kiapi::board::commands;
115using types::CommandStatus;
116using types::DocumentType;
117using types::ItemRequestStatus;
237 if( aCtx.
Request.type() != DocumentType::DOCTYPE_PCB )
241 e.set_status( ApiStatusCode::AS_UNHANDLED );
242 return tl::unexpected( e );
245 GetOpenDocumentsResponse response;
246 common::types::DocumentSpecifier doc;
248 wxFileName fn(
pcbContext()->GetCurrentFileName() );
250 doc.set_type( DocumentType::DOCTYPE_PCB );
251 doc.set_board_filename( fn.GetFullName() );
256 response.mutable_documents()->Add( std::move( doc ) );
265 return tl::unexpected( documentValidation.error() );
267 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
268 return tl::unexpected( *busy );
270 if(
board()->GetFileName().IsEmpty() )
273 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
274 e.set_error_message(
"the board is untitled; use SaveDocumentAs to save it to a new file" );
275 return tl::unexpected( e );
281 e.set_status( ApiStatusCode::AS_INTERNAL_ERROR );
282 e.set_error_message(
"board could not be saved" );
283 return tl::unexpected( e );
295 e.set_status( ApiStatusCode::AS_UNIMPLEMENTED );
296 e.set_error_message(
"SaveDocumentAs is not available in GUI mode" );
297 return tl::unexpected( e );
301 return tl::unexpected( documentValidation.error() );
303 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
304 return tl::unexpected( *busy );
306 wxString pathStr = wxString::FromUTF8( aCtx.
Request.path() );
308 if( pathStr.IsEmpty() )
311 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
312 e.set_error_message(
"path is required" );
313 return tl::unexpected( e );
316 wxFileName oldBoardFile(
pcbContext()->GetCurrentFileName() );
321 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
322 e.set_error_message( fmt::format(
"failed to save board to '{}'", pathStr.ToStdString() ) );
323 return tl::unexpected( e );
328 wxFileName newBoardFile( pathStr );
331 server->NotifyDocumentRenamed(
thisDocumentType(), oldBoardFile.GetFullPath(), newBoardFile.GetFullPath() );
342 return tl::unexpected( documentValidation.error() );
344 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
345 return tl::unexpected( *busy );
347 wxFileName boardPath(
project().AbsolutePath( wxString::FromUTF8( aCtx.
Request.path() ) ) );
349 if( !boardPath.IsOk() || !boardPath.IsDirWritable() )
352 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
353 e.set_error_message( fmt::format(
"save path '{}' could not be opened",
354 boardPath.GetFullPath().ToStdString() ) );
355 return tl::unexpected( e );
358 if( boardPath.FileExists()
359 && ( !boardPath.IsFileWritable() || !aCtx.
Request.options().overwrite() ) )
362 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
363 e.set_error_message( fmt::format(
"save path '{}' exists and cannot be overwritten",
364 boardPath.GetFullPath().ToStdString() ) );
365 return tl::unexpected( e );
371 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
372 e.set_error_message( fmt::format(
"save path '{}' must have a kicad_pcb extension",
373 boardPath.GetFullPath().ToStdString() ) );
374 return tl::unexpected( e );
379 if( board->
GetFileName().Matches( boardPath.GetFullPath() ) )
384 e.set_status( ApiStatusCode::AS_INTERNAL_ERROR );
385 e.set_error_message(
"board could not be saved" );
386 return tl::unexpected( e );
392 bool includeProject =
true;
394 if( aCtx.
Request.has_options() )
395 includeProject = aCtx.
Request.options().include_project();
397 if( !
pcbContext()->SavePcbCopy( boardPath.GetFullPath(), includeProject,
true ) )
400 e.set_status( ApiStatusCode::AS_INTERNAL_ERROR );
401 e.set_error_message( fmt::format(
"board could not be saved to '{}'",
402 boardPath.GetFullPath().ToStdString() ) );
403 return tl::unexpected( e );
415 return tl::unexpected( documentValidation.error() );
422 e.set_status( ApiStatusCode::AS_BUSY );
423 e.set_error_message(
"cannot revert while a commit is open" );
424 return tl::unexpected( e );
427 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
428 return tl::unexpected( *busy );
433 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
434 e.set_error_message(
"could not revert: there is no saved file on disk to revert to" );
435 return tl::unexpected( e );
444 if( aDocument.type() != DocumentType::DOCTYPE_PCB )
447 e.set_status( ApiStatusCode::AS_UNHANDLED );
448 return tl::unexpected( e );
451 wxFileName fn(
pcbContext()->GetCurrentFileName() );
453 if( aDocument.board_filename().compare( fn.GetFullName() ) != 0 )
456 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
457 e.set_error_message( fmt::format(
"the requested document {} is not open",
458 aDocument.board_filename() ) );
459 return tl::unexpected( e );
496 e.set_status( ApiStatusCode::AS_UNHANDLED );
497 return tl::unexpected( e );
500 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
501 return tl::unexpected( *busy );
503 GetItemsResponse response;
506 std::vector<BOARD_ITEM*> items;
507 std::set<KICAD_T> typesRequested, typesHandled;
511 if( aCtx.
Request.types().empty() )
514 for(
KICAD_T type : requestedTypes )
516 typesRequested.emplace( type );
518 if( typesHandled.count( type ) )
526 std::ranges::copy(
board->Tracks(), std::back_inserter( items ) );
532 std::ranges::copy( fp->Pads(), std::back_inserter( items ) );
538 std::ranges::copy(
board->Footprints(), std::back_inserter( items ) );
552 if( item->Type() == type ||
BaseType( item->Type() ) == type )
553 items.emplace_back( item );
556 typesHandled.insert( type );
560 std::ranges::copy(
board->Zones(), std::back_inserter( items ) );
565 std::ranges::copy(
board->Groups(), std::back_inserter( items ) );
570 std::ranges::copy(
board->Points(), std::back_inserter( items ) );
579 std::ranges::copy(
board->Generators(), std::back_inserter( items ) );
584 std::ranges::copy(
board->Constraints(), std::back_inserter( items ) );
593 if( typesHandled.empty() )
596 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
597 e.set_error_message(
"none of the requested types are valid for a Board object" );
598 return tl::unexpected( e );
603 if( !typesRequested.count( item->Type() ) && !typesRequested.count(
BaseType( item->Type() ) ) )
606 google::protobuf::Any itemBuf;
607 item->Serialize( itemBuf );
608 response.mutable_items()->Add( std::move( itemBuf ) );
611 response.set_status( ItemRequestStatus::IRS_OK );
620 return tl::unexpected( documentValidation.error() );
622 if( aCtx.
Request.copper_layer_count() < 2 || aCtx.
Request.copper_layer_count() % 2 != 0 )
625 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
626 e.set_error_message(
"copper_layer_count must be an even number of at least 2" );
627 return tl::unexpected( e );
633 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
634 e.set_error_message( fmt::format(
"copper_layer_count must be below %d",
MAX_CU_LAYERS ) );
635 return tl::unexpected( e );
638 int copperLayerCount =
static_cast<int>( aCtx.
Request.copper_layer_count() );
643 enabled &=
~LSET::AllCuMask();
648 LSET previousEnabled =
board->GetEnabledLayers();
649 LSET changedLayers = enabled ^ previousEnabled;
651 board->SetEnabledLayers( enabled );
652 board->SetVisibleLayers(
board->GetVisibleLayers() | changedLayers );
658 if( !enabled[layer_id] &&
board->HasItemsOnLayer( layer_id ) )
659 removedLayers.push_back( layer_id );
662 bool modified =
false;
664 if( !removedLayers.empty() )
669 modified |=
board->RemoveAllItemsOnLayer( layer_id );
672 if( enabled != previousEnabled || modified )
675 BoardEnabledLayersResponse response;
677 response.set_copper_layer_count( copperLayerCount );
688 return tl::unexpected( documentValidation.error() );
690 common::types::EmbeddedFiles response;
701 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
702 e.set_error_message(
"embedded file validation failed" );
703 return tl::unexpected( e );
713 return tl::unexpected( documentValidation.error() );
715 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
716 return tl::unexpected( *busy );
726 for(
const std::shared_ptr<EMBEDDED_FILES::EMBEDDED_FILE>& file : files.
EmbeddedFileMap() | std::views::values )
728 auto copy = std::make_shared<EMBEDDED_FILES::EMBEDDED_FILE>( *file );
740 return tl::unexpected( documentValidation.error() );
742 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
743 return tl::unexpected( *busy );
761 if( !documentValidation )
762 return tl::unexpected( documentValidation.error() );
765 BoardDesignRulesResponse response;
766 kiapi::board::BoardDesignRules* rules = response.mutable_rules();
768 kiapi::board::MinimumConstraints* constraints = rules->mutable_constraints();
770 constraints->mutable_min_clearance()->set_value_nm( bds.
m_MinClearance );
771 constraints->mutable_min_groove_width()->set_value_nm( bds.
m_MinGrooveWidth );
772 constraints->mutable_min_connection_width()->set_value_nm( bds.
m_MinConn );
773 constraints->mutable_min_track_width()->set_value_nm( bds.
m_TrackMinWidth );
775 constraints->mutable_min_via_size()->set_value_nm( bds.
m_ViasMinSize );
780 constraints->mutable_hole_clearance()->set_value_nm( bds.
m_HoleClearance );
781 constraints->mutable_hole_to_hole_min()->set_value_nm( bds.
m_HoleToHoleMin );
782 constraints->mutable_silk_clearance()->set_value_nm( bds.
m_SilkClearance );
787 kiapi::board::PredefinedSizes* sizes = rules->mutable_predefined_sizes();
790 sizes->add_tracks()->mutable_width()->set_value_nm( bds.
m_TrackWidthList[ii] );
794 kiapi::board::PresetViaDimension*
via = sizes->add_vias();
801 kiapi::board::PresetDiffPairDimension* pair = sizes->add_diff_pairs();
807 kiapi::board::SolderMaskPasteDefaults* maskPaste = rules->mutable_solder_mask_paste();
816 kiapi::board::TeardropDefaults* teardrops = rules->mutable_teardrops();
829 kiapi::board::TeardropTargetEntry* entry = teardrops->add_target_params();
833 entry->mutable_params()->set_enabled( params->
m_Enabled );
834 entry->mutable_params()->mutable_max_length()->set_value_nm( params->
m_TdMaxLen );
835 entry->mutable_params()->mutable_max_width()->set_value_nm( params->
m_TdMaxWidth );
839 entry->mutable_params()->set_curved_edges( params->
m_CurvedEdges );
844 kiapi::board::ViaProtectionDefaults* viaProtection = rules->mutable_via_protection();
857 board::DrcSeveritySetting* setting = rules->add_severities();
858 setting->set_rule_type(
864 rules->add_exclusions()->CopyFrom( exclusion.
ToProto() );
866 response.set_custom_rules_status( CRS_NONE );
870 if( !rulesPath.IsEmpty() && wxFileName::IsFileReadable( rulesPath ) )
872 wxFFile file( rulesPath,
"r" );
874 std::vector<std::shared_ptr<DRC_RULE>> parsedRules;
876 if( !file.IsOpened() )
878 response.set_custom_rules_status( CRS_INVALID );
882 file.ReadAll( &content );
888 parser.
Parse( parsedRules,
nullptr );
889 response.set_custom_rules_status( CRS_VALID );
893 response.set_custom_rules_status( CRS_INVALID );
906 if( !documentValidation )
907 return tl::unexpected( documentValidation.error() );
910 const kiapi::board::BoardDesignRules& rules = aCtx.
Request.rules();
912 if( rules.has_constraints() )
914 const kiapi::board::MinimumConstraints& constraints = rules.constraints();
916 newSettings.
m_MinClearance = constraints.min_clearance().value_nm();
918 newSettings.
m_MinConn = constraints.min_connection_width().value_nm();
919 newSettings.
m_TrackMinWidth = constraints.min_track_width().value_nm();
921 newSettings.
m_ViasMinSize = constraints.min_via_size().value_nm();
927 newSettings.
m_HoleToHoleMin = constraints.hole_to_hole_min().value_nm();
934 if( rules.has_predefined_sizes() )
939 for(
const kiapi::board::PresetTrackWidth& track : rules.predefined_sizes().tracks() )
945 for(
const kiapi::board::PresetViaDimension&
via : rules.predefined_sizes().vias() )
948 static_cast<int>(
via.drill().value_nm() ) );
954 for(
const kiapi::board::PresetDiffPairDimension& pair : rules.predefined_sizes().diff_pairs() )
957 static_cast<int>( pair.width().value_nm() ),
958 static_cast<int>( pair.gap().value_nm() ),
959 static_cast<int>( pair.via_gap().value_nm() ) );
963 if( rules.has_solder_mask_paste() )
965 const kiapi::board::SolderMaskPasteDefaults& maskPaste = rules.solder_mask_paste();
973 maskPaste.allow_soldermask_bridges_in_footprints();
976 if( rules.has_teardrops() )
978 const kiapi::board::TeardropDefaults& teardrops = rules.teardrops();
986 for(
const kiapi::board::TeardropTargetEntry& entry : teardrops.target_params() )
988 if( entry.target() == kiapi::board::TeardropTarget::TDT_UNKNOWN )
997 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
998 e.set_error_message(
"unknown teardrop target" );
999 return tl::unexpected( e );
1004 params->
m_Enabled = entry.params().enabled();
1005 params->
m_TdMaxLen = entry.params().max_length().value_nm();
1006 params->
m_TdMaxWidth = entry.params().max_width().value_nm();
1016 if( rules.has_via_protection() )
1018 const kiapi::board::ViaProtectionDefaults& viaProtection = rules.via_protection();
1026 newSettings.
m_CapVias = viaProtection.cap();
1027 newSettings.
m_FillVias = viaProtection.fill();
1030 if( rules.severities_size() > 0 )
1034 for(
const kiapi::board::DrcSeveritySetting& severitySetting : rules.severities() )
1042 if( !permitted.contains( setting ) )
1044 ApiResponseStatus e;
1045 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1046 e.set_error_message( fmt::format(
"DRC severity must be error, warning, or ignore" ) );
1047 return tl::unexpected( e );
1054 if( rules.exclusions_size() > 0 )
1058 for(
const kiapi::board::DrcExclusion& exclusion : rules.exclusions() )
1062 std::vector<BOARD_DESIGN_SETTINGS::VALIDATION_ERROR> errors = newSettings.
ValidateDesignRules();
1064 if( !errors.empty() )
1068 ApiResponseStatus e;
1069 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1070 e.set_error_message( fmt::format(
"Invalid board design rules: {}: {}",
1073 return tl::unexpected( e );
1092 if( !documentValidation )
1093 return tl::unexpected( documentValidation.error() );
1095 CustomRulesResponse response;
1096 response.set_status( CRS_NONE );
1100 if( rulesPath.IsEmpty() || !wxFileName::IsFileReadable( rulesPath ) )
1103 wxFFile file( rulesPath,
"r" );
1105 if( !file.IsOpened() )
1107 response.set_status( CRS_INVALID );
1108 response.set_error_text(
"Failed to open custom rules file" );
1113 file.ReadAll( &content );
1116 std::vector<std::shared_ptr<DRC_RULE>> parsedRules;
1121 parser.
Parse( parsedRules,
nullptr );
1125 response.set_status( CRS_INVALID );
1126 response.set_error_text( ioe.
What().ToStdString() );
1130 for(
const std::shared_ptr<DRC_RULE>& rule : parsedRules )
1137 kiapi::board::CustomRule* customRule = response.add_rules();
1139 if( rule->m_Condition )
1140 customRule->set_condition( rule->m_Condition->GetExpression().ToUTF8() );
1144 board::CustomRuleConstraint* constraintProto = customRule->add_constraints();
1145 constraint.
ToProto( *constraintProto );
1149 customRule->set_name( rule->m_Name.ToUTF8() );
1151 if( rule->m_LayerSource.CmpNoCase( wxS(
"outer" ) ) == 0 )
1153 customRule->set_layer_mode( kiapi::board::CRLM_OUTER );
1155 else if( rule->m_LayerSource.CmpNoCase( wxS(
"inner" ) ) == 0 )
1157 customRule->set_layer_mode( kiapi::board::CRLM_INNER );
1159 else if( !rule->m_LayerSource.IsEmpty() )
1165 customRule->set_single_layer(
1170 if( !comment.IsEmpty() )
1171 customRule->set_comments( comment );
1174 response.set_status( CRS_VALID );
1184 if( !documentValidation )
1185 return tl::unexpected( documentValidation.error() );
1189 if( aCtx.
Request.rules_size() == 0 )
1191 if( wxFileName::FileExists( rulesPath ) )
1193 if( !wxRemoveFile( rulesPath ) )
1195 CustomRulesResponse response;
1196 response.set_status( CRS_INVALID );
1197 response.set_error_text(
"Failed to remove custom rules file" );
1202 CustomRulesResponse response;
1203 response.set_status( CRS_NONE );
1208 rulesText <<
"(version 2)\n";
1210 for(
const board::CustomRule& rule : aCtx.
Request.rules() )
1212 wxString serializationError;
1215 if( serializedRule.IsEmpty() )
1217 CustomRulesResponse response;
1218 response.set_status( CRS_INVALID );
1220 if( serializationError.IsEmpty() )
1221 response.set_error_text(
"Failed to serialize custom rule" );
1223 response.set_error_text( serializationError.ToUTF8() );
1228 rulesText <<
"\n" << serializedRule;
1234 std::vector<std::shared_ptr<DRC_RULE>> parsedRules;
1236 parser.
Parse( parsedRules,
nullptr );
1240 CustomRulesResponse response;
1241 response.set_status( CRS_INVALID );
1242 response.set_error_text( ioe.
What().ToStdString() );
1246 wxFFile file( rulesPath,
"w" );
1248 if( !file.IsOpened() )
1250 CustomRulesResponse response;
1251 response.set_status( CRS_INVALID );
1252 response.set_error_text(
"Failed to open custom rules file for writing" );
1256 if( !file.Write( rulesText ) )
1260 CustomRulesResponse response;
1261 response.set_status( CRS_INVALID );
1262 response.set_error_text(
"Failed to write custom rules file" );
1278 !documentValidation )
1280 return tl::unexpected( documentValidation.error() );
1299 ApiResponseStatus e;
1300 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1301 e.set_error_message(
"Unexpected origin type" );
1302 return tl::unexpected( e );
1306 types::Vector2 reply;
1315 return tl::unexpected( documentValidation.error() );
1317 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1318 return tl::unexpected( *busy );
1375 ApiResponseStatus e;
1376 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1377 e.set_error_message(
"Unexpected origin type" );
1378 return tl::unexpected( e );
1390 !documentValidation )
1392 return tl::unexpected( documentValidation.error() );
1395 BoardLayerNameResponse response;
1399 response.set_name(
board()->GetLayerName(
id ) );
1409 !documentValidation )
1411 return tl::unexpected( documentValidation.error() );
1414 BoardLayerResponse response;
1476 brd->SynchronizeNetsAndNetClasses(
false );
1494 return tl::unexpected( documentValidation.error() );
1496 GetDocumentModifiedStateResponse response;
1497 response.set_state(
pcbContext()->IsContentModified() ? DocumentModifiedState::DMS_MODIFIED
1498 : DocumentModifiedState::DMS_UNMODIFIED );
1506 return tl::unexpected( documentValidation.error() );
1508 NetsResponse response;
1511 std::set<wxString> netclassFilter;
1513 for(
const std::string& nc : aCtx.
Request.netclass_filter() )
1514 netclassFilter.insert( wxString( nc.c_str(), wxConvUTF8 ) );
1520 if( !netclassFilter.empty() && nc )
1522 bool inClass =
false;
1524 for(
const wxString&
filter : netclassFilter )
1537 board::types::Net* netProto = response.add_nets();
1538 netProto->set_name( net->GetNetname() );
1539 netProto->mutable_code()->set_value( net->GetNetCode() );
1551 ApiResponseStatus e;
1552 e.set_status( ApiStatusCode::AS_UNHANDLED );
1553 return tl::unexpected( e );
1556 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1557 return tl::unexpected( *busy );
1560 const bool filterByType = aCtx.
Request.types_size() > 0;
1562 if( filterByType &&
types.empty() )
1564 ApiResponseStatus e;
1565 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1566 e.set_error_message(
"none of the requested types are valid for a Board object" );
1567 return tl::unexpected( e );
1570 std::set<KICAD_T> typeFilter(
types.begin(),
types.end() );
1571 std::vector<BOARD_CONNECTED_ITEM*> sourceItems;
1573 for(
const types::KIID&
id : aCtx.
Request.items() )
1575 if( std::optional<BOARD_ITEM*> item =
getItemById(
KIID(
id.value() ) ) )
1578 sourceItems.emplace_back( connected );
1582 if( sourceItems.empty() )
1584 ApiResponseStatus e;
1585 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1586 e.set_error_message(
"none of the requested IDs were found or valid connected items" );
1587 return tl::unexpected( e );
1590 GetItemsResponse response;
1592 std::set<KIID> insertedItems;
1598 if( filterByType && !typeFilter.contains( connected->Type() ) )
1601 if( !insertedItems.insert( connected->m_Uuid ).second )
1604 connected->Serialize( *response.add_items() );
1608 response.set_status( ItemRequestStatus::IRS_OK );
1618 ApiResponseStatus e;
1619 e.set_status( ApiStatusCode::AS_UNHANDLED );
1620 return tl::unexpected( e );
1623 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1624 return tl::unexpected( *busy );
1627 const bool filterByType = aCtx.
Request.types_size() > 0;
1629 if( filterByType &&
types.empty() )
1631 ApiResponseStatus e;
1632 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1633 e.set_error_message(
"none of the requested types are valid for a Board object" );
1634 return tl::unexpected( e );
1640 GetItemsResponse response;
1642 std::shared_ptr<CONNECTIVITY_DATA> conn =
board->GetConnectivity();
1643 std::set<KIID> insertedItems;
1647 for(
const board::types::Net& net : aCtx.
Request.nets() )
1656 if( !insertedItems.insert( item->m_Uuid ).second )
1659 item->Serialize( *response.add_items() );
1663 response.set_status( ItemRequestStatus::IRS_OK );
1673 ApiResponseStatus e;
1674 e.set_status( ApiStatusCode::AS_UNHANDLED );
1675 return tl::unexpected( e );
1678 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1679 return tl::unexpected( *busy );
1682 const bool filterByType = aCtx.
Request.types_size() > 0;
1684 if( filterByType &&
types.empty() )
1686 ApiResponseStatus e;
1687 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1688 e.set_error_message(
"none of the requested types are valid for a Board object" );
1689 return tl::unexpected( e );
1695 std::set<wxString> requestedClasses;
1697 for(
const std::string& netClass : aCtx.
Request.net_classes() )
1698 requestedClasses.insert( wxString( netClass.c_str(), wxConvUTF8 ) );
1700 GetItemsResponse response;
1702 std::shared_ptr<CONNECTIVITY_DATA> conn =
board->GetConnectivity();
1703 std::set<KIID> insertedItems;
1712 if( !requestedClasses.empty() )
1717 bool inClass =
false;
1719 for(
const wxString&
filter : requestedClasses )
1734 if( !insertedItems.insert( item->m_Uuid ).second )
1737 item->Serialize( *response.add_items() );
1741 response.set_status( ItemRequestStatus::IRS_OK );
1749 NetClassForNetsResponse response;
1754 for(
const board::types::Net& net : aCtx.
Request.net() )
1761 auto [pair, rc] = response.mutable_classes()->insert( { net.name(), {} } );
1772 return tl::unexpected( documentValidation.error() );
1774 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1775 return tl::unexpected( *busy );
1784 if( aCtx.
Request.zones().empty() )
1788 frame()->CallAfter( [mgr]()
1802 std::vector<ZONE*> toFill;
1804 for(
const types::KIID&
id : aCtx.
Request.zones() )
1808 if( !item || ( *item )->Type() !=
PCB_ZONE_T )
1810 ApiResponseStatus e;
1811 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1812 e.set_error_message( fmt::format(
"zone with ID {} not found on the board",
id.value() ) );
1813 return tl::unexpected( e );
1816 ZONE* zone =
static_cast<ZONE*
>( *item );
1821 ApiResponseStatus e;
1822 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1823 e.set_error_message( fmt::format(
"zone with ID {} is a rule area and cannot be filled",
1825 return tl::unexpected( e );
1830 toFill.push_back( zone );
1836 if( !filler.
Fill( toFill ) )
1840 ApiResponseStatus e;
1841 e.set_status( ApiStatusCode::AS_UNKNOWN );
1842 e.set_error_message(
"zone fill failed" );
1843 return tl::unexpected( e );
1861 if( !documentValidation )
1862 return tl::unexpected( documentValidation.error() );
1864 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1865 return tl::unexpected( *busy );
1867 wxFileName netlistPath(
project().AbsolutePath( wxString::FromUTF8( aCtx.
Request.netlist_path() ) ) );
1869 if( !netlistPath.IsOk() || !netlistPath.FileExists() )
1871 ApiResponseStatus e;
1872 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1873 e.set_error_message(
1874 fmt::format(
"netlist file '{}' could not be opened", netlistPath.GetFullPath().ToStdString() ) );
1875 return tl::unexpected( e );
1881 const bool lookupByTimestamp = aCtx.
Request.match_mode() != NetlistMatchMode::NMM_REFERENCE;
1884 netlist.SetFindByTimeStamp( lookupByTimestamp );
1885 netlist.SetReplaceFootprints( aCtx.
Request.update_footprints() );
1889 ApiResponseStatus e;
1890 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1891 e.set_error_message( fmt::format(
"unable to handle netlist file '{}': {}",
1892 netlistPath.GetFullPath().ToStdString(),
1893 reporter.GetMessages().ToStdString() ) );
1894 return tl::unexpected( e );
1900 updater->SetIsDryRun( aCtx.
Request.dry_run() );
1901 updater->SetWillDrag(
false );
1902 updater->SetLookupByTimestamp( lookupByTimestamp );
1903 updater->SetDeleteUnusedFootprints( aCtx.
Request.delete_extra_footprints() );
1904 updater->SetReplaceFootprints( aCtx.
Request.update_footprints() );
1905 updater->SetTransferGroups( aCtx.
Request.transfer_groups() );
1906 updater->SetOverrideLocks( aCtx.
Request.override_locks() );
1907 updater->SetUpdateFields(
true );
1909 const bool success = updater->UpdateNetlist(
netlist );
1911 if( !aCtx.
Request.dry_run() && success )
1914 ImportNetlistResponse response;
1915 response.set_report(
reporter.GetMessages().ToUTF8() );
1916 response.set_error_count( updater->GetErrorCount() );
1917 response.set_warning_count( updater->GetWarningCount() );
1918 response.set_new_footprint_count( updater->GetNewFootprintCount() );
1927 return tl::unexpected( documentValidation.error() );
1929 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1930 return tl::unexpected( *busy );
1932 wxFileName sesPath(
project().AbsolutePath( wxString::FromUTF8( aCtx.
Request.session_path() ) ) );
1934 if( !sesPath.IsOk() || !sesPath.FileExists() )
1936 ApiResponseStatus e;
1937 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1938 e.set_error_message(
1939 fmt::format(
"session file '{}' could not be opened", sesPath.GetFullPath().ToStdString() ) );
1940 return tl::unexpected( e );
1943 int skippedCount = 0;
1955 ApiResponseStatus e;
1956 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1957 e.set_error_message( fmt::format(
"failed to import session '{}': {}", sesPath.GetFullPath().ToStdString(),
1958 ioe.
What().ToStdString() ) );
1959 return tl::unexpected( e );
1965 ImportSpecctraSessionResponse response;
1966 response.set_report(
reporter.GetMessages().ToUTF8() );
1967 response.set_skipped_count( skippedCount );
1975 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"GetBoardEditorAppearanceSettings" ) )
1976 return tl::unexpected( *headless );
1978 BoardEditorAppearanceSettings reply;
1986 reply.set_net_color_display(
1989 reply.set_board_flip(
frame()->GetCanvas()->GetView()->IsMirroredX()
1990 ? BoardFlipMode::BFM_FLIPPED_X
1991 : BoardFlipMode::BFM_NORMAL );
2005 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"SetBoardEditorAppearanceSettings" ) )
2006 return tl::unexpected( *headless );
2008 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2009 return tl::unexpected( *busy );
2013 const BoardEditorAppearanceSettings& newSettings = aCtx.
Request.settings();
2019 options.
m_FlipBoardView = newSettings.board_flip() == BoardFlipMode::BFM_FLIPPED_X;
2036 return tl::unexpected( documentValidation.error() );
2040 BoardPlotSettingsResponse response;
2041 BoardPlotSettings* settings = response.mutable_plot_settings();
2048 settings->set_mirror( plotOpts.
GetMirror() );
2051 settings->set_scale( plotOpts.
GetScale() );
2058 settings->set_plot_footprint_values( plotOpts.
GetPlotValue() );
2074 return tl::unexpected( documentValidation.error() );
2076 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2077 return tl::unexpected( *busy );
2079 const BoardPlotSettings& settings = aCtx.
Request.plot_settings();
2086 for(
int layer : settings.common_layers() )
2093 ApiResponseStatus e;
2094 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2095 e.set_error_message( fmt::format(
"SetBoardPlotSettings contains an invalid layer {}",
2096 magic_enum::enum_name( layerId ) ) );
2097 return tl::unexpected( e );
2100 commonLayers.push_back( layerId );
2105 plotOpts.
SetMirror( settings.mirror() );
2108 plotOpts.
SetScale( settings.scale() );
2115 plotOpts.
SetPlotValue( settings.plot_footprint_values() );
2136 return tl::unexpected( documentValidation.error() );
2138 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2139 return tl::unexpected( *busy );
2147 drcItem->SetErrorMessage( wxString::FromUTF8( aCtx.
Request.message() ) );
2149 std::vector<KIID> ids;
2151 for(
const auto&
id : aCtx.
Request.items() )
2152 ids.emplace_back(
KIID(
id.value() ) );
2155 drcItem->SetItems( ids );
2157 const auto& pos = aCtx.
Request.position();
2158 VECTOR2I position(
static_cast<int>( pos.x_nm() ),
static_cast<int>( pos.y_nm() ) );
2163 commit->
Add( marker );
2168 InjectDrcErrorResponse response;
2176 const std::string& aCommandName )
2178 if( aUnits == types::Units::U_INCH || aUnits == types::Units::U_MM
2179 || aUnits == types::Units::U_UNKNOWN )
2181 return std::nullopt;
2184 ApiResponseStatus e;
2185 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2186 e.set_error_message( fmt::format(
"{} supports only inch and mm units", aCommandName ) );
2191std::optional<ApiResponseStatus>
2193 const std::string& aCommandName )
2195 if( aMode == kiapi::board::jobs::BoardJobPaginationMode::BJPM_UNKNOWN
2196 || aMode == kiapi::board::jobs::BoardJobPaginationMode::BJPM_ALL_LAYERS_ONE_PAGE
2197 || aMode == kiapi::board::jobs::BoardJobPaginationMode::BJPM_EACH_LAYER_OWN_FILE )
2199 return std::nullopt;
2202 ApiResponseStatus e;
2203 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2204 e.set_error_message( fmt::format(
"{} does not support EACH_LAYER_OWN_PAGE pagination mode",
2213 for(
int layer : aSettings.layers() )
2216 static_cast<board::types::BoardLayer
>( layer ) );
2218 if( !
IsPcbLayer(
static_cast<int>( layerId ) ) )
2220 ApiResponseStatus e;
2221 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2222 e.set_error_message(
"Board plot settings contain an invalid layer" );
2229 for(
int layer : aSettings.common_layers() )
2232 static_cast<board::types::BoardLayer
>( layer ) );
2234 if( !
IsPcbLayer(
static_cast<int>( layerId ) ) )
2236 ApiResponseStatus e;
2237 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2238 e.set_error_message(
"Board plot settings contain an invalid common layer" );
2245 aJob.
m_colorTheme = wxString::FromUTF8( aSettings.color_theme() );
2246 aJob.
m_drawingSheet = wxString::FromUTF8( aSettings.drawing_sheet() );
2247 aJob.
m_variant = wxString::FromUTF8( aSettings.variant() );
2249 aJob.
m_mirror = aSettings.mirror();
2252 aJob.
m_scale = aSettings.scale();
2260 aJob.
m_plotRefDes = aSettings.plot_reference_designators();
2270 return std::nullopt;
2276 types::RunJobResponse response;
2279 if( !aContext || !aContext->
GetKiway() )
2281 response.set_status( types::JobStatus::JS_ERROR );
2282 response.set_message(
"Internal error" );
2283 wxCHECK_MSG(
false, response,
"context missing valid kiway in ExecuteBoardJob?" );
2290 response.add_output_path( output.m_outputPath.ToUTF8() );
2294 response.set_status( types::JobStatus::JS_SUCCESS );
2298 response.set_status( types::JobStatus::JS_ERROR );
2299 response.set_message( fmt::format(
"Board export job '{}' failed with exit code {}: {}",
2301 reporter.GetMessages().ToStdString() ) );
2310 return tl::unexpected( validation.error() );
2312 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2313 return tl::unexpected( *busy );
2367 return tl::unexpected( validation.error() );
2369 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2370 return tl::unexpected( *busy );
2413 return tl::unexpected( validation.error() );
2415 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2416 return tl::unexpected( *busy );
2423 return tl::unexpected( *err );
2428 if( std::optional<ApiResponseStatus> paginationError =
2430 "RunBoardJobExportSvg" ) )
2432 return tl::unexpected( *paginationError );
2445 return tl::unexpected( validation.error() );
2447 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2448 return tl::unexpected( *busy );
2455 return tl::unexpected( *err );
2460 if( std::optional<ApiResponseStatus> unitError =
2463 return tl::unexpected( *unitError );
2468 if( std::optional<ApiResponseStatus> paginationError =
2470 "RunBoardJobExportDxf" ) )
2472 return tl::unexpected( *paginationError );
2485 return tl::unexpected( validation.error() );
2487 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2488 return tl::unexpected( *busy );
2495 return tl::unexpected( *err );
2513 return tl::unexpected( validation.error() );
2515 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2516 return tl::unexpected( *busy );
2523 return tl::unexpected( *err );
2525 if( std::optional<ApiResponseStatus> paginationError =
2527 "RunBoardJobExportPs" ) )
2529 return tl::unexpected( *paginationError );
2548 return tl::unexpected( validation.error() );
2550 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2551 return tl::unexpected( *busy );
2558 return tl::unexpected( *err );
2560 if( std::optional<ApiResponseStatus> paginationError =
2563 return tl::unexpected( *paginationError );
2574 ApiResponseStatus status;
2575 status.set_status( ApiStatusCode::AS_BAD_REQUEST );
2577 return tl::unexpected( status );
2595 return tl::unexpected( validation.error() );
2597 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2598 return tl::unexpected( *busy );
2609 return tl::unexpected( *err );
2618 switch( aCtx.
Request.precision() )
2621 case GerberPrecision::GP_5: job.
m_precision = 5;
break;
2622 case GerberPrecision::GP_6: job.
m_precision = 6;
break;
2633 return tl::unexpected( validation.error() );
2635 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2636 return tl::unexpected( *busy );
2644 if( std::optional<ApiResponseStatus> unitError =
2647 return tl::unexpected( *unitError );
2654 if( aCtx.
Request.has_excellon() )
2656 const ExcellonFormatOptions& excellonOptions = aCtx.
Request.excellon();
2658 if( excellonOptions.has_mirror_y() )
2661 if( excellonOptions.has_minimal_header() )
2664 if( excellonOptions.has_combine_pth_npth() )
2667 if( excellonOptions.has_route_oval_holes() )
2671 if( aCtx.
Request.map_format() != DrillMapFormat::DMF_UNKNOWN )
2679 if( aCtx.
Request.has_gerber_generate_tenting() )
2682 if( aCtx.
Request.report_format() != DrillReportFormat::DRF_UNKNOWN )
2686 if( aCtx.
Request.has_report_filename() )
2698 return tl::unexpected( validation.error() );
2700 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2701 return tl::unexpected( *busy );
2707 if( aCtx.
Request.has_use_drill_place_file_origin() )
2717 if( aCtx.
Request.has_include_board_edge_for_gerber() )
2724 if( std::optional<ApiResponseStatus> unitError =
2727 return tl::unexpected( *unitError );
2741 return tl::unexpected( validation.error() );
2743 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2744 return tl::unexpected( *busy );
2764 return tl::unexpected( validation.error() );
2766 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2767 return tl::unexpected( *busy );
2781 return tl::unexpected( validation.error() );
2783 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2784 return tl::unexpected( *busy );
2791 if( !aCtx.
Request.variant().empty() )
2796 if( aCtx.
Request.has_precision() )
2801 job.
m_colMfgPn = wxString::FromUTF8( aCtx.
Request.manufacturer_part_number_column() );
2802 job.
m_colMfg = wxString::FromUTF8( aCtx.
Request.manufacturer_column() );
2803 job.
m_colDistPn = wxString::FromUTF8( aCtx.
Request.distributor_part_number_column() );
2807 if( std::optional<ApiResponseStatus> unitError =
2810 return tl::unexpected( *unitError );
2827 return tl::unexpected( validation.error() );
2829 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2830 return tl::unexpected( *busy );
2843 aJob.
m_sections = aContent.sections().empty()
2845 : std::optional<wxString>( wxString::FromUTF8( aContent.sections() ) );
2852 aJob.
m_drawingSheet = wxString::FromUTF8( aRequest.drawing_sheet() );
2854 if( aRequest.variant_names_size() > 0 )
2856 for(
const std::string&
name : aRequest.variant_names() )
2859 else if( !aRequest.variant().empty() )
2861 aJob.
m_variantNames.push_back( wxString::FromUTF8( aRequest.variant() ) );
2865 aRequest.variant_packaging() );
2867 if( aRequest.has_precision() )
2873 aJob.
m_colMfgPn = wxString::FromUTF8( aRequest.manufacturer_part_number_column() );
2875 aJob.
m_productName = wxString::FromUTF8( aRequest.product_name() );
2884 return tl::unexpected( validation.error() );
2886 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2887 return tl::unexpected( *busy );
2893 if( std::optional<ApiResponseStatus> unitError =
2896 return tl::unexpected( *unitError );
2909 return tl::unexpected( validation.error() );
2911 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2912 return tl::unexpected( *busy );
2920 if( std::optional<ApiResponseStatus> unitError =
2923 return tl::unexpected( *unitError );
2940 return tl::unexpected( valid.error() );
2942 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2943 return tl::unexpected( *busy );
2945 switch( aCtx.
Request.units() )
2947 case types::Units::U_UNKNOWN:
2948 case types::Units::U_MM:
2949 case types::Units::U_MILS:
2954 ApiResponseStatus e;
2955 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2956 e.set_error_message(
"RunBoardJobExportIdf supports only mm and mils units" );
2957 return tl::unexpected( e );
2968 if( aCtx.
Request.origin_mode() == IdfOriginMode::IOM_USER )
2979 if( aCtx.
Request.has_part_number_field() )
2991 wxLogTrace(
traceApi,
"Received announce from frame %d at %s",
2997 CrossProbeAnnounceResponse response;
2998 response.set_status( CPS_OK );
3005 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"SyncSelection" ) )
3006 return tl::unexpected( *headless );
3008 SyncSelectionResponse response;
3012 if( !settings.
on_selection && aCtx.
Request.context() != SyncSelectionContext::SSC_EXPLICIT )
3014 response.set_status( CPS_DISABLED );
3015 response.set_message(
"implicit selection sync disabled by user" );
3019 std::vector<BOARD_ITEM*> items =
3024 if( aCtx.
Request.mode() == SyncSelectionMode::SSM_ITEMS_AND_NETS )
3036 wxLogTrace(
traceCrossProbeFlash,
"MAIL_SELECTION(_FORCE) PCB: flash enabled, items=%zu", items.size() );
3043 std::vector<BOARD_ITEM*> boardItems;
3044 std::copy( items.begin(), items.end(), std::back_inserter( boardItems ) );
3053 response.set_status( CPS_OK );
3061 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"HighlightNets" ) )
3062 return tl::unexpected( *headless );
3064 HighlightNetsResponse response;
3072 response.set_status( CPS_DISABLED );
3073 response.set_message(
"net highlight cross-probing disabled by user" );
3078 std::vector<wxString> nets;
3080 for(
const std::string&
name : aCtx.
Request.net_name() )
3081 nets.emplace_back( wxString::FromUTF8(
name ) );
3085 response.set_status( CPS_OK );
3093 return tl::unexpected( documentValidation.error() );
3095 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3096 return tl::unexpected( *busy );
3099 VariantsResponse response;
3103 for(
const wxString&
name :
board->GetVariantNames() )
3105 types::DesignVariant* var = response.add_variants();
3106 var->set_name(
name.ToUTF8() );
3107 var->set_description(
board->GetVariantDescription(
name ).ToUTF8() );
3117 return tl::unexpected( documentValidation.error() );
3119 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3120 return tl::unexpected( *busy );
3124 wxString
name = wxString::FromUTF8( aCtx.
Request.name() );
3128 ApiResponseStatus e;
3129 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3130 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.name() ) );
3131 return tl::unexpected( e );
3136 ApiResponseStatus e;
3137 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3138 e.set_error_message( fmt::format(
"a variant named '{}' already exists", aCtx.
Request.name() ) );
3139 return tl::unexpected( e );
3144 if( aCtx.
Request.has_description() )
3145 board->SetVariantDescription(
name, wxString::FromUTF8( aCtx.
Request.description() ) );
3159 return tl::unexpected( documentValidation.error() );
3161 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3162 return tl::unexpected( *busy );
3166 wxString
name = wxString::FromUTF8( aCtx.
Request.name() );
3170 ApiResponseStatus e;
3171 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3172 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.name() ) );
3173 return tl::unexpected( e );
3178 ApiResponseStatus e;
3179 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3180 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.name() ) );
3181 return tl::unexpected( e );
3198 return tl::unexpected( documentValidation.error() );
3200 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3201 return tl::unexpected( *busy );
3205 wxString oldName = wxString::FromUTF8( aCtx.
Request.old_name() );
3206 wxString newName = wxString::FromUTF8( aCtx.
Request.new_name() );
3210 ApiResponseStatus e;
3211 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3212 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.old_name() ) );
3213 return tl::unexpected( e );
3218 ApiResponseStatus e;
3219 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3220 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.new_name() ) );
3221 return tl::unexpected( e );
3224 if( !
board->HasVariant( oldName ) )
3226 ApiResponseStatus e;
3227 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3228 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.old_name() ) );
3229 return tl::unexpected( e );
3232 if(
board->HasVariant( newName ) )
3234 ApiResponseStatus e;
3235 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3236 e.set_error_message( fmt::format(
"a variant named '{}' already exists", aCtx.
Request.new_name() ) );
3237 return tl::unexpected( e );
3240 board->RenameVariant( oldName, newName );
3254 return tl::unexpected( documentValidation.error() );
3256 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3257 return tl::unexpected( *busy );
3261 wxString oldName = wxString::FromUTF8( aCtx.
Request.old_name() );
3262 wxString newName = wxString::FromUTF8( aCtx.
Request.new_name() );
3266 ApiResponseStatus e;
3267 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3268 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.old_name() ) );
3269 return tl::unexpected( e );
3274 ApiResponseStatus e;
3275 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3276 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.new_name() ) );
3277 return tl::unexpected( e );
3280 if( !
board->HasVariant( oldName ) )
3282 ApiResponseStatus e;
3283 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3284 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.old_name() ) );
3285 return tl::unexpected( e );
3288 if(
board->HasVariant( newName ) )
3290 ApiResponseStatus e;
3291 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3292 e.set_error_message( fmt::format(
"a variant named '{}' already exists", aCtx.
Request.new_name() ) );
3293 return tl::unexpected( e );
3296 board->CopyVariant( oldName, newName,
3297 aCtx.
Request.has_new_description() ? wxString::FromUTF8( aCtx.
Request.new_description() )
3312 return tl::unexpected( documentValidation.error() );
3314 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3315 return tl::unexpected( *busy );
3319 wxString
name = wxString::FromUTF8( aCtx.
Request.name() );
3323 ApiResponseStatus e;
3324 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3325 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.name() ) );
3326 return tl::unexpected( e );
3329 board->SetVariantDescription(
name, wxString::FromUTF8( aCtx.
Request.description() ) );
3340 return tl::unexpected( documentValidation.error() );
3342 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3343 return tl::unexpected( *busy );
3351 ApiResponseStatus e;
3352 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3353 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.name() ) );
3354 return tl::unexpected( e );
3358 wxString varName = aCtx.
Request.has_name() ? wxString::FromUTF8( aCtx.
Request.name() ) : wxString();
3363 board->SetCurrentVariant( varName );
3373 return tl::unexpected( documentValidation.error() );
3375 CurrentVariantResponse response;
3377 if( wxString current =
pcbContext()->GetBoard()->GetCurrentVariant(); !current.IsEmpty() )
3378 response.set_name( current.ToUTF8() );
3389 ApiResponseStatus e;
3390 e.set_status( ApiStatusCode::AS_UNHANDLED );
3391 return tl::unexpected( e );
3394 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3395 return tl::unexpected( *busy );
3401 ApiResponseStatus e;
3402 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3403 e.set_error_message(
"lib_id must specify both a library nickname and an entry name" );
3404 return tl::unexpected( e );
3415 ApiResponseStatus e;
3416 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3417 e.set_error_message(
"layer must be F_Cu or B_Cu" );
3418 return tl::unexpected( e );
3425 ApiResponseStatus e;
3426 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3427 e.set_error_message( fmt::format(
"footprint '{}' not found", libId.
Format().
wx_str() ) );
3428 return tl::unexpected( e );
3431 footprint->SetUuid(
KIID() );
3432 footprint->RunOnChildren(
3439 footprint->SetParent(
board() );
3443 if( aCtx.
Request.has_orientation() )
3444 footprint->SetOrientationDegrees( aCtx.
Request.orientation().value_degrees() );
3446 footprint->SetLayerAndFlip( layer );
3449 FOOTPRINT* placed = footprint.release();
3450 commit->
Add( placed );
3455 PlaceFromLibraryResponse response;
3456 response.mutable_header()->CopyFrom( aCtx.
Request.header() );
3457 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 > handleRunBoardJobExportSpecctraDsn(const HANDLER_CONTEXT< RunBoardJobExportSpecctraDsn > &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< ImportSpecctraSessionResponse > handleImportSpecctraSession(const HANDLER_CONTEXT< ImportSpecctraSession > &aCtx)
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
void Revert() override
Revert the commit by restoring the modified items state.
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()
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
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
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)
wxString m_BoardDrawingSheetFile
PcbNew params.
virtual PROJECT_FILE & GetProjectFile() 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.
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 ImportSpecctraSession(BOARD *aBoard, const wxString &fullFileName, COMMIT &aCommit, REPORTER *aReporter=nullptr, int *aSkippedCount=nullptr)
Helper method to import SES file to a board.
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.
constexpr KICAD_T BaseType(const KICAD_T aType)
Return the underlying type of the given type.
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_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_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_3D_BODY_T
class PCB_3D_BODY, a 3D body (extruded or model) on a footprint
@ 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_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)
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D