From bc99545eb28ba97dc3336d777056054d8b24fc14 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sun, 13 Dec 2020 11:39:53 +0000 Subject: [PATCH] ADDED Migrate Libraries button to Manage Symbol Libraries... Allows easier conversion of legacy libraries. Note that performance will be suboptimal as it must read/write each library once for each symbol in the library. Doing otherwise would require modifying the PlugIn API, which probably isn't worth it for a one-time migration. --- eeschema/dialogs/panel_sym_lib_table.cpp | 184 +++++++++++++----- eeschema/dialogs/panel_sym_lib_table.h | 23 ++- eeschema/dialogs/panel_sym_lib_table_base.cpp | 14 +- eeschema/dialogs/panel_sym_lib_table_base.fbp | 89 ++++++++- eeschema/dialogs/panel_sym_lib_table_base.h | 2 + 5 files changed, 245 insertions(+), 67 deletions(-) diff --git a/eeschema/dialogs/panel_sym_lib_table.cpp b/eeschema/dialogs/panel_sym_lib_table.cpp index 7765b3b47c..e4491c909c 100644 --- a/eeschema/dialogs/panel_sym_lib_table.cpp +++ b/eeschema/dialogs/panel_sym_lib_table.cpp @@ -40,9 +40,9 @@ #include #include #include - #include #include +#include // clang-format off @@ -69,39 +69,6 @@ enum { }; -/** - * Map with event id as the key to supported file types that will be listed for the add - * a library option. - */ -static const std::map& fileTypes() -{ - static const std::map fileTypes = - { - { ID_PANEL_SYM_LIB_LEGACY, - { - "KiCad legacy symbol library file (*.lib)", - LegacySymbolLibFileWildcard(), - "", - true, - SCH_IO_MGR::SCH_LEGACY - } - }, - { - ID_PANEL_SYM_LIB_KICAD, - { - "KiCad s-expression symbol library file (*.kicad_sym)", - KiCadSymbolLibFileWildcard(), - "", - true, - SCH_IO_MGR::SCH_KICAD - } - } - }; - - return fileTypes; -} - - /** * Build a wxGridTableBase by wrapping an #SYMBOL_LIB_TABLE object. */ @@ -204,21 +171,20 @@ protected: }; -PANEL_SYM_LIB_TABLE::PANEL_SYM_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent, - SYMBOL_LIB_TABLE* aGlobal, +PANEL_SYM_LIB_TABLE::PANEL_SYM_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent, PROJECT* aProject , + SYMBOL_LIB_TABLE* aGlobalTable, const wxString& aGlobalTablePath, - SYMBOL_LIB_TABLE* aProject, - const wxString& aProjectTablePath, - const wxString& aProjectBasePath ) : + SYMBOL_LIB_TABLE* aProjectTable, + const wxString& aProjectTablePath ) : PANEL_SYM_LIB_TABLE_BASE( aParent ), - m_globalTable( aGlobal ), - m_projectTable( aProject ), - m_projectBasePath( aProjectBasePath ), + m_globalTable( aGlobalTable ), + m_projectTable( aProjectTable ), + m_project( aProject ), m_parent( aParent ) { // wxGrid only supports user owned tables if they exist past end of ~wxGrid(), // so make it a grid owned table. - m_global_grid->SetTable( new SYMBOL_LIB_TABLE_GRID( *aGlobal ), true ); + m_global_grid->SetTable( new SYMBOL_LIB_TABLE_GRID( *m_globalTable ), true ); // For user info, shows the table filenames: m_GblTableFilename->SetLabel( aGlobalTablePath ); @@ -232,7 +198,7 @@ PANEL_SYM_LIB_TABLE::PANEL_SYM_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent, if( cfg->m_lastSymbolLibDir.IsEmpty() ) { - cfg->m_lastSymbolLibDir = m_projectBasePath; + cfg->m_lastSymbolLibDir = m_project->GetProjectPath(); } auto setupGrid = @@ -256,8 +222,8 @@ PANEL_SYM_LIB_TABLE::PANEL_SYM_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent, + "|" + KiCadSymbolLibFileWildcard() + "|" + LegacySymbolLibFileWildcard(); attr->SetEditor( new GRID_CELL_PATH_EDITOR( m_parent, &cfg->m_lastSymbolLibDir, - wildcards, - true, m_projectBasePath ) ); + wildcards, true, + m_project->GetProjectPath() ) ); aGrid->SetColAttr( COL_URI, attr ); attr = new wxGridCellAttr; @@ -287,10 +253,10 @@ PANEL_SYM_LIB_TABLE::PANEL_SYM_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent, setupGrid( m_global_grid ); - if( aProject ) + if( m_projectTable ) { m_PrjTableFilename->SetLabel( aProjectTablePath ); - m_project_grid->SetTable( new SYMBOL_LIB_TABLE_GRID( *aProject ), true ); + m_project_grid->SetTable( new SYMBOL_LIB_TABLE_GRID( *m_projectTable ), true ); setupGrid( m_project_grid ); } else @@ -535,13 +501,13 @@ void PANEL_SYM_LIB_TABLE::browseLibrariesHandler( wxCommandEvent& event ) if( SCH_IO_MGR::GetLibraryFileExtension( pluginType ).Lower() == fn.GetExt().Lower() ) { m_cur_grid->SetCellValue( last_row, COL_TYPE, - SCH_IO_MGR::ShowType( pluginType ) ); + SCH_IO_MGR::ShowType( pluginType ) ); break; } } // try to use path normalized to an environmental variable or project path - wxString path = NormalizePath( filePath, &envVars, m_projectBasePath ); + wxString path = NormalizePath( filePath, &envVars, m_project->GetProjectPath() ); // Do not use the project path in the global library table. This will almost // assuredly be wrong for a different project. @@ -698,6 +664,119 @@ void PANEL_SYM_LIB_TABLE::moveDownHandler( wxCommandEvent& event ) } +void PANEL_SYM_LIB_TABLE::onConvertLegacyLibraries( wxCommandEvent& event ) +{ + if( !m_cur_grid->CommitPendingChanges() ) + return; + + wxArrayInt selectedRows = m_cur_grid->GetSelectedRows(); + + if( selectedRows.empty() ) + selectedRows.push_back( m_cur_grid->GetGridCursorRow() ); + + wxArrayInt legacyRows; + wxString legacyType = SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_LEGACY ); + wxString kicadType = SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_KICAD ); + wxString msg; + + for( int row : selectedRows ) + { + if( m_cur_grid->GetCellValue( row, COL_TYPE ) == legacyType ) + legacyRows.push_back( row ); + } + + if( legacyRows.size() <= 0 ) + { + wxMessageBox( _( "Select one or more table rows containing legacy libraries to save as " + "current format (*.kicad_sym)." ) ); + return; + } + else + { + if( legacyRows.size() == 1 ) + { + msg.Printf( _( "Save '%s' as current format (*.kicad_sym) and " + "replace legacy entry in table?" ), + m_cur_grid->GetCellValue( legacyRows[0], COL_NICKNAME ) ); + } + else + { + msg.Printf( _( "Save %d legacy libraries as current format (*.kicad_sym) and " + "replace legacy entries in table?" ), + legacyRows.size() ); + } + + if( !IsOK( m_parent, msg ) ) + return; + } + + for( int row : legacyRows ) + { + wxString libName = m_cur_grid->GetCellValue( row, COL_NICKNAME ); + wxString relPath = m_cur_grid->GetCellValue( row, COL_URI ); + wxString resolvedPath = ExpandEnvVarSubstitutions( relPath, m_project ); + wxFileName legacyLib( resolvedPath ); + + if( !legacyLib.Exists() ) + { + msg.Printf( _( "Library '%s' not found." ), relPath ); + DisplayErrorMessage( this, msg ); + continue; + } + + wxFileName newLib( resolvedPath ); + newLib.SetExt( "kicad_sym" ); + + if( convertLibrary( libName, legacyLib.GetFullPath(), newLib.GetFullPath() ) ) + { + relPath = NormalizePath( newLib.GetFullPath(), &Pgm().GetLocalEnvVariables(), + m_project ); + + m_cur_grid->SetCellValue( row, COL_URI, relPath ); + m_cur_grid->SetCellValue( row, COL_TYPE, kicadType ); + } + else + { + msg.Printf( _( "Failed to save symbol library file '%s'." ), newLib.GetFullPath() ); + DisplayErrorMessage( this, msg ); + } + } +} + + +bool PANEL_SYM_LIB_TABLE::convertLibrary( const wxString& aLibrary, const wxString& legacyFilepath, + const wxString& newFilepath ) +{ + SCH_PLUGIN::SCH_PLUGIN_RELEASER legacyPI( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) ); + SCH_PLUGIN::SCH_PLUGIN_RELEASER kicadPI( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_KICAD ) ); + std::vector parts; + std::vector newParts; + + try + { + // Write a stub file; SaveSymbol() expects something to be there already. + FILE_OUTPUTFORMATTER* formatter = new FILE_OUTPUTFORMATTER( newFilepath ); + + formatter->Print( 0, "(kicad_symbol_lib (version %d) (generator kicad_converter))", + SEXPR_SYMBOL_LIB_FILE_VERSION ); + + // This will write the file + delete formatter; + + legacyPI->EnumerateSymbolLib( parts, legacyFilepath ); + + for( LIB_PART* part : parts ) + kicadPI->SaveSymbol( newFilepath, new LIB_PART( *part ) ); + } + catch( ... ) + { + return false; + } + + return true; +} + + bool PANEL_SYM_LIB_TABLE::TransferDataFromWindow() { if( !m_cur_grid->CommitPendingChanges() ) @@ -882,9 +961,8 @@ void InvokeSchEditSymbolLibTable( KIWAY* aKiway, wxWindow *aParent ) DIALOG_EDIT_LIBRARY_TABLES dlg( aParent, _( "Symbol Libraries" ) ); - dlg.InstallPanel( new PANEL_SYM_LIB_TABLE( &dlg, globalTable, globalTablePath, - projectTable, projectTableFn.GetFullPath(), - aKiway->Prj().GetProjectPath() ) ); + dlg.InstallPanel( new PANEL_SYM_LIB_TABLE( &dlg, &aKiway->Prj(), globalTable, globalTablePath, + projectTable, projectTableFn.GetFullPath() ) ); if( dlg.ShowModal() == wxID_CANCEL ) { diff --git a/eeschema/dialogs/panel_sym_lib_table.h b/eeschema/dialogs/panel_sym_lib_table.h index 18c2896f0a..3e8088f8cf 100644 --- a/eeschema/dialogs/panel_sym_lib_table.h +++ b/eeschema/dialogs/panel_sym_lib_table.h @@ -24,6 +24,7 @@ #include #include + class SYMBOL_LIB_TABLE; class SYMBOL_LIB_TABLE_GRID; @@ -35,10 +36,9 @@ class PANEL_SYM_LIB_TABLE : public PANEL_SYM_LIB_TABLE_BASE { public: - PANEL_SYM_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent, + PANEL_SYM_LIB_TABLE( DIALOG_EDIT_LIBRARY_TABLES* aParent, PROJECT* m_project, SYMBOL_LIB_TABLE* aGlobal, const wxString& aGlobalTablePath, - SYMBOL_LIB_TABLE* aProject, const wxString& aProjectTablePath, - const wxString& m_projectBasePath ); + SYMBOL_LIB_TABLE* aProject, const wxString& aProjectTablePath ); virtual ~PANEL_SYM_LIB_TABLE(); private: @@ -57,6 +57,7 @@ private: void moveDownHandler( wxCommandEvent& event ) override; void onSizeGrid( wxSizeEvent& event ) override; void adjustPathSubsGridColumns( int aWidth ); + void onConvertLegacyLibraries( wxCommandEvent& event ) override; bool TransferDataFromWindow() override; @@ -64,10 +65,8 @@ private: /// by examining all the full_uri columns. void populateEnvironReadOnlyTable(); - // Caller's tables are modified only on OK button and successful verification. - SYMBOL_LIB_TABLE* m_globalTable; - SYMBOL_LIB_TABLE* m_projectTable; - wxString m_projectBasePath; + bool convertLibrary( const wxString& aLibrary, const wxString& legacyFilepath, + const wxString& newFilepath ); SYMBOL_LIB_TABLE_GRID* global_model() const; @@ -75,10 +74,16 @@ private: SYMBOL_LIB_TABLE_GRID* cur_model() const; +private: + // Caller's tables are modified only on OK button and successful verification. + SYMBOL_LIB_TABLE* m_globalTable; + SYMBOL_LIB_TABLE* m_projectTable; + PROJECT* m_project; + DIALOG_EDIT_LIBRARY_TABLES* m_parent; - WX_GRID* m_cur_grid; ///< changed based on tab choice - static size_t m_pageNdx; ///< Remember the last notebook page selected during a session + WX_GRID* m_cur_grid; ///< changed based on tab choice + static size_t m_pageNdx; ///< Remember the last notebook page selected }; diff --git a/eeschema/dialogs/panel_sym_lib_table_base.cpp b/eeschema/dialogs/panel_sym_lib_table_base.cpp index e581283f1e..c4a8cb8722 100644 --- a/eeschema/dialogs/panel_sym_lib_table_base.cpp +++ b/eeschema/dialogs/panel_sym_lib_table_base.cpp @@ -20,6 +20,8 @@ PANEL_SYM_LIB_TABLE_BASE::PANEL_SYM_LIB_TABLE_BASE( wxWindow* parent, wxWindowID m_top_sizer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Libraries by Scope") ), wxVERTICAL ); m_notebook = new wxNotebook( m_top_sizer->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); + m_notebook->SetMinSize( wxSize( 400,-1 ) ); + m_global_panel = new wxPanel( m_notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); wxBoxSizer* m_global_sizer; m_global_sizer = new wxBoxSizer( wxVERTICAL ); @@ -126,7 +128,7 @@ PANEL_SYM_LIB_TABLE_BASE::PANEL_SYM_LIB_TABLE_BASE( wxWindow* parent, wxWindowID m_project_sizer->Fit( m_project_panel ); m_notebook->AddPage( m_project_panel, _("Project Specific Libraries"), false ); - m_top_sizer->Add( m_notebook, 1, wxEXPAND | wxALL, 5 ); + m_top_sizer->Add( m_notebook, 1, wxEXPAND|wxTOP|wxBOTTOM, 5 ); wxBoxSizer* bSizer51; bSizer51 = new wxBoxSizer( wxHORIZONTAL ); @@ -160,7 +162,13 @@ PANEL_SYM_LIB_TABLE_BASE::PANEL_SYM_LIB_TABLE_BASE( wxWindow* parent, wxWindowID bSizer51->Add( m_delete_button, 0, wxBOTTOM|wxRIGHT, 5 ); - m_top_sizer->Add( bSizer51, 0, 0, 8 ); + bSizer51->Add( 0, 0, 1, wxEXPAND, 5 ); + + m_convertLegacy = new wxButton( m_top_sizer->GetStaticBox(), wxID_ANY, _("Migrate Libraries..."), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer51->Add( m_convertLegacy, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + + m_top_sizer->Add( bSizer51, 0, wxEXPAND, 8 ); bSizer1->Add( m_top_sizer, 1, wxALL|wxEXPAND, 5 ); @@ -214,6 +222,7 @@ PANEL_SYM_LIB_TABLE_BASE::PANEL_SYM_LIB_TABLE_BASE( wxWindow* parent, wxWindowID m_move_up_button->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SYM_LIB_TABLE_BASE::moveUpHandler ), NULL, this ); m_move_down_button->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SYM_LIB_TABLE_BASE::moveDownHandler ), NULL, this ); m_delete_button->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SYM_LIB_TABLE_BASE::deleteRowHandler ), NULL, this ); + m_convertLegacy->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SYM_LIB_TABLE_BASE::onConvertLegacyLibraries ), NULL, this ); m_path_subs_grid->Connect( wxEVT_SIZE, wxSizeEventHandler( PANEL_SYM_LIB_TABLE_BASE::onSizeGrid ), NULL, this ); } @@ -226,6 +235,7 @@ PANEL_SYM_LIB_TABLE_BASE::~PANEL_SYM_LIB_TABLE_BASE() m_move_up_button->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SYM_LIB_TABLE_BASE::moveUpHandler ), NULL, this ); m_move_down_button->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SYM_LIB_TABLE_BASE::moveDownHandler ), NULL, this ); m_delete_button->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SYM_LIB_TABLE_BASE::deleteRowHandler ), NULL, this ); + m_convertLegacy->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_SYM_LIB_TABLE_BASE::onConvertLegacyLibraries ), NULL, this ); m_path_subs_grid->Disconnect( wxEVT_SIZE, wxSizeEventHandler( PANEL_SYM_LIB_TABLE_BASE::onSizeGrid ), NULL, this ); } diff --git a/eeschema/dialogs/panel_sym_lib_table_base.fbp b/eeschema/dialogs/panel_sym_lib_table_base.fbp index 6709cce320..d750200f91 100644 --- a/eeschema/dialogs/panel_sym_lib_table_base.fbp +++ b/eeschema/dialogs/panel_sym_lib_table_base.fbp @@ -69,7 +69,7 @@ none 5 - wxEXPAND | wxALL + wxEXPAND|wxTOP|wxBOTTOM 1 1 @@ -105,7 +105,7 @@ 0 - + 400,-1 1 m_notebook 1 @@ -710,7 +710,7 @@ 8 - + wxEXPAND 0 @@ -1092,6 +1092,89 @@ deleteRowHandler + + 5 + wxEXPAND + 1 + + 0 + protected + 0 + + + + 5 + wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 1 + + 1 + + + 0 + 0 + wxID_ANY + Migrate Libraries... + + 0 + + 0 + + + 0 + + 1 + m_convertLegacy + 1 + + + protected + 1 + + + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onConvertLegacyLibraries + + diff --git a/eeschema/dialogs/panel_sym_lib_table_base.h b/eeschema/dialogs/panel_sym_lib_table_base.h index 2089b1c935..e46ed04728 100644 --- a/eeschema/dialogs/panel_sym_lib_table_base.h +++ b/eeschema/dialogs/panel_sym_lib_table_base.h @@ -54,6 +54,7 @@ class PANEL_SYM_LIB_TABLE_BASE : public wxPanel wxBitmapButton* m_move_up_button; wxBitmapButton* m_move_down_button; wxBitmapButton* m_delete_button; + wxButton* m_convertLegacy; WX_GRID* m_path_subs_grid; // Virtual event handlers, overide them in your derived class @@ -63,6 +64,7 @@ class PANEL_SYM_LIB_TABLE_BASE : public wxPanel virtual void moveUpHandler( wxCommandEvent& event ) { event.Skip(); } virtual void moveDownHandler( wxCommandEvent& event ) { event.Skip(); } virtual void deleteRowHandler( wxCommandEvent& event ) { event.Skip(); } + virtual void onConvertLegacyLibraries( wxCommandEvent& event ) { event.Skip(); } virtual void onSizeGrid( wxSizeEvent& event ) { event.Skip(); }