KiCad PCB EDA Suite
Loading...
Searching...
No Matches
api_handler_common.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
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <optional>
22#include <ranges>
23#include <set>
24#include <tuple>
25
27#include <build_version.h>
28#include <eda_shape.h>
29#include <eda_text.h>
30#include <gestfich.h>
32#include <google/protobuf/empty.pb.h>
33#include <paths.h>
34#include <pgm_base.h>
35#include <api/api_plugin.h>
36#include <api/api_utils.h>
40#include <wx/string.h>
41
42using namespace kiapi::common::commands;
43using namespace kiapi::common::types;
44using google::protobuf::Empty;
45
46
49{
79}
80
81
84{
85 GetVersionResponse reply;
86
87 reply.mutable_version()->set_full_version( GetBuildVersion().ToStdString() );
88
89 std::tuple<int, int, int> version = GetMajorMinorPatchTuple();
90 reply.mutable_version()->set_major( std::get<0>( version ) );
91 reply.mutable_version()->set_minor( std::get<1>( version ) );
92 reply.mutable_version()->set_patch( std::get<2>( version ) );
93
94 return reply;
95}
96
97
100{
101 wxFileName fn( wxEmptyString, wxString::FromUTF8( aCtx.Request.binary_name() ) );
102#ifdef _WIN32
103 fn.SetExt( wxT( "exe" ) );
104#endif
105
106 wxString path = FindKicadFile( fn.GetFullName() );
107 PathResponse reply;
108 reply.set_path( path.ToUTF8() );
109 return reply;
110}
111
112
113tl::expected<bool, ApiResponseStatus> API_HANDLER_COMMON::validateProject( const ProjectSpecifier& aProject,
114 bool aAllowEmpty )
115{
116 if( !aAllowEmpty && ( aProject.name().empty() || aProject.path().empty() ) )
117 {
118 ApiResponseStatus e;
119 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
120 e.set_error_message( "a project name and path must be specified" );
121 return tl::unexpected( e );
122 }
123
124 const PROJECT& prj = Pgm().GetSettingsManager().Prj();
125
126 if( aProject.name().compare( prj.GetProjectName().ToUTF8() ) != 0 )
127 {
128 ApiResponseStatus e;
129 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
130 e.set_error_message( fmt::format( "the requested project {} is not open", aProject.name() ) );
131 return tl::unexpected( e );
132 }
133
134 if( aProject.path().compare( prj.GetProjectPath().ToUTF8() ) != 0 )
135 {
136 ApiResponseStatus e;
137 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
138 e.set_error_message( fmt::format( "the requested project {} is not open at path {}", aProject.name(),
139 aProject.path() ) );
140 return tl::unexpected( e );
141 }
142
143 return true;
144}
145
146
148{
149 if( tl::expected<bool, ApiResponseStatus> result = validateProject( aCtx.Request.project(), true ); !result )
150 return tl::unexpected( result.error() );
151
152 NetClassesResponse reply;
153
154 std::shared_ptr<NET_SETTINGS>& netSettings =
156
157 google::protobuf::Any any;
158
159 netSettings->GetDefaultNetclass()->Serialize( any );
160 any.UnpackTo( reply.add_net_classes() );
161
162 for( const auto& netClass : netSettings->GetNetclasses() | std::views::values )
163 {
164 netClass->Serialize( any );
165 any.UnpackTo( reply.add_net_classes() );
166 }
167
168 return reply;
169}
170
171
173{
174 if( tl::expected<bool, ApiResponseStatus> result = validateProject( aCtx.Request.project(), true ); !result )
175 return tl::unexpected( result.error() );
176
177 std::shared_ptr<NET_SETTINGS>& netSettings =
179
180 if( aCtx.Request.merge_mode() == MapMergeMode::MMM_REPLACE )
181 netSettings->ClearNetclasses();
182
183 auto netClasses = netSettings->GetNetclasses();
184 google::protobuf::Any any;
185
186 for( const auto& ncProto : aCtx.Request.net_classes() )
187 {
188 any.PackFrom( ncProto );
189 wxString name = wxString::FromUTF8( ncProto.name() );
190
191 bool deserialized = false;
192
193 if( name == wxT( "Default" ) )
194 {
195 deserialized = netSettings->GetDefaultNetclass()->Deserialize( any );
196 }
197 else
198 {
199 if( !netClasses.contains( name ) )
200 netClasses.insert( { name, std::make_shared<NETCLASS>( name, false ) } );
201
202 deserialized = netClasses[name]->Deserialize( any );
203 }
204
205 if( !deserialized )
206 {
207 ApiResponseStatus e;
208 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
209 e.set_error_message( fmt::format( "could not unpack netclass '{}'", name.ToUTF8().data() ) );
210 return tl::unexpected( e );
211 }
212 }
213
214 netSettings->SetNetclasses( netClasses );
216
217 return Empty();
218}
219
220
223{
224 if( tl::expected<bool, ApiResponseStatus> result = validateProject( aCtx.Request.project() ); !result )
225 return tl::unexpected( result.error() );
226
227 std::shared_ptr<NET_SETTINGS>& netSettings = Pgm().GetSettingsManager().Prj().GetProjectFile().m_NetSettings;
228
229 NetClassAssignmentsResponse reply;
230
231 for( const auto& [netName, netclassNames] : netSettings->GetNetclassLabelAssignments() )
232 {
233 project::NetClassAssignment* assignment = reply.add_assignments();
234 assignment->set_net( netName.ToUTF8() );
235
236 for( const wxString& netclassName : netclassNames )
237 assignment->add_netclasses( netclassName.ToUTF8() );
238 }
239
240 for( const auto& [matcher, netclassName] : netSettings->GetNetclassPatternAssignments() )
241 {
242 project::NetClassPatternAssignment* pattern = reply.add_pattern_assignments();
243 pattern->set_pattern( matcher->GetPattern().ToUTF8() );
244 pattern->set_netclass( netclassName.ToUTF8() );
245 }
246
247 return reply;
248}
249
250
253{
254 if( tl::expected<bool, ApiResponseStatus> result = validateProject( aCtx.Request.project() ); !result )
255 return tl::unexpected( result.error() );
256
257 std::shared_ptr<NET_SETTINGS>& netSettings = Pgm().GetSettingsManager().Prj().GetProjectFile().m_NetSettings;
258
259 std::set<wxString, std::less<>> knownNetclasses;
260 knownNetclasses.insert( NETCLASS::Default );
261
262 for( const wxString& name : netSettings->GetNetclasses() | std::views::keys )
263 knownNetclasses.insert( name );
264
265 auto checkNetclassName = [&]( const std::string& aName, const char* aKind ) -> std::optional<ApiResponseStatus>
266 {
267 if( knownNetclasses.contains( wxString::FromUTF8( aName ) ) )
268 return std::nullopt;
269
270 ApiResponseStatus e;
271 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
272 e.set_error_message( fmt::format( "unknown netclass '{}' in {} assignment", aName, aKind ) );
273 return e;
274 };
275
276 if( aCtx.Request.merge_mode() == MapMergeMode::MMM_REPLACE )
277 {
278 netSettings->ClearNetclassLabelAssignments();
279 netSettings->ClearNetclassPatternAssignments();
280 }
281
282 for( const project::NetClassAssignment& assignment : aCtx.Request.assignments() )
283 {
284 if( assignment.net().empty() )
285 {
286 ApiResponseStatus e;
287 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
288 e.set_error_message( "net name cannot be empty in a netclass assignment" );
289 return tl::unexpected( e );
290 }
291
292 for( const std::string& netclassName : assignment.netclasses() )
293 {
294 if( std::optional<ApiResponseStatus> err = checkNetclassName( netclassName, "net" ) )
295 return tl::unexpected( *err );
296 }
297
298 std::set<wxString> netclasses;
299
300 for( const std::string& netclassName : assignment.netclasses() )
301 netclasses.insert( wxString::FromUTF8( netclassName ) );
302
303 if( netclasses.empty() )
304 netSettings->ClearNetclassLabelAssignment( wxString::FromUTF8( assignment.net() ) );
305 else
306 netSettings->SetNetclassLabelAssignment( wxString::FromUTF8( assignment.net() ), netclasses );
307 }
308
309 for( const project::NetClassPatternAssignment& pattern : aCtx.Request.pattern_assignments() )
310 {
311 if( pattern.pattern().empty() )
312 {
313 ApiResponseStatus e;
314 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
315 e.set_error_message( "pattern cannot be empty in a netclass pattern assignment" );
316 return tl::unexpected( e );
317 }
318
319 if( !pattern.netclass().empty() )
320 {
321 if( std::optional<ApiResponseStatus> err = checkNetclassName( pattern.netclass(), "pattern" ) )
322 return tl::unexpected( *err );
323 }
324
325 std::vector<std::pair<std::unique_ptr<EDA_COMBINED_MATCHER>, wxString>> kept;
326
327 for( auto& existing : netSettings->GetNetclassPatternAssignments() )
328 {
329 if( existing.first->GetPattern() != wxString::FromUTF8( pattern.pattern() ) )
330 kept.emplace_back( std::move( existing ) );
331 }
332
333 netSettings->SetNetclassPatternAssignments( std::move( kept ) );
334
335 if( !pattern.netclass().empty() )
336 {
337 netSettings->SetNetclassPatternAssignment( wxString::FromUTF8( pattern.pattern() ),
338 wxString::FromUTF8( pattern.netclass() ) );
339 }
340 }
341
342 netSettings->ClearAllCaches();
344
345 return Empty();
346}
347
348
353
354
357{
359 google::protobuf::Any any;
360 any.PackFrom( aCtx.Request.text() );
361
362 if( !text.Deserialize( any ) )
363 {
364 ApiResponseStatus e;
365 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
366 e.set_error_message( "Could not decode text in GetTextExtents message" );
367 return tl::unexpected( e );
368 }
369
370 types::Box2 response;
371
372 BOX2I bbox = text.GetTextBox( nullptr );
373 EDA_ANGLE angle = text.GetTextAngle();
374
375 if( !angle.IsZero() )
376 bbox = bbox.GetBoundingBoxRotated( text.GetTextPos(), text.GetTextAngle() );
377
378 response.mutable_position()->set_x_nm( bbox.GetPosition().x );
379 response.mutable_position()->set_y_nm( bbox.GetPosition().y );
380 response.mutable_size()->set_x_nm( bbox.GetSize().x );
381 response.mutable_size()->set_y_nm( bbox.GetSize().y );
382
383 return response;
384}
385
386
389{
390 GetTextAsShapesResponse reply;
391
392 for( const TextOrTextBox& textMsg : aCtx.Request.text() )
393 {
394 Text dummyText;
395 const Text* textPtr = &textMsg.text();
396
397 if( textMsg.has_textbox() )
398 {
399 dummyText.set_text( textMsg.textbox().text() );
400 dummyText.mutable_attributes()->CopyFrom( textMsg.textbox().attributes() );
401 textPtr = &dummyText;
402 }
403
405 google::protobuf::Any any;
406 any.PackFrom( *textPtr );
407
408 if( !text.Deserialize( any ) )
409 {
410 ApiResponseStatus e;
411 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
412 e.set_error_message( "Could not decode text in GetTextAsShapes message" );
413 return tl::unexpected( e );
414 }
415
416 std::shared_ptr<SHAPE_COMPOUND> shapes = text.GetEffectiveTextShape( false );
417
418 TextWithShapes* entry = reply.add_text_with_shapes();
419 entry->mutable_text()->CopyFrom( textMsg );
420
421 for( SHAPE* subshape : shapes->Shapes() )
422 {
423 EDA_SHAPE proxy( *subshape );
424 proxy.Serialize( any );
425 GraphicShape* shapeMsg = entry->mutable_shapes()->add_shapes();
426 any.UnpackTo( shapeMsg );
427 }
428
429 if( textMsg.has_textbox() && textMsg.textbox().border_enabled() )
430 {
431 GraphicShape* border = entry->mutable_shapes()->add_shapes();
432 int width = textMsg.textbox().attributes().stroke_width().value_nm();
433 border->mutable_attributes()->mutable_stroke()->mutable_width()->set_value_nm( width );
434 VECTOR2I tl = UnpackVector2( textMsg.textbox().top_left() );
435 VECTOR2I br = UnpackVector2( textMsg.textbox().bottom_right() );
436
437 // top
438 PackVector2( *border->mutable_segment()->mutable_start(), tl );
439 PackVector2( *border->mutable_segment()->mutable_end(), VECTOR2I( br.x, tl.y ) );
440
441 // right
442 border = entry->mutable_shapes()->add_shapes();
443 border->mutable_attributes()->mutable_stroke()->mutable_width()->set_value_nm( width );
444 PackVector2( *border->mutable_segment()->mutable_start(), VECTOR2I( br.x, tl.y ) );
445 PackVector2( *border->mutable_segment()->mutable_end(), br );
446
447 // bottom
448 border = entry->mutable_shapes()->add_shapes();
449 border->mutable_attributes()->mutable_stroke()->mutable_width()->set_value_nm( width );
450 PackVector2( *border->mutable_segment()->mutable_start(), br );
451 PackVector2( *border->mutable_segment()->mutable_end(), VECTOR2I( tl.x, br.y ) );
452
453 // left
454 border = entry->mutable_shapes()->add_shapes();
455 border->mutable_attributes()->mutable_stroke()->mutable_width()->set_value_nm( width );
456 PackVector2( *border->mutable_segment()->mutable_start(), VECTOR2I( tl.x, br.y ) );
457 PackVector2( *border->mutable_segment()->mutable_end(), tl );
458 }
459 }
460
461 return reply;
462}
463
464
467{
468 if( !aCtx.Request.has_document() || aCtx.Request.document().type() != DOCTYPE_PROJECT )
469 {
470 ApiResponseStatus e;
471 e.set_status( ApiStatusCode::AS_UNHANDLED );
472 // No error message, this is a flag that the server should try a different handler
473 return tl::unexpected( e );
474 }
475
476 ExpandTextVariablesResponse reply;
478
479 for( const std::string& textMsg : aCtx.Request.text() )
480 {
481 wxString result = ExpandTextVars( wxString::FromUTF8( textMsg ), &project, INTERNAL );
482
483 if( aCtx.Request.expand_env_vars() )
485
486 reply.add_text( result.ToUTF8() );
487 }
488
489 return reply;
490}
491
492
495{
496 wxString identifier = wxString::FromUTF8( aCtx.Request.identifier() );
497
498 if( identifier.IsEmpty() )
499 {
500 ApiResponseStatus e;
501 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
502 e.set_error_message( "plugin identifier is missing" );
503 return tl::unexpected( e );
504 }
505
506 if( !API_PLUGIN::IsValidIdentifier( identifier ) )
507 {
508 ApiResponseStatus e;
509 e.set_status( ApiStatusCode::AS_BAD_REQUEST );
510 e.set_error_message( "plugin identifier is invalid" );
511 return tl::unexpected( e );
512 }
513
514 wxFileName path( PATHS::GetUserSettingsPath(), wxEmptyString );
515 path.AppendDir( "plugins" );
516
517 // Create the base plugins path if needed, but leave the specific plugin to create its own path
518 PATHS::EnsurePathExists( path.GetPath() );
519
520 path.AppendDir( identifier );
521
522 StringResponse reply;
523 reply.set_response( path.GetPath() );
524 return reply;
525}
526
527
530{
531 if( !aCtx.Request.has_document() || aCtx.Request.document().type() != DOCTYPE_PROJECT )
532 {
533 ApiResponseStatus e;
534 e.set_status( ApiStatusCode::AS_UNHANDLED );
535 // No error message, this is a flag that the server should try a different handler
536 return tl::unexpected( e );
537 }
538
539 if( tl::expected<bool, ApiResponseStatus> result = validateProject( aCtx.Request.document().project() );
540 !result )
541 {
542 return tl::unexpected( result.error() );
543 }
544
546
547 if( project.IsNullProject() )
548 {
549 ApiResponseStatus e;
550 e.set_status( ApiStatusCode::AS_NOT_READY );
551 e.set_error_message( "no valid project is loaded, cannot get text variables" );
552 return tl::unexpected( e );
553 }
554
555 const std::map<wxString, wxString>& vars = project.GetTextVars();
556
557 project::TextVariables reply;
558 auto map = reply.mutable_variables();
559
560 for( const auto& [key, value] : vars )
561 ( *map )[ std::string( key.ToUTF8() ) ] = value.ToUTF8();
562
563 return reply;
564}
565
566
569{
570 if( !aCtx.Request.has_document() || aCtx.Request.document().type() != DOCTYPE_PROJECT )
571 {
572 ApiResponseStatus e;
573 e.set_status( ApiStatusCode::AS_UNHANDLED );
574 // No error message, this is a flag that the server should try a different handler
575 return tl::unexpected( e );
576 }
577
578 if( tl::expected<bool, ApiResponseStatus> result = validateProject( aCtx.Request.document().project() );
579 !result )
580 {
581 return tl::unexpected( result.error() );
582 }
583
585
586 if( project.IsNullProject() )
587 {
588 ApiResponseStatus e;
589 e.set_status( ApiStatusCode::AS_NOT_READY );
590 e.set_error_message( "no valid project is loaded, cannot set text variables" );
591 return tl::unexpected( e );
592 }
593
594 const project::TextVariables& newVars = aCtx.Request.variables();
595 std::map<wxString, wxString>& vars = project.GetTextVars();
596
597 if( aCtx.Request.merge_mode() == MapMergeMode::MMM_REPLACE )
598 vars.clear();
599
600 for( const auto& [key, value] : newVars.variables() )
601 vars[wxString::FromUTF8( key )] = wxString::FromUTF8( value );
602
603 if( !Pgm().GetSettingsManager().SaveProject() )
604 {
605 ApiResponseStatus e;
606 e.set_status( ApiStatusCode::AS_INTERNAL_ERROR );
607 e.set_error_message( "failed to save project text variables" );
608 return tl::unexpected( e );
609 }
610
611 return Empty();
612}
613
614
617{
619 {
620 ApiResponseStatus e;
621 e.set_status( ApiStatusCode::AS_UNIMPLEMENTED );
622 e.set_error_message( "OpenDocument is not available in this KiCad mode" );
623 return tl::unexpected( e );
624 }
625
626 return m_openDocumentHandler( aCtx.Request );
627}
628
629
632{
634 {
635 ApiResponseStatus e;
636 e.set_status( ApiStatusCode::AS_UNIMPLEMENTED );
637 e.set_error_message( "CloseDocument is not available in this KiCad mode" );
638 return tl::unexpected( e );
639 }
640
641 return m_closeDocumentHandler( aCtx.Request );
642}
643
644
647{
649 {
650 ApiResponseStatus e;
651 e.set_status( ApiStatusCode::AS_UNIMPLEMENTED );
652 e.set_error_message( "CreateDocument is not available in this KiCad mode" );
653 return tl::unexpected( e );
654 }
655
656 return m_createDocumentHandler( aCtx.Request );
657}
658
659
661{
663 {
664 ApiResponseStatus e;
665 e.set_status( ApiStatusCode::AS_UNIMPLEMENTED );
666 e.set_error_message( "CloseAllDocuments is not available in this KiCad mode" );
667 return tl::unexpected( e );
668 }
669
670 return m_closeAllDocumentsHandler( aCtx.Request );
671}
672
673
675{
676 GetPathsResponse reply;
677
678 auto addPath = [&]( types::PathType aType, const wxString& aPath )
679 {
680 PathEntry* entry = reply.add_paths();
681 entry->set_type( aType );
682 entry->set_path( aPath.ToUTF8() );
683 };
684
685 addPath( types::PATH_USER_PLUGINS, PATHS::GetUserPluginsPath() );
686 addPath( types::PATH_USER_TEMPLATES, PATHS::GetUserTemplatesPath() );
687 addPath( types::PATH_USER_SETTINGS, PATHS::GetUserSettingsPath() );
688 addPath( types::PATH_STOCK_SYMBOLS, PATHS::GetStockSymbolsPath() );
689 addPath( types::PATH_STOCK_FOOTPRINTS, PATHS::GetStockFootprintsPath() );
690 addPath( types::PATH_STOCK_DESIGN_BLOCKS, PATHS::GetStockDesignBlocksPath() );
691 addPath( types::PATH_STOCK_3DMODELS, PATHS::GetStock3dmodelsPath() );
692 addPath( types::PATH_STOCK_TEMPLATES, PATHS::GetStockTemplatesPath() );
693
694 return reply;
695}
const char * name
tl::expected< T, ApiResponseStatus > HANDLER_RESULT
Definition api_handler.h:47
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:128
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
const std::tuple< int, int, int > & GetMajorMinorPatchTuple()
Get the build version numbers as a tuple.
wxString GetBuildVersion()
Get the full KiCad version string.
HANDLER_RESULT< Empty > handlePing(const HANDLER_CONTEXT< commands::Ping > &aCtx)
HANDLER_RESULT< types::Box2 > handleGetTextExtents(const HANDLER_CONTEXT< commands::GetTextExtents > &aCtx)
CLOSE_ALL_DOCUMENTS_HANDLER m_closeAllDocumentsHandler
HANDLER_RESULT< commands::GetTextAsShapesResponse > handleGetTextAsShapes(const HANDLER_CONTEXT< commands::GetTextAsShapes > &aCtx)
HANDLER_RESULT< commands::GetVersionResponse > handleGetVersion(const HANDLER_CONTEXT< commands::GetVersion > &aCtx)
CREATE_DOCUMENT_HANDLER m_createDocumentHandler
HANDLER_RESULT< Empty > handleCloseAllDocuments(const HANDLER_CONTEXT< commands::CloseAllDocuments > &aCtx)
HANDLER_RESULT< Empty > handleSetNetClassAssignments(const HANDLER_CONTEXT< commands::SetNetClassAssignments > &aCtx)
HANDLER_RESULT< commands::OpenDocumentResponse > handleCreateDocument(const HANDLER_CONTEXT< commands::CreateDocument > &aCtx)
HANDLER_RESULT< commands::NetClassAssignmentsResponse > handleGetNetClassAssignments(const HANDLER_CONTEXT< commands::GetNetClassAssignments > &aCtx)
HANDLER_RESULT< commands::PathResponse > handleGetKiCadBinaryPath(const HANDLER_CONTEXT< commands::GetKiCadBinaryPath > &aCtx)
HANDLER_RESULT< commands::NetClassesResponse > handleGetNetClasses(const HANDLER_CONTEXT< commands::GetNetClasses > &aCtx)
CLOSE_DOCUMENT_HANDLER m_closeDocumentHandler
OPEN_DOCUMENT_HANDLER m_openDocumentHandler
HANDLER_RESULT< Empty > handleCloseDocument(const HANDLER_CONTEXT< commands::CloseDocument > &aCtx)
HANDLER_RESULT< Empty > handleSetNetClasses(const HANDLER_CONTEXT< commands::SetNetClasses > &aCtx)
static tl::expected< bool, ApiResponseStatus > validateProject(const ProjectSpecifier &aProject, bool aAllowEmpty=false)
HANDLER_RESULT< commands::StringResponse > handleGetPluginSettingsPath(const HANDLER_CONTEXT< commands::GetPluginSettingsPath > &aCtx)
HANDLER_RESULT< commands::OpenDocumentResponse > handleOpenDocument(const HANDLER_CONTEXT< commands::OpenDocument > &aCtx)
HANDLER_RESULT< commands::ExpandTextVariablesResponse > handleExpandTextVariables(const HANDLER_CONTEXT< commands::ExpandTextVariables > &aCtx)
HANDLER_RESULT< Empty > handleSetTextVariables(const HANDLER_CONTEXT< commands::SetTextVariables > &aCtx)
HANDLER_RESULT< commands::GetPathsResponse > handleGetPaths(const HANDLER_CONTEXT< commands::GetPaths > &aCtx)
HANDLER_RESULT< project::TextVariables > handleGetTextVariables(const HANDLER_CONTEXT< commands::GetTextVariables > &aCtx)
void registerHandler(HANDLER_RESULT< ResponseType >(HandlerType::*aHandler)(const HANDLER_CONTEXT< RequestType > &))
Registers an API command handler for the given message types.
void requestNetSettingsNotification()
Definition api_handler.h:78
static bool IsValidIdentifier(const wxString &aIdentifier)
constexpr const Vec & GetPosition() const
Definition box2.h:208
const BOX2< Vec > GetBoundingBoxRotated(const VECTOR2I &aRotCenter, const EDA_ANGLE &aAngle) const
Useful to calculate bounding box of rotated items, when rotation is not cardinal.
Definition box2.h:656
constexpr const SizeVec & GetSize() const
Definition box2.h:203
bool IsZero() const
Definition eda_angle.h:135
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:94
static const char Default[]
the name of the default NETCLASS
Definition netclass.h:45
static wxString GetUserPluginsPath()
Gets the user path for plugins.
Definition paths.cpp:49
static wxString GetStockSymbolsPath()
Gets the stock (install) symbols path.
Definition paths.cpp:300
static wxString GetUserTemplatesPath()
Gets the user path for custom templates.
Definition paths.cpp:71
static bool EnsurePathExists(const wxString &aPath, bool aPathToFile=false)
Attempts to create a given path if it does not exist.
Definition paths.cpp:508
static wxString GetStock3dmodelsPath()
Gets the stock (install) 3dmodels path.
Definition paths.cpp:333
static wxString GetStockTemplatesPath()
Gets the stock (install) templates path.
Definition paths.cpp:355
static wxString GetUserSettingsPath()
Return the user configuration path used to store KiCad's configuration files.
Definition paths.cpp:624
static wxString GetStockDesignBlocksPath()
Gets the stock (install) footprints path.
Definition paths.cpp:322
static wxString GetStockFootprintsPath()
Gets the stock (install) footprints path.
Definition paths.cpp:311
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:123
std::shared_ptr< NET_SETTINGS > m_NetSettings
Net settings for this project (owned here)
Container for project specific data.
Definition project.h:63
virtual const wxString GetProjectPath() const
Return the full path of the project.
Definition project.cpp:183
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition project.cpp:195
virtual PROJECT_FILE & GetProjectFile() const
Definition project.h:201
PROJECT & Prj() const
A helper while we are not MDI-capable – return the one and only project.
An abstract shape on 2D plane.
Definition shape.h:124
A type-safe container of any type.
Definition ki_any.h:92
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition common.cpp:776
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, RESOLUTION_CONTEXT aContext)
Definition common.cpp:60
@ INTERNAL
Definition common.h:94
static std::string ToStdString(const wxString &aStr)
wxString FindKicadFile(const wxString &shortname)
Search the executable file shortname in KiCad binary path and return full file name if found or short...
Definition gestfich.cpp:67
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput, const EDA_IU_SCALE &aScale)
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
RequestMessageType Request
Definition api_handler.h:54
std::string path
wxString result
Test unit parsing edge cases and error handling.
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708