21#include <magic_enum.hpp> 
   25#include <wx/stdstream.h> 
   26#include <wx/wfstream.h> 
   42    void error( 
const nlohmann::json::json_pointer& ptr, 
const nlohmann::json& instance,
 
   43                const std::string& message )
 override 
   47                    wxString::Format( wxS( 
"JSON error: at %s, value:\n%s\n%s" ),
 
   48                                      ptr.to_string(), instance.dump(), message ) );
 
 
 
   62        type = magic_enum::enum_cast<PLUGIN_RUNTIME_TYPE>( aJson.at( 
"type" ).get<std::string>(),
 
   63                                                           magic_enum::case_insensitive )
 
 
   99    if( !aConfigFile.IsFileReadable() )
 
  102    wxLogTrace( 
traceApi, 
"Plugin: parsing config file" );
 
  104    wxFFileInputStream fp( aConfigFile.GetFullPath(), wxT( 
"rt" ) );
 
  105    wxStdInputStream fstream( fp );
 
  111        js = nlohmann::json::parse( fstream, 
nullptr,
 
  117        wxLogTrace( 
traceApi, 
"Plugin: exception during parse" );
 
  122    aValidator.
Validate( js, handler, nlohmann::json_uri( 
"#/definitions/Plugin" ) );
 
  125        wxLogTrace( 
traceApi, 
"Plugin: schema validation successful" );
 
  130        identifier = js.at( 
"identifier" ).get<wxString>();
 
  131        name = js.at( 
"name" ).get<wxString>();
 
  132        description = js.at( 
"description" ).get<wxString>();
 
  134        if( !
runtime.FromJson( js.at( 
"runtime" ) ) )
 
  136            wxLogTrace( 
traceApi, 
"Plugin: error parsing runtime section" );
 
  142        wxLogTrace( 
traceApi, 
"Plugin: exception while parsing required keys" );
 
  148        wxLogTrace( 
traceApi, wxString::Format( 
"Plugin: identifier %s does not meet requirements",
 
  157        const nlohmann::json& actionsJs = js.at( 
"actions" );
 
  159        if( actionsJs.is_array() )
 
  161            for( 
const nlohmann::json& actionJs : actionsJs )
 
  163                if( std::optional<PLUGIN_ACTION> a = 
parent.createActionFromJson( actionJs ) )
 
  165                    a->identifier = wxString::Format( 
"%s.%s", 
identifier, a->identifier );
 
  166                    wxLogTrace( 
traceApi, wxString::Format( 
"Plugin: loaded action %s",
 
  175        wxLogTrace( 
traceApi, 
"Plugin: exception while parsing actions" );
 
 
  203    wxRegEx identifierRegex( wxS( 
"[\\w\\d]{2,}\\.[\\w\\d]+\\.[\\w\\d]+" ) );
 
  204    return identifierRegex.Matches( aIdentifier );
 
 
  258        action.
identifier = aJson.at( 
"identifier" ).get<wxString>();
 
  259        wxLogTrace( 
traceApi, wxString::Format( 
"Plugin: load action %s", action.
identifier ) );
 
  260        action.
name = aJson.at( 
"name" ).get<wxString>();
 
  261        action.
description = aJson.at( 
"description" ).get<wxString>();
 
  262        action.
entrypoint = aJson.at( 
"entrypoint" ).get<wxString>();
 
  263        action.
show_button = aJson.contains( 
"show-button" ) && aJson.at( 
"show-button" ).get<
bool>();
 
  267        wxLogTrace( 
traceApi, 
"Plugin: exception while parsing action required keys" );
 
  273    if( !f.IsRelative() )
 
  275        wxLogTrace( 
traceApi, wxString::Format( 
"Plugin: action contains abs path %s; skipping",
 
  280    f.Normalize( wxPATH_NORM_ABSOLUTE, 
m_configFile.GetPath() );
 
  282    if( !f.IsFileReadable() )
 
  284        wxLogTrace( 
traceApi, wxString::Format( 
"WARNING: action entrypoint %s is not readable",
 
  288    if( aJson.contains( 
"args" ) && aJson.at( 
"args" ).is_array() )
 
  290        for( 
const nlohmann::json& argJs : aJson.at( 
"args" ) )
 
  294                action.
args.emplace_back( argJs.get<wxString>() );
 
  298                wxLogTrace( 
traceApi, 
"Plugin: exception while parsing action args" );
 
  304    if( aJson.contains( 
"scopes" ) && aJson.at( 
"scopes" ).is_array() )
 
  306        for( 
const nlohmann::json& scopeJs : aJson.at( 
"scopes" ) )
 
  310                action.
scopes.insert( magic_enum::enum_cast<PLUGIN_ACTION_SCOPE>(
 
  311                        scopeJs.get<std::string>(), magic_enum::case_insensitive )
 
  316                wxLogTrace( 
traceApi, 
"Plugin: exception while parsing action scopes" );
 
  323            [&]( 
const std::string& aKey, wxBitmapBundle& aDest )
 
  325                if( aJson.contains( aKey ) && aJson.at( aKey ).is_array() )
 
  327                    wxVector<wxBitmap> bitmaps;
 
  329                    for( 
const nlohmann::json& iconJs : aJson.at( aKey ) )
 
  335                            iconFile = iconJs.get<wxString>();
 
  342                        iconFile.Normalize( wxPATH_NORM_ABSOLUTE, 
m_configFile.GetPath() );
 
  345                                    wxString::Format( 
"Plugin: action %s: loading icon %s",
 
  346                                                      action.
identifier, iconFile.GetFullPath() ) );
 
  349                        if( !iconFile.IsFileReadable() )
 
  351                            wxLogTrace( 
traceApi, 
"Plugin: icon file could not be read" );
 
  357                        bmp.LoadFile( iconFile.GetFullPath(), wxBITMAP_TYPE_PNG );
 
  360                            bitmaps.push_back( bmp );
 
  362                            wxLogTrace( 
traceApi, 
"Plugin: icon file not a valid bitmap" );
 
  365                    aDest = wxBitmapBundle::FromBitmaps( bitmaps );
 
  369    handleBitmap( 
"icons-light", action.
icon_light );
 
  370    handleBitmap( 
"icons-dark", action.
icon_dark );
 
 
A plugin that is invoked by KiCad and runs as an external process; communicating with KiCad via the I...
 
const PLUGIN_RUNTIME & Runtime() const
 
const wxString & Name() const
 
const std::vector< PLUGIN_ACTION > & Actions() const
 
friend struct API_PLUGIN_CONFIG
 
wxString ActionSettingsKey(const PLUGIN_ACTION &aAction) const
 
const wxString & Identifier() const
 
std::unique_ptr< API_PLUGIN_CONFIG > m_config
 
wxString BasePath() const
 
static bool IsValidIdentifier(const wxString &aIdentifier)
 
const wxString & Description() const
 
API_PLUGIN(const wxFileName &aConfigFile, const JSON_SCHEMA_VALIDATOR &aValidator)
 
std::optional< PLUGIN_ACTION > createActionFromJson(const nlohmann::json &aJson)
 
nlohmann::json Validate(const nlohmann::json &aJson, nlohmann::json_schema::error_handler &aErrorHandler, const nlohmann::json_uri &aInitialUri=nlohmann::json_uri("#")) const
 
void error(const nlohmann::json::json_pointer &ptr, const nlohmann::json &instance, const std::string &message) override
 
const wxChar *const traceApi
Flag to enable debug output related to the IPC API and its plugin system.
 
API_PLUGIN_CONFIG(API_PLUGIN &aParent, const wxFileName &aConfigFile, const JSON_SCHEMA_VALIDATOR &aValidator)
 
std::vector< PLUGIN_ACTION > actions
 
An action performed by a plugin via the IPC API (not to be confused with ACTION_PLUGIN,...
 
wxBitmapBundle icon_light
 
std::set< PLUGIN_ACTION_SCOPE > scopes
 
std::vector< wxString > args
 
bool FromJson(const nlohmann::json &aJson)