29#include <fmt/ranges.h>
31#include <magic_enum.hpp>
69#include <wx/filename.h>
71#include <api/common/commands/library_commands.pb.h>
72#include <api/common/types/base_types.pb.h>
77using namespace kiapi::common::commands;
78using kiapi::common::types::CommandStatus;
79using kiapi::common::types::DocumentType;
80using kiapi::common::types::ItemRequestStatus;
107 types::RunJobResponse response;
112 response.add_output_path( output.m_outputPath.ToUTF8() );
116 response.set_status( types::JobStatus::JS_SUCCESS );
120 response.set_status( types::JobStatus::JS_ERROR );
121 response.set_message( fmt::format(
"Schematic export job '{}' failed with exit code {}: {}",
123 reporter.GetMessages().ToStdString() ) );
139 using namespace kiapi::schematic::jobs;
141 using namespace kiapi::schematic::commands;
208 return std::make_unique<SCH_COMMIT>(
toolManager() );
231 e.set_status( ApiStatusCode::AS_UNIMPLEMENTED );
232 e.set_error_message( fmt::format(
"{} is not available in headless mode", aCommandName ) );
242 kiapi::schematic::types::SchematicSymbolInstance symbol;
247 aOut.PackFrom( symbol );
251 kiapi::schematic::types::SheetSymbol sheet;
256 aOut.PackFrom( sheet );
281tl::expected<bool, ApiResponseStatus>
284 if( aDocument.type() != DocumentType::DOCTYPE_SCHEMATIC )
287 e.set_status( ApiStatusCode::AS_UNHANDLED );
288 return tl::unexpected( e );
293 if( aDocument.project().name().compare( prj.
GetProjectName().ToUTF8() ) != 0 )
296 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
297 e.set_error_message( fmt::format(
"the requested project {} is not open",
298 aDocument.project().name() ) );
299 return tl::unexpected( e );
302 if( aDocument.project().path().compare( prj.
GetProjectPath().ToUTF8() ) != 0 )
305 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
306 e.set_error_message( fmt::format(
"the requested project {} is not open at path {}",
307 aDocument.project().name(),
308 aDocument.project().path() ) );
309 return tl::unexpected( e );
312 if( aDocument.has_sheet_path() )
319 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
320 e.set_error_message( fmt::format(
"the requested sheet path {} is not valid for this schematic",
321 path.AsString().ToStdString() ) );
322 return tl::unexpected( e );
333 return tl::unexpected( documentValidation.error() );
335 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
336 return tl::unexpected( *busy );
341 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
342 e.set_error_message(
"the schematic is untitled; use SaveDocumentAs to save it to a new file" );
343 return tl::unexpected( e );
346 if( !
context()->SaveSchematic() )
349 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
350 e.set_error_message(
"failed to save schematic" );
351 return tl::unexpected( e );
354 return google::protobuf::Empty();
366 e.set_status( ApiStatusCode::AS_UNIMPLEMENTED );
367 e.set_error_message(
"SaveDocumentAs is not available in GUI mode" );
368 return tl::unexpected( e );
371 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
372 return tl::unexpected( *busy );
376 if( !documentValidation )
377 return tl::unexpected( documentValidation.error() );
379 wxString pathStr = wxString::FromUTF8( aCtx.
Request.path() );
381 if( pathStr.IsEmpty() )
384 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
385 e.set_error_message(
"path is required" );
386 return tl::unexpected( e );
389 wxFileName oldSchematicFile(
m_context->GetCurrentFileName() );
391 if( !
context()->SaveSchematicAs( pathStr ) )
394 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
395 e.set_error_message( fmt::format(
"failed to save schematic to '{}'", pathStr.ToStdString() ) );
396 return tl::unexpected( e );
401 wxFileName newSchematicFile( pathStr );
404 server->NotifyDocumentRenamed(
thisDocumentType(), oldSchematicFile.GetFullPath(),
405 newSchematicFile.GetFullPath() );
408 return google::protobuf::Empty();
417 if( !documentValidation )
418 return tl::unexpected( documentValidation.error() );
420 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
421 return tl::unexpected( *busy );
423 wxFileName schematicPath(
project().AbsolutePath( wxString::FromUTF8( aCtx.
Request.path() ) ) );
425 if( !schematicPath.IsOk() || !schematicPath.IsDirWritable() )
428 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
430 fmt::format(
"save path '{}' could not be opened", schematicPath.GetFullPath().ToStdString() ) );
431 return tl::unexpected( e );
434 if( schematicPath.FileExists() && ( !schematicPath.IsFileWritable() || !aCtx.
Request.options().overwrite() ) )
437 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
438 e.set_error_message( fmt::format(
"save path '{}' exists and cannot be overwritten",
439 schematicPath.GetFullPath().ToStdString() ) );
440 return tl::unexpected( e );
446 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
447 e.set_error_message( fmt::format(
"save path '{}' must have a kicad_sch extension",
448 schematicPath.GetFullPath().ToStdString() ) );
449 return tl::unexpected( e );
452 bool includeProject =
true;
454 if( aCtx.
Request.has_options() )
455 includeProject = aCtx.
Request.options().include_project();
457 if( !
context()->SaveSchematicCopy( schematicPath.GetFullPath(), includeProject ) )
460 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
461 e.set_error_message(
"failed to save schematic copy" );
462 return tl::unexpected( e );
465 return google::protobuf::Empty();
472 if( aCtx.
Request.document().type() != DocumentType::DOCTYPE_SCHEMATIC )
475 e.set_status( ApiStatusCode::AS_UNHANDLED );
476 return tl::unexpected( e );
481 if( !documentValidation )
482 return tl::unexpected( documentValidation.error() );
487 e.set_status( ApiStatusCode::AS_BUSY );
488 e.set_error_message(
"cannot revert while a commit is open" );
489 return tl::unexpected( e );
492 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
493 return tl::unexpected( *busy );
495 if( !
context()->RevertToSaved() )
498 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
499 e.set_error_message(
"could not revert: there is no saved file on disk to revert to" );
500 return tl::unexpected( e );
503 return google::protobuf::Empty();
512 if( !documentValidation )
513 return tl::unexpected( documentValidation.error() );
515 commands::SavedDocumentResponse response;
519 if( aCtx.
Request.document().has_sheet_path() )
523 if( std::optional<SCH_SHEET_PATH> resolvedPath =
schematic()->Hierarchy().GetSheetPathByKIIDPath( kiidPath ) )
524 topLevelSheet = resolvedPath->Last();
527 if( !topLevelSheet || !topLevelSheet->
GetScreen() )
530 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
531 e.set_error_message(
"schematic has no top-level sheet to save" );
532 return tl::unexpected( e );
540 std::string contents = formatter.
GetString();
542 response.set_contents( contents );
551 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"SaveSelectionToString" ) )
552 return tl::unexpected( *headless );
557 if( selection.Empty() )
560 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
561 e.set_error_message(
"the selection is empty" );
562 return tl::unexpected( e );
565 commands::SavedSelectionResponse response;
570 response.add_ids()->set_value( item->m_Uuid.AsStdString() );
577 std::string contents = formatter.
GetString();
579 response.set_contents( contents );
588 if( aCtx.
Request.type() != DocumentType::DOCTYPE_SCHEMATIC )
593 e.set_status( ApiStatusCode::AS_UNHANDLED );
594 return tl::unexpected( e );
597 GetOpenDocumentsResponse response;
598 common::types::DocumentSpecifier doc;
600 wxFileName fn(
m_context->GetCurrentFileName() );
602 doc.set_type( DocumentType::DOCTYPE_SCHEMATIC );
604 if( std::optional<SCH_SHEET_PATH>
path =
m_context->GetCurrentSheet() )
609 response.mutable_documents()->Add( std::move( doc ) );
618 return tl::unexpected( documentValidation.error() );
620 GetDocumentModifiedStateResponse response;
622 if( aCtx.
Request.document().has_sheet_path() )
631 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
632 e.set_error_message(
"the requested sheet path is not valid for this schematic" );
633 return tl::unexpected( e );
636 if(
const SCH_SCREEN* screen = sheetPath->LastScreen() )
638 response.set_state( screen->IsContentModified() ? DocumentModifiedState::DMS_MODIFIED
639 : DocumentModifiedState::DMS_UNMODIFIED );
648 response.set_state(
schematic()->Hierarchy().IsModified() ? DocumentModifiedState::DMS_MODIFIED
649 : DocumentModifiedState::DMS_UNMODIFIED );
656 std::erase_if( aTypeList,
669 return tl::unexpected( valid.error() );
672 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
673 return tl::unexpected( *busy );
677 if( aCtx.
Request.types().empty() )
680 std::set<KICAD_T> typesRequested;
682 for(
KICAD_T type : requestedTypes )
683 typesRequested.insert( type );
687 if( typesRequested.empty() )
690 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
691 e.set_error_message(
"none of the requested types are valid for a Schematic object" );
692 return tl::unexpected( e );
696 std::optional<SCH_SHEET_PATH> pathFilter;
698 if( aCtx.
Request.header().document().has_sheet_path() )
704 std::map<KICAD_T, std::vector<std::pair<EDA_ITEM*, SCH_SHEET_PATH>>> itemMap;
709 const SCH_SCREEN* aScreen = aPath.LastScreen();
716 itemMap[ aItem->Type() ].emplace_back( aItem, aPath );
722 aItem->RunOnChildren(
725 itemMap[ aChild->
Type() ].emplace_back( aChild, aPath );
733 processScreen( *pathFilter );
738 processScreen(
path );
741 GetItemsResponse response;
742 google::protobuf::Any
any;
744 for(
KICAD_T type : typesRequested )
746 for(
const auto& [item, itemPath] : itemMap[type] )
749 response.mutable_items()->Add( std::move(
any ) );
753 response.set_status( ItemRequestStatus::IRS_OK );
763 e.set_status( ApiStatusCode::AS_UNHANDLED );
764 return tl::unexpected( e );
767 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
768 return tl::unexpected( *busy );
771 std::optional<SCH_SHEET_PATH> pathFilter;
773 if( aCtx.
Request.header().document().has_sheet_path() )
779 GetItemsResponse response;
781 google::protobuf::Any
any;
783 for(
const types::KIID& idProto : aCtx.
Request.items() )
785 KIID id( idProto.value() );
791 item = pathFilter->ResolveItem(
id );
792 itemPath = *pathFilter;
796 item = hierarchy.
ResolveItem(
id, &itemPath,
true );
804 kiapi::schematic::types::SchematicSymbolInstance symbol;
809 any.PackFrom( symbol );
813 kiapi::schematic::types::SheetSymbol sheet;
818 any.PackFrom( sheet );
825 response.mutable_items()->Add( std::move(
any ) );
828 if( response.items().empty() )
831 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
832 e.set_error_message(
"none of the requested IDs were found or valid" );
833 return tl::unexpected( e );
836 response.set_status( ItemRequestStatus::IRS_OK );
844 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"GetSelection" ) )
845 return tl::unexpected( *headless );
851 e.set_status( ApiStatusCode::AS_UNHANDLED );
852 return tl::unexpected( e );
863 SelectionResponse response;
864 google::protobuf::Any
any;
871 response.mutable_items()->Add( std::move(
any ) );
882 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"ClearSelection" ) )
883 return tl::unexpected( *headless );
889 e.set_status( ApiStatusCode::AS_UNHANDLED );
890 return tl::unexpected( e );
893 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
894 return tl::unexpected( *busy );
906 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"AddToSelection" ) )
907 return tl::unexpected( *headless );
913 e.set_status( ApiStatusCode::AS_UNHANDLED );
914 return tl::unexpected( e );
917 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
918 return tl::unexpected( *busy );
925 for(
const types::KIID&
id : aCtx.
Request.items() )
930 if( std::optional<SCH_ITEM*> item =
getItemById(
KIID(
id.value() ), &itemPath );
931 item && itemPath == current )
933 toAdd.push_back( *item );
940 SelectionResponse response;
941 google::protobuf::Any
any;
946 response.mutable_items()->Add( std::move(
any ) );
956 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"RemoveFromSelection" ) )
957 return tl::unexpected( *headless );
963 e.set_status( ApiStatusCode::AS_UNHANDLED );
964 return tl::unexpected( e );
967 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
968 return tl::unexpected( *busy );
975 for(
const types::KIID&
id : aCtx.
Request.items() )
979 if( std::optional<SCH_ITEM*> item =
getItemById(
KIID(
id.value() ), &itemPath );
980 item && itemPath == current )
982 toRemove.push_back( *item );
989 SelectionResponse response;
990 google::protobuf::Any
any;
995 response.mutable_items()->Add( std::move(
any ) );
1004 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"FocusOnItems" ) )
1005 return tl::unexpected( *headless );
1008 return tl::unexpected( documentValidation.error() );
1010 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1011 return tl::unexpected( *busy );
1013 std::vector<KIID> ids;
1015 for(
const types::KIID&
id : aCtx.
Request.items() )
1016 ids.emplace_back(
id.value() );
1018 std::optional<KIID_PATH> sheetPath;
1020 if( aCtx.
Request.document().has_sheet_path() )
1026 return tl::unexpected( target.error() );
1031 BOX2I bbox = target->BBox;
1033 if( aCtx.
Request.has_margin() )
1046 ApiResponseStatus e;
1047 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1048 e.set_error_message(
"Tried to create an item in a null container" );
1049 return tl::unexpected( e );
1054 ApiResponseStatus e;
1055 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1056 e.set_error_message( fmt::format(
"type {} is not supported by the schematic API handler",
1057 magic_enum::enum_name( aType ) ) );
1058 return tl::unexpected( e );
1063 ApiResponseStatus e;
1064 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1065 e.set_error_message( fmt::format(
"Tried to create a pin in {}, which is not a symbol",
1067 return tl::unexpected( e );
1071 ApiResponseStatus e;
1072 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1073 e.set_error_message( fmt::format(
"Tried to create a sheet symbol in {}, which is not a "
1076 return tl::unexpected( e );
1080 ApiResponseStatus e;
1081 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1082 e.set_error_message( fmt::format(
"Tried to create a symbol in {}, which is not a "
1085 return tl::unexpected( e );
1090 if( created && !created->GetParent() )
1091 created->SetParent( aContainer );
1095 ApiResponseStatus e;
1096 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1097 e.set_error_message( fmt::format(
"Tried to create an item of type {}, which is unhandled",
1098 magic_enum::enum_name( aType ) ) );
1099 return tl::unexpected( e );
1107 const std::string& aClientName,
1108 const types::ItemHeader &aHeader,
1109 const google::protobuf::RepeatedPtrField<google::protobuf::Any>& aItems,
1110 std::function<
void( ItemStatus, google::protobuf::Any )> aItemHandler )
1112 ApiResponseStatus e;
1116 if( !containerResult && containerResult.error().status() == ApiStatusCode::AS_UNHANDLED )
1119 e.set_status( ApiStatusCode::AS_UNHANDLED );
1120 return tl::unexpected( e );
1122 else if( !containerResult )
1124 e.CopyFrom( containerResult.error() );
1125 return tl::unexpected( e );
1132 if( aHeader.document().has_sheet_path() )
1145 bool connectivityChanged =
false;
1146 EDA_ITEM* container = targetScreen;
1148 if( containerResult->has_value() )
1152 if( !containerItem )
1154 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1155 e.set_error_message(
"the requested container does not exist in this document" );
1156 return tl::unexpected( e );
1159 container = containerItem;
1162 for(
const google::protobuf::Any& anyItem : aItems )
1169 status.set_code( ItemStatusCode::ISC_INVALID_TYPE );
1170 status.set_error_message( fmt::format(
"Could not decode a valid type from {}", anyItem.type_url() ) );
1171 aItemHandler( status, anyItem );
1177 if( !creationResult )
1179 status.set_code( ItemStatusCode::ISC_INVALID_TYPE );
1180 status.set_error_message( creationResult.error().error_message() );
1181 aItemHandler( status, anyItem );
1185 std::unique_ptr<EDA_ITEM> item( std::move( *creationResult ) );
1187 bool unpacked =
false;
1191 kiapi::schematic::types::SchematicSymbolInstance symbolProto;
1192 kiapi::schematic::types::SheetSymbol sheetProto;
1196 unpacked = anyItem.UnpackTo( &symbolProto )
1201 unpacked = anyItem.UnpackTo( &sheetProto );
1207 if( tl::expected<bool, ApiResponseStatus>
result =
UnpackSheet( sheet, sheetProto );
1214 return tl::unexpected(
result.error() );
1220 unpacked =
group->DeserializeGroup( anyItem, commit );
1224 unpacked = item->Deserialize( anyItem );
1231 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1232 e.set_error_message( fmt::format(
"could not unpack {} from request", item->GetClass().ToStdString() ) );
1233 return tl::unexpected( e );
1236 if( std::vector<wxString> removed = item->RemoveConflictingCustomProperties(); !removed.empty() )
1239 [](
const wxString& aIn )
1241 return std::string( aIn.ToUTF8() );
1244 status.set_code( ItemStatusCode::ISC_INVALID_DATA );
1245 status.set_error_message( fmt::format(
"Invalid custom properties for item {}: property name(s) '{}' "
1247 item->m_Uuid.AsStdString(),
1248 fmt::join( std::views::transform( removed, as_str ),
", " ) ) );
1250 aItemHandler( status, anyItem );
1257 existingItem = targetPath.
ResolveItem( item->m_Uuid );
1260 existingPath = targetPath;
1262 if( aCreate && existingItem )
1264 status.set_code( ItemStatusCode::ISC_EXISTING );
1265 status.set_error_message( fmt::format(
"an item with UUID {} already exists",
1266 item->m_Uuid.AsStdString() ) );
1267 aItemHandler( status, anyItem );
1270 else if( !aCreate && !existingItem )
1272 status.set_code( ItemStatusCode::ISC_NONEXISTENT );
1273 status.set_error_message( fmt::format(
"an item with UUID {} does not exist",
1274 item->m_Uuid.AsStdString() ) );
1275 aItemHandler( status, anyItem );
1279 if( !aCreate && existingItem->
Type() != *type )
1281 status.set_code( ItemStatusCode::ISC_INVALID_DATA );
1282 status.set_error_message( fmt::format(
"item {} is not of the requested type",
1283 item->m_Uuid.AsStdString() ) );
1284 aItemHandler( status, anyItem );
1292 if( itemScreen != targetScreen )
1294 status.set_code( ItemStatusCode::ISC_INVALID_DATA );
1295 status.set_error_message( fmt::format(
"item {} exists on a different sheet than targeted",
1296 item->m_Uuid.AsStdString() ) );
1297 aItemHandler( status, anyItem );
1304 if( symbolProto.has_definition() )
1306 if( symbolProto.definition().id().entry_name().empty() )
1308 status.set_code( ItemStatusCode::ISC_INVALID_DATA );
1309 status.set_error_message(
"symbol definition is missing an entry name" );
1310 aItemHandler( status, anyItem );
1316 status.set_code( ItemStatusCode::ISC_INVALID_DATA );
1317 status.set_error_message(
"a symbol definition is required" );
1318 aItemHandler( status, anyItem );
1330 ? wxString( wxEmptyString )
1333 for(
const std::unique_ptr<SCH_PIN>&
pin : existingSymbol->
GetRawPins() )
1335 tempSymbol->
GetRawPins().emplace_back( std::make_unique<SCH_PIN>( *
pin ) );
1336 tempSymbol->
GetRawPins().back()->SetParent( tempSymbol );
1352 if( wxString rawFilename = sheet->
GetFileName(); !rawFilename.IsEmpty() )
1359 status.set_code( ItemStatusCode::ISC_INVALID_DATA );
1360 status.set_error_message( fmt::format(
"could not resolve sheet filename '{}' for new sheet",
1361 rawFilename.ToStdString() ) );
1362 aItemHandler( status, anyItem );
1374 parentPath = targetPath;
1376 parentPath = existingPath;
1380 if( !destFilePath.IsEmpty() )
1387 status.set_code( ItemStatusCode::ISC_INVALID_DATA );
1388 status.set_error_message(
"sheet update would create recursive hierarchy" );
1389 aItemHandler( status, anyItem );
1395 status.set_code( ItemStatusCode::ISC_OK );
1396 google::protobuf::Any newItem;
1398 if( aCreate && !item )
1402 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1403 e.set_error_message(
"could not add the requested item to its parent container" );
1404 return tl::unexpected( e );
1427 commit->
Add( createdItem, targetScreen );
1432 kiapi::schematic::types::SchematicSymbolInstance packed;
1436 aItemHandler( status, anyItem );
1440 if(
PackSymbol( &packed, symbol, targetPath ) )
1441 newItem.PackFrom( packed );
1446 kiapi::schematic::types::SheetSymbol packed;
1448 if( sheetProto.page_number().empty() )
1453 aItemHandler( status, anyItem );
1457 if(
PackSheet( &packed, sheet, targetPath ) )
1458 newItem.PackFrom( packed );
1469 std::vector<SCH_SYMBOL_INSTANCE> symbolPlacements;
1470 std::vector<SCH_SHEET_INSTANCE> sheetPlacements;
1473 symbolPlacements =
static_cast<SCH_SYMBOL*
>( existingItem )->GetInstances();
1475 sheetPlacements =
static_cast<SCH_SHEET*
>( existingItem )->GetInstances();
1477 commit->
Modify( existingItem, targetScreen );
1483 connectivityChanged =
true;
1489 kiapi::schematic::types::SchematicSymbolInstance packed;
1496 aItemHandler( status, anyItem );
1500 if(
PackSymbol( &packed, symbol, existingPath ) )
1501 newItem.PackFrom( packed );
1506 kiapi::schematic::types::SheetSymbol packed;
1513 aItemHandler( status, anyItem );
1517 if(
PackSheet( &packed, sheet, existingPath ) )
1518 newItem.PackFrom( packed );
1526 aItemHandler( status, newItem );
1532 :
_(
"Modified items via API" ) );
1535 if(
m_frame && connectivityChanged )
1538 return ItemRequestStatus::IRS_OK;
1543 const std::string& aClientName )
1548 for(
auto& [
id, status] : aItemsToDelete )
1558 status = ItemDeletionStatus::IDS_IMMUTABLE;
1563 status = ItemDeletionStatus::IDS_OK;
1574 return std::nullopt;
1579 return std::nullopt;
1587 if( aDocument.has_sheet_path() )
1591 if( std::optional<SCH_SHEET_PATH> sheetPath =
schematic()->Hierarchy().GetSheetPathByKIIDPath(
path ) )
1592 return sheetPath->LastScreen();
1597 if( std::optional<SCH_SHEET_PATH> current =
m_context->GetCurrentSheet() )
1598 return current->LastScreen();
1610 return std::nullopt;
1617 return screen->GetPageSettings();
1619 return std::nullopt;
1627 screen->SetPageSettings( aPageInfo );
1628 screen->SetContentModified();
1659 else if(
schematic()->GetCurrentScreen() )
1673static std::optional<ApiResponseStatus>
1677 aJob.
m_drawingSheet = wxString::FromUTF8( aSettings.drawing_sheet() );
1678 aJob.
m_defaultFont = wxString::FromUTF8( aSettings.default_font() );
1679 aJob.
m_variant = wxString::FromUTF8( aSettings.variant() );
1686 aJob.
m_theme = wxString::FromUTF8( aSettings.theme() );
1690 for(
const std::string& page : aSettings.plot_pages() )
1691 aJob.
m_plotPages.push_back( wxString::FromUTF8( page ) );
1693 if( aSettings.page_size() != schematic::jobs::SchematicJobPageSize::SJPS_UNKNOWN )
1696 switch( aSettings.sheet_mode() )
1698 case schematic::jobs::SJSM_ALL_SHEETS: aJob.
m_plotAll =
true;
break;
1699 case schematic::jobs::SJSM_SINGLE_SHEET: aJob.
m_plotAll =
false;
break;
1700 case schematic::jobs::SJSM_UNKNOWN:
1704 if( aDocument.has_sheet_path() )
1707 return std::nullopt;
1716 if( !documentValidation )
1717 return tl::unexpected( documentValidation.error() );
1719 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1720 return tl::unexpected( *busy );
1722 auto plotJob = std::make_unique<JOB_EXPORT_SCH_PLOT_SVG>( aCtx.
Request.plot_settings().sheet_mode()
1723 != schematic::jobs::SJSM_SINGLE_SHEET );
1726 if( !aCtx.
Request.job_settings().output_path().empty() )
1727 plotJob->SetConfiguredOutputPath( wxString::FromUTF8( aCtx.
Request.job_settings().output_path() ) );
1732 return tl::unexpected( *err );
1744 if( !documentValidation )
1745 return tl::unexpected( documentValidation.error() );
1747 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1748 return tl::unexpected( *busy );
1750 auto plotJob = std::make_unique<JOB_EXPORT_SCH_PLOT_DXF>( aCtx.
Request.plot_settings().sheet_mode()
1751 != schematic::jobs::SJSM_SINGLE_SHEET );
1755 if( !aCtx.
Request.job_settings().output_path().empty() )
1756 plotJob->SetConfiguredOutputPath( wxString::FromUTF8( aCtx.
Request.job_settings().output_path() ) );
1761 return tl::unexpected( *err );
1773 if( !documentValidation )
1774 return tl::unexpected( documentValidation.error() );
1776 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1777 return tl::unexpected( *busy );
1779 auto plotJob = std::make_unique<JOB_EXPORT_SCH_PLOT_PDF>(
false );
1782 if( !aCtx.
Request.job_settings().output_path().empty() )
1783 plotJob->SetConfiguredOutputPath( wxString::FromUTF8( aCtx.
Request.job_settings().output_path() ) );
1788 return tl::unexpected( *err );
1792 plotJob->m_PDFHierarchicalLinks = aCtx.
Request.hierarchical_links();
1804 if( !documentValidation )
1805 return tl::unexpected( documentValidation.error() );
1807 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1808 return tl::unexpected( *busy );
1810 auto plotJob = std::make_unique<JOB_EXPORT_SCH_PLOT_PS>( aCtx.
Request.plot_settings().sheet_mode()
1811 != schematic::jobs::SJSM_SINGLE_SHEET );
1814 if( !aCtx.
Request.job_settings().output_path().empty() )
1815 plotJob->SetConfiguredOutputPath( wxString::FromUTF8( aCtx.
Request.job_settings().output_path() ) );
1820 return tl::unexpected( *err );
1831 return tl::unexpected( validation.error() );
1833 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1834 return tl::unexpected( *busy );
1836 const schematic::jobs::SchematicJobSheetMode sheetMode = aCtx.
Request.plot_settings().sheet_mode();
1838 auto plotJob = std::make_unique<JOB_EXPORT_SCH_PLOT_PNG>( sheetMode != schematic::jobs::SJSM_SINGLE_SHEET );
1841 if( !aCtx.
Request.job_settings().output_path().empty() )
1842 plotJob->SetConfiguredOutputPath( wxString::FromUTF8( aCtx.
Request.job_settings().output_path() ) );
1847 return tl::unexpected( *err );
1856 ApiResponseStatus status;
1857 status.set_status( ApiStatusCode::AS_BAD_REQUEST );
1859 return tl::unexpected( status );
1866 plotJob->m_antialias = aCtx.
Request.antialiasing() != types::AntialiasingMode::AAM_NONE;
1867 plotJob->m_useBackgroundColor = aCtx.
Request.plot_background_color();
1878 if( !documentValidation )
1879 return tl::unexpected( documentValidation.error() );
1881 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1882 return tl::unexpected( *busy );
1884 if( aCtx.
Request.format() == kiapi::schematic::jobs::SchematicNetlistFormat::SNF_UNKNOWN )
1886 ApiResponseStatus e;
1887 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1888 e.set_error_message(
"RunSchematicJobExportNetlist requires a valid format" );
1889 return tl::unexpected( e );
1895 if( !aCtx.
Request.job_settings().output_path().empty() )
1900 if( !aCtx.
Request.variant_name().empty() )
1912 if( !documentValidation )
1913 return tl::unexpected( documentValidation.error() );
1915 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1916 return tl::unexpected( *busy );
1921 if( !aCtx.
Request.job_settings().output_path().empty() )
1939 ApiResponseStatus e;
1940 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1941 e.set_error_message(
"A list of fields fields or a fields preset are required" );
1942 return tl::unexpected( e );
1945 switch( aCtx.
Request.fields().filter_scope() )
1947 case kiapi::schematic::jobs::BOMFilterScope::BFS_VISIBLE:
1951 case kiapi::schematic::jobs::BOMFilterScope::BFS_ALL:
1955 case kiapi::schematic::jobs::BOMFilterScope::BFS_REFERENCE:
1961 if( aCtx.
Request.fields().sort_direction() == kiapi::schematic::jobs::BOMSortDirection::BSD_ASCENDING )
1965 else if( aCtx.
Request.fields().sort_direction() == kiapi::schematic::jobs::BOMSortDirection::BSD_DESCENDING )
1970 for(
const kiapi::schematic::jobs::BOMField& field : aCtx.
Request.fields().fields() )
1972 bomJob.
m_fieldsOrdered.emplace_back( wxString::FromUTF8( field.name() ) );
1973 bomJob.
m_fieldsLabels.emplace_back( wxString::FromUTF8( field.label() ) );
1975 if( field.group_by() )
1976 bomJob.
m_fieldsGroupBy.emplace_back( wxString::FromUTF8( field.name() ) );
1982 if( !aCtx.
Request.variant_name().empty() )
1998 if( sheetName.IsEmpty() && aSheet->
GetScreen() )
2001 sheetName = fn.GetName();
2004 aInstance->set_name( sheetName.ToUTF8() );
2005 aInstance->set_filename( aSheet->
GetFileName().ToUTF8() );
2006 aInstance->set_page_number( aPath.
GetPageNumber().ToUTF8() );
2010 std::vector<SCH_ITEM*> childSheets;
2013 std::ranges::sort( childSheets,
2025 for(
SCH_ITEM* childItem : childSheets )
2028 kiapi::schematic::types::SheetInstance* childInstance = aInstance->add_children();
2042 if( !documentValidation )
2043 return tl::unexpected( documentValidation.error() );
2045 kiapi::schematic::commands::SchematicHierarchyResponse response;
2046 response.mutable_document()->CopyFrom( aCtx.
Request.document() );
2054 std::ranges::sort( topLevelSheets,
2066 for(
SCH_SHEET* topSheet : topLevelSheets )
2068 kiapi::schematic::types::SheetInstance* instance = response.add_top_level_sheets();
2084 ApiResponseStatus status;
2085 status.set_status( ApiStatusCode::AS_BUSY );
2086 status.set_error_message(
"Cannot rebuild connectivity during an interactive operation" );
2087 return tl::unexpected( status );
2092 if( !documentValidation )
2093 return tl::unexpected( documentValidation.error() );
2095 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2096 return tl::unexpected( *busy );
2099 const bool filterByType = aCtx.
Request.types_size() > 0;
2101 static const std::set<KICAD_T> s_netlistTypes = {
2116 std::set<KICAD_T> typeFilter(
types.begin(),
types.end() );
2117 std::erase_if( typeFilter, [](
KICAD_T aType ) {
return !s_netlistTypes.contains( aType ); } );
2119 if( filterByType && typeFilter.empty() )
2121 ApiResponseStatus e;
2122 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2123 e.set_error_message(
"none of the requested types are valid for a netlist object" );
2124 return tl::unexpected( e );
2129 if( !connectionGraph )
2131 ApiResponseStatus e;
2132 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2133 e.set_error_message(
"schematic has no connection graph" );
2134 return tl::unexpected( e );
2143 catch(
const std::exception& error )
2147 m_frame->ShowInfoBarError(
_(
"Unable to rebuild schematic connectivity." ),
true );
2151 wxLogTrace(
traceApi, wxS(
"GetSchematicNetlist rebuild failed: %s" ),
2152 wxString::FromUTF8( error.what() ) );
2154 ApiResponseStatus status;
2155 status.set_status( ApiStatusCode::AS_UNKNOWN );
2156 status.set_error_message( error.what() );
2157 return tl::unexpected( status );
2161 kiapi::schematic::commands::SchematicNetlistResponse response;
2162 response.mutable_document()->CopyFrom( aCtx.
Request.document() );
2166 for(
const auto&
group :
schematic()->Connectivity().GetNetMap() )
2168 if(
group.instances.empty() || !
group.instances.front().IsNet()
2169 || !
group.instances.front().Driver() )
2174 kiapi::schematic::types::SchematicNet* net =
nullptr;
2176 for(
const auto& view :
group.instances )
2178 const auto physicalItems = view.Items();
2180 if( physicalItems.empty() )
2185 net = response.add_nets();
2186 net->set_name(
group.name.ToUTF8() );
2189 auto* sheet = net->add_sheets();
2192 for(
SCH_ITEM* item : physicalItems )
2194 if( !filterByType || typeFilter.contains( item->Type() ) )
2195 sheet->add_items()->set_value( item->m_Uuid.AsStdString() );
2203 for(
const auto& [key, subgraphList] : connectionGraph->
GetNetMap() )
2205 if( subgraphList.empty() )
2216 kiapi::schematic::types::SchematicNet* net = response.add_nets();
2217 net->set_name( key.Name.ToUTF8() );
2221 kiapi::schematic::types::SchematicNetSheetContents* sheetContents = net->add_sheets();
2222 PackSheetPath( *sheetContents->mutable_path(), subGraph->GetSheet() );
2224 for(
SCH_ITEM* item : subGraph->GetItems() )
2226 if( filterByType && !typeFilter.contains( item->Type() ) )
2229 sheetContents->add_items()->set_value( item->m_Uuid.AsStdString() );
2242 wxLogTrace(
traceApi,
"Received announce from frame %d at %s",
2248 CrossProbeAnnounceResponse response;
2249 response.set_status( CPS_OK );
2255 std::unordered_map<wxString, std::vector<SCH_REFERENCE>>& aSyncSymMap,
2256 std::unordered_map<wxString, std::unordered_map<wxString, SCH_PIN*>>& aSyncPinMap,
2257 const wxString& aVariantName = wxEmptyString,
bool aRecursive =
false )
2267 findSymbolsAndPins( aSchematicSheetList, candidate, aSyncSymMap, aSyncPinMap, aVariantName, aRecursive );
2275 for(
unsigned ii = 0; ii < references.
GetCount(); ii++ )
2284 wxString fullRef = schRef.
GetRef() + refNum;
2287 if( fullRef.StartsWith( wxS(
"#" ) ) )
2291 if( refNum.compare( wxS(
"?" ) ) == 0 )
2295 auto symMatchIt = aSyncSymMap.find( fullRef );
2297 if( symMatchIt != aSyncSymMap.end() )
2299 symMatchIt->second.emplace_back( schRef );
2306 auto symPinMatchIt = aSyncPinMap.find( fullRef );
2308 if( symPinMatchIt != aSyncPinMap.end() )
2310 std::unordered_map<wxString, SCH_PIN*>& pinMap = symPinMatchIt->second;
2311 std::vector<SCH_PIN*> pinsOnSheet = symbol->
GetPins( &aSheetPath );
2315 int pinUnit =
pin->GetLibPin() ?
pin->GetLibPin()->GetUnit() :
ALL_UNITS;
2317 if( pinUnit > 0 && pinUnit != schRef.
GetUnit() )
2322 for(
const wxString&
pad :
2325 auto pinIt = pinMap.find(
pad );
2327 if( pinIt != pinMap.end() )
2329 pinIt->second =
pin;
2343 std::unordered_map<wxString, std::vector<SCH_REFERENCE>>& aSyncSymMap,
2344 std::unordered_map<wxString, std::unordered_map<wxString, SCH_PIN*>>& aSyncPinMap,
2345 std::unordered_map<SCH_SHEET_PATH, bool>& aCache )
2347 auto cacheIt = aCache.find( aSheetPath );
2349 if( cacheIt != aCache.end() )
2350 return cacheIt->second;
2359 aSyncPinMap, aCache );
2363 aCache.emplace( aSheetPath,
false );
2373 aCache.emplace( aSheetPath,
false );
2377 for(
unsigned ii = 0; ii < references.
GetCount(); ii++ )
2385 wxString fullRef = schRef.
GetRef() + refNum;
2388 if( fullRef.StartsWith( wxS(
"#" ) ) )
2392 if( refNum.compare( wxS(
"?" ) ) == 0 )
2395 if( aSyncSymMap.find( fullRef ) == aSyncSymMap.end() )
2397 aCache.emplace( aSheetPath,
false );
2401 if( aSyncPinMap.find( fullRef ) != aSyncPinMap.end() )
2403 aCache.emplace( aSheetPath,
false );
2408 aCache.emplace( aSheetPath,
true );
2413std::optional<std::tuple<SCH_SHEET_PATH, SCH_ITEM*, std::vector<SCH_ITEM*>>>
2415 const kiapi::common::commands::SyncSelection& aSync )
2417 std::unordered_map<wxString, std::vector<SCH_REFERENCE>> syncSymMap;
2418 std::unordered_map<wxString, std::unordered_map<wxString, SCH_PIN*>> syncPinMap;
2419 std::unordered_map<SCH_SHEET_PATH, bool> fullyWantedCache;
2421 std::optional<wxString> focusSymbol;
2422 std::optional<std::pair<wxString, wxString>> focusPin;
2423 std::unordered_map<SCH_SHEET_PATH, std::vector<SCH_ITEM*>> focusItemResults;
2428 std::vector<SCH_SHEET_PATH> orderedSheets;
2429 orderedSheets.reserve( allSheetsList.size() );
2435 orderedSheets.push_back( sheetPath );
2438 const bool focusOnFirst = ( aSync.mode() == kiapi::common::commands::SSM_ITEMS_AND_NETS ) && aSync.has_focus_item();
2440 for(
const kiapi::common::commands::SelectionSpec& spec : aSync.items() )
2442 switch( spec.spec_case() )
2444 case kiapi::common::commands::SelectionSpec::kFootprint:
2446 wxString symRef = wxString::FromUTF8( spec.footprint().reference() );
2447 syncSymMap[symRef] = std::vector<SCH_REFERENCE>();
2451 case kiapi::common::commands::SelectionSpec::kPad:
2453 wxString symRef = wxString::FromUTF8( spec.pad().reference() );
2454 wxString padNum = wxString::FromUTF8( spec.pad().number() );
2455 syncPinMap[symRef][padNum] =
nullptr;
2466 const kiapi::common::commands::SelectionSpec& focusSpec = aSync.focus_item();
2468 if( focusSpec.has_footprint() )
2469 focusSymbol = wxString::FromUTF8( focusSpec.footprint().reference() );
2470 else if( focusSpec.has_pad() )
2471 focusPin = std::make_pair( wxString::FromUTF8( focusSpec.pad().reference() ),
2472 wxString::FromUTF8( focusSpec.pad().number() ) );
2476 auto flattenSyncMaps =
2477 [&syncSymMap, &syncPinMap]() -> std::vector<SCH_ITEM*>
2479 std::vector<SCH_ITEM*> allVec;
2481 for(
const auto& [symRef, symbols] : syncSymMap )
2484 allVec.push_back( ref.GetSymbol() );
2487 for(
const auto& [symRef, pinMap] : syncPinMap )
2489 for(
const auto& [padNum,
pin] : pinMap )
2492 allVec.push_back(
pin );
2499 auto clearSyncMaps =
2500 [&syncSymMap, &syncPinMap]()
2502 for(
auto& [symRef, symbols] : syncSymMap )
2505 for(
auto& [reference, pins] : syncPinMap )
2507 for(
auto& [number,
pin] : pins )
2512 auto syncMapsValuesEmpty =
2513 [&syncSymMap, &syncPinMap]() ->
bool
2515 for(
const auto& [symRef, symbols] : syncSymMap )
2517 if( symbols.size() > 0 )
2521 for(
const auto& [symRef, pins] : syncPinMap )
2523 for(
const auto& [padNum,
pin] : pins )
2533 auto checkFocusItems =
2538 auto findIt = syncSymMap.find( *focusSymbol );
2540 if( findIt != syncSymMap.end() )
2542 if( findIt->second.size() > 0 )
2543 focusItemResults[aSheet].push_back( findIt->second.front().GetSymbol() );
2548 auto findIt = syncPinMap.find( focusPin->first );
2550 if( findIt != syncPinMap.end() )
2552 if( findIt->second[focusPin->second] )
2553 focusItemResults[aSheet].push_back( findIt->second[focusPin->second] );
2558 auto makeRetForSheet =
2565 std::vector<SCH_ITEM*> itemsVector = flattenSyncMaps();
2571 kiidPath.push_back( item->m_Uuid );
2573 std::optional<SCH_SHEET_PATH> subsheetPath =
2580 syncPinMap, fullyWantedCache ) )
2582 itemsVector.push_back( item );
2586 return std::make_tuple( aSheet, aFocusItem, itemsVector );
2597 checkFocusItems( sheetPath );
2600 if( focusItemResults.size() > 0 )
2604 const std::vector<SCH_ITEM*>& items = focusItemResults[sheetPath];
2606 if( !items.empty() )
2607 return makeRetForSheet( sheetPath, items.front() );
2619 if( !syncMapsValuesEmpty() )
2622 return makeRetForSheet( sheetPath,
nullptr );
2627 return std::nullopt;
2634 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"SyncSelection" ) )
2635 return tl::unexpected( *headless );
2637 SyncSelectionResponse response;
2641 if( !settings.
on_selection && aCtx.
Request.context() != SyncSelectionContext::SSC_EXPLICIT )
2643 response.set_status( CPS_DISABLED );
2644 response.set_message(
"implicit selection sync disabled by user" );
2649 if( aCtx.
Request.items_size() == 0 )
2657 response.set_status( CPS_OK );
2661 std::optional<std::tuple<SCH_SHEET_PATH, SCH_ITEM*, std::vector<SCH_ITEM*>>> findRet =
2666 auto& [sheetPath, focusItem, items] = *findRet;
2674 if(
frame()->eeconfig()->m_CrossProbing.flash_selection )
2685 std::vector<SCH_ITEM*> itemPtrs;
2686 std::copy( items.begin(), items.end(), std::back_inserter( itemPtrs ) );
2697 response.set_status( CPS_OK );
2705 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"HighlightNets" ) )
2706 return tl::unexpected( *headless );
2708 HighlightNetsResponse response;
2716 response.set_status( CPS_DISABLED );
2723 if( aCtx.
Request.net_name_size() > 0 )
2724 net = wxString::FromUTF8( aCtx.
Request.net_name( 0 ) );
2728 response.set_status( CPS_OK );
2739 if( !documentValidation )
2740 return tl::unexpected( documentValidation.error() );
2744 if( aCtx.
Request.document().has_sheet_path() )
2748 if( std::optional<SCH_SHEET_PATH> resolvedPath =
schematic()->Hierarchy().GetSheetPathByKIIDPath( kiidPath ) )
2750 path = *resolvedPath;
2754 ExpandTextVariablesResponse reply;
2756 std::function<bool( wxString* )> textResolver =
2757 [&]( wxString* token ) ->
bool
2764 for(
const std::string& textMsg : aCtx.
Request.text() )
2768 if( aCtx.
Request.expand_env_vars() )
2771 reply.add_text(
text.ToUTF8() );
2781 return tl::unexpected( documentValidation.error() );
2783 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2784 return tl::unexpected( *busy );
2786 VariantsResponse response;
2788 response.mutable_document()->CopyFrom( aCtx.
Request.document() );
2790 for(
const wxString&
name :
schematic()->GetVariantNames() )
2792 types::DesignVariant* var = response.add_variants();
2793 var->set_name(
name.ToUTF8() );
2794 var->set_description(
schematic()->GetVariantDescription(
name ).ToUTF8() );
2804 return tl::unexpected( documentValidation.error() );
2806 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2807 return tl::unexpected( *busy );
2810 wxString
name = wxString::FromUTF8( aCtx.
Request.name() );
2814 ApiResponseStatus e;
2815 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2816 e.set_error_message( fmt::format(
"'{}' is not a usable new variant name", aCtx.
Request.name() ) );
2817 return tl::unexpected( e );
2827 if( aCtx.
Request.has_description() )
2850 return tl::unexpected( documentValidation.error() );
2852 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2853 return tl::unexpected( *busy );
2856 wxString
name = wxString::FromUTF8( aCtx.
Request.name() );
2860 ApiResponseStatus e;
2861 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2862 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.name() ) );
2863 return tl::unexpected( e );
2868 ApiResponseStatus e;
2869 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2870 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.name() ) );
2871 return tl::unexpected( e );
2876 bool pushedCommit =
false;
2883 if( !commit.
Empty() )
2886 pushedCommit =
true;
2900 if(
frame()->Schematic().GetCurrentVariant().CmpNoCase(
name ) == 0 )
2914 return tl::unexpected( documentValidation.error() );
2916 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2917 return tl::unexpected( *busy );
2920 wxString oldName = wxString::FromUTF8( aCtx.
Request.old_name() );
2921 wxString newName = wxString::FromUTF8( aCtx.
Request.new_name() );
2925 ApiResponseStatus e;
2926 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2927 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.old_name() ) );
2928 return tl::unexpected( e );
2933 ApiResponseStatus e;
2934 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2935 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.new_name() ) );
2936 return tl::unexpected( e );
2941 ApiResponseStatus e;
2942 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2943 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.old_name() ) );
2944 return tl::unexpected( e );
2949 ApiResponseStatus e;
2950 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2951 e.set_error_message( fmt::format(
"a variant named '{}' already exists", aCtx.
Request.new_name() ) );
2952 return tl::unexpected( e );
2959 bool pushedCommit =
false;
2962 oldName = *canonicalOld;
2964 schematic->RenameVariant( oldName, newName, &commit );
2966 if( !commit.
Empty() )
2969 pushedCommit =
true;
3001 return tl::unexpected( documentValidation.error() );
3003 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3004 return tl::unexpected( *busy );
3007 wxString oldName = wxString::FromUTF8( aCtx.
Request.old_name() );
3008 wxString newName = wxString::FromUTF8( aCtx.
Request.new_name() );
3012 ApiResponseStatus e;
3013 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3014 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.old_name() ) );
3015 return tl::unexpected( e );
3020 ApiResponseStatus e;
3021 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3022 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.new_name() ) );
3023 return tl::unexpected( e );
3028 ApiResponseStatus e;
3029 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3030 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.old_name() ) );
3031 return tl::unexpected( e );
3036 ApiResponseStatus e;
3037 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3038 e.set_error_message( fmt::format(
"a variant named '{}' already exists", aCtx.
Request.new_name() ) );
3039 return tl::unexpected( e );
3044 bool pushedCommit =
false;
3047 oldName = *canonicalOld;
3049 schematic->CopyVariant( oldName, newName, &commit );
3051 if( aCtx.
Request.has_new_description() )
3052 schematic->SetVariantDescription( newName, wxString::FromUTF8( aCtx.
Request.new_description() ) );
3054 if( !commit.
Empty() )
3057 pushedCommit =
true;
3081 return tl::unexpected( documentValidation.error() );
3083 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3084 return tl::unexpected( *busy );
3087 wxString
name = wxString::FromUTF8( aCtx.
Request.name() );
3091 ApiResponseStatus e;
3092 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3093 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.name() ) );
3094 return tl::unexpected( e );
3120 return tl::unexpected( documentValidation.error() );
3122 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3123 return tl::unexpected( *busy );
3131 ApiResponseStatus e;
3132 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3133 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.name() ) );
3134 return tl::unexpected( e );
3138 wxString
name = aCtx.
Request.has_name() ? wxString::FromUTF8( aCtx.
Request.name() ) : wxString();
3156 return tl::unexpected( documentValidation.error() );
3158 CurrentVariantResponse response;
3160 if( wxString current =
schematic()->GetCurrentVariant(); !current.
IsEmpty() )
3161 response.set_name( current.ToUTF8() );
3172 ApiResponseStatus e;
3173 e.set_status( ApiStatusCode::AS_UNHANDLED );
3174 return tl::unexpected( e );
3177 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3178 return tl::unexpected( *busy );
3184 ApiResponseStatus e;
3185 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3186 e.set_error_message(
"lib_id must specify both a library nickname and an entry name" );
3187 return tl::unexpected( e );
3195 ApiResponseStatus e;
3196 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3197 e.set_error_message( fmt::format(
"symbol '{}' not found", libId.
Format().
wx_str() ) );
3198 return tl::unexpected( e );
3204 if( aCtx.
Request.header().document().has_sheet_path() )
3214 ApiResponseStatus e;
3215 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3216 e.set_error_message( fmt::format(
"the requested sheet path {} is not valid for this schematic",
3218 return tl::unexpected( e );
3224 int unit = aCtx.
Request.has_unit() ? aCtx.
Request.unit().unit() : 1;
3228 ApiResponseStatus e;
3229 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3230 e.set_error_message( fmt::format(
"unit {} is out of range for symbol '{}' ({} units)", unit,
3232 return tl::unexpected( e );
3237 std::unique_ptr<SCH_SYMBOL> symbol(
3238 std::make_unique<SCH_SYMBOL>( *libSymbol, libId, &targetPath, unit, 0, position ) );
3240 if( aCtx.
Request.has_orientation() )
3243 if( !aCtx.
Request.reference().empty() )
3245 symbol->SetRef( &targetPath, wxString::FromUTF8( aCtx.
Request.reference() ) );
3256 annotate |=
frame->eeconfig()->m_AnnotatePanel.automatic;
3267 schematic()->Settings().m_AnnotateStartNum, existingRefs,
false, &hierarchy );
3274 if(
frame->eeconfig()->m_AutoplaceFields.enable )
3280 commit->
Add( placed, targetScreen );
3285 PlaceFromLibraryResponse response;
3286 response.mutable_header()->CopyFrom( aCtx.
Request.header() );
3288 kiapi::schematic::types::SchematicSymbolInstance packed;
3290 if(
PackSymbol( &packed, placed, targetPath ) )
3291 response.mutable_item()->PackFrom( packed );
KICOMMON_API KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
tl::expected< T, ApiResponseStatus > HANDLER_RESULT
static std::optional< ApiResponseStatus > applySchematicPlotSettings(const schematic::jobs::SchematicPlotSettings &aSettings, const types::DocumentSpecifier &aDocument, JOB_EXPORT_SCH_PLOT &aJob)
HANDLER_RESULT< types::RunJobResponse > ExecuteSchematicJob(KIWAY *aKiway, JOB &aJob)
bool findSymbolsAndPins(const SCH_SHEET_LIST &aSchematicSheetList, const SCH_SHEET_PATH &aSheetPath, std::unordered_map< wxString, std::vector< SCH_REFERENCE > > &aSyncSymMap, std::unordered_map< wxString, std::unordered_map< wxString, SCH_PIN * > > &aSyncPinMap, const wxString &aVariantName=wxEmptyString, bool aRecursive=false)
std::optional< std::tuple< SCH_SHEET_PATH, SCH_ITEM *, std::vector< SCH_ITEM * > > > findItemsFromSyncSelection(const SCHEMATIC &aSchematic, const kiapi::common::commands::SyncSelection &aSync)
bool sheetContainsOnlyWantedItems(const SCH_SHEET_LIST &aSchematicSheetList, const SCH_SHEET_PATH &aSheetPath, std::unordered_map< wxString, std::vector< SCH_REFERENCE > > &aSyncSymMap, std::unordered_map< wxString, std::unordered_map< wxString, SCH_PIN * > > &aSyncPinMap, std::unordered_map< SCH_SHEET_PATH, bool > &aCache)
std::unique_ptr< EDA_ITEM > CreateItemForType(KICAD_T aType, EDA_ITEM *aContainer)
tl::expected< bool, ApiResponseStatus > UnpackSheet(SCH_SHEET *aOutput, const kiapi::schematic::types::SheetSymbol &aInput)
Unpack the every placement data from the input.
bool ApplySymbolInstance(kiapi::common::commands::ItemStatus *aStatus, SCH_SYMBOL *aSymbol, const kiapi::schematic::types::SchematicSymbolInstance &aInput, const SCH_SHEET_PATH &aPath, SCHEMATIC *aSchematic)
Apply placement-specific data to an aSymbol at aPath: reference, unit, and the per-placement attribut...
std::optional< wxString > FindVariantNoCase(const SCHEMATIC *aSchematic, const wxString &aName)
Variant names are stored and compared exactly, but SCHEMATIC::HasVariant matches case-insensitively.
bool PackSheet(kiapi::schematic::types::SheetSymbol *aOutput, const SCH_SHEET *aInput, const SCH_SHEET_PATH &aPath)
bool ApplySheetInstance(commands::ItemStatus *aStatus, SCH_SHEET *aSheet, const kiapi::schematic::types::SheetSymbol &aInput, const SCH_SHEET_PATH &aParentPath, SCHEMATIC *aSchematic)
bool PackSymbol(kiapi::schematic::types::SchematicSymbolInstance *aOutput, const SCH_SYMBOL *aInput, const SCH_SHEET_PATH &aPath)
tl::expected< SCH_FOCUS_TARGET, ApiResponseStatus > ResolveFocusItems(SCHEMATIC &aSchematic, const std::vector< KIID > &aIds, const std::optional< KIID_PATH > &aSheetPath)
Resolve the items of a FocusOnItems request to the sheet that shows them and their combined bounding ...
bool UnpackSymbol(SCH_SYMBOL *aOutput, const kiapi::schematic::types::SchematicSymbolInstance &aInput)
Unpack the geometry, the library definition, fields, and the default-variant attributes that are shar...
BASE_SCREEN class implementation.
constexpr EDA_IU_SCALE schIUScale
static TOOL_ACTION selectionClear
Clear the current selection.
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
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)
API_HANDLER_EDITOR(EDA_BASE_FRAME *aFrame=nullptr)
static std::vector< KICAD_T > parseRequestedItemTypes(const google::protobuf::RepeatedField< int > &aTypes)
COMMIT * getCurrentCommit(const std::string &aClientName)
virtual void pushCurrentCommit(const std::string &aClientName, const wxString &aMessage)
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< types::RunJobResponse > handleRunSchematicJobExportDxf(const HANDLER_CONTEXT< kiapi::schematic::jobs::RunSchematicJobExportDxf > &aCtx)
HANDLER_RESULT< Empty > handleFocusOnItems(const HANDLER_CONTEXT< commands::FocusOnItems > &aCtx)
wxString getDrawingSheetFileName() override
HANDLER_RESULT< types::RunJobResponse > handleRunSchematicJobExportPng(const HANDLER_CONTEXT< kiapi::schematic::jobs::RunSchematicJobExportPng > &aCtx)
HANDLER_RESULT< Empty > handleSetCurrentVariant(const HANDLER_CONTEXT< commands::SetCurrentVariant > &aCtx)
HANDLER_RESULT< kiapi::schematic::commands::SchematicHierarchyResponse > handleGetSchematicHierarchy(const HANDLER_CONTEXT< kiapi::schematic::commands::GetSchematicHierarchy > &aCtx)
HANDLER_RESULT< commands::VariantsResponse > handleGetVariants(const HANDLER_CONTEXT< commands::GetVariants > &aCtx)
std::unique_ptr< COMMIT > createCommit() override
Override this to create an appropriate COMMIT subclass for the frame in question.
SCHEMATIC * schematic() const
HANDLER_RESULT< commands::SelectionResponse > handleGetSelection(const HANDLER_CONTEXT< commands::GetSelection > &aCtx)
HANDLER_RESULT< Empty > handleCopyVariant(const HANDLER_CONTEXT< commands::CopyVariant > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunSchematicJobExportPdf(const HANDLER_CONTEXT< kiapi::schematic::jobs::RunSchematicJobExportPdf > &aCtx)
SCH_SCREEN * resolveScreenFromDocument(const DocumentSpecifier &aDocument) const
Returns the sheet path's screen when one is given and it is found, or null.
HANDLER_RESULT< commands::CurrentVariantResponse > handleGetCurrentVariant(const HANDLER_CONTEXT< commands::GetCurrentVariant > &aCtx)
static std::set< KICAD_T > s_allowedTypes
HANDLER_RESULT< commands::GetItemsResponse > handleGetItemsById(const HANDLER_CONTEXT< commands::GetItemsById > &aCtx)
HANDLER_RESULT< google::protobuf::Empty > handleSaveDocument(const HANDLER_CONTEXT< commands::SaveDocument > &aCtx)
std::optional< PAGE_INFO > getPageSettings(const DocumentSpecifier &aDocument) override
HANDLER_RESULT< kiapi::schematic::commands::SchematicNetlistResponse > handleGetSchematicNetlist(const HANDLER_CONTEXT< kiapi::schematic::commands::GetSchematicNetlist > &aCtx)
std::optional< SCH_ITEM * > getItemById(const KIID &aId, SCH_SHEET_PATH *aPathOut=nullptr) const
std::shared_ptr< SCH_CONTEXT > m_context
std::optional< EDA_ITEM * > getItemFromDocument(const DocumentSpecifier &aDocument, const KIID &aId) override
TOOL_MANAGER * toolManager() const
HANDLER_RESULT< types::RunJobResponse > handleRunSchematicJobExportSvg(const HANDLER_CONTEXT< kiapi::schematic::jobs::RunSchematicJobExportSvg > &aCtx)
HANDLER_RESULT< Empty > handleDeleteVariant(const HANDLER_CONTEXT< commands::DeleteVariant > &aCtx)
HANDLER_RESULT< Empty > handleClearSelection(const HANDLER_CONTEXT< commands::ClearSelection > &aCtx)
HANDLER_RESULT< commands::HighlightNetsResponse > handleHighlightNets(const HANDLER_CONTEXT< commands::HighlightNets > &aCtx)
std::optional< ApiResponseStatus > checkForHeadless(const std::string &aCommandName) const
bool setPageSettings(const DocumentSpecifier &aDocument, const PAGE_INFO &aPageInfo) override
HANDLER_RESULT< commands::SavedSelectionResponse > handleSaveSelectionToString(const HANDLER_CONTEXT< commands::SaveSelectionToString > &aCtx)
HANDLER_RESULT< commands::CrossProbeAnnounceResponse > handleCrossProbeAnnounce(const HANDLER_CONTEXT< commands::CrossProbeAnnounce > &aCtx)
HANDLER_RESULT< std::unique_ptr< EDA_ITEM > > createItemForType(KICAD_T aType, EDA_ITEM *aContainer)
HANDLER_RESULT< kiapi::common::commands::PlaceFromLibraryResponse > handlePlaceSymbolFromLibrary(const HANDLER_CONTEXT< kiapi::schematic::commands::PlaceSymbolFromLibrary > &aCtx)
HANDLER_RESULT< commands::GetDocumentModifiedStateResponse > handleGetDocumentModifiedState(const HANDLER_CONTEXT< commands::GetDocumentModifiedState > &aCtx) override
HANDLER_RESULT< Empty > handleRenameVariant(const HANDLER_CONTEXT< commands::RenameVariant > &aCtx)
void filterValidSchTypes(std::set< KICAD_T > &aTypeList)
std::optional< TITLE_BLOCK * > getTitleBlock(const DocumentSpecifier &aDocument) override
HANDLER_RESULT< types::RunJobResponse > handleRunSchematicJobExportBOM(const HANDLER_CONTEXT< kiapi::schematic::jobs::RunSchematicJobExportBOM > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunSchematicJobExportPs(const HANDLER_CONTEXT< kiapi::schematic::jobs::RunSchematicJobExportPs > &aCtx)
HANDLER_RESULT< commands::SavedDocumentResponse > handleSaveDocumentToString(const HANDLER_CONTEXT< commands::SaveDocumentToString > &aCtx)
PROJECT & project() const
void onModified() override
API_HANDLER_SCH(SCH_EDIT_FRAME *aFrame)
bool packSchItem(google::protobuf::Any &aOut, SCH_ITEM *aItem, const SCH_SHEET_PATH &aPath)
Serializes a schematic item into aOut, using path-aware packing for symbols and sheets.
HANDLER_RESULT< Empty > handleAddVariant(const HANDLER_CONTEXT< commands::AddVariant > &aCtx)
kiapi::common::types::DocumentType thisDocumentType() const override
Override this to specify which document type this editor handles.
HANDLER_RESULT< types::ItemRequestStatus > handleCreateUpdateItemsInternal(bool aCreate, const std::string &aClientName, const types::ItemHeader &aHeader, const google::protobuf::RepeatedPtrField< google::protobuf::Any > &aItems, std::function< void(commands::ItemStatus, google::protobuf::Any)> aItemHandler) override
HANDLER_RESULT< commands::GetOpenDocumentsResponse > handleGetOpenDocuments(const HANDLER_CONTEXT< commands::GetOpenDocuments > &aCtx)
HANDLER_RESULT< types::RunJobResponse > handleRunSchematicJobExportNetlist(const HANDLER_CONTEXT< kiapi::schematic::jobs::RunSchematicJobExportNetlist > &aCtx)
HANDLER_RESULT< google::protobuf::Empty > handleRevertDocument(const HANDLER_CONTEXT< commands::RevertDocument > &aCtx)
HANDLER_RESULT< commands::SelectionResponse > handleAddToSelection(const HANDLER_CONTEXT< commands::AddToSelection > &aCtx)
HANDLER_RESULT< commands::SelectionResponse > handleRemoveFromSelection(const HANDLER_CONTEXT< commands::RemoveFromSelection > &aCtx)
void onNetSettingsChanged() override
Called on all registered handlers after project net settings (netclasses or netclass assignments) hav...
HANDLER_RESULT< commands::ExpandTextVariablesResponse > handleExpandTextVariables(const HANDLER_CONTEXT< commands::ExpandTextVariables > &aCtx)
void deleteItemsInternal(std::map< KIID, ItemDeletionStatus > &aItemsToDelete, const std::string &aClientName) override
void packSheetInstance(kiapi::schematic::types::SheetInstance *aInstance, SCH_SHEET_PATH &aPath, SCH_SHEET *aSheet)
tl::expected< bool, ApiResponseStatus > validateDocumentInternal(const DocumentSpecifier &aDocument) const override
HANDLER_RESULT< commands::SyncSelectionResponse > handleSyncSelection(const HANDLER_CONTEXT< commands::SyncSelection > &aCtx)
SCH_EDIT_FRAME * frame() const
HANDLER_RESULT< google::protobuf::Empty > handleSaveCopyOfDocument(const HANDLER_CONTEXT< commands::SaveCopyOfDocument > &aCtx)
SCH_CONTEXT * context() const
void setDrawingSheetFileName(const wxString &aFileName) override
HANDLER_RESULT< Empty > handleSetVariantDescription(const HANDLER_CONTEXT< commands::SetVariantDescription > &aCtx)
HANDLER_RESULT< commands::GetItemsResponse > handleGetItems(const HANDLER_CONTEXT< commands::GetItems > &aCtx)
HANDLER_RESULT< google::protobuf::Empty > handleSaveDocumentAs(const HANDLER_CONTEXT< commands::SaveDocumentAs > &aCtx)
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 SetContentModified(bool aModified=true)
Represent a set of changes (additions, deletions or modifications) of a data model (e....
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Calculate the connectivity of a schematic and generate netlists.
const NET_MAP & GetNetMap() const
A subgraph is a set of items that are electrically connected on a single sheet.
static PRIORITY GetDriverPriority(SCH_ITEM *aDriver)
Return the priority (higher is more important) of a candidate driver.
const SCH_CONNECTION * GetDriverConnection() const
static void RegisterPeer(FRAME_T aFrameType, const std::string &aSocketPath)
virtual void PushCommandToUndoList(PICKED_ITEMS_LIST *aItem)
Add a command to undo in the undo list.
virtual PICKED_ITEMS_LIST * PopCommandFromUndoList()
Return the last command to undo and remove it from list, nothing is deleted.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
virtual void FinalizeGroupDeserialization()
A base class for most all the KiCad significant classes used in schematics and boards.
KICAD_T Type() const
Returns the type of object.
virtual wxString GetFriendlyName() const
EE_TYPE OfType(KICAD_T aType) const
std::vector< wxString > m_variantNames
wxString m_stringDelimiter
wxString m_fieldDelimiter
bool m_includeByteOrderMark
std::vector< wxString > m_fieldsOrdered
wxString m_refRangeDelimiter
std::vector< wxString > m_fieldsLabels
std::vector< wxString > m_fieldsGroupBy
wxString m_bomFmtPresetName
BOM_FILTER_SCOPE m_filterScope
std::vector< wxString > m_variantNames
JOB_PAGE_SIZE m_pageSizeSelect
bool m_useBackgroundColor
std::vector< wxString > m_plotPages
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
wxString AsString() const
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
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.
Define a library symbol object.
int GetUnitCount() const override
Describe the page size and margins of a paper page on which to eventually print or plot.
A holder to handle information on schematic or board items.
void PushItem(const ITEM_PICKER &aItem)
Push aItem to the top of the list.
void SetDescription(const wxString &aDescription)
static SYMBOL_LIBRARY_ADAPTER * SymbolLibAdapter(PROJECT *aProject)
Accessor for project symbol library manager adapter.
Container for project specific data.
virtual const wxString GetProjectPath() const
Return the full path of the project.
virtual const wxString GetProjectName() const
Return the short name of the project.
wxString m_SchDrawingSheetFileName
Holds all the data relating to one schematic.
SCHEMATIC_SETTINGS & Settings() const
SCH_SCREEN * GetCurrentScreen() const
SCH_ITEM * ResolveItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr, bool aAllowNullptrReturn=false) const
SCH_SHEET_LIST Hierarchy() const
Return the full schematic flattened hierarchical sheet list.
SCH_SHEET * GetTopLevelSheet(int aIndex=0) const
wxString GetCurrentVariant() const
Return the current variant being edited.
CONNECTION_GRAPH * ConnectionGraph() const
SCH_SCREEN * RootScreen() const
Helper to retrieve the screen of the root sheet.
bool ResolveTextVar(const SCH_SHEET_PATH *aSheetPath, wxString *token, int aDepth) const
void RebuildConnectivity(std::function< void(SCH_ITEM *)> *aChangedItemHandler=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr, KIGFX::SCH_VIEW *aSchView=nullptr)
std::vector< SCH_SHEET * > GetTopLevelSheets() const
Get the list of top-level sheets.
SCH_SHEET_PATH & CurrentSheet() const
static TOOL_ACTION changeSheet
SCH_DRAW_PANEL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
EESCHEMA_SETTINGS * eeconfig() const
Commit for the schematic and symbol editors.
void RevertToCheckpoint(int aCheckpoint) override
void Push(const wxString &aMessage=wxEmptyString, int aCommitFlags=0) override
Execute the changes.
Schematic editor (Eeschema) main window.
void OnModify() override
Must be called after a schematic change in order to set the "modify" flag and update other data struc...
void RefreshConnectivity(bool aForce=false, const SCH_CONNECTIVITY::CHANGE_SET *aChanges=nullptr)
void SetCurrentVariant(const wxString &aVariantName)
void UpdateVariantSelectionCtrl(const wxArrayString &aVariantNames)
Update the variant name control on the main toolbar.
bool RecalculateConnections(SCH_COMMIT *aCommit, SCH_CLEANUP_FLAGS aCleanupFlags, PROGRESS_REPORTER *aProgressReporter=nullptr, bool aCleanupDone=false)
Generate the connection data for the entire schematic hierarchy.
SCH_SHEET_PATH & GetCurrentSheet() const
SCHEMATIC & Schematic() const
void LoadDrawingSheet()
Load the drawing sheet file.
void SetSyncingSelection(bool aSet)
void StartCrossProbeFlash(const std::vector< SCH_ITEM * > &aItems)
void HandleRemoteNetHighlight(const wxString &aNetName)
A set of SCH_ITEMs (i.e., without duplicates).
A SCH_IO derivation for loading schematic files using the new s-expression file format.
void FormatSchematicToFormatter(OUTPUTFORMATTER *aOut, SCH_SHEET *aSheet, SCHEMATIC *aSchematic, const std::map< std::string, UTF8 > *aProperties=nullptr)
Serialize a schematic sheet to an OUTPUTFORMATTER without file I/O or Prettify.
void Format(SCH_SHEET *aSheet)
Base class for any item which can be embedded within the SCHEMATIC container class,...
virtual bool IsConnectable() const
void SetConnectivityDirty(bool aDirty=true)
Set the dirty flag.
void SwapItemData(SCH_ITEM *aImage)
Swap data between aItem and aImage.
Container to create a flattened list of symbols because in a complex hierarchy, a symbol can be used ...
void SortByReferenceOnly()
Sort the list of references by reference.
void ReannotateByOptions(ANNOTATE_ORDER_T aSortOption, ANNOTATE_ALGO_T aAlgoOption, int aStartNumber, const SCH_REFERENCE_LIST &aAdditionalRefs, bool aStartAtCurrent, SCH_SHEET_LIST *aHierarchy)
Forces reannotation of the provided references.
void SetRefDesTracker(std::shared_ptr< REFDES_TRACKER > aTracker)
void AddItem(const SCH_REFERENCE &aItem)
void UpdateAnnotation()
Update the symbol references for the schematic project (or the current sheet).
A helper to define a symbol's reference designator in a schematic.
bool AlwaysAnnotate() const
Verify the reference should always be automatically annotated.
void Split()
Attempt to split the reference designator into a name (U) and number (1).
SCH_SYMBOL * GetSymbol() const
bool IsSplitNeeded() const
Determine if this reference needs to be split or if it likely already has been.
wxString GetRefNumber() const
EE_RTREE & Items()
Get the full RTree, usually for iterating.
const wxString & GetFileName() const
void SetFileName(const wxString &aFileName)
Set the file name for this screen to aFileName.
TITLE_BLOCK & GetTitleBlock()
void GetSheets(std::vector< SCH_ITEM * > *aItems) const
Similar to Items().OfType( SCH_SHEET_T ), but return the sheets in a deterministic order (L-R,...
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
std::optional< SCH_SHEET_PATH > GetSheetPathByKIIDPath(const KIID_PATH &aPath, bool aIncludeLastSheet=true) const
Finds a SCH_SHEET_PATH that matches the provided KIID_PATH.
SCH_ITEM * ResolveItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr, bool aAllowNullptrReturn=false) const
Fetch a SCH_ITEM by ID.
wxString GetNextPageNumber() const
void GetSymbols(SCH_REFERENCE_LIST &aReferences, SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols=false) const
Add a SCH_REFERENCE object to aReferences for each symbol in the list of sheets.
bool TestForRecursion(const SCH_SHEET_LIST &aSrcSheetHierarchy, const wxString &aDestFileName)
Test every SCH_SHEET_PATH in this SCH_SHEET_LIST to verify if adding the sheets stored in aSrcSheetHi...
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
int ComparePageNum(const SCH_SHEET_PATH &aSheetPathToTest) const
Compare sheets by their page number.
void GetSymbols(SCH_REFERENCE_LIST &aReferences, SYMBOL_FILTER aSymbolFilter, bool aForceIncludeOrphanSymbols=false) const
Adds SCH_REFERENCE object to aReferences for each symbol in the sheet.
KIID_PATH Path() const
Get the sheet path as an KIID_PATH.
SCH_ITEM * ResolveItem(const KIID &aID) const
Fetch a SCH_ITEM by ID.
SCH_SCREEN * LastScreen()
wxString GetPageNumber() const
bool IsContainedWithin(const SCH_SHEET_PATH &aSheetPathToTest) const
Check if this path is contained inside aSheetPathToTest.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
void pop_back()
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
wxString GetFileName() const
Return the filename corresponding to this sheet.
void AddInstance(const SCH_SHEET_INSTANCE &aInstance)
SCH_SCREEN * GetScreen() const
wxString GetShownName(RESOLUTION_CONTEXT aContext) const
void SetScreen(SCH_SCREEN *aScreen)
Set the SCH_SCREEN associated with this sheet to aScreen.
std::vector< SCH_SHEET_PIN * > & GetPins()
void SetLibId(const LIB_ID &aName)
std::vector< std::unique_ptr< SCH_PIN > > & GetRawPins()
bool UseLibIdLookup() const
wxString GetSchSymbolLibraryName() const
std::vector< const SCH_PIN * > GetPins(const SCH_SHEET_PATH *aSheet) const
Retrieve a list of the SCH_PINs for the given sheet path.
void AddHierarchicalReference(const KIID_PATH &aPath, const wxString &aRef, int aUnit)
Add a full hierarchical reference to this symbol.
const LIB_ID & GetLibId() const override
void SetSchSymbolLibraryName(const wxString &aName)
The name of the symbol in the schematic library symbol list.
std::unique_ptr< LIB_SYMBOL > & GetLibSymbolRef()
void SetLibSymbol(LIB_SYMBOL *aLibSymbol)
Set this schematic symbol library symbol reference to aLibSymbol.
virtual void Serialize(google::protobuf::Any &aContainer) const
Serializes this object to the given Any message.
An interface to the global shared library manager that is schematic-specific and linked to one projec...
LIB_SYMBOL * LoadSymbol(const wxString &aNickname, const wxString &aName)
Load a LIB_SYMBOL having aName from the library given by aNickname.
A wrapper for reporting to a wxString object.
A type-safe container of any type.
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject, bool aAllowEscapes)
Replace any environment variable & text variable references with their values.
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, RESOLUTION_CONTEXT aContext)
FRAME_T
The set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
bool m_ConnectivityEngine
Use the schematic connectivity engine instead of CONNECTION_GRAPH.
static const std::string KiCadSchematicFileExtension
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.
KICOMMON_API void PackProject(types::ProjectSpecifier &aOutput, const PROJECT &aInput)
KICOMMON_API int UnpackDistance(const types::Distance &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API KIID_PATH UnpackSheetPath(const types::SheetPath &aInput)
KICOMMON_API std::optional< KICAD_T > TypeNameFromAny(const google::protobuf::Any &aMessage)
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackSheetPath(types::SheetPath &aOutput, const KIID_PATH &aInput)
KICOMMON_API LIB_ID UnpackLibId(const types::LibraryIdentifier &aId)
const KICOMMON_API std::string KiwayClientName
const KICOMMON_API std::string StandaloneCrossProbeClientName
static int plotJob(JOB_EXPORT_PCB_PLOT *aJob, PCB_PLOTTER &aPlotter, const wxString &aOutPath, bool aSingleOutput, bool aUseOverrides)
PGM_BASE & Pgm()
The global program "get" accessor.
constexpr int MIN_PNG_DPI
constexpr int MAX_PNG_DPI
std::shared_ptr< SCH_CONTEXT > CreateSchFrameContext(SCH_EDIT_FRAME *aFrame)
Class to handle a set of SCH_ITEMs.
std::vector< EDA_ITEM * > EDA_ITEMS
ANNOTATE_ORDER_T
Schematic annotation order options.
ANNOTATE_ALGO_T
Schematic annotation type options.
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
@ SYMBOL_FILTER_NON_POWER
wxString GetDefaultVariantName()
std::vector< wxString > ExpandStackedPinNotation(const wxString &aPinName, bool *aValid)
Expand stacked pin notation like [1,2,3], [1-4], [A1-A4], or [AA1-AA3,AB4,CD12-CD14] into individual ...
bool on_selection
Synchronize the selection for multiple items too.
bool auto_highlight
Automatically turn on highlight mode in the target frame.
RequestMessageType Request
A simple container for sheet instance information.
A simple container for schematic symbol instance information.
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.
VECTOR2< int32_t > VECTOR2I
Definition of file extensions used in Kicad.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().