KiCad PCB EDA Suite
Loading...
Searching...
No Matches
api_handler_pcb.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2023 Jon Evans <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <magic_enum.hpp>
22#include <properties/property.h>
23
24#include <common.h>
25#include <api/api_handler_pcb.h>
26#include <api/api_pcb_utils.h>
27#include <api/api_enums.h>
28#include <api/api_utils.h>
29#include <board_commit.h>
31#include <footprint.h>
32#include <kicad_clipboard.h>
33#include <netinfo.h>
34#include <pad.h>
35#include <pcb_edit_frame.h>
36#include <pcb_group.h>
37#include <pcb_reference_image.h>
38#include <pcb_shape.h>
39#include <pcb_text.h>
40#include <pcb_textbox.h>
41#include <pcb_track.h>
42#include <pcbnew_id.h>
43#include <pcb_marker.h>
44#include <drc/drc_item.h>
45#include <layer_ids.h>
46#include <project.h>
47#include <tool/tool_manager.h>
48#include <tools/pcb_actions.h>
50#include <zone.h>
51
52#include <api/common/types/base_types.pb.h>
55
56using namespace kiapi::common::commands;
57using types::CommandStatus;
58using types::DocumentType;
59using types::ItemRequestStatus;
60
61
63 API_HANDLER_EDITOR( aFrame )
64{
71
74
80
101
107
124}
125
126
128{
129 return static_cast<PCB_EDIT_FRAME*>( m_frame );
130}
131
132
134 const HANDLER_CONTEXT<RunAction>& aCtx )
135{
136 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
137 return tl::unexpected( *busy );
138
139 RunActionResponse response;
140
141 if( frame()->GetToolManager()->RunAction( aCtx.Request.action(), true ) )
142 response.set_status( RunActionStatus::RAS_OK );
143 else
144 response.set_status( RunActionStatus::RAS_INVALID );
145
146 return response;
147}
148
149
152{
153 if( aCtx.Request.type() != DocumentType::DOCTYPE_PCB )
154 {
155 ApiResponseStatus e;
156 // No message needed for AS_UNHANDLED; this is an internal flag for the API server
157 e.set_status( ApiStatusCode::AS_UNHANDLED );
158 return tl::unexpected( e );
159 }
160
161 GetOpenDocumentsResponse response;
162 common::types::DocumentSpecifier doc;
163
164 wxFileName fn( frame()->GetCurrentFileName() );
165
166 doc.set_type( DocumentType::DOCTYPE_PCB );
167 doc.set_board_filename( fn.GetFullName() );
168
169 doc.mutable_project()->set_name( frame()->Prj().GetProjectName().ToStdString() );
170 doc.mutable_project()->set_path( frame()->Prj().GetProjectDirectory().ToStdString() );
171
172 response.mutable_documents()->Add( std::move( doc ) );
173 return response;
174}
175
176
179{
180 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
181 return tl::unexpected( *busy );
182
183 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.document() );
184
185 if( !documentValidation )
186 return tl::unexpected( documentValidation.error() );
187
188 frame()->SaveBoard();
189 return Empty();
190}
191
192
195{
196 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
197 return tl::unexpected( *busy );
198
199 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.document() );
200
201 if( !documentValidation )
202 return tl::unexpected( documentValidation.error() );
203
204 wxFileName boardPath( frame()->Prj().AbsolutePath( wxString::FromUTF8( aCtx.Request.path() ) ) );
205
206 if( !boardPath.IsOk() || !boardPath.IsDirWritable() )
207 {
208 ApiResponseStatus e;
209 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
210 e.set_error_message( fmt::format( "save path '{}' could not be opened",
211 boardPath.GetFullPath().ToStdString() ) );
212 return tl::unexpected( e );
213 }
214
215 if( boardPath.FileExists()
216 && ( !boardPath.IsFileWritable() || !aCtx.Request.options().overwrite() ) )
217 {
218 ApiResponseStatus e;
219 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
220 e.set_error_message( fmt::format( "save path '{}' exists and cannot be overwritten",
221 boardPath.GetFullPath().ToStdString() ) );
222 return tl::unexpected( e );
223 }
224
225 if( boardPath.GetExt() != FILEEXT::KiCadPcbFileExtension )
226 {
227 ApiResponseStatus e;
228 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
229 e.set_error_message( fmt::format( "save path '{}' must have a kicad_pcb extension",
230 boardPath.GetFullPath().ToStdString() ) );
231 return tl::unexpected( e );
232 }
233
234 BOARD* board = frame()->GetBoard();
235
236 if( board->GetFileName().Matches( boardPath.GetFullPath() ) )
237 {
238 frame()->SaveBoard();
239 return Empty();
240 }
241
242 bool includeProject = true;
243
244 if( aCtx.Request.has_options() )
245 includeProject = aCtx.Request.options().include_project();
246
247 frame()->SavePcbCopy( boardPath.GetFullPath(), includeProject, /* aHeadless = */ true );
248
249 return Empty();
250}
251
252
255{
256 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
257 return tl::unexpected( *busy );
258
259 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.document() );
260
261 if( !documentValidation )
262 return tl::unexpected( documentValidation.error() );
263
264 wxFileName fn = frame()->Prj().AbsolutePath( frame()->GetBoard()->GetFileName() );
265
266 frame()->GetScreen()->SetContentModified( false );
267 frame()->ReleaseFile();
268 frame()->OpenProjectFiles( std::vector<wxString>( 1, fn.GetFullPath() ), KICTL_REVERT );
269
270 return Empty();
271}
272
273
274void API_HANDLER_PCB::pushCurrentCommit( const std::string& aClientName, const wxString& aMessage )
275{
276 API_HANDLER_EDITOR::pushCurrentCommit( aClientName, aMessage );
277 frame()->Refresh();
278}
279
280
281std::unique_ptr<COMMIT> API_HANDLER_PCB::createCommit()
282{
283 return std::make_unique<BOARD_COMMIT>( frame() );
284}
285
286
287std::optional<BOARD_ITEM*> API_HANDLER_PCB::getItemById( const KIID& aId ) const
288{
289 BOARD_ITEM* item = frame()->GetBoard()->ResolveItem( aId, true );
290
291 if( !item )
292 return std::nullopt;
293
294 return item;
295}
296
297
298bool API_HANDLER_PCB::validateDocumentInternal( const DocumentSpecifier& aDocument ) const
299{
300 if( aDocument.type() != DocumentType::DOCTYPE_PCB )
301 return false;
302
303 wxFileName fn( frame()->GetCurrentFileName() );
304 return 0 == aDocument.board_filename().compare( fn.GetFullName() );
305}
306
307
309 BOARD_ITEM_CONTAINER* aContainer )
310{
311 if( !aContainer )
312 {
313 ApiResponseStatus e;
314 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
315 e.set_error_message( "Tried to create an item in a null container" );
316 return tl::unexpected( e );
317 }
318
319 if( aType == PCB_PAD_T && !dynamic_cast<FOOTPRINT*>( aContainer ) )
320 {
321 ApiResponseStatus e;
322 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
323 e.set_error_message( fmt::format( "Tried to create a pad in {}, which is not a footprint",
324 aContainer->GetFriendlyName().ToStdString() ) );
325 return tl::unexpected( e );
326 }
327 else if( aType == PCB_FOOTPRINT_T && !dynamic_cast<BOARD*>( aContainer ) )
328 {
329 ApiResponseStatus e;
330 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
331 e.set_error_message( fmt::format( "Tried to create a footprint in {}, which is not a board",
332 aContainer->GetFriendlyName().ToStdString() ) );
333 return tl::unexpected( e );
334 }
335
336 std::unique_ptr<BOARD_ITEM> created = CreateItemForType( aType, aContainer );
337
338 if( !created )
339 {
340 ApiResponseStatus e;
341 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
342 e.set_error_message( fmt::format( "Tried to create an item of type {}, which is unhandled",
343 magic_enum::enum_name( aType ) ) );
344 return tl::unexpected( e );
345 }
346
347 return created;
348}
349
350
352 const std::string& aClientName,
353 const types::ItemHeader &aHeader,
354 const google::protobuf::RepeatedPtrField<google::protobuf::Any>& aItems,
355 std::function<void( ItemStatus, google::protobuf::Any )> aItemHandler )
356{
357 ApiResponseStatus e;
358
359 auto containerResult = validateItemHeaderDocument( aHeader );
360
361 if( !containerResult && containerResult.error().status() == ApiStatusCode::AS_UNHANDLED )
362 {
363 // No message needed for AS_UNHANDLED; this is an internal flag for the API server
364 e.set_status( ApiStatusCode::AS_UNHANDLED );
365 return tl::unexpected( e );
366 }
367 else if( !containerResult )
368 {
369 e.CopyFrom( containerResult.error() );
370 return tl::unexpected( e );
371 }
372
373 BOARD* board = frame()->GetBoard();
374 BOARD_ITEM_CONTAINER* container = board;
375
376 if( containerResult->has_value() )
377 {
378 const KIID& containerId = **containerResult;
379 std::optional<BOARD_ITEM*> optItem = getItemById( containerId );
380
381 if( optItem )
382 {
383 container = dynamic_cast<BOARD_ITEM_CONTAINER*>( *optItem );
384
385 if( !container )
386 {
387 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
388 e.set_error_message( fmt::format(
389 "The requested container {} is not a valid board item container",
390 containerId.AsStdString() ) );
391 return tl::unexpected( e );
392 }
393 }
394 else
395 {
396 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
397 e.set_error_message( fmt::format(
398 "The requested container {} does not exist in this document",
399 containerId.AsStdString() ) );
400 return tl::unexpected( e );
401 }
402 }
403
404 BOARD_COMMIT* commit = static_cast<BOARD_COMMIT*>( getCurrentCommit( aClientName ) );
405
406 for( const google::protobuf::Any& anyItem : aItems )
407 {
408 ItemStatus status;
409 std::optional<KICAD_T> type = TypeNameFromAny( anyItem );
410
411 if( !type )
412 {
413 status.set_code( ItemStatusCode::ISC_INVALID_TYPE );
414 status.set_error_message( fmt::format( "Could not decode a valid type from {}",
415 anyItem.type_url() ) );
416 aItemHandler( status, anyItem );
417 continue;
418 }
419
420 if( type == PCB_DIMENSION_T )
421 {
422 board::types::Dimension dimension;
423 anyItem.UnpackTo( &dimension );
424
425 switch( dimension.dimension_style_case() )
426 {
427 case board::types::Dimension::kAligned: type = PCB_DIM_ALIGNED_T; break;
428 case board::types::Dimension::kOrthogonal: type = PCB_DIM_ORTHOGONAL_T; break;
429 case board::types::Dimension::kRadial: type = PCB_DIM_RADIAL_T; break;
430 case board::types::Dimension::kLeader: type = PCB_DIM_LEADER_T; break;
431 case board::types::Dimension::kCenter: type = PCB_DIM_CENTER_T; break;
432 case board::types::Dimension::DIMENSION_STYLE_NOT_SET: break;
433 }
434 }
435
437 createItemForType( *type, container );
438
439 if( !creationResult )
440 {
441 status.set_code( ItemStatusCode::ISC_INVALID_TYPE );
442 status.set_error_message( creationResult.error().error_message() );
443 aItemHandler( status, anyItem );
444 continue;
445 }
446
447 std::unique_ptr<BOARD_ITEM> item( std::move( *creationResult ) );
448
449 if( !item->Deserialize( anyItem ) )
450 {
451 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
452 e.set_error_message( fmt::format( "could not unpack {} from request",
453 item->GetClass().ToStdString() ) );
454 return tl::unexpected( e );
455 }
456
457 std::optional<BOARD_ITEM*> optItem = getItemById( item->m_Uuid );
458
459 if( aCreate && optItem )
460 {
461 status.set_code( ItemStatusCode::ISC_EXISTING );
462 status.set_error_message( fmt::format( "an item with UUID {} already exists",
463 item->m_Uuid.AsStdString() ) );
464 aItemHandler( status, anyItem );
465 continue;
466 }
467 else if( !aCreate && !optItem )
468 {
469 status.set_code( ItemStatusCode::ISC_NONEXISTENT );
470 status.set_error_message( fmt::format( "an item with UUID {} does not exist",
471 item->m_Uuid.AsStdString() ) );
472 aItemHandler( status, anyItem );
473 continue;
474 }
475
476 if( aCreate && !( board->GetEnabledLayers() & item->GetLayerSet() ).any() )
477 {
478 status.set_code( ItemStatusCode::ISC_INVALID_DATA );
479 status.set_error_message(
480 "attempted to add item with no overlapping layers with the board" );
481 aItemHandler( status, anyItem );
482 continue;
483 }
484
485 status.set_code( ItemStatusCode::ISC_OK );
486 google::protobuf::Any newItem;
487
488 if( aCreate )
489 {
490 if( item->Type() == PCB_FOOTPRINT_T )
491 {
492 // Ensure children have unique identifiers; in case the API client created this new
493 // footprint by cloning an existing one and only changing the parent UUID.
494 item->RunOnChildren(
495 []( BOARD_ITEM* aChild )
496 {
497 const_cast<KIID&>( aChild->m_Uuid ) = KIID();
498 },
499 RECURSE );
500 }
501
502 item->Serialize( newItem );
503 commit->Add( item.release() );
504 }
505 else
506 {
507 BOARD_ITEM* boardItem = *optItem;
508
509 // Footprints can't be modified by CopyFrom at the moment because the commit system
510 // doesn't currently know what to do with a footprint that has had its children
511 // replaced with other children; which results in things like the view not having its
512 // cached geometry for footprint children updated when you move a footprint around.
513 // And also, groups are special because they can contain any item type, so we
514 // can't use CopyFrom on them either.
515 if( boardItem->Type() == PCB_FOOTPRINT_T || boardItem->Type() == PCB_GROUP_T )
516 {
517 // Save group membership before removal, since Remove() severs the relationship
518 PCB_GROUP* parentGroup = dynamic_cast<PCB_GROUP*>( boardItem->GetParentGroup() );
519
520 commit->Remove( boardItem );
521 item->Serialize( newItem );
522
523 BOARD_ITEM* newBoardItem = item.release();
524 commit->Add( newBoardItem );
525
526 // Restore group membership for the newly added item
527 if( parentGroup )
528 parentGroup->AddItem( newBoardItem );
529 }
530 else
531 {
532 commit->Modify( boardItem );
533 boardItem->CopyFrom( item.get() );
534 boardItem->Serialize( newItem );
535 }
536 }
537
538 aItemHandler( status, newItem );
539 }
540
541 if( !m_activeClients.count( aClientName ) )
542 {
543 pushCurrentCommit( aClientName, aCreate ? _( "Created items via API" )
544 : _( "Modified items via API" ) );
545 }
546
547
548 return ItemRequestStatus::IRS_OK;
549}
550
551
553{
554 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
555 return tl::unexpected( *busy );
556
557 if( !validateItemHeaderDocument( aCtx.Request.header() ) )
558 {
559 ApiResponseStatus e;
560 // No message needed for AS_UNHANDLED; this is an internal flag for the API server
561 e.set_status( ApiStatusCode::AS_UNHANDLED );
562 return tl::unexpected( e );
563 }
564
565 GetItemsResponse response;
566
567 BOARD* board = frame()->GetBoard();
568 std::vector<BOARD_ITEM*> items;
569 std::set<KICAD_T> typesRequested, typesInserted;
570 bool handledAnything = false;
571
572 for( int typeRaw : aCtx.Request.types() )
573 {
574 auto typeMessage = static_cast<common::types::KiCadObjectType>( typeRaw );
575 KICAD_T type = FromProtoEnum<KICAD_T>( typeMessage );
576
577 if( type == TYPE_NOT_INIT )
578 continue;
579
580 typesRequested.emplace( type );
581
582 if( typesInserted.count( type ) )
583 continue;
584
585 switch( type )
586 {
587 case PCB_TRACE_T:
588 case PCB_ARC_T:
589 case PCB_VIA_T:
590 handledAnything = true;
591 std::copy( board->Tracks().begin(), board->Tracks().end(),
592 std::back_inserter( items ) );
593 typesInserted.insert( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T } );
594 break;
595
596 case PCB_PAD_T:
597 {
598 handledAnything = true;
599
600 for( FOOTPRINT* fp : board->Footprints() )
601 {
602 std::copy( fp->Pads().begin(), fp->Pads().end(),
603 std::back_inserter( items ) );
604 }
605
606 typesInserted.insert( PCB_PAD_T );
607 break;
608 }
609
610 case PCB_FOOTPRINT_T:
611 {
612 handledAnything = true;
613
614 std::copy( board->Footprints().begin(), board->Footprints().end(),
615 std::back_inserter( items ) );
616
617 typesInserted.insert( PCB_FOOTPRINT_T );
618 break;
619 }
620
621 case PCB_SHAPE_T:
622 case PCB_TEXT_T:
623 case PCB_TEXTBOX_T:
624 case PCB_BARCODE_T:
625 {
626 handledAnything = true;
627 bool inserted = false;
628
629 for( BOARD_ITEM* item : board->Drawings() )
630 {
631 if( item->Type() == type )
632 {
633 items.emplace_back( item );
634 inserted = true;
635 }
636 }
637
638 if( inserted )
639 typesInserted.insert( type );
640
641 break;
642 }
643
644 case PCB_ZONE_T:
645 {
646 handledAnything = true;
647
648 std::copy( board->Zones().begin(), board->Zones().end(),
649 std::back_inserter( items ) );
650
651 typesInserted.insert( PCB_ZONE_T );
652 break;
653 }
654
655 case PCB_GROUP_T:
656 {
657 handledAnything = true;
658
659 std::copy( board->Groups().begin(), board->Groups().end(),
660 std::back_inserter( items ) );
661
662 typesInserted.insert( PCB_GROUP_T );
663 break;
664 }
665 default:
666 break;
667 }
668 }
669
670 if( !handledAnything )
671 {
672 ApiResponseStatus e;
673 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
674 e.set_error_message( "none of the requested types are valid for a Board object" );
675 return tl::unexpected( e );
676 }
677
678 for( const BOARD_ITEM* item : items )
679 {
680 if( !typesRequested.count( item->Type() ) )
681 continue;
682
683 google::protobuf::Any itemBuf;
684 item->Serialize( itemBuf );
685 response.mutable_items()->Add( std::move( itemBuf ) );
686 }
687
688 response.set_status( ItemRequestStatus::IRS_OK );
689 return response;
690}
691
692
695{
696 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
697 return tl::unexpected( *busy );
698
699 if( !validateItemHeaderDocument( aCtx.Request.header() ) )
700 {
701 ApiResponseStatus e;
702 e.set_status( ApiStatusCode::AS_UNHANDLED );
703 return tl::unexpected( e );
704 }
705
706 GetItemsResponse response;
707
708 std::vector<BOARD_ITEM*> items;
709
710 for( const kiapi::common::types::KIID& id : aCtx.Request.items() )
711 {
712 if( std::optional<BOARD_ITEM*> item = getItemById( KIID( id.value() ) ) )
713 items.emplace_back( *item );
714 }
715
716 if( items.empty() )
717 {
718 ApiResponseStatus e;
719 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
720 e.set_error_message( "none of the requested IDs were found or valid" );
721 return tl::unexpected( e );
722 }
723
724 for( const BOARD_ITEM* item : items )
725 {
726 google::protobuf::Any itemBuf;
727 item->Serialize( itemBuf );
728 response.mutable_items()->Add( std::move( itemBuf ) );
729 }
730
731 response.set_status( ItemRequestStatus::IRS_OK );
732 return response;
733}
734
735void API_HANDLER_PCB::deleteItemsInternal( std::map<KIID, ItemDeletionStatus>& aItemsToDelete,
736 const std::string& aClientName )
737{
738 BOARD* board = frame()->GetBoard();
739 std::vector<BOARD_ITEM*> validatedItems;
740
741 for( std::pair<const KIID, ItemDeletionStatus> pair : aItemsToDelete )
742 {
743 if( BOARD_ITEM* item = board->ResolveItem( pair.first, true ) )
744 {
745 validatedItems.push_back( item );
746 aItemsToDelete[pair.first] = ItemDeletionStatus::IDS_OK;
747 }
748
749 // Note: we don't currently support locking items from API modification, but here is where
750 // to add it in the future (and return IDS_IMMUTABLE)
751 }
752
753 COMMIT* commit = getCurrentCommit( aClientName );
754
755 for( BOARD_ITEM* item : validatedItems )
756 commit->Remove( item );
757
758 if( !m_activeClients.count( aClientName ) )
759 pushCurrentCommit( aClientName, _( "Deleted items via API" ) );
760}
761
762
763std::optional<EDA_ITEM*> API_HANDLER_PCB::getItemFromDocument( const DocumentSpecifier& aDocument,
764 const KIID& aId )
765{
766 if( !validateDocument( aDocument ) )
767 return std::nullopt;
768
769 return getItemById( aId );
770}
771
772
775{
776 if( !validateItemHeaderDocument( aCtx.Request.header() ) )
777 {
778 ApiResponseStatus e;
779 // No message needed for AS_UNHANDLED; this is an internal flag for the API server
780 e.set_status( ApiStatusCode::AS_UNHANDLED );
781 return tl::unexpected( e );
782 }
783
784 std::set<KICAD_T> filter;
785
786 for( int typeRaw : aCtx.Request.types() )
787 {
788 auto typeMessage = static_cast<types::KiCadObjectType>( typeRaw );
789 KICAD_T type = FromProtoEnum<KICAD_T>( typeMessage );
790
791 if( type == TYPE_NOT_INIT )
792 continue;
793
794 filter.insert( type );
795 }
796
798 PCB_SELECTION_TOOL* selectionTool = mgr->GetTool<PCB_SELECTION_TOOL>();
799
800 SelectionResponse response;
801
802 for( EDA_ITEM* item : selectionTool->GetSelection() )
803 {
804 if( filter.empty() || filter.contains( item->Type() ) )
805 item->Serialize( *response.add_items() );
806 }
807
808 return response;
809}
810
811
814{
815 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
816 return tl::unexpected( *busy );
817
818 if( !validateItemHeaderDocument( aCtx.Request.header() ) )
819 {
820 ApiResponseStatus e;
821 // No message needed for AS_UNHANDLED; this is an internal flag for the API server
822 e.set_status( ApiStatusCode::AS_UNHANDLED );
823 return tl::unexpected( e );
824 }
825
828 frame()->Refresh();
829
830 return Empty();
831}
832
833
836{
837 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
838 return tl::unexpected( *busy );
839
840 if( !validateItemHeaderDocument( aCtx.Request.header() ) )
841 {
842 ApiResponseStatus e;
843 // No message needed for AS_UNHANDLED; this is an internal flag for the API server
844 e.set_status( ApiStatusCode::AS_UNHANDLED );
845 return tl::unexpected( e );
846 }
847
849 PCB_SELECTION_TOOL* selectionTool = mgr->GetTool<PCB_SELECTION_TOOL>();
850
851 std::vector<EDA_ITEM*> toAdd;
852
853 for( const types::KIID& id : aCtx.Request.items() )
854 {
855 if( std::optional<BOARD_ITEM*> item = getItemById( KIID( id.value() ) ) )
856 toAdd.emplace_back( *item );
857 }
858
859 selectionTool->AddItemsToSel( &toAdd );
860 frame()->Refresh();
861
862 SelectionResponse response;
863
864 for( EDA_ITEM* item : selectionTool->GetSelection() )
865 item->Serialize( *response.add_items() );
866
867 return response;
868}
869
870
873{
874 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
875 return tl::unexpected( *busy );
876
877 if( !validateItemHeaderDocument( aCtx.Request.header() ) )
878 {
879 ApiResponseStatus e;
880 // No message needed for AS_UNHANDLED; this is an internal flag for the API server
881 e.set_status( ApiStatusCode::AS_UNHANDLED );
882 return tl::unexpected( e );
883 }
884
886 PCB_SELECTION_TOOL* selectionTool = mgr->GetTool<PCB_SELECTION_TOOL>();
887
888 std::vector<EDA_ITEM*> toRemove;
889
890 for( const types::KIID& id : aCtx.Request.items() )
891 {
892 if( std::optional<BOARD_ITEM*> item = getItemById( KIID( id.value() ) ) )
893 toRemove.emplace_back( *item );
894 }
895
896 selectionTool->RemoveItemsFromSel( &toRemove );
897 frame()->Refresh();
898
899 SelectionResponse response;
900
901 for( EDA_ITEM* item : selectionTool->GetSelection() )
902 item->Serialize( *response.add_items() );
903
904 return response;
905}
906
907
910{
911 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.board() );
912
913 if( !documentValidation )
914 return tl::unexpected( documentValidation.error() );
915
916 BoardStackupResponse response;
917 google::protobuf::Any any;
918
920
921 any.UnpackTo( response.mutable_stackup() );
922
923 // User-settable layer names are not stored in BOARD_STACKUP at the moment
924 for( board::BoardStackupLayer& layer : *response.mutable_stackup()->mutable_layers() )
925 {
926 if( layer.type() == board::BoardStackupLayerType::BSLT_DIELECTRIC )
927 continue;
928
929 PCB_LAYER_ID id = FromProtoEnum<PCB_LAYER_ID>( layer.layer() );
930 wxCHECK2( id != UNDEFINED_LAYER, continue );
931
932 layer.set_user_name( frame()->GetBoard()->GetLayerName( id ) );
933 }
934
935 return response;
936}
937
938
941{
942 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.board() );
943
944 if( !documentValidation )
945 return tl::unexpected( documentValidation.error() );
946
947 BoardEnabledLayersResponse response;
948
949 BOARD* board = frame()->GetBoard();
950 int copperLayerCount = board->GetCopperLayerCount();
951
952 response.set_copper_layer_count( copperLayerCount );
953
954 LSET enabled = board->GetEnabledLayers();
955
956 // The Rescue layer is an internal detail and should be hidden from the API
957 enabled.reset( Rescue );
958
959 // Just in case this is out of sync; the API should always return the expected copper layers
960 enabled |= LSET::AllCuMask( copperLayerCount );
961
962 board::PackLayerSet( *response.mutable_layers(), enabled );
963
964 return response;
965}
966
967
970{
971 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.board() );
972
973 if( !documentValidation )
974 return tl::unexpected( documentValidation.error() );
975
976 if( aCtx.Request.copper_layer_count() % 2 != 0 )
977 {
978 ApiResponseStatus e;
979 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
980 e.set_error_message( "copper_layer_count must be an even number" );
981 return tl::unexpected( e );
982 }
983
984 if( aCtx.Request.copper_layer_count() > MAX_CU_LAYERS )
985 {
986 ApiResponseStatus e;
987 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
988 e.set_error_message( fmt::format( "copper_layer_count must be below %d", MAX_CU_LAYERS ) );
989 return tl::unexpected( e );
990 }
991
992 int copperLayerCount = static_cast<int>( aCtx.Request.copper_layer_count() );
993 LSET enabled = board::UnpackLayerSet( aCtx.Request.layers() );
994
995 // Sanitize the input
996 enabled |= LSET( { Edge_Cuts, Margin, F_CrtYd, B_CrtYd } );
997 enabled &= ~LSET::AllCuMask();
998 enabled |= LSET::AllCuMask( copperLayerCount );
999
1000 BOARD* board = frame()->GetBoard();
1001
1002 LSET previousEnabled = board->GetEnabledLayers();
1003 LSET changedLayers = enabled ^ previousEnabled;
1004
1005 board->SetEnabledLayers( enabled );
1006 board->SetVisibleLayers( board->GetVisibleLayers() | changedLayers );
1007
1008 LSEQ removedLayers;
1009
1010 for( PCB_LAYER_ID layer_id : previousEnabled )
1011 {
1012 if( !enabled[layer_id] && board->HasItemsOnLayer( layer_id ) )
1013 removedLayers.push_back( layer_id );
1014 }
1015
1016 bool modified = false;
1017
1018 if( !removedLayers.empty() )
1019 {
1020 m_frame->GetToolManager()->RunAction( PCB_ACTIONS::selectionClear );
1021
1022 for( PCB_LAYER_ID layer_id : removedLayers )
1023 modified |= board->RemoveAllItemsOnLayer( layer_id );
1024 }
1025
1026 if( enabled != previousEnabled )
1028
1029 if( modified )
1030 frame()->OnModify();
1031
1032 BoardEnabledLayersResponse response;
1033
1034 response.set_copper_layer_count( copperLayerCount );
1035 board::PackLayerSet( *response.mutable_layers(), enabled );
1036
1037 return response;
1038}
1039
1040
1043{
1044 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.board() );
1045
1046 if( !documentValidation )
1047 return tl::unexpected( documentValidation.error() );
1048
1050 GraphicsDefaultsResponse response;
1051
1052 // TODO: This should change to be an enum class
1053 constexpr std::array<kiapi::board::BoardLayerClass, LAYER_CLASS_COUNT> classOrder = {
1054 kiapi::board::BLC_SILKSCREEN,
1055 kiapi::board::BLC_COPPER,
1056 kiapi::board::BLC_EDGES,
1057 kiapi::board::BLC_COURTYARD,
1058 kiapi::board::BLC_FABRICATION,
1059 kiapi::board::BLC_OTHER
1060 };
1061
1062 for( int i = 0; i < LAYER_CLASS_COUNT; ++i )
1063 {
1064 kiapi::board::BoardLayerGraphicsDefaults* l = response.mutable_defaults()->add_layers();
1065
1066 l->set_layer( classOrder[i] );
1067 l->mutable_line_thickness()->set_value_nm( bds.m_LineThickness[i] );
1068
1069 kiapi::common::types::TextAttributes* text = l->mutable_text();
1070 text->mutable_size()->set_x_nm( bds.m_TextSize[i].x );
1071 text->mutable_size()->set_y_nm( bds.m_TextSize[i].y );
1072 text->mutable_stroke_width()->set_value_nm( bds.m_TextThickness[i] );
1073 text->set_italic( bds.m_TextItalic[i] );
1074 text->set_keep_upright( bds.m_TextUpright[i] );
1075 }
1076
1077 return response;
1078}
1079
1080
1083{
1084 if( HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.board() );
1085 !documentValidation )
1086 {
1087 return tl::unexpected( documentValidation.error() );
1088 }
1089
1090 VECTOR2I origin;
1091 const BOARD_DESIGN_SETTINGS& settings = frame()->GetBoard()->GetDesignSettings();
1092
1093 switch( aCtx.Request.type() )
1094 {
1095 case BOT_GRID:
1096 origin = settings.GetGridOrigin();
1097 break;
1098
1099 case BOT_DRILL:
1100 origin = settings.GetAuxOrigin();
1101 break;
1102
1103 default:
1104 case BOT_UNKNOWN:
1105 {
1106 ApiResponseStatus e;
1107 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1108 e.set_error_message( "Unexpected origin type" );
1109 return tl::unexpected( e );
1110 }
1111 }
1112
1113 types::Vector2 reply;
1114 PackVector2( reply, origin );
1115 return reply;
1116}
1117
1120{
1121 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
1122 return tl::unexpected( *busy );
1123
1124 if( HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.board() );
1125 !documentValidation )
1126 {
1127 return tl::unexpected( documentValidation.error() );
1128 }
1129
1130 VECTOR2I origin = UnpackVector2( aCtx.Request.origin() );
1131
1132 switch( aCtx.Request.type() )
1133 {
1134 case BOT_GRID:
1135 {
1136 PCB_EDIT_FRAME* f = frame();
1137
1138 frame()->CallAfter( [f, origin]()
1139 {
1140 // gridSetOrigin takes ownership and frees this
1141 VECTOR2D* dorigin = new VECTOR2D( origin );
1142 TOOL_MANAGER* mgr = f->GetToolManager();
1143 mgr->RunAction( PCB_ACTIONS::gridSetOrigin, dorigin );
1144 f->Refresh();
1145 } );
1146 break;
1147 }
1148
1149 case BOT_DRILL:
1150 {
1151 PCB_EDIT_FRAME* f = frame();
1152
1153 frame()->CallAfter( [f, origin]()
1154 {
1155 TOOL_MANAGER* mgr = f->GetToolManager();
1156 mgr->RunAction( PCB_ACTIONS::drillSetOrigin, origin );
1157 f->Refresh();
1158 } );
1159 break;
1160 }
1161
1162 default:
1163 case BOT_UNKNOWN:
1164 {
1165 ApiResponseStatus e;
1166 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1167 e.set_error_message( "Unexpected origin type" );
1168 return tl::unexpected( e );
1169 }
1170 }
1171
1172 return Empty();
1173}
1174
1175
1178{
1179 if( HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.board() );
1180 !documentValidation )
1181 {
1182 return tl::unexpected( documentValidation.error() );
1183 }
1184
1185 BoardLayerNameResponse response;
1186
1188
1189 response.set_name( frame()->GetBoard()->GetLayerName( id ) );
1190
1191 return response;
1192}
1193
1194
1197{
1198 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
1199 return tl::unexpected( *busy );
1200
1201 if( !validateItemHeaderDocument( aCtx.Request.header() ) )
1202 {
1203 ApiResponseStatus e;
1204 // No message needed for AS_UNHANDLED; this is an internal flag for the API server
1205 e.set_status( ApiStatusCode::AS_UNHANDLED );
1206 return tl::unexpected( e );
1207 }
1208
1209 GetBoundingBoxResponse response;
1210 bool includeText = aCtx.Request.mode() == BoundingBoxMode::BBM_ITEM_AND_CHILD_TEXT;
1211
1212 for( const types::KIID& idMsg : aCtx.Request.items() )
1213 {
1214 KIID id( idMsg.value() );
1215 std::optional<BOARD_ITEM*> optItem = getItemById( id );
1216
1217 if( !optItem )
1218 continue;
1219
1220 BOARD_ITEM* item = *optItem;
1221 BOX2I bbox;
1222
1223 if( item->Type() == PCB_FOOTPRINT_T )
1224 bbox = static_cast<FOOTPRINT*>( item )->GetBoundingBox( includeText );
1225 else
1226 bbox = item->GetBoundingBox();
1227
1228 response.add_items()->set_value( idMsg.value() );
1229 PackBox2( *response.add_boxes(), bbox );
1230 }
1231
1232 return response;
1233}
1234
1235
1238{
1239 if( HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.board() );
1240 !documentValidation )
1241 {
1242 return tl::unexpected( documentValidation.error() );
1243 }
1244
1245 PadShapeAsPolygonResponse response;
1247
1248 for( const types::KIID& padRequest : aCtx.Request.pads() )
1249 {
1250 KIID id( padRequest.value() );
1251 std::optional<BOARD_ITEM*> optPad = getItemById( id );
1252
1253 if( !optPad || ( *optPad )->Type() != PCB_PAD_T )
1254 continue;
1255
1256 response.add_pads()->set_value( padRequest.value() );
1257
1258 PAD* pad = static_cast<PAD*>( *optPad );
1259 SHAPE_POLY_SET poly;
1260 pad->TransformShapeToPolygon( poly, pad->Padstack().EffectiveLayerFor( layer ), 0,
1261 pad->GetMaxError(), ERROR_INSIDE );
1262
1263 types::PolygonWithHoles* polyMsg = response.mutable_polygons()->Add();
1264 PackPolyLine( *polyMsg->mutable_outline(), poly.COutline( 0 ) );
1265 }
1266
1267 return response;
1268}
1269
1270
1273{
1274 using board::types::BoardLayer;
1275
1276 if( HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.board() );
1277 !documentValidation )
1278 {
1279 return tl::unexpected( documentValidation.error() );
1280 }
1281
1282 PadstackPresenceResponse response;
1283
1284 LSET layers;
1285
1286 for( const int layer : aCtx.Request.layers() )
1287 layers.set( FromProtoEnum<PCB_LAYER_ID, BoardLayer>( static_cast<BoardLayer>( layer ) ) );
1288
1289 for( const types::KIID& padRequest : aCtx.Request.items() )
1290 {
1291 KIID id( padRequest.value() );
1292 std::optional<BOARD_ITEM*> optItem = getItemById( id );
1293
1294 if( !optItem )
1295 continue;
1296
1297 switch( ( *optItem )->Type() )
1298 {
1299 case PCB_PAD_T:
1300 {
1301 PAD* pad = static_cast<PAD*>( *optItem );
1302
1303 for( PCB_LAYER_ID layer : layers )
1304 {
1305 PadstackPresenceEntry* entry = response.add_entries();
1306 entry->mutable_item()->set_value( pad->m_Uuid.AsStdString() );
1307 entry->set_layer( ToProtoEnum<PCB_LAYER_ID, BoardLayer>( layer ) );
1308 entry->set_presence( pad->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT );
1309 }
1310
1311 break;
1312 }
1313
1314 case PCB_VIA_T:
1315 {
1316 PCB_VIA* via = static_cast<PCB_VIA*>( *optItem );
1317
1318 for( PCB_LAYER_ID layer : layers )
1319 {
1320 PadstackPresenceEntry* entry = response.add_entries();
1321 entry->mutable_item()->set_value( via->m_Uuid.AsStdString() );
1322 entry->set_layer( ToProtoEnum<PCB_LAYER_ID, BoardLayer>( layer ) );
1323 entry->set_presence( via->FlashLayer( layer ) ? PSP_PRESENT : PSP_NOT_PRESENT );
1324 }
1325
1326 break;
1327 }
1328
1329 default:
1330 break;
1331 }
1332 }
1333
1334 return response;
1335}
1336
1337
1340{
1341 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.document() );
1342
1343 if( !documentValidation )
1344 return tl::unexpected( documentValidation.error() );
1345
1346 BOARD* board = frame()->GetBoard();
1347 const TITLE_BLOCK& block = board->GetTitleBlock();
1348
1349 types::TitleBlockInfo response;
1350
1351 response.set_title( block.GetTitle().ToUTF8() );
1352 response.set_date( block.GetDate().ToUTF8() );
1353 response.set_revision( block.GetRevision().ToUTF8() );
1354 response.set_company( block.GetCompany().ToUTF8() );
1355 response.set_comment1( block.GetComment( 0 ).ToUTF8() );
1356 response.set_comment2( block.GetComment( 1 ).ToUTF8() );
1357 response.set_comment3( block.GetComment( 2 ).ToUTF8() );
1358 response.set_comment4( block.GetComment( 3 ).ToUTF8() );
1359 response.set_comment5( block.GetComment( 4 ).ToUTF8() );
1360 response.set_comment6( block.GetComment( 5 ).ToUTF8() );
1361 response.set_comment7( block.GetComment( 6 ).ToUTF8() );
1362 response.set_comment8( block.GetComment( 7 ).ToUTF8() );
1363 response.set_comment9( block.GetComment( 8 ).ToUTF8() );
1364
1365 return response;
1366}
1367
1368
1371{
1372 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.document() );
1373
1374 if( !documentValidation )
1375 return tl::unexpected( documentValidation.error() );
1376
1377 ExpandTextVariablesResponse reply;
1378 BOARD* board = frame()->GetBoard();
1379
1380 std::function<bool( wxString* )> textResolver =
1381 [&]( wxString* token ) -> bool
1382 {
1383 // Handles m_board->GetTitleBlock() *and* m_board->GetProject()
1384 return board->ResolveTextVar( token, 0 );
1385 };
1386
1387 for( const std::string& textMsg : aCtx.Request.text() )
1388 {
1389 wxString text = ExpandTextVars( wxString::FromUTF8( textMsg ), &textResolver );
1390 reply.add_text( text.ToUTF8() );
1391 }
1392
1393 return reply;
1394}
1395
1396
1399{
1400 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
1401 return tl::unexpected( *busy );
1402
1403 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.board() );
1404
1405 if( !documentValidation )
1406 return tl::unexpected( documentValidation.error() );
1407
1408 TOOL_MANAGER* mgr = frame()->GetToolManager();
1409 std::vector<EDA_ITEM*> toSelect;
1410
1411 for( const kiapi::common::types::KIID& id : aCtx.Request.items() )
1412 {
1413 if( std::optional<BOARD_ITEM*> item = getItemById( KIID( id.value() ) ) )
1414 toSelect.emplace_back( static_cast<EDA_ITEM*>( *item ) );
1415 }
1416
1417 if( toSelect.empty() )
1418 {
1419 ApiResponseStatus e;
1420 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
1421 e.set_error_message( fmt::format( "None of the given items exist on the board",
1422 aCtx.Request.board().board_filename() ) );
1423 return tl::unexpected( e );
1424 }
1425
1426 PCB_SELECTION_TOOL* selectionTool = mgr->GetTool<PCB_SELECTION_TOOL>();
1427 selectionTool->GetSelection().SetReferencePoint( toSelect[0]->GetPosition() );
1428
1430 mgr->RunAction<EDA_ITEMS*>( ACTIONS::selectItems, &toSelect );
1431
1432 COMMIT* commit = getCurrentCommit( aCtx.ClientName );
1433 mgr->PostAPIAction( PCB_ACTIONS::move, commit );
1434
1435 return Empty();
1436}
1437
1438
1440{
1441 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.board() );
1442
1443 if( !documentValidation )
1444 return tl::unexpected( documentValidation.error() );
1445
1446 NetsResponse response;
1447 BOARD* board = frame()->GetBoard();
1448
1449 std::set<wxString> netclassFilter;
1450
1451 for( const std::string& nc : aCtx.Request.netclass_filter() )
1452 netclassFilter.insert( wxString( nc.c_str(), wxConvUTF8 ) );
1453
1454 for( NETINFO_ITEM* net : board->GetNetInfo() )
1455 {
1456 NETCLASS* nc = net->GetNetClass();
1457
1458 if( !netclassFilter.empty() && nc && !netclassFilter.count( nc->GetName() ) )
1459 continue;
1460
1461 board::types::Net* netProto = response.add_nets();
1462 netProto->set_name( net->GetNetname() );
1463 netProto->mutable_code()->set_value( net->GetNetCode() );
1464 }
1465
1466 return response;
1467}
1468
1469
1472{
1473 NetClassForNetsResponse response;
1474
1475 BOARD* board = frame()->GetBoard();
1476 const NETINFO_LIST& nets = board->GetNetInfo();
1477 google::protobuf::Any any;
1478
1479 for( const board::types::Net& net : aCtx.Request.net() )
1480 {
1481 NETINFO_ITEM* netInfo = nets.GetNetItem( wxString::FromUTF8( net.name() ) );
1482
1483 if( !netInfo )
1484 continue;
1485
1486 netInfo->GetNetClass()->Serialize( any );
1487 auto [pair, rc] = response.mutable_classes()->insert( { net.name(), {} } );
1488 any.UnpackTo( &pair->second );
1489 }
1490
1491 return response;
1492}
1493
1494
1496{
1497 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
1498 return tl::unexpected( *busy );
1499
1500 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.board() );
1501
1502 if( !documentValidation )
1503 return tl::unexpected( documentValidation.error() );
1504
1505 if( aCtx.Request.zones().empty() )
1506 {
1507 TOOL_MANAGER* mgr = frame()->GetToolManager();
1508 frame()->CallAfter( [mgr]()
1509 {
1511 } );
1512 }
1513 else
1514 {
1515 // TODO
1516 ApiResponseStatus e;
1517 e.set_status( ApiStatusCode::AS_UNIMPLEMENTED );
1518 return tl::unexpected( e );
1519 }
1520
1521 return Empty();
1522}
1523
1524
1527{
1528 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.document() );
1529
1530 if( !documentValidation )
1531 return tl::unexpected( documentValidation.error() );
1532
1533 SavedDocumentResponse response;
1534 response.mutable_document()->CopyFrom( aCtx.Request.document() );
1535
1536 CLIPBOARD_IO io;
1537 io.SetWriter(
1538 [&]( const wxString& aData )
1539 {
1540 response.set_contents( aData.ToUTF8() );
1541 } );
1542
1543 io.SaveBoard( wxEmptyString, frame()->GetBoard(), nullptr );
1544
1545 return response;
1546}
1547
1548
1551{
1552 SavedSelectionResponse response;
1553
1554 TOOL_MANAGER* mgr = frame()->GetToolManager();
1555 PCB_SELECTION_TOOL* selectionTool = mgr->GetTool<PCB_SELECTION_TOOL>();
1556 PCB_SELECTION& selection = selectionTool->GetSelection();
1557
1558 CLIPBOARD_IO io;
1559 io.SetWriter(
1560 [&]( const wxString& aData )
1561 {
1562 response.set_contents( aData.ToUTF8() );
1563 } );
1564
1565 io.SetBoard( frame()->GetBoard() );
1566 io.SaveSelection( selection, false );
1567
1568 return response;
1569}
1570
1571
1574{
1575 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
1576 return tl::unexpected( *busy );
1577
1578 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.document() );
1579
1580 if( !documentValidation )
1581 return tl::unexpected( documentValidation.error() );
1582
1583 CreateItemsResponse response;
1584 return response;
1585}
1586
1587
1590{
1591 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.board() );
1592
1593 if( !documentValidation )
1594 return tl::unexpected( documentValidation.error() );
1595
1596 BoardLayers response;
1597
1598 for( PCB_LAYER_ID layer : frame()->GetBoard()->GetVisibleLayers() )
1599 response.add_layers( ToProtoEnum<PCB_LAYER_ID, board::types::BoardLayer>( layer ) );
1600
1601 return response;
1602}
1603
1604
1607{
1608 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
1609 return tl::unexpected( *busy );
1610
1611 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.board() );
1612
1613 if( !documentValidation )
1614 return tl::unexpected( documentValidation.error() );
1615
1616 LSET visible;
1617 LSET enabled = frame()->GetBoard()->GetEnabledLayers();
1618
1619 for( int layerIdx : aCtx.Request.layers() )
1620 {
1621 PCB_LAYER_ID layer =
1622 FromProtoEnum<PCB_LAYER_ID>( static_cast<board::types::BoardLayer>( layerIdx ) );
1623
1624 if( enabled.Contains( layer ) )
1625 visible.set( layer );
1626 }
1627
1628 frame()->GetBoard()->SetVisibleLayers( visible );
1631 frame()->Refresh();
1632 return Empty();
1633}
1634
1635
1638{
1639 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.board() );
1640
1641 if( !documentValidation )
1642 return tl::unexpected( documentValidation.error() );
1643
1644 BoardLayerResponse response;
1645 response.set_layer(
1647
1648 return response;
1649}
1650
1651
1654{
1655 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
1656 return tl::unexpected( *busy );
1657
1658 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.board() );
1659
1660 if( !documentValidation )
1661 return tl::unexpected( documentValidation.error() );
1662
1663 PCB_LAYER_ID layer = FromProtoEnum<PCB_LAYER_ID>( aCtx.Request.layer() );
1664
1665 if( !frame()->GetBoard()->GetEnabledLayers().Contains( layer ) )
1666 {
1667 ApiResponseStatus err;
1668 err.set_status( ApiStatusCode::AS_BAD_REQUEST );
1669 err.set_error_message( fmt::format( "Layer {} is not a valid layer for the given board",
1670 magic_enum::enum_name( layer ) ) );
1671 return tl::unexpected( err );
1672 }
1673
1674 frame()->SetActiveLayer( layer );
1675 return Empty();
1676}
1677
1678
1681{
1682 BoardEditorAppearanceSettings reply;
1683
1684 // TODO: might be nice to put all these things in one place and have it derive SERIALIZABLE
1685
1686 const PCB_DISPLAY_OPTIONS& displayOptions = frame()->GetDisplayOptions();
1687
1688 reply.set_inactive_layer_display( ToProtoEnum<HIGH_CONTRAST_MODE, InactiveLayerDisplayMode>(
1689 displayOptions.m_ContrastModeDisplay ) );
1690 reply.set_net_color_display(
1692
1693 reply.set_board_flip( frame()->GetCanvas()->GetView()->IsMirroredX()
1694 ? BoardFlipMode::BFM_FLIPPED_X
1695 : BoardFlipMode::BFM_NORMAL );
1696
1697 PCBNEW_SETTINGS* editorSettings = frame()->GetPcbNewSettings();
1698
1699 reply.set_ratsnest_display( ToProtoEnum<RATSNEST_MODE, RatsnestDisplayMode>(
1700 editorSettings->m_Display.m_RatsnestMode ) );
1701
1702 return reply;
1703}
1704
1705
1708{
1709 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
1710 return tl::unexpected( *busy );
1711
1713 KIGFX::PCB_VIEW* view = frame()->GetCanvas()->GetView();
1714 PCBNEW_SETTINGS* editorSettings = frame()->GetPcbNewSettings();
1715 const BoardEditorAppearanceSettings& newSettings = aCtx.Request.settings();
1716
1717 options.m_ContrastModeDisplay =
1718 FromProtoEnum<HIGH_CONTRAST_MODE>( newSettings.inactive_layer_display() );
1719 options.m_NetColorMode =
1720 FromProtoEnum<NET_COLOR_MODE>( newSettings.net_color_display() );
1721
1722 bool flip = newSettings.board_flip() == BoardFlipMode::BFM_FLIPPED_X;
1723
1724 if( flip != view->IsMirroredX() )
1725 {
1726 view->SetMirror( !view->IsMirroredX(), view->IsMirroredY() );
1727 view->RecacheAllItems();
1728 }
1729
1730 editorSettings->m_Display.m_RatsnestMode =
1731 FromProtoEnum<RATSNEST_MODE>( newSettings.ratsnest_display() );
1732
1733 frame()->SetDisplayOptions( options );
1735 frame()->GetCanvas()->Refresh();
1736
1737 return Empty();
1738}
1739
1740
1743{
1744 if( std::optional<ApiResponseStatus> busy = checkForBusy() )
1745 return tl::unexpected( *busy );
1746
1747 HANDLER_RESULT<bool> documentValidation = validateDocument( aCtx.Request.board() );
1748
1749 if( !documentValidation )
1750 return tl::unexpected( documentValidation.error() );
1751
1752 SEVERITY severity = FromProtoEnum<SEVERITY>( aCtx.Request.severity() );
1753 int layer = severity == RPT_SEVERITY_WARNING ? LAYER_DRC_WARNING : LAYER_DRC_ERROR;
1755
1756 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( code );
1757
1758 drcItem->SetErrorMessage( wxString::FromUTF8( aCtx.Request.message() ) );
1759
1760 RC_ITEM::KIIDS ids;
1761
1762 for( const auto& id : aCtx.Request.items() )
1763 ids.emplace_back( KIID( id.value() ) );
1764
1765 if( !ids.empty() )
1766 drcItem->SetItems( ids );
1767
1768 const auto& pos = aCtx.Request.position();
1769 VECTOR2I position( static_cast<int>( pos.x_nm() ), static_cast<int>( pos.y_nm() ) );
1770
1771 PCB_MARKER* marker = new PCB_MARKER( drcItem, position, layer );
1772
1773 COMMIT* commit = getCurrentCommit( aCtx.ClientName );
1774 commit->Add( marker );
1775 commit->Push( wxS( "API injected DRC marker" ) );
1776
1777 InjectDrcErrorResponse response;
1778 response.mutable_marker()->set_value( marker->GetUUID().AsStdString() );
1779
1780 return response;
1781}
types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
Definition api_enums.cpp:97
KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:36
tl::expected< T, ApiResponseStatus > HANDLER_RESULT
Definition api_handler.h:45
std::unique_ptr< EDA_ITEM > CreateItemForType(KICAD_T aType, EDA_ITEM *aContainer)
@ ERROR_INSIDE
@ LAYER_CLASS_COUNT
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:224
static TOOL_ACTION gridSetOrigin
Definition actions.h:195
static TOOL_ACTION selectItems
Select a list of items (specified as the event parameter)
Definition actions.h:232
HANDLER_RESULT< bool > validateDocument(const DocumentSpecifier &aDocument)
HANDLER_RESULT< std::optional< KIID > > validateItemHeaderDocument(const kiapi::common::types::ItemHeader &aHeader)
If the header is valid, returns the item container.
API_HANDLER_EDITOR(EDA_BASE_FRAME *aFrame=nullptr)
COMMIT * getCurrentCommit(const std::string &aClientName)
virtual void pushCurrentCommit(const std::string &aClientName, const wxString &aMessage)
std::set< std::string > m_activeClients
virtual std::optional< ApiResponseStatus > checkForBusy()
Checks if the editor can accept commands.
EDA_BASE_FRAME * m_frame
HANDLER_RESULT< commands::SelectionResponse > handleAddToSelection(const HANDLER_CONTEXT< commands::AddToSelection > &aCtx)
HANDLER_RESULT< commands::CreateItemsResponse > handleParseAndCreateItemsFromString(const HANDLER_CONTEXT< commands::ParseAndCreateItemsFromString > &aCtx)
HANDLER_RESULT< Empty > handleInteractiveMoveItems(const HANDLER_CONTEXT< InteractiveMoveItems > &aCtx)
bool validateDocumentInternal(const DocumentSpecifier &aDocument) const override
HANDLER_RESULT< Empty > handleSetActiveLayer(const HANDLER_CONTEXT< SetActiveLayer > &aCtx)
API_HANDLER_PCB(PCB_EDIT_FRAME *aFrame)
static HANDLER_RESULT< std::unique_ptr< BOARD_ITEM > > createItemForType(KICAD_T aType, BOARD_ITEM_CONTAINER *aContainer)
std::optional< BOARD_ITEM * > getItemById(const KIID &aId) const
HANDLER_RESULT< types::Vector2 > handleGetBoardOrigin(const HANDLER_CONTEXT< GetBoardOrigin > &aCtx)
std::unique_ptr< COMMIT > createCommit() override
Override this to create an appropriate COMMIT subclass for the frame in question.
HANDLER_RESULT< BoardStackupResponse > handleGetStackup(const HANDLER_CONTEXT< GetBoardStackup > &aCtx)
HANDLER_RESULT< types::TitleBlockInfo > handleGetTitleBlockInfo(const HANDLER_CONTEXT< commands::GetTitleBlockInfo > &aCtx)
HANDLER_RESULT< commands::SelectionResponse > handleGetSelection(const HANDLER_CONTEXT< commands::GetSelection > &aCtx)
HANDLER_RESULT< NetClassForNetsResponse > handleGetNetClassForNets(const HANDLER_CONTEXT< GetNetClassForNets > &aCtx)
std::optional< EDA_ITEM * > getItemFromDocument(const DocumentSpecifier &aDocument, const KIID &aId) override
HANDLER_RESULT< commands::ExpandTextVariablesResponse > handleExpandTextVariables(const HANDLER_CONTEXT< commands::ExpandTextVariables > &aCtx)
HANDLER_RESULT< Empty > handleSetVisibleLayers(const HANDLER_CONTEXT< SetVisibleLayers > &aCtx)
HANDLER_RESULT< Empty > handleSaveCopyOfDocument(const HANDLER_CONTEXT< commands::SaveCopyOfDocument > &aCtx)
HANDLER_RESULT< GraphicsDefaultsResponse > handleGetGraphicsDefaults(const HANDLER_CONTEXT< GetGraphicsDefaults > &aCtx)
HANDLER_RESULT< commands::GetItemsResponse > handleGetItemsById(const HANDLER_CONTEXT< commands::GetItemsById > &aCtx)
HANDLER_RESULT< Empty > handleSetBoardOrigin(const HANDLER_CONTEXT< SetBoardOrigin > &aCtx)
HANDLER_RESULT< BoardLayerNameResponse > handleGetBoardLayerName(const HANDLER_CONTEXT< GetBoardLayerName > &aCtx)
HANDLER_RESULT< Empty > handleClearSelection(const HANDLER_CONTEXT< commands::ClearSelection > &aCtx)
HANDLER_RESULT< commands::RunActionResponse > handleRunAction(const HANDLER_CONTEXT< commands::RunAction > &aCtx)
HANDLER_RESULT< BoardLayers > handleGetVisibleLayers(const HANDLER_CONTEXT< GetVisibleLayers > &aCtx)
HANDLER_RESULT< PadstackPresenceResponse > handleCheckPadstackPresenceOnLayers(const HANDLER_CONTEXT< CheckPadstackPresenceOnLayers > &aCtx)
HANDLER_RESULT< commands::SelectionResponse > handleRemoveFromSelection(const HANDLER_CONTEXT< commands::RemoveFromSelection > &aCtx)
HANDLER_RESULT< commands::GetOpenDocumentsResponse > handleGetOpenDocuments(const HANDLER_CONTEXT< commands::GetOpenDocuments > &aCtx)
HANDLER_RESULT< BoardEditorAppearanceSettings > handleGetBoardEditorAppearanceSettings(const HANDLER_CONTEXT< GetBoardEditorAppearanceSettings > &aCtx)
HANDLER_RESULT< NetsResponse > handleGetNets(const HANDLER_CONTEXT< GetNets > &aCtx)
HANDLER_RESULT< commands::SavedDocumentResponse > handleSaveDocumentToString(const HANDLER_CONTEXT< commands::SaveDocumentToString > &aCtx)
HANDLER_RESULT< commands::GetBoundingBoxResponse > handleGetBoundingBox(const HANDLER_CONTEXT< commands::GetBoundingBox > &aCtx)
HANDLER_RESULT< Empty > handleSaveDocument(const HANDLER_CONTEXT< commands::SaveDocument > &aCtx)
void deleteItemsInternal(std::map< KIID, ItemDeletionStatus > &aItemsToDelete, const std::string &aClientName) override
HANDLER_RESULT< BoardEnabledLayersResponse > handleGetBoardEnabledLayers(const HANDLER_CONTEXT< GetBoardEnabledLayers > &aCtx)
HANDLER_RESULT< commands::GetItemsResponse > handleGetItems(const HANDLER_CONTEXT< commands::GetItems > &aCtx)
HANDLER_RESULT< PadShapeAsPolygonResponse > handleGetPadShapeAsPolygon(const HANDLER_CONTEXT< GetPadShapeAsPolygon > &aCtx)
HANDLER_RESULT< InjectDrcErrorResponse > handleInjectDrcError(const HANDLER_CONTEXT< InjectDrcError > &aCtx)
PCB_EDIT_FRAME * frame() const
HANDLER_RESULT< BoardEnabledLayersResponse > handleSetBoardEnabledLayers(const HANDLER_CONTEXT< SetBoardEnabledLayers > &aCtx)
HANDLER_RESULT< Empty > handleSetBoardEditorAppearanceSettings(const HANDLER_CONTEXT< SetBoardEditorAppearanceSettings > &aCtx)
HANDLER_RESULT< Empty > handleRefillZones(const HANDLER_CONTEXT< RefillZones > &aCtx)
HANDLER_RESULT< types::ItemRequestStatus > handleCreateUpdateItemsInternal(bool aCreate, const std::string &aClientName, const types::ItemHeader &aHeader, const google::protobuf::RepeatedPtrField< google::protobuf::Any > &aItems, std::function< void(commands::ItemStatus, google::protobuf::Any)> aItemHandler) override
HANDLER_RESULT< BoardLayerResponse > handleGetActiveLayer(const HANDLER_CONTEXT< GetActiveLayer > &aCtx)
HANDLER_RESULT< Empty > handleRevertDocument(const HANDLER_CONTEXT< commands::RevertDocument > &aCtx)
HANDLER_RESULT< commands::SavedSelectionResponse > handleSaveSelectionToString(const HANDLER_CONTEXT< commands::SaveSelectionToString > &aCtx)
void pushCurrentCommit(const std::string &aClientName, const wxString &aMessage) override
void registerHandler(HANDLER_RESULT< ResponseType >(HandlerType::*aHandler)(const HANDLER_CONTEXT< RequestType > &))
Registers an API command handler for the given message types.
Definition api_handler.h:93
void SetContentModified(bool aModified=true)
Definition base_screen.h:59
BASE_SET & reset(size_t pos)
Definition base_set.h:143
BASE_SET & set(size_t pos)
Definition base_set.h:116
Container for design settings for a BOARD object.
bool m_TextUpright[LAYER_CLASS_COUNT]
const VECTOR2I & GetGridOrigin() const
const VECTOR2I & GetAuxOrigin() const
int m_TextThickness[LAYER_CLASS_COUNT]
int m_LineThickness[LAYER_CLASS_COUNT]
VECTOR2I m_TextSize[LAYER_CLASS_COUNT]
bool m_TextItalic[LAYER_CLASS_COUNT]
Abstract interface for BOARD_ITEMs capable of storing other items inside.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
virtual void CopyFrom(const BOARD_ITEM *aOther)
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
BOARD_STACKUP GetStackupOrDefault() const
Definition board.cpp:2904
void SetVisibleLayers(const LSET &aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings changes the bit-mask of vis...
Definition board.cpp:1000
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition board.cpp:1083
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition board.cpp:968
BOARD_ITEM * ResolveItem(const KIID &aID, bool aAllowNullptrReturn=false) const
Definition board.cpp:1780
void SaveSelection(const PCB_SELECTION &selected, bool isFootprintEditor)
void SetWriter(std::function< void(const wxString &)> aWriter)
void SaveBoard(const wxString &aFileName, BOARD *aBoard, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aBoard to a storage file in a format that this PCB_IO implementation knows about or it can be u...
void SetBoard(BOARD *aBoard)
Represent a set of changes (additions, deletions or modifications) of a data model (e....
Definition commit.h:72
COMMIT & Remove(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Remove a new item from the model.
Definition commit.h:90
virtual void Push(const wxString &aMessage=wxT("A commit"), int aFlags=0)=0
Execute the changes.
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
Definition commit.h:106
COMMIT & Add(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr)
Add a new item to the model.
Definition commit.h:78
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
Definition drc_item.cpp:405
void ReleaseFile()
Release the current file marked in use.
virtual void Refresh(bool aEraseBackground=true, const wxRect *aRect=nullptr) override
void AddItem(EDA_ITEM *aItem)
Add item to group.
Definition eda_group.cpp:27
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:99
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition eda_item.cpp:120
const KIID m_Uuid
Definition eda_item.h:527
virtual EDA_GROUP * GetParentGroup() const
Definition eda_item.h:117
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:111
virtual wxString GetFriendlyName() const
Definition eda_item.cpp:411
void SetMirror(bool aMirrorX, bool aMirrorY)
Control the mirroring of the VIEW.
Definition view.cpp:563
void UpdateAllLayersColor()
Apply the new coloring scheme to all layers.
Definition view.cpp:783
bool IsMirroredX() const
Return true if view is flipped across the X axis.
Definition view.h:251
void RecacheAllItems()
Rebuild GAL display lists.
Definition view.cpp:1469
bool IsMirroredY() const
Return true if view is flipped across the Y axis.
Definition view.h:259
Definition kiid.h:49
std::string AsStdString() const
Definition kiid.cpp:250
PROJECT & Prj() const
Return a reference to the PROJECT associated with this KIWAY.
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition lseq.h:47
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:608
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
Definition lset.h:63
A collection of nets and the parameters used to route or test these nets.
Definition netclass.h:45
const wxString GetName() const
Gets the name of this (maybe aggregate) netclass in a format for internal usage or for export to exte...
Definition netclass.cpp:328
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition netclass.cpp:136
Handle the data for a net.
Definition netinfo.h:54
NETCLASS * GetNetClass()
Definition netinfo.h:99
Container for NETINFO_ITEM elements, which are the nets.
Definition netinfo.h:212
NETINFO_ITEM * GetNetItem(int aNetCode) const
Definition pad.h:55
DISPLAY_OPTIONS m_Display
static TOOL_ACTION zoneFillAll
static TOOL_ACTION move
move or drag an item
static TOOL_ACTION drillSetOrigin
APPEARANCE_CONTROLS * GetAppearancePanel()
const PCB_DISPLAY_OPTIONS & GetDisplayOptions() const
Display options control the way tracks, vias, outlines and other things are shown (for instance solid...
PCBNEW_SETTINGS * GetPcbNewSettings() const
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
BOARD * GetBoard() const
void SetDisplayOptions(const PCB_DISPLAY_OPTIONS &aOptions, bool aRefresh=true)
Update the current display options.
HIGH_CONTRAST_MODE m_ContrastModeDisplay
How inactive layers are displayed.
NET_COLOR_MODE m_NetColorMode
How to use color overrides on specific nets and netclasses.
virtual KIGFX::PCB_VIEW * GetView() const override
Return a pointer to the #VIEW instance used in the panel.
void SyncLayersVisibility(const BOARD *aBoard)
Update "visibility" property of each layer of a given BOARD.
The main frame for Pcbnew.
void SetActiveLayer(PCB_LAYER_ID aLayer) override
Change the currently active layer to aLayer and also update the APPEARANCE_CONTROLS.
void OnModify() override
Must be called after a board change to set the modified flag.
bool SaveBoard(bool aSaveAs=false, bool aSaveCopy=false)
bool OpenProjectFiles(const std::vector< wxString > &aFileSet, int aCtl=0) override
Load a KiCad board (.kicad_pcb) from aFileName.
void UpdateUserInterface()
Update the layer manager and other widgets from the board setup (layer and items visibility,...
bool SavePcbCopy(const wxString &aFileName, bool aCreateProject=false, bool aHeadless=false)
Write the board data structures to aFileName.
A set of BOARD_ITEMs (i.e., without duplicates).
Definition pcb_group.h:53
const KIID GetUUID() const override
Definition pcb_marker.h:49
The selection tool: currently supports:
PCB_SELECTION & GetSelection()
virtual const wxString AbsolutePath(const wxString &aFileName) const
Fix up aFileName if it is relative to the project's directory to be an absolute path and filename.
Definition project.cpp:401
std::vector< KIID > KIIDS
Definition rc_item.h:83
int AddItemsToSel(const TOOL_EVENT &aEvent)
int RemoveItemsFromSel(const TOOL_EVENT &aEvent)
void SetReferencePoint(const VECTOR2I &aP)
virtual void Serialize(google::protobuf::Any &aContainer) const
Serializes this object to the given Any message.
Represent a set of closed polygons.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Hold the information shown in the lower right corner of a plot, printout, or editing view.
Definition title_block.h:41
const wxString & GetCompany() const
Definition title_block.h:96
const wxString & GetRevision() const
Definition title_block.h:86
const wxString & GetDate() const
Definition title_block.h:76
const wxString & GetComment(int aIdx) const
const wxString & GetTitle() const
Definition title_block.h:63
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Master controller class:
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
bool PostAPIAction(const TOOL_ACTION &aAction, COMMIT *aCommit)
A type-safe container of any type.
Definition ki_any.h:93
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
Definition common.cpp:62
The common library.
@ DRCE_GENERIC_ERROR
Definition drc_item.h:91
@ DRCE_GENERIC_WARNING
Definition drc_item.h:90
#define _(s)
@ RECURSE
Definition eda_item.h:52
static const std::string KiCadPcbFileExtension
PROJECT & Prj()
Definition kicad.cpp:642
#define KICTL_REVERT
reverting to a previously-saved (KiCad) file.
#define MAX_CU_LAYERS
Definition layer_ids.h:176
@ LAYER_DRC_WARNING
Layer for DRC markers with #SEVERITY_WARNING.
Definition layer_ids.h:301
@ LAYER_DRC_ERROR
Layer for DRC markers with #SEVERITY_ERROR.
Definition layer_ids.h:277
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
@ F_CrtYd
Definition layer_ids.h:116
@ Edge_Cuts
Definition layer_ids.h:112
@ Margin
Definition layer_ids.h:113
@ B_CrtYd
Definition layer_ids.h:115
@ UNDEFINED_LAYER
Definition layer_ids.h:61
@ Rescue
Definition layer_ids.h:121
void PackLayerSet(google::protobuf::RepeatedField< int > &aOutput, const LSET &aLayerSet)
LSET UnpackLayerSet(const google::protobuf::RepeatedField< int > &aProtoLayerSet)
KICOMMON_API void PackBox2(types::Box2 &aOutput, const BOX2I &aInput)
KICOMMON_API std::optional< KICAD_T > TypeNameFromAny(const google::protobuf::Any &aMessage)
Definition api_utils.cpp:33
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput)
Definition api_utils.cpp:86
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput)
Definition api_utils.cpp:79
KICOMMON_API void PackPolyLine(types::PolyLine &aOutput, const SHAPE_LINE_CHAIN &aSlc)
Class to handle a set of BOARD_ITEMs.
BOARD * GetBoard()
SEVERITY
@ RPT_SEVERITY_WARNING
std::vector< EDA_ITEM * > EDA_ITEMS
std::string ClientName
Definition api_handler.h:51
RequestMessageType Request
Definition api_handler.h:52
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:78
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition typeinfo.h:88
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition typeinfo.h:106
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition typeinfo.h:103
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:97
@ TYPE_NOT_INIT
Definition typeinfo.h:81
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition typeinfo.h:104
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition typeinfo.h:111
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition typeinfo.h:93
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition typeinfo.h:108
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition typeinfo.h:92
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:101
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition typeinfo.h:86
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition typeinfo.h:102
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:87
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition typeinfo.h:98
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
Definition typeinfo.h:100
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition typeinfo.h:96
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition typeinfo.h:105
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694