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 if(
PackSymbol( &packed, symbol, targetPath ) )
1437 newItem.PackFrom( packed );
1442 kiapi::schematic::types::SheetSymbol packed;
1444 if( sheetProto.page_number().empty() )
1449 if(
PackSheet( &packed, sheet, targetPath ) )
1450 newItem.PackFrom( packed );
1461 std::vector<SCH_SYMBOL_INSTANCE> symbolPlacements;
1462 std::vector<SCH_SHEET_INSTANCE> sheetPlacements;
1465 symbolPlacements =
static_cast<SCH_SYMBOL*
>( existingItem )->GetInstances();
1467 sheetPlacements =
static_cast<SCH_SHEET*
>( existingItem )->GetInstances();
1469 commit->
Modify( existingItem, targetScreen );
1475 connectivityChanged =
true;
1481 kiapi::schematic::types::SchematicSymbolInstance packed;
1488 if(
PackSymbol( &packed, symbol, existingPath ) )
1489 newItem.PackFrom( packed );
1494 kiapi::schematic::types::SheetSymbol packed;
1501 if(
PackSheet( &packed, sheet, existingPath ) )
1502 newItem.PackFrom( packed );
1510 aItemHandler( status, newItem );
1516 :
_(
"Modified items via API" ) );
1519 if(
m_frame && connectivityChanged )
1522 return ItemRequestStatus::IRS_OK;
1527 const std::string& aClientName )
1532 for(
auto& [
id, status] : aItemsToDelete )
1542 status = ItemDeletionStatus::IDS_IMMUTABLE;
1547 status = ItemDeletionStatus::IDS_OK;
1558 return std::nullopt;
1563 return std::nullopt;
1571 if( aDocument.has_sheet_path() )
1575 if( std::optional<SCH_SHEET_PATH> sheetPath =
schematic()->Hierarchy().GetSheetPathByKIIDPath(
path ) )
1576 return sheetPath->LastScreen();
1581 if( std::optional<SCH_SHEET_PATH> current =
m_context->GetCurrentSheet() )
1582 return current->LastScreen();
1594 return std::nullopt;
1601 return screen->GetPageSettings();
1603 return std::nullopt;
1611 screen->SetPageSettings( aPageInfo );
1612 screen->SetContentModified();
1643 else if(
schematic()->GetCurrentScreen() )
1657static std::optional<ApiResponseStatus>
1661 aJob.
m_drawingSheet = wxString::FromUTF8( aSettings.drawing_sheet() );
1662 aJob.
m_defaultFont = wxString::FromUTF8( aSettings.default_font() );
1663 aJob.
m_variant = wxString::FromUTF8( aSettings.variant() );
1670 aJob.
m_theme = wxString::FromUTF8( aSettings.theme() );
1674 for(
const std::string& page : aSettings.plot_pages() )
1675 aJob.
m_plotPages.push_back( wxString::FromUTF8( page ) );
1677 if( aSettings.page_size() != schematic::jobs::SchematicJobPageSize::SJPS_UNKNOWN )
1680 switch( aSettings.sheet_mode() )
1682 case schematic::jobs::SJSM_ALL_SHEETS: aJob.
m_plotAll =
true;
break;
1683 case schematic::jobs::SJSM_SINGLE_SHEET: aJob.
m_plotAll =
false;
break;
1684 case schematic::jobs::SJSM_UNKNOWN:
1688 if( aDocument.has_sheet_path() )
1691 return std::nullopt;
1700 if( !documentValidation )
1701 return tl::unexpected( documentValidation.error() );
1703 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1704 return tl::unexpected( *busy );
1706 auto plotJob = std::make_unique<JOB_EXPORT_SCH_PLOT_SVG>( aCtx.
Request.plot_settings().sheet_mode()
1707 != schematic::jobs::SJSM_SINGLE_SHEET );
1710 if( !aCtx.
Request.job_settings().output_path().empty() )
1711 plotJob->SetConfiguredOutputPath( wxString::FromUTF8( aCtx.
Request.job_settings().output_path() ) );
1716 return tl::unexpected( *err );
1728 if( !documentValidation )
1729 return tl::unexpected( documentValidation.error() );
1731 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1732 return tl::unexpected( *busy );
1734 auto plotJob = std::make_unique<JOB_EXPORT_SCH_PLOT_DXF>( aCtx.
Request.plot_settings().sheet_mode()
1735 != schematic::jobs::SJSM_SINGLE_SHEET );
1739 if( !aCtx.
Request.job_settings().output_path().empty() )
1740 plotJob->SetConfiguredOutputPath( wxString::FromUTF8( aCtx.
Request.job_settings().output_path() ) );
1745 return tl::unexpected( *err );
1757 if( !documentValidation )
1758 return tl::unexpected( documentValidation.error() );
1760 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1761 return tl::unexpected( *busy );
1763 auto plotJob = std::make_unique<JOB_EXPORT_SCH_PLOT_PDF>(
false );
1766 if( !aCtx.
Request.job_settings().output_path().empty() )
1767 plotJob->SetConfiguredOutputPath( wxString::FromUTF8( aCtx.
Request.job_settings().output_path() ) );
1772 return tl::unexpected( *err );
1776 plotJob->m_PDFHierarchicalLinks = aCtx.
Request.hierarchical_links();
1788 if( !documentValidation )
1789 return tl::unexpected( documentValidation.error() );
1791 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1792 return tl::unexpected( *busy );
1794 auto plotJob = std::make_unique<JOB_EXPORT_SCH_PLOT_PS>( aCtx.
Request.plot_settings().sheet_mode()
1795 != schematic::jobs::SJSM_SINGLE_SHEET );
1798 if( !aCtx.
Request.job_settings().output_path().empty() )
1799 plotJob->SetConfiguredOutputPath( wxString::FromUTF8( aCtx.
Request.job_settings().output_path() ) );
1804 return tl::unexpected( *err );
1815 return tl::unexpected( validation.error() );
1817 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1818 return tl::unexpected( *busy );
1820 const schematic::jobs::SchematicJobSheetMode sheetMode = aCtx.
Request.plot_settings().sheet_mode();
1822 auto plotJob = std::make_unique<JOB_EXPORT_SCH_PLOT_PNG>( sheetMode != schematic::jobs::SJSM_SINGLE_SHEET );
1825 if( !aCtx.
Request.job_settings().output_path().empty() )
1826 plotJob->SetConfiguredOutputPath( wxString::FromUTF8( aCtx.
Request.job_settings().output_path() ) );
1831 return tl::unexpected( *err );
1840 ApiResponseStatus status;
1841 status.set_status( ApiStatusCode::AS_BAD_REQUEST );
1843 return tl::unexpected( status );
1850 plotJob->m_antialias = aCtx.
Request.antialiasing() != types::AntialiasingMode::AAM_NONE;
1851 plotJob->m_useBackgroundColor = aCtx.
Request.plot_background_color();
1862 if( !documentValidation )
1863 return tl::unexpected( documentValidation.error() );
1865 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1866 return tl::unexpected( *busy );
1868 if( aCtx.
Request.format() == kiapi::schematic::jobs::SchematicNetlistFormat::SNF_UNKNOWN )
1870 ApiResponseStatus e;
1871 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1872 e.set_error_message(
"RunSchematicJobExportNetlist requires a valid format" );
1873 return tl::unexpected( e );
1879 if( !aCtx.
Request.job_settings().output_path().empty() )
1884 if( !aCtx.
Request.variant_name().empty() )
1896 if( !documentValidation )
1897 return tl::unexpected( documentValidation.error() );
1899 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
1900 return tl::unexpected( *busy );
1905 if( !aCtx.
Request.job_settings().output_path().empty() )
1923 ApiResponseStatus e;
1924 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1925 e.set_error_message(
"A list of fields fields or a fields preset are required" );
1926 return tl::unexpected( e );
1929 switch( aCtx.
Request.fields().filter_scope() )
1931 case kiapi::schematic::jobs::BOMFilterScope::BFS_VISIBLE:
1935 case kiapi::schematic::jobs::BOMFilterScope::BFS_ALL:
1939 case kiapi::schematic::jobs::BOMFilterScope::BFS_REFERENCE:
1945 if( aCtx.
Request.fields().sort_direction() == kiapi::schematic::jobs::BOMSortDirection::BSD_ASCENDING )
1949 else if( aCtx.
Request.fields().sort_direction() == kiapi::schematic::jobs::BOMSortDirection::BSD_DESCENDING )
1954 for(
const kiapi::schematic::jobs::BOMField& field : aCtx.
Request.fields().fields() )
1956 bomJob.
m_fieldsOrdered.emplace_back( wxString::FromUTF8( field.name() ) );
1957 bomJob.
m_fieldsLabels.emplace_back( wxString::FromUTF8( field.label() ) );
1959 if( field.group_by() )
1960 bomJob.
m_fieldsGroupBy.emplace_back( wxString::FromUTF8( field.name() ) );
1966 if( !aCtx.
Request.variant_name().empty() )
1982 if( sheetName.IsEmpty() && aSheet->
GetScreen() )
1985 sheetName = fn.GetName();
1988 aInstance->set_name( sheetName.ToUTF8() );
1989 aInstance->set_filename( aSheet->
GetFileName().ToUTF8() );
1990 aInstance->set_page_number( aPath.
GetPageNumber().ToUTF8() );
1994 std::vector<SCH_ITEM*> childSheets;
1997 std::ranges::sort( childSheets,
2009 for(
SCH_ITEM* childItem : childSheets )
2012 kiapi::schematic::types::SheetInstance* childInstance = aInstance->add_children();
2026 if( !documentValidation )
2027 return tl::unexpected( documentValidation.error() );
2029 kiapi::schematic::commands::SchematicHierarchyResponse response;
2030 response.mutable_document()->CopyFrom( aCtx.
Request.document() );
2038 std::ranges::sort( topLevelSheets,
2050 for(
SCH_SHEET* topSheet : topLevelSheets )
2052 kiapi::schematic::types::SheetInstance* instance = response.add_top_level_sheets();
2068 ApiResponseStatus status;
2069 status.set_status( ApiStatusCode::AS_BUSY );
2070 status.set_error_message(
"Cannot rebuild connectivity during an interactive operation" );
2071 return tl::unexpected( status );
2076 if( !documentValidation )
2077 return tl::unexpected( documentValidation.error() );
2079 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2080 return tl::unexpected( *busy );
2083 const bool filterByType = aCtx.
Request.types_size() > 0;
2085 static const std::set<KICAD_T> s_netlistTypes = {
2100 std::set<KICAD_T> typeFilter(
types.begin(),
types.end() );
2101 std::erase_if( typeFilter, [](
KICAD_T aType ) {
return !s_netlistTypes.contains( aType ); } );
2103 if( filterByType && typeFilter.empty() )
2105 ApiResponseStatus e;
2106 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2107 e.set_error_message(
"none of the requested types are valid for a netlist object" );
2108 return tl::unexpected( e );
2113 if( !connectionGraph )
2115 ApiResponseStatus e;
2116 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2117 e.set_error_message(
"schematic has no connection graph" );
2118 return tl::unexpected( e );
2127 catch(
const std::exception& error )
2131 m_frame->ShowInfoBarError(
_(
"Unable to rebuild schematic connectivity." ),
true );
2135 wxLogTrace(
traceApi, wxS(
"GetSchematicNetlist rebuild failed: %s" ),
2136 wxString::FromUTF8( error.what() ) );
2138 ApiResponseStatus status;
2139 status.set_status( ApiStatusCode::AS_UNKNOWN );
2140 status.set_error_message( error.what() );
2141 return tl::unexpected( status );
2145 kiapi::schematic::commands::SchematicNetlistResponse response;
2146 response.mutable_document()->CopyFrom( aCtx.
Request.document() );
2150 for(
const auto&
group :
schematic()->Connectivity().GetNetMap() )
2152 if(
group.instances.empty() || !
group.instances.front().IsNet()
2153 || !
group.instances.front().Driver() )
2158 kiapi::schematic::types::SchematicNet* net =
nullptr;
2160 for(
const auto& view :
group.instances )
2162 const auto physicalItems = view.Items();
2164 if( physicalItems.empty() )
2169 net = response.add_nets();
2170 net->set_name(
group.name.ToUTF8() );
2173 auto* sheet = net->add_sheets();
2176 for(
SCH_ITEM* item : physicalItems )
2178 if( !filterByType || typeFilter.contains( item->Type() ) )
2179 sheet->add_items()->set_value( item->m_Uuid.AsStdString() );
2187 for(
const auto& [key, subgraphList] : connectionGraph->
GetNetMap() )
2189 if( subgraphList.empty() )
2200 kiapi::schematic::types::SchematicNet* net = response.add_nets();
2201 net->set_name( key.Name.ToUTF8() );
2205 kiapi::schematic::types::SchematicNetSheetContents* sheetContents = net->add_sheets();
2206 PackSheetPath( *sheetContents->mutable_path(), subGraph->GetSheet() );
2208 for(
SCH_ITEM* item : subGraph->GetItems() )
2210 if( filterByType && !typeFilter.contains( item->Type() ) )
2213 sheetContents->add_items()->set_value( item->m_Uuid.AsStdString() );
2226 wxLogTrace(
traceApi,
"Received announce from frame %d at %s",
2232 CrossProbeAnnounceResponse response;
2233 response.set_status( CPS_OK );
2239 std::unordered_map<wxString, std::vector<SCH_REFERENCE>>& aSyncSymMap,
2240 std::unordered_map<wxString, std::unordered_map<wxString, SCH_PIN*>>& aSyncPinMap,
2241 const wxString& aVariantName = wxEmptyString,
bool aRecursive =
false )
2251 findSymbolsAndPins( aSchematicSheetList, candidate, aSyncSymMap, aSyncPinMap, aVariantName, aRecursive );
2259 for(
unsigned ii = 0; ii < references.
GetCount(); ii++ )
2268 wxString fullRef = schRef.
GetRef() + refNum;
2271 if( fullRef.StartsWith( wxS(
"#" ) ) )
2275 if( refNum.compare( wxS(
"?" ) ) == 0 )
2279 auto symMatchIt = aSyncSymMap.find( fullRef );
2281 if( symMatchIt != aSyncSymMap.end() )
2283 symMatchIt->second.emplace_back( schRef );
2290 auto symPinMatchIt = aSyncPinMap.find( fullRef );
2292 if( symPinMatchIt != aSyncPinMap.end() )
2294 std::unordered_map<wxString, SCH_PIN*>& pinMap = symPinMatchIt->second;
2295 std::vector<SCH_PIN*> pinsOnSheet = symbol->
GetPins( &aSheetPath );
2299 int pinUnit =
pin->GetLibPin() ?
pin->GetLibPin()->GetUnit() :
ALL_UNITS;
2301 if( pinUnit > 0 && pinUnit != schRef.
GetUnit() )
2306 for(
const wxString&
pad :
2309 auto pinIt = pinMap.find(
pad );
2311 if( pinIt != pinMap.end() )
2313 pinIt->second =
pin;
2327 std::unordered_map<wxString, std::vector<SCH_REFERENCE>>& aSyncSymMap,
2328 std::unordered_map<wxString, std::unordered_map<wxString, SCH_PIN*>>& aSyncPinMap,
2329 std::unordered_map<SCH_SHEET_PATH, bool>& aCache )
2331 auto cacheIt = aCache.find( aSheetPath );
2333 if( cacheIt != aCache.end() )
2334 return cacheIt->second;
2343 aSyncPinMap, aCache );
2347 aCache.emplace( aSheetPath,
false );
2357 aCache.emplace( aSheetPath,
false );
2361 for(
unsigned ii = 0; ii < references.
GetCount(); ii++ )
2369 wxString fullRef = schRef.
GetRef() + refNum;
2372 if( fullRef.StartsWith( wxS(
"#" ) ) )
2376 if( refNum.compare( wxS(
"?" ) ) == 0 )
2379 if( aSyncSymMap.find( fullRef ) == aSyncSymMap.end() )
2381 aCache.emplace( aSheetPath,
false );
2385 if( aSyncPinMap.find( fullRef ) != aSyncPinMap.end() )
2387 aCache.emplace( aSheetPath,
false );
2392 aCache.emplace( aSheetPath,
true );
2397std::optional<std::tuple<SCH_SHEET_PATH, SCH_ITEM*, std::vector<SCH_ITEM*>>>
2399 const kiapi::common::commands::SyncSelection& aSync )
2401 std::unordered_map<wxString, std::vector<SCH_REFERENCE>> syncSymMap;
2402 std::unordered_map<wxString, std::unordered_map<wxString, SCH_PIN*>> syncPinMap;
2403 std::unordered_map<SCH_SHEET_PATH, bool> fullyWantedCache;
2405 std::optional<wxString> focusSymbol;
2406 std::optional<std::pair<wxString, wxString>> focusPin;
2407 std::unordered_map<SCH_SHEET_PATH, std::vector<SCH_ITEM*>> focusItemResults;
2412 std::vector<SCH_SHEET_PATH> orderedSheets;
2413 orderedSheets.reserve( allSheetsList.size() );
2419 orderedSheets.push_back( sheetPath );
2422 const bool focusOnFirst = ( aSync.mode() == kiapi::common::commands::SSM_ITEMS_AND_NETS ) && aSync.has_focus_item();
2424 for(
const kiapi::common::commands::SelectionSpec& spec : aSync.items() )
2426 switch( spec.spec_case() )
2428 case kiapi::common::commands::SelectionSpec::kFootprint:
2430 wxString symRef = wxString::FromUTF8( spec.footprint().reference() );
2431 syncSymMap[symRef] = std::vector<SCH_REFERENCE>();
2435 case kiapi::common::commands::SelectionSpec::kPad:
2437 wxString symRef = wxString::FromUTF8( spec.pad().reference() );
2438 wxString padNum = wxString::FromUTF8( spec.pad().number() );
2439 syncPinMap[symRef][padNum] =
nullptr;
2450 const kiapi::common::commands::SelectionSpec& focusSpec = aSync.focus_item();
2452 if( focusSpec.has_footprint() )
2453 focusSymbol = wxString::FromUTF8( focusSpec.footprint().reference() );
2454 else if( focusSpec.has_pad() )
2455 focusPin = std::make_pair( wxString::FromUTF8( focusSpec.pad().reference() ),
2456 wxString::FromUTF8( focusSpec.pad().number() ) );
2460 auto flattenSyncMaps =
2461 [&syncSymMap, &syncPinMap]() -> std::vector<SCH_ITEM*>
2463 std::vector<SCH_ITEM*> allVec;
2465 for(
const auto& [symRef, symbols] : syncSymMap )
2468 allVec.push_back( ref.GetSymbol() );
2471 for(
const auto& [symRef, pinMap] : syncPinMap )
2473 for(
const auto& [padNum,
pin] : pinMap )
2476 allVec.push_back(
pin );
2483 auto clearSyncMaps =
2484 [&syncSymMap, &syncPinMap]()
2486 for(
auto& [symRef, symbols] : syncSymMap )
2489 for(
auto& [reference, pins] : syncPinMap )
2491 for(
auto& [number,
pin] : pins )
2496 auto syncMapsValuesEmpty =
2497 [&syncSymMap, &syncPinMap]() ->
bool
2499 for(
const auto& [symRef, symbols] : syncSymMap )
2501 if( symbols.size() > 0 )
2505 for(
const auto& [symRef, pins] : syncPinMap )
2507 for(
const auto& [padNum,
pin] : pins )
2517 auto checkFocusItems =
2522 auto findIt = syncSymMap.find( *focusSymbol );
2524 if( findIt != syncSymMap.end() )
2526 if( findIt->second.size() > 0 )
2527 focusItemResults[aSheet].push_back( findIt->second.front().GetSymbol() );
2532 auto findIt = syncPinMap.find( focusPin->first );
2534 if( findIt != syncPinMap.end() )
2536 if( findIt->second[focusPin->second] )
2537 focusItemResults[aSheet].push_back( findIt->second[focusPin->second] );
2542 auto makeRetForSheet =
2549 std::vector<SCH_ITEM*> itemsVector = flattenSyncMaps();
2555 kiidPath.push_back( item->m_Uuid );
2557 std::optional<SCH_SHEET_PATH> subsheetPath =
2564 syncPinMap, fullyWantedCache ) )
2566 itemsVector.push_back( item );
2570 return std::make_tuple( aSheet, aFocusItem, itemsVector );
2581 checkFocusItems( sheetPath );
2584 if( focusItemResults.size() > 0 )
2588 const std::vector<SCH_ITEM*>& items = focusItemResults[sheetPath];
2590 if( !items.empty() )
2591 return makeRetForSheet( sheetPath, items.front() );
2603 if( !syncMapsValuesEmpty() )
2606 return makeRetForSheet( sheetPath,
nullptr );
2611 return std::nullopt;
2618 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"SyncSelection" ) )
2619 return tl::unexpected( *headless );
2621 SyncSelectionResponse response;
2625 if( !settings.
on_selection && aCtx.
Request.context() != SyncSelectionContext::SSC_EXPLICIT )
2627 response.set_status( CPS_DISABLED );
2628 response.set_message(
"implicit selection sync disabled by user" );
2633 if( aCtx.
Request.items_size() == 0 )
2641 response.set_status( CPS_OK );
2645 std::optional<std::tuple<SCH_SHEET_PATH, SCH_ITEM*, std::vector<SCH_ITEM*>>> findRet =
2650 auto& [sheetPath, focusItem, items] = *findRet;
2658 if(
frame()->eeconfig()->m_CrossProbing.flash_selection )
2669 std::vector<SCH_ITEM*> itemPtrs;
2670 std::copy( items.begin(), items.end(), std::back_inserter( itemPtrs ) );
2681 response.set_status( CPS_OK );
2689 if( std::optional<ApiResponseStatus> headless =
checkForHeadless(
"HighlightNets" ) )
2690 return tl::unexpected( *headless );
2692 HighlightNetsResponse response;
2700 response.set_status( CPS_DISABLED );
2707 if( aCtx.
Request.net_name_size() > 0 )
2708 net = wxString::FromUTF8( aCtx.
Request.net_name( 0 ) );
2712 response.set_status( CPS_OK );
2723 if( !documentValidation )
2724 return tl::unexpected( documentValidation.error() );
2728 if( aCtx.
Request.document().has_sheet_path() )
2732 if( std::optional<SCH_SHEET_PATH> resolvedPath =
schematic()->Hierarchy().GetSheetPathByKIIDPath( kiidPath ) )
2734 path = *resolvedPath;
2738 ExpandTextVariablesResponse reply;
2740 std::function<bool( wxString* )> textResolver =
2741 [&]( wxString* token ) ->
bool
2748 for(
const std::string& textMsg : aCtx.
Request.text() )
2752 if( aCtx.
Request.expand_env_vars() )
2755 reply.add_text(
text.ToUTF8() );
2765 return tl::unexpected( documentValidation.error() );
2767 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2768 return tl::unexpected( *busy );
2770 VariantsResponse response;
2772 response.mutable_document()->CopyFrom( aCtx.
Request.document() );
2774 for(
const wxString&
name :
schematic()->GetVariantNames() )
2776 types::DesignVariant* var = response.add_variants();
2777 var->set_name(
name.ToUTF8() );
2778 var->set_description(
schematic()->GetVariantDescription(
name ).ToUTF8() );
2788 return tl::unexpected( documentValidation.error() );
2790 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2791 return tl::unexpected( *busy );
2794 wxString
name = wxString::FromUTF8( aCtx.
Request.name() );
2798 ApiResponseStatus e;
2799 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2800 e.set_error_message( fmt::format(
"'{}' is not a usable new variant name", aCtx.
Request.name() ) );
2801 return tl::unexpected( e );
2811 if( aCtx.
Request.has_description() )
2834 return tl::unexpected( documentValidation.error() );
2836 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2837 return tl::unexpected( *busy );
2840 wxString
name = wxString::FromUTF8( aCtx.
Request.name() );
2844 ApiResponseStatus e;
2845 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2846 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.name() ) );
2847 return tl::unexpected( e );
2852 ApiResponseStatus e;
2853 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2854 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.name() ) );
2855 return tl::unexpected( e );
2860 bool pushedCommit =
false;
2867 if( !commit.
Empty() )
2870 pushedCommit =
true;
2884 if(
frame()->Schematic().GetCurrentVariant().CmpNoCase(
name ) == 0 )
2898 return tl::unexpected( documentValidation.error() );
2900 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2901 return tl::unexpected( *busy );
2904 wxString oldName = wxString::FromUTF8( aCtx.
Request.old_name() );
2905 wxString newName = wxString::FromUTF8( aCtx.
Request.new_name() );
2909 ApiResponseStatus e;
2910 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2911 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.old_name() ) );
2912 return tl::unexpected( e );
2917 ApiResponseStatus e;
2918 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2919 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.new_name() ) );
2920 return tl::unexpected( e );
2925 ApiResponseStatus e;
2926 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2927 e.set_error_message( fmt::format(
"no variant named '{}' exists", 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(
"a variant named '{}' already exists", aCtx.
Request.new_name() ) );
2936 return tl::unexpected( e );
2943 bool pushedCommit =
false;
2946 oldName = *canonicalOld;
2948 schematic->RenameVariant( oldName, newName, &commit );
2950 if( !commit.
Empty() )
2953 pushedCommit =
true;
2985 return tl::unexpected( documentValidation.error() );
2987 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
2988 return tl::unexpected( *busy );
2991 wxString oldName = wxString::FromUTF8( aCtx.
Request.old_name() );
2992 wxString newName = wxString::FromUTF8( aCtx.
Request.new_name() );
2996 ApiResponseStatus e;
2997 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
2998 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.old_name() ) );
2999 return tl::unexpected( e );
3004 ApiResponseStatus e;
3005 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3006 e.set_error_message( fmt::format(
"'{}' is not a valid variant name", aCtx.
Request.new_name() ) );
3007 return tl::unexpected( e );
3012 ApiResponseStatus e;
3013 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3014 e.set_error_message( fmt::format(
"no variant named '{}' exists", 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(
"a variant named '{}' already exists", aCtx.
Request.new_name() ) );
3023 return tl::unexpected( e );
3028 bool pushedCommit =
false;
3031 oldName = *canonicalOld;
3033 schematic->CopyVariant( oldName, newName, &commit );
3035 if( aCtx.
Request.has_new_description() )
3036 schematic->SetVariantDescription( newName, wxString::FromUTF8( aCtx.
Request.new_description() ) );
3038 if( !commit.
Empty() )
3041 pushedCommit =
true;
3065 return tl::unexpected( documentValidation.error() );
3067 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3068 return tl::unexpected( *busy );
3071 wxString
name = wxString::FromUTF8( aCtx.
Request.name() );
3075 ApiResponseStatus e;
3076 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3077 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.name() ) );
3078 return tl::unexpected( e );
3104 return tl::unexpected( documentValidation.error() );
3106 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3107 return tl::unexpected( *busy );
3115 ApiResponseStatus e;
3116 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3117 e.set_error_message( fmt::format(
"no variant named '{}' exists", aCtx.
Request.name() ) );
3118 return tl::unexpected( e );
3122 wxString
name = aCtx.
Request.has_name() ? wxString::FromUTF8( aCtx.
Request.name() ) : wxString();
3140 return tl::unexpected( documentValidation.error() );
3142 CurrentVariantResponse response;
3144 if( wxString current =
schematic()->GetCurrentVariant(); !current.
IsEmpty() )
3145 response.set_name( current.ToUTF8() );
3156 ApiResponseStatus e;
3157 e.set_status( ApiStatusCode::AS_UNHANDLED );
3158 return tl::unexpected( e );
3161 if( std::optional<ApiResponseStatus> busy =
checkForBusy() )
3162 return tl::unexpected( *busy );
3168 ApiResponseStatus e;
3169 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3170 e.set_error_message(
"lib_id must specify both a library nickname and an entry name" );
3171 return tl::unexpected( e );
3179 ApiResponseStatus e;
3180 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3181 e.set_error_message( fmt::format(
"symbol '{}' not found", libId.
Format().
wx_str() ) );
3182 return tl::unexpected( e );
3188 if( aCtx.
Request.header().document().has_sheet_path() )
3198 ApiResponseStatus e;
3199 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3200 e.set_error_message( fmt::format(
"the requested sheet path {} is not valid for this schematic",
3202 return tl::unexpected( e );
3208 int unit = aCtx.
Request.has_unit() ? aCtx.
Request.unit().unit() : 1;
3212 ApiResponseStatus e;
3213 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
3214 e.set_error_message( fmt::format(
"unit {} is out of range for symbol '{}' ({} units)", unit,
3216 return tl::unexpected( e );
3221 std::unique_ptr<SCH_SYMBOL> symbol(
3222 std::make_unique<SCH_SYMBOL>( *libSymbol, libId, &targetPath, unit, 0, position ) );
3224 if( aCtx.
Request.has_orientation() )
3227 if( !aCtx.
Request.reference().empty() )
3229 symbol->SetRef( &targetPath, wxString::FromUTF8( aCtx.
Request.reference() ) );
3240 annotate |=
frame->eeconfig()->m_AnnotatePanel.automatic;
3251 schematic()->Settings().m_AnnotateStartNum, existingRefs,
false, &hierarchy );
3258 if(
frame->eeconfig()->m_AutoplaceFields.enable )
3264 commit->
Add( placed, targetScreen );
3269 PlaceFromLibraryResponse response;
3270 response.mutable_header()->CopyFrom( aCtx.
Request.header() );
3272 kiapi::schematic::types::SchematicSymbolInstance packed;
3274 if(
PackSymbol( &packed, placed, targetPath ) )
3275 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)
void ApplySymbolInstance(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...
tl::expected< bool, ApiResponseStatus > UnpackSheet(SCH_SHEET *aOutput, const kiapi::schematic::types::SheetSymbol &aInput)
Unpack the every placement data from the input.
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 PackSymbol(kiapi::schematic::types::SchematicSymbolInstance *aOutput, const SCH_SYMBOL *aInput, const SCH_SHEET_PATH &aPath)
void ApplySheetInstance(SCH_SHEET *aSheet, const kiapi::schematic::types::SheetSymbol &aInput, const SCH_SHEET_PATH &aParentPath, SCHEMATIC *aSchematic)
Apply the placement data in a sheet message to aSheet: page number and the variants the message carri...
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)
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().