ADDED: Remote symbol placement
Allows activating a display panel that shows a webpage designed to provide instances of symbols, footprints, 3d models and spice models to the designer. The webpage can be installed via PCM or directly in the panel. Webpages should be registered with the KiCad project in order to avoid a warning when showing content.
This commit is contained in:
@@ -720,6 +720,7 @@ set( COMMON_SRCS
|
||||
refdes_utils.cpp
|
||||
reference_image.cpp
|
||||
render_settings.cpp
|
||||
remote_login_server.cpp
|
||||
status_popup.cpp
|
||||
stroke_params.cpp
|
||||
template_fieldnames.cpp
|
||||
|
||||
@@ -1372,6 +1372,7 @@ void EDA_BASE_FRAME::ShowPreferences( wxString aStartPage, wxString aStartParent
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_TOOLBARS ), _( "Toolbars" ) );
|
||||
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_FIELD_NAME_TEMPLATES ), _( "Field Name Templates" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_DATA_SOURCES ), _( "Data Sources" ) );
|
||||
book->AddLazySubPage( LAZY_CTOR( PANEL_SCH_SIMULATOR ), _( "Simulator" ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -656,6 +656,14 @@ std::optional<LIBRARY_TABLE_ROW*> LIBRARY_MANAGER::FindRowByURI( LIBRARY_TABLE_T
|
||||
}
|
||||
|
||||
|
||||
void LIBRARY_MANAGER::ReloadLibraryEntry( LIBRARY_TABLE_TYPE aType, const wxString& aNickname,
|
||||
LIBRARY_TABLE_SCOPE aScope )
|
||||
{
|
||||
if( std::optional<LIBRARY_MANAGER_ADAPTER*> adapter = Adapter( aType ); adapter )
|
||||
( *adapter )->ReloadLibraryEntry( aNickname, aScope );
|
||||
}
|
||||
|
||||
|
||||
void LIBRARY_MANAGER::LoadProjectTables( const wxString& aProjectPath )
|
||||
{
|
||||
if( wxFileName::IsDirReadable( aProjectPath ) )
|
||||
@@ -810,7 +818,7 @@ void LIBRARY_MANAGER_ADAPTER::CheckTableRow( LIBRARY_TABLE_ROW& aRow )
|
||||
aRow.SetErrorDescription( plugin.error().message );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
LIBRARY_TABLE* LIBRARY_MANAGER_ADAPTER::GlobalTable() const
|
||||
@@ -1003,6 +1011,59 @@ std::vector<std::pair<wxString, LIB_STATUS>> LIBRARY_MANAGER_ADAPTER::GetLibrary
|
||||
}
|
||||
|
||||
|
||||
void LIBRARY_MANAGER_ADAPTER::ReloadLibraryEntry( const wxString& aNickname,
|
||||
LIBRARY_TABLE_SCOPE aScope )
|
||||
{
|
||||
auto reloadScope =
|
||||
[&]( LIBRARY_TABLE_SCOPE aScopeToReload, std::map<wxString, LIB_DATA>& aTarget,
|
||||
std::mutex& aMutex )
|
||||
{
|
||||
bool wasLoaded = false;
|
||||
|
||||
{
|
||||
std::lock_guard lock( aMutex );
|
||||
auto it = aTarget.find( aNickname );
|
||||
|
||||
if( it != aTarget.end() && it->second.plugin )
|
||||
{
|
||||
wasLoaded = true;
|
||||
aTarget.erase( it );
|
||||
}
|
||||
}
|
||||
|
||||
if( wasLoaded )
|
||||
{
|
||||
if( LIBRARY_RESULT<LIB_DATA*> result =
|
||||
loadFromScope( aNickname, aScopeToReload, aTarget, aMutex );
|
||||
!result.has_value() )
|
||||
{
|
||||
wxLogTrace( traceLibraries,
|
||||
"ReloadLibraryEntry: failed to reload %s (%s): %s",
|
||||
aNickname, magic_enum::enum_name( aScopeToReload ),
|
||||
result.error().message );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
switch( aScope )
|
||||
{
|
||||
case LIBRARY_TABLE_SCOPE::GLOBAL:
|
||||
reloadScope( LIBRARY_TABLE_SCOPE::GLOBAL, globalLibs(), globalLibsMutex() );
|
||||
break;
|
||||
|
||||
case LIBRARY_TABLE_SCOPE::PROJECT:
|
||||
reloadScope( LIBRARY_TABLE_SCOPE::PROJECT, m_libraries, m_libraries_mutex );
|
||||
break;
|
||||
|
||||
case LIBRARY_TABLE_SCOPE::BOTH:
|
||||
case LIBRARY_TABLE_SCOPE::UNINITIALIZED:
|
||||
reloadScope( LIBRARY_TABLE_SCOPE::PROJECT, m_libraries, m_libraries_mutex );
|
||||
reloadScope( LIBRARY_TABLE_SCOPE::GLOBAL, globalLibs(), globalLibsMutex() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LIBRARY_MANAGER_ADAPTER::IsWritable( const wxString& aNickname ) const
|
||||
{
|
||||
if( std::optional<const LIB_DATA*> result = fetchIfLoaded( aNickname ) )
|
||||
@@ -1078,56 +1139,56 @@ std::optional<LIB_DATA*> LIBRARY_MANAGER_ADAPTER::fetchIfLoaded(
|
||||
}
|
||||
|
||||
|
||||
LIBRARY_RESULT<LIB_DATA*> LIBRARY_MANAGER_ADAPTER::loadIfNeeded( const wxString& aNickname )
|
||||
LIBRARY_RESULT<LIB_DATA*> LIBRARY_MANAGER_ADAPTER::loadFromScope( const wxString& aNickname,
|
||||
LIBRARY_TABLE_SCOPE aScope, std::map<wxString, LIB_DATA>& aTarget, std::mutex& aMutex )
|
||||
{
|
||||
auto tryLoadFromScope =
|
||||
[&]( LIBRARY_TABLE_SCOPE aScope, std::map<wxString, LIB_DATA>& aTarget,
|
||||
std::mutex& aMutex ) -> LIBRARY_RESULT<LIB_DATA*>
|
||||
bool present = false;
|
||||
|
||||
{
|
||||
std::lock_guard lock( aMutex );
|
||||
present = aTarget.contains( aNickname ) && aTarget.at( aNickname ).plugin;
|
||||
}
|
||||
|
||||
if( !present )
|
||||
{
|
||||
if( auto result = m_manager.GetRow( Type(), aNickname, aScope ) )
|
||||
{
|
||||
const LIBRARY_TABLE_ROW* row = *result;
|
||||
wxLogTrace( traceLibraries, "Library %s (%s) not yet loaded, will attempt...",
|
||||
aNickname, magic_enum::enum_name( aScope ) );
|
||||
|
||||
if( LIBRARY_RESULT<IO_BASE*> plugin = createPlugin( row ); plugin.has_value() )
|
||||
{
|
||||
bool present = false;
|
||||
std::lock_guard lock( aMutex );
|
||||
|
||||
{
|
||||
std::lock_guard lock( aMutex );
|
||||
present = aTarget.contains( aNickname ) && aTarget.at( aNickname ).plugin;
|
||||
}
|
||||
|
||||
if( !present )
|
||||
{
|
||||
if( auto result = m_manager.GetRow( Type(), aNickname, aScope ) )
|
||||
{
|
||||
const LIBRARY_TABLE_ROW* row = *result;
|
||||
wxLogTrace( traceLibraries, "Library %s (%s) not yet loaded, will attempt...",
|
||||
aNickname, magic_enum::enum_name( aScope ) );
|
||||
|
||||
if( LIBRARY_RESULT<IO_BASE*> plugin = createPlugin( row ); plugin.has_value() )
|
||||
{
|
||||
std::lock_guard lock( aMutex );
|
||||
|
||||
aTarget[ row->Nickname() ].status.load_status = LOAD_STATUS::LOADING;
|
||||
aTarget[ row->Nickname() ].row = row;
|
||||
aTarget[ row->Nickname() ].plugin.reset( *plugin );
|
||||
|
||||
return &aTarget.at( aNickname );
|
||||
}
|
||||
else
|
||||
{
|
||||
return tl::unexpected( plugin.error() );
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
aTarget[ row->Nickname() ].status.load_status = LOAD_STATUS::LOADING;
|
||||
aTarget[ row->Nickname() ].row = row;
|
||||
aTarget[ row->Nickname() ].plugin.reset( *plugin );
|
||||
|
||||
return &aTarget.at( aNickname );
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
return tl::unexpected( plugin.error() );
|
||||
}
|
||||
}
|
||||
|
||||
LIBRARY_RESULT<LIB_DATA*> result = tryLoadFromScope( LIBRARY_TABLE_SCOPE::PROJECT, m_libraries,
|
||||
m_libraries_mutex );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &aTarget.at( aNickname );
|
||||
}
|
||||
|
||||
|
||||
LIBRARY_RESULT<LIB_DATA*> LIBRARY_MANAGER_ADAPTER::loadIfNeeded( const wxString& aNickname )
|
||||
{
|
||||
LIBRARY_RESULT<LIB_DATA*> result =
|
||||
loadFromScope( aNickname, LIBRARY_TABLE_SCOPE::PROJECT, m_libraries, m_libraries_mutex );
|
||||
|
||||
if( !result.has_value() || *result )
|
||||
return result;
|
||||
|
||||
result = tryLoadFromScope( LIBRARY_TABLE_SCOPE::GLOBAL, globalLibs(), globalLibsMutex() );
|
||||
result = loadFromScope( aNickname, LIBRARY_TABLE_SCOPE::GLOBAL, globalLibs(), globalLibsMutex() );
|
||||
|
||||
if( !result.has_value() || *result )
|
||||
return result;
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/gpl-3.0.html
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <wx/tokenzr.h>
|
||||
#include <wx/uri.h>
|
||||
|
||||
#include <remote_login_server.h>
|
||||
|
||||
|
||||
wxDEFINE_EVENT( EVT_REMOTE_SYMBOL_LOGIN_RESULT, wxCommandEvent );
|
||||
|
||||
REMOTE_LOGIN_SERVER::REMOTE_LOGIN_SERVER( wxEvtHandler* aOwner, const wxString& aRedirectUrl ) :
|
||||
m_owner( aOwner ),
|
||||
m_redirectUrl( aRedirectUrl ),
|
||||
m_port( 0 ),
|
||||
m_done( false )
|
||||
{
|
||||
m_timeout.SetOwner( this );
|
||||
Bind( wxEVT_TIMER, &REMOTE_LOGIN_SERVER::OnTimeout, this, m_timeout.GetId() );
|
||||
}
|
||||
|
||||
REMOTE_LOGIN_SERVER::~REMOTE_LOGIN_SERVER()
|
||||
{
|
||||
m_timeout.Stop();
|
||||
Unbind( wxEVT_SOCKET, &REMOTE_LOGIN_SERVER::OnSocketEvent, this );
|
||||
Unbind( wxEVT_TIMER, &REMOTE_LOGIN_SERVER::OnTimeout, this, m_timeout.GetId() );
|
||||
Shutdown();
|
||||
m_timeout.SetOwner( nullptr );
|
||||
}
|
||||
|
||||
bool REMOTE_LOGIN_SERVER::Start()
|
||||
{
|
||||
wxIPV4address addr;
|
||||
addr.AnyAddress();
|
||||
addr.Service( 0 );
|
||||
|
||||
std::unique_ptr<wxSocketServer> server =
|
||||
std::make_unique<wxSocketServer>( addr, wxSOCKET_REUSEADDR );
|
||||
|
||||
if( !server->IsOk() )
|
||||
return false;
|
||||
|
||||
server->SetEventHandler( *this );
|
||||
server->SetNotify( wxSOCKET_CONNECTION_FLAG );
|
||||
server->Notify( true );
|
||||
|
||||
wxIPV4address local;
|
||||
server->GetLocal( local );
|
||||
m_port = local.Service();
|
||||
|
||||
Bind( wxEVT_SOCKET, &REMOTE_LOGIN_SERVER::OnSocketEvent, this );
|
||||
|
||||
m_server = std::move( server );
|
||||
m_timeout.StartOnce( 120000 );
|
||||
return m_port != 0;
|
||||
}
|
||||
|
||||
void REMOTE_LOGIN_SERVER::OnSocketEvent( wxSocketEvent& aEvent )
|
||||
{
|
||||
if( !m_server || aEvent.GetSocketEvent() != wxSOCKET_CONNECTION )
|
||||
return;
|
||||
|
||||
std::unique_ptr<wxSocketBase> client( m_server->Accept( false ) );
|
||||
|
||||
if( !client )
|
||||
return;
|
||||
|
||||
HandleClient( client.get() );
|
||||
}
|
||||
|
||||
void REMOTE_LOGIN_SERVER::OnTimeout( wxTimerEvent& aEvent )
|
||||
{
|
||||
wxUnusedVar( aEvent );
|
||||
Finish( false, wxString() );
|
||||
}
|
||||
|
||||
void REMOTE_LOGIN_SERVER::HandleClient( wxSocketBase* aClient )
|
||||
{
|
||||
if( !aClient )
|
||||
return;
|
||||
|
||||
aClient->SetTimeout( 5 );
|
||||
aClient->SetFlags( wxSOCKET_NONE );
|
||||
|
||||
std::string request;
|
||||
request.reserve( 512 );
|
||||
|
||||
char buffer[512];
|
||||
|
||||
while( aClient->IsConnected() )
|
||||
{
|
||||
if( !aClient->WaitForRead( 1, 0 ) )
|
||||
break;
|
||||
|
||||
aClient->Read( buffer, sizeof( buffer ) );
|
||||
size_t count = aClient->LastCount();
|
||||
|
||||
if( count == 0 )
|
||||
break;
|
||||
|
||||
request.append( buffer, count );
|
||||
|
||||
if( request.find( "\r\n\r\n" ) != std::string::npos || request.size() > 4096 )
|
||||
break;
|
||||
}
|
||||
|
||||
SendHttpResponse( aClient );
|
||||
|
||||
wxString requestWx = wxString::FromUTF8( request.data(), request.size() );
|
||||
int endOfLine = requestWx.Find( wxS( "\r\n" ) );
|
||||
wxString requestLine = endOfLine == wxNOT_FOUND ? requestWx : requestWx.Mid( 0, endOfLine );
|
||||
|
||||
wxString userId = ExtractUserId( requestLine );
|
||||
Finish( !userId.IsEmpty(), userId );
|
||||
}
|
||||
|
||||
wxString REMOTE_LOGIN_SERVER::ExtractUserId( const wxString& aRequestLine ) const
|
||||
{
|
||||
wxStringTokenizer tokenizer( aRequestLine, wxS( " " ) );
|
||||
|
||||
if( !tokenizer.HasMoreTokens() )
|
||||
return wxString();
|
||||
|
||||
tokenizer.GetNextToken();
|
||||
|
||||
if( !tokenizer.HasMoreTokens() )
|
||||
return wxString();
|
||||
|
||||
wxString path = tokenizer.GetNextToken();
|
||||
int queryPos = path.Find( '?' );
|
||||
|
||||
if( queryPos == wxNOT_FOUND )
|
||||
return wxString();
|
||||
|
||||
wxString query = path.Mid( queryPos + 1 );
|
||||
wxStringTokenizer queryTokenizer( query, wxS( "&" ) );
|
||||
|
||||
while( queryTokenizer.HasMoreTokens() )
|
||||
{
|
||||
wxString pair = queryTokenizer.GetNextToken();
|
||||
int eqPos = pair.Find( '=' );
|
||||
|
||||
if( eqPos == wxNOT_FOUND )
|
||||
continue;
|
||||
|
||||
wxString name = pair.Left( eqPos );
|
||||
wxString value = pair.Mid( eqPos + 1 );
|
||||
|
||||
if( name == wxS( "user_id" ) )
|
||||
return wxURI::Unescape( value );
|
||||
}
|
||||
|
||||
return wxString();
|
||||
}
|
||||
|
||||
void REMOTE_LOGIN_SERVER::SendHttpResponse( wxSocketBase* aClient )
|
||||
{
|
||||
if( !aClient )
|
||||
return;
|
||||
|
||||
wxString redirect = m_redirectUrl;
|
||||
|
||||
if( redirect.IsEmpty() )
|
||||
redirect = wxS( "about:blank" );
|
||||
|
||||
wxString html;
|
||||
html << wxS( "<!DOCTYPE html><html><head>" )
|
||||
<< wxS( "<meta http-equiv=\"refresh\" content=\"0;url=" ) << redirect << wxS( "\">" )
|
||||
<< wxS( "</head><body>" )
|
||||
<< wxS( "<script>window.location.href = '" ) << redirect << wxS( "';</script>" )
|
||||
<< wxS( "<p>Login successful. Redirecting...</p>" )
|
||||
<< wxS( "</body></html>" );
|
||||
|
||||
wxScopedCharBuffer body = html.ToUTF8();
|
||||
|
||||
wxString response;
|
||||
response << wxS( "HTTP/1.1 200 OK\r\n" )
|
||||
<< wxS( "Content-Type: text/html; charset=utf-8\r\n" )
|
||||
<< wxS( "Access-Control-Allow-Origin: *\r\n" )
|
||||
<< wxS( "Cache-Control: no-store\r\n" )
|
||||
<< wxS( "Connection: close\r\n" )
|
||||
<< wxS( "Content-Length: " ) << body.length() << wxS( "\r\n\r\n" );
|
||||
|
||||
wxScopedCharBuffer header = response.ToUTF8();
|
||||
|
||||
aClient->Write( header.data(), header.length() );
|
||||
aClient->Write( body.data(), body.length() );
|
||||
aClient->Close();
|
||||
}
|
||||
|
||||
void REMOTE_LOGIN_SERVER::Finish( bool aSuccess, const wxString& aUserId )
|
||||
{
|
||||
if( m_done )
|
||||
return;
|
||||
|
||||
m_done = true;
|
||||
m_timeout.Stop();
|
||||
|
||||
wxCommandEvent evt( EVT_REMOTE_SYMBOL_LOGIN_RESULT );
|
||||
evt.SetInt( aSuccess ? 1 : 0 );
|
||||
evt.SetString( aUserId );
|
||||
wxQueueEvent( m_owner, evt.Clone() );
|
||||
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void REMOTE_LOGIN_SERVER::Shutdown()
|
||||
{
|
||||
if( m_server )
|
||||
{
|
||||
m_server->Notify( false );
|
||||
m_server.reset();
|
||||
}
|
||||
}
|
||||
@@ -222,7 +222,7 @@ LIB_TREE::LIB_TREE( wxWindow* aParent, const wxString& aRecentSearchesKey,
|
||||
{
|
||||
m_query_ctrl->SetDescriptiveText( _( "Filter" ) );
|
||||
m_query_ctrl->SetFocus();
|
||||
m_query_ctrl->SetValue( wxEmptyString );
|
||||
m_query_ctrl->ChangeValue( wxEmptyString );
|
||||
updateRecentSearchMenu();
|
||||
|
||||
// Force an update of the adapter with the empty text to ensure preselect is done
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
*/
|
||||
|
||||
#include <build_version.h>
|
||||
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tool/tool_base.h>
|
||||
|
||||
#include <widgets/webview_panel.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/webviewarchivehandler.h>
|
||||
@@ -25,11 +29,15 @@
|
||||
#include <wx/utils.h>
|
||||
#include <wx/log.h>
|
||||
|
||||
WEBVIEW_PANEL::WEBVIEW_PANEL( wxWindow* aParent, wxWindowID aId, const wxPoint& aPos,
|
||||
const wxSize& aSize, const int aStyle )
|
||||
: wxPanel( aParent, aId, aPos, aSize, aStyle ),
|
||||
m_initialized( false ),
|
||||
m_browser( wxWebView::New() )
|
||||
WEBVIEW_PANEL::WEBVIEW_PANEL( wxWindow* aParent, wxWindowID aId, const wxPoint& aPos, const wxSize& aSize,
|
||||
const int aStyle, TOOL_MANAGER* aToolManager, TOOL_BASE* aTool ) :
|
||||
wxPanel( aParent, aId, aPos, aSize, aStyle ),
|
||||
m_initialized( false ),
|
||||
m_handleExternalLinks( false ),
|
||||
m_loadError( false ),
|
||||
m_browser( wxWebView::New() ),
|
||||
m_toolManager( aToolManager ),
|
||||
m_tool( aTool )
|
||||
{
|
||||
wxBoxSizer* sizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
@@ -66,6 +74,8 @@ WEBVIEW_PANEL::~WEBVIEW_PANEL()
|
||||
|
||||
void WEBVIEW_PANEL::LoadURL( const wxString& aURL )
|
||||
{
|
||||
wxLogTrace( "webview", "Loading URL: %s", aURL );
|
||||
|
||||
if( aURL.starts_with( "file:/" ) && !aURL.starts_with( "file:///" ) )
|
||||
{
|
||||
wxString new_url = wxString( "file:///" ) + aURL.AfterFirst( '/' );
|
||||
@@ -84,26 +94,52 @@ void WEBVIEW_PANEL::LoadURL( const wxString& aURL )
|
||||
|
||||
void WEBVIEW_PANEL::SetPage( const wxString& aHtmlContent )
|
||||
{
|
||||
wxLogTrace( "webview", "Setting page content" );
|
||||
m_browser->SetPage( aHtmlContent, "file://" );
|
||||
}
|
||||
|
||||
bool WEBVIEW_PANEL::AddMessageHandler( const wxString& aName, MESSAGE_HANDLER aHandler )
|
||||
{
|
||||
m_msgHandlers.emplace( aName, std::move(aHandler) );
|
||||
wxLogTrace( "webview", "Adding message handler for: %s", aName );
|
||||
auto it = m_msgHandlers.find( aName );
|
||||
|
||||
if( it != m_msgHandlers.end() )
|
||||
{
|
||||
it->second = std::move( aHandler );
|
||||
return true;
|
||||
}
|
||||
|
||||
m_msgHandlers.emplace( aName, std::move( aHandler ) );
|
||||
|
||||
if( m_initialized )
|
||||
{
|
||||
if( !m_browser->AddScriptMessageHandler( aName ) )
|
||||
wxLogDebug( "Could not add script message handler %s", aName );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WEBVIEW_PANEL::ClearMessageHandlers()
|
||||
{
|
||||
wxLogTrace( "webview", "Clearing all message handlers" );
|
||||
|
||||
for( const auto& handler : m_msgHandlers )
|
||||
m_browser->RemoveScriptMessageHandler( handler.first );
|
||||
|
||||
m_msgHandlers.clear();
|
||||
}
|
||||
|
||||
void WEBVIEW_PANEL::OnNavigationRequest( wxWebViewEvent& aEvt )
|
||||
{
|
||||
m_loadError = false;
|
||||
wxLogTrace( "webview", "Navigation request to URL: %s", aEvt.GetURL() );
|
||||
// Default behavior: open external links in the system browser
|
||||
bool isExternal = aEvt.GetURL().StartsWith( "http://" ) || aEvt.GetURL().StartsWith( "https://" );
|
||||
if( isExternal )
|
||||
|
||||
if( isExternal && !m_handleExternalLinks )
|
||||
{
|
||||
wxLogTrace( "webview", "Opening external URL in system browser: %s", aEvt.GetURL() );
|
||||
wxLaunchDefaultBrowser( aEvt.GetURL() );
|
||||
aEvt.Veto();
|
||||
}
|
||||
@@ -114,23 +150,17 @@ void WEBVIEW_PANEL::OnWebViewLoaded( wxWebViewEvent& aEvt )
|
||||
if( !m_initialized )
|
||||
{
|
||||
// Defer handler registration to avoid running during modal dialog/yield
|
||||
CallAfter([this]() {
|
||||
static bool handler_added_inner = false;
|
||||
if (!handler_added_inner) {
|
||||
|
||||
for( const auto& handler : m_msgHandlers )
|
||||
auto initFunc = [this]() {
|
||||
for( const auto& handler : m_msgHandlers )
|
||||
{
|
||||
if( !m_browser->AddScriptMessageHandler( handler.first ) )
|
||||
{
|
||||
if( !m_browser->AddScriptMessageHandler( handler.first ) )
|
||||
{
|
||||
wxLogDebug( "Could not add script message handler %s", handler.first );
|
||||
}
|
||||
wxLogDebug( "Could not add script message handler %s", handler.first );
|
||||
}
|
||||
|
||||
handler_added_inner = true;
|
||||
}
|
||||
|
||||
// Inject navigation hook for SPA/JS navigation to prevent webkit crashing without new window
|
||||
m_browser->AddUserScript(R"(
|
||||
// Inject navigation hook for SPA/JS navigation to prevent webkit crashing without new window
|
||||
m_browser->AddUserScript( R"(
|
||||
(function() {
|
||||
// Change window.open to navigate in the same window
|
||||
window.open = function(url) { if (url) window.location.href = url; return null; };
|
||||
@@ -153,11 +183,19 @@ void WEBVIEW_PANEL::OnWebViewLoaded( wxWebViewEvent& aEvt )
|
||||
});
|
||||
}
|
||||
})();
|
||||
)");
|
||||
});
|
||||
)" );
|
||||
|
||||
};
|
||||
|
||||
if( m_toolManager && m_tool )
|
||||
m_toolManager->RunMainStack( m_tool, initFunc );
|
||||
else
|
||||
CallAfter( initFunc );
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
aEvt.Skip();
|
||||
}
|
||||
|
||||
void WEBVIEW_PANEL::OnNewWindow( wxWebViewEvent& aEvt )
|
||||
@@ -173,22 +211,30 @@ void WEBVIEW_PANEL::OnNewWindow( wxWebViewEvent& aEvt )
|
||||
void WEBVIEW_PANEL::OnScriptMessage( wxWebViewEvent& aEvt )
|
||||
{
|
||||
wxLogTrace( "webview", "Script message received: %s for handler %s", aEvt.GetString(), aEvt.GetMessageHandler() );
|
||||
wxString handler = aEvt.GetMessageHandler();
|
||||
handler.Trim(true).Trim(false);
|
||||
|
||||
if( aEvt.GetMessageHandler().IsEmpty() )
|
||||
if( handler.IsEmpty() )
|
||||
{
|
||||
wxLogDebug( "No message handler specified for script message: %s", aEvt.GetString() );
|
||||
for( auto handlerPair : m_msgHandlers )
|
||||
{
|
||||
wxLogTrace( "webview", "No handler specified, trying: %s", handlerPair.first );
|
||||
handlerPair.second( aEvt.GetString() );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = m_msgHandlers.find( aEvt.GetMessageHandler() );
|
||||
auto it = m_msgHandlers.find( handler );
|
||||
|
||||
if( it == m_msgHandlers.end() )
|
||||
{
|
||||
wxLogDebug( "No handler registered for message: %s", aEvt.GetMessageHandler() );
|
||||
wxLogDebug( "No handler registered for message: %s", handler );
|
||||
return;
|
||||
}
|
||||
|
||||
// Call the registered handler with the message
|
||||
wxLogTrace( "webview", "Calling handler for message: %s", aEvt.GetMessageHandler() );
|
||||
wxLogTrace( "webview", "Calling handler for message: %s", handler );
|
||||
it->second( aEvt.GetString() );
|
||||
}
|
||||
|
||||
@@ -200,5 +246,6 @@ void WEBVIEW_PANEL::OnScriptResult( wxWebViewEvent& aEvt )
|
||||
|
||||
void WEBVIEW_PANEL::OnError( wxWebViewEvent& aEvt )
|
||||
{
|
||||
m_loadError = true;
|
||||
wxLogDebug( "WebView error: %s", aEvt.GetString() );
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ include_directories(
|
||||
${CMAKE_SOURCE_DIR}/libs/sexpr/include
|
||||
${INC_AFTER}
|
||||
./dialogs
|
||||
${CMAKE_SOURCE_DIR}/kicad/pcm
|
||||
./libview
|
||||
./symbol_editor
|
||||
./tools
|
||||
@@ -135,6 +136,7 @@ set( EESCHEMA_DLGS
|
||||
dialogs/dialog_pin_properties_base.cpp
|
||||
dialogs/dialog_plot_schematic.cpp
|
||||
dialogs/dialog_plot_schematic_base.cpp
|
||||
dialogs/dialog_remote_symbol_config.cpp
|
||||
dialogs/dialog_erc_job_config.cpp
|
||||
dialogs/dialog_rescue_each.cpp
|
||||
dialogs/dialog_rescue_each_base.cpp
|
||||
@@ -185,6 +187,7 @@ set( EESCHEMA_DLGS
|
||||
dialogs/panel_setup_pinmap_base.cpp
|
||||
dialogs/panel_simulator_preferences.cpp
|
||||
dialogs/panel_simulator_preferences_base.cpp
|
||||
dialogs/panel_sch_data_sources.cpp
|
||||
dialogs/panel_sym_color_settings.cpp
|
||||
dialogs/panel_sym_color_settings_base.cpp
|
||||
dialogs/panel_sym_display_options.cpp
|
||||
@@ -281,6 +284,7 @@ set( EESCHEMA_WIDGETS
|
||||
widgets/panel_sch_selection_filter_base.cpp
|
||||
widgets/panel_sch_selection_filter.cpp
|
||||
widgets/panel_symbol_chooser.cpp
|
||||
widgets/panel_remote_symbol.cpp
|
||||
widgets/pinshape_combobox.cpp
|
||||
widgets/pintype_combobox.cpp
|
||||
widgets/symbol_diff_widget.cpp
|
||||
@@ -567,6 +571,7 @@ set_source_files_properties( ${CMAKE_SOURCE_DIR}/common/single_top.cpp PROPERTIE
|
||||
|
||||
target_link_libraries( eeschema
|
||||
kicommon
|
||||
pcm
|
||||
${wxWidgets_LIBRARIES}
|
||||
)
|
||||
|
||||
@@ -584,6 +589,7 @@ if( KICAD_USE_PCH )
|
||||
<map>
|
||||
<memory>
|
||||
<unordered_map>
|
||||
<core/json_serializers.h>
|
||||
<sch_edit_frame.h>
|
||||
<string_utils.h>
|
||||
<schematic.h>
|
||||
@@ -599,7 +605,8 @@ target_include_directories( eeschema_kiface_objects
|
||||
|
||||
target_link_libraries( eeschema_kiface_objects
|
||||
PUBLIC
|
||||
common )
|
||||
common
|
||||
pcm )
|
||||
|
||||
# Since we're not using target_link_libraries, we need to explicitly
|
||||
# declare the dependency
|
||||
@@ -620,6 +627,7 @@ target_link_libraries( eeschema_kiface
|
||||
PRIVATE
|
||||
common
|
||||
eeschema_kiface_objects
|
||||
pcm
|
||||
markdown_lib
|
||||
scripting
|
||||
sexpr
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "dialog_remote_symbol_config.h"
|
||||
|
||||
#include <common.h>
|
||||
#include <kiplatform/environment.h>
|
||||
#include <pgm_base.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <widgets/ui_common.h>
|
||||
|
||||
#include <wx/button.h>
|
||||
#include <wx/dirdlg.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/intl.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/radiobut.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
|
||||
|
||||
DIALOG_REMOTE_SYMBOL_CONFIG::DIALOG_REMOTE_SYMBOL_CONFIG( wxWindow* aParent ) :
|
||||
DIALOG_SHIM( aParent, wxID_ANY, _( "Remote Symbol Settings" ), wxDefaultPosition,
|
||||
wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ),
|
||||
m_destinationCtrl( nullptr ),
|
||||
m_prefixCtrl( nullptr ),
|
||||
m_prefixHint( nullptr ),
|
||||
m_projectRadio( nullptr ),
|
||||
m_globalRadio( nullptr ),
|
||||
m_resetButton( nullptr ),
|
||||
m_browseButton( nullptr ),
|
||||
m_settings( GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" ) )
|
||||
{
|
||||
wxBoxSizer* topSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
wxStaticText* intro = new wxStaticText( this, wxID_ANY,
|
||||
_( "Configure where downloaded remote libraries are stored and how they are named." ) );
|
||||
intro->Wrap( FromDIP( 420 ) );
|
||||
topSizer->Add( intro, 0, wxALL | wxEXPAND, FromDIP( 10 ) );
|
||||
|
||||
wxFlexGridSizer* gridSizer = new wxFlexGridSizer( 2, FromDIP( 6 ), FromDIP( 6 ) );
|
||||
gridSizer->AddGrowableCol( 1, 1 );
|
||||
|
||||
gridSizer->Add( new wxStaticText( this, wxID_ANY, _( "Destination directory:" ) ),
|
||||
0, wxALIGN_CENTER_VERTICAL );
|
||||
|
||||
wxBoxSizer* destSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
m_destinationCtrl = new wxTextCtrl( this, wxID_ANY );
|
||||
m_destinationCtrl->SetMinSize( FromDIP( wxSize( 320, -1 ) ) );
|
||||
m_destinationCtrl->SetToolTip( _( "Directory where downloaded symbol, footprint, and 3D model data will be written." ) );
|
||||
destSizer->Add( m_destinationCtrl, 1, wxALIGN_CENTER_VERTICAL );
|
||||
|
||||
m_browseButton = new wxButton( this, wxID_ANY, _( "Browse…" ) );
|
||||
destSizer->Add( m_browseButton, 0, wxLEFT, FromDIP( 4 ) );
|
||||
gridSizer->Add( destSizer, 1, wxEXPAND );
|
||||
|
||||
gridSizer->Add( new wxStaticText( this, wxID_ANY, _( "Library prefix:" ) ),
|
||||
0, wxALIGN_CENTER_VERTICAL );
|
||||
m_prefixCtrl = new wxTextCtrl( this, wxID_ANY );
|
||||
m_prefixCtrl->SetToolTip( _( "Prefix that will be applied to the generated libraries." ) );
|
||||
gridSizer->Add( m_prefixCtrl, 0, wxEXPAND );
|
||||
|
||||
gridSizer->AddSpacer( 0 );
|
||||
m_prefixHint = new wxStaticText( this, wxID_ANY, wxString() );
|
||||
m_prefixHint->SetFont( KIUI::GetSmallInfoFont( this ).Italic() );
|
||||
gridSizer->Add( m_prefixHint, 0, wxEXPAND );
|
||||
|
||||
gridSizer->Add( new wxStaticText( this, wxID_ANY, _( "Add libraries to:" ) ),
|
||||
0, wxALIGN_CENTER_VERTICAL );
|
||||
|
||||
wxBoxSizer* radioSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
m_projectRadio = new wxRadioButton( this, wxID_ANY, _( "Project library table" ),
|
||||
wxDefaultPosition, wxDefaultSize, wxRB_GROUP );
|
||||
m_projectRadio->SetToolTip( _( "Adds the generated libraries to the project's library tables." ) );
|
||||
radioSizer->Add( m_projectRadio, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, FromDIP( 12 ) );
|
||||
|
||||
m_globalRadio = new wxRadioButton( this, wxID_ANY, _( "Global library table" ) );
|
||||
m_globalRadio->SetToolTip( _( "Adds the generated libraries to the global library tables." ) );
|
||||
radioSizer->Add( m_globalRadio, 0, wxALIGN_CENTER_VERTICAL );
|
||||
|
||||
gridSizer->Add( radioSizer, 0, wxEXPAND );
|
||||
|
||||
topSizer->Add( gridSizer, 0, wxALL | wxEXPAND, FromDIP( 10 ) );
|
||||
|
||||
m_resetButton = new wxButton( this, wxID_ANY, _( "Reset to Defaults" ) );
|
||||
m_resetButton->SetToolTip( _( "Restore the default destination and prefix." ) );
|
||||
topSizer->Add( m_resetButton, 0, wxLEFT | wxBOTTOM, FromDIP( 10 ) );
|
||||
|
||||
wxStdDialogButtonSizer* buttonSizer = CreateStdDialogButtonSizer( wxOK | wxCANCEL );
|
||||
topSizer->Add( buttonSizer, 0, wxALL | wxEXPAND, FromDIP( 10 ) );
|
||||
|
||||
SetSizer( topSizer );
|
||||
topSizer->Fit( this );
|
||||
|
||||
SetupStandardButtons();
|
||||
finishDialogSettings();
|
||||
|
||||
SetInitialFocus( m_destinationCtrl );
|
||||
|
||||
m_browseButton->Bind( wxEVT_BUTTON, &DIALOG_REMOTE_SYMBOL_CONFIG::onBrowseDestination, this );
|
||||
m_resetButton->Bind( wxEVT_BUTTON, &DIALOG_REMOTE_SYMBOL_CONFIG::onResetDefaults, this );
|
||||
m_prefixCtrl->Bind( wxEVT_TEXT, &DIALOG_REMOTE_SYMBOL_CONFIG::onPrefixChanged, this );
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_REMOTE_SYMBOL_CONFIG::TransferDataToWindow()
|
||||
{
|
||||
if( m_settings )
|
||||
applyRemoteSettings( m_settings->m_RemoteSymbol );
|
||||
else
|
||||
{
|
||||
EESCHEMA_SETTINGS::REMOTE_SYMBOL_CONFIG defaults;
|
||||
applyRemoteSettings( defaults );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DIALOG_REMOTE_SYMBOL_CONFIG::TransferDataFromWindow()
|
||||
{
|
||||
wxString destination = m_destinationCtrl->GetValue();
|
||||
wxString prefix = m_prefixCtrl->GetValue();
|
||||
|
||||
destination.Trim( true ).Trim( false );
|
||||
prefix.Trim( true ).Trim( false );
|
||||
|
||||
if( destination.IsEmpty() )
|
||||
{
|
||||
wxMessageBox( _( "Please choose a destination directory." ), GetTitle(), wxOK | wxICON_WARNING, this );
|
||||
m_destinationCtrl->SetFocus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if( prefix.IsEmpty() )
|
||||
{
|
||||
wxMessageBox( _( "Please enter a library prefix." ), GetTitle(), wxOK | wxICON_WARNING, this );
|
||||
m_prefixCtrl->SetFocus();
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !m_settings )
|
||||
m_settings = GetAppSettings<EESCHEMA_SETTINGS>( "eeschema" );
|
||||
|
||||
if( !m_settings )
|
||||
return true;
|
||||
|
||||
m_settings->m_RemoteSymbol.destination_dir = destination;
|
||||
m_settings->m_RemoteSymbol.library_prefix = prefix;
|
||||
m_settings->m_RemoteSymbol.add_to_global_table = m_globalRadio->GetValue();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_REMOTE_SYMBOL_CONFIG::onBrowseDestination( wxCommandEvent& aEvent )
|
||||
{
|
||||
wxUnusedVar( aEvent );
|
||||
|
||||
wxString initialPath = ExpandEnvVarSubstitutions( m_destinationCtrl->GetValue(), &Prj() );
|
||||
|
||||
if( initialPath.IsEmpty() )
|
||||
{
|
||||
if( Prj().IsNullProject() )
|
||||
initialPath = KIPLATFORM::ENV::GetDocumentsPath();
|
||||
else
|
||||
initialPath = Prj().GetProjectPath();
|
||||
}
|
||||
|
||||
wxDirDialog dlg( this, _( "Select Destination Directory" ), initialPath );
|
||||
|
||||
if( dlg.ShowModal() != wxID_OK )
|
||||
return;
|
||||
|
||||
wxString path = dlg.GetPath();
|
||||
|
||||
if( !Prj().IsNullProject() )
|
||||
{
|
||||
wxString projectRoot = Prj().GetProjectPath();
|
||||
|
||||
wxFileName selectedDir = wxFileName::DirName( path );
|
||||
|
||||
if( selectedDir.MakeRelativeTo( projectRoot ) )
|
||||
{
|
||||
wxString relative = selectedDir.GetFullPath();
|
||||
|
||||
if( relative.IsEmpty() || relative == wxS( "." ) )
|
||||
path = wxS( "${KIPRJMOD}" );
|
||||
else
|
||||
path = wxString::Format( wxS( "${KIPRJMOD}/%s" ), relative );
|
||||
}
|
||||
}
|
||||
|
||||
path.Replace( wxS( "\\" ), wxS( "/" ) );
|
||||
m_destinationCtrl->ChangeValue( path );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_REMOTE_SYMBOL_CONFIG::onResetDefaults( wxCommandEvent& aEvent )
|
||||
{
|
||||
wxUnusedVar( aEvent );
|
||||
|
||||
EESCHEMA_SETTINGS::REMOTE_SYMBOL_CONFIG defaults;
|
||||
applyRemoteSettings( defaults );
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_REMOTE_SYMBOL_CONFIG::onPrefixChanged( wxCommandEvent& aEvent )
|
||||
{
|
||||
wxUnusedVar( aEvent );
|
||||
updatePrefixHint();
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_REMOTE_SYMBOL_CONFIG::applyRemoteSettings(
|
||||
const EESCHEMA_SETTINGS::REMOTE_SYMBOL_CONFIG& aConfig )
|
||||
{
|
||||
m_destinationCtrl->ChangeValue( aConfig.destination_dir );
|
||||
m_prefixCtrl->ChangeValue( aConfig.library_prefix );
|
||||
|
||||
if( aConfig.add_to_global_table )
|
||||
m_globalRadio->SetValue( true );
|
||||
else
|
||||
m_projectRadio->SetValue( true );
|
||||
|
||||
updatePrefixHint();
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_REMOTE_SYMBOL_CONFIG::updatePrefixHint()
|
||||
{
|
||||
const wxString prefix = m_prefixCtrl->GetValue();
|
||||
|
||||
if( prefix.IsEmpty() )
|
||||
{
|
||||
m_prefixHint->SetLabel(
|
||||
_( "Library names will be created with suffixes such as _symbols, _fp, and _3d." ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_prefixHint->SetLabel( wxString::Format(
|
||||
_( "Will create libraries like %1$s_symbols, %1$s_fp, %1$s_3d, etc." ), prefix ) );
|
||||
}
|
||||
|
||||
m_prefixHint->Wrap( FromDIP( 360 ) );
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef DIALOG_REMOTE_SYMBOL_CONFIG_H
|
||||
#define DIALOG_REMOTE_SYMBOL_CONFIG_H
|
||||
|
||||
#include <dialog_shim.h>
|
||||
#include <eeschema_settings.h>
|
||||
|
||||
class wxTextCtrl;
|
||||
class wxStaticText;
|
||||
class wxRadioButton;
|
||||
class wxButton;
|
||||
|
||||
class EESCHEMA_SETTINGS;
|
||||
|
||||
class DIALOG_REMOTE_SYMBOL_CONFIG : public DIALOG_SHIM
|
||||
{
|
||||
public:
|
||||
explicit DIALOG_REMOTE_SYMBOL_CONFIG( wxWindow* aParent );
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
private:
|
||||
void onBrowseDestination( wxCommandEvent& aEvent );
|
||||
void onResetDefaults( wxCommandEvent& aEvent );
|
||||
void onPrefixChanged( wxCommandEvent& aEvent );
|
||||
|
||||
void applyRemoteSettings( const EESCHEMA_SETTINGS::REMOTE_SYMBOL_CONFIG& aConfig );
|
||||
void updatePrefixHint();
|
||||
|
||||
private:
|
||||
wxTextCtrl* m_destinationCtrl;
|
||||
wxTextCtrl* m_prefixCtrl;
|
||||
wxStaticText* m_prefixHint;
|
||||
wxRadioButton* m_projectRadio;
|
||||
wxRadioButton* m_globalRadio;
|
||||
wxButton* m_resetButton;
|
||||
wxButton* m_browseButton;
|
||||
|
||||
EESCHEMA_SETTINGS* m_settings;
|
||||
};
|
||||
|
||||
|
||||
#endif // DIALOG_REMOTE_SYMBOL_CONFIG_H
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <core/json_serializers.h>
|
||||
#include "panel_sch_data_sources.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <dialogs/dialog_pcm.h>
|
||||
#include <eda_base_frame.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <settings/kicad_settings.h>
|
||||
#include <widgets/ui_common.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/intl.h>
|
||||
#include <wx/listbox.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
|
||||
|
||||
PANEL_SCH_DATA_SOURCES::PANEL_SCH_DATA_SOURCES( wxWindow* aParent, EDA_BASE_FRAME* aFrame ) :
|
||||
RESETTABLE_PANEL( aParent ),
|
||||
m_frame( aFrame ),
|
||||
m_pcm( std::make_shared<PLUGIN_CONTENT_MANAGER>( []( int ) {} ) ),
|
||||
m_description( nullptr ),
|
||||
m_status( nullptr ),
|
||||
m_sourcesList( nullptr ),
|
||||
m_manageButton( nullptr )
|
||||
{
|
||||
wxBoxSizer* topSizer = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_description = new wxStaticText( this, wxID_ANY,
|
||||
_( "Install schematic data sources from the Plugin and Content Manager. Data sources extend KiCad by linking schematic items to external data providers." ) );
|
||||
m_description->Wrap( FromDIP( 480 ) );
|
||||
m_description->SetFont( KIUI::GetInfoFont( this ) );
|
||||
topSizer->Add( m_description, 0, wxBOTTOM | wxEXPAND, FromDIP( 12 ) );
|
||||
|
||||
m_sourcesList = new wxListBox( this, wxID_ANY );
|
||||
m_sourcesList->SetMinSize( FromDIP( wxSize( -1, 160 ) ) );
|
||||
topSizer->Add( m_sourcesList, 1, wxBOTTOM | wxEXPAND, FromDIP( 12 ) );
|
||||
|
||||
m_status = new wxStaticText( this, wxID_ANY, wxEmptyString );
|
||||
m_status->SetFont( KIUI::GetSmallInfoFont( this ).Italic() );
|
||||
topSizer->Add( m_status, 0, wxBOTTOM | wxEXPAND, FromDIP( 12 ) );
|
||||
|
||||
m_manageButton = new wxButton( this, wxID_ANY, _( "Manage Data Sources..." ) );
|
||||
topSizer->Add( m_manageButton, 0, wxALIGN_RIGHT );
|
||||
|
||||
SetSizer( topSizer );
|
||||
|
||||
m_manageButton->Bind( wxEVT_BUTTON, &PANEL_SCH_DATA_SOURCES::OnManageDataSources, this );
|
||||
}
|
||||
|
||||
|
||||
bool PANEL_SCH_DATA_SOURCES::TransferDataToWindow()
|
||||
{
|
||||
if( KICAD_SETTINGS* cfg = GetAppSettings<KICAD_SETTINGS>( "kicad" ) )
|
||||
m_pcm->SetRepositoryList( cfg->m_PcmRepositories );
|
||||
|
||||
populateInstalledSources();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PANEL_SCH_DATA_SOURCES::TransferDataFromWindow()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PANEL_SCH_DATA_SOURCES::ResetPanel()
|
||||
{
|
||||
populateInstalledSources();
|
||||
}
|
||||
|
||||
|
||||
void PANEL_SCH_DATA_SOURCES::populateInstalledSources()
|
||||
{
|
||||
m_sourcesList->Clear();
|
||||
|
||||
std::vector<wxString> entries;
|
||||
|
||||
for( const PCM_INSTALLATION_ENTRY& entry : m_pcm->GetInstalledPackages() )
|
||||
{
|
||||
PCM_PACKAGE_TYPE type = entry.package.category && entry.package.category.value() == PC_FAB
|
||||
? PT_FAB
|
||||
: entry.package.type;
|
||||
|
||||
if( type != PT_DATASOURCE )
|
||||
continue;
|
||||
|
||||
wxString label = entry.package.name;
|
||||
|
||||
if( !entry.current_version.IsEmpty() )
|
||||
label << wxS( " (" ) << entry.current_version << wxS( ")" );
|
||||
|
||||
if( !entry.repository_name.IsEmpty() )
|
||||
label << wxS( " — " ) << entry.repository_name;
|
||||
|
||||
entries.push_back( label );
|
||||
}
|
||||
|
||||
if( entries.empty() )
|
||||
{
|
||||
m_status->SetLabel( _( "No data sources are currently installed." ) );
|
||||
return;
|
||||
}
|
||||
|
||||
std::sort( entries.begin(), entries.end(),
|
||||
[]( const wxString& a, const wxString& b )
|
||||
{
|
||||
return a.CmpNoCase( b ) < 0;
|
||||
} );
|
||||
|
||||
for( const wxString& label : entries )
|
||||
m_sourcesList->Append( label );
|
||||
|
||||
m_status->SetLabel( _( "Installed data sources are listed above." ) );
|
||||
}
|
||||
|
||||
|
||||
void PANEL_SCH_DATA_SOURCES::OnManageDataSources( wxCommandEvent& aEvent )
|
||||
{
|
||||
EDA_BASE_FRAME* parentFrame = m_frame ? m_frame
|
||||
: dynamic_cast<EDA_BASE_FRAME*>( wxGetTopLevelParent( this ) );
|
||||
|
||||
DIALOG_PCM dialog( parentFrame, m_pcm );
|
||||
dialog.SetActivePackageType( PT_DATASOURCE );
|
||||
dialog.ShowModal();
|
||||
|
||||
populateInstalledSources();
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef PANEL_SCH_DATA_SOURCES_H
|
||||
#define PANEL_SCH_DATA_SOURCES_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <pcm.h>
|
||||
#include <widgets/resettable_panel.h>
|
||||
|
||||
class wxButton;
|
||||
class wxListBox;
|
||||
class wxStaticText;
|
||||
class EDA_BASE_FRAME;
|
||||
|
||||
|
||||
class PANEL_SCH_DATA_SOURCES : public RESETTABLE_PANEL
|
||||
{
|
||||
public:
|
||||
PANEL_SCH_DATA_SOURCES( wxWindow* aParent, EDA_BASE_FRAME* aFrame );
|
||||
|
||||
bool TransferDataToWindow() override;
|
||||
bool TransferDataFromWindow() override;
|
||||
|
||||
void ResetPanel() override;
|
||||
|
||||
private:
|
||||
void populateInstalledSources();
|
||||
void OnManageDataSources( wxCommandEvent& aEvent );
|
||||
|
||||
private:
|
||||
EDA_BASE_FRAME* m_frame;
|
||||
std::shared_ptr<PLUGIN_CONTENT_MANAGER> m_pcm;
|
||||
wxStaticText* m_description;
|
||||
wxStaticText* m_status;
|
||||
wxListBox* m_sourcesList;
|
||||
wxButton* m_manageButton;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -23,6 +23,7 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <core/json_serializers.h>
|
||||
#include <pgm_base.h>
|
||||
#include <kiface_base.h>
|
||||
#include <background_jobs_monitor.h>
|
||||
@@ -60,6 +61,7 @@
|
||||
#include <connection_graph.h>
|
||||
#include <panel_template_fieldnames.h>
|
||||
#include <panel_eeschema_color_settings.h>
|
||||
#include <panel_sch_data_sources.h>
|
||||
#include <panel_sym_color_settings.h>
|
||||
#include <panel_eeschema_editing_options.h>
|
||||
#include <panel_eeschema_annotation_options.h>
|
||||
@@ -360,6 +362,19 @@ static struct IFACE : public KIFACE_BASE, public UNITS_PROVIDER
|
||||
case PANEL_SCH_FIELD_NAME_TEMPLATES:
|
||||
return new PANEL_TEMPLATE_FIELDNAMES( aParent, nullptr );
|
||||
|
||||
case PANEL_SCH_DATA_SOURCES:
|
||||
{
|
||||
EDA_BASE_FRAME* frame = aKiway->Player( FRAME_SCH, false );
|
||||
|
||||
if( !frame )
|
||||
frame = aKiway->Player( FRAME_SCH_SYMBOL_EDITOR, false );
|
||||
|
||||
if( !frame )
|
||||
frame = aKiway->Player( FRAME_SCH_VIEWER, false );
|
||||
|
||||
return new class PANEL_SCH_DATA_SOURCES( aParent, frame );
|
||||
}
|
||||
|
||||
case PANEL_SCH_SIMULATOR:
|
||||
return new PANEL_SIMULATOR_PREFERENCES( aParent );
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <widgets/hierarchy_pane.h>
|
||||
#include <widgets/sch_design_block_pane.h>
|
||||
#include <widgets/sch_search_pane.h>
|
||||
#include <widgets/panel_remote_symbol.h>
|
||||
#include <widgets/panel_sch_selection_filter.h>
|
||||
#include <widgets/properties_panel.h>
|
||||
#include <settings/app_settings.h>
|
||||
@@ -368,6 +369,19 @@ void SCH_EDIT_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
|
||||
}
|
||||
|
||||
m_designBlocksPane->SaveSettings();
|
||||
|
||||
wxAuiPaneInfo& remoteSymbolPane = m_auimgr.GetPane( RemoteSymbolPaneName() );
|
||||
cfg->m_AuiPanels.remote_symbol_show = remoteSymbolPane.IsShown();
|
||||
|
||||
if( remoteSymbolPane.IsDocked() )
|
||||
{
|
||||
cfg->m_AuiPanels.remote_symbol_panel_docked_width = m_remoteSymbolPane->GetSize().x;
|
||||
}
|
||||
else
|
||||
{
|
||||
cfg->m_AuiPanels.remote_symbol_panel_float_height = remoteSymbolPane.floating_size.y;
|
||||
cfg->m_AuiPanels.remote_symbol_panel_float_width = remoteSymbolPane.floating_size.x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -149,6 +149,49 @@ const wxAuiPaneInfo& defaultDesignBlocksPaneInfo( wxWindow* aWindow )
|
||||
}
|
||||
|
||||
|
||||
const wxAuiPaneInfo& defaultRemoteSymbolPaneInfo( wxWindow* aWindow )
|
||||
{
|
||||
static wxAuiPaneInfo paneInfo;
|
||||
|
||||
paneInfo.Name( EDA_DRAW_FRAME::RemoteSymbolPaneName() )
|
||||
.Caption( _( "Remote Symbols" ) )
|
||||
.CaptionVisible( true )
|
||||
.PaneBorder( true )
|
||||
.Right().Layer( 3 ).Position( 3 )
|
||||
.TopDockable( false )
|
||||
.BottomDockable( false )
|
||||
.CloseButton( true )
|
||||
.MinSize( aWindow->FromDIP( wxSize( 240, 60 ) ) )
|
||||
.BestSize( aWindow->FromDIP( wxSize( 300, 200 ) ) )
|
||||
.FloatingSize( aWindow->FromDIP( wxSize( 800, 600 ) ) )
|
||||
.FloatingPosition( aWindow->FromDIP( wxPoint( 80, 220 ) ) )
|
||||
.Show( false );
|
||||
|
||||
return paneInfo;
|
||||
}
|
||||
|
||||
|
||||
wxString EESCHEMA_SETTINGS::REMOTE_SYMBOL_CONFIG::DefaultDestinationDir()
|
||||
{
|
||||
return wxS( "${KIPRJMOD}/RemoteLibrary" );
|
||||
}
|
||||
|
||||
|
||||
wxString EESCHEMA_SETTINGS::REMOTE_SYMBOL_CONFIG::DefaultLibraryPrefix()
|
||||
{
|
||||
return wxS( "remote" );
|
||||
}
|
||||
|
||||
|
||||
void EESCHEMA_SETTINGS::REMOTE_SYMBOL_CONFIG::ResetToDefaults()
|
||||
{
|
||||
destination_dir = DefaultDestinationDir();
|
||||
library_prefix = DefaultLibraryPrefix();
|
||||
add_to_global_table = false;
|
||||
user_ids.clear();
|
||||
}
|
||||
|
||||
|
||||
EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() :
|
||||
APP_SETTINGS_BASE( "eeschema", eeschemaSchemaVersion ),
|
||||
m_Appearance(),
|
||||
@@ -246,6 +289,18 @@ EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() :
|
||||
m_params.emplace_back( new PARAM<int>( "aui.design_blocks_panel_float_height",
|
||||
&m_AuiPanels.design_blocks_panel_float_height, -1 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<bool>( "aui.remote_symbol_show",
|
||||
&m_AuiPanels.remote_symbol_show, false ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "aui.remote_symbol_panel_docked_width",
|
||||
&m_AuiPanels.remote_symbol_panel_docked_width, -1 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "aui.remote_symbol_panel_float_width",
|
||||
&m_AuiPanels.remote_symbol_panel_float_width, -1 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "aui.remote_symbol_panel_float_height",
|
||||
&m_AuiPanels.remote_symbol_panel_float_height, -1 ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<bool>( "aui.schematic_hierarchy_float",
|
||||
&m_AuiPanels.schematic_hierarchy_float, false ) );
|
||||
|
||||
@@ -297,6 +352,20 @@ EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() :
|
||||
m_params.emplace_back( new PARAM<bool>( "autoplace_fields.align_to_grid",
|
||||
&m_AutoplaceFields.align_to_grid, true ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<wxString>( "remote_symbols.destination_dir",
|
||||
&m_RemoteSymbol.destination_dir,
|
||||
REMOTE_SYMBOL_CONFIG::DefaultDestinationDir() ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<wxString>( "remote_symbols.library_prefix",
|
||||
&m_RemoteSymbol.library_prefix,
|
||||
REMOTE_SYMBOL_CONFIG::DefaultLibraryPrefix() ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<bool>( "remote_symbols.add_to_global_table",
|
||||
&m_RemoteSymbol.add_to_global_table, false ) );
|
||||
|
||||
m_params.emplace_back( new PARAM_WXSTRING_MAP( "remote_symbols.user_ids",
|
||||
&m_RemoteSymbol.user_ids, {} ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<int>( "drawing.default_bus_thickness",
|
||||
&m_Drawing.default_bus_thickness, DEFAULT_BUS_WIDTH_MILS ) );
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
#include <wx/aui/framemanager.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <settings/app_settings.h>
|
||||
#include <sim/sim_preferences.h>
|
||||
|
||||
@@ -35,6 +37,7 @@ extern const wxAuiPaneInfo& defaultNetNavigatorPaneInfo();
|
||||
extern const wxAuiPaneInfo& defaultPropertiesPaneInfo( wxWindow* aWindow );
|
||||
extern const wxAuiPaneInfo& defaultSchSelectionFilterPaneInfo( wxWindow* aWindow );
|
||||
extern const wxAuiPaneInfo& defaultDesignBlocksPaneInfo( wxWindow* aWindow );
|
||||
extern const wxAuiPaneInfo& defaultRemoteSymbolPaneInfo( wxWindow* aWindow );
|
||||
|
||||
|
||||
|
||||
@@ -104,6 +107,27 @@ public:
|
||||
int design_blocks_panel_docked_width;
|
||||
int design_blocks_panel_float_width;
|
||||
int design_blocks_panel_float_height;
|
||||
bool remote_symbol_show;
|
||||
int remote_symbol_panel_docked_width;
|
||||
int remote_symbol_panel_float_width;
|
||||
int remote_symbol_panel_float_height;
|
||||
};
|
||||
|
||||
struct REMOTE_SYMBOL_CONFIG
|
||||
{
|
||||
REMOTE_SYMBOL_CONFIG()
|
||||
{
|
||||
ResetToDefaults();
|
||||
}
|
||||
|
||||
wxString destination_dir;
|
||||
wxString library_prefix;
|
||||
bool add_to_global_table;
|
||||
std::map<wxString, wxString> user_ids;
|
||||
|
||||
void ResetToDefaults();
|
||||
static wxString DefaultDestinationDir();
|
||||
static wxString DefaultLibraryPrefix();
|
||||
};
|
||||
|
||||
struct AUTOPLACE_FIELDS
|
||||
@@ -321,6 +345,7 @@ private:
|
||||
public:
|
||||
APPEARANCE m_Appearance;
|
||||
AUI_PANELS m_AuiPanels;
|
||||
REMOTE_SYMBOL_CONFIG m_RemoteSymbol;
|
||||
|
||||
DRAWING m_Drawing;
|
||||
INPUT m_Input;
|
||||
@@ -346,4 +371,3 @@ public:
|
||||
|
||||
wxString m_lastSymbolLibDir;
|
||||
};
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include <magic_enum.hpp>
|
||||
#include <memory>
|
||||
|
||||
#include <common.h>
|
||||
#include <dialog_shim.h>
|
||||
@@ -212,7 +213,62 @@ LIB_SYMBOL* SYMBOL_LIBRARY_ADAPTER::LoadSymbol( const wxString& aNickname, const
|
||||
SYMBOL_LIBRARY_ADAPTER::SAVE_T SYMBOL_LIBRARY_ADAPTER::SaveSymbol( const wxString& aNickname,
|
||||
const LIB_SYMBOL* aSymbol, bool aOverwrite )
|
||||
{
|
||||
wxCHECK_MSG( false, SAVE_SKIPPED, "Unimplemented!" );
|
||||
wxCHECK( aSymbol, SAVE_SKIPPED );
|
||||
|
||||
LIBRARY_RESULT<LIB_DATA*> libResult = loadIfNeeded( aNickname );
|
||||
|
||||
if( !libResult.has_value() )
|
||||
{
|
||||
wxLogTrace( traceLibraries, "SaveSymbol: unable to load library %s: %s",
|
||||
aNickname, libResult.error().message );
|
||||
return SAVE_SKIPPED;
|
||||
}
|
||||
|
||||
LIB_DATA* lib = *libResult;
|
||||
|
||||
if( !lib )
|
||||
{
|
||||
wxLogTrace( traceLibraries, "SaveSymbol: library %s not found", aNickname );
|
||||
return SAVE_SKIPPED;
|
||||
}
|
||||
|
||||
SCH_IO* plugin = schplugin( lib );
|
||||
wxCHECK( plugin, SAVE_SKIPPED );
|
||||
|
||||
std::map<std::string, UTF8> options = lib->row->GetOptionsMap();
|
||||
|
||||
if( !aOverwrite )
|
||||
{
|
||||
try
|
||||
{
|
||||
std::unique_ptr<LIB_SYMBOL> existing( plugin->LoadSymbol( getUri( lib->row ),
|
||||
aSymbol->GetName(),
|
||||
&options ) );
|
||||
|
||||
if( existing )
|
||||
return SAVE_SKIPPED;
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
wxLogTrace( traceLibraries,
|
||||
"SaveSymbol: error checking for existing symbol %s:%s: %s",
|
||||
aNickname, aSymbol->GetName(), e.What() );
|
||||
return SAVE_SKIPPED;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
plugin->SaveSymbol( getUri( lib->row ), aSymbol, &options );
|
||||
}
|
||||
catch( const IO_ERROR& e )
|
||||
{
|
||||
wxLogTrace( traceLibraries, "SaveSymbol: error saving %s:%s: %s",
|
||||
aNickname, aSymbol->GetName(), e.What() );
|
||||
return SAVE_SKIPPED;
|
||||
}
|
||||
|
||||
return SAVE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "eeschema_id.h"
|
||||
#include "sch_edit_frame.h"
|
||||
#include <widgets/wx_menubar.h>
|
||||
#include <widgets/panel_remote_symbol.h>
|
||||
#include <advanced_config.h>
|
||||
|
||||
|
||||
@@ -187,6 +188,13 @@ void SCH_EDIT_FRAME::doReCreateMenuBar()
|
||||
showHidePanels->Add( SCH_ACTIONS::showNetNavigator, ACTION_MENU::CHECK );
|
||||
|
||||
showHidePanels->Add( SCH_ACTIONS::showDesignBlockPanel, ACTION_MENU::CHECK, _( "Design Blocks" ) );
|
||||
wxMenuItem* remoteSymbolItem = showHidePanels->Add( SCH_ACTIONS::showRemoteSymbolPanel, ACTION_MENU::CHECK, _( "Remote Symbols" ) );
|
||||
|
||||
if( m_remoteSymbolPane && !m_remoteSymbolPane->HasDataSources() )
|
||||
{
|
||||
remoteSymbolItem->Enable( false );
|
||||
remoteSymbolItem->SetHelp( _( "Install a remote symbol server using the Plugin and Content Manger to enable" ) );
|
||||
}
|
||||
|
||||
viewMenu->Add( showHidePanels );
|
||||
|
||||
@@ -363,4 +371,3 @@ void SCH_EDIT_FRAME::doReCreateMenuBar()
|
||||
delete oldMenuBar;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <dialogs/dialog_book_reporter.h>
|
||||
#include <dialogs/dialog_symbol_fields_table.h>
|
||||
#include <widgets/sch_design_block_pane.h>
|
||||
#include <widgets/panel_remote_symbol.h>
|
||||
#include <wx/srchctrl.h>
|
||||
#include <mail_type.h>
|
||||
#include <wx/clntdata.h>
|
||||
@@ -165,7 +166,8 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
m_netNavigatorFilterValue(),
|
||||
m_netNavigatorMenuNetName(),
|
||||
m_highlightedConnChanged( false ),
|
||||
m_designBlocksPane( nullptr )
|
||||
m_designBlocksPane( nullptr ),
|
||||
m_remoteSymbolPane( nullptr )
|
||||
{
|
||||
m_maximizeByDefault = true;
|
||||
m_schematic = new SCHEMATIC( &Prj() );
|
||||
@@ -226,6 +228,7 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
|
||||
m_searchPane = new SCH_SEARCH_PANE( this );
|
||||
m_propertiesPanel = new SCH_PROPERTIES_PANEL( this, this );
|
||||
m_remoteSymbolPane = new PANEL_REMOTE_SYMBOL( this );
|
||||
|
||||
m_propertiesPanel->SetSplitterProportion( eeconfig()->m_AuiPanels.properties_splitter );
|
||||
|
||||
@@ -265,6 +268,7 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
m_auimgr.AddPane( m_selectionFilterPanel, defaultSchSelectionFilterPaneInfo( this ) );
|
||||
|
||||
m_auimgr.AddPane( m_designBlocksPane, defaultDesignBlocksPaneInfo( this ) );
|
||||
m_auimgr.AddPane( m_remoteSymbolPane, defaultRemoteSymbolPaneInfo( this ) );
|
||||
|
||||
m_auimgr.AddPane( createHighlightedNetNavigator(), defaultNetNavigatorPaneInfo() );
|
||||
|
||||
@@ -298,11 +302,18 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
wxAuiPaneInfo& propertiesPane = m_auimgr.GetPane( PropertiesPaneName() );
|
||||
wxAuiPaneInfo& selectionFilterPane = m_auimgr.GetPane( wxS( "SelectionFilter" ) );
|
||||
wxAuiPaneInfo& designBlocksPane = m_auimgr.GetPane( DesignBlocksPaneName() );
|
||||
wxAuiPaneInfo& remoteSymbolPane = m_auimgr.GetPane( RemoteSymbolPaneName() );
|
||||
|
||||
hierarchy_pane.Show( aui_cfg.show_schematic_hierarchy );
|
||||
netNavigatorPane.Show( aui_cfg.show_net_nav_panel );
|
||||
propertiesPane.Show( aui_cfg.show_properties );
|
||||
designBlocksPane.Show( aui_cfg.design_blocks_show );
|
||||
|
||||
if( m_remoteSymbolPane && !m_remoteSymbolPane->HasDataSources() )
|
||||
remoteSymbolPane.Show( false );
|
||||
else
|
||||
remoteSymbolPane.Show( aui_cfg.remote_symbol_show );
|
||||
|
||||
updateSelectionFilterVisbility();
|
||||
|
||||
// The selection filter doesn't need to grow in the vertical direction when docked
|
||||
@@ -352,6 +363,9 @@ SCH_EDIT_FRAME::SCH_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
if( aui_cfg.design_blocks_show )
|
||||
SetAuiPaneSize( m_auimgr, designBlocksPane, aui_cfg.design_blocks_panel_docked_width, -1 );
|
||||
|
||||
if( aui_cfg.remote_symbol_show )
|
||||
SetAuiPaneSize( m_auimgr, remoteSymbolPane, aui_cfg.remote_symbol_panel_docked_width, -1 );
|
||||
|
||||
if( aui_cfg.hierarchy_panel_docked_width > 0 )
|
||||
{
|
||||
// If the net navigator is not show, let the hierarchy navigator take all of the vertical
|
||||
@@ -728,6 +742,12 @@ void SCH_EDIT_FRAME::setupUIConditions()
|
||||
return m_auimgr.GetPane( DesignBlocksPaneName() ).IsShown();
|
||||
};
|
||||
|
||||
auto remoteSymbolCond =
|
||||
[ this ] (const SELECTION& aSel )
|
||||
{
|
||||
return m_auimgr.GetPane( RemoteSymbolPaneName() ).IsShown();
|
||||
};
|
||||
|
||||
auto undoCond =
|
||||
[ this ] (const SELECTION& aSel )
|
||||
{
|
||||
@@ -763,6 +783,7 @@ void SCH_EDIT_FRAME::setupUIConditions()
|
||||
mgr->SetConditions( SCH_ACTIONS::showNetNavigator, CHECK( netNavigatorCond ) );
|
||||
mgr->SetConditions( ACTIONS::showProperties, CHECK( propertiesCond ) );
|
||||
mgr->SetConditions( SCH_ACTIONS::showDesignBlockPanel, CHECK( designBlockCond ) );
|
||||
mgr->SetConditions( SCH_ACTIONS::showRemoteSymbolPanel, CHECK( remoteSymbolCond ) );
|
||||
mgr->SetConditions( ACTIONS::toggleGrid, CHECK( cond.GridVisible() ) );
|
||||
mgr->SetConditions( ACTIONS::toggleGridOverrides, CHECK( cond.GridOverrides() ) );
|
||||
|
||||
@@ -2001,6 +2022,7 @@ void SCH_EDIT_FRAME::ShowChangedLanguage()
|
||||
m_auimgr.GetPane( m_selectionFilterPanel ).Caption( _( "Selection Filter" ) );
|
||||
m_auimgr.GetPane( m_propertiesPanel ).Caption( _( "Properties" ) );
|
||||
m_auimgr.GetPane( m_designBlocksPane ).Caption( _( "Design Blocks" ) );
|
||||
m_auimgr.GetPane( RemoteSymbolPaneName() ).Caption( _( "Remote Symbols" ) );
|
||||
m_auimgr.Update();
|
||||
m_hierarchy->UpdateHierarchyTree();
|
||||
|
||||
@@ -2901,6 +2923,47 @@ void SCH_EDIT_FRAME::ToggleLibraryTree()
|
||||
}
|
||||
|
||||
|
||||
void SCH_EDIT_FRAME::ToggleRemoteSymbolPanel()
|
||||
{
|
||||
EESCHEMA_SETTINGS* cfg = eeconfig();
|
||||
|
||||
wxCHECK( cfg, /* void */ );
|
||||
|
||||
wxAuiPaneInfo& remotePane = m_auimgr.GetPane( RemoteSymbolPaneName() );
|
||||
|
||||
remotePane.Show( !remotePane.IsShown() );
|
||||
|
||||
if( remotePane.IsShown() )
|
||||
{
|
||||
if( remotePane.IsFloating() )
|
||||
{
|
||||
remotePane.FloatingSize( cfg->m_AuiPanels.remote_symbol_panel_float_width,
|
||||
cfg->m_AuiPanels.remote_symbol_panel_float_height );
|
||||
m_auimgr.Update();
|
||||
}
|
||||
else if( cfg->m_AuiPanels.remote_symbol_panel_docked_width > 0 )
|
||||
{
|
||||
SetAuiPaneSize( m_auimgr, remotePane,
|
||||
cfg->m_AuiPanels.remote_symbol_panel_docked_width, -1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( remotePane.IsFloating() )
|
||||
{
|
||||
cfg->m_AuiPanels.remote_symbol_panel_float_width = remotePane.floating_size.x;
|
||||
cfg->m_AuiPanels.remote_symbol_panel_float_height = remotePane.floating_size.y;
|
||||
}
|
||||
else if( m_remoteSymbolPane )
|
||||
{
|
||||
cfg->m_AuiPanels.remote_symbol_panel_docked_width = m_remoteSymbolPane->GetSize().x;
|
||||
}
|
||||
|
||||
m_auimgr.Update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SCH_EDIT_FRAME::SetSchematic( SCHEMATIC* aSchematic )
|
||||
{
|
||||
wxCHECK( aSchematic, /* void */ );
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <wx/string.h>
|
||||
#include <wx/treectrl.h>
|
||||
#include <wx/utils.h>
|
||||
#include <wx/filename.h>
|
||||
|
||||
#include <core/typeinfo.h>
|
||||
#include <eda_base_frame.h>
|
||||
@@ -57,6 +58,7 @@ class SCH_JUNCTION;
|
||||
class SCHEMATIC;
|
||||
class SCH_COMMIT;
|
||||
class SCH_DESIGN_BLOCK_PANE;
|
||||
class PANEL_REMOTE_SYMBOL;
|
||||
class DIALOG_BOOK_REPORTER;
|
||||
class DIALOG_ERC;
|
||||
class DIALOG_SYMBOL_FIELDS_TABLE;
|
||||
@@ -816,6 +818,9 @@ public:
|
||||
|
||||
void ToggleLibraryTree() override;
|
||||
|
||||
void ToggleRemoteSymbolPanel();
|
||||
|
||||
|
||||
DIALOG_BOOK_REPORTER* GetSymbolDiffDialog();
|
||||
|
||||
DIALOG_ERC* GetErcDialog();
|
||||
@@ -1061,6 +1066,7 @@ private:
|
||||
|
||||
std::vector<LIB_ID> m_designBlockHistoryList;
|
||||
SCH_DESIGN_BLOCK_PANE* m_designBlocksPane;
|
||||
PANEL_REMOTE_SYMBOL* m_remoteSymbolPane;
|
||||
|
||||
wxChoice* m_currentVariantCtrl;
|
||||
|
||||
|
||||
@@ -124,6 +124,13 @@ TOOL_ACTION SCH_ACTIONS::showDesignBlockPanel( TOOL_ACTION_ARGS()
|
||||
.Tooltip( _( "Show/hide design blocks library" ) )
|
||||
.Icon( BITMAPS::search_tree ) );
|
||||
|
||||
TOOL_ACTION SCH_ACTIONS::showRemoteSymbolPanel( TOOL_ACTION_ARGS()
|
||||
.Name( "eeschema.RemoteSymbols.showPanel" )
|
||||
.Scope( AS_GLOBAL )
|
||||
.FriendlyName( _( "Remote Symbols" ) )
|
||||
.Tooltip( _( "Show/hide the remote symbol panel" ) )
|
||||
.Icon( BITMAPS::library_browser ) );
|
||||
|
||||
TOOL_ACTION SCH_ACTIONS::saveSheetAsDesignBlock( TOOL_ACTION_ARGS()
|
||||
.Name( "eeschema.SchDesignBlockControl.saveSheetAsDesignBlock" )
|
||||
.Scope( AS_GLOBAL )
|
||||
|
||||
@@ -202,6 +202,7 @@ public:
|
||||
|
||||
// Design Block management
|
||||
static TOOL_ACTION showDesignBlockPanel;
|
||||
static TOOL_ACTION showRemoteSymbolPanel;
|
||||
static TOOL_ACTION saveSheetAsDesignBlock;
|
||||
static TOOL_ACTION saveSelectionAsDesignBlock;
|
||||
static TOOL_ACTION saveSheetToDesignBlock;
|
||||
|
||||
@@ -2673,6 +2673,13 @@ int SCH_EDITOR_CONTROL::ToggleLibraryTree( const TOOL_EVENT& aEvent )
|
||||
}
|
||||
|
||||
|
||||
int SCH_EDITOR_CONTROL::ToggleRemoteSymbolPanel( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
getEditFrame<SCH_EDIT_FRAME>()->ToggleRemoteSymbolPanel();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int SCH_EDITOR_CONTROL::ToggleHiddenPins( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
|
||||
@@ -3191,6 +3198,7 @@ void SCH_EDITOR_CONTROL::setTransitions()
|
||||
Go( &SCH_EDITOR_CONTROL::ToggleProperties, ACTIONS::showProperties.MakeEvent() );
|
||||
Go( &SCH_EDITOR_CONTROL::ToggleLibraryTree, SCH_ACTIONS::showDesignBlockPanel.MakeEvent() );
|
||||
Go( &SCH_EDITOR_CONTROL::ToggleLibraryTree, SCH_ACTIONS::showDesignBlockPanel.MakeEvent() );
|
||||
Go( &SCH_EDITOR_CONTROL::ToggleRemoteSymbolPanel, SCH_ACTIONS::showRemoteSymbolPanel.MakeEvent() );
|
||||
|
||||
Go( &SCH_EDITOR_CONTROL::ToggleHiddenPins, SCH_ACTIONS::toggleHiddenPins.MakeEvent() );
|
||||
Go( &SCH_EDITOR_CONTROL::ToggleHiddenFields, SCH_ACTIONS::toggleHiddenFields.MakeEvent() );
|
||||
|
||||
@@ -133,6 +133,7 @@ public:
|
||||
int ShowNetNavigator( const TOOL_EVENT& aEvent );
|
||||
int ToggleProperties( const TOOL_EVENT& aEvent );
|
||||
int ToggleLibraryTree( const TOOL_EVENT& aEvent );
|
||||
int ToggleRemoteSymbolPanel( const TOOL_EVENT& aEvent );
|
||||
|
||||
int ToggleHiddenPins( const TOOL_EVENT& aEvent );
|
||||
int ToggleHiddenFields( const TOOL_EVENT& aEvent );
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef PANEL_REMOTE_SYMBOL_H
|
||||
#define PANEL_REMOTE_SYMBOL_H
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <pcm.h>
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
class BITMAP_BUTTON;
|
||||
class LIB_SYMBOL;
|
||||
class SCH_EDIT_FRAME;
|
||||
class WEBVIEW_PANEL;
|
||||
class wxChoice;
|
||||
class wxCommandEvent;
|
||||
class wxWebViewEvent;
|
||||
class REMOTE_LOGIN_SERVER;
|
||||
|
||||
#define REMOTE_SYMBOL_SESSION_VERSION 1
|
||||
|
||||
class PANEL_REMOTE_SYMBOL : public wxPanel
|
||||
{
|
||||
public:
|
||||
explicit PANEL_REMOTE_SYMBOL( SCH_EDIT_FRAME* aParent );
|
||||
|
||||
void RefreshDataSources();
|
||||
bool HasDataSources() const;
|
||||
|
||||
private:
|
||||
void onDataSourceChanged( wxCommandEvent& aEvent );
|
||||
void onConfigure( wxCommandEvent& aEvent );
|
||||
void onRefresh( wxCommandEvent& aEvent );
|
||||
void onWebViewLoaded( wxWebViewEvent& aEvent );
|
||||
void onRemoteLoginResult( wxCommandEvent& aEvent );
|
||||
|
||||
bool loadDataSource( size_t aIndex );
|
||||
bool loadDataSource( const PCM_INSTALLATION_ENTRY& aEntry );
|
||||
std::optional<wxFileName> findDataSourceJson( const PCM_INSTALLATION_ENTRY& aEntry ) const;
|
||||
void showMessage( const wxString& aMessage );
|
||||
std::optional<wxString> extractUrlFromJson( const wxString& aJsonContent ) const;
|
||||
void onKicadMessage( const wxString& aMessage );
|
||||
void handleRpcMessage( const nlohmann::json& aMessage );
|
||||
void beginSessionHandshake();
|
||||
void handleRemoteLogin( const nlohmann::json& aParams, int aMessageId );
|
||||
void stopLoginServer();
|
||||
void storeUserIdForActiveSource( const wxString& aUserId );
|
||||
void loadStoredUserIdForActiveSource();
|
||||
wxString currentDataSourceKey() const;
|
||||
|
||||
void sendRpcMessage( const wxString& aCommand,
|
||||
nlohmann::json aParameters = nlohmann::json::object(),
|
||||
std::optional<int> aResponseTo = std::nullopt,
|
||||
const wxString& aStatus = wxS( "OK" ),
|
||||
const std::string& aData = std::string(),
|
||||
const wxString& aErrorCode = wxEmptyString,
|
||||
const wxString& aErrorMessage = wxEmptyString );
|
||||
|
||||
void respondWithError( const wxString& aCommand, int aResponseTo,
|
||||
const wxString& aErrorCode, const wxString& aErrorMessage );
|
||||
|
||||
bool ensureDestinationRoot( wxFileName& aOutDir, wxString& aError ) const;
|
||||
bool ensureSymbolLibraryEntry( const wxFileName& aLibraryFile, const wxString& aNickname,
|
||||
bool aGlobalTable, wxString& aError ) const;
|
||||
bool ensureFootprintLibraryEntry( const wxFileName& aLibraryDir, const wxString& aNickname,
|
||||
bool aGlobalTable, wxString& aError ) const;
|
||||
wxString sanitizedPrefix() const;
|
||||
|
||||
bool receiveFootprint( const nlohmann::json& aParams, const std::vector<uint8_t>& aPayload,
|
||||
wxString& aError );
|
||||
bool receiveSymbol( const nlohmann::json& aParams, const std::vector<uint8_t>& aPayload,
|
||||
wxString& aError );
|
||||
bool receive3DModel( const nlohmann::json& aParams, const std::vector<uint8_t>& aPayload,
|
||||
wxString& aError );
|
||||
bool receiveSPICEModel( const nlohmann::json& aParams, const std::vector<uint8_t>& aPayload,
|
||||
wxString& aError );
|
||||
bool receiveComponent( const nlohmann::json& aParams, const std::vector<uint8_t>& aPayload,
|
||||
wxString& aError, nlohmann::json* aResponseParams = nullptr );
|
||||
bool placeDownloadedSymbol( const wxString& aNickname, const wxString& aLibItemName,
|
||||
wxString& aError );
|
||||
|
||||
wxString sanitizeFileComponent( const wxString& aComponent, const wxString& aDefault ) const;
|
||||
wxString sanitizeForScript( const std::string& aJson ) const;
|
||||
|
||||
wxString jsonString( const nlohmann::json& aObject, const char* aKey ) const;
|
||||
wxString normalizeDataSourceUrl( const wxString& aUrl ) const;
|
||||
|
||||
bool decodeBase64Payload( const std::string& aMessage,
|
||||
std::vector<uint8_t>& aOutPayload,
|
||||
wxString& aError ) const;
|
||||
|
||||
bool decompressIfNeeded( const std::string& aCompression,
|
||||
const std::vector<uint8_t>& aInput,
|
||||
std::vector<uint8_t>& aOutput,
|
||||
wxString& aError ) const;
|
||||
|
||||
bool writeBinaryFile( const wxFileName& aFile,
|
||||
const std::vector<uint8_t>& aData,
|
||||
wxString& aError ) const;
|
||||
|
||||
std::unique_ptr<LIB_SYMBOL> loadSymbolFromPayload( const std::vector<uint8_t>& aPayload,
|
||||
const wxString& aLibItemName,
|
||||
wxString& aError ) const;
|
||||
|
||||
private:
|
||||
SCH_EDIT_FRAME* m_frame;
|
||||
wxChoice* m_dataSourceChoice;
|
||||
BITMAP_BUTTON* m_configButton;
|
||||
BITMAP_BUTTON* m_refreshButton;
|
||||
WEBVIEW_PANEL* m_webView;
|
||||
std::shared_ptr<PLUGIN_CONTENT_MANAGER> m_pcm;
|
||||
std::vector<PCM_INSTALLATION_ENTRY> m_dataSources;
|
||||
KIID m_sessionId;
|
||||
int m_messageIdCounter;
|
||||
bool m_pendingHandshake;
|
||||
std::unique_ptr<REMOTE_LOGIN_SERVER> m_loginServer;
|
||||
wxString m_activeDataSourceUrl;
|
||||
wxString m_activeUserId;
|
||||
};
|
||||
|
||||
#endif // PANEL_REMOTE_SYMBOL_H
|
||||
@@ -438,6 +438,8 @@ public:
|
||||
|
||||
static const wxString DesignBlocksPaneName() { return wxS( "DesignBlocks" ); }
|
||||
|
||||
static const wxString RemoteSymbolPaneName() { return wxS( "RemoteSymbol" ); }
|
||||
|
||||
static const wxString AppearancePanelName() { return wxS( "LayersManager" ); }
|
||||
|
||||
/**
|
||||
|
||||
@@ -82,6 +82,7 @@ enum FRAME_T
|
||||
PANEL_SCH_TOOLBARS,
|
||||
PANEL_SCH_FIELD_NAME_TEMPLATES,
|
||||
PANEL_SCH_SIMULATOR,
|
||||
PANEL_SCH_DATA_SOURCES,
|
||||
|
||||
PANEL_FP_DISPLAY_OPTIONS,
|
||||
PANEL_FP_GRIDS,
|
||||
|
||||
@@ -148,6 +148,9 @@ public:
|
||||
/// Returns a list of all library nicknames and their status (even if they failed to load)
|
||||
std::vector<std::pair<wxString, LIB_STATUS>> GetLibraryStatuses() const;
|
||||
|
||||
void ReloadLibraryEntry( const wxString& aNickname,
|
||||
LIBRARY_TABLE_SCOPE aScope = LIBRARY_TABLE_SCOPE::BOTH );
|
||||
|
||||
/// Return true if the given nickname exists and is not a read-only library
|
||||
virtual bool IsWritable( const wxString& aNickname ) const;
|
||||
|
||||
@@ -174,6 +177,11 @@ protected:
|
||||
/// Fetches a loaded library, triggering a load of that library if it isn't loaded yet
|
||||
LIBRARY_RESULT<LIB_DATA*> loadIfNeeded( const wxString& aNickname );
|
||||
|
||||
LIBRARY_RESULT<LIB_DATA*> loadFromScope( const wxString& aNickname,
|
||||
LIBRARY_TABLE_SCOPE aScope,
|
||||
std::map<wxString, LIB_DATA>& aTarget,
|
||||
std::mutex& aMutex );
|
||||
|
||||
/// Aborts any async load in progress; blocks until fully done aborting
|
||||
void abortLoad();
|
||||
|
||||
@@ -272,6 +280,9 @@ public:
|
||||
LIBRARY_TABLE_SCOPE aScope =
|
||||
LIBRARY_TABLE_SCOPE::BOTH ) const;
|
||||
|
||||
void ReloadLibraryEntry( LIBRARY_TABLE_TYPE aType, const wxString& aNickname,
|
||||
LIBRARY_TABLE_SCOPE aScope = LIBRARY_TABLE_SCOPE::BOTH );
|
||||
|
||||
void LoadProjectTables( const wxString& aProjectPath );
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright The KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 3 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/gpl-3.0.html
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <wx/event.h>
|
||||
#include <wx/socket.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/timer.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
wxDECLARE_EVENT( EVT_REMOTE_SYMBOL_LOGIN_RESULT, wxCommandEvent );
|
||||
|
||||
class REMOTE_LOGIN_SERVER : public wxEvtHandler
|
||||
{
|
||||
public:
|
||||
REMOTE_LOGIN_SERVER( wxEvtHandler* aOwner, const wxString& aRedirectUrl );
|
||||
~REMOTE_LOGIN_SERVER() override;
|
||||
|
||||
bool Start();
|
||||
unsigned short GetPort() const { return m_port; }
|
||||
|
||||
private:
|
||||
void OnSocketEvent( wxSocketEvent& aEvent );
|
||||
void OnTimeout( wxTimerEvent& aEvent );
|
||||
void HandleClient( wxSocketBase* aClient );
|
||||
wxString ExtractUserId( const wxString& aRequestLine ) const;
|
||||
void SendHttpResponse( wxSocketBase* aClient );
|
||||
void Finish( bool aSuccess, const wxString& aUserId );
|
||||
void Shutdown();
|
||||
|
||||
wxEvtHandler* m_owner;
|
||||
wxString m_redirectUrl;
|
||||
std::unique_ptr<wxSocketServer> m_server;
|
||||
wxTimer m_timeout;
|
||||
unsigned short m_port;
|
||||
bool m_done;
|
||||
};
|
||||
@@ -25,13 +25,17 @@
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
||||
class TOOL_MANAGER;
|
||||
class TOOL_BASE;
|
||||
|
||||
class WEBVIEW_PANEL : public wxPanel
|
||||
{
|
||||
public:
|
||||
using MESSAGE_HANDLER = std::function<void( const wxString& )>;
|
||||
|
||||
explicit WEBVIEW_PANEL( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize, const int style = 0 );
|
||||
const wxSize& size = wxDefaultSize, const int style = 0,
|
||||
TOOL_MANAGER* aToolManager = nullptr, TOOL_BASE* aTool = nullptr );
|
||||
~WEBVIEW_PANEL() override;
|
||||
|
||||
wxWebView* GetWebView() const { return m_browser; }
|
||||
@@ -42,6 +46,16 @@ public:
|
||||
bool AddMessageHandler( const wxString& name, MESSAGE_HANDLER handler );
|
||||
void ClearMessageHandlers();
|
||||
|
||||
void SetHandleExternalLinks( bool aHandle ) { m_handleExternalLinks = aHandle; }
|
||||
bool GetHandleExternalLinks() const { return m_handleExternalLinks; }
|
||||
|
||||
void RunScriptAsync( const wxString& aScript, void* aClientData = nullptr ) const
|
||||
{
|
||||
m_browser->RunScriptAsync( aScript, aClientData );
|
||||
}
|
||||
|
||||
bool HasLoadError() const { return m_loadError; }
|
||||
|
||||
protected:
|
||||
void OnNavigationRequest( wxWebViewEvent& evt );
|
||||
void OnWebViewLoaded( wxWebViewEvent& evt );
|
||||
@@ -51,9 +65,14 @@ protected:
|
||||
void OnError( wxWebViewEvent& evt );
|
||||
|
||||
private:
|
||||
|
||||
bool m_initialized;
|
||||
bool m_handleExternalLinks;
|
||||
bool m_loadError;
|
||||
wxWebView* m_browser;
|
||||
std::map<wxString, MESSAGE_HANDLER> m_msgHandlers;
|
||||
TOOL_MANAGER* m_toolManager;
|
||||
TOOL_BASE* m_tool;
|
||||
};
|
||||
|
||||
#endif // WEBVIEW_PANEL_H
|
||||
|
||||
@@ -51,6 +51,7 @@ static std::vector<std::pair<PCM_PACKAGE_TYPE, wxString>> PACKAGE_TYPE_LIST = {
|
||||
{ PT_PLUGIN, _( "Plugins (%d)" ) },
|
||||
{ PT_FAB, _( "Fabrication plugins (%d)" ) },
|
||||
{ PT_LIBRARY, _( "Libraries (%d)" ) },
|
||||
{ PT_DATASOURCE, _( "Data sources (%d)" ) },
|
||||
{ PT_COLORTHEME, _( "Color themes (%d)" ) },
|
||||
};
|
||||
|
||||
@@ -201,6 +202,19 @@ DIALOG_PCM::~DIALOG_PCM()
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM::SetActivePackageType( PCM_PACKAGE_TYPE aType )
|
||||
{
|
||||
for( size_t i = 0; i < PACKAGE_TYPE_LIST.size(); ++i )
|
||||
{
|
||||
if( PACKAGE_TYPE_LIST[i].first == aType )
|
||||
{
|
||||
m_contentNotebook->SetSelection( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DIALOG_PCM::OnUpdateEventButtons( wxUpdateUIEvent& event )
|
||||
{
|
||||
event.Enable( !m_pendingActions.empty() );
|
||||
|
||||
@@ -83,6 +83,8 @@ public:
|
||||
return m_changed_package_types;
|
||||
};
|
||||
|
||||
void SetActivePackageType( PCM_PACKAGE_TYPE aType );
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Gets package data from PCM and displays it on repository tab
|
||||
|
||||
@@ -44,6 +44,7 @@ enum PCM_PACKAGE_TYPE
|
||||
PT_PLUGIN,
|
||||
PT_FAB,
|
||||
PT_LIBRARY,
|
||||
PT_DATASOURCE,
|
||||
PT_COLORTHEME,
|
||||
};
|
||||
|
||||
@@ -172,6 +173,7 @@ NLOHMANN_JSON_SERIALIZE_ENUM( PCM_PACKAGE_TYPE, {
|
||||
{ PT_PLUGIN, "plugin" },
|
||||
{ PT_FAB, "fab" },
|
||||
{ PT_LIBRARY, "library" },
|
||||
{ PT_DATASOURCE, "datasource" },
|
||||
{ PT_COLORTHEME, "colortheme" },
|
||||
} )
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"enum": [
|
||||
"plugin",
|
||||
"library",
|
||||
"datasource",
|
||||
"fab",
|
||||
"colortheme"
|
||||
],
|
||||
|
||||
@@ -48,6 +48,10 @@
|
||||
"design_blocks_panel_float_height": -1,
|
||||
"design_blocks_panel_float_width": -1,
|
||||
"design_blocks_show": false,
|
||||
"remote_symbol_panel_docked_width": -1,
|
||||
"remote_symbol_panel_float_height": -1,
|
||||
"remote_symbol_panel_float_width": -1,
|
||||
"remote_symbol_show": false,
|
||||
"float_net_nav_panel": false,
|
||||
"hierarchy_panel_docked_height": -1,
|
||||
"hierarchy_panel_docked_width": -1,
|
||||
|
||||
@@ -0,0 +1,377 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://go.kicad.org/schemas/kicad-rpc-v1-message-combined.json",
|
||||
"title": "KiCad Remote Content Protocol Message (v1, combined)",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
|
||||
"required": [
|
||||
"version",
|
||||
"session_id",
|
||||
"message_id",
|
||||
"command"
|
||||
],
|
||||
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "Protocol major version. For this schema: 1."
|
||||
},
|
||||
|
||||
"session_id": {
|
||||
"type": "string",
|
||||
"description": "Session UUID (UUID-4).",
|
||||
"pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
|
||||
},
|
||||
|
||||
"message_id": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "Monotonically increasing per-session message ID, starting at 1."
|
||||
},
|
||||
|
||||
"response_to": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "If present, refers to the message_id of the message being responded to."
|
||||
},
|
||||
|
||||
"command": {
|
||||
"type": "string",
|
||||
"description": "Command name for this message.",
|
||||
"enum": [
|
||||
"NEW_SESSION",
|
||||
"GET_KICAD_VERSION",
|
||||
"LIST_SUPPORTED_VERSIONS",
|
||||
"CAPABILITIES",
|
||||
"PING",
|
||||
"PONG",
|
||||
"LOGOUT",
|
||||
"DL_FOOTPRINT",
|
||||
"DL_SYMBOL",
|
||||
"DL_SPICE",
|
||||
"DL_3DMODEL"
|
||||
]
|
||||
},
|
||||
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "Status of the message, especially for responses.",
|
||||
"enum": ["OK", "ERROR", "PENDING"]
|
||||
},
|
||||
|
||||
"error_code": {
|
||||
"type": "string",
|
||||
"description": "Machine-readable error code when status == ERROR.",
|
||||
"enum": [
|
||||
"UNKNOWN_COMMAND",
|
||||
"UNSUPPORTED_VERSION",
|
||||
"INVALID_PARAMETERS",
|
||||
"INVALID_PAYLOAD",
|
||||
"INTERNAL_ERROR",
|
||||
"TOO_LARGE",
|
||||
"UNAUTHORIZED_ORIGIN",
|
||||
"NOT_FOUND",
|
||||
"CONFLICT"
|
||||
]
|
||||
},
|
||||
|
||||
"error_message": {
|
||||
"type": "string",
|
||||
"description": "Human-readable error description when status == ERROR."
|
||||
},
|
||||
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"description": "Command-specific parameters. Keys are strings; values are arbitrary JSON.",
|
||||
"additionalProperties": true
|
||||
},
|
||||
|
||||
"data": {
|
||||
"type": "string",
|
||||
"description": "Optional payload data. Typically base64-encoded, possibly compressed.",
|
||||
"contentEncoding": "base64"
|
||||
}
|
||||
},
|
||||
|
||||
"allOf": [
|
||||
{
|
||||
"if": {
|
||||
"properties": {
|
||||
"status": { "const": "ERROR" }
|
||||
},
|
||||
"required": ["status"]
|
||||
},
|
||||
"then": {
|
||||
"required": ["error_code"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"title": "NEW_SESSION message",
|
||||
"properties": {
|
||||
"command": { "const": "NEW_SESSION" },
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"client_name": { "type": "string" },
|
||||
"client_version": { "type": "string" },
|
||||
"supported_versions": {
|
||||
"type": "array",
|
||||
"items": { "type": "integer", "minimum": 1 }
|
||||
},
|
||||
"server_name": { "type": "string" },
|
||||
"server_version": { "type": "string" },
|
||||
"reason": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"title": "GET_KICAD_VERSION message",
|
||||
"properties": {
|
||||
"command": { "const": "GET_KICAD_VERSION" },
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"kicad_version": { "type": "string" }
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"title": "LIST_SUPPORTED_VERSIONS message",
|
||||
"properties": {
|
||||
"command": { "const": "LIST_SUPPORTED_VERSIONS" },
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"supported_versions": {
|
||||
"type": "array",
|
||||
"items": { "type": "integer", "minimum": 1 }
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"title": "CAPABILITIES message",
|
||||
"properties": {
|
||||
"command": { "const": "CAPABILITIES" },
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"commands": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"max_message_size": {
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
},
|
||||
"compression": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": ["NONE", "ZSTD"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"title": "PING message",
|
||||
"properties": {
|
||||
"command": { "const": "PING" },
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nonce": {
|
||||
"type": ["string", "number"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"title": "PONG message",
|
||||
"properties": {
|
||||
"command": { "const": "PONG" },
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nonce": {
|
||||
"type": ["string", "number"]
|
||||
},
|
||||
"latency_ms": {
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"title": "LOGOUT message",
|
||||
"properties": {
|
||||
"command": { "const": "LOGOUT" },
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"title": "DL_FOOTPRINT message",
|
||||
"properties": {
|
||||
"command": { "const": "DL_FOOTPRINT" },
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"required": ["mode", "compression", "content_type"],
|
||||
"properties": {
|
||||
"mode": {
|
||||
"type": "string",
|
||||
"enum": ["SAVE", "PLACE"]
|
||||
},
|
||||
"compression": {
|
||||
"type": "string",
|
||||
"enum": ["NONE", "ZSTD"]
|
||||
},
|
||||
"content_type": {
|
||||
"type": "string",
|
||||
"enum": ["KICAD_FOOTPRINT_V1"]
|
||||
},
|
||||
"library": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"required": ["command", "parameters", "data"]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"title": "DL_SYMBOL message",
|
||||
"properties": {
|
||||
"command": { "const": "DL_SYMBOL" },
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"required": ["mode", "compression", "content_type"],
|
||||
"properties": {
|
||||
"mode": {
|
||||
"type": "string",
|
||||
"enum": ["SAVE", "PLACE"]
|
||||
},
|
||||
"compression": {
|
||||
"type": "string",
|
||||
"enum": ["NONE", "ZSTD"]
|
||||
},
|
||||
"content_type": {
|
||||
"type": "string",
|
||||
"enum": ["KICAD_SYMBOL_V1"]
|
||||
},
|
||||
"library": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"required": ["command", "parameters", "data"]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"title": "DL_SPICE message",
|
||||
"properties": {
|
||||
"command": { "const": "DL_SPICE" },
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"required": ["mode", "compression", "content_type"],
|
||||
"properties": {
|
||||
"mode": {
|
||||
"type": "string",
|
||||
"enum": ["SAVE", "PLACE"]
|
||||
},
|
||||
"compression": {
|
||||
"type": "string",
|
||||
"enum": ["NONE", "ZSTD"]
|
||||
},
|
||||
"content_type": {
|
||||
"type": "string",
|
||||
"enum": ["KICAD_SPICE_MODEL_V1"]
|
||||
},
|
||||
"library": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"required": ["command", "parameters", "data"]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"title": "DL_3DMODEL message",
|
||||
"properties": {
|
||||
"command": { "const": "DL_3DMODEL" },
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"required": ["mode", "compression", "content_type"],
|
||||
"properties": {
|
||||
"mode": {
|
||||
"type": "string",
|
||||
"enum": ["SAVE", "PLACE"]
|
||||
},
|
||||
"compression": {
|
||||
"type": "string",
|
||||
"enum": ["NONE", "ZSTD"]
|
||||
},
|
||||
"content_type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"KICAD_3D_MODEL_STEP",
|
||||
"KICAD_3D_MODEL_WRL"
|
||||
]
|
||||
},
|
||||
"library": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"required": ["command", "parameters", "data"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,203 @@
|
||||
(footprint "R_0603_1608Metric"
|
||||
(version 20240108)
|
||||
(generator "pcbnew")
|
||||
(generator_version "8.0")
|
||||
(layer "F.Cu")
|
||||
(descr "Resistor SMD 0603 (1608 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: IPC-SM-782 page 72, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf), generated with kicad-footprint-generator")
|
||||
(tags "resistor")
|
||||
(property "Reference" "REF**"
|
||||
(at 0 -1.43 0)
|
||||
(layer "F.SilkS")
|
||||
(uuid "6df974b4-b819-4abf-a570-cfac24b90f22")
|
||||
(effects
|
||||
(font
|
||||
(size 1 1)
|
||||
(thickness 0.15)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Value" "R_0603_1608Metric"
|
||||
(at 0 1.43 0)
|
||||
(layer "F.Fab")
|
||||
(uuid "43a2d3f9-8880-4891-bb65-e1f1adf1c2a5")
|
||||
(effects
|
||||
(font
|
||||
(size 1 1)
|
||||
(thickness 0.15)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Footprint" ""
|
||||
(at 0 0 0)
|
||||
(unlocked yes)
|
||||
(layer "F.Fab")
|
||||
(hide yes)
|
||||
(uuid "6f0e4074-96ae-4ea8-867e-199cfa095a90")
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Datasheet" ""
|
||||
(at 0 0 0)
|
||||
(unlocked yes)
|
||||
(layer "F.Fab")
|
||||
(hide yes)
|
||||
(uuid "0814cc48-e15c-47d7-a42f-32beb2895ccf")
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Description" ""
|
||||
(at 0 0 0)
|
||||
(unlocked yes)
|
||||
(layer "F.Fab")
|
||||
(hide yes)
|
||||
(uuid "9ae02bb0-5305-4720-96a2-b8307ae3a157")
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(attr smd)
|
||||
(fp_line
|
||||
(start -0.237258 -0.5225)
|
||||
(end 0.237258 -0.5225)
|
||||
(stroke
|
||||
(width 0.12)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.SilkS")
|
||||
(uuid "8ec8ba9e-3d89-4f37-94bb-eddf5e4d7489")
|
||||
)
|
||||
(fp_line
|
||||
(start -0.237258 0.5225)
|
||||
(end 0.237258 0.5225)
|
||||
(stroke
|
||||
(width 0.12)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.SilkS")
|
||||
(uuid "2bf1d867-cdfa-44dc-9124-ce584dcd094b")
|
||||
)
|
||||
(fp_line
|
||||
(start -1.48 -0.73)
|
||||
(end 1.48 -0.73)
|
||||
(stroke
|
||||
(width 0.05)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.CrtYd")
|
||||
(uuid "24e272be-4051-4b9b-9127-1c7f22532469")
|
||||
)
|
||||
(fp_line
|
||||
(start -1.48 0.73)
|
||||
(end -1.48 -0.73)
|
||||
(stroke
|
||||
(width 0.05)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.CrtYd")
|
||||
(uuid "39fddbf8-ad85-4516-95fc-b7f57b1b5476")
|
||||
)
|
||||
(fp_line
|
||||
(start 1.48 -0.73)
|
||||
(end 1.48 0.73)
|
||||
(stroke
|
||||
(width 0.05)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.CrtYd")
|
||||
(uuid "2bbe1e5e-3213-443e-930c-a0ae97a345e1")
|
||||
)
|
||||
(fp_line
|
||||
(start 1.48 0.73)
|
||||
(end -1.48 0.73)
|
||||
(stroke
|
||||
(width 0.05)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.CrtYd")
|
||||
(uuid "dc275714-5365-4c02-a2fb-5cbd77201d52")
|
||||
)
|
||||
(fp_line
|
||||
(start -0.8 -0.4125)
|
||||
(end 0.8 -0.4125)
|
||||
(stroke
|
||||
(width 0.1)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.Fab")
|
||||
(uuid "30e382fb-e120-4499-bc15-156f98cd93e8")
|
||||
)
|
||||
(fp_line
|
||||
(start -0.8 0.4125)
|
||||
(end -0.8 -0.4125)
|
||||
(stroke
|
||||
(width 0.1)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.Fab")
|
||||
(uuid "d04dd1a4-2178-41f5-9bb7-ad470915f47a")
|
||||
)
|
||||
(fp_line
|
||||
(start 0.8 -0.4125)
|
||||
(end 0.8 0.4125)
|
||||
(stroke
|
||||
(width 0.1)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.Fab")
|
||||
(uuid "0746adbb-419c-491f-ae91-c14351e88a28")
|
||||
)
|
||||
(fp_line
|
||||
(start 0.8 0.4125)
|
||||
(end -0.8 0.4125)
|
||||
(stroke
|
||||
(width 0.1)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.Fab")
|
||||
(uuid "9ddd7cd8-091d-447c-bc2a-eed5612caf40")
|
||||
)
|
||||
(fp_text user "${REFERENCE}"
|
||||
(at 0 0 0)
|
||||
(layer "F.Fab")
|
||||
(uuid "2dfd6efa-e1ab-4e55-ab2b-7f9e70f33afa")
|
||||
(effects
|
||||
(font
|
||||
(size 0.4 0.4)
|
||||
(thickness 0.06)
|
||||
)
|
||||
)
|
||||
)
|
||||
(pad "1" smd roundrect
|
||||
(at -0.825 0)
|
||||
(size 0.8 0.95)
|
||||
(layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(roundrect_rratio 0.25)
|
||||
(uuid "958f80d5-b7aa-4100-9f8f-c88ef419994d")
|
||||
)
|
||||
(pad "2" smd roundrect
|
||||
(at 0.825 0)
|
||||
(size 0.8 0.95)
|
||||
(layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(roundrect_rratio 0.25)
|
||||
(uuid "dbf61a86-b574-45d2-ba89-95e1ee8fabb2")
|
||||
)
|
||||
(model "${KICAD8_3DMODEL_DIR}/Resistor_SMD.3dshapes/R_0603_1608Metric.wrl"
|
||||
(offset
|
||||
(xyz 0 0 0)
|
||||
)
|
||||
(scale
|
||||
(xyz 1 1 1)
|
||||
)
|
||||
(rotate
|
||||
(xyz 0 0 0)
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="160" height="100" viewBox="0 0 160 100">
|
||||
<rect width="160" height="100" fill="#eef7ff" rx="12" />
|
||||
<line x1="20" y1="50" x2="60" y2="50" stroke="#0059b2" stroke-width="6" stroke-linecap="round" />
|
||||
<rect x="60" y="28" width="16" height="44" fill="#00a3a3" />
|
||||
<rect x="84" y="28" width="16" height="44" fill="#00a3a3" />
|
||||
<line x1="100" y1="50" x2="140" y2="50" stroke="#0059b2" stroke-width="6" stroke-linecap="round" />
|
||||
<text x="80" y="87" font-family="Arial, sans-serif" font-size="20" text-anchor="middle" fill="#00395d">C0603</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 600 B |
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="160" height="100" viewBox="0 0 160 100">
|
||||
<rect width="160" height="100" fill="#f5f5f5" rx="12" />
|
||||
<line x1="20" y1="50" x2="50" y2="50" stroke="#0d47a1" stroke-width="6" stroke-linecap="round" />
|
||||
<polyline points="50,50 60,35 70,65 80,35 90,65 100,35 110,65 120,35 130,50" fill="none" stroke="#ff6f00" stroke-width="6" stroke-linecap="round" stroke-linejoin="round" />
|
||||
<line x1="130" y1="50" x2="140" y2="50" stroke="#0d47a1" stroke-width="6" stroke-linecap="round" />
|
||||
<text x="80" y="88" font-family="Arial, sans-serif" font-size="20" text-anchor="middle" fill="#333">R0603</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 646 B |
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"Parts": [
|
||||
{
|
||||
"Name": "Resistor 0603 1k",
|
||||
"Image": "images/resistor.svg",
|
||||
"Symbol": "symbols/r.kicad_sym",
|
||||
"Footprint": "footprints/R_0603_1608Metric.kicad_mod",
|
||||
"SPICE Model": "spice/resistor.cir",
|
||||
"3D Model": "3dmodels/R_0603_1608Metric.step"
|
||||
},
|
||||
{
|
||||
"Name": "Capacitor 0603 100nF",
|
||||
"Symbol": "symbols/c.kicad_sym",
|
||||
"Footprint": "footprints/R_0603_1608Metric.kicad_mod",
|
||||
"SPICE Model": "spice/capacitor.cir"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
* Simple capacitor SPICE model used by the WebView test harness
|
||||
.subckt C0603 1 2
|
||||
C1 1 2 100n
|
||||
.ends C0603
|
||||
@@ -0,0 +1,4 @@
|
||||
* Simple resistor SPICE model used by the WebView test harness
|
||||
.subckt R0603 1 2
|
||||
R1 1 2 1k
|
||||
.ends R0603
|
||||
@@ -0,0 +1,145 @@
|
||||
(kicad_symbol_lib
|
||||
(version 20250925)
|
||||
(generator "kicad_symbol_editor")
|
||||
(generator_version "9.99")
|
||||
(symbol "C"
|
||||
(pin_numbers
|
||||
(hide yes)
|
||||
)
|
||||
(pin_names
|
||||
(offset 0.254)
|
||||
)
|
||||
(exclude_from_sim no)
|
||||
(in_bom yes)
|
||||
(on_board yes)
|
||||
(duplicate_pin_numbers_are_jumpers no)
|
||||
(property "Reference" "C"
|
||||
(at 0.635 2.54 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
(property "Value" "C"
|
||||
(at 0.635 -2.54 0)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
(justify left)
|
||||
)
|
||||
)
|
||||
(property "Footprint" ""
|
||||
(at 0.9652 -3.81 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Datasheet" ""
|
||||
(at 0 0 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Description" "Unpolarized capacitor"
|
||||
(at 0 0 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "ki_keywords" "cap capacitor"
|
||||
(at 0 0 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "ki_fp_filters" "C_*"
|
||||
(at 0 0 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol "C_0_1"
|
||||
(polyline
|
||||
(pts
|
||||
(xy -2.032 0.762) (xy 2.032 0.762)
|
||||
)
|
||||
(stroke
|
||||
(width 0.508)
|
||||
(type default)
|
||||
)
|
||||
(fill
|
||||
(type none)
|
||||
)
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy -2.032 -0.762) (xy 2.032 -0.762)
|
||||
)
|
||||
(stroke
|
||||
(width 0.508)
|
||||
(type default)
|
||||
)
|
||||
(fill
|
||||
(type none)
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol "C_1_1"
|
||||
(pin passive line
|
||||
(at 0 3.81 270)
|
||||
(length 2.794)
|
||||
(name ""
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(number "1"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(pin passive line
|
||||
(at 0 -3.81 90)
|
||||
(length 2.794)
|
||||
(name ""
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(number "2"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(embedded_fonts no)
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,130 @@
|
||||
(kicad_symbol_lib
|
||||
(version 20250925)
|
||||
(generator "kicad_symbol_editor")
|
||||
(generator_version "9.99")
|
||||
(symbol "R"
|
||||
(pin_numbers
|
||||
(hide yes)
|
||||
)
|
||||
(pin_names
|
||||
(offset 0)
|
||||
)
|
||||
(exclude_from_sim no)
|
||||
(in_bom yes)
|
||||
(on_board yes)
|
||||
(duplicate_pin_numbers_are_jumpers no)
|
||||
(property "Reference" "R"
|
||||
(at 2.032 0 90)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Value" "R"
|
||||
(at 0 0 90)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Footprint" ""
|
||||
(at -1.778 0 90)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Datasheet" ""
|
||||
(at 0 0 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Description" "Resistor"
|
||||
(at 0 0 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "ki_keywords" "R res resistor"
|
||||
(at 0 0 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "ki_fp_filters" "R_*"
|
||||
(at 0 0 0)
|
||||
(hide yes)
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol "R_0_1"
|
||||
(rectangle
|
||||
(start -1.016 -2.54)
|
||||
(end 1.016 2.54)
|
||||
(stroke
|
||||
(width 0.254)
|
||||
(type default)
|
||||
)
|
||||
(fill
|
||||
(type none)
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol "R_1_1"
|
||||
(pin passive line
|
||||
(at 0 3.81 270)
|
||||
(length 1.27)
|
||||
(name ""
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(number "1"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(pin passive line
|
||||
(at 0 -3.81 90)
|
||||
(length 1.27)
|
||||
(name ""
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
(number "2"
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(embedded_fonts no)
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "WebView Test Datasource",
|
||||
"description": "Local development datasource for the schematic remote symbol panel.",
|
||||
"description_full": "Installs a datasource that points to the local WebView test server shipped with the KiCad source tree. Start the server found in utils/webview_test/server/webview_test_server.py and install this package from file via the Plugin and Content Manager.",
|
||||
"identifier": "org.kicad.dev.webview.test",
|
||||
"type": "datasource",
|
||||
"author": {
|
||||
"name": "KiCad Developers",
|
||||
"contact": {
|
||||
"url": "https://www.kicad.org/"
|
||||
}
|
||||
},
|
||||
"license": "GPL-3.0",
|
||||
"resources": {
|
||||
"server": "http://localhost:8080/",
|
||||
"instructions": "Start the local test server with python3 webview_test_server.py before using this datasource."
|
||||
},
|
||||
"versions": [
|
||||
{
|
||||
"kicad_version": "7.0.0",
|
||||
"version": "0.1.0",
|
||||
"status": "stable",
|
||||
"platforms": [
|
||||
"windows",
|
||||
"macos",
|
||||
"linux"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"host": "http://localhost",
|
||||
"port": 8080,
|
||||
"path": "/"
|
||||
}
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user